summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/backend/spirv/emit_spirv.cpp
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2021-03-20 19:11:56 -0300
committerGravatar ameerj2021-07-22 21:51:23 -0400
commit76c8a962ac4eae77e71d66a72c448930240339f9 (patch)
tree267bdb72f0fad43779080cd1907dd8159a6c7154 /src/shader_recompiler/backend/spirv/emit_spirv.cpp
parentshader: Refactor half floating instructions (diff)
downloadyuzu-76c8a962ac4eae77e71d66a72c448930240339f9.tar.gz
yuzu-76c8a962ac4eae77e71d66a72c448930240339f9.tar.xz
yuzu-76c8a962ac4eae77e71d66a72c448930240339f9.zip
spirv: Implement VertexId and InstanceId, refactor code
Diffstat (limited to 'src/shader_recompiler/backend/spirv/emit_spirv.cpp')
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv.cpp107
1 files changed, 60 insertions, 47 deletions
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.cpp b/src/shader_recompiler/backend/spirv/emit_spirv.cpp
index b8978b94a..efd0b70b7 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv.cpp
@@ -113,6 +113,43 @@ Id TypeId(const EmitContext& ctx, IR::Type type) {
113 } 113 }
114} 114}
115 115
116Id DefineMain(EmitContext& ctx, IR::Program& program) {
117 const Id void_function{ctx.TypeFunction(ctx.void_id)};
118 const Id main{ctx.OpFunction(ctx.void_id, spv::FunctionControlMask::MaskNone, void_function)};
119 for (IR::Block* const block : program.blocks) {
120 ctx.AddLabel(block->Definition<Id>());
121 for (IR::Inst& inst : block->Instructions()) {
122 EmitInst(ctx, &inst);
123 }
124 }
125 ctx.OpFunctionEnd();
126 return main;
127}
128
129void DefineEntryPoint(Environment& env, EmitContext& ctx, Id main) {
130 const std::span interfaces(ctx.interfaces.data(), ctx.interfaces.size());
131 spv::ExecutionModel execution_model{};
132 switch (env.ShaderStage()) {
133 case Shader::Stage::Compute: {
134 const std::array<u32, 3> workgroup_size{env.WorkgroupSize()};
135 execution_model = spv::ExecutionModel::GLCompute;
136 ctx.AddExecutionMode(main, spv::ExecutionMode::LocalSize, workgroup_size[0],
137 workgroup_size[1], workgroup_size[2]);
138 break;
139 }
140 case Shader::Stage::VertexB:
141 execution_model = spv::ExecutionModel::Vertex;
142 break;
143 case Shader::Stage::Fragment:
144 execution_model = spv::ExecutionModel::Fragment;
145 ctx.AddExecutionMode(main, spv::ExecutionMode::OriginUpperLeft);
146 break;
147 default:
148 throw NotImplementedException("Stage {}", env.ShaderStage());
149 }
150 ctx.AddEntryPoint(execution_model, main, "main", interfaces);
151}
152
116void SetupDenormControl(const Profile& profile, const IR::Program& program, EmitContext& ctx, 153void SetupDenormControl(const Profile& profile, const IR::Program& program, EmitContext& ctx,
117 Id main_func) { 154 Id main_func) {
118 if (!profile.support_float_controls) { 155 if (!profile.support_float_controls) {
@@ -173,6 +210,25 @@ void SetupDenormControl(const Profile& profile, const IR::Program& program, Emit
173 } 210 }
174} 211}
175 212
213void SetupCapabilities(const Profile& profile, const Info& info, EmitContext& ctx) {
214 if (info.uses_sampled_1d) {
215 ctx.AddCapability(spv::Capability::Sampled1D);
216 }
217 if (info.uses_sparse_residency) {
218 ctx.AddCapability(spv::Capability::SparseResidency);
219 }
220 if (info.uses_demote_to_helper_invocation) {
221 ctx.AddExtension("SPV_EXT_demote_to_helper_invocation");
222 ctx.AddCapability(spv::Capability::DemoteToHelperInvocationEXT);
223 }
224 if (!profile.support_vertex_instance_id && (info.loads_instance_id || info.loads_vertex_id)) {
225 ctx.AddExtension("SPV_KHR_shader_draw_parameters");
226 ctx.AddCapability(spv::Capability::DrawParameters);
227 }
228 // TODO: Track this usage
229 ctx.AddCapability(spv::Capability::ImageGatherExtended);
230}
231
176Id PhiArgDef(EmitContext& ctx, IR::Inst* inst, size_t index) { 232Id PhiArgDef(EmitContext& ctx, IR::Inst* inst, size_t index) {
177 // Phi nodes can have forward declarations, if an argument is not defined provide a forward 233 // Phi nodes can have forward declarations, if an argument is not defined provide a forward
178 // declaration of it. Invoke will take care of giving it the right definition when it's 234 // declaration of it. Invoke will take care of giving it the right definition when it's
@@ -202,53 +258,10 @@ Id PhiArgDef(EmitContext& ctx, IR::Inst* inst, size_t index) {
202std::vector<u32> EmitSPIRV(const Profile& profile, Environment& env, IR::Program& program, 258std::vector<u32> EmitSPIRV(const Profile& profile, Environment& env, IR::Program& program,
203 u32& binding) { 259 u32& binding) {
204 EmitContext ctx{profile, program, binding}; 260 EmitContext ctx{profile, program, binding};
205 const Id void_function{ctx.TypeFunction(ctx.void_id)}; 261 const Id main{DefineMain(ctx, program)};
206 const Id func{ctx.OpFunction(ctx.void_id, spv::FunctionControlMask::MaskNone, void_function)}; 262 DefineEntryPoint(env, ctx, main);
207 for (IR::Block* const block : program.blocks) { 263 SetupDenormControl(profile, program, ctx, main);
208 ctx.AddLabel(block->Definition<Id>()); 264 SetupCapabilities(profile, program.info, ctx);
209 for (IR::Inst& inst : block->Instructions()) {
210 EmitInst(ctx, &inst);
211 }
212 }
213 ctx.OpFunctionEnd();
214
215 const std::span interfaces(ctx.interfaces.data(), ctx.interfaces.size());
216 spv::ExecutionModel execution_model{};
217 switch (env.ShaderStage()) {
218 case Shader::Stage::Compute: {
219 const std::array<u32, 3> workgroup_size{env.WorkgroupSize()};
220 execution_model = spv::ExecutionModel::GLCompute;
221 ctx.AddExecutionMode(func, spv::ExecutionMode::LocalSize, workgroup_size[0],
222 workgroup_size[1], workgroup_size[2]);
223 break;
224 }
225 case Shader::Stage::VertexB:
226 execution_model = spv::ExecutionModel::Vertex;
227 break;
228 case Shader::Stage::Fragment:
229 execution_model = spv::ExecutionModel::Fragment;
230 ctx.AddExecutionMode(func, spv::ExecutionMode::OriginUpperLeft);
231 break;
232 default:
233 throw NotImplementedException("Stage {}", env.ShaderStage());
234 }
235 ctx.AddEntryPoint(execution_model, func, "main", interfaces);
236
237 SetupDenormControl(profile, program, ctx, func);
238 const Info& info{program.info};
239 if (info.uses_sampled_1d) {
240 ctx.AddCapability(spv::Capability::Sampled1D);
241 }
242 if (info.uses_sparse_residency) {
243 ctx.AddCapability(spv::Capability::SparseResidency);
244 }
245 if (info.uses_demote_to_helper_invocation) {
246 ctx.AddExtension("SPV_EXT_demote_to_helper_invocation");
247 ctx.AddCapability(spv::Capability::DemoteToHelperInvocationEXT);
248 }
249 // TODO: Track this usage
250 ctx.AddCapability(spv::Capability::ImageGatherExtended);
251
252 return ctx.Assemble(); 265 return ctx.Assemble();
253} 266}
254 267