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,