MacroHLE: Add HLE replacement for base vertex and base instance.
This commit is contained in:
parent
209ce46a9f
commit
7842543573
22 changed files with 265 additions and 70 deletions
|
@ -339,6 +339,10 @@ Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, Id vertex) {
|
|||
const Id base{ctx.OpLoad(ctx.U32[1], ctx.base_vertex)};
|
||||
return ctx.OpBitcast(ctx.F32[1], ctx.OpISub(ctx.U32[1], index, base));
|
||||
}
|
||||
case IR::Attribute::BaseInstance:
|
||||
return ctx.OpBitcast(ctx.F32[1], ctx.OpLoad(ctx.U32[1], ctx.base_instance));
|
||||
case IR::Attribute::BaseVertex:
|
||||
return ctx.OpBitcast(ctx.F32[1], ctx.OpLoad(ctx.U32[1], ctx.base_vertex));
|
||||
case IR::Attribute::FrontFace:
|
||||
return ctx.OpSelect(ctx.F32[1], ctx.OpLoad(ctx.U1, ctx.front_face),
|
||||
ctx.OpBitcast(ctx.F32[1], ctx.Const(std::numeric_limits<u32>::max())),
|
||||
|
@ -380,6 +384,10 @@ Id EmitGetAttributeU32(EmitContext& ctx, IR::Attribute attr, Id) {
|
|||
const Id base{ctx.OpLoad(ctx.U32[1], ctx.base_vertex)};
|
||||
return ctx.OpISub(ctx.U32[1], index, base);
|
||||
}
|
||||
case IR::Attribute::BaseInstance:
|
||||
return ctx.OpLoad(ctx.U32[1], ctx.base_instance);
|
||||
case IR::Attribute::BaseVertex:
|
||||
return ctx.OpLoad(ctx.U32[1], ctx.base_vertex);
|
||||
default:
|
||||
throw NotImplementedException("Read U32 attribute {}", attr);
|
||||
}
|
||||
|
|
|
@ -1379,18 +1379,28 @@ void EmitContext::DefineInputs(const IR::Program& program) {
|
|||
if (loads[IR::Attribute::InstanceId]) {
|
||||
if (profile.support_vertex_instance_id) {
|
||||
instance_id = DefineInput(*this, U32[1], true, spv::BuiltIn::InstanceId);
|
||||
if (loads[IR::Attribute::BaseInstance]) {
|
||||
base_instance = DefineInput(*this, U32[1], true, spv::BuiltIn::BaseVertex);
|
||||
}
|
||||
} else {
|
||||
instance_index = DefineInput(*this, U32[1], true, spv::BuiltIn::InstanceIndex);
|
||||
base_instance = DefineInput(*this, U32[1], true, spv::BuiltIn::BaseInstance);
|
||||
}
|
||||
} else if (loads[IR::Attribute::BaseInstance]) {
|
||||
base_instance = DefineInput(*this, U32[1], true, spv::BuiltIn::BaseInstance);
|
||||
}
|
||||
if (loads[IR::Attribute::VertexId]) {
|
||||
if (profile.support_vertex_instance_id) {
|
||||
vertex_id = DefineInput(*this, U32[1], true, spv::BuiltIn::VertexId);
|
||||
if (loads[IR::Attribute::BaseVertex]) {
|
||||
base_vertex = DefineInput(*this, U32[1], true, spv::BuiltIn::BaseVertex);
|
||||
}
|
||||
} else {
|
||||
vertex_index = DefineInput(*this, U32[1], true, spv::BuiltIn::VertexIndex);
|
||||
base_vertex = DefineInput(*this, U32[1], true, spv::BuiltIn::BaseVertex);
|
||||
}
|
||||
} else if (loads[IR::Attribute::BaseVertex]) {
|
||||
base_vertex = DefineInput(*this, U32[1], true, spv::BuiltIn::BaseVertex);
|
||||
}
|
||||
if (loads[IR::Attribute::FrontFace]) {
|
||||
front_face = DefineInput(*this, U1, true, spv::BuiltIn::FrontFacing);
|
||||
|
|
|
@ -34,6 +34,11 @@ public:
|
|||
|
||||
[[nodiscard]] virtual std::array<u32, 3> WorkgroupSize() const = 0;
|
||||
|
||||
[[nodiscard]] virtual bool HasHLEMacroState() const = 0;
|
||||
|
||||
[[nodiscard]] virtual std::optional<ReplaceConstant> GetReplaceConstBuffer(
|
||||
u32 bank, u32 offset) = 0;
|
||||
|
||||
virtual void Dump(u64 hash) = 0;
|
||||
|
||||
[[nodiscard]] const ProgramHeader& SPH() const noexcept {
|
||||
|
|
|
@ -446,6 +446,10 @@ std::string NameOf(Attribute attribute) {
|
|||
return "ViewportMask";
|
||||
case Attribute::FrontFace:
|
||||
return "FrontFace";
|
||||
case Attribute::BaseInstance:
|
||||
return "BaseInstance";
|
||||
case Attribute::BaseVertex:
|
||||
return "BaseVertex";
|
||||
}
|
||||
return fmt::format("<reserved attribute {}>", static_cast<int>(attribute));
|
||||
}
|
||||
|
|
|
@ -219,6 +219,10 @@ enum class Attribute : u64 {
|
|||
FixedFncTexture9Q = 231,
|
||||
ViewportMask = 232,
|
||||
FrontFace = 255,
|
||||
|
||||
// Implementation attributes
|
||||
BaseInstance = 256,
|
||||
BaseVertex = 257,
|
||||
};
|
||||
|
||||
constexpr size_t NUM_GENERICS = 32;
|
||||
|
|
|
@ -294,6 +294,14 @@ F32 IREmitter::GetAttribute(IR::Attribute attribute, const U32& vertex) {
|
|||
return Inst<F32>(Opcode::GetAttribute, attribute, vertex);
|
||||
}
|
||||
|
||||
U32 IREmitter::GetAttributeU32(IR::Attribute attribute) {
|
||||
return GetAttributeU32(attribute, Imm32(0));
|
||||
}
|
||||
|
||||
U32 IREmitter::GetAttributeU32(IR::Attribute attribute, const U32& vertex) {
|
||||
return Inst<U32>(Opcode::GetAttributeU32, attribute, vertex);
|
||||
}
|
||||
|
||||
void IREmitter::SetAttribute(IR::Attribute attribute, const F32& value, const U32& vertex) {
|
||||
Inst(Opcode::SetAttribute, attribute, value, vertex);
|
||||
}
|
||||
|
|
|
@ -74,6 +74,8 @@ public:
|
|||
|
||||
[[nodiscard]] F32 GetAttribute(IR::Attribute attribute);
|
||||
[[nodiscard]] F32 GetAttribute(IR::Attribute attribute, const U32& vertex);
|
||||
[[nodiscard]] U32 GetAttributeU32(IR::Attribute attribute);
|
||||
[[nodiscard]] U32 GetAttributeU32(IR::Attribute attribute, const U32& vertex);
|
||||
void SetAttribute(IR::Attribute attribute, const F32& value, const U32& vertex);
|
||||
|
||||
[[nodiscard]] F32 GetAttributeIndexed(const U32& phys_address);
|
||||
|
|
|
@ -219,7 +219,7 @@ IR::Program TranslateProgram(ObjectPool<IR::Inst>& inst_pool, ObjectPool<IR::Blo
|
|||
}
|
||||
Optimization::SsaRewritePass(program);
|
||||
|
||||
Optimization::ConstantPropagationPass(program);
|
||||
Optimization::ConstantPropagationPass(env, program);
|
||||
|
||||
Optimization::PositionPass(env, program);
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <type_traits>
|
||||
|
||||
#include "common/bit_cast.h"
|
||||
#include "shader_recompiler/environment.h"
|
||||
#include "shader_recompiler/exception.h"
|
||||
#include "shader_recompiler/frontend/ir/ir_emitter.h"
|
||||
#include "shader_recompiler/frontend/ir/value.h"
|
||||
|
@ -515,6 +516,8 @@ void FoldBitCast(IR::Inst& inst, IR::Opcode reverse) {
|
|||
case IR::Attribute::PrimitiveId:
|
||||
case IR::Attribute::InstanceId:
|
||||
case IR::Attribute::VertexId:
|
||||
case IR::Attribute::BaseVertex:
|
||||
case IR::Attribute::BaseInstance:
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
|
@ -644,7 +647,37 @@ void FoldFSwizzleAdd(IR::Block& block, IR::Inst& inst) {
|
|||
}
|
||||
}
|
||||
|
||||
void ConstantPropagation(IR::Block& block, IR::Inst& inst) {
|
||||
void FoldConstBuffer(Environment& env, IR::Block& block, IR::Inst& inst) {
|
||||
const IR::Value bank{inst.Arg(0)};
|
||||
const IR::Value offset{inst.Arg(1)};
|
||||
if (!bank.IsImmediate() || !offset.IsImmediate()) {
|
||||
return;
|
||||
}
|
||||
const auto bank_value = bank.U32();
|
||||
const auto offset_value = offset.U32();
|
||||
auto replacement = env.GetReplaceConstBuffer(bank_value, offset_value);
|
||||
if (!replacement) {
|
||||
return;
|
||||
}
|
||||
const auto new_attribute = [replacement]() {
|
||||
switch (*replacement) {
|
||||
case ReplaceConstant::BaseInstance:
|
||||
return IR::Attribute::BaseInstance;
|
||||
case ReplaceConstant::BaseVertex:
|
||||
return IR::Attribute::BaseVertex;
|
||||
default:
|
||||
throw NotImplementedException("Not implemented replacement variable {}", *replacement);
|
||||
}
|
||||
}();
|
||||
IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)};
|
||||
if (inst.GetOpcode() == IR::Opcode::GetCbufU32) {
|
||||
inst.ReplaceUsesWith(ir.GetAttributeU32(new_attribute));
|
||||
} else {
|
||||
inst.ReplaceUsesWith(ir.GetAttribute(new_attribute));
|
||||
}
|
||||
}
|
||||
|
||||
void ConstantPropagation(Environment& env, IR::Block& block, IR::Inst& inst) {
|
||||
switch (inst.GetOpcode()) {
|
||||
case IR::Opcode::GetRegister:
|
||||
return FoldGetRegister(inst);
|
||||
|
@ -789,18 +822,24 @@ void ConstantPropagation(IR::Block& block, IR::Inst& inst) {
|
|||
IR::Opcode::CompositeInsertF16x4);
|
||||
case IR::Opcode::FSwizzleAdd:
|
||||
return FoldFSwizzleAdd(block, inst);
|
||||
case IR::Opcode::GetCbufF32:
|
||||
case IR::Opcode::GetCbufU32:
|
||||
if (env.HasHLEMacroState()) {
|
||||
return FoldConstBuffer(env, block, inst);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
void ConstantPropagationPass(IR::Program& program) {
|
||||
void ConstantPropagationPass(Environment& env, IR::Program& program) {
|
||||
const auto end{program.post_order_blocks.rend()};
|
||||
for (auto it = program.post_order_blocks.rbegin(); it != end; ++it) {
|
||||
IR::Block* const block{*it};
|
||||
for (IR::Inst& inst : block->Instructions()) {
|
||||
ConstantPropagation(*block, inst);
|
||||
ConstantPropagation(env, *block, inst);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ struct HostTranslateInfo;
|
|||
namespace Shader::Optimization {
|
||||
|
||||
void CollectShaderInfoPass(Environment& env, IR::Program& program);
|
||||
void ConstantPropagationPass(IR::Program& program);
|
||||
void ConstantPropagationPass(Environment& env, IR::Program& program);
|
||||
void DeadCodeEliminationPass(IR::Program& program);
|
||||
void GlobalMemoryToStorageBufferPass(IR::Program& program);
|
||||
void IdentityRemovalPass(IR::Program& program);
|
||||
|
|
|
@ -16,6 +16,11 @@
|
|||
|
||||
namespace Shader {
|
||||
|
||||
enum class ReplaceConstant : u32 {
|
||||
BaseInstance,
|
||||
BaseVertex,
|
||||
};
|
||||
|
||||
enum class TextureType : u32 {
|
||||
Color1D,
|
||||
ColorArray1D,
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
namespace Shader {
|
||||
|
||||
struct VaryingState {
|
||||
std::bitset<256> mask{};
|
||||
std::bitset<512> mask{};
|
||||
|
||||
void Set(IR::Attribute attribute, bool state = true) {
|
||||
mask[static_cast<size_t>(attribute)] = state;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue