summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/backend/glsl
diff options
context:
space:
mode:
Diffstat (limited to 'src/shader_recompiler/backend/glsl')
-rw-r--r--src/shader_recompiler/backend/glsl/emit_context.cpp90
-rw-r--r--src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp69
-rw-r--r--src/shader_recompiler/backend/glsl/emit_glsl_floating_point.cpp2
-rw-r--r--src/shader_recompiler/backend/glsl/emit_glsl_instructions.h2
-rw-r--r--src/shader_recompiler/backend/glsl/emit_glsl_not_implemented.cpp10
5 files changed, 146 insertions, 27 deletions
diff --git a/src/shader_recompiler/backend/glsl/emit_context.cpp b/src/shader_recompiler/backend/glsl/emit_context.cpp
index 923060386..01403ca17 100644
--- a/src/shader_recompiler/backend/glsl/emit_context.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_context.cpp
@@ -21,10 +21,21 @@ std::string_view InterpDecorator(Interpolation interp) {
21 throw InvalidArgument("Invalid interpolation {}", interp); 21 throw InvalidArgument("Invalid interpolation {}", interp);
22} 22}
23 23
24std::string_view ArrayDecorator(Stage stage) { 24std::string_view InputArrayDecorator(Stage stage) {
25 switch (stage) { 25 switch (stage) {
26 case Stage::Geometry: 26 case Stage::Geometry:
27 return "[1]"; 27 case Stage::TessellationControl:
28 case Stage::TessellationEval:
29 return "[]";
30 default:
31 return "";
32 }
33}
34
35std::string OutputDecorator(Stage stage, u32 size) {
36 switch (stage) {
37 case Stage::TessellationControl:
38 return fmt::format("[{}]", size);
28 default: 39 default:
29 return ""; 40 return "";
30 } 41 }
@@ -73,6 +84,30 @@ std::string_view SamplerType(TextureType type, bool is_depth) {
73 } 84 }
74} 85}
75 86
87std::string_view GetTessMode(TessPrimitive primitive) {
88 switch (primitive) {
89 case TessPrimitive::Triangles:
90 return "triangles";
91 case TessPrimitive::Quads:
92 return "quads";
93 case TessPrimitive::Isolines:
94 return "isolines";
95 }
96 throw InvalidArgument("Invalid tessellation primitive {}", primitive);
97}
98
99std::string_view GetTessSpacing(TessSpacing spacing) {
100 switch (spacing) {
101 case TessSpacing::Equal:
102 return "equal_spacing";
103 case TessSpacing::FractionalOdd:
104 return "fractional_odd_spacing";
105 case TessSpacing::FractionalEven:
106 return "fractional_even_spacing";
107 }
108 throw InvalidArgument("Invalid tessellation spacing {}", spacing);
109}
110
76std::string_view InputPrimitive(InputTopology topology) { 111std::string_view InputPrimitive(InputTopology topology) {
77 switch (topology) { 112 switch (topology) {
78 case InputTopology::Points: 113 case InputTopology::Points:
@@ -100,6 +135,23 @@ std::string_view OutputPrimitive(OutputTopology topology) {
100 } 135 }
101 throw InvalidArgument("Invalid output topology {}", topology); 136 throw InvalidArgument("Invalid output topology {}", topology);
102} 137}
138
139void SetupOutPerVertex(Stage stage, const Info& info, std::string& header) {
140 if (stage != Stage::VertexA && stage != Stage::VertexB && stage != Stage::Geometry) {
141 return;
142 }
143 header += "out gl_PerVertex{";
144 if (info.stores_position) {
145 header += "vec4 gl_Position;";
146 }
147 if (info.stores_point_size) {
148 header += "float gl_PointSize;";
149 }
150 if (info.stores_clip_distance) {
151 header += "float gl_ClipDistance[];";
152 }
153 header += "};";
154}
103} // namespace 155} // namespace
104 156
105EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile& profile_, 157EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile& profile_,
@@ -111,17 +163,20 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile
111 case Stage::VertexA: 163 case Stage::VertexA:
112 case Stage::VertexB: 164 case Stage::VertexB:
113 stage_name = "vs"; 165 stage_name = "vs";
114 // TODO: add only what's used by the shader
115 header +=
116 "out gl_PerVertex {vec4 gl_Position;float gl_PointSize;float gl_ClipDistance[];};";
117 break; 166 break;
118 case Stage::TessellationControl: 167 case Stage::TessellationControl:
168 stage_name = "tsc";
169 header += fmt::format("layout(vertices={})out;\n", program.invocations);
170 break;
119 case Stage::TessellationEval: 171 case Stage::TessellationEval:
120 stage_name = "ts"; 172 stage_name = "tse";
173 header += fmt::format("layout({},{},{})in;\n", GetTessMode(runtime_info.tess_primitive),
174 GetTessSpacing(runtime_info.tess_spacing),
175 runtime_info.tess_clockwise ? "cw" : "ccw");
121 break; 176 break;
122 case Stage::Geometry: 177 case Stage::Geometry:
123 stage_name = "gs"; 178 stage_name = "gs";
124 header += fmt::format("layout({})in;layout({}, max_vertices={})out;\n", 179 header += fmt::format("layout({})in;layout({},max_vertices={})out;\n",
125 InputPrimitive(runtime_info.input_topology), 180 InputPrimitive(runtime_info.input_topology),
126 OutputPrimitive(program.output_topology), program.output_vertices); 181 OutputPrimitive(program.output_topology), program.output_vertices);
127 break; 182 break;
@@ -135,12 +190,23 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile
135 program.workgroup_size[2]); 190 program.workgroup_size[2]);
136 break; 191 break;
137 } 192 }
193 SetupOutPerVertex(stage, info, header);
138 for (size_t index = 0; index < info.input_generics.size(); ++index) { 194 for (size_t index = 0; index < info.input_generics.size(); ++index) {
139 const auto& generic{info.input_generics[index]}; 195 const auto& generic{info.input_generics[index]};
140 if (generic.used) { 196 if (generic.used) {
141 header += 197 header += fmt::format("layout(location={}){} in vec4 in_attr{}{};", index,
142 fmt::format("layout(location={}){} in vec4 in_attr{}{};", index, 198 InterpDecorator(generic.interpolation), index,
143 InterpDecorator(generic.interpolation), index, ArrayDecorator(stage)); 199 InputArrayDecorator(stage));
200 }
201 }
202 for (size_t index = 0; index < info.uses_patches.size(); ++index) {
203 if (!info.uses_patches[index]) {
204 continue;
205 }
206 if (stage == Stage::TessellationControl) {
207 header += fmt::format("layout(location={})patch out vec4 patch{};", index, index);
208 } else {
209 header += fmt::format("layout(location={})patch in vec4 patch{};", index, index);
144 } 210 }
145 } 211 }
146 for (size_t index = 0; index < info.stores_frag_color.size(); ++index) { 212 for (size_t index = 0; index < info.stores_frag_color.size(); ++index) {
@@ -151,8 +217,8 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile
151 } 217 }
152 for (size_t index = 0; index < info.stores_generics.size(); ++index) { 218 for (size_t index = 0; index < info.stores_generics.size(); ++index) {
153 // TODO: Properly resolve attribute issues 219 // TODO: Properly resolve attribute issues
154 const auto declaration{ 220 const auto declaration{fmt::format("layout(location={}) out vec4 out_attr{}{};", index,
155 fmt::format("layout(location={}) out vec4 out_attr{};", index, index)}; 221 index, OutputDecorator(stage, program.invocations))};
156 if (info.stores_generics[index] || stage == Stage::VertexA || stage == Stage::VertexB) { 222 if (info.stores_generics[index] || stage == Stage::VertexA || stage == Stage::VertexB) {
157 header += declaration; 223 header += declaration;
158 } 224 }
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 28e89a0a6..5c56477bf 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
@@ -25,9 +25,24 @@ bool IsInputArray(Stage stage) {
25 stage == Stage::TessellationEval; 25 stage == Stage::TessellationEval;
26} 26}
27 27
28std::string VertexIndex(EmitContext& ctx, std::string_view vertex) { 28std::string InputVertexIndex(EmitContext& ctx, std::string_view vertex) {
29 return IsInputArray(ctx.stage) ? fmt::format("[{}]", vertex) : ""; 29 return IsInputArray(ctx.stage) ? fmt::format("[{}]", vertex) : "";
30} 30}
31
32bool IsOutputArray(Stage stage) {
33 return stage == Stage::Geometry || stage == Stage::TessellationControl;
34}
35
36std::string OutputVertexIndex(EmitContext& ctx, std::string_view vertex) {
37 switch (ctx.stage) {
38 case Stage::Geometry:
39 return fmt::format("[{}]", vertex);
40 case Stage::TessellationControl:
41 return "[gl_InvocationID]";
42 default:
43 return "";
44 }
45}
31} // namespace 46} // namespace
32 47
33void EmitGetCbufU8([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, 48void EmitGetCbufU8([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
@@ -132,12 +147,12 @@ void EmitGetCbufU32x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding
132} 147}
133 148
134void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, 149void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr,
135 [[maybe_unused]] std::string_view vertex) { 150 std::string_view vertex) {
136 const u32 element{static_cast<u32>(attr) % 4}; 151 const u32 element{static_cast<u32>(attr) % 4};
137 const char swizzle{"xyzw"[element]}; 152 const char swizzle{"xyzw"[element]};
138 if (IR::IsGeneric(attr)) { 153 if (IR::IsGeneric(attr)) {
139 const u32 index{IR::GenericAttributeIndex(attr)}; 154 const u32 index{IR::GenericAttributeIndex(attr)};
140 ctx.AddF32("{}=in_attr{}{}.{};", inst, index, VertexIndex(ctx, vertex), swizzle); 155 ctx.AddF32("{}=in_attr{}{}.{};", inst, index, InputVertexIndex(ctx, vertex), swizzle);
141 return; 156 return;
142 } 157 }
143 switch (attr) { 158 switch (attr) {
@@ -150,6 +165,10 @@ void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr,
150 case Stage::VertexB: 165 case Stage::VertexB:
151 ctx.AddF32("{}=gl_Position.{};", inst, swizzle); 166 ctx.AddF32("{}=gl_Position.{};", inst, swizzle);
152 break; 167 break;
168 case Stage::TessellationEval:
169 ctx.AddF32("{}=gl_TessCoord.{};", inst, swizzle);
170 break;
171 case Stage::TessellationControl:
153 case Stage::Geometry: 172 case Stage::Geometry:
154 ctx.AddF32("{}=gl_in[{}].gl_Position.{};", inst, vertex, swizzle); 173 ctx.AddF32("{}=gl_in[{}].gl_Position.{};", inst, vertex, swizzle);
155 break; 174 break;
@@ -173,6 +192,10 @@ void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr,
173 case IR::Attribute::FrontFace: 192 case IR::Attribute::FrontFace:
174 ctx.AddF32("{}=intBitsToFloat(gl_FrontFacing?-1:0);", inst); 193 ctx.AddF32("{}=intBitsToFloat(gl_FrontFacing?-1:0);", inst);
175 break; 194 break;
195 case IR::Attribute::TessellationEvaluationPointU:
196 case IR::Attribute::TessellationEvaluationPointV:
197 ctx.AddF32("{}=gl_TessCoord.{};", inst, swizzle);
198 break;
176 default: 199 default:
177 fmt::print("Get attribute {}", attr); 200 fmt::print("Get attribute {}", attr);
178 throw NotImplementedException("Get attribute {}", attr); 201 throw NotImplementedException("Get attribute {}", attr);
@@ -185,7 +208,7 @@ void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, std::string_view val
185 const char swizzle{"xyzw"[element]}; 208 const char swizzle{"xyzw"[element]};
186 if (IR::IsGeneric(attr)) { 209 if (IR::IsGeneric(attr)) {
187 const u32 index{IR::GenericAttributeIndex(attr)}; 210 const u32 index{IR::GenericAttributeIndex(attr)};
188 ctx.Add("out_attr{}.{}={};", index, swizzle, value); 211 ctx.Add("out_attr{}{}.{}={};", index, OutputVertexIndex(ctx, vertex), swizzle, value);
189 return; 212 return;
190 } 213 }
191 switch (attr) { 214 switch (attr) {
@@ -219,6 +242,44 @@ void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, std::string_view val
219 } 242 }
220} 243}
221 244
245void EmitGetPatch([[maybe_unused]] EmitContext& ctx, IR::Inst& inst,
246 [[maybe_unused]] IR::Patch patch) {
247 if (!IR::IsGeneric(patch)) {
248 throw NotImplementedException("Non-generic patch load");
249 }
250 const u32 index{IR::GenericPatchIndex(patch)};
251 const u32 element{IR::GenericPatchElement(patch)};
252 const char swizzle{"xyzw"[element]};
253 ctx.AddF32("{}=patch{}.{};", inst, index, swizzle);
254}
255
256void EmitSetPatch(EmitContext& ctx, IR::Patch patch, std::string_view value) {
257 if (IR::IsGeneric(patch)) {
258 const u32 index{IR::GenericPatchIndex(patch)};
259 const u32 element{IR::GenericPatchElement(patch)};
260 ctx.Add("patch{}.{}={};", index, "xyzw"[element], value);
261 return;
262 }
263 switch (patch) {
264 case IR::Patch::TessellationLodLeft:
265 case IR::Patch::TessellationLodRight:
266 case IR::Patch::TessellationLodTop:
267 case IR::Patch::TessellationLodBottom: {
268 const u32 index{static_cast<u32>(patch) - u32(IR::Patch::TessellationLodLeft)};
269 ctx.Add("gl_TessLevelOuter[{}]={};", index, value);
270 break;
271 }
272 case IR::Patch::TessellationLodInteriorU:
273 ctx.Add("gl_TessLevelInner[0]={};", value);
274 break;
275 case IR::Patch::TessellationLodInteriorV:
276 ctx.Add("gl_TessLevelInner[1]={};", value);
277 break;
278 default:
279 throw NotImplementedException("Patch {}", patch);
280 }
281}
282
222void EmitSetFragColor(EmitContext& ctx, u32 index, u32 component, std::string_view value) { 283void EmitSetFragColor(EmitContext& ctx, u32 index, u32 component, std::string_view value) {
223 const char swizzle{"xyzw"[component]}; 284 const char swizzle{"xyzw"[component]};
224 ctx.Add("frag_color{}.{}={};", index, swizzle, value); 285 ctx.Add("frag_color{}.{}={};", index, swizzle, value);
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_floating_point.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_floating_point.cpp
index 49ab182ea..f4b81407a 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_floating_point.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_floating_point.cpp
@@ -161,7 +161,7 @@ void EmitFPRecip64(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
161 161
162void EmitFPRecipSqrt32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, 162void EmitFPRecipSqrt32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
163 [[maybe_unused]] std::string_view value) { 163 [[maybe_unused]] std::string_view value) {
164 ctx.AddF32("{}=(1.0f)/sqrt({});", inst, value); 164 ctx.AddF32("{}=inversesqrt({});", inst, value);
165} 165}
166 166
167void EmitFPRecipSqrt64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, 167void EmitFPRecipSqrt64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h b/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h
index e7009d8e9..89ded3614 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h
@@ -75,7 +75,7 @@ void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, std::string_view val
75void EmitGetAttributeIndexed(EmitContext& ctx, std::string_view offset, std::string_view vertex); 75void EmitGetAttributeIndexed(EmitContext& ctx, std::string_view offset, std::string_view vertex);
76void EmitSetAttributeIndexed(EmitContext& ctx, std::string_view offset, std::string_view value, 76void EmitSetAttributeIndexed(EmitContext& ctx, std::string_view offset, std::string_view value,
77 std::string_view vertex); 77 std::string_view vertex);
78void EmitGetPatch(EmitContext& ctx, IR::Patch patch); 78void EmitGetPatch(EmitContext& ctx, IR::Inst& inst, IR::Patch patch);
79void EmitSetPatch(EmitContext& ctx, IR::Patch patch, std::string_view value); 79void EmitSetPatch(EmitContext& ctx, IR::Patch patch, std::string_view value);
80void EmitSetFragColor(EmitContext& ctx, u32 index, u32 component, std::string_view value); 80void EmitSetFragColor(EmitContext& ctx, u32 index, u32 component, std::string_view value);
81void EmitSetSampleMask(EmitContext& ctx, std::string_view value); 81void EmitSetSampleMask(EmitContext& ctx, std::string_view value);
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_not_implemented.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_not_implemented.cpp
index 3ed4e04d3..cf7b2a51e 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_not_implemented.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_not_implemented.cpp
@@ -151,14 +151,6 @@ void EmitSetAttributeIndexed(EmitContext& ctx, std::string_view offset, std::str
151 NotImplemented(); 151 NotImplemented();
152} 152}
153 153
154void EmitGetPatch(EmitContext& ctx, IR::Patch patch) {
155 NotImplemented();
156}
157
158void EmitSetPatch(EmitContext& ctx, IR::Patch patch, std::string_view value) {
159 NotImplemented();
160}
161
162void EmitSetSampleMask(EmitContext& ctx, std::string_view value) { 154void EmitSetSampleMask(EmitContext& ctx, std::string_view value) {
163 NotImplemented(); 155 NotImplemented();
164} 156}
@@ -204,7 +196,7 @@ void EmitWorkgroupId(EmitContext& ctx, IR::Inst& inst) {
204} 196}
205 197
206void EmitInvocationId(EmitContext& ctx, IR::Inst& inst) { 198void EmitInvocationId(EmitContext& ctx, IR::Inst& inst) {
207 NotImplemented(); 199 ctx.AddU32("{}=uint(gl_InvocationID);", inst);
208} 200}
209 201
210void EmitSampleId(EmitContext& ctx, IR::Inst& inst) { 202void EmitSampleId(EmitContext& ctx, IR::Inst& inst) {