[Vulkan] Only declare the clip-distance or cull-distance array that is written

This commit is contained in:
oreyg
2026-05-15 05:20:52 +02:00
committed by Radosław Gliński
parent 02a2591295
commit 562aa0dd91
3 changed files with 28 additions and 11 deletions

View File

@@ -1328,9 +1328,15 @@ void SpirvShaderTranslator::StartVertexOrTessEvalShaderBeforeMain() {
// actually enabled (count > 0). // actually enabled (count > 0).
uint32_t user_clip_plane_count = uint32_t user_clip_plane_count =
shader_modification.vertex.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_clip_distance_member_index_ = 0;
output_per_vertex_cull_distance_member_index_ = 0; output_per_vertex_cull_distance_member_index_ = 0;
constexpr uint32_t kMaxUserClipPlanes = 6;
if (user_clip_plane_count > 0) { if (user_clip_plane_count > 0) {
// Create separate uniform buffer for clip planes. // Create separate uniform buffer for clip planes.
spv::Id type_float4_array_6 = builder_->makeArrayType( spv::Id type_float4_array_6 = builder_->makeArrayType(
@@ -1356,16 +1362,18 @@ void SpirvShaderTranslator::StartVertexOrTessEvalShaderBeforeMain() {
if (features_.spirv_version >= spv::Spv_1_4) { if (features_.spirv_version >= spv::Spv_1_4) {
main_interface_.push_back(uniform_clip_plane_constants_); main_interface_.push_back(uniform_clip_plane_constants_);
} }
}
if (clip_distance_count > 0) {
output_per_vertex_clip_distance_member_index_ = output_per_vertex_clip_distance_member_index_ =
static_cast<unsigned int>(struct_per_vertex_members.size()); static_cast<unsigned int>(struct_per_vertex_members.size());
struct_per_vertex_members.push_back(builder_->makeArrayType( 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_ = output_per_vertex_cull_distance_member_index_ =
static_cast<unsigned int>(struct_per_vertex_members.size()); static_cast<unsigned int>(struct_per_vertex_members.size());
struct_per_vertex_members.push_back(builder_->makeArrayType( 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 = spv::Id type_struct_per_vertex =
@@ -1377,14 +1385,15 @@ void SpirvShaderTranslator::StartVertexOrTessEvalShaderBeforeMain() {
spv::DecorationBuiltIn, static_cast<int>(spv::BuiltIn::Position)); spv::DecorationBuiltIn, static_cast<int>(spv::BuiltIn::Position));
// Decorate clip/cull arrays only if allocated. // Decorate clip/cull arrays only if allocated.
if (user_clip_plane_count > 0) { if (clip_distance_count > 0) {
builder_->addMemberName(type_struct_per_vertex, builder_->addMemberName(type_struct_per_vertex,
output_per_vertex_clip_distance_member_index_, output_per_vertex_clip_distance_member_index_,
"gl_ClipDistance"); "gl_ClipDistance");
builder_->addMemberDecoration( builder_->addMemberDecoration(
type_struct_per_vertex, output_per_vertex_clip_distance_member_index_, type_struct_per_vertex, output_per_vertex_clip_distance_member_index_,
spv::DecorationBuiltIn, static_cast<int>(spv::BuiltIn::ClipDistance)); spv::DecorationBuiltIn, static_cast<int>(spv::BuiltIn::ClipDistance));
}
if (cull_distance_count > 0) {
builder_->addMemberName(type_struct_per_vertex, builder_->addMemberName(type_struct_per_vertex,
output_per_vertex_cull_distance_member_index_, output_per_vertex_cull_distance_member_index_,
"gl_CullDistance"); "gl_CullDistance");

View File

@@ -1407,6 +1407,8 @@ bool VulkanPipelineCache::GetGeometryShaderKey(
// Single bit to indicate if clip planes are enabled. // Single bit to indicate if clip planes are enabled.
key.has_user_clip_planes = key.has_user_clip_planes =
uint32_t(vertex_shader_modification.vertex.user_clip_plane_count > 0); 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; key_out = key;
return true; return true;
} }
@@ -1453,11 +1455,16 @@ VkShaderModule VulkanPipelineCache::GetGeometryShader(GeometryShaderKey key) {
// When enabled, use max size to reduce variants from different counts. // When enabled, use max size to reduce variants from different counts.
constexpr uint32_t kMaxUserClipPlanes = 6; constexpr uint32_t kMaxUserClipPlanes = 6;
uint32_t clip_distance_count = uint32_t user_clip_plane_count =
key.has_user_clip_planes ? kMaxUserClipPlanes : 0; key.has_user_clip_planes ? kMaxUserClipPlanes : 0;
uint32_t cull_distance_count = uint32_t clip_distance_count = 0;
(key.has_user_clip_planes ? kMaxUserClipPlanes : 0) + uint32_t cull_distance_count = 0;
key.has_vertex_kill_and; 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, SpirvBuilder builder(spv::Spv_1_0,
(SpirvShaderTranslator::kSpirvMagicToolId << 16) | 1, (SpirvShaderTranslator::kSpirvMagicToolId << 16) | 1,

View File

@@ -312,6 +312,7 @@ class VulkanPipelineCache {
PipelineGeometryShader type : 2; PipelineGeometryShader type : 2;
uint32_t interpolator_count : 5; uint32_t interpolator_count : 5;
uint32_t has_user_clip_planes : 1; uint32_t has_user_clip_planes : 1;
uint32_t user_clip_plane_cull : 1;
uint32_t has_vertex_kill_and : 1; uint32_t has_vertex_kill_and : 1;
uint32_t has_point_size : 1; uint32_t has_point_size : 1;
uint32_t has_point_coordinates : 1; uint32_t has_point_coordinates : 1;