mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-12-11 14:19:10 +00:00
renderer_vulkan: Parse fetch shader per-pipeline (#1656)
* shader_recompiler: Read image format info directly from sharps instead of storing in shader info. * renderer_vulkan: Parse fetch shader per-pipeline * Few minor fixes. * shader_recompiler: Specialize on vertex attribute number types. * shader_recompiler: Move GetDrawOffsets to fetch shader
This commit is contained in:
@@ -3,26 +3,80 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ranges>
|
||||
#include <vector>
|
||||
#include "common/types.h"
|
||||
#include "shader_recompiler/info.h"
|
||||
|
||||
namespace Shader::Gcn {
|
||||
|
||||
struct VertexAttribute {
|
||||
enum InstanceIdType : u8 {
|
||||
None = 0,
|
||||
OverStepRate0 = 1,
|
||||
OverStepRate1 = 2,
|
||||
Plain = 3,
|
||||
};
|
||||
|
||||
u8 semantic; ///< Semantic index of the attribute
|
||||
u8 dest_vgpr; ///< Destination VGPR to load first component.
|
||||
u8 num_elements; ///< Number of components to load
|
||||
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
|
||||
|
||||
[[nodiscard]] InstanceIdType GetStepRate() const {
|
||||
return static_cast<InstanceIdType>(instance_data);
|
||||
}
|
||||
|
||||
[[nodiscard]] bool UsesStepRates() const {
|
||||
const auto step_rate = GetStepRate();
|
||||
return step_rate == OverStepRate0 || step_rate == OverStepRate1;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr AmdGpu::Buffer GetSharp(const Shader::Info& info) const noexcept {
|
||||
return info.ReadUdReg<AmdGpu::Buffer>(sgpr_base, dword_offset);
|
||||
}
|
||||
|
||||
bool operator==(const VertexAttribute& other) const {
|
||||
return semantic == other.semantic && dest_vgpr == other.dest_vgpr &&
|
||||
num_elements == other.num_elements && sgpr_base == other.sgpr_base &&
|
||||
dword_offset == other.dword_offset && instance_data == other.instance_data;
|
||||
}
|
||||
};
|
||||
|
||||
struct FetchShaderData {
|
||||
const u32* code;
|
||||
u32 size = 0;
|
||||
std::vector<VertexAttribute> attributes;
|
||||
s8 vertex_offset_sgpr = -1; ///< SGPR of vertex offset from VADDR
|
||||
s8 instance_offset_sgpr = -1; ///< SGPR of instance offset from VADDR
|
||||
|
||||
[[nodiscard]] bool UsesStepRates() const {
|
||||
return std::ranges::find_if(attributes, [](const VertexAttribute& attribute) {
|
||||
return attribute.UsesStepRates();
|
||||
}) != attributes.end();
|
||||
}
|
||||
|
||||
[[nodiscard]] std::pair<u32, u32> GetDrawOffsets(const AmdGpu::Liverpool::Regs& regs,
|
||||
const Info& info) const {
|
||||
u32 vertex_offset = regs.index_offset;
|
||||
u32 instance_offset = 0;
|
||||
if (vertex_offset == 0 && vertex_offset_sgpr != -1) {
|
||||
vertex_offset = info.user_data[vertex_offset_sgpr];
|
||||
}
|
||||
if (instance_offset_sgpr != -1) {
|
||||
instance_offset = info.user_data[instance_offset_sgpr];
|
||||
}
|
||||
return {vertex_offset, instance_offset};
|
||||
}
|
||||
|
||||
bool operator==(const FetchShaderData& other) const {
|
||||
return attributes == other.attributes && vertex_offset_sgpr == other.vertex_offset_sgpr &&
|
||||
instance_offset_sgpr == other.instance_offset_sgpr;
|
||||
}
|
||||
};
|
||||
|
||||
FetchShaderData ParseFetchShader(const u32* code, u32* out_size);
|
||||
std::optional<FetchShaderData> ParseFetchShader(const Shader::Info& info);
|
||||
|
||||
} // namespace Shader::Gcn
|
||||
|
||||
Reference in New Issue
Block a user