diff options
Diffstat (limited to 'src/shader_recompiler')
3 files changed, 63 insertions, 13 deletions
diff --git a/src/shader_recompiler/backend/glsl/emit_context.cpp b/src/shader_recompiler/backend/glsl/emit_context.cpp index 6f10002fe..58355d5e3 100644 --- a/src/shader_recompiler/backend/glsl/emit_context.cpp +++ b/src/shader_recompiler/backend/glsl/emit_context.cpp | |||
| @@ -37,7 +37,6 @@ bool StoresPerVertexAttributes(Stage stage) { | |||
| 37 | case Stage::VertexA: | 37 | case Stage::VertexA: |
| 38 | case Stage::VertexB: | 38 | case Stage::VertexB: |
| 39 | case Stage::Geometry: | 39 | case Stage::Geometry: |
| 40 | case Stage::TessellationControl: | ||
| 41 | case Stage::TessellationEval: | 40 | case Stage::TessellationEval: |
| 42 | return true; | 41 | return true; |
| 43 | default: | 42 | default: |
| @@ -154,9 +153,7 @@ void SetupOutPerVertex(Stage stage, const Info& info, std::string& header) { | |||
| 154 | return; | 153 | return; |
| 155 | } | 154 | } |
| 156 | header += "out gl_PerVertex{"; | 155 | header += "out gl_PerVertex{"; |
| 157 | if (info.stores_position) { | 156 | header += "vec4 gl_Position;"; |
| 158 | header += "vec4 gl_Position;"; | ||
| 159 | } | ||
| 160 | if (info.stores_point_size) { | 157 | if (info.stores_point_size) { |
| 161 | header += "float gl_PointSize;"; | 158 | header += "float gl_PointSize;"; |
| 162 | } | 159 | } |
| @@ -236,10 +233,8 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile | |||
| 236 | } | 233 | } |
| 237 | for (size_t index = 0; index < info.stores_generics.size(); ++index) { | 234 | for (size_t index = 0; index < info.stores_generics.size(); ++index) { |
| 238 | // TODO: Properly resolve attribute issues | 235 | // TODO: Properly resolve attribute issues |
| 239 | const auto declaration{fmt::format("layout(location={}) out vec4 out_attr{}{};", index, | ||
| 240 | index, OutputDecorator(stage, program.invocations))}; | ||
| 241 | if (info.stores_generics[index] || stage == Stage::VertexA || stage == Stage::VertexB) { | 236 | if (info.stores_generics[index] || stage == Stage::VertexA || stage == Stage::VertexB) { |
| 242 | header += declaration; | 237 | DefineGenericOutput(index, program.invocations); |
| 243 | } | 238 | } |
| 244 | } | 239 | } |
| 245 | header += "\n"; | 240 | header += "\n"; |
| @@ -312,13 +307,53 @@ void EmitContext::DefineStorageBuffers(Bindings& bindings) { | |||
| 312 | } | 307 | } |
| 313 | } | 308 | } |
| 314 | 309 | ||
| 310 | void EmitContext::DefineGenericOutput(size_t index, u32 invocations) { | ||
| 311 | static constexpr std::string_view swizzle{"xyzw"}; | ||
| 312 | const size_t base_index{static_cast<size_t>(IR::Attribute::Generic0X) + index * 4}; | ||
| 313 | u32 element{0}; | ||
| 314 | while (element < 4) { | ||
| 315 | std::string definition{fmt::format("layout(location={}", index)}; | ||
| 316 | const u32 remainder{4 - element}; | ||
| 317 | const TransformFeedbackVarying* xfb_varying{}; | ||
| 318 | if (!runtime_info.xfb_varyings.empty()) { | ||
| 319 | xfb_varying = &runtime_info.xfb_varyings[base_index + element]; | ||
| 320 | xfb_varying = xfb_varying && xfb_varying->components > 0 ? xfb_varying : nullptr; | ||
| 321 | } | ||
| 322 | const u32 num_components{xfb_varying ? xfb_varying->components : remainder}; | ||
| 323 | if (element > 0) { | ||
| 324 | definition += fmt::format(",component={}", element); | ||
| 325 | } | ||
| 326 | if (xfb_varying) { | ||
| 327 | definition += | ||
| 328 | fmt::format(",xfb_buffer={},xfb_stride={},xfb_offset={}", xfb_varying->buffer, | ||
| 329 | xfb_varying->stride, xfb_varying->offset); | ||
| 330 | } | ||
| 331 | std::string name{fmt::format("out_attr{}", index)}; | ||
| 332 | if (num_components < 4 || element > 0) { | ||
| 333 | name += fmt::format("_{}", swizzle.substr(element, num_components)); | ||
| 334 | } | ||
| 335 | const auto type{num_components == 1 ? "float" : fmt::format("vec{}", num_components)}; | ||
| 336 | definition += fmt::format(")out {} {}{};", type, name, OutputDecorator(stage, invocations)); | ||
| 337 | header += definition; | ||
| 338 | |||
| 339 | const GenericElementInfo element_info{ | ||
| 340 | .name = name, | ||
| 341 | .first_element = element, | ||
| 342 | .num_components = num_components, | ||
| 343 | }; | ||
| 344 | std::fill_n(output_generics[index].begin() + element, num_components, element_info); | ||
| 345 | element += num_components; | ||
| 346 | } | ||
| 347 | header += "\n"; | ||
| 348 | } | ||
| 349 | |||
| 315 | void EmitContext::DefineHelperFunctions() { | 350 | void EmitContext::DefineHelperFunctions() { |
| 316 | if (info.uses_global_increment || info.uses_shared_increment) { | 351 | if (info.uses_global_increment || info.uses_shared_increment) { |
| 317 | header += "uint CasIncrement(uint op_a,uint op_b){return(op_a>=op_b)?0u:(op_a+1u);}\n"; | 352 | header += "uint CasIncrement(uint op_a,uint op_b){return(op_a>=op_b)?0u:(op_a+1u);}\n"; |
| 318 | } | 353 | } |
| 319 | if (info.uses_global_decrement || info.uses_shared_decrement) { | 354 | if (info.uses_global_decrement || info.uses_shared_decrement) { |
| 320 | header += | 355 | header += "uint CasDecrement(uint op_a,uint " |
| 321 | "uint CasDecrement(uint op_a,uint op_b){return(op_a==0||op_a>op_b)?op_b:(op_a-1u);}\n"; | 356 | "op_b){return(op_a==0||op_a>op_b)?op_b:(op_a-1u);}\n"; |
| 322 | } | 357 | } |
| 323 | if (info.uses_atomic_f32_add) { | 358 | if (info.uses_atomic_f32_add) { |
| 324 | header += "uint CasFloatAdd(uint op_a,float op_b){return " | 359 | header += "uint CasFloatAdd(uint op_a,float op_b){return " |
diff --git a/src/shader_recompiler/backend/glsl/emit_context.h b/src/shader_recompiler/backend/glsl/emit_context.h index 48786a2c7..5d48675e6 100644 --- a/src/shader_recompiler/backend/glsl/emit_context.h +++ b/src/shader_recompiler/backend/glsl/emit_context.h | |||
| @@ -30,6 +30,12 @@ struct Program; | |||
| 30 | 30 | ||
| 31 | namespace Shader::Backend::GLSL { | 31 | namespace Shader::Backend::GLSL { |
| 32 | 32 | ||
| 33 | struct GenericElementInfo { | ||
| 34 | std::string name{}; | ||
| 35 | u32 first_element{}; | ||
| 36 | u32 num_components{}; | ||
| 37 | }; | ||
| 38 | |||
| 33 | class EmitContext { | 39 | class EmitContext { |
| 34 | public: | 40 | public: |
| 35 | explicit EmitContext(IR::Program& program, Bindings& bindings, const Profile& profile_, | 41 | explicit EmitContext(IR::Program& program, Bindings& bindings, const Profile& profile_, |
| @@ -149,6 +155,7 @@ public: | |||
| 149 | std::vector<u32> image_buffer_bindings; | 155 | std::vector<u32> image_buffer_bindings; |
| 150 | std::vector<u32> texture_bindings; | 156 | std::vector<u32> texture_bindings; |
| 151 | std::vector<u32> image_bindings; | 157 | std::vector<u32> image_bindings; |
| 158 | std::array<std::array<GenericElementInfo, 4>, 32> output_generics{}; | ||
| 152 | 159 | ||
| 153 | bool uses_y_direction{}; | 160 | bool uses_y_direction{}; |
| 154 | bool uses_cc_carry{}; | 161 | bool uses_cc_carry{}; |
| @@ -157,6 +164,7 @@ private: | |||
| 157 | void SetupExtensions(std::string& header); | 164 | void SetupExtensions(std::string& header); |
| 158 | void DefineConstantBuffers(Bindings& bindings); | 165 | void DefineConstantBuffers(Bindings& bindings); |
| 159 | void DefineStorageBuffers(Bindings& bindings); | 166 | void DefineStorageBuffers(Bindings& bindings); |
| 167 | void DefineGenericOutput(size_t index, u32 invocations); | ||
| 160 | void DefineHelperFunctions(); | 168 | void DefineHelperFunctions(); |
| 161 | void SetupImages(Bindings& bindings); | 169 | void SetupImages(Bindings& bindings); |
| 162 | }; | 170 | }; |
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 0cf31329d..c48492a17 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 | |||
| @@ -200,13 +200,21 @@ void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, | |||
| 200 | 200 | ||
| 201 | void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, std::string_view value, | 201 | void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, std::string_view value, |
| 202 | [[maybe_unused]] std::string_view vertex) { | 202 | [[maybe_unused]] std::string_view vertex) { |
| 203 | const u32 element{static_cast<u32>(attr) % 4}; | ||
| 204 | const char swizzle{"xyzw"[element]}; | ||
| 205 | if (IR::IsGeneric(attr)) { | 203 | if (IR::IsGeneric(attr)) { |
| 206 | const u32 index{IR::GenericAttributeIndex(attr)}; | 204 | const u32 index{IR::GenericAttributeIndex(attr)}; |
| 207 | ctx.Add("out_attr{}{}.{}={};", index, OutputVertexIndex(ctx, vertex), swizzle, value); | 205 | const u32 element{IR::GenericAttributeElement(attr)}; |
| 206 | const GenericElementInfo& info{ctx.output_generics.at(index).at(element)}; | ||
| 207 | const auto output_decorator{OutputVertexIndex(ctx, vertex)}; | ||
| 208 | if (info.num_components == 1) { | ||
| 209 | ctx.Add("{}{}={};", info.name, output_decorator, value); | ||
| 210 | } else { | ||
| 211 | const u32 index_element{element - info.first_element}; | ||
| 212 | ctx.Add("{}{}.{}={};", info.name, output_decorator, "xyzw"[index_element], value); | ||
| 213 | } | ||
| 208 | return; | 214 | return; |
| 209 | } | 215 | } |
| 216 | const u32 element{static_cast<u32>(attr) % 4}; | ||
| 217 | const char swizzle{"xyzw"[element]}; | ||
| 210 | switch (attr) { | 218 | switch (attr) { |
| 211 | case IR::Attribute::PointSize: | 219 | case IR::Attribute::PointSize: |
| 212 | ctx.Add("gl_PointSize={};", value); | 220 | ctx.Add("gl_PointSize={};", value); |
| @@ -233,7 +241,6 @@ void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, std::string_view val | |||
| 233 | break; | 241 | break; |
| 234 | } | 242 | } |
| 235 | default: | 243 | default: |
| 236 | fmt::print("Set attribute {}", attr); | ||
| 237 | throw NotImplementedException("Set attribute {}", attr); | 244 | throw NotImplementedException("Set attribute {}", attr); |
| 238 | } | 245 | } |
| 239 | } | 246 | } |