diff --git a/src/shader_recompiler/frontend/fetch_shader.cpp b/src/shader_recompiler/frontend/fetch_shader.cpp index 7f2a0989..16938410 100644 --- a/src/shader_recompiler/frontend/fetch_shader.cpp +++ b/src/shader_recompiler/frontend/fetch_shader.cpp @@ -35,7 +35,7 @@ namespace Shader::Gcn { **/ FetchShaderData ParseFetchShader(const u32* code, u32* out_size) { - std::vector attributes; + FetchShaderData data{}; GcnCodeSlice code_slice(code, code + std::numeric_limits::max()); GcnDecodeContext decoder; @@ -46,9 +46,6 @@ FetchShaderData ParseFetchShader(const u32* code, u32* out_size) { }; boost::container::static_vector loads; - s8 fetch_index_sgpr = -1; - s8 fetch_offset_sgpr = -1; - u32 semantic_index = 0; while (!code_slice.atEnd()) { const auto inst = decoder.decodeInstruction(code_slice); @@ -67,11 +64,11 @@ FetchShaderData ParseFetchShader(const u32* code, u32* out_size) { const auto vgpr = inst.dst[0].code; const auto sgpr = s8(inst.src[0].code); switch (vgpr) { - case 0: // V0 is always the index - fetch_index_sgpr = sgpr; + case 0: // V0 is always the vertex offset + data.vertex_offset_sgpr = sgpr; break; - case 3: // V3 is always the offset - fetch_offset_sgpr = sgpr; + case 3: // V3 is always the instance offset + data.instance_offset_sgpr = sgpr; break; default: UNREACHABLE(); @@ -87,7 +84,7 @@ FetchShaderData ParseFetchShader(const u32* code, u32* out_size) { const auto it = std::ranges::find_if( loads, [&](VsharpLoad& load) { return load.dst_reg == base_sgpr; }); - auto& attrib = attributes.emplace_back(); + auto& attrib = data.attributes.emplace_back(); attrib.semantic = semantic_index++; attrib.dest_vgpr = inst.src[1].code; attrib.num_elements = inst.control.mubuf.count; @@ -102,11 +99,7 @@ FetchShaderData ParseFetchShader(const u32* code, u32* out_size) { } } - return FetchShaderData{ - .attributes = std::move(attributes), - .fetch_index_sgpr = fetch_index_sgpr, - .fetch_offset_sgpr = fetch_offset_sgpr, - }; + return data; } } // namespace Shader::Gcn diff --git a/src/shader_recompiler/frontend/fetch_shader.h b/src/shader_recompiler/frontend/fetch_shader.h index 4ea4853c..0e5d1541 100644 --- a/src/shader_recompiler/frontend/fetch_shader.h +++ b/src/shader_recompiler/frontend/fetch_shader.h @@ -19,8 +19,8 @@ struct VertexAttribute { struct FetchShaderData { std::vector attributes; - s8 fetch_index_sgpr; ///< Read index from VADDR - s8 fetch_offset_sgpr; ///< Read offset from VADDR + s8 vertex_offset_sgpr = -1; ///< SGPR of vertex offset from VADDR + s8 instance_offset_sgpr = -1; ///< SGPR of instance offset from VADDR }; FetchShaderData ParseFetchShader(const u32* code, u32* out_size); diff --git a/src/shader_recompiler/frontend/translate/translate.cpp b/src/shader_recompiler/frontend/translate/translate.cpp index 14e2e83b..e59cd565 100644 --- a/src/shader_recompiler/frontend/translate/translate.cpp +++ b/src/shader_recompiler/frontend/translate/translate.cpp @@ -359,8 +359,8 @@ void Translator::EmitFetch(const GcnInst& inst) { file.WriteRaw(code, fetch_size); } - info.fetch_index_sgpr = fetch_data.fetch_index_sgpr; - info.fetch_offset_sgpr = fetch_data.fetch_offset_sgpr; + info.vertex_offset_sgpr = fetch_data.vertex_offset_sgpr; + info.instance_offset_sgpr = fetch_data.instance_offset_sgpr; for (const auto& attrib : fetch_data.attributes) { const IR::Attribute attr{IR::Attribute::Param0 + attrib.semantic}; diff --git a/src/shader_recompiler/runtime_info.h b/src/shader_recompiler/runtime_info.h index 099be527..7d36dbe1 100644 --- a/src/shader_recompiler/runtime_info.h +++ b/src/shader_recompiler/runtime_info.h @@ -175,8 +175,8 @@ struct Info { AttributeFlags stores{}; boost::container::static_vector vs_outputs; - s8 fetch_index_sgpr = -1; - s8 fetch_offset_sgpr = -1; + s8 vertex_offset_sgpr = -1; + s8 instance_offset_sgpr = -1; BufferResourceList buffers; ImageResourceList images; @@ -213,6 +213,18 @@ struct Info { std::memcpy(&data, base + dword_offset, sizeof(T)); return data; } + + [[nodiscard]] std::pair GetDrawOffsets() const noexcept { + u32 vertex_offset = 0; + u32 instance_offset = 0; + if (vertex_offset_sgpr != -1) { + vertex_offset = user_data[vertex_offset_sgpr]; + } + if (instance_offset_sgpr != -1) { + instance_offset = user_data[instance_offset_sgpr]; + } + return {vertex_offset, instance_offset}; + } }; constexpr AmdGpu::Buffer BufferResource::GetVsharp(const Info& info) const noexcept { diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index d80e268d..90dee1fe 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -51,24 +51,17 @@ void Rasterizer::Draw(bool is_indexed, u32 index_offset) { BeginRendering(); UpdateDynamicState(*pipeline); - u32 instance_offset = 0; - if (vs_info.fetch_offset_sgpr != -1) { - instance_offset = vs_info.user_data[vs_info.fetch_offset_sgpr]; - } + const auto [vertex_offset, instance_offset] = vs_info.GetDrawOffsets(); if (is_indexed) { - u32 vertex_offset = 0; - if (vs_info.fetch_index_sgpr != -1) { - vertex_offset = vs_info.user_data[vs_info.fetch_index_sgpr]; - } - cmdbuf.drawIndexed(num_indices, regs.num_instances.NumInstances(), 0, s32(vertex_offset), instance_offset); } else { const u32 num_vertices = regs.primitive_type == AmdGpu::Liverpool::PrimitiveType::RectList ? 4 : regs.num_indices; - cmdbuf.draw(num_vertices, regs.num_instances.NumInstances(), 0, instance_offset); + cmdbuf.draw(num_vertices, regs.num_instances.NumInstances(), vertex_offset, + instance_offset); } }