mirror of
https://github.com/yuzu-mirror/yuzu
synced 2024-12-24 06:13:05 +00:00
shader: Implement indexed attributes
This commit is contained in:
parent
0df7e509db
commit
1d51803169
12 changed files with 279 additions and 35 deletions
|
@ -82,6 +82,28 @@ Id GetAttributeType(EmitContext& ctx, AttributeType type) {
|
||||||
}
|
}
|
||||||
throw InvalidArgument("Invalid attribute type {}", type);
|
throw InvalidArgument("Invalid attribute type {}", type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct AttrInfo {
|
||||||
|
Id pointer;
|
||||||
|
Id id;
|
||||||
|
bool needs_cast;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::optional<AttrInfo> AttrTypes(EmitContext& ctx, u32 index) {
|
||||||
|
const AttributeType type{ctx.profile.generic_input_types.at(index)};
|
||||||
|
switch (type) {
|
||||||
|
case AttributeType::Float:
|
||||||
|
return AttrInfo{ctx.input_f32, ctx.F32[1], false};
|
||||||
|
case AttributeType::UnsignedInt:
|
||||||
|
return AttrInfo{ctx.input_u32, ctx.U32[1], true};
|
||||||
|
case AttributeType::SignedInt:
|
||||||
|
return AttrInfo{ctx.input_s32, ctx.TypeInt(32, true), true};
|
||||||
|
case AttributeType::Disabled:
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
throw InvalidArgument("Invalid attribute type {}", type);
|
||||||
|
}
|
||||||
|
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
void VectorTypes::Define(Sirit::Module& sirit_ctx, Id base_type, std::string_view name) {
|
void VectorTypes::Define(Sirit::Module& sirit_ctx, Id base_type, std::string_view name) {
|
||||||
|
@ -107,6 +129,7 @@ EmitContext::EmitContext(const Profile& profile_, IR::Program& program, u32& bin
|
||||||
DefineConstantBuffers(program.info, binding);
|
DefineConstantBuffers(program.info, binding);
|
||||||
DefineStorageBuffers(program.info, binding);
|
DefineStorageBuffers(program.info, binding);
|
||||||
DefineTextures(program.info, binding);
|
DefineTextures(program.info, binding);
|
||||||
|
DefineAttributeMemAccess(program.info);
|
||||||
DefineLabels(program);
|
DefineLabels(program);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,6 +313,107 @@ void EmitContext::DefineSharedMemory(const IR::Program& program) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EmitContext::DefineAttributeMemAccess(const Info& info) {
|
||||||
|
const auto make_load{[&]() {
|
||||||
|
const Id end_block{OpLabel()};
|
||||||
|
const Id default_label{OpLabel()};
|
||||||
|
|
||||||
|
const Id func_type_load{TypeFunction(F32[1], U32[1])};
|
||||||
|
const Id func{OpFunction(F32[1], spv::FunctionControlMask::MaskNone, func_type_load)};
|
||||||
|
const Id offset{OpFunctionParameter(U32[1])};
|
||||||
|
AddLabel();
|
||||||
|
const Id base_index{OpShiftRightLogical(U32[1], offset, Constant(U32[1], 2U))};
|
||||||
|
const Id masked_index{OpBitwiseAnd(U32[1], base_index, Constant(U32[1], 3U))};
|
||||||
|
const Id compare_index{OpShiftRightLogical(U32[1], base_index, Constant(U32[1], 2U))};
|
||||||
|
std::vector<Sirit::Literal> literals;
|
||||||
|
std::vector<Id> labels;
|
||||||
|
const u32 base_attribute_value = static_cast<u32>(IR::Attribute::Generic0X) >> 2;
|
||||||
|
for (u32 i = 0; i < info.input_generics.size(); i++) {
|
||||||
|
if (!info.input_generics[i].used) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
literals.push_back(base_attribute_value + i);
|
||||||
|
labels.push_back(OpLabel());
|
||||||
|
}
|
||||||
|
OpSelectionMerge(end_block, spv::SelectionControlMask::MaskNone);
|
||||||
|
OpSwitch(compare_index, default_label, literals, labels);
|
||||||
|
AddLabel(default_label);
|
||||||
|
OpReturnValue(Constant(F32[1], 0.0f));
|
||||||
|
size_t label_index = 0;
|
||||||
|
for (u32 i = 0; i < info.input_generics.size(); i++) {
|
||||||
|
if (!info.input_generics[i].used) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
AddLabel(labels[label_index]);
|
||||||
|
const auto type{AttrTypes(*this, i)};
|
||||||
|
if (!type) {
|
||||||
|
OpReturnValue(Constant(F32[1], 0.0f));
|
||||||
|
label_index++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const Id generic_id{input_generics.at(i)};
|
||||||
|
const Id pointer{OpAccessChain(type->pointer, generic_id, masked_index)};
|
||||||
|
const Id value{OpLoad(type->id, pointer)};
|
||||||
|
const Id result{type->needs_cast ? OpBitcast(F32[1], value) : value};
|
||||||
|
OpReturnValue(result);
|
||||||
|
label_index++;
|
||||||
|
}
|
||||||
|
AddLabel(end_block);
|
||||||
|
OpUnreachable();
|
||||||
|
OpFunctionEnd();
|
||||||
|
return func;
|
||||||
|
}};
|
||||||
|
const auto make_store{[&]() {
|
||||||
|
const Id end_block{OpLabel()};
|
||||||
|
const Id default_label{OpLabel()};
|
||||||
|
|
||||||
|
const Id func_type_store{TypeFunction(void_id, U32[1], F32[1])};
|
||||||
|
const Id func{OpFunction(void_id, spv::FunctionControlMask::MaskNone, func_type_store)};
|
||||||
|
const Id offset{OpFunctionParameter(U32[1])};
|
||||||
|
const Id store_value{OpFunctionParameter(F32[1])};
|
||||||
|
AddLabel();
|
||||||
|
const Id base_index{OpShiftRightLogical(U32[1], offset, Constant(U32[1], 2U))};
|
||||||
|
const Id masked_index{OpBitwiseAnd(U32[1], base_index, Constant(U32[1], 3U))};
|
||||||
|
const Id compare_index{OpShiftRightLogical(U32[1], base_index, Constant(U32[1], 2U))};
|
||||||
|
std::vector<Sirit::Literal> literals;
|
||||||
|
std::vector<Id> labels;
|
||||||
|
const u32 base_attribute_value = static_cast<u32>(IR::Attribute::Generic0X) >> 2;
|
||||||
|
for (u32 i = 0; i < info.stores_generics.size(); i++) {
|
||||||
|
if (!info.stores_generics[i]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
literals.push_back(base_attribute_value + i);
|
||||||
|
labels.push_back(OpLabel());
|
||||||
|
}
|
||||||
|
OpSelectionMerge(end_block, spv::SelectionControlMask::MaskNone);
|
||||||
|
OpSwitch(compare_index, default_label, literals, labels);
|
||||||
|
AddLabel(default_label);
|
||||||
|
OpReturn();
|
||||||
|
size_t label_index = 0;
|
||||||
|
for (u32 i = 0; i < info.stores_generics.size(); i++) {
|
||||||
|
if (!info.stores_generics[i]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
AddLabel(labels[label_index]);
|
||||||
|
const Id generic_id{output_generics.at(i)};
|
||||||
|
const Id pointer{OpAccessChain(output_f32, generic_id, masked_index)};
|
||||||
|
OpStore(pointer, store_value);
|
||||||
|
OpReturn();
|
||||||
|
label_index++;
|
||||||
|
}
|
||||||
|
AddLabel(end_block);
|
||||||
|
OpUnreachable();
|
||||||
|
OpFunctionEnd();
|
||||||
|
return func;
|
||||||
|
}};
|
||||||
|
if (info.loads_indexed_attributes) {
|
||||||
|
indexed_load_func = make_load();
|
||||||
|
}
|
||||||
|
if (info.stores_indexed_attributes) {
|
||||||
|
indexed_store_func = make_store();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void EmitContext::DefineConstantBuffers(const Info& info, u32& binding) {
|
void EmitContext::DefineConstantBuffers(const Info& info, u32& binding) {
|
||||||
if (info.constant_buffer_descriptors.empty()) {
|
if (info.constant_buffer_descriptors.empty()) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -116,6 +116,9 @@ public:
|
||||||
Id fswzadd_lut_a{};
|
Id fswzadd_lut_a{};
|
||||||
Id fswzadd_lut_b{};
|
Id fswzadd_lut_b{};
|
||||||
|
|
||||||
|
Id indexed_load_func{};
|
||||||
|
Id indexed_store_func{};
|
||||||
|
|
||||||
Id local_memory{};
|
Id local_memory{};
|
||||||
|
|
||||||
Id shared_memory_u8{};
|
Id shared_memory_u8{};
|
||||||
|
@ -148,6 +151,7 @@ private:
|
||||||
void DefineConstantBuffers(const Info& info, u32& binding);
|
void DefineConstantBuffers(const Info& info, u32& binding);
|
||||||
void DefineStorageBuffers(const Info& info, u32& binding);
|
void DefineStorageBuffers(const Info& info, u32& binding);
|
||||||
void DefineTextures(const Info& info, u32& binding);
|
void DefineTextures(const Info& info, u32& binding);
|
||||||
|
void DefineAttributeMemAccess(const Info& info);
|
||||||
void DefineLabels(IR::Program& program);
|
void DefineLabels(IR::Program& program);
|
||||||
|
|
||||||
void DefineConstantBuffers(const Info& info, Id UniformDefinitions::*member_type, u32 binding,
|
void DefineConstantBuffers(const Info& info, Id UniformDefinitions::*member_type, u32 binding,
|
||||||
|
|
|
@ -51,8 +51,8 @@ Id EmitGetCbufF32(EmitContext& ctx, const IR::Value& binding, const IR::Value& o
|
||||||
Id EmitGetCbufU32x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset);
|
Id EmitGetCbufU32x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset);
|
||||||
Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr);
|
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);
|
||||||
void EmitGetAttributeIndexed(EmitContext& ctx);
|
Id EmitGetAttributeIndexed(EmitContext& ctx, Id offset);
|
||||||
void EmitSetAttributeIndexed(EmitContext& ctx);
|
void EmitSetAttributeIndexed(EmitContext& ctx, Id offset, Id value);
|
||||||
void EmitSetFragColor(EmitContext& ctx, u32 index, u32 component, Id value);
|
void EmitSetFragColor(EmitContext& ctx, u32 index, u32 component, Id value);
|
||||||
void EmitSetFragDepth(EmitContext& ctx, Id value);
|
void EmitSetFragDepth(EmitContext& ctx, Id value);
|
||||||
void EmitGetZFlag(EmitContext& ctx);
|
void EmitGetZFlag(EmitContext& ctx);
|
||||||
|
|
|
@ -216,12 +216,12 @@ void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, Id value) {
|
||||||
ctx.OpStore(*output, value);
|
ctx.OpStore(*output, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitGetAttributeIndexed(EmitContext&) {
|
Id EmitGetAttributeIndexed(EmitContext& ctx, Id offset) {
|
||||||
throw NotImplementedException("SPIR-V Instruction");
|
return ctx.OpFunctionCall(ctx.F32[1], ctx.indexed_load_func, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitSetAttributeIndexed(EmitContext&) {
|
void EmitSetAttributeIndexed(EmitContext& ctx, Id offset, Id value) {
|
||||||
throw NotImplementedException("SPIR-V Instruction");
|
ctx.OpFunctionCall(ctx.void_id, ctx.indexed_store_func, offset, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitSetFragColor(EmitContext& ctx, u32 index, u32 component, Id value) {
|
void EmitSetFragColor(EmitContext& ctx, u32 index, u32 component, Id value) {
|
||||||
|
|
|
@ -307,6 +307,14 @@ void IREmitter::SetAttribute(IR::Attribute attribute, const F32& value) {
|
||||||
Inst(Opcode::SetAttribute, attribute, value);
|
Inst(Opcode::SetAttribute, attribute, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
F32 IREmitter::GetAttributeIndexed(IR::U32 phys_address) {
|
||||||
|
return Inst<F32>(Opcode::GetAttributeIndexed, phys_address);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IREmitter::SetAttributeIndexed(IR::U32 phys_address, const F32& value) {
|
||||||
|
Inst(Opcode::SetAttributeIndexed, phys_address, value);
|
||||||
|
}
|
||||||
|
|
||||||
void IREmitter::SetFragColor(u32 index, u32 component, const F32& value) {
|
void IREmitter::SetFragColor(u32 index, u32 component, const F32& value) {
|
||||||
Inst(Opcode::SetFragColor, Imm32(index), Imm32(component), value);
|
Inst(Opcode::SetFragColor, Imm32(index), Imm32(component), value);
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,6 +76,9 @@ public:
|
||||||
[[nodiscard]] F32 GetAttribute(IR::Attribute attribute);
|
[[nodiscard]] F32 GetAttribute(IR::Attribute attribute);
|
||||||
void SetAttribute(IR::Attribute attribute, const F32& value);
|
void SetAttribute(IR::Attribute attribute, const F32& value);
|
||||||
|
|
||||||
|
[[nodiscard]] F32 GetAttributeIndexed(IR::U32 phys_address);
|
||||||
|
void SetAttributeIndexed(IR::U32 phys_address, const F32& value);
|
||||||
|
|
||||||
void SetFragColor(u32 index, u32 component, const F32& value);
|
void SetFragColor(u32 index, u32 component, const F32& value);
|
||||||
void SetFragDepth(const F32& value);
|
void SetFragDepth(const F32& value);
|
||||||
|
|
||||||
|
|
|
@ -87,7 +87,7 @@ IR::Program TranslateProgram(ObjectPool<IR::Inst>& inst_pool, ObjectPool<IR::Blo
|
||||||
Optimization::DeadCodeEliminationPass(program);
|
Optimization::DeadCodeEliminationPass(program);
|
||||||
Optimization::IdentityRemovalPass(program);
|
Optimization::IdentityRemovalPass(program);
|
||||||
Optimization::VerificationPass(program);
|
Optimization::VerificationPass(program);
|
||||||
Optimization::CollectShaderInfoPass(program);
|
Optimization::CollectShaderInfoPass(env, program);
|
||||||
CollectInterpolationInfo(env, program);
|
CollectInterpolationInfo(env, program);
|
||||||
return program;
|
return program;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ enum class SampleMode : u64 {
|
||||||
Offset,
|
Offset,
|
||||||
};
|
};
|
||||||
|
|
||||||
int NumElements(Size size) {
|
u32 NumElements(Size size) {
|
||||||
switch (size) {
|
switch (size) {
|
||||||
case Size::B32:
|
case Size::B32:
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -65,15 +65,21 @@ void TranslatorVisitor::ALD(u64 insn) {
|
||||||
if (ald.patch != 0) {
|
if (ald.patch != 0) {
|
||||||
throw NotImplementedException("P");
|
throw NotImplementedException("P");
|
||||||
}
|
}
|
||||||
if (ald.index_reg != IR::Reg::RZ) {
|
|
||||||
throw NotImplementedException("Indexed");
|
|
||||||
}
|
|
||||||
const u64 offset{ald.absolute_offset.Value()};
|
const u64 offset{ald.absolute_offset.Value()};
|
||||||
if (offset % 4 != 0) {
|
if (offset % 4 != 0) {
|
||||||
throw NotImplementedException("Unaligned absolute offset {}", offset);
|
throw NotImplementedException("Unaligned absolute offset {}", offset);
|
||||||
}
|
}
|
||||||
const int num_elements{NumElements(ald.size)};
|
const u32 num_elements{NumElements(ald.size)};
|
||||||
for (int element = 0; element < num_elements; ++element) {
|
if (ald.index_reg != IR::Reg::RZ) {
|
||||||
|
const IR::U32 index_value = X(ald.index_reg);
|
||||||
|
for (u32 element = 0; element < num_elements; ++element) {
|
||||||
|
const IR::U32 final_offset =
|
||||||
|
element == 0 ? index_value : IR::U32{ir.IAdd(index_value, ir.Imm32(element * 4U))};
|
||||||
|
F(ald.dest_reg + element, ir.GetAttributeIndexed(final_offset));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (u32 element = 0; element < num_elements; ++element) {
|
||||||
F(ald.dest_reg + element, ir.GetAttribute(IR::Attribute{offset / 4 + element}));
|
F(ald.dest_reg + element, ir.GetAttribute(IR::Attribute{offset / 4 + element}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,8 +109,17 @@ void TranslatorVisitor::AST(u64 insn) {
|
||||||
if (offset % 4 != 0) {
|
if (offset % 4 != 0) {
|
||||||
throw NotImplementedException("Unaligned absolute offset {}", offset);
|
throw NotImplementedException("Unaligned absolute offset {}", offset);
|
||||||
}
|
}
|
||||||
const int num_elements{NumElements(ast.size)};
|
const u32 num_elements{NumElements(ast.size)};
|
||||||
for (int element = 0; element < num_elements; ++element) {
|
if (ast.index_reg != IR::Reg::RZ) {
|
||||||
|
const IR::U32 index_value = X(ast.index_reg);
|
||||||
|
for (u32 element = 0; element < num_elements; ++element) {
|
||||||
|
const IR::U32 final_offset =
|
||||||
|
element == 0 ? index_value : IR::U32{ir.IAdd(index_value, ir.Imm32(element * 4U))};
|
||||||
|
ir.SetAttributeIndexed(final_offset, F(ast.src_reg + element));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (u32 element = 0; element < num_elements; ++element) {
|
||||||
ir.SetAttribute(IR::Attribute{offset / 4 + element}, F(ast.src_reg + element));
|
ir.SetAttribute(IR::Attribute{offset / 4 + element}, F(ast.src_reg + element));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -134,12 +149,9 @@ void TranslatorVisitor::IPA(u64 insn) {
|
||||||
// gl_FragColor = colors[idx];
|
// gl_FragColor = colors[idx];
|
||||||
// }
|
// }
|
||||||
const bool is_indexed{ipa.idx != 0 && ipa.index_reg != IR::Reg::RZ};
|
const bool is_indexed{ipa.idx != 0 && ipa.index_reg != IR::Reg::RZ};
|
||||||
if (is_indexed) {
|
|
||||||
throw NotImplementedException("IDX");
|
|
||||||
}
|
|
||||||
|
|
||||||
const IR::Attribute attribute{ipa.attribute};
|
const IR::Attribute attribute{ipa.attribute};
|
||||||
IR::F32 value{ir.GetAttribute(attribute)};
|
IR::F32 value{is_indexed ? ir.GetAttributeIndexed(X(ipa.index_reg))
|
||||||
|
: ir.GetAttribute(attribute)};
|
||||||
if (IR::IsGeneric(attribute)) {
|
if (IR::IsGeneric(attribute)) {
|
||||||
const ProgramHeader& sph{env.SPH()};
|
const ProgramHeader& sph{env.SPH()};
|
||||||
const u32 attr_index{IR::GenericAttributeIndex(attribute)};
|
const u32 attr_index{IR::GenericAttributeIndex(attribute)};
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include "shader_recompiler/environment.h"
|
||||||
#include "shader_recompiler/frontend/ir/microinstruction.h"
|
#include "shader_recompiler/frontend/ir/microinstruction.h"
|
||||||
#include "shader_recompiler/frontend/ir/modifiers.h"
|
#include "shader_recompiler/frontend/ir/modifiers.h"
|
||||||
#include "shader_recompiler/frontend/ir/program.h"
|
#include "shader_recompiler/frontend/ir/program.h"
|
||||||
|
@ -323,6 +324,12 @@ void VisitUsages(Info& info, IR::Inst& inst) {
|
||||||
case IR::Opcode::SetAttribute:
|
case IR::Opcode::SetAttribute:
|
||||||
SetAttribute(info, inst.Arg(0).Attribute());
|
SetAttribute(info, inst.Arg(0).Attribute());
|
||||||
break;
|
break;
|
||||||
|
case IR::Opcode::GetAttributeIndexed:
|
||||||
|
info.loads_indexed_attributes = true;
|
||||||
|
break;
|
||||||
|
case IR::Opcode::SetAttributeIndexed:
|
||||||
|
info.stores_indexed_attributes = true;
|
||||||
|
break;
|
||||||
case IR::Opcode::SetFragColor:
|
case IR::Opcode::SetFragColor:
|
||||||
info.stores_frag_color[inst.Arg(0).U32()] = true;
|
info.stores_frag_color[inst.Arg(0).U32()] = true;
|
||||||
break;
|
break;
|
||||||
|
@ -502,15 +509,42 @@ void Visit(Info& info, IR::Inst& inst) {
|
||||||
VisitUsages(info, inst);
|
VisitUsages(info, inst);
|
||||||
VisitFpModifiers(info, inst);
|
VisitFpModifiers(info, inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GatherInfoFromHeader(Environment& env, Info& info) {
|
||||||
|
auto stage = env.ShaderStage();
|
||||||
|
if (stage == Stage::Compute) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto& header = env.SPH();
|
||||||
|
if (stage == Stage::Fragment) {
|
||||||
|
for (size_t i = 0; i < info.input_generics.size(); i++) {
|
||||||
|
info.input_generics[i].used =
|
||||||
|
info.input_generics[i].used || header.ps.IsGenericVectorActive(i);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < info.input_generics.size(); i++) {
|
||||||
|
info.input_generics[i].used =
|
||||||
|
info.input_generics[i].used || header.vtg.IsInputGenericVectorActive(i);
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < info.stores_generics.size(); i++) {
|
||||||
|
info.stores_generics[i] =
|
||||||
|
info.stores_generics[i] || header.vtg.IsOutputGenericVectorActive(i);
|
||||||
|
}
|
||||||
|
info.stores_clip_distance =
|
||||||
|
info.stores_clip_distance || header.vtg.omap_systemc.clip_distances != 0;
|
||||||
|
}
|
||||||
|
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
void CollectShaderInfoPass(IR::Program& program) {
|
void CollectShaderInfoPass(Environment& env, IR::Program& program) {
|
||||||
Info& info{program.info};
|
Info& info{program.info};
|
||||||
for (IR::Block* const block : program.post_order_blocks) {
|
for (IR::Block* const block : program.post_order_blocks) {
|
||||||
for (IR::Inst& inst : block->Instructions()) {
|
for (IR::Inst& inst : block->Instructions()) {
|
||||||
Visit(info, inst);
|
Visit(info, inst);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
GatherInfoFromHeader(env, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Shader::Optimization
|
} // namespace Shader::Optimization
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
namespace Shader::Optimization {
|
namespace Shader::Optimization {
|
||||||
|
|
||||||
void CollectShaderInfoPass(IR::Program& program);
|
void CollectShaderInfoPass(Environment& env, IR::Program& program);
|
||||||
void ConstantPropagationPass(IR::Program& program);
|
void ConstantPropagationPass(IR::Program& program);
|
||||||
void DeadCodeEliminationPass(IR::Program& program);
|
void DeadCodeEliminationPass(IR::Program& program);
|
||||||
void GlobalMemoryToStorageBufferPass(IR::Program& program);
|
void GlobalMemoryToStorageBufferPass(IR::Program& program);
|
||||||
|
|
|
@ -68,10 +68,24 @@ struct ProgramHeader {
|
||||||
|
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
INSERT_PADDING_BYTES_NOINIT(3); // ImapSystemValuesA
|
INSERT_PADDING_BYTES_NOINIT(3); // ImapSystemValuesA
|
||||||
INSERT_PADDING_BYTES_NOINIT(1); // ImapSystemValuesB
|
INSERT_PADDING_BYTES_NOINIT(1); // ImapSystemValuesB
|
||||||
INSERT_PADDING_BYTES_NOINIT(16); // ImapGenericVector[32]
|
|
||||||
INSERT_PADDING_BYTES_NOINIT(2); // ImapColor
|
union {
|
||||||
|
BitField<0, 1, u8> x;
|
||||||
|
BitField<1, 1, u8> y;
|
||||||
|
BitField<2, 1, u8> z;
|
||||||
|
BitField<3, 1, u8> w;
|
||||||
|
BitField<4, 1, u8> x2;
|
||||||
|
BitField<5, 1, u8> y2;
|
||||||
|
BitField<6, 1, u8> z2;
|
||||||
|
BitField<7, 1, u8> w2;
|
||||||
|
BitField<0, 4, u8> first;
|
||||||
|
BitField<4, 4, u8> second;
|
||||||
|
u8 raw;
|
||||||
|
} imap_generic_vector[16];
|
||||||
|
|
||||||
|
INSERT_PADDING_BYTES_NOINIT(2); // ImapColor
|
||||||
union {
|
union {
|
||||||
BitField<0, 8, u16> clip_distances;
|
BitField<0, 8, u16> clip_distances;
|
||||||
BitField<8, 1, u16> point_sprite_s;
|
BitField<8, 1, u16> point_sprite_s;
|
||||||
|
@ -82,15 +96,54 @@ struct ProgramHeader {
|
||||||
BitField<14, 1, u16> instance_id;
|
BitField<14, 1, u16> instance_id;
|
||||||
BitField<15, 1, u16> vertex_id;
|
BitField<15, 1, u16> vertex_id;
|
||||||
};
|
};
|
||||||
INSERT_PADDING_BYTES_NOINIT(5); // ImapFixedFncTexture[10]
|
INSERT_PADDING_BYTES_NOINIT(5); // ImapFixedFncTexture[10]
|
||||||
INSERT_PADDING_BYTES_NOINIT(1); // ImapReserved
|
INSERT_PADDING_BYTES_NOINIT(1); // ImapReserved
|
||||||
INSERT_PADDING_BYTES_NOINIT(3); // OmapSystemValuesA
|
INSERT_PADDING_BYTES_NOINIT(3); // OmapSystemValuesA
|
||||||
INSERT_PADDING_BYTES_NOINIT(1); // OmapSystemValuesB
|
INSERT_PADDING_BYTES_NOINIT(1); // OmapSystemValuesB
|
||||||
INSERT_PADDING_BYTES_NOINIT(16); // OmapGenericVector[32]
|
|
||||||
INSERT_PADDING_BYTES_NOINIT(2); // OmapColor
|
union {
|
||||||
INSERT_PADDING_BYTES_NOINIT(2); // OmapSystemValuesC
|
BitField<0, 1, u8> x;
|
||||||
INSERT_PADDING_BYTES_NOINIT(5); // OmapFixedFncTexture[10]
|
BitField<1, 1, u8> y;
|
||||||
INSERT_PADDING_BYTES_NOINIT(1); // OmapReserved
|
BitField<2, 1, u8> z;
|
||||||
|
BitField<3, 1, u8> w;
|
||||||
|
BitField<4, 1, u8> x2;
|
||||||
|
BitField<5, 1, u8> y2;
|
||||||
|
BitField<6, 1, u8> z2;
|
||||||
|
BitField<7, 1, u8> w2;
|
||||||
|
BitField<0, 4, u8> first;
|
||||||
|
BitField<4, 4, u8> second;
|
||||||
|
u8 raw;
|
||||||
|
} omap_generic_vector[16];
|
||||||
|
|
||||||
|
INSERT_PADDING_BYTES_NOINIT(2); // OmapColor
|
||||||
|
|
||||||
|
union {
|
||||||
|
BitField<0, 8, u16> clip_distances;
|
||||||
|
BitField<8, 1, u16> point_sprite_s;
|
||||||
|
BitField<9, 1, u16> point_sprite_t;
|
||||||
|
BitField<10, 1, u16> fog_coordinate;
|
||||||
|
BitField<12, 1, u16> tessellation_eval_point_u;
|
||||||
|
BitField<13, 1, u16> tessellation_eval_point_v;
|
||||||
|
BitField<14, 1, u16> instance_id;
|
||||||
|
BitField<15, 1, u16> vertex_id;
|
||||||
|
} omap_systemc;
|
||||||
|
|
||||||
|
INSERT_PADDING_BYTES_NOINIT(5); // OmapFixedFncTexture[10]
|
||||||
|
INSERT_PADDING_BYTES_NOINIT(1); // OmapReserved
|
||||||
|
|
||||||
|
[[nodiscard]] bool IsInputGenericVectorActive(size_t index) const {
|
||||||
|
if ((index & 1) == 0) {
|
||||||
|
return imap_generic_vector[index >> 1].first != 0;
|
||||||
|
}
|
||||||
|
return imap_generic_vector[index >> 1].second != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool IsOutputGenericVectorActive(size_t index) const {
|
||||||
|
if ((index & 1) == 0) {
|
||||||
|
return omap_generic_vector[index >> 1].first != 0;
|
||||||
|
}
|
||||||
|
return omap_generic_vector[index >> 1].second != 0;
|
||||||
|
}
|
||||||
} vtg;
|
} vtg;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
@ -128,6 +181,10 @@ struct ProgramHeader {
|
||||||
const auto& vector{imap_generic_vector[attribute]};
|
const auto& vector{imap_generic_vector[attribute]};
|
||||||
return {vector.x, vector.y, vector.z, vector.w};
|
return {vector.x, vector.y, vector.z, vector.w};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool IsGenericVectorActive(size_t index) const {
|
||||||
|
return imap_generic_vector[index].raw != 0;
|
||||||
|
}
|
||||||
} ps;
|
} ps;
|
||||||
|
|
||||||
std::array<u32, 0xf> raw;
|
std::array<u32, 0xf> raw;
|
||||||
|
|
|
@ -76,6 +76,7 @@ struct Info {
|
||||||
bool loads_vertex_id{};
|
bool loads_vertex_id{};
|
||||||
bool loads_front_face{};
|
bool loads_front_face{};
|
||||||
bool loads_point_coord{};
|
bool loads_point_coord{};
|
||||||
|
bool loads_indexed_attributes{};
|
||||||
|
|
||||||
std::array<bool, 8> stores_frag_color{};
|
std::array<bool, 8> stores_frag_color{};
|
||||||
bool stores_frag_depth{};
|
bool stores_frag_depth{};
|
||||||
|
@ -84,6 +85,7 @@ struct Info {
|
||||||
bool stores_point_size{};
|
bool stores_point_size{};
|
||||||
bool stores_clip_distance{};
|
bool stores_clip_distance{};
|
||||||
bool stores_viewport_index{};
|
bool stores_viewport_index{};
|
||||||
|
bool stores_indexed_attributes{};
|
||||||
|
|
||||||
bool uses_fp16{};
|
bool uses_fp16{};
|
||||||
bool uses_fp64{};
|
bool uses_fp64{};
|
||||||
|
|
Loading…
Reference in a new issue