Core: Add Vulkan GPU renderer

This commit is contained in:
Connor McLaughlin 2020-06-19 00:18:17 +10:00
parent 3cd5b7ae74
commit 49d11988bf
15 changed files with 1460 additions and 42 deletions

View file

@ -36,6 +36,8 @@ add_library(core
gpu_hw_opengl.h
gpu_hw_shadergen.cpp
gpu_hw_shadergen.h
gpu_hw_vulkan.cpp
gpu_hw_vulkan.h
gpu_sw.cpp
gpu_sw.h
gte.cpp
@ -91,7 +93,7 @@ set(RECOMPILER_SRCS
target_include_directories(core PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/..")
target_include_directories(core PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/..")
target_link_libraries(core PUBLIC Threads::Threads common imgui tinyxml2 zlib)
target_link_libraries(core PUBLIC Threads::Threads common imgui tinyxml2 zlib vulkan-loader)
target_link_libraries(core PRIVATE glad stb)
if(WIN32)

View file

@ -64,6 +64,7 @@
<ClCompile Include="gpu_commands.cpp" />
<ClCompile Include="gpu_hw_d3d11.cpp" />
<ClCompile Include="gpu_hw_shadergen.cpp" />
<ClCompile Include="gpu_hw_vulkan.cpp" />
<ClCompile Include="gpu_sw.cpp" />
<ClCompile Include="gte.cpp" />
<ClCompile Include="dma.cpp" />
@ -105,6 +106,7 @@
<ClInclude Include="game_list.h" />
<ClInclude Include="gpu_hw_d3d11.h" />
<ClInclude Include="gpu_hw_shadergen.h" />
<ClInclude Include="gpu_hw_vulkan.h" />
<ClInclude Include="gpu_sw.h" />
<ClInclude Include="gte.h" />
<ClInclude Include="cpu_types.h" />
@ -296,7 +298,7 @@
<PreprocessorDefinitions>WITH_RECOMPILER=1;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<AdditionalIncludeDirectories>$(SolutionDir)dep\msvc\include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\imgui\include;$(SolutionDir)dep\xbyak\xbyak;$(SolutionDir)dep\tinyxml2\include;$(SolutionDir)dep\zlib\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SolutionDir)dep\msvc\include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\imgui\include;$(SolutionDir)dep\xbyak\xbyak;$(SolutionDir)dep\tinyxml2\include;$(SolutionDir)dep\zlib\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<MinimalRebuild>false</MinimalRebuild>
<LanguageStandard>stdcpp17</LanguageStandard>
@ -321,7 +323,7 @@
<PreprocessorDefinitions>WITH_RECOMPILER=1;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<AdditionalIncludeDirectories>$(SolutionDir)dep\msvc\include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\imgui\include;$(SolutionDir)dep\xbyak\xbyak;$(SolutionDir)dep\tinyxml2\include;$(SolutionDir)dep\zlib\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SolutionDir)dep\msvc\include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\imgui\include;$(SolutionDir)dep\xbyak\xbyak;$(SolutionDir)dep\tinyxml2\include;$(SolutionDir)dep\zlib\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<MinimalRebuild>false</MinimalRebuild>
<LanguageStandard>stdcpp17</LanguageStandard>
@ -346,7 +348,7 @@
<PreprocessorDefinitions>WITH_RECOMPILER=1;_ITERATOR_DEBUG_LEVEL=1;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUGFAST;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<AdditionalIncludeDirectories>$(SolutionDir)dep\msvc\include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\imgui\include;$(SolutionDir)dep\xbyak\xbyak;$(SolutionDir)dep\tinyxml2\include;$(SolutionDir)dep\zlib\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SolutionDir)dep\msvc\include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\imgui\include;$(SolutionDir)dep\xbyak\xbyak;$(SolutionDir)dep\tinyxml2\include;$(SolutionDir)dep\zlib\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<MinimalRebuild>false</MinimalRebuild>
@ -374,7 +376,7 @@
<PreprocessorDefinitions>WITH_RECOMPILER=1;_ITERATOR_DEBUG_LEVEL=1;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUGFAST;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<AdditionalIncludeDirectories>$(SolutionDir)dep\msvc\include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\imgui\include;$(SolutionDir)dep\xbyak\xbyak;$(SolutionDir)dep\tinyxml2\include;$(SolutionDir)dep\zlib\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SolutionDir)dep\msvc\include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\imgui\include;$(SolutionDir)dep\xbyak\xbyak;$(SolutionDir)dep\tinyxml2\include;$(SolutionDir)dep\zlib\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<MinimalRebuild>false</MinimalRebuild>
@ -401,7 +403,7 @@
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WITH_RECOMPILER=1;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir)dep\msvc\include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\imgui\include;$(SolutionDir)dep\xbyak\xbyak;$(SolutionDir)dep\tinyxml2\include;$(SolutionDir)dep\zlib\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SolutionDir)dep\msvc\include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\imgui\include;$(SolutionDir)dep\xbyak\xbyak;$(SolutionDir)dep\tinyxml2\include;$(SolutionDir)dep\zlib\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<WholeProgramOptimization>false</WholeProgramOptimization>
<LanguageStandard>stdcpp17</LanguageStandard>
@ -427,7 +429,7 @@
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WITH_RECOMPILER=1;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir)dep\msvc\include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\imgui\include;$(SolutionDir)dep\xbyak\xbyak;$(SolutionDir)dep\tinyxml2\include;$(SolutionDir)dep\zlib\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SolutionDir)dep\msvc\include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\imgui\include;$(SolutionDir)dep\xbyak\xbyak;$(SolutionDir)dep\tinyxml2\include;$(SolutionDir)dep\zlib\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<WholeProgramOptimization>true</WholeProgramOptimization>
<LanguageStandard>stdcpp17</LanguageStandard>
@ -454,7 +456,7 @@
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WITH_RECOMPILER=1;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir)dep\msvc\include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\imgui\include;$(SolutionDir)dep\xbyak\xbyak;$(SolutionDir)dep\tinyxml2\include;$(SolutionDir)dep\zlib\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SolutionDir)dep\msvc\include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\imgui\include;$(SolutionDir)dep\xbyak\xbyak;$(SolutionDir)dep\tinyxml2\include;$(SolutionDir)dep\zlib\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<WholeProgramOptimization>false</WholeProgramOptimization>
<LanguageStandard>stdcpp17</LanguageStandard>
@ -480,7 +482,7 @@
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WITH_RECOMPILER=1;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir)dep\msvc\include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\imgui\include;$(SolutionDir)dep\xbyak\xbyak;$(SolutionDir)dep\tinyxml2\include;$(SolutionDir)dep\zlib\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SolutionDir)dep\msvc\include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\imgui\include;$(SolutionDir)dep\xbyak\xbyak;$(SolutionDir)dep\tinyxml2\include;$(SolutionDir)dep\zlib\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<WholeProgramOptimization>true</WholeProgramOptimization>
<LanguageStandard>stdcpp17</LanguageStandard>

