[PATCH vkd3d 3/4] vkd3d-shader: Add support for retrieving the shader version through vkd3d_shader_scan().

Zebediah Figura zfigura at codeweavers.com
Tue Dec 28 16:20:19 CST 2021


Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
---
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




More information about the wine-devel mailing list