glsl: textures wip

This commit is contained in:
ameerj 2021-05-26 21:18:17 -04:00
parent 3d086e6130
commit d171083d53
9 changed files with 139 additions and 75 deletions

View file

@ -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

View file

@ -6,6 +6,8 @@
#include <string>
#include <utility>
#include <vector>
#include <fmt/format.h>
#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<u32> texture_buffer_bindings;
std::vector<u32> image_buffer_bindings;
std::vector<u32> texture_bindings;
std::vector<u32> image_bindings;
private:
void SetupExtensions(std::string& header);
void DefineConstantBuffers();
void DefineStorageBuffers();
void DefineHelperFunctions();
void SetupImages(Bindings& bindings);
};
} // namespace Shader::Backend::GLSL

View file

@ -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;
}

View file

@ -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<Id>());

View file

@ -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<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,

View file

@ -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);

View file

@ -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<Id>().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();
}

View file

@ -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>(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<Id>());
}
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

View file

@ -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);