shader_recompiler: Better branch detection + more opcodes

This commit is contained in:
raphaelthegreat 2024-06-01 20:25:31 +03:00
parent f624f7749c
commit 02a50265f8
31 changed files with 772 additions and 120 deletions

View file

@ -9,6 +9,7 @@
#include "shader_recompiler/backend/spirv/emit_spirv.h"
#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h"
#include "shader_recompiler/backend/spirv/spirv_emit_context.h"
#include "shader_recompiler/frontend/translate/translate.h"
#include "shader_recompiler/ir/basic_block.h"
#include "shader_recompiler/ir/program.h"
@ -28,6 +29,8 @@ ArgType Arg(EmitContext& ctx, const IR::Value& arg) {
return arg;
} else if constexpr (std::is_same_v<ArgType, u32>) {
return arg.U32();
} else if constexpr (std::is_same_v<ArgType, u64>) {
return arg.U64();
} else if constexpr (std::is_same_v<ArgType, IR::Attribute>) {
return arg.Attribute();
} else if constexpr (std::is_same_v<ArgType, IR::ScalarReg>) {
@ -279,6 +282,10 @@ void EmitGetVccLo(EmitContext& ctx) {
throw LogicError("Unreachable instruction");
}
void EmitGetVccHi(EmitContext& ctx) {
throw LogicError("Unreachable instruction");
}
void EmitSetScc(EmitContext& ctx) {
throw LogicError("Unreachable instruction");
}
@ -295,4 +302,8 @@ void EmitSetVccLo(EmitContext& ctx) {
throw LogicError("Unreachable instruction");
}
void EmitSetVccHi(EmitContext& ctx) {
throw LogicError("Unreachable instruction");
}
} // namespace Shader::Backend::SPIRV

View file

