From 7101741637268dea66428306ac06fbf9905f8499 Mon Sep 17 00:00:00 2001 From: nmzik Date: Thu, 1 Oct 2026 23:48:34 +0400 Subject: [PATCH] Cache SPIR-V arithmetic types lazily in existing emitters --- .../backend/spirv/spirvEmitterInternal.h | 14 ++++ .../backend/spirv/spirvEmitterModule.cpp | 78 +++++++++++++++---- 2 files changed, 76 insertions(+), 16 deletions(-) diff --git a/src/graphics/shader/recompiler/backend/spirv/spirvEmitterInternal.h b/src/graphics/shader/recompiler/backend/spirv/spirvEmitterInternal.h index 7c5fb5941..12a6d6ee2 100644 --- a/src/graphics/shader/recompiler/backend/spirv/spirvEmitterInternal.h +++ b/src/graphics/shader/recompiler/backend/spirv/spirvEmitterInternal.h @@ -84,6 +84,20 @@ struct EmitterState { Builder builder; const IR::Program& program; ShaderStageInputInfo input_info; + uint32_t void_type = 0; + uint32_t bool_type = 0; + uint32_t u32_type = 0; + uint32_t native_u64_type = 0; + uint32_t i32_type = 0; + uint32_t f32_type = 0; + uint32_t f64_type = 0; + uint32_t u32_pair_type = 0; + uint32_t i32_pair_type = 0; + uint32_t function_type = 0; + std::array bool_vector_types {}; + std::array u32_vector_types {}; + std::array i32_vector_types {}; + std::array f32_vector_types {}; std::array tess_variables {}; uint32_t tess_inner_variable = 0; uint32_t tess_patch_base = 0; diff --git a/src/graphics/shader/recompiler/backend/spirv/spirvEmitterModule.cpp b/src/graphics/shader/recompiler/backend/spirv/spirvEmitterModule.cpp index e693a999f..771eccddc 100644 --- a/src/graphics/shader/recompiler/backend/spirv/spirvEmitterModule.cpp +++ b/src/graphics/shader/recompiler/backend/spirv/spirvEmitterModule.cpp @@ -6,19 +6,32 @@ namespace Libs::Graphics::ShaderRecompiler::Spirv::Emitter { uint32_t TypeVoid(EmitterState& state) { - return state.builder.Type(spv::OpTypeVoid); + if (state.void_type == 0) { + state.void_type = state.builder.Type(spv::OpTypeVoid); + } + return state.void_type; } uint32_t TypeBool(EmitterState& state) { - return state.builder.Type(spv::OpTypeBool); + if (state.bool_type == 0) { + state.bool_type = state.builder.Type(spv::OpTypeBool); + } + return state.bool_type; } uint32_t TypeBoolVector(EmitterState& state, uint32_t components) { - return state.builder.Type(spv::OpTypeVector, TypeBool(state), components); + auto& type = state.bool_vector_types[components - 2u]; + if (type == 0) { + type = state.builder.Type(spv::OpTypeVector, TypeBool(state), components); + } + return type; } uint32_t TypeU32(EmitterState& state) { - return state.builder.Type(spv::OpTypeInt, 32, 0); + if (state.u32_type == 0) { + state.u32_type = state.builder.Type(spv::OpTypeInt, 32, 0); + } + return state.u32_type; } uint32_t TypeU64(EmitterState& state) { @@ -26,33 +39,55 @@ uint32_t TypeU64(EmitterState& state) { } uint32_t TypeScalarU64(EmitterState& state) { - return state.builder.Type(spv::OpTypeInt, 64, 0); + if (state.native_u64_type == 0) { + state.native_u64_type = state.builder.Type(spv::OpTypeInt, 64, 0); + } + return state.native_u64_type; } uint32_t TypeU32Pair(EmitterState& state) { - const auto element = TypeU32(state); - return state.builder.Type(spv::OpTypeStruct, element, element); + if (state.u32_pair_type == 0) { + const auto element = TypeU32(state); + state.u32_pair_type = state.builder.Type(spv::OpTypeStruct, element, element); + } + return state.u32_pair_type; } uint32_t TypeI32(EmitterState& state) { - return state.builder.Type(spv::OpTypeInt, 32, 1); + if (state.i32_type == 0) { + state.i32_type = state.builder.Type(spv::OpTypeInt, 32, 1); + } + return state.i32_type; } uint32_t TypeI32Pair(EmitterState& state) { - const auto element = TypeI32(state); - return state.builder.Type(spv::OpTypeStruct, element, element); + if (state.i32_pair_type == 0) { + const auto element = TypeI32(state); + state.i32_pair_type = state.builder.Type(spv::OpTypeStruct, element, element); + } + return state.i32_pair_type; } uint32_t TypeF32(EmitterState& state) { - return state.builder.Type(spv::OpTypeFloat, 32); + if (state.f32_type == 0) { + state.f32_type = state.builder.Type(spv::OpTypeFloat, 32); + } + return state.f32_type; } uint32_t TypeF64(EmitterState& state) { - return state.builder.Type(spv::OpTypeFloat, 64); + if (state.f64_type == 0) { + state.f64_type = state.builder.Type(spv::OpTypeFloat, 64); + } + return state.f64_type; } uint32_t TypeU32Vector(EmitterState& state, uint32_t components) { - return state.builder.Type(spv::OpTypeVector, TypeU32(state), components); + auto& type = state.u32_vector_types[components - 2u]; + if (type == 0) { + type = state.builder.Type(spv::OpTypeVector, TypeU32(state), components); + } + return type; } uint32_t TypeU32Composite(EmitterState& state, uint32_t components) { @@ -61,11 +96,19 @@ uint32_t TypeU32Composite(EmitterState& state, uint32_t components) { } uint32_t TypeI32Vector(EmitterState& state, uint32_t components) { - return state.builder.Type(spv::OpTypeVector, TypeI32(state), components); + auto& type = state.i32_vector_types[components - 2u]; + if (type == 0) { + type = state.builder.Type(spv::OpTypeVector, TypeI32(state), components); + } + return type; } uint32_t TypeF32Vector(EmitterState& state, uint32_t components) { - return state.builder.Type(spv::OpTypeVector, TypeF32(state), components); + auto& type = state.f32_vector_types[components - 2u]; + if (type == 0) { + type = state.builder.Type(spv::OpTypeVector, TypeF32(state), components); + } + return type; } uint32_t TypePointer(EmitterState& state, spv::StorageClass storage_class, uint32_t pointee) { @@ -73,7 +116,10 @@ uint32_t TypePointer(EmitterState& state, spv::StorageClass storage_class, uint3 } uint32_t TypeFunction(EmitterState& state) { - return state.builder.Type(spv::OpTypeFunction, TypeVoid(state)); + if (state.function_type == 0) { + state.function_type = state.builder.Type(spv::OpTypeFunction, TypeVoid(state)); + } + return state.function_type; } uint32_t StorageRuntimeArrayType(EmitterState& state) {