1
1
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
2
2
// SPDX-License-Identifier: GPL-2.0-or-later
3
-
4
3
#include < span>
5
4
#include < type_traits>
6
5
#include < utility>
13
12
#include " shader_recompiler/frontend/translate/translate.h"
14
13
#include " shader_recompiler/ir/basic_block.h"
15
14
#include " shader_recompiler/ir/program.h"
15
+ #include " shader_recompiler/runtime_info.h"
16
16
#include " video_core/amdgpu/types.h"
17
17
18
18
namespace Shader ::Backend::SPIRV {
@@ -72,7 +72,10 @@ ArgType Arg(EmitContext& ctx, const IR::Value& arg) {
72
72
return arg.VectorReg ();
73
73
} else if constexpr (std::is_same_v<ArgType, const char *>) {
74
74
return arg.StringLiteral ();
75
+ } else if constexpr (std::is_same_v<ArgType, IR::Patch>) {
76
+ return arg.Patch ();
75
77
}
78
+ UNREACHABLE ();
76
79
}
77
80
78
81
template <auto func, bool is_first_arg_inst, size_t ... I>
@@ -206,6 +209,32 @@ Id DefineMain(EmitContext& ctx, const IR::Program& program) {
206
209
return main;
207
210
}
208
211
212
+ spv::ExecutionMode ExecutionMode (AmdGpu::TessellationType primitive) {
213
+ switch (primitive) {
214
+ case AmdGpu::TessellationType::Isoline:
215
+ return spv::ExecutionMode::Isolines;
216
+ case AmdGpu::TessellationType::Triangle:
217
+ return spv::ExecutionMode::Triangles;
218
+ case AmdGpu::TessellationType::Quad:
219
+ return spv::ExecutionMode::Quads;
220
+ }
221
+ UNREACHABLE_MSG (" Tessellation primitive {}" , primitive);
222
+ }
223
+
224
+ spv::ExecutionMode ExecutionMode (AmdGpu::TessellationPartitioning spacing) {
225
+ switch (spacing) {
226
+ case AmdGpu::TessellationPartitioning::Integer:
227
+ return spv::ExecutionMode::SpacingEqual;
228
+ case AmdGpu::TessellationPartitioning::FracOdd:
229
+ return spv::ExecutionMode::SpacingFractionalOdd;
230
+ case AmdGpu::TessellationPartitioning::FracEven:
231
+ return spv::ExecutionMode::SpacingFractionalEven;
232
+ default :
233
+ break ;
234
+ }
235
+ UNREACHABLE_MSG (" Tessellation spacing {}" , spacing);
236
+ }
237
+
209
238
void SetupCapabilities (const Info& info, const Profile& profile, EmitContext& ctx) {
210
239
ctx.AddCapability (spv::Capability::Image1D);
211
240
ctx.AddCapability (spv::Capability::Sampled1D);
@@ -248,36 +277,55 @@ void SetupCapabilities(const Info& info, const Profile& profile, EmitContext& ct
248
277
if (info.uses_group_ballot ) {
249
278
ctx.AddCapability (spv::Capability::GroupNonUniformBallot);
250
279
}
251
- if (info.stage == Stage::Export || info.stage == Stage::Vertex) {
280
+ const auto stage = info.l_stage ;
281
+ if (stage == LogicalStage::Vertex) {
252
282
ctx.AddExtension (" SPV_KHR_shader_draw_parameters" );
253
283
ctx.AddCapability (spv::Capability::DrawParameters);
254
284
}
255
- if (info. stage == Stage ::Geometry) {
285
+ if (stage == LogicalStage ::Geometry) {
256
286
ctx.AddCapability (spv::Capability::Geometry);
257
287
}
258
288
if (info.stage == Stage::Fragment && profile.needs_manual_interpolation ) {
259
289
ctx.AddExtension (" SPV_KHR_fragment_shader_barycentric" );
260
290
ctx.AddCapability (spv::Capability::FragmentBarycentricKHR);
261
291
}
292
+ if (stage == LogicalStage::TessellationControl || stage == LogicalStage::TessellationEval) {
293
+ ctx.AddCapability (spv::Capability::Tessellation);
294
+ }
262
295
}
263
296
264
- void DefineEntryPoint (const IR::Program& program, EmitContext& ctx, Id main) {
265
- const auto & info = program.info ;
297
+ void DefineEntryPoint (const Info& info, EmitContext& ctx, Id main) {
266
298
const std::span interfaces (ctx.interfaces .data (), ctx.interfaces .size ());
267
299
spv::ExecutionModel execution_model{};
268
- switch (program. info .stage ) {
269
- case Stage ::Compute: {
300
+ switch (info.l_stage ) {
301
+ case LogicalStage ::Compute: {
270
302
const std::array<u32 , 3 > workgroup_size{ctx.runtime_info .cs_info .workgroup_size };
271
303
execution_model = spv::ExecutionModel::GLCompute;
272
304
ctx.AddExecutionMode (main, spv::ExecutionMode::LocalSize, workgroup_size[0 ],
273
305
workgroup_size[1 ], workgroup_size[2 ]);
274
306
break ;
275
307
}
276
- case Stage::Export:
277
- case Stage::Vertex:
308
+ case LogicalStage::Vertex:
278
309
execution_model = spv::ExecutionModel::Vertex;
279
310
break ;
280
- case Stage::Fragment:
311
+ case LogicalStage::TessellationControl:
312
+ execution_model = spv::ExecutionModel::TessellationControl;
313
+ ctx.AddCapability (spv::Capability::Tessellation);
314
+ ctx.AddExecutionMode (main, spv::ExecutionMode::OutputVertices,
315
+ ctx.runtime_info .hs_info .NumOutputControlPoints ());
316
+ break ;
317
+ case LogicalStage::TessellationEval: {
318
+ execution_model = spv::ExecutionModel::TessellationEvaluation;
319
+ const auto & vs_info = ctx.runtime_info .vs_info ;
320
+ ctx.AddExecutionMode (main, ExecutionMode (vs_info.tess_type ));
321
+ ctx.AddExecutionMode (main, ExecutionMode (vs_info.tess_partitioning ));
322
+ ctx.AddExecutionMode (main,
323
+ vs_info.tess_topology == AmdGpu::TessellationTopology::TriangleCcw
324
+ ? spv::ExecutionMode::VertexOrderCcw
325
+ : spv::ExecutionMode::VertexOrderCw);
326
+ break ;
327
+ }
328
+ case LogicalStage::Fragment:
281
329
execution_model = spv::ExecutionModel::Fragment;
282
330
if (ctx.profile .lower_left_origin_mode ) {
283
331
ctx.AddExecutionMode (main, spv::ExecutionMode::OriginLowerLeft);
@@ -292,7 +340,7 @@ void DefineEntryPoint(const IR::Program& program, EmitContext& ctx, Id main) {
292
340
ctx.AddExecutionMode (main, spv::ExecutionMode::DepthReplacing);
293
341
}
294
342
break ;
295
- case Stage ::Geometry:
343
+ case LogicalStage ::Geometry:
296
344
execution_model = spv::ExecutionModel::Geometry;
297
345
ctx.AddExecutionMode (main, GetInputPrimitiveType (ctx.runtime_info .gs_info .in_primitive ));
298
346
ctx.AddExecutionMode (main,
@@ -303,7 +351,7 @@ void DefineEntryPoint(const IR::Program& program, EmitContext& ctx, Id main) {
303
351
ctx.runtime_info .gs_info .num_invocations );
304
352
break ;
305
353
default :
306
- throw NotImplementedException (" Stage {}" , u32 (program. info .stage ));
354
+ UNREACHABLE_MSG (" Stage {}" , u32 (info.stage ));
307
355
}
308
356
ctx.AddEntryPoint (execution_model, main, " main" , interfaces);
309
357
}
@@ -349,7 +397,7 @@ std::vector<u32> EmitSPIRV(const Profile& profile, const RuntimeInfo& runtime_in
349
397
const IR::Program& program, Bindings& binding) {
350
398
EmitContext ctx{profile, runtime_info, program.info , binding};
351
399
const Id main{DefineMain (ctx, program)};
352
- DefineEntryPoint (program, ctx, main);
400
+ DefineEntryPoint (program. info , ctx, main);
353
401
SetupCapabilities (program.info , profile, ctx);
354
402
SetupFloatMode (ctx, profile, runtime_info, main);
355
403
PatchPhiNodes (program, ctx);
0 commit comments