View file

@ -44,6 +44,7 @@
<ClCompile Include="namco_guncon.cpp" />
<ClCompile Include="playstation_mouse.cpp" />
<ClCompile Include="negcon.cpp" />
<ClCompile Include="gpu_hw_vulkan.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="types.h" />
@ -89,6 +90,7 @@
<ClInclude Include="namco_guncon.h" />
<ClInclude Include="playstation_mouse.h" />
<ClInclude Include="negcon.h" />
<ClInclude Include="gpu_hw_vulkan.h" />
</ItemGroup>
<ItemGroup>
<None Include="cpu_core.inl" />

View file

@ -164,6 +164,9 @@ public:
// gpu_hw_opengl.cpp
static std::unique_ptr<GPU> CreateHardwareOpenGLRenderer();
// gpu_hw_vulkan.cpp
static std::unique_ptr<GPU> CreateHardwareVulkanRenderer();
// gpu_sw.cpp
static std::unique_ptr<GPU> CreateSoftwareRenderer();
@ -602,7 +605,7 @@ protected:
void ClearTextureWindowChangedFlag() { texture_window_changed = false; }
} m_draw_mode = {};
Common::Rectangle<u32> m_drawing_area;
Common::Rectangle<u32> m_drawing_area{0, 0, VRAM_WIDTH, VRAM_HEIGHT};
struct DrawingOffset
{

View file

@ -527,6 +527,36 @@ bool GPU_HW::UseVRAMCopyShader(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 w
.Intersects(Common::Rectangle<u32>::FromExtents(dst_x, dst_y, width, height)));
}
GPU_HW::VRAMFillUBOData GPU_HW::GetVRAMFillUBOData(u32 x, u32 y, u32 width, u32 height, u32 color) const
{
// drop precision unless true colour is enabled
if (!m_true_color)
color = RGBA5551ToRGBA8888(RGBA8888ToRGBA5551(color));
VRAMFillUBOData uniforms;
std::tie(uniforms.u_fill_color[0], uniforms.u_fill_color[1], uniforms.u_fill_color[2], uniforms.u_fill_color[3]) =
RGBA8ToFloat(color);
uniforms.u_interlaced_displayed_field = GetActiveLineLSB();
return uniforms;
}
GPU_HW::VRAMCopyUBOData GPU_HW::GetVRAMCopyUBOData(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 width,
u32 height) const
{
const VRAMCopyUBOData uniforms = {src_x * m_resolution_scale,
src_y * m_resolution_scale,
dst_x * m_resolution_scale,
dst_y * m_resolution_scale,
((dst_x + width) % VRAM_WIDTH) * m_resolution_scale,
((dst_y + height) % VRAM_HEIGHT) * m_resolution_scale,
width * m_resolution_scale,
height * m_resolution_scale,
m_GPUSTAT.set_mask_while_drawing ? 1u : 0u,
GetCurrentNormalizedBatchVertexDepthID()};
return uniforms;
}
GPU_HW::BatchPrimitive GPU_HW::GetPrimitiveForCommand(RenderCommand rc)
{
if (rc.primitive == Primitive::Line)

View file

@ -14,9 +14,7 @@ public:
enum class BatchPrimitive : u8
{
Lines = 0,
LineStrip = 1,
Triangles = 2,
TriangleStrip = 3
Triangles = 1
};
enum class BatchRenderMode : u8
@ -119,6 +117,12 @@ protected:
u32 u_set_mask_while_drawing;
};
struct VRAMFillUBOData
{
float u_fill_color[4];
u32 u_interlaced_displayed_field;
};
struct VRAMWriteUBOData
{
u32 u_base_coords[2];
@ -230,6 +234,9 @@ protected:
/// Returns true if the VRAM copy shader should be used (oversized copies, masking).
bool UseVRAMCopyShader(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 width, u32 height) const;
VRAMFillUBOData GetVRAMFillUBOData(u32 x, u32 y, u32 width, u32 height, u32 color) const;
VRAMCopyUBOData GetVRAMCopyUBOData(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 width, u32 height) const;
/// Handles quads with flipped texture coordinate directions.
static void HandleFlippedQuadTextureCoordinates(BatchVertex* vertices);

View file

@ -534,9 +534,8 @@ void GPU_HW_D3D11::DrawBatchVertices(BatchRenderMode render_mode, u32 base_verte
{
const bool textured = (m_batch.texture_mode != TextureMode::Disabled);
static constexpr std::array<D3D11_PRIMITIVE_TOPOLOGY, 4> d3d_primitives = {
{D3D11_PRIMITIVE_TOPOLOGY_LINELIST, D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST,
D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP}};
static constexpr std::array<D3D11_PRIMITIVE_TOPOLOGY, 2> d3d_primitives = {
{D3D11_PRIMITIVE_TOPOLOGY_LINELIST, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST}};
m_context->IASetPrimitiveTopology(d3d_primitives[static_cast<u8>(m_batch.primitive)]);
m_context->VSSetShader(m_batch_vertex_shaders[BoolToUInt8(textured)].Get(), nullptr, 0);

View file

@ -535,7 +535,7 @@ void GPU_HW_OpenGL::DrawBatchVertices(BatchRenderMode render_mode, u32 base_vert
glDepthFunc(m_GPUSTAT.check_mask_before_draw ? GL_GEQUAL : GL_ALWAYS);
static constexpr std::array<GLenum, 4> gl_primitives = {{GL_LINES, GL_LINE_STRIP, GL_TRIANGLES, GL_TRIANGLE_STRIP}};
static constexpr std::array<GLenum, 2> gl_primitives = {{GL_LINES, GL_TRIANGLES}};
glDrawArrays(gl_primitives[static_cast<u8>(m_batch.primitive)], m_batch_base_vertex, num_vertices);
}

View file

@ -14,10 +14,11 @@ GPU_HW_ShaderGen::GPU_HW_ShaderGen(HostDisplay::RenderAPI render_api, u32 resolu
{
if (m_glsl)
{
if (m_render_api == HostDisplay::RenderAPI::OpenGL || m_render_api == HostDisplay::RenderAPI::OpenGLES)
SetGLSLVersionString();
m_use_glsl_interface_blocks = (GLAD_GL_ES_VERSION_3_2 || GLAD_GL_VERSION_3_2);
m_use_glsl_binding_layout = UseGLSLBindingLayout();
m_use_glsl_interface_blocks = (IsVulkan() || GLAD_GL_ES_VERSION_3_2 || GLAD_GL_VERSION_3_2);
m_use_glsl_binding_layout = (IsVulkan() || UseGLSLBindingLayout());
}
}
@ -82,6 +83,8 @@ void GPU_HW_ShaderGen::WriteHeader(std::stringstream& ss)
{
if (m_render_api == HostDisplay::RenderAPI::OpenGL || m_render_api == HostDisplay::RenderAPI::OpenGLES)
ss << m_glsl_version_string << "\n\n";
else if (m_render_api == HostDisplay::RenderAPI::Vulkan)
ss << "#version 450 core\n\n";
// Extension enabling for OpenGL.
if (m_render_api == HostDisplay::RenderAPI::OpenGLES)
@ -107,6 +110,7 @@ void GPU_HW_ShaderGen::WriteHeader(std::stringstream& ss)
DefineMacro(ss, "API_OPENGL", m_render_api == HostDisplay::RenderAPI::OpenGL);
DefineMacro(ss, "API_OPENGL_ES", m_render_api == HostDisplay::RenderAPI::OpenGLES);
DefineMacro(ss, "API_D3D11", m_render_api == HostDisplay::RenderAPI::D3D11);
DefineMacro(ss, "API_VULKAN", m_render_api == HostDisplay::RenderAPI::Vulkan);
if (m_render_api == HostDisplay::RenderAPI::OpenGLES)
{
@ -219,9 +223,17 @@ float4 RGBA5551ToRGBA8(uint v)
)";
}
void GPU_HW_ShaderGen::DeclareUniformBuffer(std::stringstream& ss, const std::initializer_list<const char*>& members)
void GPU_HW_ShaderGen::DeclareUniformBuffer(std::stringstream& ss, const std::initializer_list<const char*>& members,
bool push_constant_on_vulkan)
{
if (m_glsl)
if (IsVulkan())
{
if (push_constant_on_vulkan)
ss << "layout(push_constant) uniform PushConstants\n";
else
ss << "layout(std140, set = 0, binding = 0) uniform UBOBlock\n";
}
else if (m_glsl)
{
if (m_use_glsl_binding_layout)
ss << "layout(std140, binding = 1) uniform UBOBlock\n";
@ -243,7 +255,9 @@ void GPU_HW_ShaderGen::DeclareTexture(std::stringstream& ss, const char* name, u
{
if (m_glsl)
{
if (m_use_glsl_binding_layout)
if (IsVulkan())
ss << "layout(set = 0, binding = " << (index + 1u) << ") ";
else if (m_use_glsl_binding_layout)
ss << "layout(binding = " << index << ") ";
ss << "uniform sampler2D " << name << ";\n";
@ -260,7 +274,9 @@ void GPU_HW_ShaderGen::DeclareTextureBuffer(std::stringstream& ss, const char* n
{
if (m_glsl)
{
if (m_use_glsl_binding_layout)
if (IsVulkan())
ss << "layout(set = 0, binding = " << index << ") ";
else if (m_use_glsl_binding_layout)
ss << "layout(binding = " << index << ") ";
ss << "uniform " << (is_int ? (is_unsigned ? "u" : "i") : "") << "samplerBuffer " << name << ";\n";
@ -296,6 +312,9 @@ void GPU_HW_ShaderGen::DeclareVertexEntryPoint(
if (m_use_glsl_interface_blocks)
{
if (IsVulkan())
ss << "layout(location = 0) ";
ss << "out VertexData {\n";
for (u32 i = 0; i < num_color_outputs; i++)
ss << " float4 v_col" << i << ";\n";
@ -321,7 +340,12 @@ void GPU_HW_ShaderGen::DeclareVertexEntryPoint(
ss << "#define v_pos gl_Position\n\n";
if (declare_vertex_id)
{
if (IsVulkan())
ss << "#define v_id uint(gl_VertexIndex)\n";
else
ss << "#define v_id uint(gl_VertexID)\n";
}
ss << "\n";
ss << "void main()\n";
@ -366,6 +390,9 @@ void GPU_HW_ShaderGen::DeclareFragmentEntryPoint(
{
if (m_use_glsl_interface_blocks)
{
if (IsVulkan())
ss << "layout(location = 0) ";
ss << "in VertexData {\n";
for (u32 i = 0; i < num_color_inputs; i++)
ss << " float4 v_col" << i << ";\n";
@ -467,7 +494,8 @@ void GPU_HW_ShaderGen::WriteBatchUniformBuffer(std::stringstream& ss)
DeclareUniformBuffer(ss,
{"uint2 u_texture_window_mask", "uint2 u_texture_window_offset", "float u_src_alpha_factor",
"float u_dst_alpha_factor", "uint u_interlaced_displayed_field", "uint u_base_vertex_depth_id",
"bool u_check_mask_before_draw", "bool u_set_mask_while_drawing"});
"bool u_check_mask_before_draw", "bool u_set_mask_while_drawing"},
false);
}
std::string GPU_HW_ShaderGen::GenerateBatchVertexShader(bool textured)
@ -507,6 +535,12 @@ std::string GPU_HW_ShaderGen::GenerateBatchVertexShader(bool textured)
#if API_OPENGL || API_OPENGL_ES
pos_y += EPSILON;
#endif
// NDC space Y flip in Vulkan.
#if API_VULKAN
pos_y = -pos_y;
#endif
v_pos = float4(pos_x, pos_y, 0.0, 1.0);
#if API_D3D11
@ -861,13 +895,18 @@ CONSTANT float2 WIDTH = (1.0 / float2(VRAM_SIZE)) * float2(RESOLUTION_SCALE, RES
// GS is a pain, too different between HLSL and GLSL...
if (m_glsl)
{
ss << R"(
in VertexData {
if (IsVulkan())
ss << "layout(location = 0) ";
ss << R"(in VertexData {
float4 v_col0;
nointerpolation float v_depth;
} in_data[];
} in_data[];)";
out VertexData {
if (IsVulkan())
ss << "layout(location = 0) ";
ss << R"(out VertexData {
float4 v_col0;
nointerpolation float v_depth;
} out_data;
@ -968,8 +1007,8 @@ std::string GPU_HW_ShaderGen::GenerateScreenQuadVertexShader()
{
v_tex0 = float2(float((v_id << 1) & 2u), float(v_id & 2u));
v_pos = float4(v_tex0 * float2(2.0f, -2.0f) + float2(-1.0f, 1.0f), 0.0f, 1.0f);
#if API_OPENGL || API_OPENGL_ES
v_pos.y = -gl_Position.y;
#if API_OPENGL || API_OPENGL_ES || API_VULKAN
v_pos.y = -v_pos.y;
#endif
}
)";
@ -981,7 +1020,7 @@ std::string GPU_HW_ShaderGen::GenerateFillFragmentShader()
{
std::stringstream ss;
WriteHeader(ss);
DeclareUniformBuffer(ss, {"float4 u_fill_color"});
DeclareUniformBuffer(ss, {"float4 u_fill_color"}, true);
DeclareFragmentEntryPoint(ss, 0, 1, {}, false, 1, true);
ss << R"(
@ -999,7 +1038,7 @@ std::string GPU_HW_ShaderGen::GenerateInterlacedFillFragmentShader()
std::stringstream ss;
WriteHeader(ss);
WriteCommonFunctions(ss);
DeclareUniformBuffer(ss, {"float4 u_fill_color", "uint u_interlaced_displayed_field"});
DeclareUniformBuffer(ss, {"float4 u_fill_color", "uint u_interlaced_displayed_field"}, true);
DeclareFragmentEntryPoint(ss, 0, 1, {}, true, 1, true);
ss << R"(
@ -1019,7 +1058,7 @@ std::string GPU_HW_ShaderGen::GenerateCopyFragmentShader()
{
std::stringstream ss;
WriteHeader(ss);
DeclareUniformBuffer(ss, {"float4 u_src_rect"});
DeclareUniformBuffer(ss, {"float4 u_src_rect"}, true);
DeclareTexture(ss, "samp0", 0);
DeclareFragmentEntryPoint(ss, 0, 1, {}, false, 1);
@ -1043,7 +1082,7 @@ std::string GPU_HW_ShaderGen::GenerateDisplayFragmentShader(bool depth_24bit,
DefineMacro(ss, "INTERLEAVED", interlace_mode == GPU_HW::InterlacedRenderMode::InterleavedFields);
WriteCommonFunctions(ss);
DeclareUniformBuffer(ss, {"uint2 u_vram_offset", "uint u_crop_left", "uint u_field_offset"});
DeclareUniformBuffer(ss, {"uint2 u_vram_offset", "uint u_crop_left", "uint u_field_offset"}, true);
DeclareTexture(ss, "samp0", 0);
DeclareFragmentEntryPoint(ss, 0, 1, {}, true, 1);
@ -1093,7 +1132,7 @@ std::string GPU_HW_ShaderGen::GenerateVRAMReadFragmentShader()
std::stringstream ss;
WriteHeader(ss);
WriteCommonFunctions(ss);
DeclareUniformBuffer(ss, {"uint2 u_base_coords", "uint2 u_size"});
DeclareUniformBuffer(ss, {"uint2 u_base_coords", "uint2 u_size"}, true);
DeclareTexture(ss, "samp0", 0);
@ -1146,8 +1185,10 @@ std::string GPU_HW_ShaderGen::GenerateVRAMWriteFragmentShader()
std::stringstream ss;
WriteHeader(ss);
WriteCommonFunctions(ss);
DeclareUniformBuffer(ss, {"uint2 u_base_coords", "uint2 u_size", "uint u_buffer_base_offset", "uint u_mask_or_bits",
"float u_depth_value"});
DeclareUniformBuffer(
ss,
{"uint2 u_base_coords", "uint2 u_size", "uint u_buffer_base_offset", "uint u_mask_or_bits", "float u_depth_value"},
true);
DeclareTextureBuffer(ss, "samp0", 0, true, true);
DeclareFragmentEntryPoint(ss, 0, 1, {}, true, 1, true);
@ -1176,8 +1217,10 @@ std::string GPU_HW_ShaderGen::GenerateVRAMCopyFragmentShader()
std::stringstream ss;
WriteHeader(ss);
WriteCommonFunctions(ss);
DeclareUniformBuffer(ss, {"uint2 u_src_coords", "uint2 u_dst_coords", "uint2 u_end_coords", "uint2 u_size",
"bool u_set_mask_bit", "float u_depth_value"});
DeclareUniformBuffer(ss,
{"uint2 u_src_coords", "uint2 u_dst_coords", "uint2 u_end_coords", "uint2 u_size",
"bool u_set_mask_bit", "float u_depth_value"},
true);
DeclareTexture(ss, "samp0", 0);
DeclareFragmentEntryPoint(ss, 0, 1, {}, true, 1, true);

View file

@ -28,9 +28,12 @@ public:
std::string GenerateVRAMUpdateDepthFragmentShader();
private:
ALWAYS_INLINE bool IsVulkan() const { return (m_render_api == HostDisplay::RenderAPI::Vulkan); }
void SetGLSLVersionString();
void WriteHeader(std::stringstream& ss);
void DeclareUniformBuffer(std::stringstream& ss, const std::initializer_list<const char*>& members);
void DeclareUniformBuffer(std::stringstream& ss, const std::initializer_list<const char*>& members,
bool push_constant_on_vulkan);
void DeclareTexture(std::stringstream& ss, const char* name, u32 index);
void DeclareTextureBuffer(std::stringstream& ss, const char* name, u32 index, bool is_int, bool is_unsigned);
void DeclareVertexEntryPoint(std::stringstream& ss, const std::initializer_list<const char*>& attributes,

1191
src/core/gpu_hw_vulkan.cpp Normal file

File diff suppressed because it is too large Load diff

124
src/core/gpu_hw_vulkan.h Normal file
View file

@ -0,0 +1,124 @@
#pragma once
#include "common/dimensional_array.h"
#include "common/vulkan/staging_texture.h"
#include "common/vulkan/stream_buffer.h"
#include "common/vulkan/texture.h"
#include "gpu_hw.h"
#include <array>
#include <memory>
#include <tuple>
class GPU_HW_Vulkan : public GPU_HW
{
public:
GPU_HW_Vulkan();
~GPU_HW_Vulkan() override;
bool Initialize(HostDisplay* host_display, System* system, DMA* dma, InterruptController* interrupt_controller,
Timers* timers) override;
void Reset() override;
void ResetGraphicsAPIState() override;
void RestoreGraphicsAPIState() override;
void UpdateSettings() override;
protected:
void UpdateDisplay() override;
void ReadVRAM(u32 x, u32 y, u32 width, u32 height) override;
void FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color) override;
void UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* data) override;
void CopyVRAM(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 width, u32 height) override;
void UpdateVRAMReadTexture() override;
void UpdateDepthBufferFromMaskBit() override;
void SetScissorFromDrawingArea() override;
void MapBatchVertexPointer(u32 required_vertices) override;
void UnmapBatchVertexPointer(u32 used_vertices) override;
void UploadUniformBuffer(const void* data, u32 data_size) override;
void DrawBatchVertices(BatchRenderMode render_mode, u32 base_vertex, u32 num_vertices) override;
private:
enum : u32
{
MAX_PUSH_CONSTANTS_SIZE = 64,
};
void SetCapabilities();
void DestroyResources();
ALWAYS_INLINE bool InRenderPass() const { return (m_current_render_pass != VK_NULL_HANDLE); }
void BeginRenderPass(VkRenderPass render_pass, VkFramebuffer framebuffer, u32 x, u32 y, u32 width, u32 height);
void BeginVRAMRenderPass();
void EndRenderPass();
bool CreatePipelineLayouts();
bool CreateSamplers();
bool CreateFramebuffer();
void ClearFramebuffer();
void DestroyFramebuffer();
bool CreateVertexBuffer();
bool CreateUniformBuffer();
bool CreateTextureBuffer();
bool CompilePipelines();
void DestroyPipelines();
VkRenderPass m_current_render_pass = VK_NULL_HANDLE;
VkRenderPass m_vram_render_pass = VK_NULL_HANDLE;
VkRenderPass m_vram_update_depth_render_pass = VK_NULL_HANDLE;
VkRenderPass m_display_render_pass = VK_NULL_HANDLE;
VkRenderPass m_vram_readback_render_pass = VK_NULL_HANDLE;
VkDescriptorSetLayout m_batch_descriptor_set_layout = VK_NULL_HANDLE;
VkDescriptorSetLayout m_single_sampler_descriptor_set_layout = VK_NULL_HANDLE;
VkDescriptorSetLayout m_vram_write_descriptor_set_layout = VK_NULL_HANDLE;
VkPipelineLayout m_batch_pipeline_layout = VK_NULL_HANDLE;
VkPipelineLayout m_no_samplers_pipeline_layout = VK_NULL_HANDLE;
VkPipelineLayout m_single_sampler_pipeline_layout = VK_NULL_HANDLE;
VkPipelineLayout m_vram_write_pipeline_layout = VK_NULL_HANDLE;
Vulkan::Texture m_vram_texture;
Vulkan::Texture m_vram_depth_texture;
Vulkan::Texture m_vram_read_texture;
Vulkan::Texture m_vram_readback_texture;
Vulkan::StagingTexture m_vram_readback_staging_texture;
Vulkan::Texture m_display_texture;
VkFramebuffer m_vram_framebuffer = VK_NULL_HANDLE;
VkFramebuffer m_vram_update_depth_framebuffer = VK_NULL_HANDLE;
VkFramebuffer m_vram_readback_framebuffer = VK_NULL_HANDLE;
VkFramebuffer m_display_framebuffer = VK_NULL_HANDLE;
VkSampler m_point_sampler = VK_NULL_HANDLE;
VkSampler m_linear_sampler = VK_NULL_HANDLE;
VkDescriptorSet m_batch_descriptor_set = VK_NULL_HANDLE;
VkDescriptorSet m_vram_copy_descriptor_set = VK_NULL_HANDLE;
VkDescriptorSet m_vram_read_descriptor_set = VK_NULL_HANDLE;
VkDescriptorSet m_vram_write_descriptor_set = VK_NULL_HANDLE;
Vulkan::StreamBuffer m_vertex_stream_buffer;
Vulkan::StreamBuffer m_uniform_stream_buffer;
Vulkan::StreamBuffer m_texture_stream_buffer;
u32 m_current_uniform_buffer_offset = 0;
VkBufferView m_texture_stream_buffer_view = VK_NULL_HANDLE;
// [primitive][depth_test][render_mode][texture_mode][transparency_mode][dithering][interlacing]
DimensionalArray<VkPipeline, 2, 2, 5, 9, 4, 2, 2> m_batch_pipelines{};
// [interlaced]
std::array<VkPipeline, 2> m_vram_fill_pipelines{};
// [depth_test]
std::array<VkPipeline, 2> m_vram_write_pipelines{};
std::array<VkPipeline, 2> m_vram_copy_pipelines{};
VkPipeline m_vram_readback_pipeline = VK_NULL_HANDLE;
VkPipeline m_vram_update_depth_pipeline = VK_NULL_HANDLE;
// [depth_24][interlace_mode]
DimensionalArray<VkPipeline, 3, 2> m_display_pipelines{};
};

View file

@ -314,6 +314,11 @@ void HostInterface::OnRunningGameChanged() {}
void HostInterface::OnControllerTypeChanged(u32 slot) {}
std::string HostInterface::GetShaderCacheDirectory()
{
return GetUserDirectoryRelativePath("cache");
}
void HostInterface::SetDefaultSettings(SettingsInterface& si)
{
si.SetStringValue("Console", "Region", Settings::GetConsoleRegionName(ConsoleRegion::Auto));

View file

@ -114,6 +114,9 @@ protected:
virtual void OnRunningGameChanged();
virtual void OnControllerTypeChanged(u32 slot);
/// Returns the path to the shader cache directory.
virtual std::string GetShaderCacheDirectory();
/// Restores all settings to defaults.
virtual void SetDefaultSettings(SettingsInterface& si);

View file

@ -288,6 +288,10 @@ bool System::CreateGPU(GPURenderer renderer)
m_gpu = GPU::CreateHardwareOpenGLRenderer();
break;
case GPURenderer::HardwareVulkan:
m_gpu = GPU::CreateHardwareVulkanRenderer();
break;
#ifdef WIN32
case GPURenderer::HardwareD3D11:
m_gpu = GPU::CreateHardwareD3D11Renderer();