diff options
| author | 2021-05-31 13:28:53 -0400 | |
|---|---|---|
| committer | 2021-07-22 21:51:37 -0400 | |
| commit | 19247ba4fad59b3d821b099dfbcd60e985041249 (patch) | |
| tree | c30455f98fa5c2fe5b5febdc4baabb61db3fd293 /src/shader_recompiler/backend/glsl | |
| parent | glsl: Use NotImplemented macro with function name output (diff) | |
| download | yuzu-19247ba4fad59b3d821b099dfbcd60e985041249.tar.gz yuzu-19247ba4fad59b3d821b099dfbcd60e985041249.tar.xz yuzu-19247ba4fad59b3d821b099dfbcd60e985041249.zip | |
glsl: Implement geometry shaders
Diffstat (limited to 'src/shader_recompiler/backend/glsl')
4 files changed, 62 insertions, 9 deletions
diff --git a/src/shader_recompiler/backend/glsl/emit_context.cpp b/src/shader_recompiler/backend/glsl/emit_context.cpp index 2a5ec7414..923060386 100644 --- a/src/shader_recompiler/backend/glsl/emit_context.cpp +++ b/src/shader_recompiler/backend/glsl/emit_context.cpp | |||
| @@ -21,6 +21,15 @@ 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) { | ||
| 25 | switch (stage) { | ||
| 26 | case Stage::Geometry: | ||
| 27 | return "[1]"; | ||
| 28 | default: | ||
| 29 | return ""; | ||
| 30 | } | ||
| 31 | } | ||
| 32 | |||
| 24 | std::string_view SamplerType(TextureType type, bool is_depth) { | 33 | std::string_view SamplerType(TextureType type, bool is_depth) { |
| 25 | if (is_depth) { | 34 | if (is_depth) { |
| 26 | switch (type) { | 35 | switch (type) { |
| @@ -64,6 +73,33 @@ std::string_view SamplerType(TextureType type, bool is_depth) { | |||
| 64 | } | 73 | } |
| 65 | } | 74 | } |
| 66 | 75 | ||
| 76 | std::string_view InputPrimitive(InputTopology topology) { | ||
| 77 | switch (topology) { | ||
| 78 | case InputTopology::Points: | ||
| 79 | return "points"; | ||
| 80 | case InputTopology::Lines: | ||
| 81 | return "lines"; | ||
| 82 | case InputTopology::LinesAdjacency: | ||
| 83 | return "lines_adjacency"; | ||
| 84 | case InputTopology::Triangles: | ||
| 85 | return "triangles"; | ||
| 86 | case InputTopology::TrianglesAdjacency: | ||
| 87 | return "triangles_adjacency"; | ||
| 88 | } | ||
| 89 | throw InvalidArgument("Invalid input topology {}", topology); | ||
| 90 | } | ||
| 91 | |||
| 92 | std::string_view OutputPrimitive(OutputTopology topology) { | ||
| 93 | switch (topology) { | ||
| 94 | case OutputTopology::PointList: | ||
| 95 | return "points"; | ||
| 96 | case OutputTopology::LineStrip: | ||
| 97 | return "line_strip"; | ||
| 98 | case OutputTopology::TriangleStrip: | ||
| 99 | return "triangle_strip"; | ||
| 100 | } | ||
| 101 | throw InvalidArgument("Invalid output topology {}", topology); | ||
| 102 | } | ||
| 67 | } // namespace | 103 | } // namespace |
| 68 | 104 | ||
| 69 | EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile& profile_, | 105 | EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile& profile_, |
| @@ -85,6 +121,9 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile | |||
| 85 | break; | 121 | break; |
| 86 | case Stage::Geometry: | 122 | case Stage::Geometry: |
| 87 | stage_name = "gs"; | 123 | stage_name = "gs"; |
| 124 | header += fmt::format("layout({})in;layout({}, max_vertices={})out;\n", | ||
| 125 | InputPrimitive(runtime_info.input_topology), | ||
| 126 | OutputPrimitive(program.output_topology), program.output_vertices); | ||
| 88 | break; | 127 | break; |
| 89 | case Stage::Fragment: | 128 | case Stage::Fragment: |
| 90 | stage_name = "fs"; | 129 | stage_name = "fs"; |
| @@ -99,8 +138,9 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile | |||
| 99 | for (size_t index = 0; index < info.input_generics.size(); ++index) { | 138 | for (size_t index = 0; index < info.input_generics.size(); ++index) { |
| 100 | const auto& generic{info.input_generics[index]}; | 139 | const auto& generic{info.input_generics[index]}; |
| 101 | if (generic.used) { | 140 | if (generic.used) { |
| 102 | header += fmt::format("layout(location={}) {} in vec4 in_attr{};", index, | 141 | header += |
| 103 | InterpDecorator(generic.interpolation), index); | 142 | fmt::format("layout(location={}){} in vec4 in_attr{}{};", index, |
| 143 | InterpDecorator(generic.interpolation), index, ArrayDecorator(stage)); | ||
| 104 | } | 144 | } |
| 105 | } | 145 | } |
| 106 | for (size_t index = 0; index < info.stores_frag_color.size(); ++index) { | 146 | for (size_t index = 0; index < info.stores_frag_color.size(); ++index) { |
| @@ -126,8 +166,6 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile | |||
| 126 | void EmitContext::SetupExtensions(std::string&) { | 166 | void EmitContext::SetupExtensions(std::string&) { |
| 127 | // TODO: track this usage | 167 | // TODO: track this usage |
| 128 | header += "#extension GL_ARB_sparse_texture2 : enable\n"; | 168 | header += "#extension GL_ARB_sparse_texture2 : enable\n"; |
| 129 | header += "#extension GL_ARB_shader_viewport_layer_array : enable\n"; | ||
| 130 | header += "#extension GL_NV_viewport_array2 : enable\n"; | ||
| 131 | header += "#extension GL_EXT_texture_shadow_lod : enable\n"; | 169 | header += "#extension GL_EXT_texture_shadow_lod : enable\n"; |
| 132 | if (info.uses_int64) { | 170 | if (info.uses_int64) { |
| 133 | header += "#extension GL_ARB_gpu_shader_int64 : enable\n"; | 171 | header += "#extension GL_ARB_gpu_shader_int64 : enable\n"; |
| @@ -157,6 +195,10 @@ void EmitContext::SetupExtensions(std::string&) { | |||
| 157 | header += "#extension GL_ARB_gpu_shader_int64 : enable\n"; | 195 | header += "#extension GL_ARB_gpu_shader_int64 : enable\n"; |
| 158 | } | 196 | } |
| 159 | } | 197 | } |
| 198 | if (info.stores_viewport_index) { | ||
| 199 | header += "#extension GL_ARB_shader_viewport_layer_array : enable\n"; | ||
| 200 | header += "#extension GL_NV_viewport_array2 : enable\n"; | ||
| 201 | } | ||
| 160 | } | 202 | } |
| 161 | 203 | ||
| 162 | void EmitContext::DefineConstantBuffers(Bindings& bindings) { | 204 | void EmitContext::DefineConstantBuffers(Bindings& bindings) { |
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl.cpp b/src/shader_recompiler/backend/glsl/emit_glsl.cpp index 19cf4e46b..f467d978c 100644 --- a/src/shader_recompiler/backend/glsl/emit_glsl.cpp +++ b/src/shader_recompiler/backend/glsl/emit_glsl.cpp | |||
| @@ -162,7 +162,7 @@ void EmitCode(EmitContext& ctx, const IR::Program& program) { | |||
| 162 | break; | 162 | break; |
| 163 | default: | 163 | default: |
| 164 | fmt::print("{}", node.type); | 164 | fmt::print("{}", node.type); |
| 165 | throw NotImplementedException("{}", node.type); | 165 | throw NotImplementedException("AbstractSyntaxNode::Type {}", node.type); |
| 166 | break; | 166 | break; |
| 167 | } | 167 | } |
| 168 | } | 168 | } |
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 c66b4b282..28e89a0a6 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 | |||
| @@ -19,6 +19,15 @@ u32 CbufIndex(u32 offset) { | |||
| 19 | char OffsetSwizzle(u32 offset) { | 19 | char OffsetSwizzle(u32 offset) { |
| 20 | return SWIZZLE[CbufIndex(offset)]; | 20 | return SWIZZLE[CbufIndex(offset)]; |
| 21 | } | 21 | } |
| 22 | |||
| 23 | bool IsInputArray(Stage stage) { | ||
| 24 | return stage == Stage::Geometry || stage == Stage::TessellationControl || | ||
| 25 | stage == Stage::TessellationEval; | ||
| 26 | } | ||
| 27 | |||
| 28 | std::string VertexIndex(EmitContext& ctx, std::string_view vertex) { | ||
| 29 | return IsInputArray(ctx.stage) ? fmt::format("[{}]", vertex) : ""; | ||
| 30 | } | ||
| 22 | } // namespace | 31 | } // namespace |
| 23 | 32 | ||
| 24 | void EmitGetCbufU8([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, | 33 | void EmitGetCbufU8([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, |
| @@ -128,7 +137,7 @@ void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, | |||
| 128 | const char swizzle{"xyzw"[element]}; | 137 | const char swizzle{"xyzw"[element]}; |
| 129 | if (IR::IsGeneric(attr)) { | 138 | if (IR::IsGeneric(attr)) { |
| 130 | const u32 index{IR::GenericAttributeIndex(attr)}; | 139 | const u32 index{IR::GenericAttributeIndex(attr)}; |
| 131 | ctx.AddF32("{}=in_attr{}.{};", inst, index, swizzle); | 140 | ctx.AddF32("{}=in_attr{}{}.{};", inst, index, VertexIndex(ctx, vertex), swizzle); |
| 132 | return; | 141 | return; |
| 133 | } | 142 | } |
| 134 | switch (attr) { | 143 | switch (attr) { |
| @@ -139,9 +148,11 @@ void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, | |||
| 139 | switch (ctx.stage) { | 148 | switch (ctx.stage) { |
| 140 | case Stage::VertexA: | 149 | case Stage::VertexA: |
| 141 | case Stage::VertexB: | 150 | case Stage::VertexB: |
| 142 | case Stage::Geometry: | ||
| 143 | ctx.AddF32("{}=gl_Position.{};", inst, swizzle); | 151 | ctx.AddF32("{}=gl_Position.{};", inst, swizzle); |
| 144 | break; | 152 | break; |
| 153 | case Stage::Geometry: | ||
| 154 | ctx.AddF32("{}=gl_in[{}].gl_Position.{};", inst, vertex, swizzle); | ||
| 155 | break; | ||
| 145 | case Stage::Fragment: | 156 | case Stage::Fragment: |
| 146 | ctx.AddF32("{}=gl_FragCoord.{};", inst, swizzle); | 157 | ctx.AddF32("{}=gl_FragCoord.{};", inst, swizzle); |
| 147 | break; | 158 | break; |
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 e3d0b15ba..9e5715605 100644 --- a/src/shader_recompiler/backend/glsl/emit_glsl_not_implemented.cpp +++ b/src/shader_recompiler/backend/glsl/emit_glsl_not_implemented.cpp | |||
| @@ -103,11 +103,11 @@ void EmitEpilogue(EmitContext& ctx) { | |||
| 103 | } | 103 | } |
| 104 | 104 | ||
| 105 | void EmitEmitVertex(EmitContext& ctx, const IR::Value& stream) { | 105 | void EmitEmitVertex(EmitContext& ctx, const IR::Value& stream) { |
| 106 | NotImplemented(); | 106 | ctx.Add("EmitStreamVertex(int({}));", ctx.var_alloc.Consume(stream)); |
| 107 | } | 107 | } |
| 108 | 108 | ||
| 109 | void EmitEndPrimitive(EmitContext& ctx, const IR::Value& stream) { | 109 | void EmitEndPrimitive(EmitContext& ctx, const IR::Value& stream) { |
| 110 | NotImplemented(); | 110 | ctx.Add("EndStreamPrimitive(int({}));", ctx.var_alloc.Consume(stream)); |
| 111 | } | 111 | } |
| 112 | 112 | ||
| 113 | void EmitGetRegister(EmitContext& ctx) { | 113 | void EmitGetRegister(EmitContext& ctx) { |