diff options
Diffstat (limited to 'src/shader_recompiler/backend/glsl')
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 | ||
| 24 | std::string_view ArrayDecorator(Stage stage) { | 24 | std::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 | |||
| 35 | std::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 | ||
| 87 | std::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 | |||
| 99 | std::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 | |||
| 76 | std::string_view InputPrimitive(InputTopology topology) { | 111 | std::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 | |||
| 139 | void 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 | ||
| 105 | EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile& profile_, | 157 | EmitContext::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 | ||
| 28 | std::string VertexIndex(EmitContext& ctx, std::string_view vertex) { | 28 | std::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 | |||
| 32 | bool IsOutputArray(Stage stage) { | ||
| 33 | return stage == Stage::Geometry || stage == Stage::TessellationControl; | ||
| 34 | } | ||
| 35 | |||
| 36 | std::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 | ||
| 33 | void EmitGetCbufU8([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, | 48 | void 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 | ||
| 134 | void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, | 149 | void 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 | ||
| 245 | void 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 | |||
| 256 | void 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 | |||
| 222 | void EmitSetFragColor(EmitContext& ctx, u32 index, u32 component, std::string_view value) { | 283 | void 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 | ||
| 162 | void EmitFPRecipSqrt32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, | 162 | void 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 | ||
| 167 | void EmitFPRecipSqrt64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, | 167 | void 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 | |||
| 75 | void EmitGetAttributeIndexed(EmitContext& ctx, std::string_view offset, std::string_view vertex); | 75 | void EmitGetAttributeIndexed(EmitContext& ctx, std::string_view offset, std::string_view vertex); |
| 76 | void EmitSetAttributeIndexed(EmitContext& ctx, std::string_view offset, std::string_view value, | 76 | void EmitSetAttributeIndexed(EmitContext& ctx, std::string_view offset, std::string_view value, |
| 77 | std::string_view vertex); | 77 | std::string_view vertex); |
| 78 | void EmitGetPatch(EmitContext& ctx, IR::Patch patch); | 78 | void EmitGetPatch(EmitContext& ctx, IR::Inst& inst, IR::Patch patch); |
| 79 | void EmitSetPatch(EmitContext& ctx, IR::Patch patch, std::string_view value); | 79 | void EmitSetPatch(EmitContext& ctx, IR::Patch patch, std::string_view value); |
| 80 | void EmitSetFragColor(EmitContext& ctx, u32 index, u32 component, std::string_view value); | 80 | void EmitSetFragColor(EmitContext& ctx, u32 index, u32 component, std::string_view value); |
| 81 | void EmitSetSampleMask(EmitContext& ctx, std::string_view value); | 81 | void 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 | ||
| 154 | void EmitGetPatch(EmitContext& ctx, IR::Patch patch) { | ||
| 155 | NotImplemented(); | ||
| 156 | } | ||
| 157 | |||
| 158 | void EmitSetPatch(EmitContext& ctx, IR::Patch patch, std::string_view value) { | ||
| 159 | NotImplemented(); | ||
| 160 | } | ||
| 161 | |||
| 162 | void EmitSetSampleMask(EmitContext& ctx, std::string_view value) { | 154 | void 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 | ||
| 206 | void EmitInvocationId(EmitContext& ctx, IR::Inst& inst) { | 198 | void EmitInvocationId(EmitContext& ctx, IR::Inst& inst) { |
| 207 | NotImplemented(); | 199 | ctx.AddU32("{}=uint(gl_InvocationID);", inst); |
| 208 | } | 200 | } |
| 209 | 201 | ||
| 210 | void EmitSampleId(EmitContext& ctx, IR::Inst& inst) { | 202 | void EmitSampleId(EmitContext& ctx, IR::Inst& inst) { |