shader: Address Feedback
This commit is contained in:
parent
45d547af11
commit
baec84247f
|
@ -510,7 +510,8 @@ void EmitContext::DefineOutputs(const Info& info) {
|
||||||
const Id type{TypeArray(F32[1], Constant(U32[1], 8U))};
|
const Id type{TypeArray(F32[1], Constant(U32[1], 8U))};
|
||||||
clip_distances = DefineOutput(*this, type, spv::BuiltIn::ClipDistance);
|
clip_distances = DefineOutput(*this, type, spv::BuiltIn::ClipDistance);
|
||||||
}
|
}
|
||||||
if (info.stores_viewport_index && !ignore_viewport_layer) {
|
if (info.stores_viewport_index &&
|
||||||
|
(profile.support_viewport_index_layer_non_geometry || stage == Shader::Stage::Geometry)) {
|
||||||
if (stage == Stage::Fragment) {
|
if (stage == Stage::Fragment) {
|
||||||
throw NotImplementedException("Storing ViewportIndex in Fragment stage");
|
throw NotImplementedException("Storing ViewportIndex in Fragment stage");
|
||||||
}
|
}
|
||||||
|
|
|
@ -134,8 +134,6 @@ public:
|
||||||
|
|
||||||
std::vector<Id> interfaces;
|
std::vector<Id> interfaces;
|
||||||
|
|
||||||
bool ignore_viewport_layer{};
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void DefineCommonTypes(const Info& info);
|
void DefineCommonTypes(const Info& info);
|
||||||
void DefineCommonConstants();
|
void DefineCommonConstants();
|
||||||
|
|
|
@ -228,11 +228,9 @@ void SetupCapabilities(const Profile& profile, const Info& info, EmitContext& ct
|
||||||
if (info.stores_viewport_index) {
|
if (info.stores_viewport_index) {
|
||||||
ctx.AddCapability(spv::Capability::MultiViewport);
|
ctx.AddCapability(spv::Capability::MultiViewport);
|
||||||
if (profile.support_viewport_index_layer_non_geometry &&
|
if (profile.support_viewport_index_layer_non_geometry &&
|
||||||
ctx.stage == Shader::Stage::VertexB) {
|
ctx.stage != Shader::Stage::Geometry) {
|
||||||
ctx.AddExtension("SPV_EXT_shader_viewport_index_layer");
|
ctx.AddExtension("SPV_EXT_shader_viewport_index_layer");
|
||||||
ctx.AddCapability(spv::Capability::ShaderViewportIndexLayerEXT);
|
ctx.AddCapability(spv::Capability::ShaderViewportIndexLayerEXT);
|
||||||
} else {
|
|
||||||
ctx.ignore_viewport_layer = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!profile.support_vertex_instance_id && (info.loads_instance_id || info.loads_vertex_id)) {
|
if (!profile.support_vertex_instance_id && (info.loads_instance_id || info.loads_vertex_id)) {
|
||||||
|
|
|
@ -28,7 +28,9 @@ void EmitSelectionMerge(EmitContext& ctx, Id merge_label);
|
||||||
void EmitReturn(EmitContext& ctx);
|
void EmitReturn(EmitContext& ctx);
|
||||||
void EmitUnreachable(EmitContext& ctx);
|
void EmitUnreachable(EmitContext& ctx);
|
||||||
void EmitDemoteToHelperInvocation(EmitContext& ctx, Id continue_label);
|
void EmitDemoteToHelperInvocation(EmitContext& ctx, Id continue_label);
|
||||||
void EmitMemoryBarrier(EmitContext& ctx, IR::Inst* inst);
|
void EmitMemoryBarrierWorkgroupLevel(EmitContext& ctx);
|
||||||
|
void EmitMemoryBarrierDeviceLevel(EmitContext& ctx);
|
||||||
|
void EmitMemoryBarrierSystemLevel(EmitContext& ctx);
|
||||||
void EmitPrologue(EmitContext& ctx);
|
void EmitPrologue(EmitContext& ctx);
|
||||||
void EmitEpilogue(EmitContext& ctx);
|
void EmitEpilogue(EmitContext& ctx);
|
||||||
void EmitGetRegister(EmitContext& ctx);
|
void EmitGetRegister(EmitContext& ctx);
|
||||||
|
@ -60,14 +62,6 @@ void EmitSetZFlag(EmitContext& ctx);
|
||||||
void EmitSetSFlag(EmitContext& ctx);
|
void EmitSetSFlag(EmitContext& ctx);
|
||||||
void EmitSetCFlag(EmitContext& ctx);
|
void EmitSetCFlag(EmitContext& ctx);
|
||||||
void EmitSetOFlag(EmitContext& ctx);
|
void EmitSetOFlag(EmitContext& ctx);
|
||||||
void EmitGetFCSMFlag(EmitContext& ctx);
|
|
||||||
void EmitGetTAFlag(EmitContext& ctx);
|
|
||||||
void EmitGetTRFlag(EmitContext& ctx);
|
|
||||||
void EmitGetMXFlag(EmitContext& ctx);
|
|
||||||
void EmitSetFCSMFlag(EmitContext& ctx);
|
|
||||||
void EmitSetTAFlag(EmitContext& ctx);
|
|
||||||
void EmitSetTRFlag(EmitContext& ctx);
|
|
||||||
void EmitSetMXFlag(EmitContext& ctx);
|
|
||||||
Id EmitWorkgroupId(EmitContext& ctx);
|
Id EmitWorkgroupId(EmitContext& ctx);
|
||||||
Id EmitLocalInvocationId(EmitContext& ctx);
|
Id EmitLocalInvocationId(EmitContext& ctx);
|
||||||
Id EmitLoadLocal(EmitContext& ctx, Id word_offset);
|
Id EmitLoadLocal(EmitContext& ctx, Id word_offset);
|
||||||
|
|
|
@ -7,34 +7,27 @@
|
||||||
|
|
||||||
namespace Shader::Backend::SPIRV {
|
namespace Shader::Backend::SPIRV {
|
||||||
namespace {
|
namespace {
|
||||||
spv::Scope MemoryScopeToSpirVScope(IR::MemoryScope scope) {
|
void EmitMemoryBarrierImpl(EmitContext& ctx, spv::Scope scope) {
|
||||||
switch (scope) {
|
|
||||||
case IR::MemoryScope::Warp:
|
|
||||||
return spv::Scope::Subgroup;
|
|
||||||
case IR::MemoryScope::Workgroup:
|
|
||||||
return spv::Scope::Workgroup;
|
|
||||||
case IR::MemoryScope::Device:
|
|
||||||
return spv::Scope::Device;
|
|
||||||
case IR::MemoryScope::System:
|
|
||||||
return spv::Scope::CrossDevice;
|
|
||||||
case IR::MemoryScope::DontCare:
|
|
||||||
return spv::Scope::Invocation;
|
|
||||||
default:
|
|
||||||
throw NotImplementedException("Unknown memory scope!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
void EmitMemoryBarrier(EmitContext& ctx, IR::Inst* inst) {
|
|
||||||
const auto info{inst->Flags<IR::BarrierInstInfo>()};
|
|
||||||
const auto semantics =
|
const auto semantics =
|
||||||
spv::MemorySemanticsMask::AcquireRelease | spv::MemorySemanticsMask::UniformMemory |
|
spv::MemorySemanticsMask::AcquireRelease | spv::MemorySemanticsMask::UniformMemory |
|
||||||
spv::MemorySemanticsMask::WorkgroupMemory | spv::MemorySemanticsMask::AtomicCounterMemory |
|
spv::MemorySemanticsMask::WorkgroupMemory | spv::MemorySemanticsMask::AtomicCounterMemory |
|
||||||
spv::MemorySemanticsMask::ImageMemory;
|
spv::MemorySemanticsMask::ImageMemory;
|
||||||
const auto scope = MemoryScopeToSpirVScope(info.scope);
|
|
||||||
ctx.OpMemoryBarrier(ctx.Constant(ctx.U32[1], static_cast<u32>(scope)),
|
ctx.OpMemoryBarrier(ctx.Constant(ctx.U32[1], static_cast<u32>(scope)),
|
||||||
ctx.Constant(ctx.U32[1], static_cast<u32>(semantics)));
|
ctx.Constant(ctx.U32[1], static_cast<u32>(semantics)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // Anonymous namespace
|
||||||
|
|
||||||
|
void EmitMemoryBarrierWorkgroupLevel(EmitContext& ctx) {
|
||||||
|
EmitMemoryBarrierImpl(ctx, spv::Scope::Workgroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitMemoryBarrierDeviceLevel(EmitContext& ctx) {
|
||||||
|
EmitMemoryBarrierImpl(ctx, spv::Scope::Device);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitMemoryBarrierSystemLevel(EmitContext& ctx) {
|
||||||
|
EmitMemoryBarrierImpl(ctx, spv::Scope::CrossDevice);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Shader::Backend::SPIRV
|
} // namespace Shader::Backend::SPIRV
|
||||||
|
|
|
@ -58,7 +58,10 @@ std::optional<Id> OutputAttrPointer(EmitContext& ctx, IR::Attribute attr) {
|
||||||
return ctx.OpAccessChain(ctx.output_f32, ctx.clip_distances, clip_num);
|
return ctx.OpAccessChain(ctx.output_f32, ctx.clip_distances, clip_num);
|
||||||
}
|
}
|
||||||
case IR::Attribute::ViewportIndex:
|
case IR::Attribute::ViewportIndex:
|
||||||
return ctx.ignore_viewport_layer ? std::nullopt : std::optional<Id>{ctx.viewport_index};
|
return (ctx.profile.support_viewport_index_layer_non_geometry ||
|
||||||
|
ctx.stage == Shader::Stage::Geometry)
|
||||||
|
? std::optional<Id>{ctx.viewport_index}
|
||||||
|
: std::nullopt;
|
||||||
default:
|
default:
|
||||||
throw NotImplementedException("Read attribute {}", attr);
|
throw NotImplementedException("Read attribute {}", attr);
|
||||||
}
|
}
|
||||||
|
@ -206,7 +209,7 @@ Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, Id value) {
|
void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, Id value) {
|
||||||
auto output = OutputAttrPointer(ctx, attr);
|
const std::optional<Id> output{OutputAttrPointer(ctx, attr)};
|
||||||
if (!output) {
|
if (!output) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -263,38 +266,6 @@ void EmitSetOFlag(EmitContext&) {
|
||||||
throw NotImplementedException("SPIR-V Instruction");
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitGetFCSMFlag(EmitContext&) {
|
|
||||||
throw NotImplementedException("SPIR-V Instruction");
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmitGetTAFlag(EmitContext&) {
|
|
||||||
throw NotImplementedException("SPIR-V Instruction");
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmitGetTRFlag(EmitContext&) {
|
|
||||||
throw NotImplementedException("SPIR-V Instruction");
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmitGetMXFlag(EmitContext&) {
|
|
||||||
throw NotImplementedException("SPIR-V Instruction");
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmitSetFCSMFlag(EmitContext&) {
|
|
||||||
throw NotImplementedException("SPIR-V Instruction");
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmitSetTAFlag(EmitContext&) {
|
|
||||||
throw NotImplementedException("SPIR-V Instruction");
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmitSetTRFlag(EmitContext&) {
|
|
||||||
throw NotImplementedException("SPIR-V Instruction");
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmitSetMXFlag(EmitContext&) {
|
|
||||||
throw NotImplementedException("SPIR-V Instruction");
|
|
||||||
}
|
|
||||||
|
|
||||||
Id EmitWorkgroupId(EmitContext& ctx) {
|
Id EmitWorkgroupId(EmitContext& ctx) {
|
||||||
return ctx.OpLoad(ctx.U32[3], ctx.workgroup_id);
|
return ctx.OpLoad(ctx.U32[3], ctx.workgroup_id);
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,8 +82,17 @@ void IREmitter::SelectionMerge(Block* merge_block) {
|
||||||
Inst(Opcode::SelectionMerge, merge_block);
|
Inst(Opcode::SelectionMerge, merge_block);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IREmitter::MemoryBarrier(BarrierInstInfo info) {
|
void IREmitter::MemoryBarrier(MemoryScope scope) {
|
||||||
Inst(Opcode::MemoryBarrier, Flags{info});
|
switch (scope) {
|
||||||
|
case MemoryScope::Workgroup:
|
||||||
|
Inst(Opcode::MemoryBarrierWorkgroupLevel);
|
||||||
|
case MemoryScope::Device:
|
||||||
|
Inst(Opcode::MemoryBarrierDeviceLevel);
|
||||||
|
case MemoryScope::System:
|
||||||
|
Inst(Opcode::MemoryBarrierSystemLevel);
|
||||||
|
default:
|
||||||
|
throw InvalidArgument("Invalid memory scope {}", scope);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IREmitter::Return() {
|
void IREmitter::Return() {
|
||||||
|
@ -202,38 +211,6 @@ void IREmitter::SetOFlag(const U1& value) {
|
||||||
Inst(Opcode::SetOFlag, value);
|
Inst(Opcode::SetOFlag, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
U1 IREmitter::GetFCSMFlag() {
|
|
||||||
return Inst<U1>(Opcode::GetFCSMFlag);
|
|
||||||
}
|
|
||||||
|
|
||||||
U1 IREmitter::GetTAFlag() {
|
|
||||||
return Inst<U1>(Opcode::GetTAFlag);
|
|
||||||
}
|
|
||||||
|
|
||||||
U1 IREmitter::GetTRFlag() {
|
|
||||||
return Inst<U1>(Opcode::GetTRFlag);
|
|
||||||
}
|
|
||||||
|
|
||||||
U1 IREmitter::GetMXFlag() {
|
|
||||||
return Inst<U1>(Opcode::GetMXFlag);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IREmitter::SetFCSMFlag(const U1& value) {
|
|
||||||
Inst(Opcode::SetFCSMFlag, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IREmitter::SetTAFlag(const U1& value) {
|
|
||||||
Inst(Opcode::SetTAFlag, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IREmitter::SetTRFlag(const U1& value) {
|
|
||||||
Inst(Opcode::SetTRFlag, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IREmitter::SetMXFlag(const U1& value) {
|
|
||||||
Inst(Opcode::SetMXFlag, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
static U1 GetFlowTest(IREmitter& ir, FlowTest flow_test) {
|
static U1 GetFlowTest(IREmitter& ir, FlowTest flow_test) {
|
||||||
switch (flow_test) {
|
switch (flow_test) {
|
||||||
case FlowTest::F:
|
case FlowTest::F:
|
||||||
|
@ -292,9 +269,9 @@ static U1 GetFlowTest(IREmitter& ir, FlowTest flow_test) {
|
||||||
return ir.LogicalOr(ir.GetSFlag(), ir.GetZFlag());
|
return ir.LogicalOr(ir.GetSFlag(), ir.GetZFlag());
|
||||||
case FlowTest::RGT:
|
case FlowTest::RGT:
|
||||||
return ir.LogicalAnd(ir.LogicalNot(ir.GetSFlag()), ir.LogicalNot(ir.GetZFlag()));
|
return ir.LogicalAnd(ir.LogicalNot(ir.GetSFlag()), ir.LogicalNot(ir.GetZFlag()));
|
||||||
|
|
||||||
case FlowTest::FCSM_TR:
|
case FlowTest::FCSM_TR:
|
||||||
return ir.LogicalAnd(ir.GetFCSMFlag(), ir.GetTRFlag());
|
// LOG_WARNING(ShaderDecompiler, "FCSM_TR CC State (Stubbed)");
|
||||||
|
return ir.Imm1(false);
|
||||||
case FlowTest::CSM_TA:
|
case FlowTest::CSM_TA:
|
||||||
case FlowTest::CSM_TR:
|
case FlowTest::CSM_TR:
|
||||||
case FlowTest::CSM_MX:
|
case FlowTest::CSM_MX:
|
||||||
|
|
|
@ -70,16 +70,6 @@ public:
|
||||||
void SetCFlag(const U1& value);
|
void SetCFlag(const U1& value);
|
||||||
void SetOFlag(const U1& value);
|
void SetOFlag(const U1& value);
|
||||||
|
|
||||||
[[nodiscard]] U1 GetFCSMFlag();
|
|
||||||
[[nodiscard]] U1 GetTAFlag();
|
|
||||||
[[nodiscard]] U1 GetTRFlag();
|
|
||||||
[[nodiscard]] U1 GetMXFlag();
|
|
||||||
|
|
||||||
void SetFCSMFlag(const U1& value);
|
|
||||||
void SetTAFlag(const U1& value);
|
|
||||||
void SetTRFlag(const U1& value);
|
|
||||||
void SetMXFlag(const U1& value);
|
|
||||||
|
|
||||||
[[nodiscard]] U1 Condition(IR::Condition cond);
|
[[nodiscard]] U1 Condition(IR::Condition cond);
|
||||||
[[nodiscard]] U1 GetFlowTestResult(FlowTest test);
|
[[nodiscard]] U1 GetFlowTestResult(FlowTest test);
|
||||||
|
|
||||||
|
@ -138,7 +128,7 @@ public:
|
||||||
[[nodiscard]] Value Select(const U1& condition, const Value& true_value,
|
[[nodiscard]] Value Select(const U1& condition, const Value& true_value,
|
||||||
const Value& false_value);
|
const Value& false_value);
|
||||||
|
|
||||||
[[nodiscard]] void MemoryBarrier(BarrierInstInfo info);
|
[[nodiscard]] void MemoryBarrier(MemoryScope scope);
|
||||||
|
|
||||||
template <typename Dest, typename Source>
|
template <typename Dest, typename Source>
|
||||||
[[nodiscard]] Dest BitCast(const Source& value);
|
[[nodiscard]] Dest BitCast(const Source& value);
|
||||||
|
|
|
@ -25,13 +25,7 @@ enum class FpRounding : u8 {
|
||||||
RZ, // Round towards zero
|
RZ, // Round towards zero
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class MemoryScope : u32 {
|
enum class MemoryScope : u32 { DontCare, Warp, Workgroup, Device, System };
|
||||||
DontCare,
|
|
||||||
Warp,
|
|
||||||
Workgroup,
|
|
||||||
Device,
|
|
||||||
System
|
|
||||||
};
|
|
||||||
|
|
||||||
struct FpControl {
|
struct FpControl {
|
||||||
bool no_contraction{false};
|
bool no_contraction{false};
|
||||||
|
@ -40,11 +34,6 @@ struct FpControl {
|
||||||
};
|
};
|
||||||
static_assert(sizeof(FpControl) <= sizeof(u32));
|
static_assert(sizeof(FpControl) <= sizeof(u32));
|
||||||
|
|
||||||
union BarrierInstInfo {
|
|
||||||
u32 raw;
|
|
||||||
BitField<0, 3, MemoryScope> scope;
|
|
||||||
};
|
|
||||||
|
|
||||||
union TextureInstInfo {
|
union TextureInstInfo {
|
||||||
u32 raw;
|
u32 raw;
|
||||||
BitField<0, 8, TextureType> type;
|
BitField<0, 8, TextureType> type;
|
||||||
|
|
|
@ -17,7 +17,9 @@ OPCODE(Unreachable, Void,
|
||||||
OPCODE(DemoteToHelperInvocation, Void, Label, )
|
OPCODE(DemoteToHelperInvocation, Void, Label, )
|
||||||
|
|
||||||
// Barriers
|
// Barriers
|
||||||
OPCODE(MemoryBarrier, Void, )
|
OPCODE(MemoryBarrierWorkgroupLevel, Void, )
|
||||||
|
OPCODE(MemoryBarrierDeviceLevel, Void, )
|
||||||
|
OPCODE(MemoryBarrierSystemLevel, Void, )
|
||||||
|
|
||||||
// Special operations
|
// Special operations
|
||||||
OPCODE(Prologue, Void, )
|
OPCODE(Prologue, Void, )
|
||||||
|
@ -49,18 +51,10 @@ OPCODE(GetZFlag, U1, Void
|
||||||
OPCODE(GetSFlag, U1, Void, )
|
OPCODE(GetSFlag, U1, Void, )
|
||||||
OPCODE(GetCFlag, U1, Void, )
|
OPCODE(GetCFlag, U1, Void, )
|
||||||
OPCODE(GetOFlag, U1, Void, )
|
OPCODE(GetOFlag, U1, Void, )
|
||||||
OPCODE(GetFCSMFlag, U1, Void, )
|
|
||||||
OPCODE(GetTAFlag, U1, Void, )
|
|
||||||
OPCODE(GetTRFlag, U1, Void, )
|
|
||||||
OPCODE(GetMXFlag, U1, Void, )
|
|
||||||
OPCODE(SetZFlag, Void, U1, )
|
OPCODE(SetZFlag, Void, U1, )
|
||||||
OPCODE(SetSFlag, Void, U1, )
|
OPCODE(SetSFlag, Void, U1, )
|
||||||
OPCODE(SetCFlag, Void, U1, )
|
OPCODE(SetCFlag, Void, U1, )
|
||||||
OPCODE(SetOFlag, Void, U1, )
|
OPCODE(SetOFlag, Void, U1, )
|
||||||
OPCODE(SetFCSMFlag, Void, U1, )
|
|
||||||
OPCODE(SetTAFlag, Void, U1, )
|
|
||||||
OPCODE(SetTRFlag, Void, U1, )
|
|
||||||
OPCODE(SetMXFlag, Void, U1, )
|
|
||||||
OPCODE(WorkgroupId, U32x3, )
|
OPCODE(WorkgroupId, U32x3, )
|
||||||
OPCODE(LocalInvocationId, U32x3, )
|
OPCODE(LocalInvocationId, U32x3, )
|
||||||
OPCODE(LaneId, U32, )
|
OPCODE(LaneId, U32, )
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
#include "common/bit_field.h"
|
#include "common/bit_field.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "shader_recompiler/frontend/ir/modifiers.h"
|
#include "shader_recompiler/frontend/ir/modifiers.h"
|
||||||
#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h"
|
|
||||||
#include "shader_recompiler/frontend/maxwell/opcodes.h"
|
#include "shader_recompiler/frontend/maxwell/opcodes.h"
|
||||||
|
#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h"
|
||||||
|
|
||||||
namespace Shader::Maxwell {
|
namespace Shader::Maxwell {
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -21,28 +21,24 @@ enum class LocalScope : u64 {
|
||||||
IR::MemoryScope LocalScopeToMemoryScope(LocalScope scope) {
|
IR::MemoryScope LocalScopeToMemoryScope(LocalScope scope) {
|
||||||
switch (scope) {
|
switch (scope) {
|
||||||
case LocalScope::CTG:
|
case LocalScope::CTG:
|
||||||
return IR::MemoryScope::Warp;
|
return IR::MemoryScope::Workgroup;
|
||||||
case LocalScope::GL:
|
case LocalScope::GL:
|
||||||
return IR::MemoryScope::Device;
|
return IR::MemoryScope::Device;
|
||||||
case LocalScope::SYS:
|
case LocalScope::SYS:
|
||||||
return IR::MemoryScope::System;
|
return IR::MemoryScope::System;
|
||||||
case LocalScope::VC:
|
|
||||||
return IR::MemoryScope::Workgroup; // or should be device?
|
|
||||||
default:
|
default:
|
||||||
throw NotImplementedException("Unimplemented Local Scope {}", scope);
|
throw NotImplementedException("Unimplemented Local Scope {}", scope);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
void TranslatorVisitor::MEMBAR(u64 inst) {
|
void TranslatorVisitor::MEMBAR(u64 inst) {
|
||||||
union {
|
union {
|
||||||
u64 raw;
|
u64 raw;
|
||||||
BitField<8, 2, LocalScope> scope;
|
BitField<8, 2, LocalScope> scope;
|
||||||
} membar{inst};
|
} membar{inst};
|
||||||
IR::BarrierInstInfo info{};
|
ir.MemoryBarrier(LocalScopeToMemoryScope(membar.scope));
|
||||||
info.scope.Assign(LocalScopeToMemoryScope(membar.scope));
|
|
||||||
ir.MemoryBarrier(info);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TranslatorVisitor::DEPBAR() {
|
void TranslatorVisitor::DEPBAR() {
|
||||||
|
|
|
@ -96,8 +96,10 @@ enum class SpecialRegister : u64 {
|
||||||
case SpecialRegister::SR_CTAID_Z:
|
case SpecialRegister::SR_CTAID_Z:
|
||||||
return ir.WorkgroupIdZ();
|
return ir.WorkgroupIdZ();
|
||||||
case SpecialRegister::SR_WSCALEFACTOR_XY:
|
case SpecialRegister::SR_WSCALEFACTOR_XY:
|
||||||
|
// LOG_WARNING(ShaderDecompiler, "SR_WSCALEFACTOR_XY (Stubbed)");
|
||||||
return ir.Imm32(Common::BitCast<u32>(1.0f));
|
return ir.Imm32(Common::BitCast<u32>(1.0f));
|
||||||
case SpecialRegister::SR_WSCALEFACTOR_Z:
|
case SpecialRegister::SR_WSCALEFACTOR_Z:
|
||||||
|
// LOG_WARNING(ShaderDecompiler, "SR_WSCALEFACTOR_Z (Stubbed)");
|
||||||
return ir.Imm32(Common::BitCast<u32>(1.0f));
|
return ir.Imm32(Common::BitCast<u32>(1.0f));
|
||||||
case SpecialRegister::SR_LANEID:
|
case SpecialRegister::SR_LANEID:
|
||||||
return ir.LaneId();
|
return ir.LaneId();
|
||||||
|
|
|
@ -50,10 +50,7 @@ void TranslatorVisitor::VOTE(u64 insn) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void TranslatorVisitor::VOTE_vtg(u64) {
|
void TranslatorVisitor::VOTE_vtg(u64) {
|
||||||
// LOG_WARNING("VOTE.VTG: Stubbed!");
|
// LOG_WARNING(ShaderDecompiler, "VOTE.VTG: Stubbed!");
|
||||||
auto imm = ir.Imm1(false);
|
|
||||||
ir.SetFCSMFlag(imm);
|
|
||||||
ir.SetTRFlag(imm);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Shader::Maxwell
|
} // namespace Shader::Maxwell
|
||||||
|
|
|
@ -374,17 +374,14 @@ std::optional<IR::Value> FoldCompositeExtractImpl(IR::Value inst_value, IR::Opco
|
||||||
if (inst->Opcode() == construct) {
|
if (inst->Opcode() == construct) {
|
||||||
return inst->Arg(first_index);
|
return inst->Arg(first_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inst->Opcode() != insert) {
|
if (inst->Opcode() != insert) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
IR::Value value_index{inst->Arg(2)};
|
IR::Value value_index{inst->Arg(2)};
|
||||||
if (!value_index.IsImmediate()) {
|
if (!value_index.IsImmediate()) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
const u32 second_index{value_index.U32()};
|
||||||
const u32 second_index = value_index.U32();
|
|
||||||
if (first_index != second_index) {
|
if (first_index != second_index) {
|
||||||
IR::Value value_composite{inst->Arg(0)};
|
IR::Value value_composite{inst->Arg(0)};
|
||||||
if (value_composite.IsImmediate()) {
|
if (value_composite.IsImmediate()) {
|
||||||
|
@ -404,8 +401,8 @@ void FoldCompositeExtract(IR::Inst& inst, IR::Opcode construct, IR::Opcode inser
|
||||||
if (!value_2.IsImmediate()) {
|
if (!value_2.IsImmediate()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const u32 first_index = value_2.U32();
|
const u32 first_index{value_2.U32()};
|
||||||
auto result = FoldCompositeExtractImpl(value_1, insert, construct, first_index);
|
const std::optional result{FoldCompositeExtractImpl(value_1, insert, construct, first_index)};
|
||||||
if (!result) {
|
if (!result) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <compare>
|
#include <compare>
|
||||||
|
#include <map>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <ranges>
|
#include <ranges>
|
||||||
#include <map>
|
|
||||||
|
|
||||||
#include <boost/container/flat_set.hpp>
|
#include <boost/container/flat_set.hpp>
|
||||||
#include <boost/container/small_vector.hpp>
|
#include <boost/container/small_vector.hpp>
|
||||||
|
@ -295,8 +295,8 @@ void CollectStorageBuffers(IR::Block& block, IR::Inst& inst, StorageBufferSet& s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Collect storage buffer and the instruction
|
// Collect storage buffer and the instruction
|
||||||
const bool is_a_write = IsGlobalMemoryWrite(inst);
|
const bool is_a_write{IsGlobalMemoryWrite(inst)};
|
||||||
auto it = writes_map.find(*storage_buffer);
|
auto it{writes_map.find(*storage_buffer)};
|
||||||
if (it == writes_map.end()) {
|
if (it == writes_map.end()) {
|
||||||
writes_map[*storage_buffer] = is_a_write;
|
writes_map[*storage_buffer] = is_a_write;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -38,10 +38,6 @@ struct ZeroFlagTag : FlagTag {};
|
||||||
struct SignFlagTag : FlagTag {};
|
struct SignFlagTag : FlagTag {};
|
||||||
struct CarryFlagTag : FlagTag {};
|
struct CarryFlagTag : FlagTag {};
|
||||||
struct OverflowFlagTag : FlagTag {};
|
struct OverflowFlagTag : FlagTag {};
|
||||||
struct FCSMFlagTag : FlagTag {};
|
|
||||||
struct TAFlagTag : FlagTag {};
|
|
||||||
struct TRFlagTag : FlagTag {};
|
|
||||||
struct MXFlagTag : FlagTag {};
|
|
||||||
|
|
||||||
struct GotoVariable : FlagTag {
|
struct GotoVariable : FlagTag {
|
||||||
GotoVariable() = default;
|
GotoVariable() = default;
|
||||||
|
@ -57,8 +53,7 @@ struct IndirectBranchVariable {
|
||||||
};
|
};
|
||||||
|
|
||||||
using Variant = std::variant<IR::Reg, IR::Pred, ZeroFlagTag, SignFlagTag, CarryFlagTag,
|
using Variant = std::variant<IR::Reg, IR::Pred, ZeroFlagTag, SignFlagTag, CarryFlagTag,
|
||||||
OverflowFlagTag, FCSMFlagTag, TAFlagTag, TRFlagTag, MXFlagTag,
|
OverflowFlagTag, GotoVariable, IndirectBranchVariable>;
|
||||||
GotoVariable, IndirectBranchVariable>;
|
|
||||||
using ValueMap = boost::container::flat_map<IR::Block*, IR::Value, std::less<IR::Block*>>;
|
using ValueMap = boost::container::flat_map<IR::Block*, IR::Value, std::less<IR::Block*>>;
|
||||||
|
|
||||||
struct DefTable {
|
struct DefTable {
|
||||||
|
@ -94,22 +89,6 @@ struct DefTable {
|
||||||
return overflow_flag;
|
return overflow_flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] ValueMap& operator[](FCSMFlagTag) noexcept {
|
|
||||||
return fcsm_flag;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] ValueMap& operator[](TAFlagTag) noexcept {
|
|
||||||
return ta_flag;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] ValueMap& operator[](TRFlagTag) noexcept {
|
|
||||||
return tr_flag;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] ValueMap& operator[](MXFlagTag) noexcept {
|
|
||||||
return mr_flag;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::array<ValueMap, IR::NUM_USER_REGS> regs;
|
std::array<ValueMap, IR::NUM_USER_REGS> regs;
|
||||||
std::array<ValueMap, IR::NUM_USER_PREDS> preds;
|
std::array<ValueMap, IR::NUM_USER_PREDS> preds;
|
||||||
boost::container::flat_map<u32, ValueMap> goto_vars;
|
boost::container::flat_map<u32, ValueMap> goto_vars;
|
||||||
|
@ -118,10 +97,6 @@ struct DefTable {
|
||||||
ValueMap sign_flag;
|
ValueMap sign_flag;
|
||||||
ValueMap carry_flag;
|
ValueMap carry_flag;
|
||||||
ValueMap overflow_flag;
|
ValueMap overflow_flag;
|
||||||
ValueMap fcsm_flag;
|
|
||||||
ValueMap ta_flag;
|
|
||||||
ValueMap tr_flag;
|
|
||||||
ValueMap mr_flag;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
IR::Opcode UndefOpcode(IR::Reg) noexcept {
|
IR::Opcode UndefOpcode(IR::Reg) noexcept {
|
||||||
|
@ -272,18 +247,6 @@ void VisitInst(Pass& pass, IR::Block* block, IR::Inst& inst) {
|
||||||
case IR::Opcode::SetOFlag:
|
case IR::Opcode::SetOFlag:
|
||||||
pass.WriteVariable(OverflowFlagTag{}, block, inst.Arg(0));
|
pass.WriteVariable(OverflowFlagTag{}, block, inst.Arg(0));
|
||||||
break;
|
break;
|
||||||
case IR::Opcode::SetFCSMFlag:
|
|
||||||
pass.WriteVariable(FCSMFlagTag{}, block, inst.Arg(0));
|
|
||||||
break;
|
|
||||||
case IR::Opcode::SetTAFlag:
|
|
||||||
pass.WriteVariable(TAFlagTag{}, block, inst.Arg(0));
|
|
||||||
break;
|
|
||||||
case IR::Opcode::SetTRFlag:
|
|
||||||
pass.WriteVariable(TRFlagTag{}, block, inst.Arg(0));
|
|
||||||
break;
|
|
||||||
case IR::Opcode::SetMXFlag:
|
|
||||||
pass.WriteVariable(MXFlagTag{}, block, inst.Arg(0));
|
|
||||||
break;
|
|
||||||
case IR::Opcode::GetRegister:
|
case IR::Opcode::GetRegister:
|
||||||
if (const IR::Reg reg{inst.Arg(0).Reg()}; reg != IR::Reg::RZ) {
|
if (const IR::Reg reg{inst.Arg(0).Reg()}; reg != IR::Reg::RZ) {
|
||||||
inst.ReplaceUsesWith(pass.ReadVariable(reg, block));
|
inst.ReplaceUsesWith(pass.ReadVariable(reg, block));
|
||||||
|
@ -312,17 +275,6 @@ void VisitInst(Pass& pass, IR::Block* block, IR::Inst& inst) {
|
||||||
case IR::Opcode::GetOFlag:
|
case IR::Opcode::GetOFlag:
|
||||||
inst.ReplaceUsesWith(pass.ReadVariable(OverflowFlagTag{}, block));
|
inst.ReplaceUsesWith(pass.ReadVariable(OverflowFlagTag{}, block));
|
||||||
break;
|
break;
|
||||||
case IR::Opcode::GetFCSMFlag:
|
|
||||||
inst.ReplaceUsesWith(pass.ReadVariable(FCSMFlagTag{}, block));
|
|
||||||
break;
|
|
||||||
case IR::Opcode::GetTAFlag:
|
|
||||||
inst.ReplaceUsesWith(pass.ReadVariable(TAFlagTag{}, block));
|
|
||||||
break;
|
|
||||||
case IR::Opcode::GetTRFlag:
|
|
||||||
inst.ReplaceUsesWith(pass.ReadVariable(TRFlagTag{}, block));
|
|
||||||
break;
|
|
||||||
case IR::Opcode::GetMXFlag:
|
|
||||||
inst.ReplaceUsesWith(pass.ReadVariable(MXFlagTag{}, block));
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
Reference in New Issue