refactor(shader): simplify buffer access emission

This commit is contained in:
nmzik
2026-08-19 06:32:47 +02:00
parent 49145c1902
commit 3ea2099245
12 changed files with 474 additions and 474 deletions
@@ -71,15 +71,16 @@ std::string_view ValueOpcodeName(ValueOpcode opcode) {
}
bool HasSideEffects(ValueOpcode opcode) {
const auto buffer_access = BufferAccessOf(opcode);
if (buffer_access == BufferAccess::Write || buffer_access == BufferAccess::Atomic) {
return true;
}
switch (opcode) {
case ValueOpcode::Reference:
case ValueOpcode::ReferenceU32:
case ValueOpcode::StoreAddressU8:
case ValueOpcode::StoreAddressU16:
case ValueOpcode::StoreAddressU32:
case ValueOpcode::StoreBufferU8:
case ValueOpcode::StoreBufferU16:
case ValueOpcode::StoreBufferU32:
case ValueOpcode::WriteSharedU8:
case ValueOpcode::WriteSharedU16:
case ValueOpcode::WriteSharedU32:
@@ -110,18 +111,6 @@ bool HasSideEffects(ValueOpcode opcode) {
case ValueOpcode::GdsAtomicAnd32:
case ValueOpcode::GdsAtomicOr32:
case ValueOpcode::GdsAtomicXor32:
case ValueOpcode::BufferAtomicSwap32:
case ValueOpcode::BufferAtomicIAdd32:
case ValueOpcode::BufferAtomicISub32:
case ValueOpcode::BufferAtomicSMin32:
case ValueOpcode::BufferAtomicUMin32:
case ValueOpcode::BufferAtomicSMax32:
case ValueOpcode::BufferAtomicUMax32:
case ValueOpcode::BufferAtomicAnd32:
case ValueOpcode::BufferAtomicOr32:
case ValueOpcode::BufferAtomicXor32:
case ValueOpcode::BufferAtomicFMin32:
case ValueOpcode::BufferAtomicFMax32:
case ValueOpcode::ImageAtomicIAdd32:
case ValueOpcode::ImageAtomicUMin32:
case ValueOpcode::ImageAtomicUMax32:
@@ -139,4 +128,29 @@ bool HasSideEffects(ValueOpcode opcode) {
}
}
BufferAccess BufferAccessOf(ValueOpcode opcode) {
switch (opcode) {
case ValueOpcode::ReadConstBuffer:
case ValueOpcode::LoadBufferU8:
case ValueOpcode::LoadBufferU16:
case ValueOpcode::LoadBufferU32: return BufferAccess::Read;
case ValueOpcode::StoreBufferU8:
case ValueOpcode::StoreBufferU16:
case ValueOpcode::StoreBufferU32: return BufferAccess::Write;
case ValueOpcode::BufferAtomicSwap32:
case ValueOpcode::BufferAtomicIAdd32:
case ValueOpcode::BufferAtomicISub32:
case ValueOpcode::BufferAtomicSMin32:
case ValueOpcode::BufferAtomicUMin32:
case ValueOpcode::BufferAtomicSMax32:
case ValueOpcode::BufferAtomicUMax32:
case ValueOpcode::BufferAtomicAnd32:
case ValueOpcode::BufferAtomicOr32:
case ValueOpcode::BufferAtomicXor32:
case ValueOpcode::BufferAtomicFMin32:
case ValueOpcode::BufferAtomicFMax32: return BufferAccess::Atomic;
default: return BufferAccess::None;
}
}
} // namespace Libs::Graphics::ShaderRecompiler::IR
@@ -16,6 +16,8 @@ enum class ValueOpcode {
Count,
};
enum class BufferAccess { None, Read, Write, Atomic };
struct DppMoveFlags {
uint16_t control = 0;
uint8_t row_mask = 0xf;
@@ -52,6 +54,7 @@ static_assert(std::is_trivially_copyable_v<ExportFlags>);
[[nodiscard]] Type ArgTypeOf(ValueOpcode opcode, size_t index);
[[nodiscard]] size_t NumArgsOf(ValueOpcode opcode);
[[nodiscard]] bool HasSideEffects(ValueOpcode opcode);
[[nodiscard]] BufferAccess BufferAccessOf(ValueOpcode opcode);
[[nodiscard]] std::string_view ValueOpcodeName(ValueOpcode opcode);
} // namespace Libs::Graphics::ShaderRecompiler::IR
@@ -25,46 +25,6 @@ const char* StageName(ShaderType stage) {
}
}
bool IsBufferAtomic(ValueOpcode op) {
switch (op) {
case ValueOpcode::BufferAtomicSwap32:
case ValueOpcode::BufferAtomicIAdd32:
case ValueOpcode::BufferAtomicISub32:
case ValueOpcode::BufferAtomicSMin32:
case ValueOpcode::BufferAtomicUMin32:
case ValueOpcode::BufferAtomicSMax32:
case ValueOpcode::BufferAtomicUMax32:
case ValueOpcode::BufferAtomicAnd32:
case ValueOpcode::BufferAtomicOr32:
case ValueOpcode::BufferAtomicXor32:
case ValueOpcode::BufferAtomicFMin32:
case ValueOpcode::BufferAtomicFMax32: return true;
default: return false;
}
}
bool IsBufferStore(ValueOpcode op) {
switch (op) {
case ValueOpcode::StoreBufferU8:
case ValueOpcode::StoreBufferU16:
case ValueOpcode::StoreBufferU32: return true;
default: return IsBufferAtomic(op);
}
}
bool IsBuffer(ValueOpcode op) {
switch (op) {
case ValueOpcode::ReadConstBuffer:
case ValueOpcode::LoadBufferU8:
case ValueOpcode::LoadBufferU16:
case ValueOpcode::LoadBufferU32:
case ValueOpcode::StoreBufferU8:
case ValueOpcode::StoreBufferU16:
case ValueOpcode::StoreBufferU32: return true;
default: return IsBufferAtomic(op);
}
}
bool IsAddressStore(ValueOpcode op) {
switch (op) {
case ValueOpcode::StoreAddressU8:
@@ -393,7 +353,8 @@ private:
for (const auto* block: m_values.blocks) {
for (const auto& inst: *block) {
const auto op = inst.GetOpcode();
if ((!IsBuffer(op) && !IsAddress(op) && !IsImage(op)) || &inst == &owner) {
if ((BufferAccessOf(op) == BufferAccess::None && !IsAddress(op) && !IsImage(op)) ||
&inst == &owner) {
continue;
}
if (inst.Flags<MemoryFlags>().index == index) {
@@ -669,8 +630,9 @@ private:
static void Merge(BufferResource& resource, const MemoryInfo& memory, ValueOpcode op,
uint32_t pc) {
const bool atomic = IsBufferAtomic(op);
const bool write = IsBufferStore(op);
const auto access = BufferAccessOf(op);
const bool atomic = access == BufferAccess::Atomic;
const bool write = access == BufferAccess::Write || atomic;
resource.first_use_pc = std::min(resource.first_use_pc, pc);
resource.max_byte_extent = std::max(resource.max_byte_extent, ByteExtent(memory));
resource.read = resource.read || !write || atomic;
@@ -813,7 +775,7 @@ private:
bool Collect(Inst& inst, std::string* error) {
const auto op = inst.GetOpcode();
if (!IsBuffer(op) && !IsAddress(op) && !IsImage(op)) {
if (BufferAccessOf(op) == BufferAccess::None && !IsAddress(op) && !IsImage(op)) {
return true;
}
const auto flags = inst.Flags<MemoryFlags>();
@@ -832,7 +794,7 @@ private:
uint32_t source = 0;
uint32_t resource = 0;
if (IsBuffer(op)) {
if (BufferAccessOf(op) != BufferAccess::None) {
if (!GetHandle(inst.Arg(0), ValueOpcode::GetBufferResource, 4, flags.pc, handle, source,
error)) {
return false;