glsl: Fix bindings, add some CC ops
This commit is contained in:
		| @@ -20,6 +20,20 @@ std::string_view InterpDecorator(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 | ||||
|  | ||||
| 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) { | ||||
|     case Stage::VertexA: | ||||
|     case Stage::VertexB: | ||||
|         stage_name = "vertex"; | ||||
|         attrib_name = "vertex"; | ||||
|         stage_name = "vs"; | ||||
|         // TODO: add only what's used by the shader | ||||
|         header += | ||||
|             "out gl_PerVertex {vec4 gl_Position;float gl_PointSize;float gl_ClipDistance[];};"; | ||||
|         break; | ||||
|     case Stage::TessellationControl: | ||||
|     case Stage::TessellationEval: | ||||
|         stage_name = "primitive"; | ||||
|         attrib_name = "primitive"; | ||||
|         stage_name = "ts"; | ||||
|         break; | ||||
|     case Stage::Geometry: | ||||
|         stage_name = "primitive"; | ||||
|         attrib_name = "vertex"; | ||||
|         stage_name = "gs"; | ||||
|         break; | ||||
|     case Stage::Fragment: | ||||
|         stage_name = "fragment"; | ||||
|         attrib_name = "fragment"; | ||||
|         stage_name = "fs"; | ||||
|         break; | ||||
|     case Stage::Compute: | ||||
|         stage_name = "invocation"; | ||||
|         stage_name = "cs"; | ||||
|         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[2]); | ||||
| @@ -77,12 +87,12 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile | ||||
|             Add("layout(location={}) out vec4 out_attr{};", index, index); | ||||
|         } | ||||
|     } | ||||
|     DefineConstantBuffers(); | ||||
|     DefineStorageBuffers(); | ||||
|     DefineHelperFunctions(); | ||||
|     DefineConstantBuffers(bindings); | ||||
|     DefineStorageBuffers(bindings); | ||||
|     SetupImages(bindings); | ||||
|     Add("void main(){{"); | ||||
|     DefineHelperFunctions(); | ||||
|  | ||||
|     Add("void main(){{"); | ||||
|     if (stage == Stage::VertexA || stage == Stage::VertexB) { | ||||
|         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()) { | ||||
|         return; | ||||
|     } | ||||
|     u32 binding{}; | ||||
|     for (const auto& desc : info.constant_buffer_descriptors) { | ||||
|         Add("layout(std140,binding={}) uniform cbuf_{}{{vec4 cbuf{}[{}];}};", binding, desc.index, | ||||
|             desc.index, 4 * 1024); | ||||
|         ++binding; | ||||
|         Add("layout(std140,binding={}) uniform {}_cbuf_{}{{vec4 {}_cbuf{}[{}];}};", | ||||
|             bindings.uniform_buffer, stage_name, desc.index, stage_name, desc.index, 4 * 1024); | ||||
|         bindings.uniform_buffer += desc.count; | ||||
|     } | ||||
| } | ||||
|  | ||||
| void EmitContext::DefineStorageBuffers() { | ||||
| void EmitContext::DefineStorageBuffers(Bindings& bindings) { | ||||
|     if (info.storage_buffers_descriptors.empty()) { | ||||
|         return; | ||||
|     } | ||||
|     u32 binding{}; | ||||
|     for (const auto& desc : info.storage_buffers_descriptors) { | ||||
|         Add("layout(std430,binding={}) buffer ssbo_{}{{uint ssbo{}[];}};", binding, binding, | ||||
|             desc.cbuf_index, desc.count); | ||||
|         ++binding; | ||||
|         Add("layout(std430,binding={}) buffer ssbo_{}{{uint ssbo{}[];}};", bindings.storage_buffer, | ||||
|             bindings.storage_buffer, desc.cbuf_index); | ||||
|         bindings.storage_buffer += desc.count; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -203,10 +211,11 @@ void EmitContext::SetupImages(Bindings& bindings) { | ||||
|     } | ||||
|     texture_bindings.reserve(info.texture_descriptors.size()); | ||||
|     for (const auto& desc : info.texture_descriptors) { | ||||
|         const auto sampler_type{SamplerType(desc.type)}; | ||||
|         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); | ||||
|             Add("layout(binding={}) uniform {} tex{};", bindings.texture, sampler_type, index); | ||||
|         } | ||||
|         bindings.texture += desc.count; | ||||
|     } | ||||
|   | ||||
| @@ -127,7 +127,6 @@ public: | ||||
|  | ||||
|     Stage stage{}; | ||||
|     std::string_view stage_name = "invalid"; | ||||
|     std::string_view attrib_name = "invalid"; | ||||
|  | ||||
|     std::vector<u32> texture_buffer_bindings; | ||||
|     std::vector<u32> image_buffer_bindings; | ||||
| @@ -138,8 +137,8 @@ public: | ||||
|  | ||||
| private: | ||||
|     void SetupExtensions(std::string& header); | ||||
|     void DefineConstantBuffers(); | ||||
|     void DefineStorageBuffers(); | ||||
|     void DefineConstantBuffers(Bindings& bindings); | ||||
|     void DefineStorageBuffers(Bindings& bindings); | ||||
|     void DefineHelperFunctions(); | ||||
|     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, | ||||
|                     const IR::Value& offset) { | ||||
|     if (offset.IsImmediate()) { | ||||
|         ctx.AddU32("{}=floatBitsToUint(cbuf{}[{}].{});", inst, binding.U32(), offset.U32() / 16, | ||||
|                    OffsetSwizzle(offset.U32())); | ||||
|         ctx.AddU32("{}=floatBitsToUint({}_cbuf{}[{}].{});", inst, ctx.stage_name, binding.U32(), | ||||
|                    offset.U32() / 16, OffsetSwizzle(offset.U32())); | ||||
|     } else { | ||||
|         const auto offset_var{ctx.reg_alloc.Consume(offset)}; | ||||
|         ctx.AddU32("{}=floatBitsToUint(cbuf{}[{}/16][({}/4)%4]);", inst, binding.U32(), offset_var, | ||||
|                    offset_var); | ||||
|         ctx.AddU32("{}=floatBitsToUint({}_cbuf{}[{}/16][({}/4)%4]);", inst, ctx.stage_name, | ||||
|                    binding.U32(), offset_var, offset_var); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void EmitGetCbufF32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, | ||||
|                     const IR::Value& offset) { | ||||
|     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())); | ||||
|     } else { | ||||
|         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()) { | ||||
|         const auto u32_offset{offset.U32()}; | ||||
|         const auto index{(u32_offset / 4) % 4}; | ||||
|         ctx.AddU32x2("{}=uvec2(floatBitsToUint(cbuf{}[{}].{}),floatBitsToUint(cbuf{}[{}].{}));", | ||||
|                      inst, binding.U32(), offset.U32() / 16, OffsetSwizzle(offset.U32()), | ||||
|                      binding.U32(), (offset.U32() + 1) / 16, OffsetSwizzle(offset.U32() + 1)); | ||||
|         ctx.AddU32x2( | ||||
|             "{}=uvec2(floatBitsToUint({}_cbuf{}[{}].{}),floatBitsToUint({}_cbuf{}[{}].{}));", inst, | ||||
|             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 { | ||||
|         const auto offset_var{ctx.reg_alloc.Consume(offset)}; | ||||
|         ctx.AddU32x2("{}=uvec2(floatBitsToUint(cbuf{}[{}/16][({}/" | ||||
|                      "4)%4]),floatBitsToUint(cbuf{}[({}+1)/16][(({}+1/4))%4]));", | ||||
|                      inst, binding.U32(), offset_var, offset_var, binding.U32(), offset_var, | ||||
|                      offset_var); | ||||
|         ctx.AddU32x2("{}=uvec2(floatBitsToUint({}_cbuf{}[{}/16][({}/" | ||||
|                      "4)%4]),floatBitsToUint({}_cbuf{}[({}+1)/16][(({}+1/4))%4]));", | ||||
|                      inst, ctx.stage_name, binding.U32(), offset_var, offset_var, ctx.stage_name, | ||||
|                      binding.U32(), offset_var, offset_var); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -107,10 +110,10 @@ void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, | ||||
|         } | ||||
|         break; | ||||
|     case IR::Attribute::InstanceId: | ||||
|         ctx.AddS32("{}=gl_InstanceID;", inst, ctx.attrib_name); | ||||
|         ctx.AddS32("{}=gl_InstanceID;", inst); | ||||
|         break; | ||||
|     case IR::Attribute::VertexId: | ||||
|         ctx.AddS32("{}=gl_VertexID;", inst, ctx.attrib_name); | ||||
|         ctx.AddS32("{}=gl_VertexID;", inst); | ||||
|         break; | ||||
|     default: | ||||
|         fmt::print("Get attribute {}", attr); | ||||
|   | ||||
| @@ -32,14 +32,13 @@ void EmitImageSampleImplicitLod([[maybe_unused]] EmitContext& ctx, [[maybe_unuse | ||||
|     if (info.has_lod_clamp) { | ||||
|         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)}; | ||||
|     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, | ||||
|   | ||||
| @@ -207,8 +207,8 @@ void EmitCompositeInsertF64x3(EmitContext& ctx, std::string_view composite, std: | ||||
|                               u32 index); | ||||
| void EmitCompositeInsertF64x4(EmitContext& ctx, std::string_view composite, std::string_view object, | ||||
|                               u32 index); | ||||
| void EmitSelectU1(EmitContext& ctx, std::string_view cond, std::string_view true_value, | ||||
|                   std::string_view false_value); | ||||
| void EmitSelectU1(EmitContext& ctx, IR::Inst& inst, std::string_view cond, | ||||
|                   std::string_view true_value, std::string_view false_value); | ||||
| void EmitSelectU8(EmitContext& ctx, std::string_view cond, std::string_view true_value, | ||||
|                   std::string_view false_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" | ||||
|  | ||||
| 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) { | ||||
|     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) { | ||||
| @@ -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, | ||||
|                           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) { | ||||
|   | ||||
| @@ -29,7 +29,7 @@ void EmitPhi(EmitContext& ctx, IR::Inst& phi) { | ||||
| } | ||||
|  | ||||
| void EmitVoid(EmitContext& ctx) { | ||||
|     NotImplemented(); | ||||
|     // NotImplemented(); | ||||
| } | ||||
|  | ||||
| void EmitReference(EmitContext&) { | ||||
|   | ||||
| @@ -8,10 +8,9 @@ | ||||
| #include "shader_recompiler/frontend/ir/value.h" | ||||
|  | ||||
| namespace Shader::Backend::GLSL { | ||||
| void EmitSelectU1([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view cond, | ||||
|                   [[maybe_unused]] std::string_view true_value, | ||||
|                   [[maybe_unused]] std::string_view false_value) { | ||||
|     throw NotImplementedException("GLSL Instruction"); | ||||
| void EmitSelectU1(EmitContext& ctx, IR::Inst& inst, std::string_view cond, | ||||
|                   std::string_view true_value, std::string_view false_value) { | ||||
|     ctx.AddU1("{}={}?{}:{};", inst, cond, true_value, false_value); | ||||
| } | ||||
|  | ||||
| void EmitSelectU8([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view cond, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user