[PATCH vkd3d 4/4] vkd3d-shader: Add support for retrieving the creator string from DXBC shaders.
Zebediah Figura
zfigura at codeweavers.com
Tue Dec 28 16:20:20 CST 2021
Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
---
include/vkd3d_shader.h | 4 +
libs/vkd3d-shader/d3dbc.c | 7 +-
libs/vkd3d-shader/dxbc.c | 159 +++++++++++++++--------
libs/vkd3d-shader/vkd3d_shader.map | 1 +
libs/vkd3d-shader/vkd3d_shader_main.c | 20 ++-
libs/vkd3d-shader/vkd3d_shader_private.h | 11 +-
tests/vkd3d_shader_api.c | 1 +
7 files changed, 146 insertions(+), 57 deletions(-)
diff --git a/include/vkd3d_shader.h b/include/vkd3d_shader.h
index 25abf217e..da926b620 100644
--- a/include/vkd3d_shader.h
+++ b/include/vkd3d_shader.h
@@ -1304,6 +1304,8 @@ struct vkd3d_shader_scan_function_info
const void *next;
struct vkd3d_shader_version version;
+
+ const char *creator;
};
/**
@@ -1815,6 +1817,8 @@ VKD3D_SHADER_API void vkd3d_shader_free_shader_signature(struct vkd3d_shader_sig
VKD3D_SHADER_API int vkd3d_shader_preprocess(const struct vkd3d_shader_compile_info *compile_info,
struct vkd3d_shader_code *out, char **messages);
+VKD3D_SHADER_API void vkd3d_shader_free_scan_function_info(struct vkd3d_shader_scan_function_info *info);
+
#endif /* VKD3D_SHADER_NO_PROTOTYPES */
/** Type of vkd3d_shader_get_version(). */
diff --git a/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d-shader/d3dbc.c
index c5518752a..eabcc73e9 100644
--- a/libs/vkd3d-shader/d3dbc.c
+++ b/libs/vkd3d-shader/d3dbc.c
@@ -728,6 +728,10 @@ static void shader_sm1_validate_instruction(struct vkd3d_shader_sm1_parser *sm1,
}
}
+static void shader_sm1_read_metadata(struct vkd3d_shader_parser *parser)
+{
+}
+
static void shader_sm1_read_instruction(struct vkd3d_shader_parser *parser, struct vkd3d_shader_instruction *ins)
{
struct vkd3d_shader_sm1_parser *sm1 = vkd3d_shader_sm1_parser(parser);
@@ -863,6 +867,7 @@ const struct vkd3d_shader_parser_ops shader_sm1_parser_ops =
{
.parser_reset = shader_sm1_reset,
.parser_destroy = shader_sm1_destroy,
+ .parser_read_metadata = shader_sm1_read_metadata,
.parser_read_instruction = shader_sm1_read_instruction,
.parser_is_end = shader_sm1_is_end,
};
@@ -922,7 +927,7 @@ static enum vkd3d_result shader_sm1_init(struct vkd3d_shader_sm1_parser *sm1,
sm1->start = &code[1];
sm1->end = &code[token_count];
- vkd3d_shader_parser_init(&sm1->p, message_context, compile_info->source_name, &version, &shader_sm1_parser_ops);
+ vkd3d_shader_parser_init(&sm1->p, message_context, compile_info, &version, &shader_sm1_parser_ops);
shader_desc = &sm1->p.shader_desc;
shader_desc->byte_code = code;
shader_desc->byte_code_size = code_size;
diff --git a/libs/vkd3d-shader/dxbc.c b/libs/vkd3d-shader/dxbc.c
index 0b76a4a35..9144881e9 100644
--- a/libs/vkd3d-shader/dxbc.c
+++ b/libs/vkd3d-shader/dxbc.c
@@ -96,6 +96,7 @@ struct vkd3d_shader_sm4_parser
struct list src_free;
struct list src;
struct vkd3d_shader_immediate_constant_buffer icb;
+ bool found_rdef;
struct vkd3d_shader_parser p;
};
@@ -175,11 +176,63 @@ static bool shader_is_sm_5_1(const struct vkd3d_shader_sm4_parser *sm4)
return version->major >= 5 && version->minor >= 1;
}
+static int parse_dxbc(const char *data, size_t data_size,
+ struct vkd3d_shader_message_context *message_context, const char *source_name,
+ int (*chunk_handler)(const char *data, DWORD data_size, DWORD tag, void *ctx), void *ctx);
static bool shader_sm4_read_src_param(struct vkd3d_shader_sm4_parser *priv, const uint32_t **ptr,
const uint32_t *end, enum vkd3d_data_type data_type, struct vkd3d_shader_src_param *src_param);
static bool shader_sm4_read_dst_param(struct vkd3d_shader_sm4_parser *priv, const uint32_t **ptr,
const uint32_t *end, enum vkd3d_data_type data_type, struct vkd3d_shader_dst_param *dst_param);
+static bool require_space(size_t offset, size_t count, size_t size, size_t data_size)
+{
+ return !count || (data_size - offset) / count >= size;
+}
+
+static void read_dword(const char **ptr, DWORD *d)
+{
+ memcpy(d, *ptr, sizeof(*d));
+ *ptr += sizeof(*d);
+}
+
+static void read_float(const char **ptr, float *f)
+{
+ STATIC_ASSERT(sizeof(float) == sizeof(DWORD));
+ read_dword(ptr, (DWORD *)f);
+}
+
+static void skip_dword_unknown(const char **ptr, unsigned int count)
+{
+ unsigned int i;
+ DWORD d;
+
+ WARN("Skipping %u unknown DWORDs:\n", count);
+ for (i = 0; i < count; ++i)
+ {
+ read_dword(ptr, &d);
+ WARN("\t0x%08x\n", d);
+ }
+}
+
+static const char *shader_get_string(const char *data, size_t data_size, DWORD offset)
+{
+ size_t len, max_len;
+
+ if (offset >= data_size)
+ {
+ WARN("Invalid offset %#x (data size %#lx).\n", offset, (long)data_size);
+ return NULL;
+ }
+
+ max_len = data_size - offset;
+ len = strnlen(data + offset, max_len);
+
+ if (len == max_len)
+ return NULL;
+
+ return data + offset;
+}
+
static bool shader_sm4_read_register_space(struct vkd3d_shader_sm4_parser *priv,
const uint32_t **ptr, const uint32_t *end, unsigned int *register_space)
{
@@ -1441,6 +1494,54 @@ static void shader_sm4_read_instruction_modifier(DWORD modifier, struct vkd3d_sh
}
}
+static void shader_parse_rdef(uint32_t tag, const char *data, size_t data_size, struct vkd3d_shader_sm4_parser *sm4)
+{
+ DWORD cb_count, cb_offset, resource_count, resource_offset, target, flags, creator_offset;
+ const char *ptr = data;
+
+ read_dword(&ptr, &cb_count);
+ read_dword(&ptr, &cb_offset);
+ read_dword(&ptr, &resource_count);
+ read_dword(&ptr, &resource_offset);
+ read_dword(&ptr, &target);
+ read_dword(&ptr, &flags);
+ read_dword(&ptr, &creator_offset);
+
+ /* TODO: Parse RD11 chunks, resources, constant buffers. */
+
+ sm4->p.creator = shader_get_string(data, data_size, creator_offset);
+}
+
+static int metadata_handler(const char *data, DWORD data_size, DWORD tag, void *ctx)
+{
+ struct vkd3d_shader_sm4_parser *sm4 = ctx;
+
+ switch (tag)
+ {
+ case TAG_RDEF:
+ case TAG_RD11:
+ if (sm4->found_rdef)
+ FIXME("Multiple reflection chunks.\n");
+ shader_parse_rdef(tag, data, data_size, sm4);
+ break;
+
+ default:
+ TRACE("Skipping chunk %#x.\n", tag);
+ break;
+ }
+
+ return VKD3D_OK;
+}
+
+static void shader_sm4_read_metadata(struct vkd3d_shader_parser *parser)
+{
+ struct vkd3d_shader_sm4_parser *sm4 = vkd3d_shader_sm4_parser(parser);
+
+ if (parse_dxbc(parser->shader->code, parser->shader->size, parser->message_context,
+ parser->location.source_name, metadata_handler, sm4))
+ ERR("Failed to parse metadata.\n");
+}
+
static void shader_sm4_read_instruction(struct vkd3d_shader_parser *parser, struct vkd3d_shader_instruction *ins)
{
struct vkd3d_shader_sm4_parser *sm4 = vkd3d_shader_sm4_parser(parser);
@@ -1582,12 +1683,13 @@ static const struct vkd3d_shader_parser_ops shader_sm4_parser_ops =
{
.parser_reset = shader_sm4_reset,
.parser_destroy = shader_sm4_destroy,
+ .parser_read_metadata = shader_sm4_read_metadata,
.parser_read_instruction = shader_sm4_read_instruction,
.parser_is_end = shader_sm4_is_end,
};
-static bool shader_sm4_init(struct vkd3d_shader_sm4_parser *sm4, const uint32_t *byte_code,
- size_t byte_code_size, const char *source_name, const struct vkd3d_shader_signature *output_signature,
+static bool shader_sm4_init(struct vkd3d_shader_sm4_parser *sm4, const uint32_t *byte_code, size_t byte_code_size,
+ const struct vkd3d_shader_compile_info *compile_info, const struct vkd3d_shader_signature *output_signature,
struct vkd3d_shader_message_context *message_context)
{
struct vkd3d_shader_version version;
@@ -1646,7 +1748,7 @@ static bool shader_sm4_init(struct vkd3d_shader_sm4_parser *sm4, const uint32_t
version.major = VKD3D_SM4_VERSION_MAJOR(version_token);
version.minor = VKD3D_SM4_VERSION_MINOR(version_token);
- vkd3d_shader_parser_init(&sm4->p, message_context, source_name, &version, &shader_sm4_parser_ops);
+ vkd3d_shader_parser_init(&sm4->p, message_context, compile_info, &version, &shader_sm4_parser_ops);
sm4->p.ptr = sm4->start;
memset(sm4->output_map, 0xff, sizeof(sm4->output_map));
@@ -1669,55 +1771,6 @@ static bool shader_sm4_init(struct vkd3d_shader_sm4_parser *sm4, const uint32_t
return true;
}
-static bool require_space(size_t offset, size_t count, size_t size, size_t data_size)
-{
- return !count || (data_size - offset) / count >= size;
-}
-
-static void read_dword(const char **ptr, DWORD *d)
-{
- memcpy(d, *ptr, sizeof(*d));
- *ptr += sizeof(*d);
-}
-
-static void read_float(const char **ptr, float *f)
-{
- STATIC_ASSERT(sizeof(float) == sizeof(DWORD));
- read_dword(ptr, (DWORD *)f);
-}
-
-static void skip_dword_unknown(const char **ptr, unsigned int count)
-{
- unsigned int i;
- DWORD d;
-
- WARN("Skipping %u unknown DWORDs:\n", count);
- for (i = 0; i < count; ++i)
- {
- read_dword(ptr, &d);
- WARN("\t0x%08x\n", d);
- }
-}
-
-static const char *shader_get_string(const char *data, size_t data_size, DWORD offset)
-{
- size_t len, max_len;
-
- if (offset >= data_size)
- {
- WARN("Invalid offset %#x (data size %#lx).\n", offset, (long)data_size);
- return NULL;
- }
-
- max_len = data_size - offset;
- len = strnlen(data + offset, max_len);
-
- if (len == max_len)
- return NULL;
-
- return data + offset;
-}
-
static int parse_dxbc(const char *data, size_t data_size,
struct vkd3d_shader_message_context *message_context, const char *source_name,
int (*chunk_handler)(const char *data, DWORD data_size, DWORD tag, void *ctx), void *ctx)
@@ -2050,7 +2103,7 @@ int vkd3d_shader_sm4_parser_create(const struct vkd3d_shader_compile_info *compi
}
if (!shader_sm4_init(sm4, shader_desc->byte_code, shader_desc->byte_code_size,
- compile_info->source_name, &shader_desc->output_signature, message_context))
+ compile_info, &shader_desc->output_signature, message_context))
{
WARN("Failed to initialise shader parser.\n");
free_shader_desc(shader_desc);
diff --git a/libs/vkd3d-shader/vkd3d_shader.map b/libs/vkd3d-shader/vkd3d_shader.map
index 2e49fe248..1127391cf 100644
--- a/libs/vkd3d-shader/vkd3d_shader.map
+++ b/libs/vkd3d-shader/vkd3d_shader.map
@@ -7,6 +7,7 @@ global:
vkd3d_shader_free_messages;
vkd3d_shader_free_root_signature;
vkd3d_shader_free_scan_descriptor_info;
+ vkd3d_shader_free_scan_function_info;
vkd3d_shader_free_shader_code;
vkd3d_shader_free_shader_signature;
vkd3d_shader_get_supported_source_types;
diff --git a/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d-shader/vkd3d_shader_main.c
index 7e82f18db..307ffce70 100644
--- a/libs/vkd3d-shader/vkd3d_shader_main.c
+++ b/libs/vkd3d-shader/vkd3d_shader_main.c
@@ -365,11 +365,12 @@ void vkd3d_shader_dump_shader(enum vkd3d_shader_source_type source_type,
}
void vkd3d_shader_parser_init(struct vkd3d_shader_parser *parser,
- struct vkd3d_shader_message_context *message_context, const char *source_name,
+ struct vkd3d_shader_message_context *message_context, const struct vkd3d_shader_compile_info *compile_info,
const struct vkd3d_shader_version *version, const struct vkd3d_shader_parser_ops *ops)
{
+ parser->shader = &compile_info->source;
parser->message_context = message_context;
- parser->location.source_name = source_name;
+ parser->location.source_name = compile_info->source_name;
parser->location.line = 1;
parser->location.column = 0;
parser->shader_version = *version;
@@ -983,7 +984,15 @@ static int scan_with_parser(const struct vkd3d_shader_compile_info *compile_info
if (func_info)
{
+ vkd3d_shader_parser_read_metadata(parser);
+
func_info->version = parser->shader_version;
+ func_info->creator = NULL;
+ if (parser->creator && !(func_info->creator = vkd3d_strdup(parser->creator)))
+ {
+ ret = VKD3D_ERROR_OUT_OF_MEMORY;
+ goto done;
+ }
}
ret = VKD3D_OK;
@@ -1251,6 +1260,13 @@ void vkd3d_shader_free_scan_descriptor_info(struct vkd3d_shader_scan_descriptor_
vkd3d_free(scan_descriptor_info->descriptors);
}
+void vkd3d_shader_free_scan_function_info(struct vkd3d_shader_scan_function_info *info)
+{
+ TRACE("info %p.\n", info);
+
+ vkd3d_free((char *)info->creator);
+}
+
void vkd3d_shader_free_shader_code(struct vkd3d_shader_code *shader_code)
{
TRACE("shader_code %p.\n", shader_code);
diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h
index c7ffa3c81..b4d856948 100644
--- a/libs/vkd3d-shader/vkd3d_shader_private.h
+++ b/libs/vkd3d-shader/vkd3d_shader_private.h
@@ -880,6 +880,7 @@ struct vkd3d_shader_location
struct vkd3d_shader_parser
{
+ const struct vkd3d_shader_code *shader;
struct vkd3d_shader_message_context *message_context;
struct vkd3d_shader_location location;
bool failed;
@@ -888,12 +889,15 @@ struct vkd3d_shader_parser
struct vkd3d_shader_version shader_version;
const uint32_t *ptr;
const struct vkd3d_shader_parser_ops *ops;
+
+ const char *creator;
};
struct vkd3d_shader_parser_ops
{
void (*parser_reset)(struct vkd3d_shader_parser *parser);
void (*parser_destroy)(struct vkd3d_shader_parser *parser);
+ void (*parser_read_metadata)(struct vkd3d_shader_parser *parser);
void (*parser_read_instruction)(struct vkd3d_shader_parser *parser, struct vkd3d_shader_instruction *instruction);
bool (*parser_is_end)(struct vkd3d_shader_parser *parser);
};
@@ -901,7 +905,7 @@ struct vkd3d_shader_parser_ops
void vkd3d_shader_parser_error(struct vkd3d_shader_parser *parser,
enum vkd3d_shader_error error, const char *format, ...) VKD3D_PRINTF_FUNC(3, 4);
void vkd3d_shader_parser_init(struct vkd3d_shader_parser *parser,
- struct vkd3d_shader_message_context *message_context, const char *source_name,
+ struct vkd3d_shader_message_context *message_context, const struct vkd3d_shader_compile_info *compile_info,
const struct vkd3d_shader_version *version, const struct vkd3d_shader_parser_ops *ops);
void vkd3d_shader_parser_warning(struct vkd3d_shader_parser *parser,
enum vkd3d_shader_error error, const char *format, ...) VKD3D_PRINTF_FUNC(3, 4);
@@ -916,6 +920,11 @@ static inline bool vkd3d_shader_parser_is_end(struct vkd3d_shader_parser *parser
return parser->ops->parser_is_end(parser);
}
+static inline void vkd3d_shader_parser_read_metadata(struct vkd3d_shader_parser *parser)
+{
+ parser->ops->parser_read_metadata(parser);
+}
+
static inline void vkd3d_shader_parser_read_instruction(struct vkd3d_shader_parser *parser,
struct vkd3d_shader_instruction *instruction)
{
diff --git a/tests/vkd3d_shader_api.c b/tests/vkd3d_shader_api.c
index 31eeb17f2..89455b627 100644
--- a/tests/vkd3d_shader_api.c
+++ b/tests/vkd3d_shader_api.c
@@ -356,6 +356,7 @@ static void test_scan_dxbc(void)
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_scan_function_info(&func_info);
vkd3d_shader_free_shader_code(&dxbc);
}
--
2.34.1
More information about the wine-devel
mailing list