diff options
Diffstat (limited to 'src/shader_recompiler/backend/glsl')
| -rw-r--r-- | src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp | 170 |
1 files changed, 66 insertions, 104 deletions
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp index 711b568b1..5861c4d4c 100644 --- a/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp +++ b/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp | |||
| @@ -33,144 +33,106 @@ std::string InputVertexIndex(EmitContext& ctx, std::string_view vertex) { | |||
| 33 | std::string OutputVertexIndex(EmitContext& ctx) { | 33 | std::string OutputVertexIndex(EmitContext& ctx) { |
| 34 | return ctx.stage == Stage::TessellationControl ? "[gl_InvocationID]" : ""; | 34 | return ctx.stage == Stage::TessellationControl ? "[gl_InvocationID]" : ""; |
| 35 | } | 35 | } |
| 36 | } // Anonymous namespace | ||
| 37 | 36 | ||
| 38 | void EmitGetCbufU8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, | 37 | void GetCbuf(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, const IR::Value& offset, |
| 39 | const IR::Value& offset) { | 38 | u32 num_bits, std::string_view cast = {}, bool component_indexing_bug = false, |
| 40 | const auto cbuf{fmt::format("{}_cbuf{}", ctx.stage_name, binding.U32())}; | 39 | std::string_view bit_offset = {}) { |
| 41 | if (offset.IsImmediate()) { | 40 | const bool is_immediate{offset.IsImmediate()}; |
| 42 | ctx.AddU32("{}=bitfieldExtract(ftou({}[{}].{}),int({}),8);", inst, cbuf, offset.U32() / 16, | ||
| 43 | OffsetSwizzle(offset.U32()), (offset.U32() % 4) * 8); | ||
| 44 | return; | ||
| 45 | } | ||
| 46 | const auto offset_var{ctx.var_alloc.Consume(offset)}; | 41 | const auto offset_var{ctx.var_alloc.Consume(offset)}; |
| 47 | if (!ctx.profile.has_gl_component_indexing_bug) { | 42 | const auto index{is_immediate ? fmt::format("{}", offset.U32() / 16) |
| 48 | ctx.AddU32("{}=bitfieldExtract(ftou({}[{}>>4][({}>>2)%4]),int(({}%4)*8),8);", inst, cbuf, | 43 | : fmt::format("{}>>4", offset_var)}; |
| 49 | offset_var, offset_var, offset_var); | 44 | const auto swizzle{is_immediate ? fmt::format(".{}", OffsetSwizzle(offset.U32())) |
| 45 | : fmt::format("[({}>>2)%4]", offset_var)}; | ||
| 46 | |||
| 47 | const auto cbuf{fmt::format("{}_cbuf{}", ctx.stage_name, binding.U32())}; | ||
| 48 | const auto cbuf_cast{fmt::format("{}({}[{}]{{}})", cast, cbuf, index)}; | ||
| 49 | const auto extraction{num_bits == 32 ? cbuf_cast | ||
| 50 | : fmt ::format("bitfieldExtract({},int({}),{})", cbuf_cast, | ||
| 51 | bit_offset, num_bits)}; | ||
| 52 | if (!component_indexing_bug) { | ||
| 53 | const auto result{fmt::format(extraction, swizzle)}; | ||
| 54 | ctx.AddU32("{}={};", inst, result); | ||
| 50 | return; | 55 | return; |
| 51 | } | 56 | } |
| 52 | const auto ret{ctx.var_alloc.Define(inst, GlslVarType::U32)}; | 57 | const auto ret{ctx.var_alloc.Define(inst, GlslVarType::U32)}; |
| 53 | const auto cbuf_offset{fmt::format("{}>>2", offset_var)}; | 58 | const auto cbuf_offset{fmt::format("{}>>2", offset_var)}; |
| 54 | for (u32 swizzle = 0; swizzle < 4; ++swizzle) { | 59 | for (u32 i = 0; i < 4; ++i) { |
| 55 | ctx.Add("if(({}&3)=={}){}=bitfieldExtract(ftou({}[{}>>4].{}),int(({}%4)*8),8);", | 60 | const auto swizzle_string{fmt::format(".{}", "xyzw"[i])}; |
| 56 | cbuf_offset, swizzle, ret, cbuf, offset_var, "xyzw"[swizzle], offset_var); | 61 | const auto result{fmt::format(extraction, swizzle_string)}; |
| 62 | ctx.Add("if(({}&3)=={}){}={};", cbuf_offset, i, ret, result); | ||
| 57 | } | 63 | } |
| 58 | } | 64 | } |
| 59 | 65 | ||
| 60 | void EmitGetCbufS8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, | 66 | void GetCbuf8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, const IR::Value& offset, |
| 61 | const IR::Value& offset) { | 67 | std::string_view cast) { |
| 62 | const auto cbuf{fmt::format("{}_cbuf{}", ctx.stage_name, binding.U32())}; | ||
| 63 | if (offset.IsImmediate()) { | 68 | if (offset.IsImmediate()) { |
| 64 | ctx.AddU32("{}=bitfieldExtract(ftoi({}[{}].{}),int({}),8);", inst, cbuf, offset.U32() / 16, | 69 | const auto bit_offset{fmt::format("{}", (offset.U32() % 4) * 8)}; |
| 65 | OffsetSwizzle(offset.U32()), (offset.U32() % 4) * 8); | 70 | GetCbuf(ctx, inst, binding, offset, 8, cast, false, bit_offset); |
| 66 | return; | 71 | } else { |
| 67 | } | 72 | const auto offset_var{ctx.var_alloc.Consume(offset)}; |
| 68 | const auto offset_var{ctx.var_alloc.Consume(offset)}; | 73 | const auto bit_offset{fmt::format("({}%4)*8", offset_var)}; |
| 69 | if (!ctx.profile.has_gl_component_indexing_bug) { | 74 | GetCbuf(ctx, inst, binding, offset, 8, cast, ctx.profile.has_gl_component_indexing_bug, |
| 70 | ctx.AddU32("{}=bitfieldExtract(ftoi({}[{}>>4][({}>>2)%4]),int(({}%4)*8),8);", inst, cbuf, | 75 | bit_offset); |
| 71 | offset_var, offset_var, offset_var); | ||
| 72 | return; | ||
| 73 | } | 76 | } |
| 74 | const auto ret{ctx.var_alloc.Define(inst, GlslVarType::U32)}; | 77 | } |
| 75 | const auto cbuf_offset{fmt::format("{}>>2", offset_var)}; | 78 | |
| 76 | for (u32 swizzle = 0; swizzle < 4; ++swizzle) { | 79 | void GetCbuf16(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, const IR::Value& offset, |
| 77 | ctx.Add("if(({}&3)=={}){}=bitfieldExtract(ftoi({}[{}>>4].{}),int(({}%4)*8),8);", | 80 | std::string_view cast) { |
| 78 | cbuf_offset, swizzle, ret, cbuf, offset_var, "xyzw"[swizzle], offset_var); | 81 | if (offset.IsImmediate()) { |
| 82 | const auto bit_offset{fmt::format("{}", ((offset.U32() / 2) % 2) * 16)}; | ||
| 83 | GetCbuf(ctx, inst, binding, offset, 16, cast, false, bit_offset); | ||
| 84 | } else { | ||
| 85 | const auto offset_var{ctx.var_alloc.Consume(offset)}; | ||
| 86 | const auto bit_offset{fmt::format("(({}>>1)%2)*16", offset_var)}; | ||
| 87 | GetCbuf(ctx, inst, binding, offset, 16, cast, ctx.profile.has_gl_component_indexing_bug, | ||
| 88 | bit_offset); | ||
| 79 | } | 89 | } |
| 80 | } | 90 | } |
| 91 | } // Anonymous namespace | ||
| 92 | |||
| 93 | void EmitGetCbufU8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, | ||
| 94 | const IR::Value& offset) { | ||
| 95 | GetCbuf8(ctx, inst, binding, offset, "ftou"); | ||
| 96 | } | ||
| 97 | |||
| 98 | void EmitGetCbufS8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, | ||
| 99 | const IR::Value& offset) { | ||
| 100 | GetCbuf8(ctx, inst, binding, offset, "ftoi"); | ||
| 101 | } | ||
| 81 | 102 | ||
| 82 | void EmitGetCbufU16(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, | 103 | void EmitGetCbufU16(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, |
| 83 | const IR::Value& offset) { | 104 | const IR::Value& offset) { |
| 84 | const auto cbuf{fmt::format("{}_cbuf{}", ctx.stage_name, binding.U32())}; | 105 | GetCbuf16(ctx, inst, binding, offset, "ftou"); |
| 85 | if (offset.IsImmediate()) { | ||
| 86 | ctx.AddU32("{}=bitfieldExtract(ftou({}[{}].{}),int({}),16);", inst, cbuf, offset.U32() / 16, | ||
| 87 | OffsetSwizzle(offset.U32()), ((offset.U32() / 2) % 2) * 16); | ||
| 88 | return; | ||
| 89 | } | ||
| 90 | const auto offset_var{ctx.var_alloc.Consume(offset)}; | ||
| 91 | if (!ctx.profile.has_gl_component_indexing_bug) { | ||
| 92 | ctx.AddU32("{}=bitfieldExtract(ftou({}[{}>>4][({}>>2)%4]),int((({}>>1)%2)*16),16);", inst, | ||
| 93 | cbuf, offset_var, offset_var, offset_var); | ||
| 94 | return; | ||
| 95 | } | ||
| 96 | const auto ret{ctx.var_alloc.Define(inst, GlslVarType::U32)}; | ||
| 97 | const auto cbuf_offset{fmt::format("{}>>2", offset_var)}; | ||
| 98 | for (u32 swizzle = 0; swizzle < 4; ++swizzle) { | ||
| 99 | ctx.Add("if(({}&3)=={}){}=bitfieldExtract(ftou({}[{}>>4].{}),int((({}>>1)%2)*16),16);", | ||
| 100 | cbuf_offset, swizzle, ret, cbuf, offset_var, "xyzw"[swizzle], offset_var); | ||
| 101 | } | ||
| 102 | } | 106 | } |
| 103 | 107 | ||
| 104 | void EmitGetCbufS16(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, | 108 | void EmitGetCbufS16(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, |
| 105 | const IR::Value& offset) { | 109 | const IR::Value& offset) { |
| 106 | const auto cbuf{fmt::format("{}_cbuf{}", ctx.stage_name, binding.U32())}; | 110 | GetCbuf16(ctx, inst, binding, offset, "ftoi"); |
| 107 | if (offset.IsImmediate()) { | ||
| 108 | ctx.AddU32("{}=bitfieldExtract(ftoi({}[{}].{}),int({}),16);", inst, cbuf, offset.U32() / 16, | ||
| 109 | OffsetSwizzle(offset.U32()), ((offset.U32() / 2) % 2) * 16); | ||
| 110 | return; | ||
| 111 | } | ||
| 112 | const auto offset_var{ctx.var_alloc.Consume(offset)}; | ||
| 113 | if (!ctx.profile.has_gl_component_indexing_bug) { | ||
| 114 | ctx.AddU32("{}=bitfieldExtract(ftoi({}[{}>>4][({}>>2)%4]),int((({}>>1)%2)*16),16);", inst, | ||
| 115 | cbuf, offset_var, offset_var, offset_var); | ||
| 116 | return; | ||
| 117 | } | ||
| 118 | const auto ret{ctx.var_alloc.Define(inst, GlslVarType::U32)}; | ||
| 119 | const auto cbuf_offset{fmt::format("{}>>2", offset_var)}; | ||
| 120 | for (u32 swizzle = 0; swizzle < 4; ++swizzle) { | ||
| 121 | ctx.Add("if(({}&3)=={}){}=bitfieldExtract(ftoi({}[{}>>4].{}),int((({}>>1)%2)*16),16);", | ||
| 122 | cbuf_offset, swizzle, ret, cbuf, offset_var, "xyzw"[swizzle], offset_var); | ||
| 123 | } | ||
| 124 | } | 111 | } |
| 125 | 112 | ||
| 126 | void EmitGetCbufU32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, | 113 | void EmitGetCbufU32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, |
| 127 | const IR::Value& offset) { | 114 | const IR::Value& offset) { |
| 128 | const auto cbuf{fmt::format("{}_cbuf{}", ctx.stage_name, binding.U32())}; | 115 | GetCbuf(ctx, inst, binding, offset, 32, "ftou"); |
| 129 | if (offset.IsImmediate()) { | ||
| 130 | ctx.AddU32("{}=ftou({}[{}].{});", inst, cbuf, offset.U32() / 16, | ||
| 131 | OffsetSwizzle(offset.U32())); | ||
| 132 | return; | ||
| 133 | } | ||
| 134 | const auto offset_var{ctx.var_alloc.Consume(offset)}; | ||
| 135 | if (!ctx.profile.has_gl_component_indexing_bug) { | ||
| 136 | ctx.AddU32("{}=ftou({}[{}>>4][({}>>2)%4]);", inst, cbuf, offset_var, offset_var); | ||
| 137 | return; | ||
| 138 | } | ||
| 139 | const auto ret{ctx.var_alloc.Define(inst, GlslVarType::U32)}; | ||
| 140 | const auto cbuf_offset{fmt::format("{}>>2", offset_var)}; | ||
| 141 | for (u32 swizzle = 0; swizzle < 4; ++swizzle) { | ||
| 142 | ctx.Add("if(({}&3)=={}){}=ftou({}[{}>>4].{});", cbuf_offset, swizzle, ret, cbuf, offset_var, | ||
| 143 | "xyzw"[swizzle]); | ||
| 144 | } | ||
| 145 | } | 116 | } |
| 146 | 117 | ||
| 147 | void EmitGetCbufF32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, | 118 | void EmitGetCbufF32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, |
| 148 | const IR::Value& offset) { | 119 | const IR::Value& offset) { |
| 149 | const auto cbuf{fmt::format("{}_cbuf{}", ctx.stage_name, binding.U32())}; | 120 | GetCbuf(ctx, inst, binding, offset, 32); |
| 150 | if (offset.IsImmediate()) { | ||
| 151 | ctx.AddF32("{}={}[{}].{};", inst, cbuf, offset.U32() / 16, OffsetSwizzle(offset.U32())); | ||
| 152 | return; | ||
| 153 | } | ||
| 154 | const auto offset_var{ctx.var_alloc.Consume(offset)}; | ||
| 155 | if (!ctx.profile.has_gl_component_indexing_bug) { | ||
| 156 | ctx.AddF32("{}={}[{}>>4][({}>>2)%4];", inst, cbuf, offset_var, offset_var); | ||
| 157 | return; | ||
| 158 | } | ||
| 159 | const auto ret{ctx.var_alloc.Define(inst, GlslVarType::F32)}; | ||
| 160 | const auto cbuf_offset{fmt::format("{}>>2", offset_var)}; | ||
| 161 | for (u32 swizzle = 0; swizzle < 4; ++swizzle) { | ||
| 162 | ctx.Add("if(({}&3)=={}){}={}[{}>>4].{};", cbuf_offset, swizzle, ret, cbuf, offset_var, | ||
| 163 | "xyzw"[swizzle]); | ||
| 164 | } | ||
| 165 | } | 121 | } |
| 166 | 122 | ||
| 167 | void EmitGetCbufU32x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, | 123 | void EmitGetCbufU32x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, |
| 168 | const IR::Value& offset) { | 124 | const IR::Value& offset) { |
| 169 | const auto cbuf{fmt::format("{}_cbuf{}", ctx.stage_name, binding.U32())}; | 125 | const auto cbuf{fmt::format("{}_cbuf{}", ctx.stage_name, binding.U32())}; |
| 170 | if (offset.IsImmediate()) { | 126 | if (offset.IsImmediate()) { |
| 171 | ctx.AddU32x2("{}=uvec2(ftou({}[{}].{}),ftou({}[{}].{}));", inst, cbuf, offset.U32() / 16, | 127 | const u32 u32_offset{offset.U32()}; |
| 172 | OffsetSwizzle(offset.U32()), cbuf, (offset.U32() + 4) / 16, | 128 | if (u32_offset % 2 == 0) { |
| 173 | OffsetSwizzle(offset.U32() + 4)); | 129 | ctx.AddU32x2("{}=ftou({}[{}].{}{});", inst, cbuf, u32_offset / 16, |
| 130 | OffsetSwizzle(u32_offset), OffsetSwizzle(u32_offset + 4)); | ||
| 131 | } else { | ||
| 132 | ctx.AddU32x2("{}=uvec2(ftou({}[{}].{}),ftou({}[{}].{}));", inst, cbuf, u32_offset / 16, | ||
| 133 | OffsetSwizzle(u32_offset), cbuf, (u32_offset + 4) / 16, | ||
| 134 | OffsetSwizzle(u32_offset + 4)); | ||
| 135 | } | ||
| 174 | return; | 136 | return; |
| 175 | } | 137 | } |
| 176 | const auto offset_var{ctx.var_alloc.Consume(offset)}; | 138 | const auto offset_var{ctx.var_alloc.Consume(offset)}; |