diff options
| author | 2021-03-20 19:11:56 -0300 | |
|---|---|---|
| committer | 2021-07-22 21:51:23 -0400 | |
| commit | 76c8a962ac4eae77e71d66a72c448930240339f9 (patch) | |
| tree | 267bdb72f0fad43779080cd1907dd8159a6c7154 /src/shader_recompiler/backend/spirv/emit_spirv.cpp | |
| parent | shader: Refactor half floating instructions (diff) | |
| download | yuzu-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.cpp | 107 |
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 | ||
| 116 | Id 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 | |||
| 129 | void 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 | |||
| 116 | void SetupDenormControl(const Profile& profile, const IR::Program& program, EmitContext& ctx, | 153 | void 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 | ||
| 213 | void 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 | |||
| 176 | Id PhiArgDef(EmitContext& ctx, IR::Inst* inst, size_t index) { | 232 | Id 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) { | |||
| 202 | std::vector<u32> EmitSPIRV(const Profile& profile, Environment& env, IR::Program& program, | 258 | std::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 | ||