shader_recompiler: Add texel buffer multiplier

* Fixes format mismatch assert when vsharp stride is multiple of format stride
This commit is contained in:
IndecisiveTurtle 2024-12-01 16:31:46 +02:00
parent 7276853b02
commit 22b816227f
5 changed files with 17 additions and 5 deletions

View file

@ -326,7 +326,9 @@ Id EmitLoadBufferU32x4(EmitContext& ctx, IR::Inst*, u32 handle, Id address) {
Id EmitLoadBufferFormatF32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address) {
const auto& buffer = ctx.texture_buffers[handle];
const Id tex_buffer = ctx.OpLoad(buffer.image_type, buffer.id);
const Id coord = ctx.OpIAdd(ctx.U32[1], address, buffer.coord_offset);
const Id coord =
ctx.OpIAdd(ctx.U32[1], ctx.OpShiftLeftLogical(ctx.U32[1], address, buffer.coord_shift),
buffer.coord_offset);
Id texel = buffer.is_storage ? ctx.OpImageRead(buffer.result_type, tex_buffer, coord)
: ctx.OpImageFetch(buffer.result_type, tex_buffer, coord);
if (buffer.is_integer) {
@ -372,7 +374,9 @@ void EmitStoreBufferU32x4(EmitContext& ctx, IR::Inst* inst, u32 handle, Id addre
void EmitStoreBufferFormatF32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value) {
const auto& buffer = ctx.texture_buffers[handle];
const Id tex_buffer = ctx.OpLoad(buffer.image_type, buffer.id);
const Id coord = ctx.OpIAdd(ctx.U32[1], address, buffer.coord_offset);
const Id coord =
ctx.OpIAdd(ctx.U32[1], ctx.OpShiftLeftLogical(ctx.U32[1], address, buffer.coord_shift),
buffer.coord_offset);
if (buffer.is_integer) {
value = ctx.OpBitcast(buffer.result_type, value);
}

View file

@ -207,6 +207,8 @@ void EmitContext::DefineBufferOffsets() {
push_data_block, ConstU32(half), ConstU32(comp))};
const Id value{OpLoad(U32[1], ptr)};
tex_buffer.coord_offset = OpBitFieldUExtract(U32[1], value, ConstU32(offset), ConstU32(6U));
tex_buffer.coord_shift =
OpBitFieldUExtract(U32[1], value, ConstU32(offset + 6U), ConstU32(2U));
Name(tex_buffer.coord_offset, fmt::format("texbuf{}_off", binding));
}
}

View file

@ -223,6 +223,7 @@ public:
struct TextureBufferDefinition {
Id id;
Id coord_offset;
Id coord_shift;
u32 binding;
Id image_type;
Id result_type;

View file

@ -105,6 +105,11 @@ struct PushData {
ASSERT(offset < 256 && binding < buf_offsets.size());
buf_offsets[binding] = offset;
}
void AddTexelOffset(u32 binding, u32 multiplier, u32 texel_offset) {
ASSERT(texel_offset < 64 && multiplier < 16);
buf_offsets[binding] = texel_offset | (std::bit_width(multiplier) << 6);
}
};
static_assert(sizeof(PushData) <= 128,
"PushData size is greater than minimum size guaranteed by Vulkan spec");

View file

@ -548,12 +548,12 @@ void Rasterizer::BindBuffers(const Shader::Info& stage, Shader::Backend::Binding
const auto [vk_buffer, offset] = buffer_cache.ObtainBuffer(
vsharp.base_address, vsharp.GetSize(), desc.is_written, true, buffer_id);
const u32 fmt_stride = AmdGpu::NumBits(vsharp.GetDataFmt()) >> 3;
ASSERT_MSG(fmt_stride == vsharp.GetStride(),
"Texel buffer stride must match format stride");
const u32 buf_stride = vsharp.GetStride();
ASSERT_MSG(buf_stride % fmt_stride, "Texel buffer stride must match format stride");
const u32 offset_aligned = Common::AlignDown(offset, alignment);
const u32 adjust = offset - offset_aligned;
ASSERT(adjust % fmt_stride == 0);
push_data.AddOffset(binding.buffer, adjust / fmt_stride);
push_data.AddTexelOffset(binding.buffer, buf_stride / fmt_stride, adjust / fmt_stride);
buffer_view =
vk_buffer->View(offset_aligned, vsharp.GetSize() + adjust, desc.is_written,
vsharp.GetDataFmt(), vsharp.GetNumberFmt());