From: Zebediah Figura Subject: [PATCH vkd3d 3/4] vkd3d-shader: Add support for retrieving the shader version through vkd3d_shader_scan(). Message-Id: <20211228222020.13814-3-zfigura@codeweavers.com> Date: Tue, 28 Dec 2021 16:20:19 -0600 In-Reply-To: <20211228222020.13814-1-zfigura@codeweavers.com> References: <20211228222020.13814-1-zfigura@codeweavers.com> Signed-off-by: Zebediah Figura --- Besides being the first patch implementing reflection, this patch introduces an API problem with regard to D3DReflect() that will affect many different fields. Namely, if the SM4 version token contains a nonsensical version D3DReflect() will happily return it verbatim. As I see it our options are: (1) return the token verbatim anyway instead of using struct vkd3d_shader_version, (2) don't use vkd3d_shader_scan() for wine's D3DReflect() [and either diverge from native in vkd3d-utils' D3DReflect(), or don't use vkd3d_shader_scan() there either] (3) return the token verbatim in a separate field (and in a separate chained structure?) (4) punt, and use one of the above solutions if we ever do come across a shader that contains insane data. There are some other, similar problems: * HLSL compile flags would be especially annoying to translate to e.g. libvkd3d-shader compile arguments and then back again. (Frankly, it's already annoying that we have to do that in the HLSL compiler.) This is basically the same problem as the above, but it forms an argument for returning tokens verbatim, or at least that one. * Instruction counts (and I think everything else in the STAT chunk) are always taken from the STAT chunk; if the STAT chunk is missing then D3DReflect() will return zero, even though it could just count them. Should we preserve that behaviour in libvkd3d-shader? in libvkd3d-utils? include/vkd3d_shader.h | 39 ++++++++++++++++++++++ libs/vkd3d-shader/vkd3d_shader_main.c | 16 ++++++++- libs/vkd3d-shader/vkd3d_shader_private.h | 24 -------------- tests/vkd3d_shader_api.c | 42 ++++++++++++++++++++++++ 4 files changed, 96 insertions(+), 25 deletions(-) diff --git a/include/vkd3d_shader.h b/include/vkd3d_shader.h index 791ac0377..25abf217e 100644 --- a/include/vkd3d_shader.h +++ b/include/vkd3d_shader.h @@ -69,6 +69,11 @@ enum vkd3d_shader_structure_type * \since 1.3 */ VKD3D_SHADER_STRUCTURE_TYPE_DESCRIPTOR_OFFSET_INFO, + /** + * The structure is a vkd3d_shader_scan_function_info structure. + * \since 1.3 + */ + VKD3D_SHADER_STRUCTURE_TYPE_SCAN_FUNCTION_INFO, VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_STRUCTURE_TYPE), }; @@ -1267,6 +1272,40 @@ struct vkd3d_shader_scan_descriptor_info unsigned int descriptor_count; }; +enum vkd3d_shader_type +{ + VKD3D_SHADER_TYPE_PIXEL, + VKD3D_SHADER_TYPE_VERTEX, + VKD3D_SHADER_TYPE_GEOMETRY, + VKD3D_SHADER_TYPE_HULL, + VKD3D_SHADER_TYPE_DOMAIN, + VKD3D_SHADER_TYPE_GRAPHICS_COUNT, + + VKD3D_SHADER_TYPE_COMPUTE = VKD3D_SHADER_TYPE_GRAPHICS_COUNT, + + VKD3D_SHADER_TYPE_EFFECT, + VKD3D_SHADER_TYPE_TEXTURE, + VKD3D_SHADER_TYPE_LIBRARY, + VKD3D_SHADER_TYPE_COUNT, + + VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_TYPE), +}; + +struct vkd3d_shader_version +{ + enum vkd3d_shader_type type; + uint16_t major; + uint16_t minor; +}; + +struct vkd3d_shader_scan_function_info +{ + enum vkd3d_shader_structure_type type; + const void *next; + + struct vkd3d_shader_version version; +}; + /** * Data type of a shader varying, returned as part of struct * vkd3d_shader_signature_element. diff --git a/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d-shader/vkd3d_shader_main.c index 47fe3d60d..7e82f18db 100644 --- a/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d-shader/vkd3d_shader_main.c @@ -933,6 +933,7 @@ static int scan_with_parser(const struct vkd3d_shader_compile_info *compile_info struct vkd3d_shader_message_context *message_context, struct vkd3d_shader_parser *parser) { struct vkd3d_shader_scan_descriptor_info *scan_descriptor_info; + struct vkd3d_shader_scan_function_info *func_info; struct vkd3d_shader_instruction instruction; struct vkd3d_shader_scan_context context; int ret; @@ -943,6 +944,8 @@ static int scan_with_parser(const struct vkd3d_shader_compile_info *compile_info scan_descriptor_info->descriptor_count = 0; } + func_info = vkd3d_find_struct(compile_info->next, SCAN_FUNCTION_INFO); + vkd3d_shader_scan_context_init(&context, compile_info, scan_descriptor_info, message_context); if (TRACE_ON()) @@ -972,7 +975,18 @@ static int scan_with_parser(const struct vkd3d_shader_compile_info *compile_info } } - ret = parser->failed ? VKD3D_ERROR_INVALID_SHADER : VKD3D_OK; + if (parser->failed) + { + ret = VKD3D_ERROR_INVALID_SHADER; + goto done; + } + + if (func_info) + { + func_info->version = parser->shader_version; + } + + ret = VKD3D_OK; done: vkd3d_shader_scan_context_cleanup(&context); diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index ffea91d36..c7ffa3c81 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -594,30 +594,6 @@ enum vkd3d_shader_conditional_op #define MAX_IMMEDIATE_CONSTANT_BUFFER_SIZE 4096 #define MAX_REG_OUTPUT 32 -enum vkd3d_shader_type -{ - VKD3D_SHADER_TYPE_PIXEL, - VKD3D_SHADER_TYPE_VERTEX, - VKD3D_SHADER_TYPE_GEOMETRY, - VKD3D_SHADER_TYPE_HULL, - VKD3D_SHADER_TYPE_DOMAIN, - VKD3D_SHADER_TYPE_GRAPHICS_COUNT, - - VKD3D_SHADER_TYPE_COMPUTE = VKD3D_SHADER_TYPE_GRAPHICS_COUNT, - - VKD3D_SHADER_TYPE_EFFECT, - VKD3D_SHADER_TYPE_TEXTURE, - VKD3D_SHADER_TYPE_LIBRARY, - VKD3D_SHADER_TYPE_COUNT, -}; - -struct vkd3d_shader_version -{ - enum vkd3d_shader_type type; - uint8_t major; - uint8_t minor; -}; - struct vkd3d_shader_immediate_constant_buffer { unsigned int vec4_count; diff --git a/tests/vkd3d_shader_api.c b/tests/vkd3d_shader_api.c index 6fb855c26..31eeb17f2 100644 --- a/tests/vkd3d_shader_api.c +++ b/tests/vkd3d_shader_api.c @@ -318,6 +318,47 @@ static void test_d3dbc(void) ok(rc == VKD3D_ERROR_INVALID_SHADER, "Got unexpected error code %d.\n", rc); } +static void test_scan_dxbc(void) +{ + struct vkd3d_shader_scan_function_info func_info = {.type = VKD3D_SHADER_STRUCTURE_TYPE_SCAN_FUNCTION_INFO}; + struct vkd3d_shader_hlsl_source_info hlsl_info = {.type = VKD3D_SHADER_STRUCTURE_TYPE_HLSL_SOURCE_INFO}; + struct vkd3d_shader_compile_info compile_info = {.type = VKD3D_SHADER_STRUCTURE_TYPE_COMPILE_INFO}; + struct vkd3d_shader_code dxbc; + int rc; + + static const char vs_source[] = + "float4 main(float4 pos : position) : sv_position\n" + "{\n" + " return pos;\n" + "}"; + + compile_info.source.code = vs_source; + compile_info.source.size = strlen(vs_source); + compile_info.source_type = VKD3D_SHADER_SOURCE_HLSL; + compile_info.target_type = VKD3D_SHADER_TARGET_DXBC_TPF; + compile_info.log_level = VKD3D_SHADER_LOG_INFO; + + compile_info.next = &hlsl_info; + hlsl_info.profile = "vs_4_1"; + + rc = vkd3d_shader_compile(&compile_info, &dxbc, NULL); + ok(rc == VKD3D_OK, "Got unexpected error code %d.\n", rc); + + compile_info.source_type = VKD3D_SHADER_SOURCE_DXBC_TPF; + compile_info.source = dxbc; + + compile_info.next = &func_info; + + rc = vkd3d_shader_scan(&compile_info, NULL); + ok(rc == VKD3D_OK, "Got unexpected error code %d.\n", rc); + + ok(func_info.version.type == VKD3D_SHADER_TYPE_VERTEX, "Got shader type %#x.\n", func_info.version.type); + ok(func_info.version.major == 4, "Got major version %u.\n", func_info.version.major); + ok(func_info.version.minor == 1, "Got minor version %u.\n", func_info.version.minor); + + vkd3d_shader_free_shader_code(&dxbc); +} + START_TEST(vkd3d_shader_api) { setlocale(LC_ALL, ""); @@ -326,4 +367,5 @@ START_TEST(vkd3d_shader_api) run_test(test_vkd3d_shader_pfns); run_test(test_version); run_test(test_d3dbc); + run_test(test_scan_dxbc); } -- 2.34.1