From: Evan Tang etang@codeweavers.com
--- include/vkd3d_shader.h | 2 + libs/vkd3d-shader/spirv.c | 68 +++++++++++++++++++ libs/vkd3d-shader/vkd3d_shader_main.c | 5 +- libs/vkd3d-shader/vkd3d_shader_private.h | 2 + .../hlsl/rasterizer-ordered-views.shader_test | 4 +- 5 files changed, 78 insertions(+), 3 deletions(-)
diff --git a/include/vkd3d_shader.h b/include/vkd3d_shader.h index 46c685449..8f686cea7 100644 --- a/include/vkd3d_shader.h +++ b/include/vkd3d_shader.h @@ -1348,6 +1348,8 @@ enum vkd3d_shader_descriptor_info_flag /** The descriptor is a UAV resource, which is globally coherent. * \since 1.9 */ VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_UAV_GLOBALLY_COHERENT = 0x00000020, + /** The descriptor is a rasterizer-ordered UAV resource. \since 1.10 */ + VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_UAV_RASTERIZER_ORDERED = 0x00000040,
VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_DESCRIPTOR_INFO_FLAG), }; diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 08384e112..7863b985d 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -1893,6 +1893,9 @@ static bool vkd3d_spirv_compile_module(struct vkd3d_spirv_builder *builder, vkd3d_spirv_build_op_extension(&stream, "SPV_EXT_descriptor_indexing"); if (vkd3d_spirv_capability_is_enabled(builder, SpvCapabilityStencilExportEXT)) vkd3d_spirv_build_op_extension(&stream, "SPV_EXT_shader_stencil_export"); + if (vkd3d_spirv_capability_is_enabled(builder, SpvCapabilityFragmentShaderPixelInterlockEXT) + || vkd3d_spirv_capability_is_enabled(builder, SpvCapabilityFragmentShaderSampleInterlockEXT)) + vkd3d_spirv_build_op_extension(&stream, "SPV_EXT_fragment_shader_interlock");
if (builder->ext_instr_set_glsl_450) vkd3d_spirv_build_op_ext_inst_import(&stream, builder->ext_instr_set_glsl_450, "GLSL.std.450"); @@ -2334,6 +2337,7 @@ struct spirv_compiler size_t spec_constants_size; enum vkd3d_shader_compile_option_formatting_flags formatting; bool write_tess_geom_point_size; + bool wrap_main_in_interlock;
struct vkd3d_string_buffer_cache string_buffers;
@@ -5993,6 +5997,28 @@ static void spirv_compiler_emit_resource_declaration(struct spirv_compiler *comp if (d->flags & VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_UAV_GLOBALLY_COHERENT) vkd3d_spirv_build_op_decorate(builder, var_id, SpvDecorationCoherent, NULL, 0);
+ if (d->flags & VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_UAV_RASTERIZER_ORDERED) + { + if (compiler->shader_type != VKD3D_SHADER_TYPE_PIXEL) + { + FIXME("ROV is not supported for shader type %d\n", compiler->shader_type); + spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INCOMPATIBLE_PROFILE, + "ROV used in non-pixel shader."); + } + else if (spirv_compiler_is_target_extension_supported(compiler, VKD3D_SHADER_SPIRV_EXTENSION_EXT_FRAGMENT_SHADER_INTERLOCK)) + { + /* Will be later converted to SampleInterlockEXT if the shader turns out to run per-sample */ + vkd3d_spirv_enable_capability(builder, SpvCapabilityFragmentShaderPixelInterlockEXT); + compiler->wrap_main_in_interlock = true; + } + else + { + FIXME("The target environment does not support fragment shader interlock.\n"); + spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_FRAGMENT_SHADER_INTERLOCK_UNSUPPORTED, + "Cannot enable fragment shader interlock."); + } + } + if (d->flags & VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_UAV_COUNTER) { assert(structure_stride); /* counters are valid only for structured buffers */ @@ -6496,6 +6522,9 @@ static void spirv_compiler_emit_shader_epilogue_invocation(struct spirv_compiler uint32_t arguments[MAX_REG_OUTPUT]; unsigned int i, count;
+ if (compiler->wrap_main_in_interlock) + vkd3d_spirv_build_op(&builder->function_stream, SpvOpEndInvocationInterlockEXT); + if ((function_id = compiler->epilogue_function_id)) { void_id = vkd3d_spirv_get_op_type_void(builder); @@ -9276,6 +9305,21 @@ static void spirv_compiler_emit_main_prolog(struct spirv_compiler *compiler) if (compiler->xfb_info && compiler->xfb_info->element_count && compiler->shader_type != VKD3D_SHADER_TYPE_GEOMETRY) spirv_compiler_emit_point_size(compiler); + + if (compiler->wrap_main_in_interlock) + { + if (compiler->shader_type == VKD3D_SHADER_TYPE_PIXEL) + { + assert(compiler->main_block_open); + /* Maybe in the future we can try to shrink the size of the interlocked section */ + vkd3d_spirv_build_op(&compiler->spirv_builder.function_stream, SpvOpBeginInvocationInterlockEXT); + } + else + { + ERR("ROV used in non-pixel shader"); + compiler->wrap_main_in_interlock = false; + } + } }
static bool is_dcl_instruction(enum vkd3d_shader_opcode handler_idx) @@ -9670,6 +9714,28 @@ static void spirv_compiler_emit_descriptor_declarations(struct spirv_compiler *c } }
+static void spirv_compiler_fix_up_fragment_shader_interlock(struct spirv_compiler *compiler) +{ + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + unsigned int i; + + /* We don't know whether to use pixel or sample interlock during initial parse, so fix that up now */ + for (i = 0; i < builder->capabilities_count; i++) + { + if (builder->capabilities[i] == SpvCapabilityFragmentShaderPixelInterlockEXT) + { + SpvExecutionMode mode = SpvExecutionModePixelInterlockOrderedEXT; + if (vkd3d_spirv_capability_is_enabled(builder, SpvCapabilitySampleRateShading)) + { + builder->capabilities[i] = SpvCapabilityFragmentShaderSampleInterlockEXT; + mode = SpvExecutionModeSampleInterlockOrderedEXT; + } + spirv_compiler_emit_execution_mode(compiler, mode, NULL, 0); + break; + } + } +} + static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_parser *parser, struct vkd3d_shader_code *spirv) @@ -9750,6 +9816,8 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, spirv_compiler_emit_shader_epilogue_function(compiler); }
+ spirv_compiler_fix_up_fragment_shader_interlock(compiler); + if (compiler->strip_debug) vkd3d_spirv_stream_clear(&builder->debug_stream);
diff --git a/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d-shader/vkd3d_shader_main.c index fc61f0481..ca42b1a9d 100644 --- a/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d-shader/vkd3d_shader_main.c @@ -864,8 +864,11 @@ static void vkd3d_shader_scan_resource_declaration(struct vkd3d_shader_scan_cont { if (flags & VKD3DSUF_GLOBALLY_COHERENT) info_flags |= VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_UAV_GLOBALLY_COHERENT; + /* ROVs are implicitly globally coherent */ + if (flags & VKD3DSUF_RASTERISER_ORDERED_VIEW) + info_flags |= VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_UAV_GLOBALLY_COHERENT | VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_UAV_RASTERIZER_ORDERED; /* We don't distinguish between APPEND and COUNTER UAVs. */ - flags &= ~(VKD3DSUF_ORDER_PRESERVING_COUNTER | VKD3DSUF_GLOBALLY_COHERENT); + flags &= ~(VKD3DSUF_ORDER_PRESERVING_COUNTER | VKD3DSUF_GLOBALLY_COHERENT | VKD3DSUF_RASTERISER_ORDERED_VIEW); if (flags) FIXME("Unhandled UAV flags %#x.\n", flags); type = VKD3D_SHADER_DESCRIPTOR_TYPE_UAV; diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index 0de814221..603291808 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -93,6 +93,8 @@ enum vkd3d_shader_error VKD3D_SHADER_ERROR_SPV_DESCRIPTOR_IDX_UNSUPPORTED = 2003, VKD3D_SHADER_ERROR_SPV_STENCIL_EXPORT_UNSUPPORTED = 2004, VKD3D_SHADER_ERROR_SPV_OUT_OF_MEMORY = 2005, + VKD3D_SHADER_ERROR_SPV_INCOMPATIBLE_PROFILE = 2006, + VKD3D_SHADER_ERROR_SPV_FRAGMENT_SHADER_INTERLOCK_UNSUPPORTED = 2007,
VKD3D_SHADER_WARNING_SPV_INVALID_SWIZZLE = 2300, VKD3D_SHADER_WARNING_SPV_INVALID_UAV_FLAGS = 2301, diff --git a/tests/hlsl/rasterizer-ordered-views.shader_test b/tests/hlsl/rasterizer-ordered-views.shader_test index 6ab453c38..f081f956f 100644 --- a/tests/hlsl/rasterizer-ordered-views.shader_test +++ b/tests/hlsl/rasterizer-ordered-views.shader_test @@ -46,5 +46,5 @@ uint4 main(float4 pos : SV_Position, uint id : SV_PrimitiveID) : SV_Target } [test] todo(sm>=6) draw triangle list 93 -todo probe uav 1 all rui ( 0x7fffffff ) -todo probe all rui ( 0x3fffffff ) +probe uav 1 all rui ( 0x7fffffff ) +probe all rui ( 0x3fffffff )