This is ready for review, but may not go upstream until after the release.
-- v3: vkd3d-shader/spirv: Add a parameter name for int64 capability. tests/shader-runner: Add 64-bit bitwise tests. tests/shader-runner: Add 64-bit arithmetic tests. tests/shader-runner: Introduce a 'shader int64' requirement directive. vkd3d-shader/spirv: Emit an error if 64-bit integers are used. vkd3d-shader/dxil: Introduce an instruction flag to suppress masking of bitwise shift counts.
From: Conor McCarthy cmccarthy@codeweavers.com
DXIL does not use implicit masking of shift counts. --- libs/vkd3d-shader/d3d_asm.c | 6 ++++++ libs/vkd3d-shader/dxil.c | 6 ++++++ libs/vkd3d-shader/spirv.c | 4 ++-- libs/vkd3d-shader/vkd3d_shader_private.h | 1 + 4 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d-shader/d3d_asm.c index 82d1d71d9..d7b406acb 100644 --- a/libs/vkd3d-shader/d3d_asm.c +++ b/libs/vkd3d-shader/d3d_asm.c @@ -1577,6 +1577,12 @@ static void shader_dump_instruction_flags(struct vkd3d_d3d_asm_compiler *compile shader_addline(buffer, "p"); break;
+ case VKD3DSIH_ISHL: + case VKD3DSIH_ISHR: + case VKD3DSIH_USHR: + if (ins->flags & VKD3DSI_SHIFT_UNMASKED) + shader_addline(buffer, "_unmasked"); + /* fall through */ default: shader_dump_precise_flags(compiler, ins->flags); break; diff --git a/libs/vkd3d-shader/dxil.c b/libs/vkd3d-shader/dxil.c index beb9ae574..50afc91a0 100644 --- a/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d-shader/dxil.c @@ -3167,6 +3167,12 @@ static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_reco } else { + if (handler_idx == VKD3DSIH_ISHL || handler_idx == VKD3DSIH_ISHR || handler_idx == VKD3DSIH_USHR) + { + /* DXC emits AND instructions where necessary to mask shift counts. Shift binops + * do not imply masking the shift as the TPF equivalents do. */ + ins->flags |= VKD3DSI_SHIFT_UNMASKED; + } instruction_dst_param_init_ssa_scalar(ins, sm6); } } diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 2197b74dd..10d5d8b1c 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -6712,8 +6712,8 @@ static enum vkd3d_result spirv_compiler_emit_alu_instruction(struct spirv_compil * Microsoft fxc will compile immediate constants larger than 5 bits. * Fixing up the constants would be more elegant, but the simplest way is * to let this handle constants too. */ - if (instruction->handler_idx == VKD3DSIH_ISHL || instruction->handler_idx == VKD3DSIH_ISHR - || instruction->handler_idx == VKD3DSIH_USHR) + if (!(instruction->flags & VKD3DSI_SHIFT_UNMASKED) && (instruction->handler_idx == VKD3DSIH_ISHL + || instruction->handler_idx == VKD3DSIH_ISHR || instruction->handler_idx == VKD3DSIH_USHR)) { uint32_t mask_id = spirv_compiler_get_constant_vector(compiler, VKD3D_SHADER_COMPONENT_UINT, vkd3d_write_mask_component_count(dst->write_mask), 0x1f); diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index d3989672b..faea815f1 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -740,6 +740,7 @@ enum vkd3d_tessellator_domain #define VKD3DSI_RESINFO_UINT 0x2 #define VKD3DSI_SAMPLE_INFO_UINT 0x1 #define VKD3DSI_SAMPLER_COMPARISON_MODE 0x1 +#define VKD3DSI_SHIFT_UNMASKED 0x1
#define VKD3DSI_PRECISE_X 0x100 #define VKD3DSI_PRECISE_Y 0x200
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/spirv.c | 8 ++++++++ libs/vkd3d-shader/vkd3d_shader_private.h | 1 + 2 files changed, 9 insertions(+)
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 10d5d8b1c..8a8163eb6 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -5441,6 +5441,14 @@ static void spirv_compiler_emit_dcl_global_flags(struct spirv_compiler *compiler flags &= ~(VKD3DSGF_ENABLE_DOUBLE_PRECISION_FLOAT_OPS | VKD3DSGF_ENABLE_11_1_DOUBLE_EXTENSIONS); }
+ if (flags & VKD3DSGF_ENABLE_INT64) + { + FIXME("Unsupported 64-bit integer ops.\n"); + spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INT64_UNSUPPORTED, + "Support for 64-bit integers is not implemented."); + flags &= ~VKD3DSGF_ENABLE_INT64; + } + if (flags & ~(VKD3DSGF_REFACTORING_ALLOWED | VKD3DSGF_ENABLE_RAW_AND_STRUCTURED_BUFFERS)) FIXME("Unhandled global flags %#"PRIx64".\n", (uint64_t)flags); else diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index faea815f1..fe57cc6cf 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -96,6 +96,7 @@ enum vkd3d_shader_error VKD3D_SHADER_ERROR_SPV_INVALID_TYPE = 2006, VKD3D_SHADER_ERROR_SPV_INVALID_HANDLER = 2007, VKD3D_SHADER_ERROR_SPV_NOT_IMPLEMENTED = 2008, + VKD3D_SHADER_ERROR_SPV_INT64_UNSUPPORTED = 2009,
VKD3D_SHADER_WARNING_SPV_INVALID_SWIZZLE = 2300,
From: Conor McCarthy cmccarthy@codeweavers.com
--- tests/shader_runner.c | 5 +++++ tests/shader_runner.h | 1 + tests/shader_runner_d3d12.c | 19 +++++++++++++++++++ 3 files changed, 25 insertions(+)
diff --git a/tests/shader_runner.c b/tests/shader_runner.c index 0e6104ce3..1670fc26c 100644 --- a/tests/shader_runner.c +++ b/tests/shader_runner.c @@ -191,6 +191,10 @@ static void parse_require_directive(struct shader_runner *runner, const char *li runner->compile_options |= options[i].option; } } + else if (match_string(line, "shader int64", &line)) + { + runner->require_int64 = true; + } else { fatal_error("Unknown require directive '%s'.\n", line); @@ -1311,6 +1315,7 @@ void run_shader_tests(struct shader_runner *runner, const struct shader_runner_o state = STATE_REQUIRE; runner->minimum_shader_model = minimum_shader_model; runner->maximum_shader_model = maximum_shader_model; + runner->require_int64 = false; runner->compile_options = 0; skip_tests = false; } diff --git a/tests/shader_runner.h b/tests/shader_runner.h index a4f0d2fd5..1caf4bbf5 100644 --- a/tests/shader_runner.h +++ b/tests/shader_runner.h @@ -122,6 +122,7 @@ struct shader_runner char *fx_source; enum shader_model minimum_shader_model; enum shader_model maximum_shader_model; + bool require_int64;
bool last_render_failed;
diff --git a/tests/shader_runner_d3d12.c b/tests/shader_runner_d3d12.c index a05dfd059..857f3679a 100644 --- a/tests/shader_runner_d3d12.c +++ b/tests/shader_runner_d3d12.c @@ -52,6 +52,8 @@ struct d3d12_shader_runner ID3D12GraphicsCommandList *compute_list;
IDxcCompiler3 *dxc_compiler; + + D3D12_FEATURE_DATA_D3D12_OPTIONS1 options1; };
static struct d3d12_shader_runner *d3d12_shader_runner(struct shader_runner *r) @@ -96,6 +98,16 @@ static ID3D10Blob *compile_shader(const struct d3d12_shader_runner *runner, cons return blob; }
+static bool d3d12_runner_check_requirements(struct shader_runner *r) +{ + struct d3d12_shader_runner *runner = d3d12_shader_runner(r); + + if (runner->r.require_int64 && !runner->options1.Int64ShaderOps) + return false; + + return true; +} + #define MAX_RESOURCE_DESCRIPTORS (MAX_RESOURCES * 2)
static struct resource *d3d12_runner_create_resource(struct shader_runner *r, const struct resource_params *params) @@ -561,6 +573,7 @@ static void d3d12_runner_release_readback(struct shader_runner *r, struct resour
static const struct shader_runner_ops d3d12_runner_ops = { + .check_requirements = d3d12_runner_check_requirements, .create_resource = d3d12_runner_create_resource, .destroy_resource = d3d12_runner_destroy_resource, .dispatch = d3d12_runner_dispatch, @@ -602,6 +615,12 @@ void run_shader_tests_d3d12(void *dxc_compiler, enum shader_model minimum_shader runner.compute_allocator, NULL, &IID_ID3D12GraphicsCommandList, (void **)&runner.compute_list); ok(hr == S_OK, "Failed to create command list, hr %#x.\n", hr);
+ hr = ID3D12Device_CheckFeatureSupport(device, D3D12_FEATURE_D3D12_OPTIONS1, + &runner.options1, sizeof(runner.options1)); + ok(hr == S_OK, "Failed to check feature options1 support, hr %#x.\n", hr); + if (maximum_shader_model >= SHADER_MODEL_6_0) + trace("Int64ShaderOps: %u.\n", runner.options1.Int64ShaderOps); + run_shader_tests(&runner.r, &d3d12_runner_ops, dxc_compiler, minimum_shader_model, maximum_shader_model);
ID3D12GraphicsCommandList_Release(runner.compute_list);
From: Conor McCarthy cmccarthy@codeweavers.com
--- .../hlsl/arithmetic-float-uniform.shader_test | 49 ++++++++++++ tests/hlsl/arithmetic-int-uniform.shader_test | 77 +++++++++++++++++++ 2 files changed, 126 insertions(+)
diff --git a/tests/hlsl/arithmetic-float-uniform.shader_test b/tests/hlsl/arithmetic-float-uniform.shader_test index 4812d053a..bf6f92e29 100644 --- a/tests/hlsl/arithmetic-float-uniform.shader_test +++ b/tests/hlsl/arithmetic-float-uniform.shader_test @@ -90,3 +90,52 @@ float4 main() : SV_TARGET uniform 0 float4 1.0 0.0 0.0 0.0 draw quad probe all rgba (1e99, 1e99, 1e99, 1e99) + +[require] +shader model >= 5.0 + +[pixel shader todo] +uniform double2 a; + +float4 main() : SV_TARGET +{ + double x = a.x; + double y = a.y; + return float4(x + y, x - y, x * y, x / y); +} + +[test] +uniform 0 double2 7.5 -2.5 +todo(sm<6) draw quad +probe all rgba (5.0, 10.0, -18.75, -3.0) + +[pixel shader todo] +uniform double2 a; + +float4 main() : SV_TARGET +{ + double x = a.x; + double y = a.y; + return x * y; +} + +[test] +uniform 0 double2 3.0e-300 2.5e300 +todo(sm<6) draw quad +probe all rgba (7.5, 7.5, 7.5, 7.5) + +% Note: DXC does not support modulo on doubles. +[pixel shader todo] +uniform double2 a; + +float4 main() : SV_TARGET +{ + double x = a.x; + double y = a.y; + return x / y; +} + +[test] +uniform 0 double2 1.5e300 2.0e299 +todo(sm<6) draw quad +probe all rgba (7.5, 7.5, 7.5, 7.5) diff --git a/tests/hlsl/arithmetic-int-uniform.shader_test b/tests/hlsl/arithmetic-int-uniform.shader_test index 7f5cdaaa6..f27aff037 100644 --- a/tests/hlsl/arithmetic-int-uniform.shader_test +++ b/tests/hlsl/arithmetic-int-uniform.shader_test @@ -119,3 +119,80 @@ uniform 0 float4 45.0 5.0 50.0 10.0 uniform 4 float4 3.0 8.0 2.0 5.0 draw quad probe all rgba (9.0, 5.0, 1.0, 3.0) + +[require] +shader model >= 6.0 +shader int64 + +[pixel shader] +uniform int64_t2 a; + +float4 main() : SV_TARGET +{ + int64_t x = a.x; + int64_t y = a.y; + return float4(x + y, x - y, x * (y >> 4), x / y); +} + +[test] +uniform 0 int64_t2 5000000000 16000000000 +todo draw quad +probe all rgba (21.0e9, -11.0e9, 5.0e18, 0.0) 1 + +[pixel shader] +uniform int64_t2 a; + +float4 main() : SV_TARGET +{ + int64_t x = a.x; + int64_t y = a.y; + return float4(x % y, +x, -x, y / x); +} + +[test] +uniform 0 int64_t2 5000000000 16000000000 +todo draw quad +probe all rgba (5.0e9, 5.0e9, -5.0e9, 3.0) + +[pixel shader] +uniform int64_t2 a; + +float4 main() : SV_TARGET +{ + int64_t x = a.x; + int64_t y = a.y; + return float4(x / y, -x / y, x / -y, -x / -y); +} + +[test] +uniform 0 int64_t2 42000000000 5000000000 +todo draw quad +probe all rgba (8.0, -8.0, -8.0, 8.0) + +[pixel shader] +uniform int64_t2 a; + +float4 main() : SV_TARGET +{ + int64_t x = a.x; + int64_t y = a.y; + return float4(x % y, -x % y, x % -y, -x % -y); +} + +[test] +uniform 0 int64_t2 42000000000 5000000000 +todo draw quad +probe all rgba (2.0e9, -2.0e9, 2.0e9, -2.0e9) + +[pixel shader] +uniform int64_t2 a; + +float4 main() : SV_TARGET +{ + return float4(abs(a), 0, 0); +} + +[test] +uniform 0 int64_t2 5000000000 -7000000000 +todo draw quad +probe all rgba (5.0, 7.0, 0.0, 10.0)
From: Conor McCarthy cmccarthy@codeweavers.com
--- tests/hlsl/bitwise.shader_test | 85 ++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+)
diff --git a/tests/hlsl/bitwise.shader_test b/tests/hlsl/bitwise.shader_test index 20a9db55f..095c9f77d 100644 --- a/tests/hlsl/bitwise.shader_test +++ b/tests/hlsl/bitwise.shader_test @@ -160,3 +160,88 @@ float4 main() : SV_TARGET [test] draw quad probe all rgba (0.0, 1.0, 1.0, 0.0) + + +[require] +shader model >= 6.0 +shader int64 + +[pixel shader] +int64_t2 a; +int2 s; + +float4 main() : sv_target +{ + int64_t x = a.x; + int64_t y = a.y; + int z = s.x; + int w = s.y; + + return float4(x >> y, x >> -y, x >> z, x >> w); +} + +[test] +uniform 0 int64_t2 9223372036854775807 -1 +uniform 4 int4 34 66 0 0 +todo draw quad +probe all rgba (0.0, 4.611686018e18, 536870912.0, 2.305843009e18) 1 +uniform 0 int64_t2 -1 -1 +uniform 4 int4 34 66 0 0 +todo draw quad +probe all rgba (-1.0, -1.0, -1.0, -1.0) 1 + +[pixel shader] +uint64_t2 a; +uint2 s; + +float4 main() : sv_target +{ + uint64_t x = a.x; + uint64_t y = a.y; + uint z = s.x; + uint w = s.y; + + return float4(x >> y, x >> -y, x >> z, x >> w); +} + +[test] +uniform 0 uint64_t2 0xffffffffffffffff 1 +uniform 4 uint4 34 66 0 0 +todo draw quad +probe all rgba (9.223372036e18, 1.0, 1073741823.0, 4.611686018e18) 1 + +[pixel shader] +uint64_t2 a; +uint2 s; + +float4 main() : sv_target +{ + uint64_t x = a.x; + uint64_t y = a.y; + uint z = s.x; + uint w = s.y; + + return float4(x << y, x << -y, x << z, x << w); +} + +[test] +uniform 0 uint64_t2 0x83 1 +uniform 4 uint4 34 66 0 0 +todo draw quad +probe all rgba (262.0, 9.223372036e18, 2250562863104.0, 524.0) 1 + +[pixel shader] +uint64_t2 a; + +float4 main() : sv_target +{ + uint64_t x = a.x; + uint64_t y = a.y; + + return float4(x ^ y, x & y, x | y, ~x); +} + +[test] +uniform 0 uint64_t2 0x300000000 0x500000000 +todo draw quad +probe all rgba (25769803776.0, 4294967296.0, 30064771072.0, 1.844674404e19) 1
From: Conor McCarthy cmccarthy@codeweavers.com
--- include/vkd3d_shader.h | 3 +++ libs/vkd3d-shader/spirv.c | 32 +++++++++++++++++++++++++++++--- 2 files changed, 32 insertions(+), 3 deletions(-)
diff --git a/include/vkd3d_shader.h b/include/vkd3d_shader.h index c43b619dc..6b9444bea 100644 --- a/include/vkd3d_shader.h +++ b/include/vkd3d_shader.h @@ -378,6 +378,7 @@ enum vkd3d_shader_parameter_data_type { VKD3D_SHADER_PARAMETER_DATA_TYPE_UNKNOWN, VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32, + VKD3D_SHADER_PARAMETER_DATA_TYPE_BOOL,
VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_PARAMETER_DATA_TYPE), }; @@ -386,6 +387,7 @@ enum vkd3d_shader_parameter_name { VKD3D_SHADER_PARAMETER_NAME_UNKNOWN, VKD3D_SHADER_PARAMETER_NAME_RASTERIZER_SAMPLE_COUNT, + VKD3D_SHADER_PARAMETER_NAME_CAPABILITY_INT64,
VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_PARAMETER_NAME), }; @@ -395,6 +397,7 @@ struct vkd3d_shader_parameter_immediate_constant union { uint32_t u32; + bool b; } u; };
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 8a8163eb6..ab0f3ee1a 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -2342,6 +2342,7 @@ struct spirv_compiler uint32_t *descriptor_offset_ids; struct vkd3d_push_constant_buffer_binding *push_constants; const struct vkd3d_shader_spirv_target_info *spirv_target_info; + bool capability_int64;
bool main_block_open; bool after_declarations_section; @@ -5443,9 +5444,16 @@ static void spirv_compiler_emit_dcl_global_flags(struct spirv_compiler *compiler
if (flags & VKD3DSGF_ENABLE_INT64) { - FIXME("Unsupported 64-bit integer ops.\n"); - spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INT64_UNSUPPORTED, - "Support for 64-bit integers is not implemented."); + if (!compiler->capability_int64) + { + WARN("Unsupported 64-bit integer ops.\n"); + spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INT64_UNSUPPORTED, + "The target environment does not support 64-bit integers."); + } + else + { + vkd3d_spirv_enable_capability(&compiler->spirv_builder, SpvCapabilityInt64); + } flags &= ~VKD3DSGF_ENABLE_INT64; }
@@ -7090,6 +7098,13 @@ static void spirv_compiler_emit_int_div(struct spirv_compiler *compiler, div_op = instruction->handler_idx == VKD3DSIH_IDIV ? SpvOpSDiv : SpvOpUDiv; mod_op = instruction->handler_idx == VKD3DSIH_IDIV ? SpvOpSRem : SpvOpUMod;
+ if (dst[0].reg.data_type == VKD3D_DATA_UINT64 || dst[1].reg.data_type == VKD3D_DATA_UINT64) + { + FIXME("Unsupported 64-bit result.\n"); + spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INT64_UNSUPPORTED, + "Bool cast to 64-bit integer is not supported."); + } + if (dst[0].reg.type != VKD3DSPR_NULL) { component_count = vkd3d_write_mask_component_count(dst[0].write_mask); @@ -9798,6 +9813,7 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; struct vkd3d_shader_desc *shader_desc = &parser->shader_desc; struct vkd3d_shader_instruction_array instructions; + const struct vkd3d_shader_parameter *parameter; enum vkd3d_result result = VKD3D_OK; unsigned int i;
@@ -9828,6 +9844,16 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, compiler->input_control_point_count = shader_desc->input_control_point_count; compiler->output_control_point_count = shader_desc->output_control_point_count;
+ if ((parameter = spirv_compiler_get_shader_parameter(compiler, VKD3D_SHADER_PARAMETER_NAME_CAPABILITY_INT64))) + { + if (parameter->data_type != VKD3D_SHADER_PARAMETER_DATA_TYPE_BOOL) + { + ERR("Invalid data type %#x for parameter CAPABILITY_INT64.\n", parameter->data_type); + return VKD3D_ERROR_INVALID_ARGUMENT; + } + compiler->capability_int64 = parameter->u.immediate_constant.u.b; + } + if (compiler->shader_type != VKD3D_SHADER_TYPE_HULL) spirv_compiler_emit_shader_signature_outputs(compiler);
On Mon Dec 4 07:07:23 2023 +0000, Conor McCarthy wrote:
For features, not extensions, which match up with a d3d12 global flag, it may be better for vkd3d-shader to send these to the client as a set of flags in a new scan struct, so the client can determine if a particular shader is supported before attempting to include it in a pipeline build. This places responsibility on the client not to compile unsupported shaders, but that is true of graphics libraries generally. In addition to int64, this would cover wave ops, native 16-bit, int64 atomics and probably others, and new additions would only require updating the flag enum, instead of passing yet another extension or parameter and reading it in the backend.
I had though about this too, but I'm not sure of what would be the advantage. IIUC what you're proposing is that, instead of having the client declare which features are supported by the environment, we have vkd3d-shader declare which features were used for compiling a particular shader, and leave it to the client to drop the compiled shader if it doesn't support some of the required feature. However the first model seems more useful to me: * if a feature is not known by the client but needed by the shader, in the first case compilation will fail, because the client will not declare it; in the second case compilation will succeed, and the client might fail to notice that that feature is required, because it doesn't know about it; this seems problematic; * it might happen that a feature is not strictly speaking required, because vkd3d-shader can emulate it with other instructions: in this case the first model vkd3d-shader is aware that the feature is not available and can fall back to emulation code, while in the second model vkd3d-shader doesn't know anything and can only use that feature, only for the shader to be dropped immediately after because the feature is not available.
In both case supporting new features amounts to adding a flag to an enum, doesn't it?
On Tue Dec 5 09:58:48 2023 +0000, Giovanni Mascellani wrote:
I had though about this too, but I'm not sure of what would be the advantage. IIUC what you're proposing is that, instead of having the client declare which features are supported by the environment, we have vkd3d-shader declare which features were used for compiling a particular shader, and leave it to the client to drop the compiled shader if it doesn't support some of the required feature. However the first model seems more useful to me:
- if a feature is not known by the client but needed by the shader, in
the first case compilation will fail, because the client will not declare it; in the second case compilation will succeed, and the client might fail to notice that that feature is required, because it doesn't know about it; this seems problematic;
- it might happen that a feature is not strictly speaking required,
because vkd3d-shader can emulate it with other instructions: in this case the first model vkd3d-shader is aware that the feature is not available and can fall back to emulation code, while in the second model vkd3d-shader doesn't know anything and can only use that feature, only for the shader to be dropped immediately after because the feature is not available. In both case supporting new features amounts to adding a flag to an enum, doesn't it?
Another problem with checking features in the client is it requires a shader scan in `state.c` which is currently skipped if descriptor indexing is fully supported.
Either way, I really want feature information to be passed as a flag enum. Extensions and parameters are both pretty clunky ways of doing it.
On Tue Dec 5 10:07:42 2023 +0000, Conor McCarthy wrote:
Another problem with checking features in the client is it requires a shader scan in `state.c` which is currently skipped if descriptor indexing is fully supported. Either way, I really want feature information to be passed as a flag enum. Extensions and parameters are both pretty clunky ways of doing it.
I don't know, I don't find them particularly clunky. Your current solution is pretty sensible, except that using extensions make more sense to me rather than parameters (which should even make the code slightly simpler).
On Tue Dec 5 10:22:21 2023 +0000, Giovanni Mascellani wrote:
I don't know, I don't find them particularly clunky. Your current solution is pretty sensible, except that using extensions make more sense to me rather than parameters (which should even make the code slightly simpler).
That's certainly not how shader parameters are supposed to be used, no.
I think the options here are essentially either a compile option or an extension. The two existing instances of this kind of thing that we have are VKD3D_SHADER_COMPILE_OPTION_TYPED_UAV and VKD3D_SHADER_COMPILE_OPTION_WRITE_TESS_GEOM_POINT_SIZE, so a compile option would be my first choice at this point. If we already know that we're going to need a number of other features like this, we could also make that compile option a set of flags, like we do for e.g. VKD3D_SHADER_COMPILE_OPTION_FORMATTING and VKD3D_SHADER_COMPILE_OPTION_BACKWARD_COMPATIBILITY.