mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2024-11-21 16:46:41 -08:00
vkd3d-shader/dxbc: Introduce API for parsing DXBC blobs.
This commit is contained in:
parent
d0d2130f74
commit
c87492ed21
Notes:
Alexandre Julliard
2023-02-23 22:20:24 +01:00
Approved-by: Zebediah Figura (@zfigura) Approved-by: Henri Verbeet (@hverbeet) Approved-by: Alexandre Julliard (@julliard) Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/103
@ -1472,6 +1472,46 @@ enum vkd3d_shader_swizzle_component
|
|||||||
VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_SWIZZLE_COMPONENT),
|
VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_SWIZZLE_COMPONENT),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A description of a DXBC section.
|
||||||
|
*
|
||||||
|
* \since 1.7
|
||||||
|
*/
|
||||||
|
struct vkd3d_shader_dxbc_section_desc
|
||||||
|
{
|
||||||
|
/** The section tag. */
|
||||||
|
uint32_t tag;
|
||||||
|
/** The contents of the section. */
|
||||||
|
struct vkd3d_shader_code data;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A description of a DXBC blob, as returned by vkd3d_shader_parse_dxbc().
|
||||||
|
*
|
||||||
|
* \since 1.7
|
||||||
|
*/
|
||||||
|
struct vkd3d_shader_dxbc_desc
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The DXBC tag. This will always be "DXBC" in structures returned by
|
||||||
|
* this version of vkd3d-shader.
|
||||||
|
*/
|
||||||
|
uint32_t tag;
|
||||||
|
/** A checksum of the DXBC contents. */
|
||||||
|
uint32_t checksum[4];
|
||||||
|
/**
|
||||||
|
* The DXBC version. This will always be 1 in structures returned by this
|
||||||
|
* version of vkd3d-shader.
|
||||||
|
*/
|
||||||
|
unsigned int version;
|
||||||
|
/** The total size of the DXBC blob. */
|
||||||
|
size_t size;
|
||||||
|
/** The number of sections contained in the DXBC. */
|
||||||
|
size_t section_count;
|
||||||
|
/** Descriptions of the sections contained in the DXBC. */
|
||||||
|
struct vkd3d_shader_dxbc_section_desc *sections;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A mask selecting one component from a vkd3d-shader swizzle. The component has
|
* A mask selecting one component from a vkd3d-shader swizzle. The component has
|
||||||
* type \ref vkd3d_shader_swizzle_component.
|
* type \ref vkd3d_shader_swizzle_component.
|
||||||
@ -1865,6 +1905,47 @@ VKD3D_SHADER_API int vkd3d_shader_preprocess(const struct vkd3d_shader_compile_i
|
|||||||
*/
|
*/
|
||||||
VKD3D_SHADER_API void vkd3d_shader_set_log_callback(PFN_vkd3d_log callback);
|
VKD3D_SHADER_API void vkd3d_shader_set_log_callback(PFN_vkd3d_log callback);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free the contents of a vkd3d_shader_dxbc_desc structure allocated by
|
||||||
|
* another vkd3d-shader function, such as vkd3d_shader_parse_dxbc().
|
||||||
|
*
|
||||||
|
* This function may free the \ref vkd3d_shader_dxbc_desc.sections member, but
|
||||||
|
* does not free the structure itself.
|
||||||
|
*
|
||||||
|
* \param dxbc The vkd3d_shader_dxbc_desc structure to free.
|
||||||
|
*
|
||||||
|
* \since 1.7
|
||||||
|
*/
|
||||||
|
VKD3D_SHADER_API void vkd3d_shader_free_dxbc(struct vkd3d_shader_dxbc_desc *dxbc);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a DXBC blob contained in a vkd3d_shader_code structure.
|
||||||
|
*
|
||||||
|
* \param dxbc A vkd3d_shader_code structure containing the DXBC blob to parse.
|
||||||
|
*
|
||||||
|
* \param flags A set of flags modifying the behaviour of the function. No
|
||||||
|
* flags are defined for this version of vkd3d-shader, and this parameter
|
||||||
|
* should be set to 0.
|
||||||
|
*
|
||||||
|
* \param desc A vkd3d_shader_dxbc_desc structure describing the contents of
|
||||||
|
* the DXBC blob. Its vkd3d_shader_dxbc_section_desc structures will contain
|
||||||
|
* pointers into the input blob; its contents are only valid while the input
|
||||||
|
* blob is valid. The contents of this structure should be freed with
|
||||||
|
* vkd3d_shader_free_dxbc() when no longer needed.
|
||||||
|
*
|
||||||
|
* \param messages Optional output location for error or informational messages
|
||||||
|
* produced by the parser.
|
||||||
|
* \n
|
||||||
|
* This parameter behaves identically to the \a messages parameter of
|
||||||
|
* vkd3d_shader_compile().
|
||||||
|
*
|
||||||
|
* \return A member of \ref vkd3d_result.
|
||||||
|
*
|
||||||
|
* \since 1.7
|
||||||
|
*/
|
||||||
|
VKD3D_SHADER_API int vkd3d_shader_parse_dxbc(const struct vkd3d_shader_code *dxbc,
|
||||||
|
uint32_t flags, struct vkd3d_shader_dxbc_desc *desc, char **messages);
|
||||||
|
|
||||||
#endif /* VKD3D_SHADER_NO_PROTOTYPES */
|
#endif /* VKD3D_SHADER_NO_PROTOTYPES */
|
||||||
|
|
||||||
/** Type of vkd3d_shader_get_version(). */
|
/** Type of vkd3d_shader_get_version(). */
|
||||||
@ -1921,6 +2002,12 @@ typedef void (*PFN_vkd3d_shader_preprocess)(struct vkd3d_shader_compile_info *co
|
|||||||
/** Type of vkd3d_shader_set_log_callback(). \since 1.4 */
|
/** Type of vkd3d_shader_set_log_callback(). \since 1.4 */
|
||||||
typedef void (*PFN_vkd3d_shader_set_log_callback)(PFN_vkd3d_log callback);
|
typedef void (*PFN_vkd3d_shader_set_log_callback)(PFN_vkd3d_log callback);
|
||||||
|
|
||||||
|
/** Type of vkd3d_shader_free_dxbc(). \since 1.7 */
|
||||||
|
typedef void (*PFN_vkd3d_shader_free_dxbc)(struct vkd3d_shader_dxbc_desc *dxbc);
|
||||||
|
/** Type of vkd3d_shader_parse_dxbc(). \since 1.7 */
|
||||||
|
typedef int (*PFN_vkd3d_shader_parse_dxbc)(const struct vkd3d_shader_code *dxbc,
|
||||||
|
uint32_t flags, struct vkd3d_shader_dxbc_desc *desc, char **messages);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
@ -1725,20 +1725,19 @@ static const char *shader_get_string(const char *data, size_t data_size, DWORD o
|
|||||||
return data + offset;
|
return data + offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int for_each_dxbc_section(const struct vkd3d_shader_code *dxbc,
|
static int parse_dxbc(const struct vkd3d_shader_code *dxbc, struct vkd3d_shader_message_context *message_context,
|
||||||
struct vkd3d_shader_message_context *message_context, const char *source_name,
|
const char *source_name, struct vkd3d_shader_dxbc_desc *desc)
|
||||||
int (*section_handler)(const struct vkd3d_shader_dxbc_section_desc *section, void *ctx), void *ctx)
|
|
||||||
{
|
{
|
||||||
const struct vkd3d_shader_location location = {.source_name = source_name};
|
const struct vkd3d_shader_location location = {.source_name = source_name};
|
||||||
|
struct vkd3d_shader_dxbc_section_desc *sections, *section;
|
||||||
uint32_t checksum[4], calculated_checksum[4];
|
uint32_t checksum[4], calculated_checksum[4];
|
||||||
const char *data = dxbc->code;
|
const char *data = dxbc->code;
|
||||||
size_t data_size = dxbc->size;
|
size_t data_size = dxbc->size;
|
||||||
const char *ptr = data;
|
const char *ptr = data;
|
||||||
int ret = VKD3D_OK;
|
|
||||||
uint32_t chunk_count;
|
uint32_t chunk_count;
|
||||||
uint32_t total_size;
|
uint32_t total_size;
|
||||||
unsigned int i;
|
|
||||||
uint32_t version;
|
uint32_t version;
|
||||||
|
unsigned int i;
|
||||||
uint32_t tag;
|
uint32_t tag;
|
||||||
|
|
||||||
if (data_size < VKD3D_DXBC_HEADER_SIZE)
|
if (data_size < VKD3D_DXBC_HEADER_SIZE)
|
||||||
@ -1792,9 +1791,14 @@ static int for_each_dxbc_section(const struct vkd3d_shader_code *dxbc,
|
|||||||
read_dword(&ptr, &chunk_count);
|
read_dword(&ptr, &chunk_count);
|
||||||
TRACE("chunk count: %#x\n", chunk_count);
|
TRACE("chunk count: %#x\n", chunk_count);
|
||||||
|
|
||||||
|
if (!(sections = vkd3d_calloc(chunk_count, sizeof(*sections))))
|
||||||
|
{
|
||||||
|
vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXBC_OUT_OF_MEMORY, "Out of memory.");
|
||||||
|
return VKD3D_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < chunk_count; ++i)
|
for (i = 0; i < chunk_count; ++i)
|
||||||
{
|
{
|
||||||
struct vkd3d_shader_dxbc_section_desc section;
|
|
||||||
uint32_t chunk_tag, chunk_size;
|
uint32_t chunk_tag, chunk_size;
|
||||||
const char *chunk_ptr;
|
const char *chunk_ptr;
|
||||||
uint32_t chunk_offset;
|
uint32_t chunk_offset;
|
||||||
@ -1807,6 +1811,7 @@ static int for_each_dxbc_section(const struct vkd3d_shader_code *dxbc,
|
|||||||
WARN("Invalid chunk offset %#x (data size %zu).\n", chunk_offset, data_size);
|
WARN("Invalid chunk offset %#x (data size %zu).\n", chunk_offset, data_size);
|
||||||
vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXBC_INVALID_CHUNK_OFFSET,
|
vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXBC_INVALID_CHUNK_OFFSET,
|
||||||
"DXBC chunk %u has invalid offset %#x (data size %#zx).", i, chunk_offset, data_size);
|
"DXBC chunk %u has invalid offset %#x (data size %#zx).", i, chunk_offset, data_size);
|
||||||
|
vkd3d_free(sections);
|
||||||
return VKD3D_ERROR_INVALID_ARGUMENT;
|
return VKD3D_ERROR_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1822,16 +1827,80 @@ static int for_each_dxbc_section(const struct vkd3d_shader_code *dxbc,
|
|||||||
vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXBC_INVALID_CHUNK_SIZE,
|
vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXBC_INVALID_CHUNK_SIZE,
|
||||||
"DXBC chunk %u has invalid size %#x (data size %#zx, chunk offset %#x).",
|
"DXBC chunk %u has invalid size %#x (data size %#zx, chunk offset %#x).",
|
||||||
i, chunk_offset, data_size, chunk_offset);
|
i, chunk_offset, data_size, chunk_offset);
|
||||||
|
vkd3d_free(sections);
|
||||||
return VKD3D_ERROR_INVALID_ARGUMENT;
|
return VKD3D_ERROR_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
section.tag = chunk_tag;
|
section = §ions[i];
|
||||||
section.data.code = chunk_ptr;
|
section->tag = chunk_tag;
|
||||||
section.data.size = chunk_size;
|
section->data.code = chunk_ptr;
|
||||||
if ((ret = section_handler(§ion, ctx)) < 0)
|
section->data.size = chunk_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
desc->tag = tag;
|
||||||
|
memcpy(desc->checksum, checksum, sizeof(checksum));
|
||||||
|
desc->version = version;
|
||||||
|
desc->size = total_size;
|
||||||
|
desc->section_count = chunk_count;
|
||||||
|
desc->sections = sections;
|
||||||
|
|
||||||
|
return VKD3D_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vkd3d_shader_free_dxbc(struct vkd3d_shader_dxbc_desc *dxbc)
|
||||||
|
{
|
||||||
|
TRACE("dxbc %p.\n", dxbc);
|
||||||
|
|
||||||
|
vkd3d_free(dxbc->sections);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int for_each_dxbc_section(const struct vkd3d_shader_code *dxbc,
|
||||||
|
struct vkd3d_shader_message_context *message_context, const char *source_name,
|
||||||
|
int (*section_handler)(const struct vkd3d_shader_dxbc_section_desc *section, void *ctx), void *ctx)
|
||||||
|
{
|
||||||
|
struct vkd3d_shader_dxbc_desc desc;
|
||||||
|
unsigned int i;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if ((ret = parse_dxbc(dxbc, message_context, source_name, &desc)) < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
for (i = 0; i < desc.section_count; ++i)
|
||||||
|
{
|
||||||
|
if ((ret = section_handler(&desc.sections[i], ctx)) < 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vkd3d_shader_free_dxbc(&desc);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vkd3d_shader_parse_dxbc(const struct vkd3d_shader_code *dxbc,
|
||||||
|
uint32_t flags, struct vkd3d_shader_dxbc_desc *desc, char **messages)
|
||||||
|
{
|
||||||
|
struct vkd3d_shader_message_context message_context;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
TRACE("dxbc {%p, %zu}, flags %#x, desc %p, messages %p.\n", dxbc->code, dxbc->size, flags, desc, messages);
|
||||||
|
|
||||||
|
if (messages)
|
||||||
|
*messages = NULL;
|
||||||
|
vkd3d_shader_message_context_init(&message_context, VKD3D_SHADER_LOG_INFO);
|
||||||
|
|
||||||
|
ret = parse_dxbc(dxbc, &message_context, NULL, desc);
|
||||||
|
|
||||||
|
vkd3d_shader_message_context_trace_messages(&message_context);
|
||||||
|
if (!vkd3d_shader_message_context_copy_messages(&message_context, messages) && ret >= 0)
|
||||||
|
{
|
||||||
|
vkd3d_shader_free_dxbc(desc);
|
||||||
|
ret = VKD3D_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
vkd3d_shader_message_context_cleanup(&message_context);
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
memset(desc, 0, sizeof(*desc));
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ global:
|
|||||||
vkd3d_shader_compile;
|
vkd3d_shader_compile;
|
||||||
vkd3d_shader_convert_root_signature;
|
vkd3d_shader_convert_root_signature;
|
||||||
vkd3d_shader_find_signature_element;
|
vkd3d_shader_find_signature_element;
|
||||||
|
vkd3d_shader_free_dxbc;
|
||||||
vkd3d_shader_free_messages;
|
vkd3d_shader_free_messages;
|
||||||
vkd3d_shader_free_root_signature;
|
vkd3d_shader_free_root_signature;
|
||||||
vkd3d_shader_free_scan_descriptor_info;
|
vkd3d_shader_free_scan_descriptor_info;
|
||||||
@ -12,6 +13,7 @@ global:
|
|||||||
vkd3d_shader_get_supported_source_types;
|
vkd3d_shader_get_supported_source_types;
|
||||||
vkd3d_shader_get_supported_target_types;
|
vkd3d_shader_get_supported_target_types;
|
||||||
vkd3d_shader_get_version;
|
vkd3d_shader_get_version;
|
||||||
|
vkd3d_shader_parse_dxbc;
|
||||||
vkd3d_shader_parse_input_signature;
|
vkd3d_shader_parse_input_signature;
|
||||||
vkd3d_shader_parse_root_signature;
|
vkd3d_shader_parse_root_signature;
|
||||||
vkd3d_shader_preprocess;
|
vkd3d_shader_preprocess;
|
||||||
|
@ -68,6 +68,7 @@ enum vkd3d_shader_error
|
|||||||
VKD3D_SHADER_ERROR_DXBC_INVALID_VERSION = 4,
|
VKD3D_SHADER_ERROR_DXBC_INVALID_VERSION = 4,
|
||||||
VKD3D_SHADER_ERROR_DXBC_INVALID_CHUNK_OFFSET = 5,
|
VKD3D_SHADER_ERROR_DXBC_INVALID_CHUNK_OFFSET = 5,
|
||||||
VKD3D_SHADER_ERROR_DXBC_INVALID_CHUNK_SIZE = 6,
|
VKD3D_SHADER_ERROR_DXBC_INVALID_CHUNK_SIZE = 6,
|
||||||
|
VKD3D_SHADER_ERROR_DXBC_OUT_OF_MEMORY = 7,
|
||||||
|
|
||||||
VKD3D_SHADER_ERROR_TPF_MISMATCHED_CF = 1000,
|
VKD3D_SHADER_ERROR_TPF_MISMATCHED_CF = 1000,
|
||||||
VKD3D_SHADER_ERROR_TPF_INVALID_REGISTER_RANGE = 1001,
|
VKD3D_SHADER_ERROR_TPF_INVALID_REGISTER_RANGE = 1001,
|
||||||
@ -1308,12 +1309,6 @@ static inline void *vkd3d_find_struct_(const struct vkd3d_struct *chain,
|
|||||||
#define TAG_SHEX VKD3D_MAKE_TAG('S', 'H', 'E', 'X')
|
#define TAG_SHEX VKD3D_MAKE_TAG('S', 'H', 'E', 'X')
|
||||||
#define TAG_TEXT VKD3D_MAKE_TAG('T', 'E', 'X', 'T')
|
#define TAG_TEXT VKD3D_MAKE_TAG('T', 'E', 'X', 'T')
|
||||||
|
|
||||||
struct vkd3d_shader_dxbc_section_desc
|
|
||||||
{
|
|
||||||
uint32_t tag;
|
|
||||||
struct vkd3d_shader_code data;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define DXBC_MAX_SECTION_COUNT 5
|
#define DXBC_MAX_SECTION_COUNT 5
|
||||||
|
|
||||||
struct dxbc_writer
|
struct dxbc_writer
|
||||||
|
Loading…
Reference in New Issue
Block a user