From 562aa0dd917b3773f41d6e41aba8840ace8e6991 Mon Sep 17 00:00:00 2001 From: oreyg Date: Fri, 15 May 2026 05:20:52 +0200 Subject: [PATCH] [Vulkan] Only declare the clip-distance or cull-distance array that is written --- src/xenia/gpu/spirv_shader_translator.cc | 23 +++++++++++++------ src/xenia/gpu/vulkan/vulkan_pipeline_cache.cc | 15 ++++++++---- src/xenia/gpu/vulkan/vulkan_pipeline_cache.h | 1 + 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/src/xenia/gpu/spirv_shader_translator.cc b/src/xenia/gpu/spirv_shader_translator.cc index e4e7e36e2..0999febdd 100644 --- a/src/xenia/gpu/spirv_shader_translator.cc +++ b/src/xenia/gpu/spirv_shader_translator.cc @@ -1328,9 +1328,15 @@ void SpirvShaderTranslator::StartVertexOrTessEvalShaderBeforeMain() { // actually enabled (count > 0). uint32_t user_clip_plane_count = shader_modification.vertex.user_clip_plane_count; + uint32_t clip_distance_count = 0; + uint32_t cull_distance_count = 0; + if (shader_modification.vertex.user_clip_plane_cull) { + cull_distance_count = user_clip_plane_count; + } else { + clip_distance_count = user_clip_plane_count; + } output_per_vertex_clip_distance_member_index_ = 0; output_per_vertex_cull_distance_member_index_ = 0; - constexpr uint32_t kMaxUserClipPlanes = 6; if (user_clip_plane_count > 0) { // Create separate uniform buffer for clip planes. spv::Id type_float4_array_6 = builder_->makeArrayType( @@ -1356,16 +1362,18 @@ void SpirvShaderTranslator::StartVertexOrTessEvalShaderBeforeMain() { if (features_.spirv_version >= spv::Spv_1_4) { main_interface_.push_back(uniform_clip_plane_constants_); } - + } + if (clip_distance_count > 0) { output_per_vertex_clip_distance_member_index_ = static_cast(struct_per_vertex_members.size()); struct_per_vertex_members.push_back(builder_->makeArrayType( - type_float_, builder_->makeUintConstant(user_clip_plane_count), 0)); - + type_float_, builder_->makeUintConstant(clip_distance_count), 0)); + } + if (cull_distance_count > 0) { output_per_vertex_cull_distance_member_index_ = static_cast(struct_per_vertex_members.size()); struct_per_vertex_members.push_back(builder_->makeArrayType( - type_float_, builder_->makeUintConstant(user_clip_plane_count), 0)); + type_float_, builder_->makeUintConstant(cull_distance_count), 0)); } spv::Id type_struct_per_vertex = @@ -1377,14 +1385,15 @@ void SpirvShaderTranslator::StartVertexOrTessEvalShaderBeforeMain() { spv::DecorationBuiltIn, static_cast(spv::BuiltIn::Position)); // Decorate clip/cull arrays only if allocated. - if (user_clip_plane_count > 0) { + if (clip_distance_count > 0) { builder_->addMemberName(type_struct_per_vertex, output_per_vertex_clip_distance_member_index_, "gl_ClipDistance"); builder_->addMemberDecoration( type_struct_per_vertex, output_per_vertex_clip_distance_member_index_, spv::DecorationBuiltIn, static_cast(spv::BuiltIn::ClipDistance)); - + } + if (cull_distance_count > 0) { builder_->addMemberName(type_struct_per_vertex, output_per_vertex_cull_distance_member_index_, "gl_CullDistance"); diff --git a/src/xenia/gpu/vulkan/vulkan_pipeline_cache.cc b/src/xenia/gpu/vulkan/vulkan_pipeline_cache.cc index 784d369ad..100729680 100644 --- a/src/xenia/gpu/vulkan/vulkan_pipeline_cache.cc +++ b/src/xenia/gpu/vulkan/vulkan_pipeline_cache.cc @@ -1407,6 +1407,8 @@ bool VulkanPipelineCache::GetGeometryShaderKey( // Single bit to indicate if clip planes are enabled. key.has_user_clip_planes = uint32_t(vertex_shader_modification.vertex.user_clip_plane_count > 0); + key.user_clip_plane_cull = + vertex_shader_modification.vertex.user_clip_plane_cull; key_out = key; return true; } @@ -1453,11 +1455,16 @@ VkShaderModule VulkanPipelineCache::GetGeometryShader(GeometryShaderKey key) { // When enabled, use max size to reduce variants from different counts. constexpr uint32_t kMaxUserClipPlanes = 6; - uint32_t clip_distance_count = + uint32_t user_clip_plane_count = key.has_user_clip_planes ? kMaxUserClipPlanes : 0; - uint32_t cull_distance_count = - (key.has_user_clip_planes ? kMaxUserClipPlanes : 0) + - key.has_vertex_kill_and; + uint32_t clip_distance_count = 0; + uint32_t cull_distance_count = 0; + if (key.user_clip_plane_cull) { + cull_distance_count = user_clip_plane_count; + } else { + clip_distance_count = user_clip_plane_count; + } + cull_distance_count += key.has_vertex_kill_and; SpirvBuilder builder(spv::Spv_1_0, (SpirvShaderTranslator::kSpirvMagicToolId << 16) | 1, diff --git a/src/xenia/gpu/vulkan/vulkan_pipeline_cache.h b/src/xenia/gpu/vulkan/vulkan_pipeline_cache.h index fdab3c061..1e33c5a5e 100644 --- a/src/xenia/gpu/vulkan/vulkan_pipeline_cache.h +++ b/src/xenia/gpu/vulkan/vulkan_pipeline_cache.h @@ -312,6 +312,7 @@ class VulkanPipelineCache { PipelineGeometryShader type : 2; uint32_t interpolator_count : 5; uint32_t has_user_clip_planes : 1; + uint32_t user_clip_plane_cull : 1; uint32_t has_vertex_kill_and : 1; uint32_t has_point_size : 1; uint32_t has_point_coordinates : 1;