mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-28 13:56:59 +01:00
shader: decode buffer formats once
This commit is contained in:
@@ -238,28 +238,13 @@ constexpr BufferFormatInfo GetFormatInfo(Prospero::BufferFormat format) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr bool IsKnownFormat(Prospero::BufferFormat format) {
|
constexpr uint32_t GetFormatComponentByteOffset(const BufferFormatInfo& info, uint32_t component) {
|
||||||
return GetFormatInfo(format).type != ComponentType::Unknown;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr uint32_t GetFormatComponentCount(Prospero::BufferFormat format) {
|
|
||||||
return GetFormatInfo(format).component_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr uint32_t GetFormatComponentByteOffset(Prospero::BufferFormat format, uint32_t component) {
|
|
||||||
const auto info = GetFormatInfo(format);
|
|
||||||
if (component >= info.component_count) {
|
if (component >= info.component_count) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return info.packed_bitfield ? 0u : info.component_bit_offset[component] / 8u;
|
return info.packed_bitfield ? 0u : info.component_bit_offset[component] / 8u;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr bool CanUseTypedBufferLoad(Prospero::BufferFormat format) {
|
|
||||||
const auto info = GetFormatInfo(format);
|
|
||||||
return info.type != ComponentType::Unknown && !info.packed_bitfield &&
|
|
||||||
info.component_bits[0] == 32u;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Libs::Graphics::ShaderRecompiler::Format
|
} // namespace Libs::Graphics::ShaderRecompiler::Format
|
||||||
|
|
||||||
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_SHADER_RECOMPILER_BUFFERFORMAT_H_ */
|
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_SHADER_RECOMPILER_BUFFERFORMAT_H_ */
|
||||||
|
|||||||
@@ -365,15 +365,14 @@ uint32_t LoadSubword(ValueEmitContext& ctx, const IR::Inst& inst, IR::MemoryInfo
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Prospero::BufferFormat BufferFormat(const ValueEmitContext& ctx, const IR::Inst& inst,
|
Prospero::BufferFormat BufferFormat(const ValueEmitContext& ctx, const IR::MemoryInfo& mem) {
|
||||||
const IR::MemoryInfo& mem) {
|
|
||||||
return mem.typed ? Format::DecodeTBufferFormat(mem.data_format, mem.number_format)
|
return mem.typed ? Format::DecodeTBufferFormat(mem.data_format, mem.number_format)
|
||||||
: StorageBufferFormat(ctx.state, mem);
|
: StorageBufferFormat(ctx.state, mem);
|
||||||
}
|
}
|
||||||
|
|
||||||
IR::MemoryInfo RebaseFormattedComponent(IR::MemoryInfo mem, Prospero::BufferFormat format,
|
IR::MemoryInfo RebaseFormattedComponent(IR::MemoryInfo mem, const Format::BufferFormatInfo& info,
|
||||||
uint32_t component) {
|
uint32_t component) {
|
||||||
mem.offset += Format::GetFormatComponentByteOffset(format, component);
|
mem.offset += Format::GetFormatComponentByteOffset(info, component);
|
||||||
mem.data_dwords = 1u;
|
mem.data_dwords = 1u;
|
||||||
mem.component_index = component;
|
mem.component_index = component;
|
||||||
return mem;
|
return mem;
|
||||||
@@ -414,7 +413,7 @@ uint32_t FormattedConstant(ValueEmitContext& ctx, const Format::BufferFormatInfo
|
|||||||
|
|
||||||
template <typename LoadWordFn, typename LoadSubwordFn>
|
template <typename LoadWordFn, typename LoadSubwordFn>
|
||||||
uint32_t LoadFormattedComponent(ValueEmitContext& ctx, const IR::MemoryInfo& mem,
|
uint32_t LoadFormattedComponent(ValueEmitContext& ctx, const IR::MemoryInfo& mem,
|
||||||
Prospero::BufferFormat format, const Format::BufferFormatInfo& info,
|
const Format::BufferFormatInfo& info,
|
||||||
uint32_t output_component, LoadWordFn&& load_word,
|
uint32_t output_component, LoadWordFn&& load_word,
|
||||||
LoadSubwordFn&& load_subword) {
|
LoadSubwordFn&& load_subword) {
|
||||||
const auto source = ResolveFormattedSource(ctx, mem, info, output_component);
|
const auto source = ResolveFormattedSource(ctx, mem, info, output_component);
|
||||||
@@ -449,19 +448,18 @@ uint32_t LoadFormattedComponent(ValueEmitContext& ctx, const IR::MemoryInfo& mem
|
|||||||
uint32_t FormattedLoadPrepared(ValueEmitContext& ctx, const IR::Inst& inst,
|
uint32_t FormattedLoadPrepared(ValueEmitContext& ctx, const IR::Inst& inst,
|
||||||
const IR::MemoryInfo& mem, uint32_t output_component,
|
const IR::MemoryInfo& mem, uint32_t output_component,
|
||||||
const MemoryResourceAccess& resource) {
|
const MemoryResourceAccess& resource) {
|
||||||
const auto format = BufferFormat(ctx, inst, mem);
|
const auto info = Format::GetFormatInfo(BufferFormat(ctx, mem));
|
||||||
if (!Format::IsKnownFormat(format)) {
|
if (info.type == Format::ComponentType::Unknown) {
|
||||||
return LoadWordPrepared(ctx, inst, RebaseRawComponent(mem, output_component), resource);
|
return LoadWordPrepared(ctx, inst, RebaseRawComponent(mem, output_component), resource);
|
||||||
}
|
}
|
||||||
const auto info = Format::GetFormatInfo(format);
|
|
||||||
return LoadFormattedComponent(
|
return LoadFormattedComponent(
|
||||||
ctx, mem, format, info, output_component,
|
ctx, mem, info, output_component,
|
||||||
[&](uint32_t component) {
|
[&](uint32_t component) {
|
||||||
return LoadWordPrepared(ctx, inst, RebaseFormattedComponent(mem, format, component),
|
return LoadWordPrepared(ctx, inst, RebaseFormattedComponent(mem, info, component),
|
||||||
resource);
|
resource);
|
||||||
},
|
},
|
||||||
[&](uint32_t component, uint32_t bits, bool sign_extend) {
|
[&](uint32_t component, uint32_t bits, bool sign_extend) {
|
||||||
return LoadSubwordPrepared(ctx, inst, RebaseFormattedComponent(mem, format, component),
|
return LoadSubwordPrepared(ctx, inst, RebaseFormattedComponent(mem, info, component),
|
||||||
resource, bits, sign_extend);
|
resource, bits, sign_extend);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -548,15 +546,14 @@ void StoreWord(ValueEmitContext& ctx, const IR::Inst& inst, IR::MemoryInfo mem)
|
|||||||
void FormattedStorePrepared(ValueEmitContext& ctx, const IR::Inst& inst, const IR::MemoryInfo& mem,
|
void FormattedStorePrepared(ValueEmitContext& ctx, const IR::Inst& inst, const IR::MemoryInfo& mem,
|
||||||
uint32_t component, const MemoryResourceAccess& resource,
|
uint32_t component, const MemoryResourceAccess& resource,
|
||||||
uint32_t data) {
|
uint32_t data) {
|
||||||
const auto format = BufferFormat(ctx, inst, mem);
|
const auto info = Format::GetFormatInfo(BufferFormat(ctx, mem));
|
||||||
if (!Format::IsKnownFormat(format)) {
|
if (info.type == Format::ComponentType::Unknown) {
|
||||||
StoreWordPrepared(ctx, inst, RebaseRawComponent(mem, component), resource, data);
|
StoreWordPrepared(ctx, inst, RebaseRawComponent(mem, component), resource, data);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto info = Format::GetFormatInfo(format);
|
|
||||||
if (component >= info.component_count) return;
|
if (component >= info.component_count) return;
|
||||||
const auto bits = info.component_bits[component];
|
const auto bits = info.component_bits[component];
|
||||||
const auto component_mem = RebaseFormattedComponent(mem, format, component);
|
const auto component_mem = RebaseFormattedComponent(mem, info, component);
|
||||||
if (bits == 8u || bits == 16u) {
|
if (bits == 8u || bits == 16u) {
|
||||||
StoreSubwordPrepared(ctx, inst, component_mem, resource, bits, data);
|
StoreSubwordPrepared(ctx, inst, component_mem, resource, bits, data);
|
||||||
} else {
|
} else {
|
||||||
@@ -781,7 +778,6 @@ uint32_t AppendConsume(ValueEmitContext& ctx, const IR::Inst& inst, bool append)
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct PreparedFormattedMemory {
|
struct PreparedFormattedMemory {
|
||||||
Prospero::BufferFormat format = Prospero::BufferFormat::kInvalid;
|
|
||||||
Format::BufferFormatInfo info;
|
Format::BufferFormatInfo info;
|
||||||
MemoryResourceAccess resource;
|
MemoryResourceAccess resource;
|
||||||
std::array<uint32_t, 4> addresses {};
|
std::array<uint32_t, 4> addresses {};
|
||||||
@@ -794,10 +790,10 @@ enum class FormattedAccess { Load, Store };
|
|||||||
PreparedFormattedMemory PrepareFormattedMemory(ValueEmitContext& ctx, const IR::Inst& inst,
|
PreparedFormattedMemory PrepareFormattedMemory(ValueEmitContext& ctx, const IR::Inst& inst,
|
||||||
const IR::MemoryInfo& mem,
|
const IR::MemoryInfo& mem,
|
||||||
const MemoryResourceAccess& resource,
|
const MemoryResourceAccess& resource,
|
||||||
|
const Format::BufferFormatInfo& info,
|
||||||
uint32_t components, FormattedAccess access) {
|
uint32_t components, FormattedAccess access) {
|
||||||
PreparedFormattedMemory plan;
|
PreparedFormattedMemory plan;
|
||||||
plan.format = BufferFormat(ctx, inst, mem);
|
plan.info = info;
|
||||||
plan.info = Format::GetFormatInfo(plan.format);
|
|
||||||
plan.resource = resource;
|
plan.resource = resource;
|
||||||
std::array<bool, 4> required_components {};
|
std::array<bool, 4> required_components {};
|
||||||
if (access == FormattedAccess::Load) {
|
if (access == FormattedAccess::Load) {
|
||||||
@@ -816,11 +812,11 @@ PreparedFormattedMemory PrepareFormattedMemory(ValueEmitContext& ctx, const IR::
|
|||||||
bool first_bound = true;
|
bool first_bound = true;
|
||||||
for (uint32_t component = 0; component < plan.info.component_count; component++) {
|
for (uint32_t component = 0; component < plan.info.component_count; component++) {
|
||||||
if (!required_components[component]) continue;
|
if (!required_components[component]) continue;
|
||||||
const auto byte_offset = Format::GetFormatComponentByteOffset(plan.format, component);
|
const auto byte_offset = Format::GetFormatComponentByteOffset(plan.info, component);
|
||||||
bool reused = false;
|
bool reused = false;
|
||||||
for (uint32_t previous = 0; previous < component; previous++) {
|
for (uint32_t previous = 0; previous < component; previous++) {
|
||||||
if (required_components[previous] &&
|
if (required_components[previous] &&
|
||||||
Format::GetFormatComponentByteOffset(plan.format, previous) == byte_offset) {
|
Format::GetFormatComponentByteOffset(plan.info, previous) == byte_offset) {
|
||||||
plan.addresses[component] = plan.addresses[previous];
|
plan.addresses[component] = plan.addresses[previous];
|
||||||
plan.indices[component] = plan.indices[previous];
|
plan.indices[component] = plan.indices[previous];
|
||||||
reused = true;
|
reused = true;
|
||||||
@@ -828,7 +824,7 @@ PreparedFormattedMemory PrepareFormattedMemory(ValueEmitContext& ctx, const IR::
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (reused) continue;
|
if (reused) continue;
|
||||||
const auto component_mem = RebaseFormattedComponent(mem, plan.format, component);
|
const auto component_mem = RebaseFormattedComponent(mem, plan.info, component);
|
||||||
plan.addresses[component] = ByteAddress(ctx, inst, component_mem);
|
plan.addresses[component] = ByteAddress(ctx, inst, component_mem);
|
||||||
const auto raw_index = Binary(ctx.state, OpShiftRightLogical, TypeU32(ctx.state),
|
const auto raw_index = Binary(ctx.state, OpShiftRightLogical, TypeU32(ctx.state),
|
||||||
plan.addresses[component], ConstantU32(ctx.state, 2));
|
plan.addresses[component], ConstantU32(ctx.state, 2));
|
||||||
@@ -849,7 +845,7 @@ PreparedFormattedMemory PrepareFormattedMemory(ValueEmitContext& ctx, const IR::
|
|||||||
uint32_t LoadFormattedInBounds(ValueEmitContext& ctx, const IR::MemoryInfo& mem,
|
uint32_t LoadFormattedInBounds(ValueEmitContext& ctx, const IR::MemoryInfo& mem,
|
||||||
const PreparedFormattedMemory& plan, uint32_t output_component) {
|
const PreparedFormattedMemory& plan, uint32_t output_component) {
|
||||||
return LoadFormattedComponent(
|
return LoadFormattedComponent(
|
||||||
ctx, mem, plan.format, plan.info, output_component,
|
ctx, mem, plan.info, output_component,
|
||||||
[&](uint32_t component) {
|
[&](uint32_t component) {
|
||||||
return LoadWordInBounds(ctx, plan.resource, plan.indices[component]);
|
return LoadWordInBounds(ctx, plan.resource, plan.indices[component]);
|
||||||
},
|
},
|
||||||
@@ -898,10 +894,10 @@ uint32_t LoadWideBuffer(ValueEmitContext& ctx, const IR::Inst& inst, uint32_t co
|
|||||||
ConstantU32CompositeZero(state, components), [&]() {
|
ConstantU32CompositeZero(state, components), [&]() {
|
||||||
const auto mem = ctx.Memory(inst);
|
const auto mem = ctx.Memory(inst);
|
||||||
const auto resource = PrepareMemoryResourceAccess(state, mem);
|
const auto resource = PrepareMemoryResourceAccess(state, mem);
|
||||||
const auto format =
|
const auto info = Format::GetFormatInfo(
|
||||||
mem.formatted ? BufferFormat(ctx, inst, mem) : Prospero::BufferFormat::kInvalid;
|
mem.formatted ? BufferFormat(ctx, mem) : Prospero::BufferFormat::kInvalid);
|
||||||
if (Format::IsKnownFormat(format)) {
|
if (info.type != Format::ComponentType::Unknown) {
|
||||||
const auto plan = PrepareFormattedMemory(ctx, inst, mem, resource, components,
|
const auto plan = PrepareFormattedMemory(ctx, inst, mem, resource, info, components,
|
||||||
FormattedAccess::Load);
|
FormattedAccess::Load);
|
||||||
return EmitValueOrDefaultIfCondition(
|
return EmitValueOrDefaultIfCondition(
|
||||||
state, plan.in_bounds, TypeU32Composite(state, components),
|
state, plan.in_bounds, TypeU32Composite(state, components),
|
||||||
@@ -928,10 +924,10 @@ void StoreWideBuffer(ValueEmitContext& ctx, const IR::Inst& inst, uint32_t compo
|
|||||||
const auto mem = ctx.Memory(inst);
|
const auto mem = ctx.Memory(inst);
|
||||||
const auto resource = PrepareMemoryResourceAccess(state, mem);
|
const auto resource = PrepareMemoryResourceAccess(state, mem);
|
||||||
const auto composite = ctx.Arg(inst, inst.NumArgs() - 2);
|
const auto composite = ctx.Arg(inst, inst.NumArgs() - 2);
|
||||||
const auto format =
|
const auto info = Format::GetFormatInfo(
|
||||||
mem.formatted ? BufferFormat(ctx, inst, mem) : Prospero::BufferFormat::kInvalid;
|
mem.formatted ? BufferFormat(ctx, mem) : Prospero::BufferFormat::kInvalid);
|
||||||
if (Format::IsKnownFormat(format)) {
|
if (info.type != Format::ComponentType::Unknown) {
|
||||||
const auto plan = PrepareFormattedMemory(ctx, inst, mem, resource, components,
|
const auto plan = PrepareFormattedMemory(ctx, inst, mem, resource, info, components,
|
||||||
FormattedAccess::Store);
|
FormattedAccess::Store);
|
||||||
EmitIfCondition(state, plan.in_bounds, [&]() {
|
EmitIfCondition(state, plan.in_bounds, [&]() {
|
||||||
for (uint32_t component = 0; component < components; component++) {
|
for (uint32_t component = 0; component < components; component++) {
|
||||||
|
|||||||
Reference in New Issue
Block a user