From fc1a3b63101f0b88b8cb0536e68942e1ae0fd6f5 Mon Sep 17 00:00:00 2001 From: JPikachu Date: Mon, 21 Apr 2025 03:04:31 +0100 Subject: [PATCH 1/3] shader compiler: Ensure all clip distances are initialized when used Thank you to Ryujinx (riperiperi specifically) for the pointer towards clip distances Huge thanks to crueter for finding where the code works and Camille for giving pointers along the way. --- .../spirv/emit_spirv_context_get_set.cpp | 17 ++++++++ .../backend/spirv/emit_spirv_special.cpp | 2 +- .../backend/spirv/spirv_emit_context.h | 2 + .../renderer_vulkan/vk_graphics_pipeline.cpp | 43 +++++++++++-------- 4 files changed, 46 insertions(+), 18 deletions(-) diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp index be65db7657..d52ec296ed 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp @@ -53,6 +53,15 @@ std::optional OutputAttrPointer(EmitContext& ctx, IR::Attribute attr) { return OutputAccessChain(ctx, ctx.output_f32, info.id, index_id); } } + + for (u32 i = 0; i < ctx.profile.max_user_clip_distances; ++i) { + if (!clip_distance_written.test(i)) { + const Id idx = ctx.Const(i); + const Id element = OutputAccessChain(ctx, ctx.output_f32, ctx.clip_distances, idx); + ctx.OpStore(element, ctx.Const(0.0f)); + } + } + switch (attr) { case IR::Attribute::PointSize: return ctx.output_point_size; @@ -421,6 +430,14 @@ void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, Id value, [[maybe_un if (Sirit::ValidId(output->type)) { value = ctx.OpBitcast(output->type, value); } + + static constexpr IR::Attribute cd0 = IR::Attribute::ClipDistance0; + static constexpr IR::Attribute cd7 = IR::Attribute::ClipDistance7; + + if (attr >= cd0 && attr <= cd7) { + const u32 idx = (u32) attr - (u32) cd0; + clip_distance_written.set(idx); + } ctx.OpStore(output->pointer, value); } diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp index f60da758e6..7140ed6f4a 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp @@ -108,7 +108,7 @@ void EmitPrologue(EmitContext& ctx) { ctx.OpStore(element_info.id, value); element += num; } - } + } } if (ctx.stage == Stage::VertexB || ctx.stage == Stage::Geometry) { SetFixedPipelinePointSize(ctx); diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.h b/src/shader_recompiler/backend/spirv/spirv_emit_context.h index 40adcb6b67..5129293b41 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.h +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.h @@ -15,6 +15,8 @@ namespace Shader::Backend::SPIRV { +std::bitset<8> clip_distance_written; + using Sirit::Id; class VectorTypes { diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index 9f306a72b2..130dee3222 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp @@ -260,7 +260,7 @@ GraphicsPipeline::GraphicsPipeline( num_textures += Shader::NumDescriptors(info->texture_descriptors); } - // Track compilation start time for performance metrics + // Track compilation start time for performance metrics const auto start_time = std::chrono::high_resolution_clock::now(); auto func{[this, shader_notify, &render_pass_cache, &descriptor_pool, pipeline_statistics, start_time] { @@ -284,12 +284,12 @@ GraphicsPipeline::GraphicsPipeline( Validate(); MakePipeline(render_pass); - // Performance measurement + // Performance measurement const auto end_time = std::chrono::high_resolution_clock::now(); const auto compilation_time = std::chrono::duration_cast( - end_time - start_time).count(); + end_time - start_time).count(); - // Log shader compilation time for slow shaders to help diagnose performance issues + // Log shader compilation time for slow shaders to help diagnose performance issues if (compilation_time > 100) { // Only log very slow compilations LOG_DEBUG(Render_Vulkan, "Compiled graphics pipeline in {}ms", compilation_time); } @@ -375,7 +375,7 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { views[view_index++] = { .index = handle.first, .blacklist = blacklist, - .id = {}, + .id = {} }; } }}; @@ -650,14 +650,14 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) { .flags = 0, .topology = input_assembly_topology, .primitiveRestartEnable = - dynamic.primitive_restart_enable != 0 && - ((input_assembly_topology != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST && - device.IsTopologyListPrimitiveRestartSupported()) || - SupportsPrimitiveRestart(input_assembly_topology) || - (input_assembly_topology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST && - device.IsPatchListPrimitiveRestartSupported())) - ? VK_TRUE - : VK_FALSE, + dynamic.primitive_restart_enable != 0 && + ((input_assembly_topology != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST && + device.IsTopologyListPrimitiveRestartSupported()) || + SupportsPrimitiveRestart(input_assembly_topology) || + (input_assembly_topology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST && + device.IsPatchListPrimitiveRestartSupported())) + ? VK_TRUE + : VK_FALSE, }; const VkPipelineTessellationStateCreateInfo tessellation_ci{ .sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, @@ -700,11 +700,11 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) { .pNext = nullptr, .flags = 0, .depthClampEnable = - static_cast(dynamic.depth_clamp_disabled == 0 ? VK_TRUE : VK_FALSE), + static_cast(dynamic.depth_clamp_disabled == 0 ? VK_TRUE : VK_FALSE), .rasterizerDiscardEnable = - static_cast(dynamic.rasterize_enable == 0 ? VK_TRUE : VK_FALSE), + static_cast(dynamic.rasterize_enable == 0 ? VK_TRUE : VK_FALSE), .polygonMode = - MaxwellToVK::PolygonMode(FixedPipelineState::UnpackPolygonMode(key.state.polygon_mode)), + MaxwellToVK::PolygonMode(FixedPipelineState::UnpackPolygonMode(key.state.polygon_mode)), .cullMode = static_cast( dynamic.cull_enable ? MaxwellToVK::CullFace(dynamic.CullFace()) : VK_CULL_MODE_NONE), .frontFace = MaxwellToVK::FrontFace(dynamic.FrontFace()), @@ -740,6 +740,12 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) { ? VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT : VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT, }; + VkPipelineRasterizationDepthClipStateCreateInfoEXT depth_clip{ + .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_DEPTH_CLIP_STATE_CREATE_INFO_EXT, + .pNext = nullptr, + .flags = 0, + .depthClipEnable = VK_TRUE, + }; if (IsLine(input_assembly_topology) && device.IsExtLineRasterizationSupported()) { line_state.pNext = std::exchange(rasterization_ci.pNext, &line_state); } @@ -749,6 +755,9 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) { if (device.IsExtProvokingVertexSupported()) { provoking_vertex.pNext = std::exchange(rasterization_ci.pNext, &provoking_vertex); } + if (device.IsExtDepthClipControlSupported()) { + depth_clip.pNext = std::exchange(rasterization_ci.pNext, &depth_clip); + } const VkPipelineMultisampleStateCreateInfo multisample_ci{ .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, @@ -814,7 +823,7 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) { .logicOp = static_cast(dynamic.logic_op.Value()), .attachmentCount = static_cast(cb_attachments.size()), .pAttachments = cb_attachments.data(), - .blendConstants = {}, + .blendConstants = {} }; static_vector dynamic_states{ VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR, From c64f1994c7945bb1ff506430887d088b2fdf0cec Mon Sep 17 00:00:00 2001 From: JPikachu Date: Mon, 21 Apr 2025 03:50:28 +0100 Subject: [PATCH 2/3] Fix complination issues by making clip_distance_written static --- src/shader_recompiler/backend/spirv/spirv_emit_context.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.h b/src/shader_recompiler/backend/spirv/spirv_emit_context.h index 5129293b41..66cdb1d3db 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.h +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.h @@ -15,7 +15,7 @@ namespace Shader::Backend::SPIRV { -std::bitset<8> clip_distance_written; +static std::bitset<8> clip_distance_written; using Sirit::Id; From 918d6d3514076e90ca6676e6512216098b67e660 Mon Sep 17 00:00:00 2001 From: swurl Date: Mon, 21 Apr 2025 15:32:23 -0400 Subject: [PATCH 3/3] proper placement of clip distance init Signed-off-by: swurl --- CMakeLists.txt | 4 ++++ .../backend/spirv/emit_spirv_context_get_set.cpp | 8 -------- .../backend/spirv/emit_spirv_special.cpp | 12 +++++++++++- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b88ab64e53..a68aa27e2b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -285,6 +285,10 @@ if (ARCHITECTURE_arm64 AND (ANDROID OR ${CMAKE_SYSTEM_NAME} STREQUAL "Linux")) add_definitions(-DHAS_NCE=1) endif() +if (YUZU_LOG_BY_LINE) + add_definitions(-DYUZU_LOG_BY_LINE=1) +endif() + # Configure C++ standard # =========================== diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp index d52ec296ed..5dab8b62ea 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp @@ -54,14 +54,6 @@ std::optional OutputAttrPointer(EmitContext& ctx, IR::Attribute attr) { } } - for (u32 i = 0; i < ctx.profile.max_user_clip_distances; ++i) { - if (!clip_distance_written.test(i)) { - const Id idx = ctx.Const(i); - const Id element = OutputAccessChain(ctx, ctx.output_f32, ctx.clip_distances, idx); - ctx.OpStore(element, ctx.Const(0.0f)); - } - } - switch (attr) { case IR::Attribute::PointSize: return ctx.output_point_size; diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp index 7140ed6f4a..fe5e70a63b 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp @@ -108,7 +108,17 @@ void EmitPrologue(EmitContext& ctx) { ctx.OpStore(element_info.id, value); element += num; } - } + } + + if (Sirit::ValidId(ctx.clip_distances)) { + for (u32 i = 0; i < ctx.profile.max_user_clip_distances; ++i) { + if (!clip_distance_written.test(i)) { + const Id idx = ctx.Const(i); + const Id element = ctx.OpAccessChain(ctx.output_f32, ctx.clip_distances, idx); + ctx.OpStore(element, ctx.Const(0.0f)); + } + } + } } if (ctx.stage == Stage::VertexB || ctx.stage == Stage::Geometry) { SetFixedPipelinePointSize(ctx);