2016-08-13 12:57:50 +00:00
|
|
|
// Copyright 2016 Dolphin Emulator Project
|
|
|
|
// Licensed under GPLv2+
|
|
|
|
// Refer to the license.txt file included.
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
2016-10-01 03:07:50 +00:00
|
|
|
#include <array>
|
|
|
|
#include <cstddef>
|
|
|
|
|
|
|
|
#include "Common/CommonTypes.h"
|
2016-08-13 12:57:50 +00:00
|
|
|
#include "VideoBackends/Vulkan/Constants.h"
|
|
|
|
#include "VideoBackends/Vulkan/ObjectCache.h"
|
2017-04-17 13:14:17 +00:00
|
|
|
#include "VideoCommon/RenderState.h"
|
2016-08-13 12:57:50 +00:00
|
|
|
|
|
|
|
namespace Vulkan
|
|
|
|
{
|
|
|
|
class CommandBufferManager;
|
|
|
|
class ObjectCache;
|
|
|
|
class StateTracker;
|
|
|
|
|
|
|
|
namespace Util
|
|
|
|
{
|
|
|
|
size_t AlignBufferOffset(size_t offset, size_t alignment);
|
|
|
|
|
|
|
|
u32 MakeRGBA8Color(float r, float g, float b, float a);
|
|
|
|
|
|
|
|
bool IsDepthFormat(VkFormat format);
|
2017-04-16 12:23:33 +00:00
|
|
|
bool IsCompressedFormat(VkFormat format);
|
2016-08-13 12:57:50 +00:00
|
|
|
VkFormat GetLinearFormat(VkFormat format);
|
2017-04-16 12:23:33 +00:00
|
|
|
VkFormat GetVkFormatForHostTextureFormat(HostTextureFormat format);
|
2016-08-13 12:57:50 +00:00
|
|
|
u32 GetTexelSize(VkFormat format);
|
2017-04-16 12:23:33 +00:00
|
|
|
u32 GetBlockSize(VkFormat format);
|
|
|
|
|
2017-04-15 09:55:32 +00:00
|
|
|
// Clamps a VkRect2D to the specified dimensions.
|
|
|
|
VkRect2D ClampRect2D(const VkRect2D& rect, u32 width, u32 height);
|
|
|
|
|
2016-08-13 12:57:50 +00:00
|
|
|
// Map {SRC,DST}_COLOR to {SRC,DST}_ALPHA
|
|
|
|
VkBlendFactor GetAlphaBlendFactor(VkBlendFactor factor);
|
|
|
|
|
|
|
|
RasterizationState GetNoCullRasterizationState();
|
|
|
|
DepthStencilState GetNoDepthTestingDepthStencilState();
|
2017-04-17 13:14:17 +00:00
|
|
|
BlendingState GetNoBlendingBlendState();
|
2016-08-13 12:57:50 +00:00
|
|
|
|
|
|
|
// Combines viewport and scissor updates
|
|
|
|
void SetViewportAndScissor(VkCommandBuffer command_buffer, int x, int y, int width, int height,
|
|
|
|
float min_depth = 0.0f, float max_depth = 1.0f);
|
|
|
|
|
|
|
|
// Wrapper for creating an barrier on a buffer
|
|
|
|
void BufferMemoryBarrier(VkCommandBuffer command_buffer, VkBuffer buffer,
|
|
|
|
VkAccessFlags src_access_mask, VkAccessFlags dst_access_mask,
|
|
|
|
VkDeviceSize offset, VkDeviceSize size,
|
|
|
|
VkPipelineStageFlags src_stage_mask, VkPipelineStageFlags dst_stage_mask);
|
|
|
|
|
|
|
|
// Completes the current render pass, executes the command buffer, and restores state ready for next
|
|
|
|
// render. Use when you want to kick the current buffer to make room for new data.
|
2016-10-22 10:50:36 +00:00
|
|
|
void ExecuteCurrentCommandsAndRestoreState(bool execute_off_thread,
|
2016-08-13 12:57:50 +00:00
|
|
|
bool wait_for_completion = false);
|
|
|
|
|
|
|
|
// Create a shader module from the specified SPIR-V.
|
|
|
|
VkShaderModule CreateShaderModule(const u32* spv, size_t spv_word_count);
|
|
|
|
|
|
|
|
// Compile a vertex shader and create a shader module, discarding the intermediate SPIR-V.
|
|
|
|
VkShaderModule CompileAndCreateVertexShader(const std::string& source_code,
|
|
|
|
bool prepend_header = true);
|
|
|
|
|
|
|
|
// Compile a geometry shader and create a shader module, discarding the intermediate SPIR-V.
|
|
|
|
VkShaderModule CompileAndCreateGeometryShader(const std::string& source_code,
|
|
|
|
bool prepend_header = true);
|
|
|
|
|
|
|
|
// Compile a fragment shader and create a shader module, discarding the intermediate SPIR-V.
|
|
|
|
VkShaderModule CompileAndCreateFragmentShader(const std::string& source_code,
|
|
|
|
bool prepend_header = true);
|
2016-12-09 12:23:04 +00:00
|
|
|
|
|
|
|
// Compile a compute shader and create a shader module, discarding the intermediate SPIR-V.
|
|
|
|
VkShaderModule CompileAndCreateComputeShader(const std::string& source_code,
|
|
|
|
bool prepend_header = true);
|
2016-08-13 12:57:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Utility shader vertex format
|
|
|
|
#pragma pack(push, 1)
|
|
|
|
struct UtilityShaderVertex
|
|
|
|
{
|
|
|
|
float Position[4];
|
|
|
|
float TexCoord[4];
|
|
|
|
u32 Color;
|
|
|
|
|
|
|
|
void SetPosition(float x, float y)
|
|
|
|
{
|
|
|
|
Position[0] = x;
|
|
|
|
Position[1] = y;
|
|
|
|
Position[2] = 0.0f;
|
|
|
|
Position[3] = 1.0f;
|
|
|
|
}
|
|
|
|
void SetPosition(float x, float y, float z)
|
|
|
|
{
|
|
|
|
Position[0] = x;
|
|
|
|
Position[1] = y;
|
|
|
|
Position[2] = z;
|
|
|
|
Position[3] = 1.0f;
|
|
|
|
}
|
|
|
|
void SetTextureCoordinates(float u, float v)
|
|
|
|
{
|
|
|
|
TexCoord[0] = u;
|
|
|
|
TexCoord[1] = v;
|
|
|
|
TexCoord[2] = 0.0f;
|
|
|
|
TexCoord[3] = 0.0f;
|
|
|
|
}
|
|
|
|
void SetTextureCoordinates(float u, float v, float w)
|
|
|
|
{
|
|
|
|
TexCoord[0] = u;
|
|
|
|
TexCoord[1] = v;
|
|
|
|
TexCoord[2] = w;
|
|
|
|
TexCoord[3] = 0.0f;
|
|
|
|
}
|
|
|
|
void SetTextureCoordinates(float u, float v, float w, float x)
|
|
|
|
{
|
|
|
|
TexCoord[0] = u;
|
|
|
|
TexCoord[1] = v;
|
|
|
|
TexCoord[2] = w;
|
|
|
|
TexCoord[3] = x;
|
|
|
|
}
|
|
|
|
void SetColor(u32 color) { Color = color; }
|
|
|
|
void SetColor(float r, float g, float b) { Color = Util::MakeRGBA8Color(r, g, b, 1.0f); }
|
|
|
|
void SetColor(float r, float g, float b, float a) { Color = Util::MakeRGBA8Color(r, g, b, a); }
|
|
|
|
};
|
|
|
|
#pragma pack(pop)
|
|
|
|
|
|
|
|
class UtilityShaderDraw
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
UtilityShaderDraw(VkCommandBuffer command_buffer, VkPipelineLayout pipeline_layout,
|
|
|
|
VkRenderPass render_pass, VkShaderModule vertex_shader,
|
|
|
|
VkShaderModule geometry_shader, VkShaderModule pixel_shader);
|
|
|
|
|
|
|
|
UtilityShaderVertex* ReserveVertices(VkPrimitiveTopology topology, size_t count);
|
|
|
|
void CommitVertices(size_t count);
|
|
|
|
|
|
|
|
void UploadVertices(VkPrimitiveTopology topology, UtilityShaderVertex* vertices, size_t count);
|
|
|
|
|
|
|
|
u8* AllocateVSUniforms(size_t size);
|
|
|
|
void CommitVSUniforms(size_t size);
|
|
|
|
|
|
|
|
u8* AllocatePSUniforms(size_t size);
|
|
|
|
void CommitPSUniforms(size_t size);
|
|
|
|
|
|
|
|
void SetPushConstants(const void* data, size_t data_size);
|
|
|
|
|
|
|
|
void SetPSSampler(size_t index, VkImageView view, VkSampler sampler);
|
|
|
|
|
2016-11-19 14:02:06 +00:00
|
|
|
void SetPSTexelBuffer(VkBufferView view);
|
|
|
|
|
2016-08-13 12:57:50 +00:00
|
|
|
void SetRasterizationState(const RasterizationState& state);
|
|
|
|
void SetDepthStencilState(const DepthStencilState& state);
|
2017-04-17 13:14:17 +00:00
|
|
|
void SetBlendState(const BlendingState& state);
|
2016-08-13 12:57:50 +00:00
|
|
|
|
|
|
|
void BeginRenderPass(VkFramebuffer framebuffer, const VkRect2D& region,
|
|
|
|
const VkClearValue* clear_value = nullptr);
|
|
|
|
void EndRenderPass();
|
|
|
|
|
|
|
|
void Draw();
|
|
|
|
|
|
|
|
// NOTE: These methods alter the viewport state of the command buffer.
|
|
|
|
|
|
|
|
// Sets texture coordinates to 0..1
|
|
|
|
void DrawQuad(int x, int y, int width, int height, float z = 0.0f);
|
|
|
|
|
|
|
|
// Sets texture coordinates to the specified range
|
|
|
|
void DrawQuad(int dst_x, int dst_y, int dst_width, int dst_height, int src_x, int src_y,
|
|
|
|
int src_layer, int src_width, int src_height, int src_full_width,
|
|
|
|
int src_full_height, float z = 0.0f);
|
|
|
|
|
|
|
|
void DrawColoredQuad(int x, int y, int width, int height, u32 color, float z = 0.0f);
|
|
|
|
|
|
|
|
void DrawColoredQuad(int x, int y, int width, int height, float r, float g, float b, float a,
|
|
|
|
float z = 0.0f);
|
|
|
|
|
|
|
|
// Draw without a vertex buffer. Assumes viewport has been initialized separately.
|
|
|
|
void SetViewportAndScissor(int x, int y, int width, int height);
|
|
|
|
void DrawWithoutVertexBuffer(VkPrimitiveTopology primitive_topology, u32 vertex_count);
|
|
|
|
|
|
|
|
private:
|
|
|
|
void BindVertexBuffer();
|
|
|
|
void BindDescriptors();
|
|
|
|
bool BindPipeline();
|
|
|
|
|
|
|
|
VkCommandBuffer m_command_buffer = VK_NULL_HANDLE;
|
|
|
|
VkBuffer m_vertex_buffer = VK_NULL_HANDLE;
|
|
|
|
VkDeviceSize m_vertex_buffer_offset = 0;
|
|
|
|
uint32_t m_vertex_count = 0;
|
|
|
|
|
|
|
|
VkDescriptorBufferInfo m_vs_uniform_buffer = {};
|
|
|
|
VkDescriptorBufferInfo m_ps_uniform_buffer = {};
|
|
|
|
std::array<uint32_t, NUM_UBO_DESCRIPTOR_SET_BINDINGS> m_ubo_offsets = {};
|
|
|
|
|
|
|
|
std::array<VkDescriptorImageInfo, NUM_PIXEL_SHADER_SAMPLERS> m_ps_samplers = {};
|
|
|
|
|
2016-11-19 14:02:06 +00:00
|
|
|
VkBufferView m_ps_texel_buffer = VK_NULL_HANDLE;
|
|
|
|
|
2016-08-13 12:57:50 +00:00
|
|
|
PipelineInfo m_pipeline_info = {};
|
|
|
|
};
|
|
|
|
|
2016-12-09 12:23:04 +00:00
|
|
|
class ComputeShaderDispatcher
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
ComputeShaderDispatcher(VkCommandBuffer command_buffer, VkPipelineLayout pipeline_layout,
|
|
|
|
VkShaderModule compute_shader);
|
|
|
|
|
|
|
|
u8* AllocateUniformBuffer(size_t size);
|
|
|
|
void CommitUniformBuffer(size_t size);
|
|
|
|
|
|
|
|
void SetPushConstants(const void* data, size_t data_size);
|
|
|
|
|
|
|
|
void SetSampler(size_t index, VkImageView view, VkSampler sampler);
|
|
|
|
|
|
|
|
void SetTexelBuffer(size_t index, VkBufferView view);
|
|
|
|
|
|
|
|
void SetStorageImage(VkImageView view, VkImageLayout image_layout);
|
|
|
|
|
|
|
|
void Dispatch(u32 groups_x, u32 groups_y, u32 groups_z);
|
|
|
|
|
|
|
|
private:
|
|
|
|
void BindDescriptors();
|
|
|
|
bool BindPipeline();
|
|
|
|
|
|
|
|
VkCommandBuffer m_command_buffer = VK_NULL_HANDLE;
|
|
|
|
|
|
|
|
VkDescriptorBufferInfo m_uniform_buffer = {};
|
|
|
|
u32 m_uniform_buffer_offset = 0;
|
|
|
|
|
|
|
|
std::array<VkDescriptorImageInfo, 4> m_samplers = {};
|
|
|
|
|
|
|
|
std::array<VkBufferView, 2> m_texel_buffers = {};
|
|
|
|
|
|
|
|
VkDescriptorImageInfo m_storage_image = {};
|
|
|
|
|
|
|
|
ComputePipelineInfo m_pipeline_info = {};
|
|
|
|
};
|
|
|
|
|
2016-08-13 12:57:50 +00:00
|
|
|
} // namespace Vulkan
|