From d0a4c908a17b0233bf01953e2e1275edf0f693ba Mon Sep 17 00:00:00 2001 From: nmzik Date: Fri, 21 Aug 2026 02:29:23 +0200 Subject: [PATCH] shader: align address-memory buffer bindings --- .../renderer/pipeline/descriptors.cpp | 34 ++++--- .../recompiler/backend/spirv/SpirvEmitter.cpp | 5 +- .../backend/spirv/spirvEmitterInternal.h | 5 +- .../backend/spirv/spirvEmitterMemory.cpp | 22 ++++- .../spirv/spirvEmitterMemoryHelpers.cpp | 16 ++-- .../backend/spirv/spirvEmitterProgram.cpp | 2 +- src/graphics/shader/recompiler/ir/ShaderIR.h | 6 +- .../recompiler/ir/passes/BindingLayout.cpp | 5 +- src/graphics/shader/shader.cpp | 4 +- tests/ResourceTrackingTests.cpp | 6 ++ tests/ShaderRecompilerComputeTests.cpp | 90 ++++++++++++++++--- tests/shaderCfgTests.cpp | 8 +- 12 files changed, 152 insertions(+), 51 deletions(-) diff --git a/src/graphics/host_gpu/renderer/pipeline/descriptors.cpp b/src/graphics/host_gpu/renderer/pipeline/descriptors.cpp index 59f36da3f..64a989b78 100644 --- a/src/graphics/host_gpu/renderer/pipeline/descriptors.cpp +++ b/src/graphics/host_gpu/renderer/pipeline/descriptors.cpp @@ -123,8 +123,10 @@ static BufferView NativeStorageBuffer(RenderContext& context, CommandBuffer& com static BufferView NativeAddressBuffer(RenderContext& context, CommandBuffer& command_buffer, const ShaderRecompiler::IR::AddressResource& resource, - const ShaderRecompiler::IR::ResourceSnapshot::Address& address) { + const ShaderRecompiler::IR::ResourceSnapshot::Address& address, + uint32_t& address_offset) { BufferView result; + address_offset = 0; if (address.binding_base == 0) { BindNullStorageBuffer(context, result); return result; @@ -145,17 +147,17 @@ NativeAddressBuffer(RenderContext& context, CommandBuffer& command_buffer, } const auto& graphics = context.GetGraphics(); const auto alignment = graphics.StorageMinAlignment(); - if (alignment == 0 || - size > graphics.GetPhysicalDeviceProperties().limits.maxStorageBufferRange || - BufferCache::GetBufferOffset(address.binding_base) % alignment != 0) { - EXIT("address resource range or alignment is unsupported\n"); - } auto binding = context.GetBufferCache().ObtainBuffer(command_buffer, address.binding_base, size); + const auto aligned_offset = binding.offset - binding.offset % alignment; + const auto adjustment = binding.offset - aligned_offset; + const auto max_range = graphics.GetPhysicalDeviceProperties().limits.maxStorageBufferRange; + const auto visible_size = std::min(size, static_cast(max_range - adjustment)); + address_offset = static_cast(adjustment); result.owner = std::move(binding.owner); result.buffer = binding.buffer; - result.offset = binding.offset; - result.range = static_cast(size); + result.offset = aligned_offset; + result.range = static_cast(visible_size + adjustment); return result; } @@ -897,22 +899,28 @@ void RenderExecutor::RebindBuffers(CommandBuffer& buffer, resources.buffers.clear(); resources.buffers.reserve(program.info.buffers.size()); EXIT_IF(prepared.user_data.size() != layout.ShaderDataDwords()); - std::fill(prepared.user_data.begin() + layout.buffer_offset_dword, prepared.user_data.end(), 0); + std::fill(prepared.user_data.begin() + layout.memory_offset_dword, prepared.user_data.end(), 0); + auto pack_memory_offset = [&](uint32_t index, uint32_t offset) { + const auto dword = layout.memory_offset_dword + index / 4u; + const auto shift = (index % 4u) * 8u; + prepared.user_data[dword] |= offset << shift; + }; for (uint32_t i = 0; i < program.info.buffers.size(); i++) { ShaderBufferResource descriptor; CopyNativeDescriptor(snapshot.buffers[i], descriptor.fields); uint32_t buffer_offset = 0; resources.buffers.push_back(NativeStorageBuffer(m_context, buffer, descriptor, program.info.buffers[i], buffer_offset)); - const auto dword = layout.buffer_offset_dword + i / 4u; - const auto shift = (i % 4u) * 8u; - prepared.user_data[dword] |= buffer_offset << shift; + pack_memory_offset(i, buffer_offset); } resources.addresses.clear(); resources.addresses.reserve(program.info.addresses.size()); for (uint32_t i = 0; i < program.info.addresses.size(); i++) { + uint32_t address_offset = 0; resources.addresses.push_back(NativeAddressBuffer( - m_context, buffer, program.info.addresses[i], snapshot.addresses[i])); + m_context, buffer, program.info.addresses[i], snapshot.addresses[i], address_offset)); + pack_memory_offset(static_cast(program.info.buffers.size()) + i, + address_offset); } } diff --git a/src/graphics/shader/recompiler/backend/spirv/SpirvEmitter.cpp b/src/graphics/shader/recompiler/backend/spirv/SpirvEmitter.cpp index ec0b80021..af8162f82 100644 --- a/src/graphics/shader/recompiler/backend/spirv/SpirvEmitter.cpp +++ b/src/graphics/shader/recompiler/backend/spirv/SpirvEmitter.cpp @@ -109,8 +109,9 @@ bool ValidateNativeProgram(const IR::Program& program, std::string* error) { } } const auto has_user_storage = present[static_cast(Kind::UserData)]; - if (program.bindings.buffer_offset_dword != program.bindings.user_data_registers.size() || - program.bindings.buffer_offset_count != program.info.buffers.size() || + if (program.bindings.memory_offset_dword != program.bindings.user_data_registers.size() || + program.bindings.memory_offset_count != + program.info.buffers.size() + program.info.addresses.size() || (!has_user_storage && program.bindings.push_constant_size != program.bindings.ShaderDataDwords() * 4u) || (has_user_storage && program.bindings.push_constant_size != 0) || diff --git a/src/graphics/shader/recompiler/backend/spirv/spirvEmitterInternal.h b/src/graphics/shader/recompiler/backend/spirv/spirvEmitterInternal.h index dd58ca86f..6f684ccc3 100644 --- a/src/graphics/shader/recompiler/backend/spirv/spirvEmitterInternal.h +++ b/src/graphics/shader/recompiler/backend/spirv/spirvEmitterInternal.h @@ -333,7 +333,8 @@ struct EmitterState { uint32_t wave_size = 64; bool per_invocation_masks = false; uint32_t storage_buffer_variable = 0; - std::array storage_buffer_offsets {}; + std::array + memory_byte_offsets {}; uint32_t address_memory_variable = 0; uint32_t gds_variable = 0; uint32_t gds_length = 0; @@ -713,7 +714,7 @@ uint32_t StorageBufferPackedStride(const EmitterState& state, const IR::MemoryIn Prospero::BufferFormat StorageBufferFormat(const EmitterState& state, const IR::MemoryInfo& mem); -void EmitStorageBufferOffsets(EmitterState& state); +void EmitMemoryOffsets(EmitterState& state); uint32_t LdsDwordCount(const EmitterState& state); diff --git a/src/graphics/shader/recompiler/backend/spirv/spirvEmitterMemory.cpp b/src/graphics/shader/recompiler/backend/spirv/spirvEmitterMemory.cpp index 579e0b76b..ec5f347dc 100644 --- a/src/graphics/shader/recompiler/backend/spirv/spirvEmitterMemory.cpp +++ b/src/graphics/shader/recompiler/backend/spirv/spirvEmitterMemory.cpp @@ -135,6 +135,22 @@ uint32_t AddressByteAddress(ValueEmitContext& ctx, const IR::Inst& inst, const I return Select(state, TypeU32(state), valid, relative, ConstantU32(state, UINT32_MAX)); } +uint32_t AddAddressMemoryOffset(ValueEmitContext& ctx, const IR::MemoryInfo& mem, + uint32_t address) { + auto& state = ctx.state; + const auto binding = + ResourceForDescriptor(state, IR::DescriptorBindingKind::AddressMemory, mem.resource); + const auto offset = + state.memory_byte_offsets[state.program.info.buffers.size() + binding.array_index]; + const auto corrected = Binary(state, OpIAdd, TypeU32(state), address, offset); + const auto not_invalid = + Binary(state, OpINotEqual, TypeBool(state), address, ConstantU32(state, UINT32_MAX)); + const auto no_overflow = + Binary(state, OpUGreaterThanEqual, TypeBool(state), corrected, address); + return Select(state, TypeU32(state), AndCondition(state, not_invalid, no_overflow), corrected, + ConstantU32(state, UINT32_MAX)); +} + uint32_t ByteAddress(ValueEmitContext& ctx, const IR::Inst& inst, const IR::MemoryInfo& mem) { if (mem.kind == IR::ResourceKind::Buffer) { return BufferByteAddress(ctx, inst, mem, ctx.Arg(inst, 1), ctx.Arg(inst, 2), @@ -147,7 +163,11 @@ uint32_t ByteAddress(ValueEmitContext& ctx, const IR::Inst& inst, const IR::Memo return Binary(ctx.state, OpIAdd, TypeU32(ctx.state), ctx.Arg(inst, 0), ConstantU32(ctx.state, mem.offset)); } - return AddressByteAddress(ctx, inst, mem, ctx.Arg(inst, 1), ctx.Arg(inst, 2)); + const auto address = AddressByteAddress(ctx, inst, mem, ctx.Arg(inst, 1), ctx.Arg(inst, 2)); + if (mem.kind == IR::ResourceKind::Scratch) { + return address; + } + return AddAddressMemoryOffset(ctx, mem, address); } uint32_t DwordIndex(ValueEmitContext& ctx, const IR::Inst& inst, const IR::MemoryInfo& mem) { diff --git a/src/graphics/shader/recompiler/backend/spirv/spirvEmitterMemoryHelpers.cpp b/src/graphics/shader/recompiler/backend/spirv/spirvEmitterMemoryHelpers.cpp index 443e381ca..1fee95ef0 100644 --- a/src/graphics/shader/recompiler/backend/spirv/spirvEmitterMemoryHelpers.cpp +++ b/src/graphics/shader/recompiler/backend/spirv/spirvEmitterMemoryHelpers.cpp @@ -52,14 +52,14 @@ Prospero::BufferFormat StorageBufferFormat(const EmitterState& state, const IR:: return state.program.info.buffers[mem.resource].descriptor_format; } -void EmitStorageBufferOffsets(EmitterState& state) { - for (uint32_t i = 0; i < state.program.bindings.buffer_offset_count; i++) { +void EmitMemoryOffsets(EmitterState& state) { + for (uint32_t i = 0; i < state.program.bindings.memory_offset_count; i++) { const auto word = - EmitShaderDataDwordLoad(state, state.program.bindings.buffer_offset_dword + i / 4u); - const auto shift = ConstantU32(state, (i % 4u) * 8u + 2u); - state.storage_buffer_offsets[i] = EmitBinaryU32( + EmitShaderDataDwordLoad(state, state.program.bindings.memory_offset_dword + i / 4u); + const auto shift = ConstantU32(state, (i % 4u) * 8u); + state.memory_byte_offsets[i] = EmitBinaryU32( state, OpBitwiseAnd, EmitBinaryU32(state, OpShiftRightLogical, word, shift), - ConstantU32(state, 0x3fu)); + ConstantU32(state, 0xffu)); } } @@ -135,7 +135,9 @@ MemoryResourceAccess PrepareMemoryResourceAccess(EmitterState& state, const IR:: state.builder.AddFunction({OpAccessChain, TypeStorageBufferPointer(state), access.object_pointer, state.storage_buffer_variable, ConstantU32(state, binding.array_index)}); - access.index_offset = state.storage_buffer_offsets[binding.array_index]; + access.index_offset = EmitBinaryU32(state, OpShiftRightLogical, + state.memory_byte_offsets[binding.array_index], + ConstantU32(state, 2u)); access.add_index_offset = true; break; } diff --git a/src/graphics/shader/recompiler/backend/spirv/spirvEmitterProgram.cpp b/src/graphics/shader/recompiler/backend/spirv/spirvEmitterProgram.cpp index 30b144f1a..031da76cf 100644 --- a/src/graphics/shader/recompiler/backend/spirv/spirvEmitterProgram.cpp +++ b/src/graphics/shader/recompiler/backend/spirv/spirvEmitterProgram.cpp @@ -620,7 +620,7 @@ bool EmitValueProgram(EmitterState& state, const IR::ValueProgram& program, std: state.builder.AddFunction( {OpStore, state.pixel_valid_mask_variable, ConstantU32(state, 1)}); } - EmitStorageBufferOffsets(state); + EmitMemoryOffsets(state); if (program.blocks.empty()) { EmitReturn(ctx); } else if (state.program.dispatcher_fallback) { diff --git a/src/graphics/shader/recompiler/ir/ShaderIR.h b/src/graphics/shader/recompiler/ir/ShaderIR.h index b85b7331a..e7730b1ae 100644 --- a/src/graphics/shader/recompiler/ir/ShaderIR.h +++ b/src/graphics/shader/recompiler/ir/ShaderIR.h @@ -423,13 +423,13 @@ struct BindingLayout { uint32_t descriptor_set = 0; uint32_t push_constant_offset = 0; uint32_t push_constant_size = 0; - uint32_t buffer_offset_dword = 0; - uint32_t buffer_offset_count = 0; + uint32_t memory_offset_dword = 0; + uint32_t memory_offset_count = 0; std::vector user_data_registers; std::vector descriptors; [[nodiscard]] uint32_t ShaderDataDwords() const { - return buffer_offset_dword + (buffer_offset_count + 3u) / 4u; + return memory_offset_dword + (memory_offset_count + 3u) / 4u; } bool operator==(const BindingLayout& other) const = default; diff --git a/src/graphics/shader/recompiler/ir/passes/BindingLayout.cpp b/src/graphics/shader/recompiler/ir/passes/BindingLayout.cpp index 2b10633f2..0f8c03e1d 100644 --- a/src/graphics/shader/recompiler/ir/passes/BindingLayout.cpp +++ b/src/graphics/shader/recompiler/ir/passes/BindingLayout.cpp @@ -130,8 +130,9 @@ bool AllocateBindings(Program& program, const BindingLayoutOptions& options, std } return false; } - next.buffer_offset_dword = static_cast(next.user_data_registers.size()); - next.buffer_offset_count = static_cast(program.info.buffers.size()); + next.memory_offset_dword = static_cast(next.user_data_registers.size()); + next.memory_offset_count = + static_cast(program.info.buffers.size() + program.info.addresses.size()); if (!program.info.buffers.empty()) { std::vector resources(program.info.buffers.size()); diff --git a/src/graphics/shader/shader.cpp b/src/graphics/shader/shader.cpp index e115e3c7e..ff74e59cd 100644 --- a/src/graphics/shader/shader.cpp +++ b/src/graphics/shader/shader.cpp @@ -1059,8 +1059,8 @@ static void ShaderAppendNativeSpecialization(std::vector& ids.push_back(program.bindings.descriptor_set); ids.push_back(program.bindings.push_constant_offset); ids.push_back(program.bindings.push_constant_size); - ids.push_back(program.bindings.buffer_offset_dword); - ids.push_back(program.bindings.buffer_offset_count); + ids.push_back(program.bindings.memory_offset_dword); + ids.push_back(program.bindings.memory_offset_count); ids.push_back(static_cast(program.bindings.user_data_registers.size())); ids.insert(ids.end(), program.bindings.user_data_registers.begin(), program.bindings.user_data_registers.end()); diff --git a/tests/ResourceTrackingTests.cpp b/tests/ResourceTrackingTests.cpp index da420ffed..bb8890842 100644 --- a/tests/ResourceTrackingTests.cpp +++ b/tests/ResourceTrackingTests.cpp @@ -939,6 +939,12 @@ void TestDynamicSrtReadRemainsExplicit() { FindBinding(fixture.program.bindings, DescriptorBindingKind::AddressMemory) != nullptr, "dynamic scalar read received the wrong resource bindings"); + Check(fixture.program.bindings.memory_offset_dword == + fixture.program.bindings.user_data_registers.size() && + fixture.program.bindings.memory_offset_count == 2u && + fixture.program.bindings.ShaderDataDwords() == + fixture.program.bindings.memory_offset_dword + 1u, + "unified memory-offset layout is inconsistent"); } void TestPhiValidation() { diff --git a/tests/ShaderRecompilerComputeTests.cpp b/tests/ShaderRecompilerComputeTests.cpp index cbfa73a2c..9e208f7dc 100644 --- a/tests/ShaderRecompilerComputeTests.cpp +++ b/tests/ShaderRecompilerComputeTests.cpp @@ -863,6 +863,7 @@ struct TestCase { bool compile_only = false; size_t storage_buffer_range_dwords = 0; std::vector storage_buffer_offsets; + std::vector address_memory_offsets; bool force_shader_data_storage = false; bool expected_force_point_sampler = false; std::optional flat_memory_base; @@ -1177,15 +1178,28 @@ CompiledShader CompileCase(const TestCase &test) { result.resources.user_data[reg - result.program.user_data_base]); } packed_user_data.resize(result.program.bindings.ShaderDataDwords()); - for (u32 i = 0; i < result.program.bindings.buffer_offset_count; i++) { - const auto offset = i < test.storage_buffer_offsets.size() - ? test.storage_buffer_offsets[i] - : 0u; + const auto buffer_count = static_cast(result.program.info.buffers.size()); + for (u32 i = 0; i < buffer_count; i++) { + u32 offset = 0; + if (i < test.storage_buffer_offsets.size()) { + offset = test.storage_buffer_offsets[i]; + } Require(test.name, "shader data", offset % sizeof(u32) == 0 && offset < 256, "storage buffer offset is not representable"); - packed_user_data[result.program.bindings.buffer_offset_dword + i / 4u] |= + packed_user_data[result.program.bindings.memory_offset_dword + i / 4u] |= offset << ((i % 4u) * 8u); } + for (u32 i = 0; i < result.program.info.addresses.size(); i++) { + u32 offset = 0; + if (i < test.address_memory_offsets.size()) { + offset = test.address_memory_offsets[i]; + } + Require(test.name, "shader data", offset < 256, + "address-memory offset is not representable"); + const auto index = buffer_count + i; + packed_user_data[result.program.bindings.memory_offset_dword + index / 4u] |= + offset << ((index % 4u) * 8u); + } return {std::move(result.spirv), std::move(result.program), std::move(result.resources.flattened_srt), std::move(packed_user_data)}; @@ -16575,10 +16589,18 @@ TestCase FlatLoadVariants() { } AppendEnd(&code); + const std::vector guest_memory{0x80ff7f01u, 0x00008001u, 0x11223344u, + 0x55667788u, 0x99aabbccu, 0xddeeff00u}; + constexpr size_t byte_offset = 8; + std::vector host_memory( + (byte_offset + guest_memory.size() * sizeof(u32) + sizeof(u32) - 1u) / + sizeof(u32)); + std::memcpy(reinterpret_cast(host_memory.data()) + byte_offset, + guest_memory.data(), guest_memory.size() * sizeof(u32)); + TestCase test{"FlatLoadVariants", code, - {0x80ff7f01u, 0x00008001u, 0x11223344u, 0x55667788u, - 0x99aabbccu, 0xddeeff00u}, + std::move(host_memory), {0x01u, 0xffffffffu, 0x7f01u, 0xffff80ffu, 0x11223344u, 0x55667788u, 0x11223344u, 0x55667788u, 0x99aabbccu, 0x11223344u, 0x55667788u, 0x99aabbccu, 0xddeeff00u, @@ -16588,6 +16610,40 @@ TestCase FlatLoadVariants() { O::FLAT_LOAD_DWORDX2, O::FLAT_LOAD_DWORDX3, O::FLAT_LOAD_DWORDX4, O::BUFFER_STORE_DWORD, O::S_ENDPGM}}; test.flat_memory_base = 0; + test.address_memory_offsets = {static_cast(byte_offset)}; + return test; +} + +TestCase FlatSubdwordLoadsApplyByteOffset() { + using O = ShaderOpcode; + + std::vector code; + AppendVMovU32(&code, 20, 0); + AppendVMovU32(&code, 21, 0); + code.push_back(EncodeFlat0(0x08, 0, 0)); + code.push_back(EncodeFlat1(0, 0x7d, 0, 20)); + code.push_back(EncodeFlat0(0x0a, 0, 1)); + code.push_back(EncodeFlat1(1, 0x7d, 0, 20)); + AppendStoreVgpr(&code, 0, 0); + AppendStoreVgpr(&code, 1, 1); + AppendEnd(&code); + + constexpr size_t byte_offset = 3; + constexpr u32 guest_word = 0x80ff7f01u; + std::vector host_memory( + (byte_offset + sizeof(guest_word) + sizeof(u32) - 1u) / sizeof(u32)); + std::memcpy(reinterpret_cast(host_memory.data()) + byte_offset, + &guest_word, sizeof(guest_word)); + + TestCase test; + test.name = "FlatSubdwordLoadsApplyByteOffset"; + test.code = std::move(code); + test.initial = std::move(host_memory); + test.expected = {0x01u, 0x0000ff7fu}; + test.flat_memory_base = 0; + test.address_memory_offsets = {static_cast(byte_offset)}; + test.opcodes = {O::V_MOV_B32, O::FLAT_LOAD_UBYTE, O::FLAT_LOAD_USHORT, + O::BUFFER_STORE_DWORD, O::S_ENDPGM}; return test; } @@ -16667,9 +16723,10 @@ TestCase FlatVirtualAddressRebasesGuestAllocation() { TestCase test; test.name = "FlatVirtualAddressRebasesGuestAllocation"; test.code = std::move(code); - test.initial = {0, 0x12345678u}; + test.initial = {0xfeedfaceu, 0xcafebabeu, 0, 0x12345678u}; test.expected = {0x12345678u, 0x12345678u, 0}; test.flat_memory_base = GuestBase; + test.address_memory_offsets = {8, 8, 8}; test.opcodes = {O::V_MOV_B32, O::FLAT_LOAD_DWORD, O::BUFFER_STORE_DWORD, O::S_ENDPGM}; return test; @@ -16688,12 +16745,16 @@ TestCase GlobalSignedImmediateRebasesBeforeSaddr() { AppendStoreVgpr(&code, 0, 0); AppendEnd(&code); - return {"GlobalSignedImmediateRebasesBeforeSaddr", - code, - {0x11111111u, 0x22222222u, 0x12345678u}, - {0x12345678u}, - {O::S_MOV_B32, O::V_MOV_B32, O::FLAT_LOAD_DWORD, - O::BUFFER_STORE_DWORD, O::S_ENDPGM}}; + TestCase test; + test.name = "GlobalSignedImmediateRebasesBeforeSaddr"; + test.code = std::move(code); + test.initial = {0xfeedfaceu, 0xcafebabeu, 0x11111111u, 0x22222222u, + 0x12345678u}; + test.expected = {0x12345678u}; + test.address_memory_offsets = {8}; + test.opcodes = {O::S_MOV_B32, O::V_MOV_B32, O::FLAT_LOAD_DWORD, + O::BUFFER_STORE_DWORD, O::S_ENDPGM}; + return test; } TestCase FlatSegmentIgnoresSaddrAndMasksOffsetMsb() { @@ -19373,6 +19434,7 @@ std::vector MakeCases() { AddCase(TBufferLoadFormatXy88IntegerComponents); AddCase(TBufferStoreVariants); AddCase(FlatLoadVariants); + AddCase(FlatSubdwordLoadsApplyByteOffset); AddCase(FlatVirtualAddressRebasesGuestAllocation); AddCase(GlobalSignedImmediateRebasesBeforeSaddr); AddCase(FlatSegmentIgnoresSaddrAndMasksOffsetMsb); diff --git a/tests/shaderCfgTests.cpp b/tests/shaderCfgTests.cpp index 25c6d3e77..ecf97deb5 100644 --- a/tests/shaderCfgTests.cpp +++ b/tests/shaderCfgTests.cpp @@ -4231,7 +4231,7 @@ void TestNewShaderRecompilerScalarMemoryBindingDomains() { raw.program.bindings, ShaderRecompiler::IR::DescriptorBindingKind::FlattenedSrt) == nullptr && - raw.program.bindings.buffer_offset_count == 0u, + raw.program.bindings.memory_offset_count == 1u, "raw scalar load did not use only the address-memory domain"); Check(count_live_memory_ops( raw.program, ShaderRecompiler::IR::ValueOpcode::LoadAddressU32, @@ -4284,7 +4284,7 @@ void TestNewShaderRecompilerScalarMemoryBindingDomains() { buffer.program.bindings, ShaderRecompiler::IR::DescriptorBindingKind::FlattenedSrt) == nullptr && - buffer.program.bindings.buffer_offset_count == 1u, + buffer.program.bindings.memory_offset_count == 1u, "descriptor scalar load did not use only the buffer domain"); Check(count_live_memory_ops( buffer.program, ShaderRecompiler::IR::ValueOpcode::ReadConstBuffer, @@ -11442,8 +11442,8 @@ void TestNewShaderRecompilerSpirvSizeBaselines() { EncodeSopp(0x01), }; const auto wide_result = compile("wide-buffer", wide_buffer, - {.words = 797, - .instructions = 209, + {.words = 807, + .instructions = 211, .runtime_arrays = 1, .variables = 2, .loads = 9,