shader: Move loop safety tests to code emission
This commit is contained in:
parent
3877918e96
commit
808ef97a08
16 changed files with 54 additions and 108 deletions
|
@ -71,6 +71,7 @@ public:
|
|||
std::string_view stage_name = "invalid";
|
||||
std::string_view attrib_name = "invalid";
|
||||
|
||||
u32 num_safety_loop_vars{};
|
||||
bool uses_y_direction{};
|
||||
};
|
||||
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
#include "common/div_ceil.h"
|
||||
#include "common/settings.h"
|
||||
#include "shader_recompiler/backend/bindings.h"
|
||||
#include "shader_recompiler/backend/glasm/emit_context.h"
|
||||
#include "shader_recompiler/backend/glasm/emit_glasm.h"
|
||||
|
@ -222,6 +224,14 @@ void EmitCode(EmitContext& ctx, const IR::Program& program) {
|
|||
ctx.Add("REP;");
|
||||
break;
|
||||
case IR::AbstractSyntaxNode::Type::Repeat:
|
||||
if (!Settings::values.disable_shader_loop_safety_checks) {
|
||||
const u32 loop_index{ctx.num_safety_loop_vars++};
|
||||
const u32 vector_index{loop_index / 4};
|
||||
const char component{"xyzw"[loop_index % 4]};
|
||||
ctx.Add("SUB.S.CC loop{}.{},loop{}.{},1;"
|
||||
"BRK(LT.{});",
|
||||
vector_index, component, vector_index, component, component);
|
||||
}
|
||||
if (node.data.repeat.cond.IsImmediate()) {
|
||||
if (node.data.repeat.cond.U1()) {
|
||||
ctx.Add("ENDREP;");
|
||||
|
@ -425,6 +435,10 @@ std::string EmitGLASM(const Profile& profile, const RuntimeInfo& runtime_info, I
|
|||
if (program.info.uses_fswzadd) {
|
||||
header += "FSWZA[4],FSWZB[4],";
|
||||
}
|
||||
const u32 num_safety_loop_vectors{Common::DivCeil(ctx.num_safety_loop_vars, 4u)};
|
||||
for (u32 index = 0; index < num_safety_loop_vectors; ++index) {
|
||||
header += fmt::format("loop{},", index);
|
||||
}
|
||||
header += "RC;"
|
||||
"LONG TEMP ";
|
||||
for (size_t index = 0; index < ctx.reg_alloc.NumUsedLongRegisters(); ++index) {
|
||||
|
@ -441,6 +455,9 @@ std::string EmitGLASM(const Profile& profile, const RuntimeInfo& runtime_info, I
|
|||
"MOV.F FSWZB[2],1;"
|
||||
"MOV.F FSWZB[3],-1;";
|
||||
}
|
||||
for (u32 index = 0; index < num_safety_loop_vectors; ++index) {
|
||||
header += fmt::format("MOV.S loop{},{{0x2000,0x2000,0x2000,0x2000}};", index);
|
||||
}
|
||||
if (ctx.uses_y_direction) {
|
||||
header += "PARAM y_direction[1]={state.material.front.ambient};";
|
||||
}
|
||||
|
|
|
@ -42,8 +42,6 @@ void EmitSetGotoVariable(EmitContext& ctx);
|
|||
void EmitGetGotoVariable(EmitContext& ctx);
|
||||
void EmitSetIndirectBranchVariable(EmitContext& ctx);
|
||||
void EmitGetIndirectBranchVariable(EmitContext& ctx);
|
||||
void EmitSetLoopSafetyVariable(EmitContext& ctx);
|
||||
void EmitGetLoopSafetyVariable(EmitContext& ctx);
|
||||
void EmitGetCbufU8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset);
|
||||
void EmitGetCbufS8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset);
|
||||
void EmitGetCbufU16(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset);
|
||||
|
|
|
@ -153,14 +153,6 @@ void EmitGetIndirectBranchVariable(EmitContext& ctx) {
|
|||
NotImplemented();
|
||||
}
|
||||
|
||||
void EmitSetLoopSafetyVariable(EmitContext& ctx) {
|
||||
NotImplemented();
|
||||
}
|
||||
|
||||
void EmitGetLoopSafetyVariable(EmitContext& ctx) {
|
||||
NotImplemented();
|
||||
}
|
||||
|
||||
void EmitGetZFlag(EmitContext& ctx) {
|
||||
NotImplemented();
|
||||
}
|
||||
|
|
|
@ -153,6 +153,8 @@ public:
|
|||
std::vector<TextureImageDefinition> images;
|
||||
std::array<std::array<GenericElementInfo, 4>, 32> output_generics{};
|
||||
|
||||
u32 num_safety_loop_vars{};
|
||||
|
||||
bool uses_y_direction{};
|
||||
bool uses_cc_carry{};
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <string>
|
||||
|
||||
#include "common/alignment.h"
|
||||
#include "common/settings.h"
|
||||
#include "shader_recompiler/backend/glsl/emit_context.h"
|
||||
#include "shader_recompiler/backend/glsl/emit_glsl.h"
|
||||
#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h"
|
||||
|
@ -156,7 +157,12 @@ void EmitCode(EmitContext& ctx, const IR::Program& program) {
|
|||
ctx.Add("for(;;){{");
|
||||
break;
|
||||
case IR::AbstractSyntaxNode::Type::Repeat:
|
||||
ctx.Add("if(!{}){{break;}}}}", ctx.var_alloc.Consume(node.data.repeat.cond));
|
||||
if (Settings::values.disable_shader_loop_safety_checks) {
|
||||
ctx.Add("if(!{}){{break;}}}}", ctx.var_alloc.Consume(node.data.repeat.cond));
|
||||
} else {
|
||||
ctx.Add("if(--loop{}<0 || !{}){{break;}}}}", ctx.num_safety_loop_vars++,
|
||||
ctx.var_alloc.Consume(node.data.repeat.cond));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw NotImplementedException("AbstractSyntaxNode Type {}", node.type);
|
||||
|
@ -198,6 +204,9 @@ void DefineVariables(const EmitContext& ctx, std::string& header) {
|
|||
ctx.var_alloc.Representation(index, type), type_name);
|
||||
}
|
||||
}
|
||||
for (u32 i = 0; i < ctx.num_safety_loop_vars; ++i) {
|
||||
header += fmt::format("int loop{}=0x2000;", i);
|
||||
}
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
|
|
|
@ -44,8 +44,6 @@ void EmitSetGotoVariable(EmitContext& ctx);
|
|||
void EmitGetGotoVariable(EmitContext& ctx);
|
||||
void EmitSetIndirectBranchVariable(EmitContext& ctx);
|
||||
void EmitGetIndirectBranchVariable(EmitContext& ctx);
|
||||
void EmitSetLoopSafetyVariable(EmitContext& ctx);
|
||||
void EmitGetLoopSafetyVariable(EmitContext& ctx);
|
||||
void EmitGetCbufU8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
|
||||
const IR::Value& offset);
|
||||
void EmitGetCbufS8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
|
||||
|
|
|
@ -46,14 +46,6 @@ void EmitGetIndirectBranchVariable(EmitContext& ctx) {
|
|||
NotImplemented();
|
||||
}
|
||||
|
||||
void EmitSetLoopSafetyVariable(EmitContext& ctx) {
|
||||
NotImplemented();
|
||||
}
|
||||
|
||||
void EmitGetLoopSafetyVariable(EmitContext& ctx) {
|
||||
NotImplemented();
|
||||
}
|
||||
|
||||
void EmitGetZFlag(EmitContext& ctx) {
|
||||
NotImplemented();
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "common/settings.h"
|
||||
#include "shader_recompiler/backend/spirv/emit_spirv.h"
|
||||
#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h"
|
||||
#include "shader_recompiler/frontend/ir/basic_block.h"
|
||||
|
@ -151,9 +152,25 @@ void Traverse(EmitContext& ctx, IR::Program& program) {
|
|||
}
|
||||
break;
|
||||
case IR::AbstractSyntaxNode::Type::Repeat: {
|
||||
Id cond{ctx.Def(node.data.repeat.cond)};
|
||||
if (!Settings::values.disable_shader_loop_safety_checks) {
|
||||
const Id pointer_type{ctx.TypePointer(spv::StorageClass::Private, ctx.U32[1])};
|
||||
const Id safety_counter{ctx.AddGlobalVariable(
|
||||
pointer_type, spv::StorageClass::Private, ctx.Const(0x2000u))};
|
||||
if (ctx.profile.supported_spirv >= 0x00010400) {
|
||||
ctx.interfaces.push_back(safety_counter);
|
||||
}
|
||||
const Id old_counter{ctx.OpLoad(ctx.U32[1], safety_counter)};
|
||||
const Id new_counter{ctx.OpISub(ctx.U32[1], old_counter, ctx.Const(1u))};
|
||||
ctx.OpStore(safety_counter, new_counter);
|
||||
|
||||
const Id safety_cond{
|
||||
ctx.OpSGreaterThanEqual(ctx.U1, new_counter, ctx.u32_zero_value)};
|
||||
cond = ctx.OpLogicalAnd(ctx.U1, cond, safety_cond);
|
||||
}
|
||||
const Id loop_header_label{node.data.repeat.loop_header->Definition<Id>()};
|
||||
const Id merge_label{node.data.repeat.merge->Definition<Id>()};
|
||||
ctx.OpBranchConditional(ctx.Def(node.data.repeat.cond), loop_header_label, merge_label);
|
||||
ctx.OpBranchConditional(cond, loop_header_label, merge_label);
|
||||
break;
|
||||
}
|
||||
case IR::AbstractSyntaxNode::Type::Return:
|
||||
|
|
|
@ -198,14 +198,6 @@ void EmitGetIndirectBranchVariable(EmitContext&) {
|
|||
throw LogicError("Unreachable instruction");
|
||||
}
|
||||
|
||||
void EmitSetLoopSafetyVariable(EmitContext&) {
|
||||
throw LogicError("Unreachable instruction");
|
||||
}
|
||||
|
||||
void EmitGetLoopSafetyVariable(EmitContext&) {
|
||||
throw LogicError("Unreachable instruction");
|
||||
}
|
||||
|
||||
Id EmitGetCbufU8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) {
|
||||
if (ctx.profile.support_descriptor_aliasing && ctx.profile.support_int8) {
|
||||
const Id load{GetCbuf(ctx, ctx.U8, &UniformDefinitions::U8, sizeof(u8), binding, offset)};
|
||||
|
|
|
@ -43,8 +43,6 @@ void EmitSetGotoVariable(EmitContext& ctx);
|
|||
void EmitGetGotoVariable(EmitContext& ctx);
|
||||
void EmitSetIndirectBranchVariable(EmitContext& ctx);
|
||||
void EmitGetIndirectBranchVariable(EmitContext& ctx);
|
||||
void EmitSetLoopSafetyVariable(EmitContext& ctx);
|
||||
void EmitGetLoopSafetyVariable(EmitContext& ctx);
|
||||
Id EmitGetCbufU8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset);
|
||||
Id EmitGetCbufS8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset);
|
||||
Id EmitGetCbufU16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue