2024-05-21 22:35:12 +00:00
|
|
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
2024-05-25 12:33:15 +00:00
|
|
|
#include <span>
|
|
|
|
#include <boost/container/static_vector.hpp>
|
|
|
|
#include "common/assert.h"
|
|
|
|
#include "common/types.h"
|
|
|
|
#include "shader_recompiler/ir/attribute.h"
|
2024-05-26 12:51:35 +00:00
|
|
|
#include "shader_recompiler/ir/reg.h"
|
|
|
|
#include "shader_recompiler/ir/type.h"
|
2024-05-26 22:07:46 +00:00
|
|
|
#include "video_core/amdgpu/resource.h"
|
2024-05-21 22:35:12 +00:00
|
|
|
|
|
|
|
namespace Shader {
|
|
|
|
|
2024-05-25 12:33:15 +00:00
|
|
|
static constexpr size_t NumUserDataRegs = 16;
|
2024-05-21 22:35:12 +00:00
|
|
|
|
|
|
|
enum class Stage : u32 {
|
|
|
|
Vertex,
|
|
|
|
TessellationControl,
|
|
|
|
TessellationEval,
|
|
|
|
Geometry,
|
|
|
|
Fragment,
|
|
|
|
Compute,
|
|
|
|
};
|
|
|
|
constexpr u32 MaxStageTypes = 6;
|
|
|
|
|
|
|
|
[[nodiscard]] constexpr Stage StageFromIndex(size_t index) noexcept {
|
|
|
|
return static_cast<Stage>(static_cast<size_t>(Stage::Vertex) + index);
|
|
|
|
}
|
|
|
|
|
|
|
|
enum class TextureType : u32 {
|
|
|
|
Color1D,
|
|
|
|
ColorArray1D,
|
|
|
|
Color2D,
|
|
|
|
ColorArray2D,
|
|
|
|
Color3D,
|
|
|
|
ColorCube,
|
|
|
|
Buffer,
|
|
|
|
};
|
|
|
|
constexpr u32 NUM_TEXTURE_TYPES = 7;
|
|
|
|
|
2024-07-04 21:15:44 +00:00
|
|
|
enum class VsOutput : u32 {
|
|
|
|
None,
|
|
|
|
PointSprite,
|
|
|
|
EdgeFlag,
|
|
|
|
KillFlag,
|
|
|
|
GsCutFlag,
|
|
|
|
GsMrtIndex,
|
|
|
|
GsVpIndex,
|
|
|
|
CullDist0,
|
|
|
|
CullDist1,
|
|
|
|
CullDist2,
|
|
|
|
CullDist3,
|
|
|
|
CullDist4,
|
|
|
|
CullDist5,
|
|
|
|
CullDist6,
|
|
|
|
CullDist7,
|
|
|
|
ClipDist0,
|
|
|
|
ClipDist1,
|
|
|
|
ClipDist2,
|
|
|
|
ClipDist3,
|
|
|
|
ClipDist4,
|
|
|
|
ClipDist5,
|
|
|
|
ClipDist6,
|
|
|
|
ClipDist7,
|
|
|
|
};
|
|
|
|
using VsOutputMap = std::array<VsOutput, 4>;
|
|
|
|
|
|
|
|
struct Info;
|
|
|
|
|
2024-05-26 12:51:35 +00:00
|
|
|
struct BufferResource {
|
|
|
|
u32 sgpr_base;
|
|
|
|
u32 dword_offset;
|
|
|
|
u32 stride;
|
|
|
|
u32 num_records;
|
|
|
|
IR::Type used_types;
|
2024-07-04 21:15:44 +00:00
|
|
|
AmdGpu::Buffer inline_cbuf;
|
2024-05-26 12:51:35 +00:00
|
|
|
bool is_storage;
|
|
|
|
|
2024-07-04 21:15:44 +00:00
|
|
|
constexpr AmdGpu::Buffer GetVsharp(const Info& info) const noexcept;
|
2024-05-26 12:51:35 +00:00
|
|
|
};
|
2024-06-30 21:43:59 +00:00
|
|
|
using BufferResourceList = boost::container::static_vector<BufferResource, 16>;
|
2024-05-26 12:51:35 +00:00
|
|
|
|
2024-05-26 22:07:46 +00:00
|
|
|
struct ImageResource {
|
|
|
|
u32 sgpr_base;
|
|
|
|
u32 dword_offset;
|
|
|
|
AmdGpu::ImageType type;
|
|
|
|
AmdGpu::NumberFormat nfmt;
|
|
|
|
bool is_storage;
|
|
|
|
bool is_depth;
|
|
|
|
};
|
2024-06-30 21:43:59 +00:00
|
|
|
using ImageResourceList = boost::container::static_vector<ImageResource, 16>;
|
2024-05-26 22:07:46 +00:00
|
|
|
|
|
|
|
struct SamplerResource {
|
|
|
|
u32 sgpr_base;
|
|
|
|
u32 dword_offset;
|
2024-07-04 21:15:57 +00:00
|
|
|
u32 associated_image : 4;
|
|
|
|
u32 disable_aniso : 1;
|
2024-05-26 22:07:46 +00:00
|
|
|
};
|
2024-06-30 21:43:59 +00:00
|
|
|
using SamplerResourceList = boost::container::static_vector<SamplerResource, 16>;
|
2024-05-26 22:07:46 +00:00
|
|
|
|
2024-05-21 22:35:12 +00:00
|
|
|
struct Info {
|
2024-05-25 12:33:15 +00:00
|
|
|
struct VsInput {
|
2024-06-22 16:50:20 +00:00
|
|
|
enum InstanceIdType : u8 {
|
|
|
|
None = 0,
|
|
|
|
OverStepRate0 = 1,
|
|
|
|
OverStepRate1 = 2,
|
|
|
|
Plain = 3,
|
|
|
|
};
|
|
|
|
|
2024-05-25 12:33:15 +00:00
|
|
|
AmdGpu::NumberFormat fmt;
|
|
|
|
u16 binding;
|
|
|
|
u16 num_components;
|
|
|
|
u8 sgpr_base;
|
|
|
|
u8 dword_offset;
|
2024-06-22 16:50:20 +00:00
|
|
|
InstanceIdType instance_step_rate;
|
2024-05-25 12:33:15 +00:00
|
|
|
};
|
|
|
|
boost::container::static_vector<VsInput, 32> vs_inputs{};
|
|
|
|
|
|
|
|
struct PsInput {
|
|
|
|
u32 param_index;
|
|
|
|
bool is_default;
|
|
|
|
bool is_flat;
|
|
|
|
u32 default_value;
|
|
|
|
};
|
|
|
|
boost::container::static_vector<PsInput, 32> ps_inputs{};
|
|
|
|
|
|
|
|
struct AttributeFlags {
|
|
|
|
bool Get(IR::Attribute attrib, u32 comp = 0) const {
|
|
|
|
return flags[Index(attrib)] & (1 << comp);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool GetAny(IR::Attribute attrib) const {
|
|
|
|
return flags[Index(attrib)];
|
|
|
|
}
|
|
|
|
|
|
|
|
void Set(IR::Attribute attrib, u32 comp = 0) {
|
|
|
|
flags[Index(attrib)] |= (1 << comp);
|
|
|
|
}
|
|
|
|
|
|
|
|
u32 NumComponents(IR::Attribute attrib) const {
|
|
|
|
const u8 mask = flags[Index(attrib)];
|
|
|
|
ASSERT(mask != 0b1011 || mask != 0b1101);
|
|
|
|
return std::popcount(mask);
|
|
|
|
}
|
|
|
|
|
|
|
|
static size_t Index(IR::Attribute attrib) {
|
|
|
|
return static_cast<size_t>(attrib);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::array<u8, IR::NumAttributes> flags;
|
|
|
|
};
|
|
|
|
AttributeFlags loads{};
|
|
|
|
AttributeFlags stores{};
|
2024-07-04 21:15:44 +00:00
|
|
|
boost::container::static_vector<VsOutputMap, 3> vs_outputs;
|
2024-05-25 12:33:15 +00:00
|
|
|
|
2024-05-26 12:51:35 +00:00
|
|
|
BufferResourceList buffers;
|
2024-05-26 22:07:46 +00:00
|
|
|
ImageResourceList images;
|
|
|
|
SamplerResourceList samplers;
|
|
|
|
|
2024-05-28 22:28:34 +00:00
|
|
|
std::array<u32, 3> workgroup_size{};
|
|
|
|
|
|
|
|
u32 num_user_data;
|
2024-05-25 12:33:15 +00:00
|
|
|
std::span<const u32> user_data;
|
|
|
|
Stage stage;
|
|
|
|
|
2024-07-04 21:15:44 +00:00
|
|
|
uintptr_t pgm_base{};
|
|
|
|
u64 pgm_hash{};
|
|
|
|
u32 shared_memory_size{};
|
2024-06-10 19:35:14 +00:00
|
|
|
bool uses_group_quad{};
|
2024-07-04 21:15:44 +00:00
|
|
|
bool uses_shared_u8{};
|
|
|
|
bool uses_shared_u16{};
|
2024-06-16 21:45:39 +00:00
|
|
|
bool translation_failed{}; // indicates that shader has unsupported instructions
|
2024-06-10 19:35:14 +00:00
|
|
|
|
2024-05-25 12:33:15 +00:00
|
|
|
template <typename T>
|
|
|
|
T ReadUd(u32 ptr_index, u32 dword_offset) const noexcept {
|
|
|
|
T data;
|
2024-05-26 12:51:35 +00:00
|
|
|
const u32* base = user_data.data();
|
|
|
|
if (ptr_index != IR::NumScalarRegs) {
|
|
|
|
std::memcpy(&base, &user_data[ptr_index], sizeof(base));
|
|
|
|
}
|
2024-05-25 12:33:15 +00:00
|
|
|
std::memcpy(&data, base + dword_offset, sizeof(T));
|
|
|
|
return data;
|
|
|
|
}
|
2024-05-21 22:35:12 +00:00
|
|
|
};
|
|
|
|
|
2024-07-04 21:15:44 +00:00
|
|
|
constexpr AmdGpu::Buffer BufferResource::GetVsharp(const Info& info) const noexcept {
|
|
|
|
return inline_cbuf ? inline_cbuf : info.ReadUd<AmdGpu::Buffer>(sgpr_base, dword_offset);
|
|
|
|
}
|
|
|
|
|
2024-05-21 22:35:12 +00:00
|
|
|
} // namespace Shader
|
2024-05-26 12:51:35 +00:00
|
|
|
|
|
|
|
template <>
|
|
|
|
struct fmt::formatter<Shader::Stage> {
|
|
|
|
constexpr auto parse(format_parse_context& ctx) {
|
|
|
|
return ctx.begin();
|
|
|
|
}
|
|
|
|
auto format(const Shader::Stage& stage, format_context& ctx) const {
|
|
|
|
constexpr static std::array names = {"vs", "tc", "te", "gs", "fs", "cs"};
|
|
|
|
return fmt::format_to(ctx.out(), "{}", names[static_cast<size_t>(stage)]);
|
|
|
|
}
|
|
|
|
};
|