task shader initial

This commit is contained in:
Try 2023-03-18 17:20:16 +01:00
parent d26c233e1c
commit dd8839c6f9
6 changed files with 83 additions and 13 deletions

View File

@ -0,0 +1,24 @@
struct TaskPayload
{
float a;
float b;
int c;
};
static const uint3 gl_WorkGroupSize = uint3(1u, 1u, 1u);
groupshared TaskPayload _payload;
void task_main()
{
_payload.a = 1.2000000476837158203125f;
_payload.b = 2.2999999523162841796875f;
_payload.c = 3;
DispatchMesh(1u, 2u, 3u, _payload);
}
[numthreads(1, 1, 1)]
void main()
{
task_main();
}

View File

@ -0,0 +1,22 @@
#version 450
#extension GL_EXT_mesh_shader : require
layout(local_size_x = 1) in;
struct TaskPayload
{
float a;
float b;
int c;
};
taskPayloadSharedEXT TaskPayload payload;
void main()
{
payload.a = 1.2;
payload.b = 2.3;
payload.c = 3;
EmitMeshTasksEXT(1, 2, 3);
}

View File

@ -845,7 +845,6 @@ struct SPIRBlock : IVariant
// If terminator is EmitMeshTasksEXT.
struct
{
ID groups[3];
ID payload;
} mesh = {};

View File

@ -14316,6 +14316,10 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
statement("SetMeshOutputsEXT(", to_unpacked_expression(ops[0]), ", ", to_unpacked_expression(ops[1]), ");");
break;
case OpEmitMeshTasksEXT:
statement("EmitMeshTasksEXT(", to_unpacked_expression(ops[0]), ", ", to_unpacked_expression(ops[1]), ", ", to_unpacked_expression(ops[2]), ");");
break;
case OpReadClockKHR:
{
auto &type = get<SPIRType>(ops[0]);
@ -16873,10 +16877,6 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
break;
case SPIRBlock::EmitMeshTasks:
statement("EmitMeshTasksEXT(",
to_unpacked_expression(block.mesh.groups[0]), ", ",
to_unpacked_expression(block.mesh.groups[1]), ", ",
to_unpacked_expression(block.mesh.groups[2]), ");");
break;
default:

View File

@ -1635,7 +1635,7 @@ void CompilerHLSL::emit_resources()
auto &type = this->get<SPIRType>(var.basetype);
if (var.storage != StorageClassFunction && !var.remapped_variable && type.pointer &&
(var.storage == StorageClassInput || var.storage == StorageClassOutput) && !is_builtin_variable(var) &&
(var.storage == StorageClassInput || var.storage == StorageClassOutput) && !is_builtin_variable(var) &&
interface_variable_exists_in_entry_point(var.self))
{
// Builtin variables are handled separately.
@ -1808,8 +1808,10 @@ void CompilerHLSL::emit_resources()
if (is_hidden_variable(var, true))
continue;
if (var.storage != StorageClassOutput &&
var.storage != StorageClassTaskPayloadWorkgroupEXT)
if (var.storage == StorageClassTaskPayloadWorkgroupEXT && is_mesh_shader)
continue;
if (var.storage != StorageClassOutput)
{
if (!variable_is_lut(var))
{
@ -1819,6 +1821,7 @@ void CompilerHLSL::emit_resources()
switch (var.storage)
{
case StorageClassWorkgroup:
case StorageClassTaskPayloadWorkgroupEXT:
storage = "groupshared";
break;
@ -2818,6 +2821,8 @@ string CompilerHLSL::get_inner_entry_point_name() const
return "comp_main";
else if (execution.model == ExecutionModelMeshEXT)
return "mesh_main";
else if (execution.model == ExecutionModelTaskEXT)
return "task_main";
else
SPIRV_CROSS_THROW("Unsupported execution model.");
}
@ -2931,8 +2936,8 @@ void CompilerHLSL::emit_hlsl_entry_point()
switch (execution.model)
{
case spv::ExecutionModelTaskEXT:
case ExecutionModelMeshEXT:
case ExecutionModelMeshNV:
case ExecutionModelGLCompute:
{
if (execution.model == ExecutionModelMeshEXT)
@ -3204,8 +3209,9 @@ void CompilerHLSL::emit_hlsl_entry_point()
// Run the shader.
if (execution.model == ExecutionModelVertex ||
execution.model == ExecutionModelFragment ||
execution.model == ExecutionModelGLCompute ||
execution.model == ExecutionModelMeshEXT)
execution.model == ExecutionModelGLCompute ||
execution.model == ExecutionModelMeshEXT ||
execution.model == ExecutionModelTaskEXT)
{
// For mesh shaders, we receive special arguments that we must pass down as function arguments.
// HLSL does not support proper reference types for passing these IO blocks,
@ -6355,6 +6361,19 @@ void CompilerHLSL::emit_instruction(const Instruction &instruction)
statement("SetMeshOutputCounts(", to_unpacked_expression(ops[0]), ", ", to_unpacked_expression(ops[1]), ");");
break;
}
case OpEmitMeshTasksEXT:
{
if (instruction.length==4)
{
statement("DispatchMesh(", to_unpacked_expression(ops[0]), ", ", to_unpacked_expression(ops[1]), ", ",
to_unpacked_expression(ops[2]), ", ", to_unpacked_expression(ops[3]), ");");
}
else
{
SPIRV_CROSS_THROW("Amplification shader in HLSL must have payload");
}
break;
}
default:
CompilerGLSL::emit_instruction(instruction);

View File

@ -1123,16 +1123,22 @@ void Parser::parse(const Instruction &instruction)
break;
case OpEmitMeshTasksEXT:
{
if (!current_block)
SPIRV_CROSS_THROW("Trying to end a non-existing block.");
const auto *type = maybe_get<SPIRType>(ops[0]);
if (type)
ir.load_type_width.insert({ ops[1], type->width });
current_block->ops.push_back(instruction);
current_block->terminator = SPIRBlock::EmitMeshTasks;
for (uint32_t i = 0; i < 3; i++)
current_block->mesh.groups[i] = ops[i];
current_block->mesh.payload = length >= 4 ? ops[3] : 0;
current_block = nullptr;
// Currently glslang is bugged and does not treat EmitMeshTasksEXT as a terminator.
ignore_trailing_block_opcodes = true;
break;
}
case OpReturn:
{