mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-28 22:06:59 +01:00
refactor(shader): preserve native wide shared operations
This commit is contained in:
@@ -168,42 +168,33 @@ ResourceKind DsMemoryKind(const Decoder::Instruction& decoded) {
|
||||
}
|
||||
|
||||
bool LowerDsRead(const Decoder::Instruction& decoded, BasicBlock& block, std::string* error) {
|
||||
const auto ir_op = DsReadOpcode(decoded);
|
||||
const auto count = decoded.data_bits == 32u ? decoded.data_dwords : 1u;
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
Instruction inst;
|
||||
inst.pc = decoded.pc;
|
||||
inst.op = ir_op;
|
||||
inst.src_count = 1;
|
||||
inst.memory = OffsetMemoryInfo(decoded, DsMemoryKind(decoded), i);
|
||||
if (!LowerRegisterOperand(OffsetDecodedRegister(decoded.dst, i), inst.dst, error) ||
|
||||
!LowerSourceOperand(decoded.src0, inst.src[0], error)) {
|
||||
return false;
|
||||
}
|
||||
block.instructions.push_back(inst);
|
||||
const auto ir_op = DsReadOpcode(decoded);
|
||||
Instruction inst;
|
||||
inst.pc = decoded.pc;
|
||||
inst.op = ir_op;
|
||||
inst.src_count = 1;
|
||||
inst.memory = MemoryInfoFromDecoded(decoded, DsMemoryKind(decoded));
|
||||
if (!LowerRegisterOperand(decoded.dst, inst.dst, error) ||
|
||||
!LowerSourceOperand(decoded.src0, inst.src[0], error)) {
|
||||
return false;
|
||||
}
|
||||
block.instructions.push_back(inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LowerDsRead2(const Decoder::Instruction& decoded, BasicBlock& block, uint32_t dwords_per_read,
|
||||
std::string* error) {
|
||||
const uint32_t offsets[] = {decoded.offset, decoded.secondary_offset};
|
||||
for (uint32_t read = 0; read < 2u; read++) {
|
||||
for (uint32_t dword = 0; dword < dwords_per_read; dword++) {
|
||||
const auto index = read * dwords_per_read + dword;
|
||||
Instruction inst;
|
||||
inst.pc = decoded.pc;
|
||||
inst.op = Opcode::DsReadB32;
|
||||
inst.src_count = 1;
|
||||
inst.memory =
|
||||
ByteOffsetMemoryInfo(decoded, DsMemoryKind(decoded), offsets[read] + dword * 4u);
|
||||
if (!LowerRegisterOperand(OffsetDecodedRegister(decoded.dst, index), inst.dst, error) ||
|
||||
!LowerSourceOperand(decoded.src0, inst.src[0], error)) {
|
||||
return false;
|
||||
}
|
||||
block.instructions.push_back(inst);
|
||||
}
|
||||
Instruction inst;
|
||||
inst.pc = decoded.pc;
|
||||
inst.op = Opcode::DsRead2B32;
|
||||
inst.src_count = 1;
|
||||
inst.memory = MemoryInfoFromDecoded(decoded, DsMemoryKind(decoded));
|
||||
inst.memory.data_dwords = dwords_per_read * 2u;
|
||||
if (!LowerRegisterOperand(decoded.dst, inst.dst, error) ||
|
||||
!LowerSourceOperand(decoded.src0, inst.src[0], error)) {
|
||||
return false;
|
||||
}
|
||||
block.instructions.push_back(inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -408,45 +399,36 @@ bool LowerFlatStore(const Decoder::Instruction& decoded, BasicBlock& block, std:
|
||||
}
|
||||
|
||||
bool LowerDsWrite(const Decoder::Instruction& decoded, BasicBlock& block, std::string* error) {
|
||||
const auto ir_op = DsWriteOpcode(decoded.data_bits);
|
||||
const auto count = decoded.data_bits == 32u ? decoded.data_dwords : 1u;
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
Instruction inst;
|
||||
inst.pc = decoded.pc;
|
||||
inst.op = ir_op;
|
||||
inst.src_count = 2;
|
||||
inst.memory = OffsetMemoryInfo(decoded, DsMemoryKind(decoded), i);
|
||||
inst.dst.kind = OperandKind::Null;
|
||||
if (!LowerSourceOperand(OffsetDecodedRegister(decoded.src1, i), inst.src[0], error) ||
|
||||
!LowerSourceOperand(decoded.src0, inst.src[1], error)) {
|
||||
return false;
|
||||
}
|
||||
block.instructions.push_back(inst);
|
||||
const auto ir_op = DsWriteOpcode(decoded.data_bits);
|
||||
Instruction inst;
|
||||
inst.pc = decoded.pc;
|
||||
inst.op = ir_op;
|
||||
inst.src_count = 2;
|
||||
inst.memory = MemoryInfoFromDecoded(decoded, DsMemoryKind(decoded));
|
||||
inst.dst.kind = OperandKind::Null;
|
||||
if (!LowerSourceOperand(decoded.src1, inst.src[0], error) ||
|
||||
!LowerSourceOperand(decoded.src0, inst.src[1], error)) {
|
||||
return false;
|
||||
}
|
||||
block.instructions.push_back(inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LowerDsWrite2(const Decoder::Instruction& decoded, BasicBlock& block,
|
||||
uint32_t dwords_per_write, std::string* error) {
|
||||
const Decoder::Operand* data[] = {&decoded.src1, &decoded.src2};
|
||||
const uint32_t offsets[] = {decoded.offset, decoded.secondary_offset};
|
||||
for (uint32_t write = 0; write < 2u; write++) {
|
||||
for (uint32_t dword = 0; dword < dwords_per_write; dword++) {
|
||||
Instruction inst;
|
||||
inst.pc = decoded.pc;
|
||||
inst.op = Opcode::DsWriteB32;
|
||||
inst.src_count = 2;
|
||||
inst.memory =
|
||||
ByteOffsetMemoryInfo(decoded, DsMemoryKind(decoded), offsets[write] + dword * 4u);
|
||||
inst.dst.kind = OperandKind::Null;
|
||||
if (!LowerSourceOperand(OffsetDecodedRegister(*data[write], dword), inst.src[0],
|
||||
error) ||
|
||||
!LowerSourceOperand(decoded.src0, inst.src[1], error)) {
|
||||
return false;
|
||||
}
|
||||
block.instructions.push_back(inst);
|
||||
}
|
||||
Instruction inst;
|
||||
inst.pc = decoded.pc;
|
||||
inst.op = Opcode::DsWrite2B32;
|
||||
inst.src_count = 3;
|
||||
inst.memory = MemoryInfoFromDecoded(decoded, DsMemoryKind(decoded));
|
||||
inst.memory.data_dwords = dwords_per_write * 2u;
|
||||
inst.dst.kind = OperandKind::Null;
|
||||
if (!LowerSourceOperand(decoded.src1, inst.src[0], error) ||
|
||||
!LowerSourceOperand(decoded.src0, inst.src[1], error) ||
|
||||
!LowerSourceOperand(decoded.src2, inst.src[2], error)) {
|
||||
return false;
|
||||
}
|
||||
block.instructions.push_back(inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -618,7 +600,8 @@ bool LowerMemoryInstruction(const Decoder::Instruction& decoded, BasicBlock& blo
|
||||
return LowerDsWriteAddtidB32(decoded, block, error);
|
||||
case Decoder::Opcode::DS_READ_ADDTID_B32:
|
||||
return LowerDsReadAddtidB32(decoded, block, error);
|
||||
case Decoder::Opcode::DS_READ2_B32: return LowerDsRead2(decoded, block, 1, error);
|
||||
case Decoder::Opcode::DS_READ2_B32:
|
||||
case Decoder::Opcode::DS_READ2ST64_B32: return LowerDsRead2(decoded, block, 1, error);
|
||||
case Decoder::Opcode::DS_READ2_B64:
|
||||
case Decoder::Opcode::DS_READ2ST64_B64: return LowerDsRead2(decoded, block, 2, error);
|
||||
case Decoder::Opcode::DS_READ_I8:
|
||||
@@ -765,6 +748,7 @@ bool IsMemoryOpcode(Decoder::Opcode opcode) {
|
||||
case Decoder::Opcode::DS_READ_I16:
|
||||
case Decoder::Opcode::DS_READ_U16:
|
||||
case Decoder::Opcode::DS_READ2_B32:
|
||||
case Decoder::Opcode::DS_READ2ST64_B32:
|
||||
case Decoder::Opcode::DS_READ_B32:
|
||||
case Decoder::Opcode::DS_READ_B64:
|
||||
case Decoder::Opcode::DS_READ2_B64:
|
||||
|
||||
@@ -31,8 +31,6 @@ std::string TypeName(Type type) {
|
||||
"AddressResource",
|
||||
"ImageResource",
|
||||
"SamplerResource",
|
||||
"LdsResource",
|
||||
"GdsResource",
|
||||
"ImageAddress",
|
||||
};
|
||||
const auto bits = static_cast<uint32_t>(type);
|
||||
|
||||
@@ -28,9 +28,7 @@ enum class Type : uint32_t {
|
||||
AddressResource = 1u << 18u,
|
||||
ImageResource = 1u << 19u,
|
||||
SamplerResource = 1u << 20u,
|
||||
LdsResource = 1u << 21u,
|
||||
GdsResource = 1u << 22u,
|
||||
ImageAddress = 1u << 23u,
|
||||
ImageAddress = 1u << 21u,
|
||||
};
|
||||
|
||||
constexpr Type operator|(Type lhs, Type rhs) {
|
||||
|
||||
@@ -338,6 +338,34 @@ bool ValidateValueProgram(const ValueProgram& program, bool require_ssa, std::st
|
||||
ValueOpcodeName(inst.GetOpcode())));
|
||||
}
|
||||
}
|
||||
const auto shared_components = SharedComponentCount(inst.GetOpcode());
|
||||
if (shared_components != 0u) {
|
||||
const auto memory_index = inst.Flags<MemoryFlags>().index;
|
||||
if (memory_index >= program.memory_info.size()) {
|
||||
return Fail(error, fmt::format("{} has an invalid memory-info index",
|
||||
ValueOpcodeName(inst.GetOpcode())));
|
||||
}
|
||||
const auto& memory = program.memory_info[memory_index];
|
||||
if ((memory.kind != ResourceKind::Lds && memory.kind != ResourceKind::Gds) ||
|
||||
memory.resource != 0u || memory.sampler != 0u || memory.component_count == 0u ||
|
||||
memory.component_index >= memory.component_count) {
|
||||
return Fail(error, fmt::format("{} has invalid shared-memory metadata",
|
||||
ValueOpcodeName(inst.GetOpcode())));
|
||||
}
|
||||
uint32_t expected_bits = 32u;
|
||||
if (inst.GetOpcode() == ValueOpcode::LoadSharedU8 ||
|
||||
inst.GetOpcode() == ValueOpcode::WriteSharedU8) {
|
||||
expected_bits = 8u;
|
||||
} else if (inst.GetOpcode() == ValueOpcode::LoadSharedU16 ||
|
||||
inst.GetOpcode() == ValueOpcode::WriteSharedU16) {
|
||||
expected_bits = 16u;
|
||||
}
|
||||
if (memory.data_bits != expected_bits || memory.data_dwords != shared_components ||
|
||||
(shared_components > 1u && memory.component_index != 0u)) {
|
||||
return Fail(error, fmt::format("{} has inconsistent shared-memory width",
|
||||
ValueOpcodeName(inst.GetOpcode())));
|
||||
}
|
||||
}
|
||||
uint32_t composite_components = 0u;
|
||||
switch (inst.GetOpcode()) {
|
||||
case ValueOpcode::CompositeExtractU32x2: composite_components = 2u; break;
|
||||
@@ -358,10 +386,11 @@ bool ValidateValueProgram(const ValueProgram& program, bool require_ssa, std::st
|
||||
ValueOpcodeName(inst.GetOpcode())));
|
||||
}
|
||||
if (fixed_signature && arg.GetType() != ArgTypeOf(inst.GetOpcode(), arg_index)) {
|
||||
return Fail(error, fmt::format("{} argument {} has type {}, expected {}",
|
||||
ValueOpcodeName(inst.GetOpcode()), arg_index,
|
||||
TypeName(arg.GetType()),
|
||||
TypeName(ArgTypeOf(inst.GetOpcode(), arg_index))));
|
||||
return Fail(error,
|
||||
fmt::format("{} argument {} has type {}, expected {}",
|
||||
ValueOpcodeName(inst.GetOpcode()), arg_index,
|
||||
TypeName(arg.GetType()),
|
||||
TypeName(ArgTypeOf(inst.GetOpcode(), arg_index))));
|
||||
}
|
||||
if (const auto* definition = arg.TryInstruction();
|
||||
definition != nullptr && !instructions.contains(definition)) {
|
||||
|
||||
@@ -392,19 +392,20 @@ constexpr LowerMap LOWER_OPS[] = {
|
||||
{Decoder::Opcode::DS_READ_U8, Opcode::DsReadUbyte},
|
||||
{Decoder::Opcode::DS_READ_I16, Opcode::DsReadSshort},
|
||||
{Decoder::Opcode::DS_READ_U16, Opcode::DsReadUshort},
|
||||
{Decoder::Opcode::DS_READ2_B32, Opcode::DsReadB32},
|
||||
{Decoder::Opcode::DS_READ2_B32, Opcode::DsRead2B32},
|
||||
{Decoder::Opcode::DS_READ2ST64_B32, Opcode::DsRead2B32},
|
||||
{Decoder::Opcode::DS_READ_B32, Opcode::DsReadB32},
|
||||
{Decoder::Opcode::DS_READ_B64, Opcode::DsReadB32},
|
||||
{Decoder::Opcode::DS_READ2_B64, Opcode::DsReadB32},
|
||||
{Decoder::Opcode::DS_READ2ST64_B64, Opcode::DsReadB32},
|
||||
{Decoder::Opcode::DS_READ2_B64, Opcode::DsRead2B32},
|
||||
{Decoder::Opcode::DS_READ2ST64_B64, Opcode::DsRead2B32},
|
||||
{Decoder::Opcode::DS_READ_B96, Opcode::DsReadB32},
|
||||
{Decoder::Opcode::DS_READ_B128, Opcode::DsReadB32},
|
||||
{Decoder::Opcode::DS_WRITE_B8, Opcode::DsWriteByte},
|
||||
{Decoder::Opcode::DS_WRITE_B16, Opcode::DsWriteShort},
|
||||
{Decoder::Opcode::DS_WRITE2_B32, Opcode::DsWriteB32},
|
||||
{Decoder::Opcode::DS_WRITE2ST64_B32, Opcode::DsWriteB32},
|
||||
{Decoder::Opcode::DS_WRITE2_B64, Opcode::DsWriteB32},
|
||||
{Decoder::Opcode::DS_WRITE2ST64_B64, Opcode::DsWriteB32},
|
||||
{Decoder::Opcode::DS_WRITE2_B32, Opcode::DsWrite2B32},
|
||||
{Decoder::Opcode::DS_WRITE2ST64_B32, Opcode::DsWrite2B32},
|
||||
{Decoder::Opcode::DS_WRITE2_B64, Opcode::DsWrite2B32},
|
||||
{Decoder::Opcode::DS_WRITE2ST64_B64, Opcode::DsWrite2B32},
|
||||
{Decoder::Opcode::DS_WRITE_B32, Opcode::DsWriteB32},
|
||||
{Decoder::Opcode::DS_WRITE_B64, Opcode::DsWriteB32},
|
||||
{Decoder::Opcode::DS_WRITE_B96, Opcode::DsWriteB32},
|
||||
|
||||
@@ -331,9 +331,11 @@ IR_OPCODE(DsReadSbyte, General, Memory)
|
||||
IR_OPCODE(DsReadUshort, General, Memory)
|
||||
IR_OPCODE(DsReadSshort, General, Memory)
|
||||
IR_OPCODE(DsReadB32, General, Memory)
|
||||
IR_OPCODE(DsRead2B32, General, Memory)
|
||||
IR_OPCODE(DsWriteByte, General, Memory)
|
||||
IR_OPCODE(DsWriteShort, General, Memory)
|
||||
IR_OPCODE(DsWriteB32, General, Memory)
|
||||
IR_OPCODE(DsWrite2B32, General, Memory)
|
||||
IR_OPCODE(DsMinF32, General, Memory)
|
||||
IR_OPCODE(DsMaxF32, General, Memory)
|
||||
IR_OPCODE(DsSwizzleB32, General, Memory)
|
||||
|
||||
@@ -42,8 +42,6 @@ constexpr Type BufferResource = Type::BufferResource;
|
||||
constexpr Type AddressResource = Type::AddressResource;
|
||||
constexpr Type ImageResource = Type::ImageResource;
|
||||
constexpr Type SamplerResource = Type::SamplerResource;
|
||||
constexpr Type LdsResource = Type::LdsResource;
|
||||
constexpr Type GdsResource = Type::GdsResource;
|
||||
constexpr Type ImageAddress = Type::ImageAddress;
|
||||
|
||||
constexpr std::array<OpcodeMeta, static_cast<size_t>(ValueOpcode::Count)> MetaTable = {{
|
||||
@@ -76,52 +74,23 @@ bool HasSideEffects(ValueOpcode opcode) {
|
||||
if (buffer_access == BufferAccess::Write || buffer_access == BufferAccess::Atomic) {
|
||||
return true;
|
||||
}
|
||||
const auto shared_access = SharedAccessOf(opcode);
|
||||
if (shared_access == SharedAccess::Write || shared_access == SharedAccess::Atomic ||
|
||||
shared_access == SharedAccess::Append || shared_access == SharedAccess::Consume) {
|
||||
return true;
|
||||
}
|
||||
switch (opcode) {
|
||||
case ValueOpcode::Reference:
|
||||
case ValueOpcode::ReferenceU32:
|
||||
case ValueOpcode::StoreAddressU8:
|
||||
case ValueOpcode::StoreAddressU16:
|
||||
case ValueOpcode::StoreAddressU32:
|
||||
case ValueOpcode::WriteSharedU8:
|
||||
case ValueOpcode::WriteSharedU16:
|
||||
case ValueOpcode::WriteSharedU32:
|
||||
case ValueOpcode::WriteGdsU8:
|
||||
case ValueOpcode::WriteGdsU16:
|
||||
case ValueOpcode::WriteGdsU32:
|
||||
case ValueOpcode::SharedAtomicFMin32:
|
||||
case ValueOpcode::SharedAtomicFMax32:
|
||||
case ValueOpcode::GdsAtomicFMin32:
|
||||
case ValueOpcode::GdsAtomicFMax32:
|
||||
case ValueOpcode::SharedAtomicSwap32:
|
||||
case ValueOpcode::SharedAtomicIAdd32:
|
||||
case ValueOpcode::SharedAtomicISub32:
|
||||
case ValueOpcode::SharedAtomicSMin32:
|
||||
case ValueOpcode::SharedAtomicUMin32:
|
||||
case ValueOpcode::SharedAtomicSMax32:
|
||||
case ValueOpcode::SharedAtomicUMax32:
|
||||
case ValueOpcode::SharedAtomicAnd32:
|
||||
case ValueOpcode::SharedAtomicOr32:
|
||||
case ValueOpcode::SharedAtomicXor32:
|
||||
case ValueOpcode::GdsAtomicSwap32:
|
||||
case ValueOpcode::GdsAtomicIAdd32:
|
||||
case ValueOpcode::GdsAtomicISub32:
|
||||
case ValueOpcode::GdsAtomicSMin32:
|
||||
case ValueOpcode::GdsAtomicUMin32:
|
||||
case ValueOpcode::GdsAtomicSMax32:
|
||||
case ValueOpcode::GdsAtomicUMax32:
|
||||
case ValueOpcode::GdsAtomicAnd32:
|
||||
case ValueOpcode::GdsAtomicOr32:
|
||||
case ValueOpcode::GdsAtomicXor32:
|
||||
case ValueOpcode::ImageAtomicIAdd32:
|
||||
case ValueOpcode::ImageAtomicUMin32:
|
||||
case ValueOpcode::ImageAtomicUMax32:
|
||||
case ValueOpcode::ImageAtomicAnd32:
|
||||
case ValueOpcode::ImageAtomicOr32:
|
||||
case ValueOpcode::ImageAtomicXor32:
|
||||
case ValueOpcode::DataAppend:
|
||||
case ValueOpcode::DataConsume:
|
||||
case ValueOpcode::GdsDataAppend:
|
||||
case ValueOpcode::GdsDataConsume:
|
||||
case ValueOpcode::ImageWrite:
|
||||
case ValueOpcode::SetAttribute:
|
||||
case ValueOpcode::Barrier: return true;
|
||||
@@ -172,4 +141,48 @@ uint32_t BufferComponentCount(ValueOpcode opcode) {
|
||||
}
|
||||
}
|
||||
|
||||
SharedAccess SharedAccessOf(ValueOpcode opcode) {
|
||||
switch (opcode) {
|
||||
case ValueOpcode::LoadSharedU8:
|
||||
case ValueOpcode::LoadSharedU16:
|
||||
case ValueOpcode::LoadSharedU32:
|
||||
case ValueOpcode::LoadSharedU32x2:
|
||||
case ValueOpcode::LoadSharedU32x3:
|
||||
case ValueOpcode::LoadSharedU32x4: return SharedAccess::Read;
|
||||
case ValueOpcode::WriteSharedU8:
|
||||
case ValueOpcode::WriteSharedU16:
|
||||
case ValueOpcode::WriteSharedU32:
|
||||
case ValueOpcode::WriteSharedU32x2:
|
||||
case ValueOpcode::WriteSharedU32x3:
|
||||
case ValueOpcode::WriteSharedU32x4: return SharedAccess::Write;
|
||||
case ValueOpcode::SharedAtomicFMin32:
|
||||
case ValueOpcode::SharedAtomicFMax32:
|
||||
case ValueOpcode::SharedAtomicSwap32:
|
||||
case ValueOpcode::SharedAtomicIAdd32:
|
||||
case ValueOpcode::SharedAtomicISub32:
|
||||
case ValueOpcode::SharedAtomicSMin32:
|
||||
case ValueOpcode::SharedAtomicUMin32:
|
||||
case ValueOpcode::SharedAtomicSMax32:
|
||||
case ValueOpcode::SharedAtomicUMax32:
|
||||
case ValueOpcode::SharedAtomicAnd32:
|
||||
case ValueOpcode::SharedAtomicOr32:
|
||||
case ValueOpcode::SharedAtomicXor32: return SharedAccess::Atomic;
|
||||
case ValueOpcode::DataAppend: return SharedAccess::Append;
|
||||
case ValueOpcode::DataConsume: return SharedAccess::Consume;
|
||||
default: return SharedAccess::None;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t SharedComponentCount(ValueOpcode opcode) {
|
||||
switch (opcode) {
|
||||
case ValueOpcode::LoadSharedU32x2:
|
||||
case ValueOpcode::WriteSharedU32x2: return 2u;
|
||||
case ValueOpcode::LoadSharedU32x3:
|
||||
case ValueOpcode::WriteSharedU32x3: return 3u;
|
||||
case ValueOpcode::LoadSharedU32x4:
|
||||
case ValueOpcode::WriteSharedU32x4: return 4u;
|
||||
default: return SharedAccessOf(opcode) == SharedAccess::None ? 0u : 1u;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Libs::Graphics::ShaderRecompiler::IR
|
||||
|
||||
@@ -17,6 +17,7 @@ enum class ValueOpcode {
|
||||
};
|
||||
|
||||
enum class BufferAccess { None, Read, Write, Atomic };
|
||||
enum class SharedAccess { None, Read, Write, Atomic, Append, Consume };
|
||||
|
||||
struct DppMoveFlags {
|
||||
uint16_t control = 0;
|
||||
@@ -56,6 +57,8 @@ static_assert(std::is_trivially_copyable_v<ExportFlags>);
|
||||
[[nodiscard]] bool HasSideEffects(ValueOpcode opcode);
|
||||
[[nodiscard]] BufferAccess BufferAccessOf(ValueOpcode opcode);
|
||||
[[nodiscard]] uint32_t BufferComponentCount(ValueOpcode opcode);
|
||||
[[nodiscard]] SharedAccess SharedAccessOf(ValueOpcode opcode);
|
||||
[[nodiscard]] uint32_t SharedComponentCount(ValueOpcode opcode);
|
||||
[[nodiscard]] std::string_view ValueOpcodeName(ValueOpcode opcode);
|
||||
|
||||
} // namespace Libs::Graphics::ShaderRecompiler::IR
|
||||
|
||||
@@ -202,8 +202,6 @@ VALUE_OPCODE(GetBufferResource, BufferResource, U32, U32, U32, U32)
|
||||
VALUE_OPCODE(GetAddressResource, AddressResource, U32, U32)
|
||||
VALUE_OPCODE(GetImageResource, ImageResource, U32, U32, U32, U32, U32, U32, U32, U32)
|
||||
VALUE_OPCODE(GetSamplerResource, SamplerResource, U32, U32, U32, U32)
|
||||
VALUE_OPCODE(GetLdsResource, LdsResource)
|
||||
VALUE_OPCODE(GetGdsResource, GdsResource)
|
||||
VALUE_OPCODE(MakeImageAddress, ImageAddress, U32, U32, U32, U32, U32, U32, U32, U32, U32, U32, U32,
|
||||
U32, U32)
|
||||
|
||||
@@ -240,46 +238,32 @@ VALUE_OPCODE(BufferAtomicXor32, U32, BufferResource, U32, U32, U32, U32, U1)
|
||||
VALUE_OPCODE(BufferAtomicFMin32, U32, BufferResource, U32, U32, U32, U32, U1)
|
||||
VALUE_OPCODE(BufferAtomicFMax32, U32, BufferResource, U32, U32, U32, U32, U1)
|
||||
|
||||
VALUE_OPCODE(LoadSharedU8, U8, LdsResource, U32, U1)
|
||||
VALUE_OPCODE(LoadSharedU16, U16, LdsResource, U32, U1)
|
||||
VALUE_OPCODE(LoadSharedU32, U32, LdsResource, U32, U1)
|
||||
VALUE_OPCODE(WriteSharedU8, Void, LdsResource, U32, U8, U1)
|
||||
VALUE_OPCODE(WriteSharedU16, Void, LdsResource, U32, U16, U1)
|
||||
VALUE_OPCODE(WriteSharedU32, Void, LdsResource, U32, U32, U1)
|
||||
VALUE_OPCODE(LoadGdsU8, U8, GdsResource, U32, U1)
|
||||
VALUE_OPCODE(LoadGdsU16, U16, GdsResource, U32, U1)
|
||||
VALUE_OPCODE(LoadGdsU32, U32, GdsResource, U32, U1)
|
||||
VALUE_OPCODE(WriteGdsU8, Void, GdsResource, U32, U8, U1)
|
||||
VALUE_OPCODE(WriteGdsU16, Void, GdsResource, U32, U16, U1)
|
||||
VALUE_OPCODE(WriteGdsU32, Void, GdsResource, U32, U32, U1)
|
||||
VALUE_OPCODE(SharedAtomicFMin32, Void, LdsResource, U32, U32, U32, U1)
|
||||
VALUE_OPCODE(SharedAtomicFMax32, Void, LdsResource, U32, U32, U32, U1)
|
||||
VALUE_OPCODE(GdsAtomicFMin32, Void, GdsResource, U32, U32, U32, U1)
|
||||
VALUE_OPCODE(GdsAtomicFMax32, Void, GdsResource, U32, U32, U32, U1)
|
||||
VALUE_OPCODE(SharedAtomicSwap32, U32, LdsResource, U32, U32, U1)
|
||||
VALUE_OPCODE(SharedAtomicIAdd32, U32, LdsResource, U32, U32, U1)
|
||||
VALUE_OPCODE(SharedAtomicISub32, U32, LdsResource, U32, U32, U1)
|
||||
VALUE_OPCODE(SharedAtomicSMin32, U32, LdsResource, U32, U32, U1)
|
||||
VALUE_OPCODE(SharedAtomicUMin32, U32, LdsResource, U32, U32, U1)
|
||||
VALUE_OPCODE(SharedAtomicSMax32, U32, LdsResource, U32, U32, U1)
|
||||
VALUE_OPCODE(SharedAtomicUMax32, U32, LdsResource, U32, U32, U1)
|
||||
VALUE_OPCODE(SharedAtomicAnd32, U32, LdsResource, U32, U32, U1)
|
||||
VALUE_OPCODE(SharedAtomicOr32, U32, LdsResource, U32, U32, U1)
|
||||
VALUE_OPCODE(SharedAtomicXor32, U32, LdsResource, U32, U32, U1)
|
||||
VALUE_OPCODE(GdsAtomicSwap32, U32, GdsResource, U32, U32, U1)
|
||||
VALUE_OPCODE(GdsAtomicIAdd32, U32, GdsResource, U32, U32, U1)
|
||||
VALUE_OPCODE(GdsAtomicISub32, U32, GdsResource, U32, U32, U1)
|
||||
VALUE_OPCODE(GdsAtomicSMin32, U32, GdsResource, U32, U32, U1)
|
||||
VALUE_OPCODE(GdsAtomicUMin32, U32, GdsResource, U32, U32, U1)
|
||||
VALUE_OPCODE(GdsAtomicSMax32, U32, GdsResource, U32, U32, U1)
|
||||
VALUE_OPCODE(GdsAtomicUMax32, U32, GdsResource, U32, U32, U1)
|
||||
VALUE_OPCODE(GdsAtomicAnd32, U32, GdsResource, U32, U32, U1)
|
||||
VALUE_OPCODE(GdsAtomicOr32, U32, GdsResource, U32, U32, U1)
|
||||
VALUE_OPCODE(GdsAtomicXor32, U32, GdsResource, U32, U32, U1)
|
||||
VALUE_OPCODE(DataAppend, U32, LdsResource, U32, U1, U32, U32)
|
||||
VALUE_OPCODE(DataConsume, U32, LdsResource, U32, U1, U32, U32)
|
||||
VALUE_OPCODE(GdsDataAppend, U32, GdsResource, U32, U1, U32, U32)
|
||||
VALUE_OPCODE(GdsDataConsume, U32, GdsResource, U32, U1, U32, U32)
|
||||
VALUE_OPCODE(LoadSharedU8, U8, U32, U1)
|
||||
VALUE_OPCODE(LoadSharedU16, U16, U32, U1)
|
||||
VALUE_OPCODE(LoadSharedU32, U32, U32, U1)
|
||||
VALUE_OPCODE(LoadSharedU32x2, U32x2, U32, U1)
|
||||
VALUE_OPCODE(LoadSharedU32x3, U32x3, U32, U1)
|
||||
VALUE_OPCODE(LoadSharedU32x4, U32x4, U32, U1)
|
||||
VALUE_OPCODE(WriteSharedU8, Void, U32, U8, U1)
|
||||
VALUE_OPCODE(WriteSharedU16, Void, U32, U16, U1)
|
||||
VALUE_OPCODE(WriteSharedU32, Void, U32, U32, U1)
|
||||
VALUE_OPCODE(WriteSharedU32x2, Void, U32, U32, U32, U1)
|
||||
VALUE_OPCODE(WriteSharedU32x3, Void, U32, U32, U32, U32, U1)
|
||||
VALUE_OPCODE(WriteSharedU32x4, Void, U32, U32, U32, U32, U32, U1)
|
||||
VALUE_OPCODE(SharedAtomicFMin32, Void, U32, U32, U32, U1)
|
||||
VALUE_OPCODE(SharedAtomicFMax32, Void, U32, U32, U32, U1)
|
||||
VALUE_OPCODE(SharedAtomicSwap32, U32, U32, U32, U1)
|
||||
VALUE_OPCODE(SharedAtomicIAdd32, U32, U32, U32, U1)
|
||||
VALUE_OPCODE(SharedAtomicISub32, U32, U32, U32, U1)
|
||||
VALUE_OPCODE(SharedAtomicSMin32, U32, U32, U32, U1)
|
||||
VALUE_OPCODE(SharedAtomicUMin32, U32, U32, U32, U1)
|
||||
VALUE_OPCODE(SharedAtomicSMax32, U32, U32, U32, U1)
|
||||
VALUE_OPCODE(SharedAtomicUMax32, U32, U32, U32, U1)
|
||||
VALUE_OPCODE(SharedAtomicAnd32, U32, U32, U32, U1)
|
||||
VALUE_OPCODE(SharedAtomicOr32, U32, U32, U32, U1)
|
||||
VALUE_OPCODE(SharedAtomicXor32, U32, U32, U32, U1)
|
||||
VALUE_OPCODE(DataAppend, U32, U32, U1, U32, U32)
|
||||
VALUE_OPCODE(DataConsume, U32, U32, U1, U32, U32)
|
||||
VALUE_OPCODE(SwizzleU32, U32, U32, U32, U1)
|
||||
|
||||
VALUE_OPCODE(ImageQueryDimensions, U32x4, ImageResource, ImageAddress)
|
||||
|
||||
@@ -115,20 +115,25 @@ void AddBinding(BindingLayout& layout, DescriptorBindingKind kind,
|
||||
{kind, static_cast<uint32_t>(layout.descriptors.size()), std::move(resources)});
|
||||
}
|
||||
|
||||
bool UsesGds(const Program& program) {
|
||||
bool UsesGds(const Program& program, bool& uses_gds) {
|
||||
uses_gds = false;
|
||||
for (const auto* block: program.values->blocks) {
|
||||
for (const auto& inst: *block) {
|
||||
if (inst.GetOpcode() == ValueOpcode::GetGdsResource && inst.HasUses()) {
|
||||
return true;
|
||||
if (SharedAccessOf(inst.GetOpcode()) == SharedAccess::None) {
|
||||
continue;
|
||||
}
|
||||
for (size_t index = 0; index < inst.NumArgs(); index++) {
|
||||
if (inst.Arg(index).GetType() == Type::GdsResource) {
|
||||
return true;
|
||||
}
|
||||
const auto index = inst.Flags<MemoryFlags>().index;
|
||||
if (index >= program.values->memory_info.size()) {
|
||||
return false;
|
||||
}
|
||||
const auto kind = program.values->memory_info[index].kind;
|
||||
if (kind != ResourceKind::Lds && kind != ResourceKind::Gds) {
|
||||
return false;
|
||||
}
|
||||
uses_gds |= kind == ResourceKind::Gds;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -220,7 +225,14 @@ bool AllocateBindings(Program& program, const BindingLayoutOptions& options, std
|
||||
}
|
||||
AddBinding(next, DescriptorBindingKind::Samplers, std::move(resources));
|
||||
}
|
||||
if (UsesGds(program)) {
|
||||
bool uses_gds = false;
|
||||
if (!UsesGds(program, uses_gds)) {
|
||||
if (error != nullptr) {
|
||||
*error = "typed shader contains invalid shared-memory metadata";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (uses_gds) {
|
||||
AddBinding(next, DescriptorBindingKind::Gds);
|
||||
}
|
||||
if (!program.info.addresses.empty()) {
|
||||
|
||||
Reference in New Issue
Block a user