shader_recompiler: handle fetch shader address offsets

parse index & offset sgpr from fetch shader and propagate them to vkBindVertexBuffers
This commit is contained in:
Vinicius Rangel 2024-08-22 21:27:32 -03:00
parent 09da94b7b2
commit 81f8c642a6
No known key found for this signature in database
GPG key ID: A5B154D904B761D9
5 changed files with 40 additions and 3 deletions

View file

@ -44,6 +44,7 @@ std::vector<VertexAttribute> ParseFetchShader(const u32* code, u32* out_size) {
s32 dst_reg{-1};
};
boost::container::static_vector<VsharpLoad, 16> loads;
std::array<u32, 16> offsets{};
u32 semantic_index = 0;
while (!code_slice.atEnd()) {
@ -59,6 +60,10 @@ std::vector<VertexAttribute> ParseFetchShader(const u32* code, u32* out_size) {
continue;
}
if (inst.opcode == Opcode::V_ADD_I32) {
offsets[inst.dst[0].code] = inst.src[0].code;
}
if (inst.inst_class == InstClass::VectorMemBufFmt) {
// SRSRC is in units of 4 SPGRs while SBASE is in pairs of SGPRs
const u32 base_sgpr = inst.src[2].code * 4;
@ -68,13 +73,29 @@ std::vector<VertexAttribute> ParseFetchShader(const u32* code, u32* out_size) {
const auto it = std::ranges::find_if(
loads, [&](VsharpLoad& load) { return load.dst_reg == base_sgpr; });
auto mubuf = inst.control.mubuf;
auto& attrib = attributes.emplace_back();
attrib.semantic = semantic_index++;
attrib.dest_vgpr = inst.src[1].code;
attrib.num_elements = inst.control.mubuf.count;
attrib.num_elements = mubuf.count;
attrib.sgpr_base = it->base_sgpr;
attrib.dword_offset = it->dword_offset;
u8 soofs = inst.src[0].code;
if (mubuf.idxen != 0) {
attrib.index_sgpr = offsets[soofs++];
} else {
attrib.index_sgpr = 0xFF;
}
if (mubuf.offen != 0) {
attrib.offset_sgpr = offsets[soofs];
} else {
attrib.offset_sgpr = 0xFF;
}
// Store instance id rate
attrib.instance_data = inst.src[0].code;

View file

@ -15,6 +15,8 @@ struct VertexAttribute {
u8 sgpr_base; ///< SGPR that contains the pointer to the list of vertex V#
u8 dword_offset; ///< The dword offset of the V# that describes this attribute.
u8 instance_data; ///< Indicates that the buffer will be accessed in instance rate
u8 index_sgpr; ///< Read index from VADDR
u8 offset_sgpr; ///< Offset from VADDR
};
std::vector<VertexAttribute> ParseFetchShader(const u32* code, u32* out_size);

View file

@ -412,6 +412,8 @@ void Translator::EmitFetch(const GcnInst& inst) {
.num_components = std::min<u16>(attrib.num_elements, num_components),
.sgpr_base = attrib.sgpr_base,
.dword_offset = attrib.dword_offset,
.index_sgpr = attrib.index_sgpr,
.offset_sgpr = attrib.offset_sgpr,
.instance_step_rate = step_rate,
.instance_data_buf = instance_buf_handle,
});

View file

@ -135,6 +135,8 @@ struct Info {
u16 num_components;
u8 sgpr_base;
u8 dword_offset;
u8 index_sgpr;
u8 offset_sgpr;
InstanceIdType instance_step_rate;
s32 instance_data_buf;
};

View file

@ -101,7 +101,7 @@ bool BufferCache::BindVertexBuffers(const Shader::Info& vs_info) {
}
std::array<vk::Buffer, NUM_VERTEX_BUFFERS> host_buffers;
std::array<vk::DeviceSize, NUM_VERTEX_BUFFERS> host_offsets;
std::array<vk::DeviceSize, NUM_VERTEX_BUFFERS> host_offsets{};
boost::container::static_vector<AmdGpu::Buffer, NUM_VERTEX_BUFFERS> guest_buffers;
struct BufferRange {
@ -131,6 +131,16 @@ bool BufferCache::BindVertexBuffers(const Shader::Info& vs_info) {
}
guest_buffers.emplace_back(buffer);
ranges.emplace_back(buffer.base_address, buffer.base_address + buffer.GetSize());
u32 offset = 0;
if (input.index_sgpr != 0xFF) {
offset += vs_info.user_data[input.index_sgpr] * buffer.GetStride();
}
if (input.offset_sgpr != 0xFF) {
offset += vs_info.user_data[input.offset_sgpr];
}
host_offsets[guest_buffers.size() - 1] = offset;
attributes.push_back({
.location = input.binding,
.binding = input.binding,
@ -180,7 +190,7 @@ bool BufferCache::BindVertexBuffers(const Shader::Info& vs_info) {
ASSERT(host_buffer != ranges_merged.cend());
host_buffers[i] = host_buffer->vk_buffer;
host_offsets[i] = host_buffer->offset + buffer.base_address - host_buffer->base_address;
host_offsets[i] += host_buffer->offset + buffer.base_address - host_buffer->base_address;
}
if (num_buffers > 0) {