From e804b5e7012ff2065f87dd94ae5d4d2f612940c4 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Sat, 2 Sep 2023 22:09:20 +1000 Subject: [PATCH] GPUDevice: Support geometry shaders --- src/core/gpu.cpp | 1 + src/core/gpu_hw.cpp | 1 + src/core/shader_cache_version.h | 4 +-- src/util/d3d11_device.cpp | 1 + src/util/d3d11_device.h | 1 + src/util/d3d11_pipeline.cpp | 36 ++++++++++++++++++------- src/util/d3d11_pipeline.h | 7 +++-- src/util/d3d12_device.cpp | 1 + src/util/d3d12_pipeline.cpp | 7 +++++ src/util/d3d_common.cpp | 12 ++++++--- src/util/gpu_device.cpp | 19 +++++-------- src/util/gpu_device.h | 3 +++ src/util/metal_device.mm | 1 + src/util/opengl_device.cpp | 2 ++ src/util/opengl_pipeline.cpp | 32 ++++++++++++++++------ src/util/opengl_pipeline.h | 12 ++++++--- src/util/postprocessing_shader_fx.cpp | 1 + src/util/postprocessing_shader_glsl.cpp | 1 + src/util/spirv_compiler.cpp | 11 +++++++- src/util/spirv_compiler.h | 3 +++ src/util/vulkan_device.cpp | 3 +++ src/util/vulkan_pipeline.cpp | 6 ++++- 22 files changed, 121 insertions(+), 44 deletions(-) diff --git a/src/core/gpu.cpp b/src/core/gpu.cpp index 45b302fb3..a0b9cf8ad 100644 --- a/src/core/gpu.cpp +++ b/src/core/gpu.cpp @@ -1591,6 +1591,7 @@ bool GPU::CompileDisplayPipeline() plconfig.vertex_shader = vso.get(); plconfig.fragment_shader = fso.get(); + plconfig.geometry_shader = nullptr; if (!(m_display_pipeline = g_gpu_device->CreatePipeline(plconfig))) return false; GL_OBJECT_NAME(m_display_pipeline, "Display Pipeline [%s]", diff --git a/src/core/gpu_hw.cpp b/src/core/gpu_hw.cpp index c9117c627..28eb9d62c 100644 --- a/src/core/gpu_hw.cpp +++ b/src/core/gpu_hw.cpp @@ -680,6 +680,7 @@ bool GPU_HW::CompilePipelines() plconfig.depth_format = VRAM_DS_FORMAT; plconfig.samples = m_multisamples; plconfig.per_sample_shading = m_per_sample_shading; + plconfig.geometry_shader = nullptr; // [depth_test][render_mode][texture_mode][transparency_mode][dithering][interlacing] for (u8 depth_test = 0; depth_test < 3; depth_test++) diff --git a/src/core/shader_cache_version.h b/src/core/shader_cache_version.h index 840e49e5d..a867c1459 100644 --- a/src/core/shader_cache_version.h +++ b/src/core/shader_cache_version.h @@ -1,7 +1,7 @@ -// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin +// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) #pragma once #include "common/types.h" -static constexpr u32 SHADER_CACHE_VERSION = 9; \ No newline at end of file +static constexpr u32 SHADER_CACHE_VERSION = 10; \ No newline at end of file diff --git a/src/util/d3d11_device.cpp b/src/util/d3d11_device.cpp index 5de6c81ac..559e86608 100644 --- a/src/util/d3d11_device.cpp +++ b/src/util/d3d11_device.cpp @@ -173,6 +173,7 @@ void D3D11Device::SetFeatures() m_features.noperspective_interpolation = true; m_features.supports_texture_buffers = true; m_features.texture_buffers_emulated_with_ssbo = false; + m_features.geometry_shaders = true; m_features.partial_msaa_resolve = false; m_features.gpu_timing = true; m_features.shader_cache = true; diff --git a/src/util/d3d11_device.h b/src/util/d3d11_device.h index 5fcaef93c..bf696bacc 100644 --- a/src/util/d3d11_device.h +++ b/src/util/d3d11_device.h @@ -183,6 +183,7 @@ private: ID3D11InputLayout* m_current_input_layout = nullptr; ID3D11VertexShader* m_current_vertex_shader = nullptr; + ID3D11GeometryShader* m_current_geometry_shader = nullptr; ID3D11PixelShader* m_current_pixel_shader = nullptr; ID3D11RasterizerState* m_current_rasterizer_state = nullptr; ID3D11DepthStencilState* m_current_depth_state = nullptr; diff --git a/src/util/d3d11_pipeline.cpp b/src/util/d3d11_pipeline.cpp index c5721699f..0200e3749 100644 --- a/src/util/d3d11_pipeline.cpp +++ b/src/util/d3d11_pipeline.cpp @@ -34,6 +34,12 @@ ID3D11PixelShader* D3D11Shader::GetPixelShader() const return static_cast(m_shader.Get()); } +ID3D11GeometryShader* D3D11Shader::GetGeometryShader() const +{ + DebugAssert(m_stage == GPUShaderStage::Geometry); + return static_cast(m_shader.Get()); +} + ID3D11ComputeShader* D3D11Shader::GetComputeShader() const { DebugAssert(m_stage == GPUShaderStage::Compute); @@ -64,6 +70,11 @@ std::unique_ptr D3D11Device::CreateShaderFromBinary(GPUShaderStage st reinterpret_cast(shader.GetAddressOf())); break; + case GPUShaderStage::Geometry: + hr = m_device->CreateGeometryShader(data.data(), data.size(), nullptr, + reinterpret_cast(shader.GetAddressOf())); + break; + case GPUShaderStage::Compute: hr = m_device->CreateComputeShader(data.data(), data.size(), nullptr, reinterpret_cast(shader.GetAddressOf())); @@ -98,11 +109,11 @@ std::unique_ptr D3D11Device::CreateShaderFromSource(GPUShaderStage st D3D11Pipeline::D3D11Pipeline(ComPtr rs, ComPtr ds, ComPtr bs, ComPtr il, ComPtr vs, - ComPtr ps, D3D11_PRIMITIVE_TOPOLOGY topology, u32 vertex_stride, - u32 blend_factor) + ComPtr gs, ComPtr ps, + D3D11_PRIMITIVE_TOPOLOGY topology, u32 vertex_stride, u32 blend_factor) : m_rs(std::move(rs)), m_ds(std::move(ds)), m_bs(std::move(bs)), m_il(std::move(il)), m_vs(std::move(vs)), - m_ps(std::move(ps)), m_topology(topology), m_vertex_stride(vertex_stride), m_blend_factor(blend_factor), - m_blend_factor_float(GPUDevice::RGBA8ToFloat(blend_factor)) + m_gs(std::move(gs)), m_ps(std::move(ps)), m_topology(topology), m_vertex_stride(vertex_stride), + m_blend_factor(blend_factor), m_blend_factor_float(GPUDevice::RGBA8ToFloat(blend_factor)) { } @@ -318,11 +329,12 @@ std::unique_ptr D3D11Device::CreatePipeline(const GPUPipeline::Grap D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, // TriangleStrips }}; - return std::unique_ptr( - new D3D11Pipeline(std::move(rs), std::move(ds), std::move(bs), std::move(il), - static_cast(config.vertex_shader)->GetVertexShader(), - static_cast(config.fragment_shader)->GetPixelShader(), - primitives[static_cast(config.primitive)], vertex_stride, config.blend.constant)); + return std::unique_ptr(new D3D11Pipeline( + std::move(rs), std::move(ds), std::move(bs), std::move(il), + static_cast(config.vertex_shader)->GetVertexShader(), + config.geometry_shader ? static_cast(config.geometry_shader)->GetGeometryShader() : nullptr, + static_cast(config.fragment_shader)->GetPixelShader(), + primitives[static_cast(config.primitive)], vertex_stride, config.blend.constant)); } void D3D11Device::SetPipeline(GPUPipeline* pipeline) @@ -358,6 +370,12 @@ void D3D11Device::SetPipeline(GPUPipeline* pipeline) m_context->VSSetShader(vs, nullptr, 0); } + if (ID3D11GeometryShader* gs = PL->GetGeometryShader(); m_current_geometry_shader != gs) + { + m_current_geometry_shader = gs; + m_context->GSSetShader(gs, nullptr, 0); + } + if (ID3D11PixelShader* ps = PL->GetPixelShader(); m_current_pixel_shader != ps) { m_current_pixel_shader = ps; diff --git a/src/util/d3d11_pipeline.h b/src/util/d3d11_pipeline.h index 9c22c1fe5..e23190103 100644 --- a/src/util/d3d11_pipeline.h +++ b/src/util/d3d11_pipeline.h @@ -25,6 +25,7 @@ public: ID3D11VertexShader* GetVertexShader() const; ID3D11PixelShader* GetPixelShader() const; + ID3D11GeometryShader* GetGeometryShader() const; ID3D11ComputeShader* GetComputeShader() const; ALWAYS_INLINE const std::vector& GetBytecode() const { return m_bytecode; } @@ -55,6 +56,7 @@ public: ALWAYS_INLINE ID3D11BlendState* GetBlendState() const { return m_bs.Get(); } ALWAYS_INLINE ID3D11InputLayout* GetInputLayout() const { return m_il.Get(); } ALWAYS_INLINE ID3D11VertexShader* GetVertexShader() const { return m_vs.Get(); } + ALWAYS_INLINE ID3D11GeometryShader* GetGeometryShader() const { return m_gs.Get(); } ALWAYS_INLINE ID3D11PixelShader* GetPixelShader() const { return m_ps.Get(); } ALWAYS_INLINE D3D11_PRIMITIVE_TOPOLOGY GetPrimitiveTopology() const { return m_topology; } ALWAYS_INLINE u32 GetVertexStride() const { return m_vertex_stride; } @@ -63,14 +65,15 @@ public: private: D3D11Pipeline(ComPtr rs, ComPtr ds, ComPtr bs, - ComPtr il, ComPtr vs, ComPtr ps, - D3D11_PRIMITIVE_TOPOLOGY topology, u32 vertex_stride, u32 blend_factor); + ComPtr il, ComPtr vs, ComPtr gs, + ComPtr ps, D3D11_PRIMITIVE_TOPOLOGY topology, u32 vertex_stride, u32 blend_factor); ComPtr m_rs; ComPtr m_ds; ComPtr m_bs; ComPtr m_il; ComPtr m_vs; + ComPtr m_gs; ComPtr m_ps; D3D11_PRIMITIVE_TOPOLOGY m_topology; u32 m_vertex_stride; diff --git a/src/util/d3d12_device.cpp b/src/util/d3d12_device.cpp index 67e354676..b96012f20 100644 --- a/src/util/d3d12_device.cpp +++ b/src/util/d3d12_device.cpp @@ -1203,6 +1203,7 @@ void D3D12Device::SetFeatures() m_features.per_sample_shading = true; m_features.supports_texture_buffers = true; m_features.texture_buffers_emulated_with_ssbo = false; + m_features.geometry_shaders = true; m_features.partial_msaa_resolve = true; m_features.gpu_timing = true; m_features.shader_cache = true; diff --git a/src/util/d3d12_pipeline.cpp b/src/util/d3d12_pipeline.cpp index c5362df0b..55fa430a9 100644 --- a/src/util/d3d12_pipeline.cpp +++ b/src/util/d3d12_pipeline.cpp @@ -88,6 +88,8 @@ std::string D3D12Pipeline::GetPipelineName(const GraphicsConfig& config) hash.Update(shader->GetBytecodeData(), shader->GetBytecodeSize()); if (const D3D12Shader* shader = static_cast(config.fragment_shader)) hash.Update(shader->GetBytecodeData(), shader->GetBytecodeSize()); + if (const D3D12Shader* shader = static_cast(config.geometry_shader)) + hash.Update(shader->GetBytecodeData(), shader->GetBytecodeSize()); hash.Update(&config.color_format, sizeof(config.color_format)); hash.Update(&config.depth_format, sizeof(config.depth_format)); hash.Update(&config.samples, sizeof(config.samples)); @@ -178,6 +180,11 @@ std::unique_ptr D3D12Device::CreatePipeline(const GPUPipeline::Grap static_cast(config.vertex_shader)->GetBytecodeSize()); gpb.SetPixelShader(static_cast(config.fragment_shader)->GetBytecodeData(), static_cast(config.fragment_shader)->GetBytecodeSize()); + if (config.geometry_shader) + { + gpb.SetGeometryShader(static_cast(config.geometry_shader)->GetBytecodeData(), + static_cast(config.geometry_shader)->GetBytecodeSize()); + } gpb.SetPrimitiveTopologyType(primitive_types[static_cast(config.primitive)]); if (!config.input_layout.vertex_attributes.empty()) diff --git a/src/util/d3d_common.cpp b/src/util/d3d_common.cpp index e35a91057..66f3d3b22 100644 --- a/src/util/d3d_common.cpp +++ b/src/util/d3d_common.cpp @@ -358,21 +358,24 @@ std::optional> D3DCommon::CompileShader(D3D_FEATURE_LEVEL f { case D3D_FEATURE_LEVEL_10_0: { - static constexpr std::array targets = {{"vs_4_0", "ps_4_0", "cs_4_0"}}; + static constexpr std::array(GPUShaderStage::MaxCount)> targets = { + {"vs_4_0", "ps_4_0", "gs_4_0", "cs_4_0"}}; target = targets[static_cast(stage)]; } break; case D3D_FEATURE_LEVEL_10_1: { - static constexpr std::array targets = {{"vs_4_1", "ps_4_1", "cs_4_1"}}; + static constexpr std::array(GPUShaderStage::MaxCount)> targets = { + {"vs_4_1", "ps_4_1", "gs_4_0", "cs_4_1"}}; target = targets[static_cast(stage)]; } break; case D3D_FEATURE_LEVEL_11_0: { - static constexpr std::array targets = {{"vs_5_0", "ps_5_0", "cs_5_0"}}; + static constexpr std::array(GPUShaderStage::MaxCount)> targets = { + {"vs_5_0", "ps_5_0", "gs_5_0", "cs_5_0"}}; target = targets[static_cast(stage)]; } break; @@ -380,7 +383,8 @@ std::optional> D3DCommon::CompileShader(D3D_FEATURE_LEVEL f case D3D_FEATURE_LEVEL_11_1: default: { - static constexpr std::array targets = {{"vs_5_1", "ps_5_1", "cs_5_1"}}; + static constexpr std::array(GPUShaderStage::MaxCount)> targets = { + {"vs_5_1", "ps_5_1", "gs_5_1", "cs_5_1"}}; target = targets[static_cast(stage)]; } break; diff --git a/src/util/gpu_device.cpp b/src/util/gpu_device.cpp index 6b9af1799..ba080e91e 100644 --- a/src/util/gpu_device.cpp +++ b/src/util/gpu_device.cpp @@ -2,7 +2,7 @@ // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) #include "gpu_device.h" -#include "core/host.h" // TODO: Remove, needed for getting fullscreen mode. +#include "core/host.h" // TODO: Remove, needed for getting fullscreen mode. #include "core/settings.h" // TODO: Remove, needed for dump directory. #include "shadergen.h" @@ -78,18 +78,10 @@ GPUShader::~GPUShader() = default; const char* GPUShader::GetStageName(GPUShaderStage stage) { - switch (stage) - { - case GPUShaderStage::Vertex: - return "Vertex"; - case GPUShaderStage::Fragment: - return "Fragment"; - case GPUShaderStage::Compute: - return "Compute"; - default: - UnreachableCode(); - return ""; - } + static constexpr std::array(GPUShaderStage::MaxCount)> names = {"Vertex", "Fragment", + "Geometry", "Compute"}; + + return names[static_cast(stage)]; } GPUPipeline::GPUPipeline() = default; @@ -432,6 +424,7 @@ bool GPUDevice::CreateResources() plconfig.samples = 1; plconfig.per_sample_shading = false; plconfig.vertex_shader = imgui_vs.get(); + plconfig.geometry_shader = nullptr; plconfig.fragment_shader = imgui_fs.get(); m_imgui_pipeline = CreatePipeline(plconfig); diff --git a/src/util/gpu_device.h b/src/util/gpu_device.h index 25b2c65b8..ffa9805a2 100644 --- a/src/util/gpu_device.h +++ b/src/util/gpu_device.h @@ -114,6 +114,7 @@ enum class GPUShaderStage : u8 { Vertex, Fragment, + Geometry, Compute, MaxCount @@ -374,6 +375,7 @@ public: BlendState blend; GPUShader* vertex_shader; + GPUShader* geometry_shader; GPUShader* fragment_shader; GPUTexture::Format color_format; @@ -433,6 +435,7 @@ public: bool noperspective_interpolation : 1; bool supports_texture_buffers : 1; bool texture_buffers_emulated_with_ssbo : 1; + bool geometry_shaders : 1; bool partial_msaa_resolve : 1; bool gpu_timing : 1; bool shader_cache : 1; diff --git a/src/util/metal_device.mm b/src/util/metal_device.mm index 0ddd92452..9ab6fbaa4 100644 --- a/src/util/metal_device.mm +++ b/src/util/metal_device.mm @@ -210,6 +210,7 @@ void MetalDevice::SetFeatures() m_features.noperspective_interpolation = true; m_features.supports_texture_buffers = true; m_features.texture_buffers_emulated_with_ssbo = true; + m_features.geometry_shaders = false; m_features.partial_msaa_resolve = true; m_features.shader_cache = true; m_features.pipeline_cache = false; diff --git a/src/util/opengl_device.cpp b/src/util/opengl_device.cpp index 4ded4c180..7b4a4441f 100644 --- a/src/util/opengl_device.cpp +++ b/src/util/opengl_device.cpp @@ -460,6 +460,8 @@ bool OpenGLDevice::CheckFeatures(bool* buggy_pbo) // noperspective is not supported in GLSL ES. m_features.noperspective_interpolation = !is_gles; + m_features.geometry_shaders = GLAD_GL_VERSION_3_2 || GLAD_GL_ES_VERSION_3_2; + m_features.gpu_timing = !(m_gl_context->IsGLES() && (!GLAD_GL_EXT_disjoint_timer_query || !glGetQueryObjectivEXT || !glGetQueryObjectui64vEXT)); m_features.partial_msaa_resolve = true; diff --git a/src/util/opengl_pipeline.cpp b/src/util/opengl_pipeline.cpp index 43a91bf8c..e67bf797d 100644 --- a/src/util/opengl_pipeline.cpp +++ b/src/util/opengl_pipeline.cpp @@ -41,7 +41,7 @@ struct PipelineDiskCacheIndexEntry u32 uncompressed_size; u32 compressed_size; }; -static_assert(sizeof(PipelineDiskCacheIndexEntry) == 128); // No padding +static_assert(sizeof(PipelineDiskCacheIndexEntry) == 112); // No padding static unsigned s_next_bad_shader_id = 1; @@ -50,6 +50,7 @@ static GLenum GetGLShaderType(GPUShaderStage stage) static constexpr std::array(GPUShaderStage::MaxCount)> mapping = {{ GL_VERTEX_SHADER, // Vertex GL_FRAGMENT_SHADER, // Fragment + GL_GEOMETRY_SHADER, // Geometry GL_COMPUTE_SHADER, // Compute }}; @@ -222,13 +223,12 @@ size_t OpenGLPipeline::ProgramCacheKeyHash::operator()(const ProgramCacheKey& k) { // TODO: maybe use xxhash here... std::size_t h = 0; - hash_combine(h, k.vs_key.entry_point_low, k.vs_key.entry_point_high, k.vs_key.source_hash_low, - k.vs_key.source_hash_high, k.vs_key.source_length, k.vs_key.shader_type); - hash_combine(h, k.fs_key.entry_point_low, k.fs_key.entry_point_high, k.fs_key.source_hash_low, - k.fs_key.source_hash_high, k.fs_key.source_length, k.fs_key.shader_type); hash_combine(h, k.va_key.num_vertex_attributes, k.va_key.vertex_attribute_stride); for (const VertexAttribute& va : k.va_key.vertex_attributes) hash_combine(h, va.key); + hash_combine(h, k.vs_hash_low, k.vs_hash_high, k.vs_length); + hash_combine(h, k.fs_hash_low, k.fs_hash_high, k.fs_length); + hash_combine(h, k.gs_hash_low, k.gs_hash_high, k.gs_length); return h; } @@ -236,9 +236,21 @@ OpenGLPipeline::ProgramCacheKey OpenGLPipeline::GetProgramCacheKey(const Graphic { Assert(plconfig.input_layout.vertex_attributes.size() <= MAX_VERTEX_ATTRIBUTES); + const GPUShaderCache::CacheIndexKey& vs_key = static_cast(plconfig.vertex_shader)->GetKey(); + const GPUShaderCache::CacheIndexKey& fs_key = static_cast(plconfig.fragment_shader)->GetKey(); + const GPUShaderCache::CacheIndexKey* gs_key = + plconfig.geometry_shader ? &static_cast(plconfig.geometry_shader)->GetKey() : nullptr; + ProgramCacheKey ret; - ret.vs_key = static_cast(plconfig.vertex_shader)->GetKey(); - ret.fs_key = static_cast(plconfig.fragment_shader)->GetKey(); + ret.vs_hash_low = vs_key.source_hash_low; + ret.vs_hash_high = vs_key.source_hash_high; + ret.vs_length = vs_key.source_length; + ret.fs_hash_low = fs_key.source_hash_low; + ret.fs_hash_high = fs_key.source_hash_high; + ret.fs_length = fs_key.source_length; + ret.gs_hash_low = gs_key ? gs_key->source_hash_low : 0; + ret.gs_hash_high = gs_key ? gs_key->source_hash_high : 0; + ret.gs_length = gs_key ? gs_key->source_length : 0; std::memset(ret.va_key.vertex_attributes, 0, sizeof(ret.va_key.vertex_attributes)); ret.va_key.vertex_attribute_stride = 0; @@ -300,7 +312,9 @@ GLuint OpenGLDevice::CompileProgram(const GPUPipeline::GraphicsConfig& plconfig) { OpenGLShader* vertex_shader = static_cast(plconfig.vertex_shader); OpenGLShader* fragment_shader = static_cast(plconfig.fragment_shader); - if (!vertex_shader || !fragment_shader || !vertex_shader->Compile() || !fragment_shader->Compile()) + OpenGLShader* geometry_shader = static_cast(plconfig.geometry_shader); + if (!vertex_shader || !fragment_shader || !vertex_shader->Compile() || !fragment_shader->Compile() || + (geometry_shader && !geometry_shader->Compile())) { Log_ErrorPrintf("Failed to compile shaders."); return 0; @@ -320,6 +334,8 @@ GLuint OpenGLDevice::CompileProgram(const GPUPipeline::GraphicsConfig& plconfig) Assert(plconfig.vertex_shader && plconfig.fragment_shader); glAttachShader(program_id, vertex_shader->GetGLId()); glAttachShader(program_id, fragment_shader->GetGLId()); + if (geometry_shader) + glAttachShader(program_id, geometry_shader->GetGLId()); if (!ShaderGen::UseGLSLBindingLayout()) { diff --git a/src/util/opengl_pipeline.h b/src/util/opengl_pipeline.h index dceee94ca..72bc3158c 100644 --- a/src/util/opengl_pipeline.h +++ b/src/util/opengl_pipeline.h @@ -41,7 +41,7 @@ class OpenGLPipeline final : public GPUPipeline friend OpenGLDevice; public: - static constexpr u32 MAX_VERTEX_ATTRIBUTES = 6; + static constexpr u32 MAX_VERTEX_ATTRIBUTES = 7; struct VertexArrayCacheKey { @@ -65,14 +65,18 @@ public: struct ProgramCacheKey { - GPUShaderCache::CacheIndexKey vs_key; - GPUShaderCache::CacheIndexKey fs_key; + u64 vs_hash_low, vs_hash_high; + u64 gs_hash_low, gs_hash_high; + u64 fs_hash_low, fs_hash_high; + u32 vs_length; + u32 gs_length; + u32 fs_length; VertexArrayCacheKey va_key; bool operator==(const ProgramCacheKey& rhs) const; bool operator!=(const ProgramCacheKey& rhs) const; }; - static_assert(sizeof(ProgramCacheKey) == 112); // Has no padding + static_assert(sizeof(ProgramCacheKey) == 96); // Has no padding struct ProgramCacheKeyHash { size_t operator()(const ProgramCacheKey& k) const; diff --git a/src/util/postprocessing_shader_fx.cpp b/src/util/postprocessing_shader_fx.cpp index b950718f0..e8eac9f2b 100644 --- a/src/util/postprocessing_shader_fx.cpp +++ b/src/util/postprocessing_shader_fx.cpp @@ -1091,6 +1091,7 @@ bool PostProcessing::ReShadeFXShader::CompilePipeline(GPUTexture::Format format, plconfig.primitive = MapPrimitive(info.topology); plconfig.vertex_shader = vs.get(); plconfig.fragment_shader = fs.get(); + plconfig.geometry_shader = nullptr; if (!plconfig.vertex_shader || !plconfig.fragment_shader) return false; diff --git a/src/util/postprocessing_shader_glsl.cpp b/src/util/postprocessing_shader_glsl.cpp index 084df309b..e713f1551 100644 --- a/src/util/postprocessing_shader_glsl.cpp +++ b/src/util/postprocessing_shader_glsl.cpp @@ -138,6 +138,7 @@ bool PostProcessing::GLSLShader::CompilePipeline(GPUTexture::Format format, u32 plconfig.per_sample_shading = false; plconfig.vertex_shader = vs.get(); plconfig.fragment_shader = fs.get(); + plconfig.geometry_shader = nullptr; if (!(m_pipeline = g_gpu_device->CreatePipeline(plconfig))) return false; diff --git a/src/util/spirv_compiler.cpp b/src/util/spirv_compiler.cpp index 5ee64ff48..198685483 100644 --- a/src/util/spirv_compiler.cpp +++ b/src/util/spirv_compiler.cpp @@ -4,7 +4,7 @@ #include "spirv_compiler.h" #include "gpu_device.h" -#include "core/settings.h"// TODO: Remove me +#include "core/settings.h" // TODO: Remove me #include "common/assert.h" #include "common/file_system.h" @@ -137,6 +137,12 @@ std::optional SPIRVCompiler::CompileFragmentShad return CompileShaderToSPV(EShLangFragment, "ps", source_code, options); } +std::optional SPIRVCompiler::CompileGeometryShader(std::string_view source_code, + u32 options) +{ + return CompileShaderToSPV(EShLangGeometry, "gs", source_code, options); +} + std::optional SPIRVCompiler::CompileComputeShader(std::string_view source_code, u32 options) { @@ -154,6 +160,9 @@ std::optional SPIRVCompiler::CompileShader(GPUSh case GPUShaderStage::Fragment: return CompileShaderToSPV(EShLangFragment, "ps", source_code, options); + case GPUShaderStage::Geometry: + return CompileShaderToSPV(EShLangGeometry, "gs", source_code, options); + case GPUShaderStage::Compute: return CompileShaderToSPV(EShLangCompute, "cs", source_code, options); diff --git a/src/util/spirv_compiler.h b/src/util/spirv_compiler.h index 8361c0862..01e71f2ae 100644 --- a/src/util/spirv_compiler.h +++ b/src/util/spirv_compiler.h @@ -32,6 +32,9 @@ std::optional CompileVertexShader(std::string_view source_code, // Compile a fragment shader to SPIR-V. std::optional CompileFragmentShader(std::string_view source_code, u32 options); +// Compile a geometry shader to SPIR-V. +std::optional CompileGeometryShader(std::string_view source_code, u32 options); + // Compile a compute shader to SPIR-V. std::optional CompileComputeShader(std::string_view source_code, u32 options); diff --git a/src/util/vulkan_device.cpp b/src/util/vulkan_device.cpp index eace049ff..bf1ccc1c0 100644 --- a/src/util/vulkan_device.cpp +++ b/src/util/vulkan_device.cpp @@ -366,6 +366,7 @@ bool VulkanDevice::SelectDeviceFeatures() m_device_features.wideLines = available_features.wideLines; m_device_features.samplerAnisotropy = available_features.samplerAnisotropy; m_device_features.sampleRateShading = available_features.sampleRateShading; + m_device_features.geometryShader = available_features.geometryShader; return true; } @@ -2227,6 +2228,8 @@ bool VulkanDevice::CheckFeatures() if (m_features.texture_buffers_emulated_with_ssbo) Log_WarningPrintf("Emulating texture buffers with SSBOs."); + m_features.geometry_shaders = m_device_features.geometryShader; + m_features.partial_msaa_resolve = true; m_features.shader_cache = true; m_features.pipeline_cache = true; diff --git a/src/util/vulkan_pipeline.cpp b/src/util/vulkan_pipeline.cpp index fed2e5d23..637d0688c 100644 --- a/src/util/vulkan_pipeline.cpp +++ b/src/util/vulkan_pipeline.cpp @@ -44,7 +44,8 @@ std::unique_ptr VulkanDevice::CreateShaderFromBinary(GPUShaderStage s } std::unique_ptr VulkanDevice::CreateShaderFromSource(GPUShaderStage stage, const std::string_view& source, - const char* entry_point, DynamicHeapArray* out_binary) + const char* entry_point, + DynamicHeapArray* out_binary) { if (std::strcmp(entry_point, "main") != 0) { @@ -156,6 +157,9 @@ std::unique_ptr VulkanDevice::CreatePipeline(const GPUPipeline::Gra gpb.SetVertexShader(static_cast(config.vertex_shader)->GetModule()); gpb.SetFragmentShader(static_cast(config.fragment_shader)->GetModule()); + if (config.geometry_shader) + gpb.SetGeometryShader(static_cast(config.geometry_shader)->GetModule()); + if (!config.input_layout.vertex_attributes.empty()) { gpb.AddVertexBuffer(0, config.input_layout.vertex_stride);