diff --git a/src/graphics/shader/recompiler/ir/passes/ResourceMaterialization.cpp b/src/graphics/shader/recompiler/ir/passes/ResourceMaterialization.cpp index 4b61ed211..29c547f39 100644 --- a/src/graphics/shader/recompiler/ir/passes/ResourceMaterialization.cpp +++ b/src/graphics/shader/recompiler/ir/passes/ResourceMaterialization.cpp @@ -423,36 +423,6 @@ bool BuildSamplerPlan(const ShaderInfo& base, const Images& images, SamplerPlan& static bool BuildResourceSpecialization(const ResourcePlan& program, ResourceSnapshot& snapshot, ResourceSpecialization& specialization) { - specialization.buffers.clear(); - specialization.buffers.reserve(program.info.buffers.size()); - for (uint32_t i = 0; i < program.info.buffers.size(); i++) { - auto& descriptor_value = snapshot.buffers[i]; - ShaderBufferResource descriptor; - if (!DecodeBufferDescriptor(descriptor_value, descriptor)) { - return SpecializationFail(fmt::format("buffer descriptor {} has invalid width", i)); - } - if (descriptor.Type() != 0) { - descriptor_value.dwords.fill(0); - descriptor = {}; - } - auto packed_stride = descriptor.PackedStride(); - const auto stride = packed_stride & 0x3fffu; - const bool swizzle = stride != 0u && ((packed_stride >> 14u) & 1u) != 0u; - if (stride == 0u) { - packed_stride &= ~((1u << 14u) | (3u << 16u)); - } else if (!swizzle) { - packed_stride &= ~(3u << 16u); - } - specialization.buffers.push_back({ - .packed_stride = packed_stride, - .descriptor_format = program.info.buffers[i].formatted - ? descriptor.Format() - : Prospero::BufferFormat::kInvalid, - .descriptor_swizzle = - program.info.buffers[i].formatted ? descriptor.DstSelXYZW() : DstSel(4, 5, 6, 7), - .zero_stride_oob = descriptor.OutOfBounds() == 0u && stride == 0u, - }); - } for (uint32_t i = 0; i < specialization.images.size(); i++) { const auto& descriptor = snapshot.images[i]; auto& image = specialization.images[i]; @@ -1029,11 +999,39 @@ bool MaterializeResources(const ResourcePlan& program, const SrtRuntime& runtime return true; }; snapshot.buffers.resize(program.info.buffers.size()); + specialization.buffers.clear(); + specialization.buffers.reserve(program.info.buffers.size()); for (uint32_t i = 0; i < program.info.buffers.size(); ++i) { if (!evaluate(program.info.buffers[i].source, snapshot.buffers[i], program.info.buffers[i].written)) { return false; } + auto& descriptor_value = snapshot.buffers[i]; + ShaderBufferResource descriptor; + if (!DecodeBufferDescriptor(descriptor_value, descriptor)) { + return SpecializationFail(fmt::format("buffer descriptor {} has invalid width", i)); + } + if (descriptor.Type() != 0) { + descriptor_value.dwords.fill(0); + descriptor = {}; + } + auto packed_stride = descriptor.PackedStride(); + const auto stride = packed_stride & 0x3fffu; + const bool swizzle = stride != 0u && ((packed_stride >> 14u) & 1u) != 0u; + if (stride == 0u) { + packed_stride &= ~((1u << 14u) | (3u << 16u)); + } else if (!swizzle) { + packed_stride &= ~(3u << 16u); + } + specialization.buffers.push_back({ + .packed_stride = packed_stride, + .descriptor_format = program.info.buffers[i].formatted + ? descriptor.Format() + : Prospero::BufferFormat::kInvalid, + .descriptor_swizzle = + program.info.buffers[i].formatted ? descriptor.DstSelXYZW() : DstSel(4, 5, 6, 7), + .zero_stride_oob = descriptor.OutOfBounds() == 0u && stride == 0u, + }); } snapshot.images.resize(program.info.images.size()); specialization.images.resize(program.info.images.size()); @@ -1088,19 +1086,20 @@ void ApplyResourceSpecialization(Program& program, const ResourceSpecialization& EXIT_IF(program.info.buffers.size() != specialization.buffers.size() || program.info.images.size() > specialization.images.size()); - auto buffers = program.info.buffers; + auto& buffers = program.info.buffers; for (size_t index = 0; index < buffers.size(); index++) { buffers[index].packed_stride = specialization.buffers[index].packed_stride; buffers[index].descriptor_format = specialization.buffers[index].descriptor_format; buffers[index].descriptor_swizzle = specialization.buffers[index].descriptor_swizzle; } - auto images = program.info.images; + auto& images = program.info.images; + const auto original_image_count = images.size(); images.reserve(specialization.images.size()); for (uint32_t index = 0; index < specialization.images.size(); index++) { const auto& source = specialization.images[index]; if (index >= images.size()) { - EXIT_IF(source.indirect_root >= program.info.images.size()); - images.push_back(program.info.images[source.indirect_root]); + EXIT_IF(source.indirect_root >= original_image_count); + images.push_back(images[source.indirect_root]); } auto& image = images[index]; image.numeric_class = source.numeric_class; @@ -1124,13 +1123,14 @@ void ApplyResourceSpecialization(Program& program, const ResourceSpecialization& SamplerPlan sampler_plan; EXIT_IF(!BuildSamplerPlan(program.info, images, sampler_plan)); - auto samplers = program.info.samplers; - auto sampled_pairs = program.info.sampled_pairs; + auto& samplers = program.info.samplers; + auto& sampled_pairs = program.info.sampled_pairs; + const auto original_sampler_count = samplers.size(); samplers.reserve(sampler_plan.sampler_count); for (uint32_t index = 0; index < sampler_plan.sampler_count; index++) { const auto& binding = sampler_plan.bindings[index]; - if (index >= program.info.samplers.size()) { - samplers.push_back(program.info.samplers[binding.source]); + if (index >= original_sampler_count) { + samplers.push_back(samplers[binding.source]); } samplers[index].force_point_filtering = binding.type == SamplerClass::PointInteger; samplers[index].integer_border = binding.type != SamplerClass::Float; @@ -1142,11 +1142,15 @@ void ApplyResourceSpecialization(Program& program, const ResourceSpecialization& samplers[pair.sampler].depth_compare |= images[pair.image].depth_compare; } - auto memory_info = program.memory_info; + auto& memory_info = program.memory_info; const ImageRemap image_remap(specialization); for (auto* block: program.blocks) { for (auto it = block->begin(); it != block->end(); ++it) { auto& inst = *it; + if (inst.GetOpcode() == ValueOpcode::GetImageResource) { + inst.SetFlags(image_remap[inst.Flags()]); + continue; + } if (BufferAccessOf(inst.GetOpcode()) == BufferAccess::Read) { const auto& memory = memory_info[inst.Flags().index]; if (memory.kind == ResourceKind::Buffer && @@ -1217,7 +1221,7 @@ void ApplyResourceSpecialization(Program& program, const ResourceSpecialization& continue; } if (image_opcode.needs_sampler && - memory.sampler < program.info.samplers.size()) { + memory.sampler < original_sampler_count) { const auto type = static_cast(ClassifySampler(image)); memory.sampler = sampler_plan.mapping[memory.sampler][type]; EXIT_IF(memory.sampler == UINT32_MAX); @@ -1226,13 +1230,6 @@ void ApplyResourceSpecialization(Program& program, const ResourceSpecialization& inst.GetOpcode() != ValueOpcode::ImageSampleRaw); } } - for (auto* block: program.blocks) { - for (auto& inst: *block) { - if (inst.GetOpcode() == ValueOpcode::GetImageResource) { - inst.SetFlags(image_remap[inst.Flags()]); - } - } - } for (auto& memory: memory_info) { if (memory.kind == ResourceKind::Image && !memory.planning_only) { memory.resource = image_remap[memory.resource]; @@ -1255,11 +1252,6 @@ void ApplyResourceSpecialization(Program& program, const ResourceSpecialization& } } image_remap.Apply(images); - program.info.buffers = std::move(buffers); - program.info.images = std::move(images); - program.info.samplers = std::move(samplers); - program.info.sampled_pairs = std::move(sampled_pairs); - program.memory_info = std::move(memory_info); } } // namespace Libs::Graphics::ShaderRecompiler::IR