From 66ca225c760195892db9dcc81122af53025604a8 Mon Sep 17 00:00:00 2001 From: nmzik Date: Mon, 31 Aug 2026 10:26:08 +0400 Subject: [PATCH] shader: require explicit recompiler resource data --- .../shader/recompiler/ShaderRecompiler.cpp | 48 ++++-------- .../shader/recompiler/ShaderRecompiler.h | 5 +- src/graphics/shader/shader.cpp | 4 +- tests/ShaderRecompilerComputeTests.cpp | 13 ++-- tests/shaderCfgTests.cpp | 76 ++++++++----------- 5 files changed, 52 insertions(+), 94 deletions(-) diff --git a/src/graphics/shader/recompiler/ShaderRecompiler.cpp b/src/graphics/shader/recompiler/ShaderRecompiler.cpp index fc860b368..44c306002 100644 --- a/src/graphics/shader/recompiler/ShaderRecompiler.cpp +++ b/src/graphics/shader/recompiler/ShaderRecompiler.cpp @@ -30,14 +30,6 @@ namespace Libs::Graphics::ShaderRecompiler { namespace { -bool ReadZeroMemory(void*, uint64_t, uint32_t* value) { - if (value == nullptr) { - return false; - } - *value = 0; - return true; -} - const char* GetDumpLabel(const CompileOptions& options) { return options.dump_label != nullptr ? options.dump_label : "ShaderRecompiler"; } @@ -575,7 +567,8 @@ CompileResult Recompile(std::span code, const CompileOptions& op EmbeddedFetchData embedded_fetch; if (options.stage == ShaderType::Vertex && vertex->fetch_embedded) { embedded_fetch = DetectEmbeddedVertexFetch(decoded, vertex, options.user_data_base, - options.user_data_count, options.wave_size); + static_cast(options.user_data.size()), + options.wave_size); if (!embedded_fetch.loads.empty()) { LOGF("%s embedded vertex fetch plan: detected=%" PRIu64 "\n", GetDumpLabel(options), static_cast(embedded_fetch.loads.size())); @@ -586,7 +579,7 @@ CompileResult Recompile(std::span code, const CompileOptions& op .wave_size = options.wave_size, .shader_hash = options.shader_hash, .user_data_base = options.user_data_base, - .user_data_count = options.user_data_count, + .user_data_count = static_cast(options.user_data.size()), .scratch_dwords = options.scratch_dwords, .dispatcher_fallback = dispatcher_fallback, .cfg_failure_kind = cfg.failure_kind, @@ -634,32 +627,17 @@ CompileResult Recompile(std::span code, const CompileOptions& op ir.info.vertex_offset_sgpr = embedded_fetch.vertex_offset_sgpr; } + const IR::SrtRuntime runtime { + .user_data = options.user_data, + .shader_base = reinterpret_cast(code.data()), + .read_memory = options.read_memory, + .userdata = options.read_memory_data, + .read_specialization_memory = options.read_specialization_memory, + }; IR::ResourceSnapshot resources; - if (options.resource_snapshot != nullptr) { - resources = *options.resource_snapshot; - } else { - IR::SrtRuntime runtime; - std::array zero_user_data {}; - if (options.user_data == nullptr) { - for (uint32_t i = 2; i < zero_user_data.size(); i += 4) { - zero_user_data[i] = UINT32_MAX; - } - } - const auto* user_data = - options.user_data != nullptr ? options.user_data : zero_user_data.data(); - runtime.user_data = std::span(user_data, options.user_data_count); - runtime.shader_base = options.shader_base != 0 ? options.shader_base - : reinterpret_cast(code.data()); - runtime.read_memory = options.read_memory; - runtime.read_specialization_memory = options.read_specialization_memory; - if (runtime.read_memory == nullptr && options.user_data == nullptr) { - runtime.read_memory = ReadZeroMemory; - } - runtime.userdata = options.read_memory_data; - if (!IR::MaterializeResources(ir, runtime, resources)) { - EXIT("shader resource materialization failed: stage=%s hash=0x%016" PRIx64 "\n", - StageName(options.stage), options.shader_hash); - } + if (!IR::MaterializeResources(ir, runtime, resources)) { + EXIT("shader resource materialization failed: stage=%s hash=0x%016" PRIx64 "\n", + StageName(options.stage), options.shader_hash); } IR::SpecializeResources(ir, resources); diff --git a/src/graphics/shader/recompiler/ShaderRecompiler.h b/src/graphics/shader/recompiler/ShaderRecompiler.h index d4427d84c..8846f3e64 100644 --- a/src/graphics/shader/recompiler/ShaderRecompiler.h +++ b/src/graphics/shader/recompiler/ShaderRecompiler.h @@ -15,19 +15,16 @@ struct CompileOptions { ShaderType stage = ShaderType::Compute; uint32_t wave_size = 64; uint32_t user_data_base = 0; - uint32_t user_data_count = 64; uint32_t scratch_dwords = 0; uint64_t shader_hash = 0; - uint64_t shader_base = 0; uint32_t push_constant_offset = 0; bool dump_ir = true; bool early_dump = false; const char* dump_label = nullptr; - const uint32_t* user_data = nullptr; + std::span user_data; IR::SrtMemoryReader read_memory = nullptr; IR::SrtMemoryReader read_specialization_memory = nullptr; void* read_memory_data = nullptr; - const IR::ResourceSnapshot* resource_snapshot = nullptr; ShaderStageInputInfo input_info; }; diff --git a/src/graphics/shader/shader.cpp b/src/graphics/shader/shader.cpp index 84a94ed44..2648cabe4 100644 --- a/src/graphics/shader/shader.cpp +++ b/src/graphics/shader/shader.cpp @@ -1234,9 +1234,7 @@ static ShaderRecompiler::CompileOptions MakeCompileOptions(const ShaderParams& p ShaderRecompiler::CompileOptions options; options.stage = stage; options.shader_hash = params.hash; - options.shader_base = params.Base(); - options.user_data_count = static_cast(params.user_data.size()); - options.user_data = params.user_data.data(); + options.user_data = params.user_data; options.read_specialization_memory = ReadShaderGuestMemory; options.dump_ir = ShaderRecompilerTextDumpEnabled(); options.early_dump = options.dump_ir; diff --git a/tests/ShaderRecompilerComputeTests.cpp b/tests/ShaderRecompilerComputeTests.cpp index e5247a53a..00db9091c 100644 --- a/tests/ShaderRecompilerComputeTests.cpp +++ b/tests/ShaderRecompilerComputeTests.cpp @@ -1209,7 +1209,7 @@ CompiledShader CompileCase(const TestCase &test) { options.stage = ShaderType::Compute; options.dump_ir = true; options.input_info.compute = &test.compute_info; - options.user_data = user_data.data(); + options.user_data = user_data; options.read_memory = ReadTestMemory; options.read_memory_data = const_cast *>(&test.initial); options.scratch_dwords = test.compute_info.scratch_size_dwords; @@ -1349,7 +1349,7 @@ CompiledShader CompileFragmentCase(const GraphicsCase &test) { options.stage = ShaderType::Pixel; options.dump_ir = false; options.input_info.pixel = &pixel_info; - options.user_data = user_data.data(); + options.user_data = user_data; auto result = ShaderRecompiler::Recompile(test.fragment_code, options); Require(test.name, "SPIR-V emit", !result.spirv.empty(), @@ -21452,8 +21452,7 @@ void CheckPs5GameExampleImageClearRuntimeShape() { options.stage = ShaderType::Compute; options.wave_size = 64; options.user_data_base = 0; - options.user_data_count = static_cast(user_data.size()); - options.user_data = user_data.data(); + options.user_data = user_data; options.input_info.compute = &compute; options.dump_ir = false; auto result = ShaderRecompiler::Recompile(code, options); @@ -21549,8 +21548,7 @@ void CheckEmbeddedFetchVertexOffset() { ShaderRecompiler::CompileOptions options; options.stage = ShaderType::Vertex; options.user_data_base = 8; - options.user_data_count = static_cast(user_data.size()); - options.user_data = user_data.data(); + options.user_data = user_data; options.input_info.vertex = &vertex; auto result = ShaderRecompiler::Recompile(code, options); @@ -24250,8 +24248,7 @@ void CheckEmbeddedFetchLaneSpill() { ShaderRecompiler::CompileOptions options; options.stage = ShaderType::Vertex; options.user_data_base = 8; - options.user_data_count = static_cast(user_data.size()); - options.user_data = user_data.data(); + options.user_data = user_data; options.input_info.vertex = &vertex; auto result = ShaderRecompiler::Recompile(code, options); diff --git a/tests/shaderCfgTests.cpp b/tests/shaderCfgTests.cpp index 71485c636..324579969 100644 --- a/tests/shaderCfgTests.cpp +++ b/tests/shaderCfgTests.cpp @@ -84,9 +84,11 @@ ShaderRecompiler::CompileOptions MakeCompileOptions(ShaderType stage) { static const ShaderVertexInputInfo vertex{}; static const ShaderPixelInputInfo pixel{}; static const ShaderComputeInputInfo compute{}; + static const std::array user_data{}; ShaderRecompiler::CompileOptions options; options.stage = stage; + options.user_data = user_data; switch (stage) { case ShaderType::Vertex: options.input_info.vertex = &vertex; @@ -115,9 +117,7 @@ void CompilePixelRuntime(const ShaderParams ¶ms, ShaderPixelInputInfo &input_info) { auto options = MakeCompileOptions(ShaderType::Pixel); options.shader_hash = params.hash; - options.shader_base = params.Base(); - options.user_data = params.user_data.data(); - options.user_data_count = static_cast(params.user_data.size()); + options.user_data = params.user_data; options.scratch_dwords = input_info.scratch_size_dwords; options.push_constant_offset = input_info.push_constant_offset; options.read_specialization_memory = ReadHostTestMemory; @@ -3696,7 +3696,6 @@ void TestNewShaderRecompilerScalarB64LaneTranslation() { const uint32_t user_data[] = {0x01234567u, 0x89abcdefu}; auto options = MakeCompileOptions(ShaderType::Vertex); options.user_data = user_data; - options.user_data_count = static_cast(std::size(user_data)); options.dump_ir = true; auto result = ShaderRecompiler::Recompile(shader, options); @@ -4369,7 +4368,7 @@ void TestNewShaderRecompilerMemoryFamilyTranslation() { auto user_data = ImageTestUserData(); auto options = MakeCompileOptions(ShaderType::Compute); options.dump_ir = true; - options.user_data = user_data.data(); + options.user_data = user_data; options.read_memory = ReadZeroTestMemory; auto result = ShaderRecompiler::Recompile(shader, options); @@ -4463,8 +4462,7 @@ void TestNewShaderRecompilerScalarMemoryBindingDomains() { raw_user_data[8] = 0x1003u; auto raw_options = MakeCompileOptions(ShaderType::Pixel); - raw_options.user_data = raw_user_data.data(); - raw_options.user_data_count = static_cast(raw_user_data.size()); + raw_options.user_data = raw_user_data; auto raw = ShaderRecompiler::Recompile(raw_shader, raw_options); const auto *address_binding = ShaderRecompiler::IR::FindBinding( @@ -4508,9 +4506,7 @@ void TestNewShaderRecompilerScalarMemoryBindingDomains() { buffer_user_data[10] = 4u; auto buffer_options = MakeCompileOptions(ShaderType::Pixel); - buffer_options.user_data = buffer_user_data.data(); - buffer_options.user_data_count = - static_cast(buffer_user_data.size()); + buffer_options.user_data = buffer_user_data; auto buffer = ShaderRecompiler::Recompile(buffer_shader, buffer_options); const auto *buffer_binding = ShaderRecompiler::IR::FindBinding( @@ -4548,7 +4544,7 @@ void TestNewShaderRecompilerImageQueryTranslation() { auto user_data = ImageTestUserData(); auto options = MakeCompileOptions(ShaderType::Compute); options.dump_ir = true; - options.user_data = user_data.data(); + options.user_data = user_data; auto result = ShaderRecompiler::Recompile(shader, options); Check(Common::ContainsStr(result.decoded_dump, "image_get_lod"), @@ -4592,7 +4588,7 @@ void TestNewShaderRecompilerCubeSampleCoordinates() { auto user_data = ImageTestUserData(Prospero::ImageType::kCube); auto options = MakeCompileOptions(ShaderType::Compute); - options.user_data = user_data.data(); + options.user_data = user_data; auto result = ShaderRecompiler::Recompile(shader, options); Check(result.program.info.images.size() == 1 && @@ -4638,7 +4634,7 @@ void TestNewShaderRecompilerImageSampleVariants() { auto user_data = ImageTestUserData(); auto options = MakeCompileOptions(ShaderType::Compute); options.dump_ir = true; - options.user_data = user_data.data(); + options.user_data = user_data; auto result = ShaderRecompiler::Recompile(shader, options); Check(Common::ContainsStr(result.decoded_dump, "image_sample_l"), @@ -4726,7 +4722,7 @@ void TestNewShaderRecompilerImageSampleA16SamplerCoords() { auto user_data = ImageTestUserData(Prospero::ImageType::kColor3D); auto options = MakeCompileOptions(ShaderType::Compute); options.dump_ir = true; - options.user_data = user_data.data(); + options.user_data = user_data; auto result = ShaderRecompiler::Recompile(shader, options); Check(Common::ContainsStr(result.decoded_dump, @@ -4768,7 +4764,7 @@ void TestNewShaderRecompilerImageSampleOpcodeAliases() { auto user_data = ImageTestUserData(); auto options = MakeCompileOptions(ShaderType::Compute); options.dump_ir = true; - options.user_data = user_data.data(); + options.user_data = user_data; auto result = ShaderRecompiler::Recompile(shader, options); Check(Common::ContainsStr(result.decoded_dump, "image_sample_a"), @@ -4804,7 +4800,7 @@ void TestNewShaderRecompilerImageSampleA16ExceptionComponents() { auto user_data = ImageTestUserData(); auto options = MakeCompileOptions(ShaderType::Compute); options.dump_ir = true; - options.user_data = user_data.data(); + options.user_data = user_data; auto result = ShaderRecompiler::Recompile(shader, options); CheckSpirvBinaryValidates(result.spirv); @@ -4850,7 +4846,7 @@ void TestNewShaderRecompilerImageLoadA16UintCoords() { auto user_data = ImageTestUserData(); auto options = MakeCompileOptions(ShaderType::Compute); options.dump_ir = true; - options.user_data = user_data.data(); + options.user_data = user_data; auto result = ShaderRecompiler::Recompile(shader, options); Check(Common::ContainsStr(result.decoded_dump, "image_load"), @@ -4894,7 +4890,7 @@ void TestNewShaderRecompilerPixelImageSampleLodSelection() { auto options = MakeCompileOptions(ShaderType::Pixel); options.input_info.pixel = &ps_info; options.dump_ir = true; - options.user_data = user_data.data(); + options.user_data = user_data; auto result = ShaderRecompiler::Recompile(shader, options); CheckSpirvBinaryValidates(result.spirv); @@ -5005,7 +5001,7 @@ void TestNewShaderRecompilerImageViewDimensions() { auto options = MakeCompileOptions(ShaderType::Pixel); options.input_info.pixel = &ps_info; options.dump_ir = true; - options.user_data = user_data.data(); + options.user_data = user_data; auto result = ShaderRecompiler::Recompile(shader, options); Check(Common::ContainsStr(result.decoded_dump, "image_dim=2d_array"), @@ -5082,7 +5078,7 @@ void TestNewShaderRecompilerStorageImage1DDescriptorVariants() { auto options = MakeCompileOptions(ShaderType::Compute); options.dump_ir = true; - options.user_data = user_data.data(); + options.user_data = user_data; auto result = ShaderRecompiler::Recompile(shader, options); Check(Common::ContainsStr(result.ir_dump, "image_dim=1d"), @@ -5113,7 +5109,7 @@ void TestNewShaderRecompilerNullImageUsesCanonical2DView() { std::array user_data{}; auto options = MakeCompileOptions(ShaderType::Compute); - options.user_data = user_data.data(); + options.user_data = user_data; auto result = ShaderRecompiler::Recompile(shader, options); CheckSpirvBinaryValidates(result.spirv); @@ -5144,7 +5140,7 @@ void TestNewShaderRecompilerImageGatherVariants() { auto user_data = ImageTestUserData(); auto options = MakeCompileOptions(ShaderType::Compute); options.dump_ir = true; - options.user_data = user_data.data(); + options.user_data = user_data; auto result = ShaderRecompiler::Recompile(shader, options); Check(Common::ContainsStr(result.decoded_dump, "image_gather4_lz"), @@ -5230,7 +5226,7 @@ void TestNewShaderRecompilerImageLoadVariants() { auto user_data = ImageTestUserData(); auto options = MakeCompileOptions(ShaderType::Compute); options.dump_ir = true; - options.user_data = user_data.data(); + options.user_data = user_data; auto result = ShaderRecompiler::Recompile(shader, options); Check(Common::ContainsStr(result.decoded_dump, "image_load"), @@ -5276,7 +5272,7 @@ void TestNewShaderRecompilerImageLoad2DMsaa() { auto options = MakeCompileOptions(ShaderType::Pixel); options.dump_ir = true; - options.user_data = user_data.data(); + options.user_data = user_data; auto result = ShaderRecompiler::Recompile(shader, options); Check(Common::ContainsStr(result.decoded_dump, "image_dim=2d_msaa") && @@ -5317,7 +5313,7 @@ void TestNewShaderRecompilerImageStoreTranslation() { auto user_data = ImageTestUserData(); auto options = MakeCompileOptions(ShaderType::Compute); options.dump_ir = true; - options.user_data = user_data.data(); + options.user_data = user_data; auto result = ShaderRecompiler::Recompile(shader, options); Check(Common::ContainsStr(result.decoded_dump, "image_store"), @@ -5368,7 +5364,7 @@ void TestNewShaderRecompilerStorageImage3DDescriptorVariant() { auto options = MakeCompileOptions(ShaderType::Compute); options.dump_ir = true; options.input_info.compute = &input_info; - options.user_data = user_data.data(); + options.user_data = user_data; auto result = ShaderRecompiler::Recompile(shader, options); Check(Common::ContainsStr(result.decoded_dump, "image_dim=3d"), @@ -5422,7 +5418,7 @@ void TestNewShaderRecompilerStorageImage2DDescriptorOverridesMimg3D() { auto options = MakeCompileOptions(ShaderType::Compute); options.dump_ir = true; options.input_info.compute = &input_info; - options.user_data = user_data.data(); + options.user_data = user_data; auto result = ShaderRecompiler::Recompile(shader, options); Check(Common::ContainsStr(result.decoded_dump, "image_dim=3d"), @@ -5464,7 +5460,7 @@ void TestNewShaderRecompilerImageAtomicTranslation() { auto user_data = ImageTestUserData(); auto options = MakeCompileOptions(ShaderType::Compute); options.dump_ir = true; - options.user_data = user_data.data(); + options.user_data = user_data; auto result = ShaderRecompiler::Recompile(shader, options); Check(Common::ContainsStr(result.decoded_dump, "image_atomic_add"), @@ -6127,7 +6123,7 @@ void TestNewShaderRecompilerFormattedStoreUsesRuntimeArrayLengthOnly() { auto options = MakeCompileOptions(ShaderType::Compute); options.dump_ir = true; - options.user_data = user_data.data(); + options.user_data = user_data; auto result = ShaderRecompiler::Recompile(shader, options); Check(result.resources.buffers.size() == 1 && @@ -8946,7 +8942,7 @@ void TestDemandDrivenSpirvDeclarations() { auto user_data = ImageTestUserData(); SetImageTestFormat(&user_data, 0, format); auto options = MakeCompileOptions(ShaderType::Compute); - options.user_data = user_data.data(); + options.user_data = user_data; auto result = ShaderRecompiler::Recompile(shader, options); CheckSpirvBinaryValidates(result.spirv); return result.spirv; @@ -8959,7 +8955,7 @@ void TestDemandDrivenSpirvDeclarations() { auto query_pixel_info = RegressionPixelInputInfo(); auto query_options = MakeCompileOptions(ShaderType::Pixel); query_options.input_info.pixel = &query_pixel_info; - query_options.user_data = query_user_data.data(); + query_options.user_data = query_user_data; auto query_result = ShaderRecompiler::Recompile(query, query_options); CheckSpirvBinaryValidates(query_result.spirv); const auto &query_spirv = query_result.spirv; @@ -10320,7 +10316,7 @@ void TestNewShaderRecompilerNativeBindingPlan() { SetImageTestFormat(&user_data, 6, Prospero::BufferFormat::k32UInt); auto options = MakeCompileOptions(ShaderType::Compute); options.dump_ir = true; - options.user_data = user_data.data(); + options.user_data = user_data; auto result = ShaderRecompiler::Recompile(shader, options); const auto *buffers = ShaderRecompiler::IR::FindBinding( @@ -10703,7 +10699,7 @@ void TestTypedDescriptorRealCarryAndScalarLoads() { auto user_data = ImageTestUserData(); auto options = MakeCompileOptions(ShaderType::Pixel); - options.user_data = user_data.data(); + options.user_data = user_data; auto result = ShaderRecompiler::Recompile(inline_sampler_shader, options); } @@ -11189,9 +11185,7 @@ void TestComputeLdsAllocationIdentity() { "COMPUTE_PGM_RSRC2 LDS allocation units were not decoded"); auto options = MakeCompileOptions(ShaderType::Compute); options.shader_hash = params.hash; - options.shader_base = params.Base(); - options.user_data = params.user_data.data(); - options.user_data_count = static_cast(params.user_data.size()); + options.user_data = params.user_data; options.input_info.compute = &input_info; options.wave_size = input_info.wave_size; options.scratch_dwords = input_info.scratch_size_dwords; @@ -11257,10 +11251,7 @@ void TestComputeLdsAllocationIdentity() { "AGC per-thread scratch size was not propagated"); auto scratch_options = MakeCompileOptions(ShaderType::Compute); scratch_options.shader_hash = scratch_params.hash; - scratch_options.shader_base = scratch_params.Base(); - scratch_options.user_data = scratch_params.user_data.data(); - scratch_options.user_data_count = - static_cast(scratch_params.user_data.size()); + scratch_options.user_data = scratch_params.user_data; scratch_options.input_info.compute = &scratch_info; scratch_options.wave_size = scratch_info.wave_size; scratch_options.scratch_dwords = scratch_info.scratch_size_dwords; @@ -11537,8 +11528,7 @@ void TestGraphicsPushConstantPlacement() { auto options = MakeCompileOptions(ShaderType::Pixel); options.input_info.pixel = &pixel_info; - options.user_data = user_data.data(); - options.user_data_count = static_cast(user_data.size()); + options.user_data = user_data; options.push_constant_offset = 36; auto placed = ShaderRecompiler::Recompile(shader, options); @@ -11601,7 +11591,6 @@ void TestNewShaderRecompilerFlatUserPointerUsesDma() { auto options = MakeCompileOptions(ShaderType::Pixel); options.user_data = user_data; - options.user_data_count = static_cast(std::size(user_data)); auto result = ShaderRecompiler::Recompile(shader, options); Check(result.program.info.uses_dma, @@ -11623,7 +11612,6 @@ void TestNewShaderRecompilerFlatAddressDomainsUseDma() { auto options = MakeCompileOptions(ShaderType::Compute); options.user_data = user_data; - options.user_data_count = static_cast(std::size(user_data)); options.scratch_dwords = 1; auto result = ShaderRecompiler::Recompile(segmented_shader, options); Check(result.program.info.uses_dma,