glsl: Fix bindings, add some CC ops
This commit is contained in:
parent
6674637853
commit
2a71333716
|
@ -20,6 +20,20 @@ std::string_view InterpDecorator(Interpolation interp) {
|
||||||
}
|
}
|
||||||
throw InvalidArgument("Invalid interpolation {}", interp);
|
throw InvalidArgument("Invalid interpolation {}", interp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string_view SamplerType(TextureType type) {
|
||||||
|
switch (type) {
|
||||||
|
case TextureType::Color2D:
|
||||||
|
return "sampler2D";
|
||||||
|
case TextureType::ColorArray2D:
|
||||||
|
return "sampler2DArray";
|
||||||
|
case TextureType::Color3D:
|
||||||
|
return "sampler3D";
|
||||||
|
default:
|
||||||
|
throw NotImplementedException("Texture type: {}", type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile& profile_,
|
EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile& profile_,
|
||||||
|
@ -31,27 +45,23 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile
|
||||||
switch (program.stage) {
|
switch (program.stage) {
|
||||||
case Stage::VertexA:
|
case Stage::VertexA:
|
||||||
case Stage::VertexB:
|
case Stage::VertexB:
|
||||||
stage_name = "vertex";
|
stage_name = "vs";
|
||||||
attrib_name = "vertex";
|
|
||||||
// TODO: add only what's used by the shader
|
// TODO: add only what's used by the shader
|
||||||
header +=
|
header +=
|
||||||
"out gl_PerVertex {vec4 gl_Position;float gl_PointSize;float gl_ClipDistance[];};";
|
"out gl_PerVertex {vec4 gl_Position;float gl_PointSize;float gl_ClipDistance[];};";
|
||||||
break;
|
break;
|
||||||
case Stage::TessellationControl:
|
case Stage::TessellationControl:
|
||||||
case Stage::TessellationEval:
|
case Stage::TessellationEval:
|
||||||
stage_name = "primitive";
|
stage_name = "ts";
|
||||||
attrib_name = "primitive";
|
|
||||||
break;
|
break;
|
||||||
case Stage::Geometry:
|
case Stage::Geometry:
|
||||||
stage_name = "primitive";
|
stage_name = "gs";
|
||||||
attrib_name = "vertex";
|
|
||||||
break;
|
break;
|
||||||
case Stage::Fragment:
|
case Stage::Fragment:
|
||||||
stage_name = "fragment";
|
stage_name = "fs";
|
||||||
attrib_name = "fragment";
|
|
||||||
break;
|
break;
|
||||||
case Stage::Compute:
|
case Stage::Compute:
|
||||||
stage_name = "invocation";
|
stage_name = "cs";
|
||||||
header += fmt::format("layout(local_size_x={},local_size_y={},local_size_z={}) in;\n",
|
header += fmt::format("layout(local_size_x={},local_size_y={},local_size_z={}) in;\n",
|
||||||
program.workgroup_size[0], program.workgroup_size[1],
|
program.workgroup_size[0], program.workgroup_size[1],
|
||||||
program.workgroup_size[2]);
|
program.workgroup_size[2]);
|
||||||
|
@ -77,12 +87,12 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile
|
||||||
Add("layout(location={}) out vec4 out_attr{};", index, index);
|
Add("layout(location={}) out vec4 out_attr{};", index, index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DefineConstantBuffers();
|
DefineConstantBuffers(bindings);
|
||||||
DefineStorageBuffers();
|
DefineStorageBuffers(bindings);
|
||||||
DefineHelperFunctions();
|
|
||||||
SetupImages(bindings);
|
SetupImages(bindings);
|
||||||
Add("void main(){{");
|
DefineHelperFunctions();
|
||||||
|
|
||||||
|
Add("void main(){{");
|
||||||
if (stage == Stage::VertexA || stage == Stage::VertexB) {
|
if (stage == Stage::VertexA || stage == Stage::VertexB) {
|
||||||
Add("gl_Position = vec4(0.0f, 0.0f, 0.0f, 1.0f);");
|
Add("gl_Position = vec4(0.0f, 0.0f, 0.0f, 1.0f);");
|
||||||
}
|
}
|
||||||
|
@ -112,27 +122,25 @@ void EmitContext::SetupExtensions(std::string& header) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitContext::DefineConstantBuffers() {
|
void EmitContext::DefineConstantBuffers(Bindings& bindings) {
|
||||||
if (info.constant_buffer_descriptors.empty()) {
|
if (info.constant_buffer_descriptors.empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
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, desc.index,
|
Add("layout(std140,binding={}) uniform {}_cbuf_{}{{vec4 {}_cbuf{}[{}];}};",
|
||||||
desc.index, 4 * 1024);
|
bindings.uniform_buffer, stage_name, desc.index, stage_name, desc.index, 4 * 1024);
|
||||||
++binding;
|
bindings.uniform_buffer += desc.count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitContext::DefineStorageBuffers() {
|
void EmitContext::DefineStorageBuffers(Bindings& bindings) {
|
||||||
if (info.storage_buffers_descriptors.empty()) {
|
if (info.storage_buffers_descriptors.empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
u32 binding{};
|
|
||||||
for (const auto& desc : info.storage_buffers_descriptors) {
|
for (const auto& desc : info.storage_buffers_descriptors) {
|
||||||
Add("layout(std430,binding={}) buffer ssbo_{}{{uint ssbo{}[];}};", binding, binding,
|
Add("layout(std430,binding={}) buffer ssbo_{}{{uint ssbo{}[];}};", bindings.storage_buffer,
|
||||||
desc.cbuf_index, desc.count);
|
bindings.storage_buffer, desc.cbuf_index);
|
||||||
++binding;
|
bindings.storage_buffer += desc.count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,10 +211,11 @@ void EmitContext::SetupImages(Bindings& bindings) {
|
||||||
}
|
}
|
||||||
texture_bindings.reserve(info.texture_descriptors.size());
|
texture_bindings.reserve(info.texture_descriptors.size());
|
||||||
for (const auto& desc : info.texture_descriptors) {
|
for (const auto& desc : info.texture_descriptors) {
|
||||||
|
const auto sampler_type{SamplerType(desc.type)};
|
||||||
texture_bindings.push_back(bindings.texture);
|
texture_bindings.push_back(bindings.texture);
|
||||||
const auto indices{bindings.texture + desc.count};
|
const auto indices{bindings.texture + desc.count};
|
||||||
for (u32 index = bindings.texture; index < indices; ++index) {
|
for (u32 index = bindings.texture; index < indices; ++index) {
|
||||||
Add("layout(binding={}) uniform sampler2D tex{};", bindings.texture, index);
|
Add("layout(binding={}) uniform {} tex{};", bindings.texture, sampler_type, index);
|
||||||
}
|
}
|
||||||
bindings.texture += desc.count;
|
bindings.texture += desc.count;
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,7 +127,6 @@ public:
|
||||||
|
|
||||||
Stage stage{};
|
Stage stage{};
|
||||||
std::string_view stage_name = "invalid";
|
std::string_view stage_name = "invalid";
|
||||||
std::string_view attrib_name = "invalid";
|
|
||||||
|
|
||||||
std::vector<u32> texture_buffer_bindings;
|
std::vector<u32> texture_buffer_bindings;
|
||||||
std::vector<u32> image_buffer_bindings;
|
std::vector<u32> image_buffer_bindings;
|
||||||
|
@ -138,8 +137,8 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void SetupExtensions(std::string& header);
|
void SetupExtensions(std::string& header);
|
||||||
void DefineConstantBuffers();
|
void DefineConstantBuffers(Bindings& bindings);
|
||||||
void DefineStorageBuffers();
|
void DefineStorageBuffers(Bindings& bindings);
|
||||||
void DefineHelperFunctions();
|
void DefineHelperFunctions();
|
||||||
void SetupImages(Bindings& bindings);
|
void SetupImages(Bindings& bindings);
|
||||||
};
|
};
|
||||||
|
|
|
@ -43,23 +43,24 @@ void EmitGetCbufS16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] const IR
|
||||||
void EmitGetCbufU32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
|
void EmitGetCbufU32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
|
||||||
const IR::Value& offset) {
|
const IR::Value& offset) {
|
||||||
if (offset.IsImmediate()) {
|
if (offset.IsImmediate()) {
|
||||||
ctx.AddU32("{}=floatBitsToUint(cbuf{}[{}].{});", inst, binding.U32(), offset.U32() / 16,
|
ctx.AddU32("{}=floatBitsToUint({}_cbuf{}[{}].{});", inst, ctx.stage_name, binding.U32(),
|
||||||
OffsetSwizzle(offset.U32()));
|
offset.U32() / 16, OffsetSwizzle(offset.U32()));
|
||||||
} else {
|
} else {
|
||||||
const auto offset_var{ctx.reg_alloc.Consume(offset)};
|
const auto offset_var{ctx.reg_alloc.Consume(offset)};
|
||||||
ctx.AddU32("{}=floatBitsToUint(cbuf{}[{}/16][({}/4)%4]);", inst, binding.U32(), offset_var,
|
ctx.AddU32("{}=floatBitsToUint({}_cbuf{}[{}/16][({}/4)%4]);", inst, ctx.stage_name,
|
||||||
offset_var);
|
binding.U32(), offset_var, offset_var);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitGetCbufF32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
|
void EmitGetCbufF32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
|
||||||
const IR::Value& offset) {
|
const IR::Value& offset) {
|
||||||
if (offset.IsImmediate()) {
|
if (offset.IsImmediate()) {
|
||||||
ctx.AddF32("{}=cbuf{}[{}].{};", inst, binding.U32(), offset.U32() / 16,
|
ctx.AddF32("{}={}_cbuf{}[{}].{};", inst, ctx.stage_name, binding.U32(), offset.U32() / 16,
|
||||||
OffsetSwizzle(offset.U32()));
|
OffsetSwizzle(offset.U32()));
|
||||||
} else {
|
} else {
|
||||||
const auto offset_var{ctx.reg_alloc.Consume(offset)};
|
const auto offset_var{ctx.reg_alloc.Consume(offset)};
|
||||||
ctx.AddF32("{}=cbuf{}[{}/16][({}/4)%4];", inst, binding.U32(), offset_var, offset_var);
|
ctx.AddF32("{}={}_cbuf{}[{}/16][({}/4)%4];", inst, ctx.stage_name, binding.U32(),
|
||||||
|
offset_var, offset_var);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,15 +69,17 @@ void EmitGetCbufU32x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding
|
||||||
if (offset.IsImmediate()) {
|
if (offset.IsImmediate()) {
|
||||||
const auto u32_offset{offset.U32()};
|
const auto u32_offset{offset.U32()};
|
||||||
const auto index{(u32_offset / 4) % 4};
|
const auto index{(u32_offset / 4) % 4};
|
||||||
ctx.AddU32x2("{}=uvec2(floatBitsToUint(cbuf{}[{}].{}),floatBitsToUint(cbuf{}[{}].{}));",
|
ctx.AddU32x2(
|
||||||
inst, binding.U32(), offset.U32() / 16, OffsetSwizzle(offset.U32()),
|
"{}=uvec2(floatBitsToUint({}_cbuf{}[{}].{}),floatBitsToUint({}_cbuf{}[{}].{}));", inst,
|
||||||
binding.U32(), (offset.U32() + 1) / 16, OffsetSwizzle(offset.U32() + 1));
|
ctx.stage_name, binding.U32(), offset.U32() / 16, OffsetSwizzle(offset.U32()),
|
||||||
|
ctx.stage_name, binding.U32(), (offset.U32() + 1) / 16,
|
||||||
|
OffsetSwizzle(offset.U32() + 1));
|
||||||
} else {
|
} else {
|
||||||
const auto offset_var{ctx.reg_alloc.Consume(offset)};
|
const auto offset_var{ctx.reg_alloc.Consume(offset)};
|
||||||
ctx.AddU32x2("{}=uvec2(floatBitsToUint(cbuf{}[{}/16][({}/"
|
ctx.AddU32x2("{}=uvec2(floatBitsToUint({}_cbuf{}[{}/16][({}/"
|
||||||
"4)%4]),floatBitsToUint(cbuf{}[({}+1)/16][(({}+1/4))%4]));",
|
"4)%4]),floatBitsToUint({}_cbuf{}[({}+1)/16][(({}+1/4))%4]));",
|
||||||
inst, binding.U32(), offset_var, offset_var, binding.U32(), offset_var,
|
inst, ctx.stage_name, binding.U32(), offset_var, offset_var, ctx.stage_name,
|
||||||
offset_var);
|
binding.U32(), offset_var, offset_var);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,10 +110,10 @@ void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case IR::Attribute::InstanceId:
|
case IR::Attribute::InstanceId:
|
||||||
ctx.AddS32("{}=gl_InstanceID;", inst, ctx.attrib_name);
|
ctx.AddS32("{}=gl_InstanceID;", inst);
|
||||||
break;
|
break;
|
||||||
case IR::Attribute::VertexId:
|
case IR::Attribute::VertexId:
|
||||||
ctx.AddS32("{}=gl_VertexID;", inst, ctx.attrib_name);
|
ctx.AddS32("{}=gl_VertexID;", inst);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fmt::print("Get attribute {}", attr);
|
fmt::print("Get attribute {}", attr);
|
||||||
|
|
|
@ -32,14 +32,13 @@ void EmitImageSampleImplicitLod([[maybe_unused]] EmitContext& ctx, [[maybe_unuse
|
||||||
if (info.has_lod_clamp) {
|
if (info.has_lod_clamp) {
|
||||||
throw NotImplementedException("Lod clamp samples");
|
throw NotImplementedException("Lod clamp samples");
|
||||||
}
|
}
|
||||||
if (!offset.IsEmpty()) {
|
|
||||||
throw NotImplementedException("Offset");
|
|
||||||
}
|
|
||||||
if (info.type != TextureType::Color2D) {
|
|
||||||
throw NotImplementedException("Texture type: {}", info.type.Value());
|
|
||||||
}
|
|
||||||
const auto texture{Texture(ctx, info, index)};
|
const auto texture{Texture(ctx, info, index)};
|
||||||
ctx.AddF32x4("{}=texture({},{});", inst, texture, coords);
|
if (!offset.IsEmpty()) {
|
||||||
|
ctx.AddF32x4("{}=textureOffset({},{},ivec2({}));", inst, texture, coords,
|
||||||
|
ctx.reg_alloc.Consume(offset));
|
||||||
|
} else {
|
||||||
|
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,
|
||||||
|
|
|
@ -207,8 +207,8 @@ void EmitCompositeInsertF64x3(EmitContext& ctx, std::string_view composite, std:
|
||||||
u32 index);
|
u32 index);
|
||||||
void EmitCompositeInsertF64x4(EmitContext& ctx, std::string_view composite, std::string_view object,
|
void EmitCompositeInsertF64x4(EmitContext& ctx, std::string_view composite, std::string_view object,
|
||||||
u32 index);
|
u32 index);
|
||||||
void EmitSelectU1(EmitContext& ctx, std::string_view cond, std::string_view true_value,
|
void EmitSelectU1(EmitContext& ctx, IR::Inst& inst, std::string_view cond,
|
||||||
std::string_view false_value);
|
std::string_view true_value, std::string_view false_value);
|
||||||
void EmitSelectU8(EmitContext& ctx, std::string_view cond, std::string_view true_value,
|
void EmitSelectU8(EmitContext& ctx, std::string_view cond, std::string_view true_value,
|
||||||
std::string_view false_value);
|
std::string_view false_value);
|
||||||
void EmitSelectU16(EmitContext& ctx, std::string_view cond, std::string_view true_value,
|
void EmitSelectU16(EmitContext& ctx, std::string_view cond, std::string_view true_value,
|
||||||
|
|
|
@ -8,8 +8,30 @@
|
||||||
#include "shader_recompiler/frontend/ir/value.h"
|
#include "shader_recompiler/frontend/ir/value.h"
|
||||||
|
|
||||||
namespace Shader::Backend::GLSL {
|
namespace Shader::Backend::GLSL {
|
||||||
|
namespace {
|
||||||
|
void SetZeroFlag(EmitContext& ctx, IR::Inst& inst, std::string_view result) {
|
||||||
|
IR::Inst* const zero{inst.GetAssociatedPseudoOperation(IR::Opcode::GetZeroFromOp)};
|
||||||
|
if (!zero) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ctx.AddU1("{}={}==0;", *zero, result);
|
||||||
|
zero->Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetSignFlag(EmitContext& ctx, IR::Inst& inst, std::string_view result) {
|
||||||
|
IR::Inst* const sign{inst.GetAssociatedPseudoOperation(IR::Opcode::GetSignFromOp)};
|
||||||
|
if (!sign) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ctx.AddU1("{}=int({})<0;", *sign, result);
|
||||||
|
sign->Invalidate();
|
||||||
|
}
|
||||||
|
} // Anonymous namespace
|
||||||
void EmitIAdd32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) {
|
void EmitIAdd32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) {
|
||||||
ctx.AddU32("{}={}+{};", inst, a, b);
|
const auto result{ctx.reg_alloc.Define(inst)};
|
||||||
|
ctx.Add("uint {}={}+{};", result, a, b);
|
||||||
|
SetZeroFlag(ctx, inst, result);
|
||||||
|
SetSignFlag(ctx, inst, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitIAdd64(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) {
|
void EmitIAdd64(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) {
|
||||||
|
@ -98,7 +120,10 @@ void EmitBitFieldSExtract(EmitContext& ctx, IR::Inst& inst, std::string_view bas
|
||||||
|
|
||||||
void EmitBitFieldUExtract(EmitContext& ctx, IR::Inst& inst, std::string_view base,
|
void EmitBitFieldUExtract(EmitContext& ctx, IR::Inst& inst, std::string_view base,
|
||||||
std::string_view offset, std::string_view count) {
|
std::string_view offset, std::string_view count) {
|
||||||
ctx.AddU32("{}=bitfieldExtract({}, int({}), int({}));", inst, base, offset, count);
|
const auto result{ctx.reg_alloc.Define(inst)};
|
||||||
|
ctx.Add("uint {}=bitfieldExtract({},int({}),int({}));", result, base, offset, count);
|
||||||
|
SetZeroFlag(ctx, inst, result);
|
||||||
|
SetSignFlag(ctx, inst, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitBitReverse32(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
|
void EmitBitReverse32(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
|
||||||
|
|
|
@ -29,7 +29,7 @@ void EmitPhi(EmitContext& ctx, IR::Inst& phi) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitVoid(EmitContext& ctx) {
|
void EmitVoid(EmitContext& ctx) {
|
||||||
NotImplemented();
|
// NotImplemented();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitReference(EmitContext&) {
|
void EmitReference(EmitContext&) {
|
||||||
|
|
|
@ -8,10 +8,9 @@
|
||||||
#include "shader_recompiler/frontend/ir/value.h"
|
#include "shader_recompiler/frontend/ir/value.h"
|
||||||
|
|
||||||
namespace Shader::Backend::GLSL {
|
namespace Shader::Backend::GLSL {
|
||||||
void EmitSelectU1([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view cond,
|
void EmitSelectU1(EmitContext& ctx, IR::Inst& inst, std::string_view cond,
|
||||||
[[maybe_unused]] std::string_view true_value,
|
std::string_view true_value, std::string_view false_value) {
|
||||||
[[maybe_unused]] std::string_view false_value) {
|
ctx.AddU1("{}={}?{}:{};", inst, cond, true_value, false_value);
|
||||||
throw NotImplementedException("GLSL Instruction");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitSelectU8([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view cond,
|
void EmitSelectU8([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view cond,
|
||||||
|
|
Reference in New Issue