mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-21 03:16:54 +02:00
refactor(shader): centralize typed resource metadata
This commit is contained in:
@@ -13,51 +13,6 @@ using ShaderError::Fail;
|
||||
|
||||
namespace {
|
||||
|
||||
bool ImageBinding(const IR::ImageResource& image, IR::DescriptorBindingKind& kind) {
|
||||
using Kind = IR::DescriptorBindingKind;
|
||||
using Dim = Decoder::ImageDimension;
|
||||
if (image.kind == IR::ResourceKind::Image || image.kind == IR::ResourceKind::ImageUint) {
|
||||
const bool integer = image.kind == IR::ResourceKind::ImageUint;
|
||||
switch (image.dimension) {
|
||||
case Dim::Dim1D: kind = integer ? Kind::SampledUint1D : Kind::Sampled1D; return true;
|
||||
case Dim::Dim1DArray:
|
||||
kind = integer ? Kind::SampledUint1DArray : Kind::Sampled1DArray;
|
||||
return true;
|
||||
case Dim::Dim2D: kind = integer ? Kind::SampledUint2D : Kind::Sampled2D; return true;
|
||||
case Dim::Dim2DMsaa:
|
||||
kind = integer ? Kind::SampledUint2DMsaa : Kind::Sampled2DMsaa;
|
||||
return true;
|
||||
case Dim::Dim3D: kind = integer ? Kind::SampledUint3D : Kind::Sampled3D; return true;
|
||||
case Dim::Dim2DArray:
|
||||
kind = integer ? Kind::SampledUint2DArray : Kind::Sampled2DArray;
|
||||
return true;
|
||||
case Dim::Dim2DMsaaArray:
|
||||
kind = integer ? Kind::SampledUint2DMsaaArray : Kind::Sampled2DMsaaArray;
|
||||
return true;
|
||||
case Dim::Unknown: return false;
|
||||
}
|
||||
}
|
||||
const bool uint_image = image.kind == IR::ResourceKind::StorageImageUint;
|
||||
if (image.kind != IR::ResourceKind::StorageImage && !uint_image) {
|
||||
return false;
|
||||
}
|
||||
switch (image.dimension) {
|
||||
case Dim::Dim1D: kind = uint_image ? Kind::StorageUint1D : Kind::Storage1D; return true;
|
||||
case Dim::Dim1DArray:
|
||||
kind = uint_image ? Kind::StorageUint1DArray : Kind::Storage1DArray;
|
||||
return true;
|
||||
case Dim::Dim2D: kind = uint_image ? Kind::StorageUint2D : Kind::Storage2D; return true;
|
||||
case Dim::Dim3D: kind = uint_image ? Kind::StorageUint3D : Kind::Storage3D; return true;
|
||||
case Dim::Dim2DArray:
|
||||
kind = uint_image ? Kind::StorageUint2DArray : Kind::Storage2DArray;
|
||||
return true;
|
||||
case Dim::Dim2DMsaa:
|
||||
case Dim::Dim2DMsaaArray: return false;
|
||||
case Dim::Unknown: return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ValidateNativeProgram(const IR::Program& program, std::string* error) {
|
||||
using Kind = IR::DescriptorBindingKind;
|
||||
constexpr auto KindCount = static_cast<size_t>(Kind::Count);
|
||||
@@ -79,18 +34,18 @@ bool ValidateNativeProgram(const IR::Program& program, std::string* error) {
|
||||
Expect(Kind::Buffers, Dense(program.info.buffers.size()));
|
||||
}
|
||||
for (uint32_t i = 0; i < program.info.images.size(); i++) {
|
||||
Kind kind;
|
||||
if (!ImageBinding(program.info.images[i], kind)) {
|
||||
const auto kind = IR::DescriptorBindingForImage(program.info.images[i]);
|
||||
if (!kind.has_value()) {
|
||||
return Fail(error, "native shader plan has an invalid image class");
|
||||
}
|
||||
present[static_cast<size_t>(kind)] = true;
|
||||
present[static_cast<size_t>(*kind)] = true;
|
||||
const auto dynamic = program.info.images[i].mip_mode == IR::ImageMipMode::DynamicStorage;
|
||||
const auto count = dynamic ? program.info.images[i].mip_count : 1u;
|
||||
if (count == 0u || (!dynamic && program.info.images[i].mip_count != 1u)) {
|
||||
return Fail(error, "native shader plan has an invalid image mip descriptor count");
|
||||
}
|
||||
expected[static_cast<size_t>(kind)].insert(expected[static_cast<size_t>(kind)].end(), count,
|
||||
i);
|
||||
expected[static_cast<size_t>(*kind)].insert(expected[static_cast<size_t>(*kind)].end(),
|
||||
count, i);
|
||||
}
|
||||
if (!program.info.samplers.empty()) {
|
||||
Expect(Kind::Samplers, Dense(program.info.samplers.size()));
|
||||
|
||||
@@ -520,13 +520,6 @@ bool EmitValueAlu(ValueEmitContext& ctx, const IR::Inst& inst) {
|
||||
case IR::ValueOpcode::FindUMsb64:
|
||||
ctx.Define(inst, EmitFindMsb64(state, ctx.Arg(inst, 0)));
|
||||
return true;
|
||||
case IR::ValueOpcode::FindSMsb32: {
|
||||
const auto value =
|
||||
EmitExt(state, TypeI32(state), 74u,
|
||||
{NewUnary(state, OpBitcast, TypeI32(state), ctx.Arg(inst, 0))});
|
||||
ctx.Define(inst, NewUnary(state, OpBitcast, TypeU32(state), value));
|
||||
return true;
|
||||
}
|
||||
case IR::ValueOpcode::SMin32:
|
||||
ctx.Define(inst, EmitMinMaxI32Value(state, ctx.Arg(inst, 0), ctx.Arg(inst, 1), false));
|
||||
return true;
|
||||
@@ -591,26 +584,6 @@ bool EmitValueAlu(ValueEmitContext& ctx, const IR::Inst& inst) {
|
||||
ctx.Define(inst, CompareOrdered64(state, ctx.Arg(inst, 0), ctx.Arg(inst, 1),
|
||||
OpUGreaterThan, OpUGreaterThan));
|
||||
return true;
|
||||
case IR::ValueOpcode::SGreaterThan64:
|
||||
ctx.Define(inst, CompareOrdered64(state, ctx.Arg(inst, 0), ctx.Arg(inst, 1),
|
||||
OpSGreaterThan, OpUGreaterThan));
|
||||
return true;
|
||||
case IR::ValueOpcode::ULessThanEqual64:
|
||||
ctx.Define(inst, CompareOrdered64(state, ctx.Arg(inst, 0), ctx.Arg(inst, 1),
|
||||
OpULessThan, OpULessThanEqual));
|
||||
return true;
|
||||
case IR::ValueOpcode::SLessThanEqual64:
|
||||
ctx.Define(inst, CompareOrdered64(state, ctx.Arg(inst, 0), ctx.Arg(inst, 1),
|
||||
OpSLessThan, OpULessThanEqual));
|
||||
return true;
|
||||
case IR::ValueOpcode::UGreaterThanEqual64:
|
||||
ctx.Define(inst, CompareOrdered64(state, ctx.Arg(inst, 0), ctx.Arg(inst, 1),
|
||||
OpUGreaterThan, OpUGreaterThanEqual));
|
||||
return true;
|
||||
case IR::ValueOpcode::SGreaterThanEqual64:
|
||||
ctx.Define(inst, CompareOrdered64(state, ctx.Arg(inst, 0), ctx.Arg(inst, 1),
|
||||
OpSGreaterThan, OpUGreaterThanEqual));
|
||||
return true;
|
||||
case IR::ValueOpcode::LogicalOr: return binary(OpLogicalOr, IR::Type::U1);
|
||||
case IR::ValueOpcode::LogicalAnd: return binary(OpLogicalAnd, IR::Type::U1);
|
||||
case IR::ValueOpcode::LogicalXor: return binary(OpLogicalNotEqual, IR::Type::U1);
|
||||
|
||||
@@ -363,8 +363,7 @@ void EmitExport(ValueEmitContext& ctx, const IR::Inst& inst) {
|
||||
bool EmitValueFlow(ValueEmitContext& ctx, const IR::Inst& inst) {
|
||||
auto& state = ctx.state;
|
||||
switch (inst.GetOpcode()) {
|
||||
case IR::ValueOpcode::Identity:
|
||||
case IR::ValueOpcode::ConditionRef: ctx.Define(inst, ctx.Arg(inst, 0)); return true;
|
||||
case IR::ValueOpcode::Identity: ctx.Define(inst, ctx.Arg(inst, 0)); return true;
|
||||
case IR::ValueOpcode::Void:
|
||||
case IR::ValueOpcode::Reference:
|
||||
case IR::ValueOpcode::ReferenceU32:
|
||||
|
||||
@@ -345,8 +345,9 @@ uint32_t ImageAtomicOpcode(IR::ValueOpcode opcode) {
|
||||
} // namespace
|
||||
|
||||
bool EmitValueImage(ValueEmitContext& ctx, const IR::Inst& inst) {
|
||||
const auto op = inst.GetOpcode();
|
||||
if (op < IR::ValueOpcode::ImageQueryDimensions || op > IR::ValueOpcode::ImageAtomicXor32) {
|
||||
const auto op = inst.GetOpcode();
|
||||
const auto image_info = IR::ImageOpcodeInfoOf(op);
|
||||
if (image_info.access == IR::ImageAccess::None) {
|
||||
return false;
|
||||
}
|
||||
auto& state = ctx.state;
|
||||
@@ -354,10 +355,7 @@ bool EmitValueImage(ValueEmitContext& ctx, const IR::Inst& inst) {
|
||||
const auto pc = inst.Flags<IR::MemoryFlags>().pc;
|
||||
const auto image_arg = inst.Arg(0);
|
||||
ctx.ResourceIndex(image_arg, IR::ValueOpcode::GetImageResource);
|
||||
const bool sampled = op == IR::ValueOpcode::ImageQueryLod ||
|
||||
op == IR::ValueOpcode::ImageSampleRaw ||
|
||||
op == IR::ValueOpcode::ImageGatherRaw;
|
||||
const auto* address = ctx.ImageAddress(inst.Arg(sampled ? 2 : 1));
|
||||
const auto* address = ctx.ImageAddress(inst.Arg(image_info.needs_sampler ? 2 : 1));
|
||||
if (address == nullptr) return true;
|
||||
if (op == IR::ValueOpcode::ImageQueryDimensions) {
|
||||
state.builder.RequireCapability(CapabilityImageQuery);
|
||||
@@ -392,7 +390,8 @@ bool EmitValueImage(ValueEmitContext& ctx, const IR::Inst& inst) {
|
||||
ctx.Define(
|
||||
inst,
|
||||
EmitValueOrDefaultIfCondition(
|
||||
state, condition, TypeU32Vector(state, 4), ConstantU32CompositeZero(state, 4), [&]() {
|
||||
state, condition, TypeU32Vector(state, 4), ConstantU32CompositeZero(state, 4),
|
||||
[&]() {
|
||||
const auto image = LoadSampledImageDescriptor(state, mem, pc, view);
|
||||
const auto color = state.builder.AllocateId();
|
||||
const auto coord = CoordU32(ctx, mem, *address, view);
|
||||
|
||||
@@ -867,10 +867,9 @@ uint32_t LoadWideShared(ValueEmitContext& ctx, const IR::Inst& inst, uint32_t co
|
||||
const auto base = ByteAddress(ctx, inst, mem);
|
||||
std::array<uint32_t, 4> values {};
|
||||
for (uint32_t component = 0; component < components; component++) {
|
||||
const auto address = component == 0u
|
||||
? base
|
||||
: Binary(state, OpIAdd, TypeU32(state), base,
|
||||
ConstantU32(state, component * 4u));
|
||||
const auto address = component == 0u ? base
|
||||
: Binary(state, OpIAdd, TypeU32(state), base,
|
||||
ConstantU32(state, component * 4u));
|
||||
const auto raw_index = Binary(state, OpShiftRightLogical, TypeU32(state), address,
|
||||
ConstantU32(state, 2));
|
||||
const auto access = PrepareMemoryElement(ctx, mem, resource, raw_index);
|
||||
@@ -889,10 +888,9 @@ void StoreWideShared(ValueEmitContext& ctx, const IR::Inst& inst, uint32_t compo
|
||||
const auto resource = PrepareMemoryResourceAccess(state, mem);
|
||||
const auto base = ByteAddress(ctx, inst, mem);
|
||||
for (uint32_t component = 0; component < components; component++) {
|
||||
const auto address = component == 0u
|
||||
? base
|
||||
: Binary(state, OpIAdd, TypeU32(state), base,
|
||||
ConstantU32(state, component * 4u));
|
||||
const auto address = component == 0u ? base
|
||||
: Binary(state, OpIAdd, TypeU32(state), base,
|
||||
ConstantU32(state, component * 4u));
|
||||
const auto raw_index =
|
||||
Binary(state, OpShiftRightLogical, TypeU32(state), address, ConstantU32(state, 2));
|
||||
const auto access = PrepareMemoryElement(ctx, mem, resource, raw_index);
|
||||
@@ -963,13 +961,12 @@ bool EmitValueMemory(ValueEmitContext& ctx, const IR::Inst& inst) {
|
||||
}));
|
||||
return true;
|
||||
}
|
||||
const bool load_address = op == IR::ValueOpcode::LoadAddressU8 ||
|
||||
op == IR::ValueOpcode::LoadAddressU16 ||
|
||||
op == IR::ValueOpcode::LoadAddressU32;
|
||||
const auto address_info = IR::AddressOpcodeInfoOf(op);
|
||||
const bool load_address = address_info.access == IR::AddressAccess::Read;
|
||||
const bool load_buffer = op == IR::ValueOpcode::LoadBufferU8 ||
|
||||
op == IR::ValueOpcode::LoadBufferU16 ||
|
||||
op == IR::ValueOpcode::LoadBufferU32;
|
||||
const bool load_shared = IR::SharedAccessOf(op) == IR::SharedAccess::Read;
|
||||
const bool load_shared = IR::SharedAccessOf(op) == IR::SharedAccess::Read;
|
||||
if (load_address || load_buffer || load_shared) {
|
||||
const auto mem = ctx.Memory(inst);
|
||||
uint32_t value = 0;
|
||||
@@ -986,13 +983,11 @@ bool EmitValueMemory(ValueEmitContext& ctx, const IR::Inst& inst) {
|
||||
ctx.Define(inst, value);
|
||||
return true;
|
||||
}
|
||||
const bool store_address = op == IR::ValueOpcode::StoreAddressU8 ||
|
||||
op == IR::ValueOpcode::StoreAddressU16 ||
|
||||
op == IR::ValueOpcode::StoreAddressU32;
|
||||
const bool store_address = address_info.access == IR::AddressAccess::Write;
|
||||
const bool store_buffer = op == IR::ValueOpcode::StoreBufferU8 ||
|
||||
op == IR::ValueOpcode::StoreBufferU16 ||
|
||||
op == IR::ValueOpcode::StoreBufferU32;
|
||||
const bool store_shared = IR::SharedAccessOf(op) == IR::SharedAccess::Write;
|
||||
const bool store_shared = IR::SharedAccessOf(op) == IR::SharedAccess::Write;
|
||||
if (store_address || store_buffer || store_shared) {
|
||||
const auto mem = ctx.Memory(inst);
|
||||
if (op == IR::ValueOpcode::StoreBufferU32 && mem.formatted)
|
||||
|
||||
Reference in New Issue
Block a user