@ -33,6 +33,14 @@ Id EmitGetUserData(EmitContext& ctx, IR::ScalarReg reg) {
return ctx.ConstU32(ctx.info.user_data[static_cast<size_t>(reg)]);
}
void EmitGetThreadBitScalarReg(EmitContext& ctx) {
throw LogicError("Unreachable instruction");
}
void EmitSetThreadBitScalarReg(EmitContext& ctx) {
throw LogicError("Unreachable instruction");
}
void EmitGetScalarRegister(EmitContext&) {
throw LogicError("Unreachable instruction");
}
@ -68,7 +76,7 @@ Id EmitReadConstBuffer(EmitContext& ctx, u32 handle, Id index) {
}
Id EmitReadConstBufferU32(EmitContext& ctx, u32 handle, Id index) {
return EmitReadConstBuffer(ctx, handle, index);
return ctx.OpBitcast(ctx.U32[1], EmitReadConstBuffer(ctx, handle, index));
}
Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, u32 comp) {
@ -86,7 +94,13 @@ Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, u32 comp) {
return ctx.OpLoad(param.component_type, param.id);
}
}
throw NotImplementedException("Read attribute {}", attr);
switch (attr) {
case IR::Attribute::FragCoord:
return ctx.OpLoad(ctx.F32[1],
ctx.OpAccessChain(ctx.input_f32, ctx.frag_coord, ctx.ConstU32(comp)));
default:
throw NotImplementedException("Read attribute {}", attr);
}
}
Id EmitGetAttributeU32(EmitContext& ctx, IR::Attribute attr, u32 comp) {
@ -98,6 +112,9 @@ Id EmitGetAttributeU32(EmitContext& ctx, IR::Attribute attr, u32 comp) {
case IR::Attribute::LocalInvocationId:
return ctx.OpCompositeExtract(ctx.U32[1], ctx.OpLoad(ctx.U32[3], ctx.local_invocation_id),
comp);
case IR::Attribute::IsFrontFace:
return ctx.OpSelect(ctx.U32[1], ctx.OpLoad(ctx.U1[1], ctx.front_facing), ctx.u32_one_value,
ctx.u32_zero_value);
default:
throw NotImplementedException("Read U32 attribute {}", attr);
}
@ -136,19 +153,13 @@ Id EmitLoadBufferF32x3(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address)
Id EmitLoadBufferF32x4(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address) {
const auto info = inst->Flags<IR::BufferInstInfo>();
const auto& buffer = ctx.buffers[handle];
if (info.index_enable && info.offset_enable) {
UNREACHABLE();
} else if (info.index_enable) {
boost::container::static_vector<Id, 4> ids;
for (u32 i = 0; i < 4; i++) {
const Id index{ctx.OpIAdd(ctx.U32[1], address, ctx.ConstU32(i))};
const Id ptr{
ctx.OpAccessChain(buffer.pointer_type, buffer.id, ctx.u32_zero_value, index)};
ids.push_back(ctx.OpLoad(buffer.data_types->Get(1), ptr));
}
return ctx.OpCompositeConstruct(buffer.data_types->Get(4), ids);
boost::container::static_vector<Id, 4> ids;
for (u32 i = 0; i < 4; i++) {
const Id index{ctx.OpIAdd(ctx.U32[1], address, ctx.ConstU32(i))};
const Id ptr{ctx.OpAccessChain(buffer.pointer_type, buffer.id, ctx.u32_zero_value, index)};
ids.push_back(ctx.OpLoad(buffer.data_types->Get(1), ptr));
}
UNREACHABLE();
return ctx.OpCompositeConstruct(buffer.data_types->Get(4), ids);
}
void EmitStoreBufferF32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value) {

View file

@ -34,14 +34,18 @@ void EmitGetScc(EmitContext& ctx);
void EmitGetExec(EmitContext& ctx);
void EmitGetVcc(EmitContext& ctx);
void EmitGetVccLo(EmitContext& ctx);
void EmitGetVccHi(EmitContext& ctx);
void EmitSetScc(EmitContext& ctx);
void EmitSetExec(EmitContext& ctx);
void EmitSetVcc(EmitContext& ctx);
void EmitSetVccLo(EmitContext& ctx);
void EmitSetVccHi(EmitContext& ctx);
void EmitPrologue(EmitContext& ctx);
void EmitEpilogue(EmitContext& ctx);
void EmitDiscard(EmitContext& ctx);
Id EmitGetUserData(EmitContext& ctx, IR::ScalarReg reg);
void EmitGetThreadBitScalarReg(EmitContext& ctx);
void EmitSetThreadBitScalarReg(EmitContext& ctx);
void EmitGetScalarRegister(EmitContext& ctx);
void EmitSetScalarRegister(EmitContext& ctx);
void EmitGetVectorRegister(EmitContext& ctx);

View file

@ -94,6 +94,7 @@ void EmitContext::DefineArithmeticTypes() {
true_value = ConstantTrue(U1[1]);
false_value = ConstantFalse(U1[1]);
u32_one_value = ConstU32(1U);
u32_zero_value = ConstU32(0U);
f32_zero_value = ConstF32(0.0f);
@ -177,21 +178,24 @@ void EmitContext::DefineInputs(const Info& info) {
}
break;
case Stage::Fragment:
frag_coord = DefineVariable(F32[4], spv::BuiltIn::FragCoord, spv::StorageClass::Input);
front_facing = DefineVariable(U1[1], spv::BuiltIn::FrontFacing, spv::StorageClass::Input);
for (const auto& input : info.ps_inputs) {
const u32 semantic = input.param_index;
if (input.is_default) {
input_params[input.semantic] = {MakeDefaultValue(*this, input.default_value),
input_f32, F32[1]};
input_params[semantic] = {MakeDefaultValue(*this, input.default_value), input_f32,
F32[1]};
continue;
}
const IR::Attribute param{IR::Attribute::Param0 + input.param_index};
const u32 num_components = info.loads.NumComponents(param);
const Id type{F32[num_components]};
const Id id{DefineInput(type, input.semantic)};
const Id id{DefineInput(type, semantic)};
if (input.is_flat) {
Decorate(id, spv::Decoration::Flat);
}
Name(id, fmt::format("fs_in_attr{}", input.semantic));
input_params[input.semantic] = {id, input_f32, F32[1], num_components};
Name(id, fmt::format("fs_in_attr{}", semantic));
input_params[semantic] = {id, input_f32, F32[1], num_components};
interfaces.push_back(id);
}
break;
@ -260,7 +264,7 @@ void EmitContext::DefineBuffers(const Info& info) {
const Id id{AddGlobalVariable(struct_pointer_type, storage_class)};
Decorate(id, spv::Decoration::Binding, binding);
Decorate(id, spv::Decoration::DescriptorSet, 0U);
Name(id, fmt::format("{}{}", buffer.is_storage ? "ssbo" : "cbuf", i));
Name(id, fmt::format("{}_{}", buffer.is_storage ? "ssbo" : "cbuf", buffer.sgpr_base));
binding++;
buffers.push_back({
@ -318,7 +322,9 @@ Id ImageType(EmitContext& ctx, const ImageResource& desc, Id sampled_type) {
case AmdGpu::ImageType::Color2DArray:
return ctx.TypeImage(sampled_type, spv::Dim::Dim2D, false, true, false, 1, format);
case AmdGpu::ImageType::Color3D:
return ctx.TypeImage(sampled_type, spv::Dim::Dim3D, false, false, false, 2, format);
return ctx.TypeImage(sampled_type, spv::Dim::Dim3D, false, false, false, 1, format);
case AmdGpu::ImageType::Cube:
return ctx.TypeImage(sampled_type, spv::Dim::Cube, false, false, false, 1, format);
case AmdGpu::ImageType::Buffer:
throw NotImplementedException("Image buffer");
default:

View file

@ -140,6 +140,7 @@ public:
Id true_value{};
Id false_value{};
Id u32_one_value{};
Id u32_zero_value{};
Id f32_zero_value{};
@ -154,6 +155,8 @@ public:
Id output_position{};
Id vertex_index{};
Id base_vertex{};
Id frag_coord{};
Id front_facing{};
std::array<Id, 8> frag_color{};
Id workgroup_id{};