summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/backend/glsl/emit_context.cpp
diff options
context:
space:
mode:
authorGravatar ameerj2021-05-31 23:07:13 -0400
committerGravatar ameerj2021-07-22 21:51:37 -0400
commit8c684b3e2327bc7b0c02f2a22dbf52c11884ecd3 (patch)
tree7312ad1f04957f63a0a848f71f47271a5d29b234 /src/shader_recompiler/backend/glsl/emit_context.cpp
parentglsl: Implement ImageGradient and other texture function variants (diff)
downloadyuzu-8c684b3e2327bc7b0c02f2a22dbf52c11884ecd3.tar.gz
yuzu-8c684b3e2327bc7b0c02f2a22dbf52c11884ecd3.tar.xz
yuzu-8c684b3e2327bc7b0c02f2a22dbf52c11884ecd3.zip
glsl: Implement tessellation shaders
Diffstat (limited to 'src/shader_recompiler/backend/glsl/emit_context.cpp')
-rw-r--r--src/shader_recompiler/backend/glsl/emit_context.cpp90
1 files changed, 78 insertions, 12 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 }