From d171083d53e106c8c5131522fdc81d51360c562d Mon Sep 17 00:00:00 2001 From: ameerj <52414509+ameerj@users.noreply.github.com> Date: Wed, 26 May 2021 21:18:17 -0400 Subject: [PATCH] glsl: textures wip --- .../backend/glsl/emit_context.cpp | 54 ++++++++++++-- .../backend/glsl/emit_context.h | 8 +++ .../backend/glsl/emit_glsl.cpp | 6 +- .../glsl/emit_glsl_bitwise_conversion.cpp | 2 +- .../backend/glsl/emit_glsl_image.cpp | 24 ++++++- .../backend/glsl/emit_glsl_instructions.h | 10 +-- .../glsl/emit_glsl_not_implemented.cpp | 27 ++++--- .../backend/glsl/reg_alloc.cpp | 72 +++++++------------ .../backend/glsl/reg_alloc.h | 11 +-- 9 files changed, 139 insertions(+), 75 deletions(-) diff --git a/src/shader_recompiler/backend/glsl/emit_context.cpp b/src/shader_recompiler/backend/glsl/emit_context.cpp index 8e5983909..de19e0fba 100644 --- a/src/shader_recompiler/backend/glsl/emit_context.cpp +++ b/src/shader_recompiler/backend/glsl/emit_context.cpp @@ -8,9 +8,21 @@ #include "shader_recompiler/profile.h" namespace Shader::Backend::GLSL { +namespace { +std::string_view InterpDecorator(Interpolation interp) { + switch (interp) { + case Interpolation::Smooth: + return ""; + case Interpolation::Flat: + return "flat"; + case Interpolation::NoPerspective: + return "noperspective"; + } + throw InvalidArgument("Invalid interpolation {}", interp); +} +} // namespace -EmitContext::EmitContext(IR::Program& program, [[maybe_unused]] Bindings& bindings, - const Profile& profile_) +EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile& profile_) : info{program.info}, profile{profile_} { std::string header = "#version 450\n"; SetupExtensions(header); @@ -49,7 +61,8 @@ EmitContext::EmitContext(IR::Program& program, [[maybe_unused]] Bindings& bindin for (size_t index = 0; index < info.input_generics.size(); ++index) { const auto& generic{info.input_generics[index]}; if (generic.used) { - Add("layout(location={})in vec4 in_attr{};", index, index); + Add("layout(location={}) {} in vec4 in_attr{};", index, + InterpDecorator(generic.interpolation), index); } } for (size_t index = 0; index < info.stores_frag_color.size(); ++index) { @@ -66,6 +79,7 @@ EmitContext::EmitContext(IR::Program& program, [[maybe_unused]] Bindings& bindin DefineConstantBuffers(); DefineStorageBuffers(); DefineHelperFunctions(); + SetupImages(bindings); Add("void main(){{"); if (stage == Stage::VertexA || stage == Stage::VertexB) { @@ -102,7 +116,7 @@ void EmitContext::DefineConstantBuffers() { } u32 binding{}; for (const auto& desc : info.constant_buffer_descriptors) { - Add("layout(std140,binding={}) uniform cbuf_{}{{vec4 cbuf{}[{}];}};", binding, binding, + Add("layout(std140,binding={}) uniform cbuf_{}{{vec4 cbuf{}[{}];}};", binding, desc.index, desc.index, 4 * 1024); ++binding; } @@ -164,4 +178,36 @@ void EmitContext::DefineHelperFunctions() { } } +void EmitContext::SetupImages(Bindings& bindings) { + image_buffer_bindings.reserve(info.image_buffer_descriptors.size()); + for (const auto& desc : info.image_buffer_descriptors) { + throw NotImplementedException("image_buffer_descriptors"); + image_buffer_bindings.push_back(bindings.image); + bindings.image += desc.count; + } + image_bindings.reserve(info.image_descriptors.size()); + for (const auto& desc : info.image_descriptors) { + throw NotImplementedException("image_bindings"); + + image_bindings.push_back(bindings.image); + bindings.image += desc.count; + } + texture_buffer_bindings.reserve(info.texture_buffer_descriptors.size()); + for (const auto& desc : info.texture_buffer_descriptors) { + throw NotImplementedException("TextureType::Buffer"); + + texture_buffer_bindings.push_back(bindings.texture); + bindings.texture += desc.count; + } + texture_bindings.reserve(info.texture_descriptors.size()); + for (const auto& desc : info.texture_descriptors) { + texture_bindings.push_back(bindings.texture); + const auto indices{bindings.texture + desc.count}; + for (u32 index = bindings.texture; index < indices; ++index) { + Add("layout(binding={}) uniform sampler2D tex{};", bindings.texture, index); + } + bindings.texture += desc.count; + } +} + } // namespace Shader::Backend::GLSL diff --git a/src/shader_recompiler/backend/glsl/emit_context.h b/src/shader_recompiler/backend/glsl/emit_context.h index 087eaff6a..1cd051b24 100644 --- a/src/shader_recompiler/backend/glsl/emit_context.h +++ b/src/shader_recompiler/backend/glsl/emit_context.h @@ -6,6 +6,8 @@ #include #include +#include + #include #include "shader_recompiler/backend/glsl/reg_alloc.h" @@ -109,11 +111,17 @@ public: std::string_view stage_name = "invalid"; std::string_view attrib_name = "invalid"; + std::vector texture_buffer_bindings; + std::vector image_buffer_bindings; + std::vector texture_bindings; + std::vector image_bindings; + private: void SetupExtensions(std::string& header); void DefineConstantBuffers(); void DefineStorageBuffers(); void DefineHelperFunctions(); + void SetupImages(Bindings& bindings); }; } // namespace Shader::Backend::GLSL diff --git a/src/shader_recompiler/backend/glsl/emit_glsl.cpp b/src/shader_recompiler/backend/glsl/emit_glsl.cpp index a8e53cf66..35dbe19ec 100644 --- a/src/shader_recompiler/backend/glsl/emit_glsl.cpp +++ b/src/shader_recompiler/backend/glsl/emit_glsl.cpp @@ -113,7 +113,7 @@ void PrecolorInst(IR::Inst& phi) { if (arg.IsImmediate()) { ir.PhiMove(phi, arg); } else { - ir.PhiMove(phi, IR::Value{&RegAlloc::AliasInst(*arg.Inst())}); + ir.PhiMove(phi, IR::Value{&*arg.InstRecursive()}); } } for (size_t i = 0; i < num_args; ++i) { @@ -157,7 +157,7 @@ void EmitCode(EmitContext& ctx, const IR::Program& program) { break; case IR::AbstractSyntaxNode::Type::Return: case IR::AbstractSyntaxNode::Type::Unreachable: - ctx.Add("return;\n}}"); + ctx.Add("return;"); break; case IR::AbstractSyntaxNode::Type::Loop: case IR::AbstractSyntaxNode::Type::Repeat: @@ -175,6 +175,8 @@ std::string EmitGLSL(const Profile& profile, const RuntimeInfo&, IR::Program& pr EmitContext ctx{program, bindings, profile}; Precolor(program); EmitCode(ctx, program); + ctx.code += "}"; + fmt::print("\n{}\n", ctx.code); return ctx.code; } diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_bitwise_conversion.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_bitwise_conversion.cpp index 742f394d4..8512147e2 100644 --- a/src/shader_recompiler/backend/glsl/emit_glsl_bitwise_conversion.cpp +++ b/src/shader_recompiler/backend/glsl/emit_glsl_bitwise_conversion.cpp @@ -15,7 +15,7 @@ static void Alias(IR::Inst& inst, const IR::Value& value) { if (value.IsImmediate()) { return; } - IR::Inst& value_inst{RegAlloc::AliasInst(*value.Inst())}; + IR::Inst& value_inst{*value.InstRecursive()}; value_inst.DestructiveAddUsage(inst.UseCount()); value_inst.DestructiveRemoveUsage(); inst.SetDefinition(value_inst.Definition()); diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp index 109938e0e..cc5afc048 100644 --- a/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp +++ b/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp @@ -6,17 +6,39 @@ #include "shader_recompiler/backend/glsl/emit_context.h" #include "shader_recompiler/backend/glsl/emit_glsl_instructions.h" +#include "shader_recompiler/frontend/ir/modifiers.h" #include "shader_recompiler/frontend/ir/value.h" #include "shader_recompiler/profile.h" namespace Shader::Backend::GLSL { +namespace { +std::string Texture(EmitContext& ctx, IR::TextureInstInfo info, + [[maybe_unused]] const IR::Value& index) { + if (info.type == TextureType::Buffer) { + throw NotImplementedException("TextureType::Buffer"); + } else { + return fmt::format("tex{}", ctx.texture_bindings.at(info.descriptor_index)); + } +} +} // namespace void EmitImageSampleImplicitLod([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, [[maybe_unused]] const IR::Value& index, [[maybe_unused]] std::string_view coords, [[maybe_unused]] std::string_view bias_lc, [[maybe_unused]] const IR::Value& offset) { - throw NotImplementedException("GLSL Instruction"); + const auto info{inst.Flags()}; + if (info.has_bias) { + throw NotImplementedException("Bias texture samples"); + } + if (info.has_lod_clamp) { + throw NotImplementedException("Lod clamp samples"); + } + if (!offset.IsEmpty()) { + throw NotImplementedException("Offset"); + } + const auto texture{Texture(ctx, info, index)}; + ctx.AddF32x4("{}=texture({},{});", inst, texture, coords); } void EmitImageSampleExplicitLod([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h b/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h index 49ab108bb..c9b53bae2 100644 --- a/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h +++ b/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h @@ -89,11 +89,11 @@ void EmitIsHelperInvocation(EmitContext& ctx); void EmitYDirection(EmitContext& ctx); void EmitLoadLocal(EmitContext& ctx, std::string_view word_offset); void EmitWriteLocal(EmitContext& ctx, std::string_view word_offset, std::string_view value); -void EmitUndefU1(EmitContext& ctx); -void EmitUndefU8(EmitContext& ctx); -void EmitUndefU16(EmitContext& ctx); -void EmitUndefU32(EmitContext& ctx); -void EmitUndefU64(EmitContext& ctx); +void EmitUndefU1(EmitContext& ctx, IR::Inst& inst); +void EmitUndefU8(EmitContext& ctx, IR::Inst& inst); +void EmitUndefU16(EmitContext& ctx, IR::Inst& inst); +void EmitUndefU32(EmitContext& ctx, IR::Inst& inst); +void EmitUndefU64(EmitContext& ctx, IR::Inst& inst); void EmitLoadGlobalU8(EmitContext& ctx); void EmitLoadGlobalS8(EmitContext& ctx); void EmitLoadGlobalU16(EmitContext& ctx); diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_not_implemented.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_not_implemented.cpp index 14a2edd74..42b1e8764 100644 --- a/src/shader_recompiler/backend/glsl/emit_glsl_not_implemented.cpp +++ b/src/shader_recompiler/backend/glsl/emit_glsl_not_implemented.cpp @@ -39,17 +39,26 @@ void EmitReference(EmitContext&) { } void EmitPhiMove(EmitContext& ctx, const IR::Value& phi_value, const IR::Value& value) { - IR::Inst& phi{RegAlloc::AliasInst(*phi_value.Inst())}; + IR::Inst& phi{*phi_value.InstRecursive()}; + const auto phi_type{phi.Arg(0).Type()}; if (!phi.Definition().is_valid) { // The phi node wasn't forward defined - ctx.Add("{};", ctx.reg_alloc.Define(phi, phi.Arg(0).Type())); + ctx.Add("{};", ctx.reg_alloc.Define(phi, phi_type)); } const auto phi_reg{ctx.reg_alloc.Consume(IR::Value{&phi})}; const auto val_reg{ctx.reg_alloc.Consume(value)}; if (phi_reg == val_reg) { return; } - ctx.Add("{}={};", phi_reg, val_reg); + if (phi_type == value.Type()) { + ctx.Add("{}={}; // PHI MOVE", phi_reg, val_reg); + } else if (phi_type == IR::Type::U32 && value.Type() == IR::Type::F32) { + ctx.Add("{}=floatBitsToUint({}); // CAST PHI MOVE", phi_reg, val_reg); + } else { + throw NotImplementedException("{} to {} move", phi_type, value.Type()); + const auto cast{ctx.reg_alloc.GetGlslType(phi_type)}; + ctx.Add("{}={}({}); // CAST PHI MOVE", phi_reg, cast, val_reg); + } } void EmitBranch(EmitContext& ctx, std::string_view label) { @@ -235,23 +244,23 @@ void EmitWriteLocal(EmitContext& ctx, std::string_view word_offset, std::string_ NotImplemented(); } -void EmitUndefU1(EmitContext& ctx) { +void EmitUndefU1(EmitContext& ctx, IR::Inst& inst) { NotImplemented(); } -void EmitUndefU8(EmitContext& ctx) { +void EmitUndefU8(EmitContext& ctx, IR::Inst& inst) { NotImplemented(); } -void EmitUndefU16(EmitContext& ctx) { +void EmitUndefU16(EmitContext& ctx, IR::Inst& inst) { NotImplemented(); } -void EmitUndefU32(EmitContext& ctx) { - NotImplemented(); +void EmitUndefU32(EmitContext& ctx, IR::Inst& inst) { + ctx.AddU32("{}=0u;", inst); } -void EmitUndefU64(EmitContext& ctx) { +void EmitUndefU64(EmitContext& ctx, IR::Inst& inst) { NotImplemented(); } diff --git a/src/shader_recompiler/backend/glsl/reg_alloc.cpp b/src/shader_recompiler/backend/glsl/reg_alloc.cpp index a080d5341..06f1965b5 100644 --- a/src/shader_recompiler/backend/glsl/reg_alloc.cpp +++ b/src/shader_recompiler/backend/glsl/reg_alloc.cpp @@ -71,26 +71,17 @@ std::string RegAlloc::Define(IR::Inst& inst) { std::string RegAlloc::Define(IR::Inst& inst, Type type) { const Id id{Alloc()}; - const auto type_str{GetType(type, id.index)}; + std::string type_str = ""; + if (!register_defined[id.index]) { + register_defined[id.index] = true; + type_str = GetGlslType(type); + } inst.SetDefinition(id); return type_str + Representation(id); } std::string RegAlloc::Define(IR::Inst& inst, IR::Type type) { - switch (type) { - case IR::Type::U1: - return Define(inst, Type::U1); - case IR::Type::U32: - return Define(inst, Type::U32); - case IR::Type::F32: - return Define(inst, Type::F32); - case IR::Type::U64: - return Define(inst, Type::U64); - case IR::Type::F64: - return Define(inst, Type::F64); - default: - throw NotImplementedException("IR type {}", type); - } + return Define(inst, RegType(type)); } std::string RegAlloc::Consume(const IR::Value& value) { @@ -107,11 +98,24 @@ std::string RegAlloc::Consume(IR::Inst& inst) { return Representation(inst.Definition()); } -std::string RegAlloc::GetType(Type type, u32 index) { - if (register_defined[index]) { - return ""; +Type RegAlloc::RegType(IR::Type type) { + switch (type) { + case IR::Type::U1: + return Type::U1; + case IR::Type::U32: + return Type::U32; + case IR::Type::F32: + return Type::F32; + case IR::Type::U64: + return Type::U64; + case IR::Type::F64: + return Type::F64; + default: + throw NotImplementedException("IR type {}", type); } - register_defined[index] = true; +} + +std::string RegAlloc::GetGlslType(Type type) { switch (type) { case Type::U1: return "bool "; @@ -144,6 +148,10 @@ std::string RegAlloc::GetType(Type type, u32 index) { } } +std::string RegAlloc::GetGlslType(IR::Type type) { + return GetGlslType(RegType(type)); +} + Id RegAlloc::Alloc() { if (num_used_registers < NUM_REGS) { for (size_t reg = 0; reg < NUM_REGS; ++reg) { @@ -170,30 +178,4 @@ void RegAlloc::Free(Id id) { register_use[id.index] = false; } -/*static*/ bool RegAlloc::IsAliased(const IR::Inst& inst) { - switch (inst.GetOpcode()) { - case IR::Opcode::Identity: - case IR::Opcode::BitCastU16F16: - case IR::Opcode::BitCastU32F32: - case IR::Opcode::BitCastU64F64: - case IR::Opcode::BitCastF16U16: - case IR::Opcode::BitCastF32U32: - case IR::Opcode::BitCastF64U64: - return true; - default: - return false; - } -} - -/*static*/ IR::Inst& RegAlloc::AliasInst(IR::Inst& inst) { - IR::Inst* it{&inst}; - while (IsAliased(*it)) { - const IR::Value arg{it->Arg(0)}; - if (arg.IsImmediate()) { - break; - } - it = arg.InstRecursive(); - } - return *it; -} } // namespace Shader::Backend::GLSL diff --git a/src/shader_recompiler/backend/glsl/reg_alloc.h b/src/shader_recompiler/backend/glsl/reg_alloc.h index df067d3ad..419d0bde0 100644 --- a/src/shader_recompiler/backend/glsl/reg_alloc.h +++ b/src/shader_recompiler/backend/glsl/reg_alloc.h @@ -59,20 +59,15 @@ public: std::string Define(IR::Inst& inst, IR::Type type); std::string Consume(const IR::Value& value); - - /// Returns true if the instruction is expected to be aliased to another - static bool IsAliased(const IR::Inst& inst); - - /// Returns the underlying value out of an alias sequence - static IR::Inst& AliasInst(IR::Inst& inst); + std::string GetGlslType(Type type); + std::string GetGlslType(IR::Type type); private: static constexpr size_t NUM_REGS = 4096; static constexpr size_t NUM_ELEMENTS = 4; std::string Consume(IR::Inst& inst); - std::string GetType(Type type, u32 index); - + Type RegType(IR::Type type); Id Alloc(); void Free(Id id);