glsl: textures wip
This commit is contained in:
parent
3d086e6130
commit
d171083d53
|
@ -8,9 +8,21 @@
|
||||||
#include "shader_recompiler/profile.h"
|
#include "shader_recompiler/profile.h"
|
||||||
|
|
||||||
namespace Shader::Backend::GLSL {
|
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,
|
EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile& profile_)
|
||||||
const Profile& profile_)
|
|
||||||
: info{program.info}, profile{profile_} {
|
: info{program.info}, profile{profile_} {
|
||||||
std::string header = "#version 450\n";
|
std::string header = "#version 450\n";
|
||||||
SetupExtensions(header);
|
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) {
|
for (size_t index = 0; index < info.input_generics.size(); ++index) {
|
||||||
const auto& generic{info.input_generics[index]};
|
const auto& generic{info.input_generics[index]};
|
||||||
if (generic.used) {
|
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) {
|
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();
|
DefineConstantBuffers();
|
||||||
DefineStorageBuffers();
|
DefineStorageBuffers();
|
||||||
DefineHelperFunctions();
|
DefineHelperFunctions();
|
||||||
|
SetupImages(bindings);
|
||||||
Add("void main(){{");
|
Add("void main(){{");
|
||||||
|
|
||||||
if (stage == Stage::VertexA || stage == Stage::VertexB) {
|
if (stage == Stage::VertexA || stage == Stage::VertexB) {
|
||||||
|
@ -102,7 +116,7 @@ void EmitContext::DefineConstantBuffers() {
|
||||||
}
|
}
|
||||||
u32 binding{};
|
u32 binding{};
|
||||||
for (const auto& desc : info.constant_buffer_descriptors) {
|
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);
|
desc.index, 4 * 1024);
|
||||||
++binding;
|
++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
|
} // namespace Shader::Backend::GLSL
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
|
||||||
#include "shader_recompiler/backend/glsl/reg_alloc.h"
|
#include "shader_recompiler/backend/glsl/reg_alloc.h"
|
||||||
|
@ -109,11 +111,17 @@ public:
|
||||||
std::string_view stage_name = "invalid";
|
std::string_view stage_name = "invalid";
|
||||||
std::string_view attrib_name = "invalid";
|
std::string_view attrib_name = "invalid";
|
||||||
|
|
||||||
|
std::vector<u32> texture_buffer_bindings;
|
||||||
|
std::vector<u32> image_buffer_bindings;
|
||||||
|
std::vector<u32> texture_bindings;
|
||||||
|
std::vector<u32> image_bindings;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void SetupExtensions(std::string& header);
|
void SetupExtensions(std::string& header);
|
||||||
void DefineConstantBuffers();
|
void DefineConstantBuffers();
|
||||||
void DefineStorageBuffers();
|
void DefineStorageBuffers();
|
||||||
void DefineHelperFunctions();
|
void DefineHelperFunctions();
|
||||||
|
void SetupImages(Bindings& bindings);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Shader::Backend::GLSL
|
} // namespace Shader::Backend::GLSL
|
||||||
|
|
|
@ -113,7 +113,7 @@ void PrecolorInst(IR::Inst& phi) {
|
||||||
if (arg.IsImmediate()) {
|
if (arg.IsImmediate()) {
|
||||||
ir.PhiMove(phi, arg);
|
ir.PhiMove(phi, arg);
|
||||||
} else {
|
} 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) {
|
for (size_t i = 0; i < num_args; ++i) {
|
||||||
|
@ -157,7 +157,7 @@ void EmitCode(EmitContext& ctx, const IR::Program& program) {
|
||||||
break;
|
break;
|
||||||
case IR::AbstractSyntaxNode::Type::Return:
|
case IR::AbstractSyntaxNode::Type::Return:
|
||||||
case IR::AbstractSyntaxNode::Type::Unreachable:
|
case IR::AbstractSyntaxNode::Type::Unreachable:
|
||||||
ctx.Add("return;\n}}");
|
ctx.Add("return;");
|
||||||
break;
|
break;
|
||||||
case IR::AbstractSyntaxNode::Type::Loop:
|
case IR::AbstractSyntaxNode::Type::Loop:
|
||||||
case IR::AbstractSyntaxNode::Type::Repeat:
|
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};
|
EmitContext ctx{program, bindings, profile};
|
||||||
Precolor(program);
|
Precolor(program);
|
||||||
EmitCode(ctx, program);
|
EmitCode(ctx, program);
|
||||||
|
ctx.code += "}";
|
||||||
|
fmt::print("\n{}\n", ctx.code);
|
||||||
return ctx.code;
|
return ctx.code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ static void Alias(IR::Inst& inst, const IR::Value& value) {
|
||||||
if (value.IsImmediate()) {
|
if (value.IsImmediate()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
IR::Inst& value_inst{RegAlloc::AliasInst(*value.Inst())};
|
IR::Inst& value_inst{*value.InstRecursive()};
|
||||||
value_inst.DestructiveAddUsage(inst.UseCount());
|
value_inst.DestructiveAddUsage(inst.UseCount());
|
||||||
value_inst.DestructiveRemoveUsage();
|
value_inst.DestructiveRemoveUsage();
|
||||||
inst.SetDefinition(value_inst.Definition<Id>());
|
inst.SetDefinition(value_inst.Definition<Id>());
|
||||||
|
|
|
@ -6,17 +6,39 @@
|
||||||
|
|
||||||
#include "shader_recompiler/backend/glsl/emit_context.h"
|
#include "shader_recompiler/backend/glsl/emit_context.h"
|
||||||
#include "shader_recompiler/backend/glsl/emit_glsl_instructions.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/frontend/ir/value.h"
|
||||||
#include "shader_recompiler/profile.h"
|
#include "shader_recompiler/profile.h"
|
||||||
|
|
||||||
namespace Shader::Backend::GLSL {
|
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,
|
void EmitImageSampleImplicitLod([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
|
||||||
[[maybe_unused]] const IR::Value& index,
|
[[maybe_unused]] const IR::Value& index,
|
||||||
[[maybe_unused]] std::string_view coords,
|
[[maybe_unused]] std::string_view coords,
|
||||||
[[maybe_unused]] std::string_view bias_lc,
|
[[maybe_unused]] std::string_view bias_lc,
|
||||||
[[maybe_unused]] const IR::Value& offset) {
|
[[maybe_unused]] const IR::Value& offset) {
|
||||||
throw NotImplementedException("GLSL Instruction");
|
const auto info{inst.Flags<IR::TextureInstInfo>()};
|
||||||
|
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,
|
void EmitImageSampleExplicitLod([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
|
||||||
|
|
|
@ -89,11 +89,11 @@ void EmitIsHelperInvocation(EmitContext& ctx);
|
||||||
void EmitYDirection(EmitContext& ctx);
|
void EmitYDirection(EmitContext& ctx);
|
||||||
void EmitLoadLocal(EmitContext& ctx, std::string_view word_offset);
|
void EmitLoadLocal(EmitContext& ctx, std::string_view word_offset);
|
||||||
void EmitWriteLocal(EmitContext& ctx, std::string_view word_offset, std::string_view value);
|
void EmitWriteLocal(EmitContext& ctx, std::string_view word_offset, std::string_view value);
|
||||||
void EmitUndefU1(EmitContext& ctx);
|
void EmitUndefU1(EmitContext& ctx, IR::Inst& inst);
|
||||||
void EmitUndefU8(EmitContext& ctx);
|
void EmitUndefU8(EmitContext& ctx, IR::Inst& inst);
|
||||||
void EmitUndefU16(EmitContext& ctx);
|
void EmitUndefU16(EmitContext& ctx, IR::Inst& inst);
|
||||||
void EmitUndefU32(EmitContext& ctx);
|
void EmitUndefU32(EmitContext& ctx, IR::Inst& inst);
|
||||||
void EmitUndefU64(EmitContext& ctx);
|
void EmitUndefU64(EmitContext& ctx, IR::Inst& inst);
|
||||||
void EmitLoadGlobalU8(EmitContext& ctx);
|
void EmitLoadGlobalU8(EmitContext& ctx);
|
||||||
void EmitLoadGlobalS8(EmitContext& ctx);
|
void EmitLoadGlobalS8(EmitContext& ctx);
|
||||||
void EmitLoadGlobalU16(EmitContext& ctx);
|
void EmitLoadGlobalU16(EmitContext& ctx);
|
||||||
|
|
|
@ -39,17 +39,26 @@ void EmitReference(EmitContext&) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitPhiMove(EmitContext& ctx, const IR::Value& phi_value, const IR::Value& value) {
|
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<Id>().is_valid) {
|
if (!phi.Definition<Id>().is_valid) {
|
||||||
// The phi node wasn't forward defined
|
// 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 phi_reg{ctx.reg_alloc.Consume(IR::Value{&phi})};
|
||||||
const auto val_reg{ctx.reg_alloc.Consume(value)};
|
const auto val_reg{ctx.reg_alloc.Consume(value)};
|
||||||
if (phi_reg == val_reg) {
|
if (phi_reg == val_reg) {
|
||||||
return;
|
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) {
|
void EmitBranch(EmitContext& ctx, std::string_view label) {
|
||||||
|
@ -235,23 +244,23 @@ void EmitWriteLocal(EmitContext& ctx, std::string_view word_offset, std::string_
|
||||||
NotImplemented();
|
NotImplemented();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitUndefU1(EmitContext& ctx) {
|
void EmitUndefU1(EmitContext& ctx, IR::Inst& inst) {
|
||||||
NotImplemented();
|
NotImplemented();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitUndefU8(EmitContext& ctx) {
|
void EmitUndefU8(EmitContext& ctx, IR::Inst& inst) {
|
||||||
NotImplemented();
|
NotImplemented();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitUndefU16(EmitContext& ctx) {
|
void EmitUndefU16(EmitContext& ctx, IR::Inst& inst) {
|
||||||
NotImplemented();
|
NotImplemented();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitUndefU32(EmitContext& ctx) {
|
void EmitUndefU32(EmitContext& ctx, IR::Inst& inst) {
|
||||||
NotImplemented();
|
ctx.AddU32("{}=0u;", inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitUndefU64(EmitContext& ctx) {
|
void EmitUndefU64(EmitContext& ctx, IR::Inst& inst) {
|
||||||
NotImplemented();
|
NotImplemented();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,26 +71,17 @@ std::string RegAlloc::Define(IR::Inst& inst) {
|
||||||
|
|
||||||
std::string RegAlloc::Define(IR::Inst& inst, Type type) {
|
std::string RegAlloc::Define(IR::Inst& inst, Type type) {
|
||||||
const Id id{Alloc()};
|
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>(id);
|
inst.SetDefinition<Id>(id);
|
||||||
return type_str + Representation(id);
|
return type_str + Representation(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string RegAlloc::Define(IR::Inst& inst, IR::Type type) {
|
std::string RegAlloc::Define(IR::Inst& inst, IR::Type type) {
|
||||||
switch (type) {
|
return Define(inst, RegType(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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string RegAlloc::Consume(const IR::Value& value) {
|
std::string RegAlloc::Consume(const IR::Value& value) {
|
||||||
|
@ -107,11 +98,24 @@ std::string RegAlloc::Consume(IR::Inst& inst) {
|
||||||
return Representation(inst.Definition<Id>());
|
return Representation(inst.Definition<Id>());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string RegAlloc::GetType(Type type, u32 index) {
|
Type RegAlloc::RegType(IR::Type type) {
|
||||||
if (register_defined[index]) {
|
switch (type) {
|
||||||
return "";
|
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) {
|
switch (type) {
|
||||||
case Type::U1:
|
case Type::U1:
|
||||||
return "bool ";
|
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() {
|
Id RegAlloc::Alloc() {
|
||||||
if (num_used_registers < NUM_REGS) {
|
if (num_used_registers < NUM_REGS) {
|
||||||
for (size_t reg = 0; reg < NUM_REGS; ++reg) {
|
for (size_t reg = 0; reg < NUM_REGS; ++reg) {
|
||||||
|
@ -170,30 +178,4 @@ void RegAlloc::Free(Id id) {
|
||||||
register_use[id.index] = false;
|
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
|
} // namespace Shader::Backend::GLSL
|
||||||
|
|
|
@ -59,20 +59,15 @@ public:
|
||||||
std::string Define(IR::Inst& inst, IR::Type type);
|
std::string Define(IR::Inst& inst, IR::Type type);
|
||||||
|
|
||||||
std::string Consume(const IR::Value& value);
|
std::string Consume(const IR::Value& value);
|
||||||
|
std::string GetGlslType(Type type);
|
||||||
/// Returns true if the instruction is expected to be aliased to another
|
std::string GetGlslType(IR::Type type);
|
||||||
static bool IsAliased(const IR::Inst& inst);
|
|
||||||
|
|
||||||
/// Returns the underlying value out of an alias sequence
|
|
||||||
static IR::Inst& AliasInst(IR::Inst& inst);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr size_t NUM_REGS = 4096;
|
static constexpr size_t NUM_REGS = 4096;
|
||||||
static constexpr size_t NUM_ELEMENTS = 4;
|
static constexpr size_t NUM_ELEMENTS = 4;
|
||||||
|
|
||||||
std::string Consume(IR::Inst& inst);
|
std::string Consume(IR::Inst& inst);
|
||||||
std::string GetType(Type type, u32 index);
|
Type RegType(IR::Type type);
|
||||||
|
|
||||||
Id Alloc();
|
Id Alloc();
|
||||||
void Free(Id id);
|
void Free(Id id);
|
||||||
|
|
||||||
|
|
Reference in New Issue