mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2024-11-21 16:46:41 -08:00
vkd3d-shader/dxbc: Introduce API for serialising DXBC blobs.
This commit is contained in:
parent
c87492ed21
commit
b1e13d6e33
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
@ -1946,6 +1946,34 @@ VKD3D_SHADER_API void vkd3d_shader_free_dxbc(struct vkd3d_shader_dxbc_desc *dxbc
|
||||
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);
|
||||
|
||||
/**
|
||||
* Serialise a DXBC description into a blob stored in a vkd3d_shader_code
|
||||
* structure.
|
||||
*
|
||||
* \param section_count The number of DXBC sections to serialise.
|
||||
*
|
||||
* \param sections An array of vkd3d_shader_dxbc_section_desc structures
|
||||
* to serialise.
|
||||
*
|
||||
* \param dxbc A pointer to a vkd3d_shader_code structure in which the
|
||||
* serialised blob will be stored.
|
||||
* \n
|
||||
* The output blob is allocated by vkd3d-shader and should be freed with
|
||||
* vkd3d_shader_free_shader_code() when no longer needed.
|
||||
*
|
||||
* \param messages Optional output location for error or informational messages
|
||||
* produced by the serialiser.
|
||||
* \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_serialize_dxbc(size_t section_count,
|
||||
const struct vkd3d_shader_dxbc_section_desc *sections, struct vkd3d_shader_code *dxbc, char **messages);
|
||||
|
||||
#endif /* VKD3D_SHADER_NO_PROTOTYPES */
|
||||
|
||||
/** Type of vkd3d_shader_get_version(). */
|
||||
@ -2007,6 +2035,9 @@ 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);
|
||||
/** Type of vkd3d_shader_serialize_dxbc(). \since 1.7 */
|
||||
typedef int (*PFN_vkd3d_shader_serialize_dxbc)(size_t section_count,
|
||||
const struct vkd3d_shader_dxbc_section_desc *sections, struct vkd3d_shader_code *dxbc, char **messages);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -43,12 +43,18 @@ void dxbc_writer_add_section(struct dxbc_writer *dxbc, uint32_t tag, const void
|
||||
section->data.size = size;
|
||||
}
|
||||
|
||||
int dxbc_writer_write(struct dxbc_writer *dxbc, struct vkd3d_shader_code *out)
|
||||
int vkd3d_shader_serialize_dxbc(size_t section_count, const struct vkd3d_shader_dxbc_section_desc *sections,
|
||||
struct vkd3d_shader_code *dxbc, char **messages)
|
||||
{
|
||||
size_t size_position, offsets_position, checksum_position, i;
|
||||
struct vkd3d_bytecode_buffer buffer = {0};
|
||||
uint32_t checksum[4];
|
||||
|
||||
TRACE("section_count %zu, sections %p, dxbc %p, messages %p.\n", section_count, sections, dxbc, messages);
|
||||
|
||||
if (messages)
|
||||
*messages = NULL;
|
||||
|
||||
put_u32(&buffer, TAG_DXBC);
|
||||
|
||||
checksum_position = bytecode_get_size(&buffer);
|
||||
@ -57,18 +63,18 @@ int dxbc_writer_write(struct dxbc_writer *dxbc, struct vkd3d_shader_code *out)
|
||||
|
||||
put_u32(&buffer, 1); /* version */
|
||||
size_position = put_u32(&buffer, 0);
|
||||
put_u32(&buffer, dxbc->section_count);
|
||||
put_u32(&buffer, section_count);
|
||||
|
||||
offsets_position = bytecode_get_size(&buffer);
|
||||
for (i = 0; i < dxbc->section_count; ++i)
|
||||
for (i = 0; i < section_count; ++i)
|
||||
put_u32(&buffer, 0);
|
||||
|
||||
for (i = 0; i < dxbc->section_count; ++i)
|
||||
for (i = 0; i < section_count; ++i)
|
||||
{
|
||||
set_u32(&buffer, offsets_position + i * sizeof(uint32_t), bytecode_get_size(&buffer));
|
||||
put_u32(&buffer, dxbc->sections[i].tag);
|
||||
put_u32(&buffer, dxbc->sections[i].data.size);
|
||||
bytecode_put_bytes(&buffer, dxbc->sections[i].data.code, dxbc->sections[i].data.size);
|
||||
put_u32(&buffer, sections[i].tag);
|
||||
put_u32(&buffer, sections[i].data.size);
|
||||
bytecode_put_bytes(&buffer, sections[i].data.code, sections[i].data.size);
|
||||
}
|
||||
set_u32(&buffer, size_position, bytecode_get_size(&buffer));
|
||||
|
||||
@ -78,12 +84,17 @@ int dxbc_writer_write(struct dxbc_writer *dxbc, struct vkd3d_shader_code *out)
|
||||
|
||||
if (!buffer.status)
|
||||
{
|
||||
out->code = buffer.data;
|
||||
out->size = buffer.size;
|
||||
dxbc->code = buffer.data;
|
||||
dxbc->size = buffer.size;
|
||||
}
|
||||
return buffer.status;
|
||||
}
|
||||
|
||||
int dxbc_writer_write(struct dxbc_writer *dxbc, struct vkd3d_shader_code *out)
|
||||
{
|
||||
return vkd3d_shader_serialize_dxbc(dxbc->section_count, dxbc->sections, out, NULL);
|
||||
}
|
||||
|
||||
struct vkd3d_shader_src_param_entry
|
||||
{
|
||||
struct list entry;
|
||||
|
@ -18,6 +18,7 @@ global:
|
||||
vkd3d_shader_parse_root_signature;
|
||||
vkd3d_shader_preprocess;
|
||||
vkd3d_shader_scan;
|
||||
vkd3d_shader_serialize_dxbc;
|
||||
vkd3d_shader_serialize_root_signature;
|
||||
vkd3d_shader_set_log_callback;
|
||||
|
||||
|
@ -318,6 +318,89 @@ static void test_d3dbc(void)
|
||||
ok(rc == VKD3D_ERROR_INVALID_SHADER, "Got unexpected error code %d.\n", rc);
|
||||
}
|
||||
|
||||
static void test_dxbc(void)
|
||||
{
|
||||
PFN_vkd3d_shader_serialize_dxbc pfn_vkd3d_shader_serialize_dxbc;
|
||||
PFN_vkd3d_shader_parse_dxbc pfn_vkd3d_shader_parse_dxbc;
|
||||
PFN_vkd3d_shader_free_dxbc pfn_vkd3d_shader_free_dxbc;
|
||||
struct vkd3d_shader_dxbc_desc dxbc_desc;
|
||||
const uint8_t *dxbc_start, *dxbc_end;
|
||||
struct vkd3d_shader_code dxbc;
|
||||
size_t expected_size;
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
static const uint32_t section_0[] =
|
||||
{
|
||||
0x00000000, 0x00000001, 0x00000001, 0x00000002,
|
||||
0x00000003, 0x00000005, 0x00000008, 0x0000000d,
|
||||
0x00000015, 0x00000022, 0x00000037, 0x00000059,
|
||||
0x00000090, 0x000000e9, 0x00000179, 0x00000262,
|
||||
};
|
||||
static const uint8_t section_1[] =
|
||||
{
|
||||
0x1, 0x4, 0x1, 0x5, 0x9, 0x2, 0x6, 0x5, 0x3, 0x5, 0x8, 0x9, 0x7, 0x9, 0x3, 0x2,
|
||||
0x3, 0x8, 0x4, 0x6, 0x2, 0x6, 0x4, 0x3, 0x3, 0x8, 0x3, 0x2, 0x7, 0x9, 0x5, 0x0,
|
||||
0x2, 0x8, 0x8, 0x4, 0x1, 0x9, 0x7, 0x1, 0x6, 0x9, 0x3, 0x9, 0x9, 0x3, 0x7, 0x5,
|
||||
0x1, 0x0, 0x5, 0x8, 0x2, 0x0, 0x9, 0x7, 0x4, 0x9, 0x4, 0x4, 0x5, 0x9, 0x2, 0x3,
|
||||
};
|
||||
static const struct vkd3d_shader_dxbc_section_desc sections[] =
|
||||
{
|
||||
{.tag = 0x00424946, .data = {.code = section_0, .size = sizeof(section_0)}},
|
||||
{.tag = 0x49504950, .data = {.code = section_1, .size = sizeof(section_1)}},
|
||||
};
|
||||
static const uint32_t checksum[] = {0x7cfc687d, 0x7e8f4cff, 0x72a4739a, 0xd75c3703};
|
||||
|
||||
pfn_vkd3d_shader_serialize_dxbc = vkd3d_shader_serialize_dxbc;
|
||||
pfn_vkd3d_shader_parse_dxbc = vkd3d_shader_parse_dxbc;
|
||||
pfn_vkd3d_shader_free_dxbc = vkd3d_shader_free_dxbc;
|
||||
|
||||
/* 8 * u32 for the DXBC header */
|
||||
expected_size = 8 * sizeof(uint32_t);
|
||||
for (i = 0; i < ARRAY_SIZE(sections); ++i)
|
||||
{
|
||||
/* 1 u32 for the section offset + 2 u32 for the section header. */
|
||||
expected_size += 3 * sizeof(uint32_t) + sections[i].data.size;
|
||||
}
|
||||
|
||||
ret = pfn_vkd3d_shader_serialize_dxbc(ARRAY_SIZE(sections), sections, &dxbc, NULL);
|
||||
ok(ret == VKD3D_OK, "Got unexpected ret %d.\n", ret);
|
||||
ok(dxbc.size == expected_size, "Got unexpected size %zu, expected %zu.\n", dxbc_desc.size, expected_size);
|
||||
|
||||
ret = pfn_vkd3d_shader_parse_dxbc(&dxbc, 0, &dxbc_desc, NULL);
|
||||
ok(ret == VKD3D_OK, "Got unexpected ret %d.\n", ret);
|
||||
ok(dxbc_desc.tag == 0x43425844, "Got unexpected tag 0x%08x.\n", dxbc_desc.tag);
|
||||
ok(!memcmp(dxbc_desc.checksum, checksum, sizeof(dxbc_desc.checksum)),
|
||||
"Got unexpected checksum 0x%08x 0x%08x 0x%08x 0x%08x.\n",
|
||||
dxbc_desc.checksum[0], dxbc_desc.checksum[1], dxbc_desc.checksum[2], dxbc_desc.checksum[3]);
|
||||
ok(dxbc_desc.version == 1, "Got unexpected version %#x.\n", dxbc_desc.version);
|
||||
ok(dxbc_desc.size == expected_size, "Got unexpected size %zu, expected %zu.\n", dxbc_desc.size, expected_size);
|
||||
ok(dxbc_desc.section_count == ARRAY_SIZE(sections), "Got unexpected section count %zu, expected %zu.\n",
|
||||
dxbc_desc.section_count, ARRAY_SIZE(sections));
|
||||
|
||||
dxbc_start = dxbc.code;
|
||||
dxbc_end = dxbc_start + dxbc.size;
|
||||
for (i = 0; i < dxbc_desc.section_count; ++i)
|
||||
{
|
||||
const struct vkd3d_shader_dxbc_section_desc *section = &dxbc_desc.sections[i];
|
||||
const uint8_t *data = section->data.code;
|
||||
|
||||
vkd3d_test_set_context("Section %u", i);
|
||||
ok(section->tag == sections[i].tag, "Got unexpected tag 0x%08x, expected 0x%08x.\n",
|
||||
section->tag, sections[i].tag);
|
||||
ok(section->data.size == sections[i].data.size, "Got unexpected size %zu, expected %zu.\n",
|
||||
section->data.size, sections[i].data.size);
|
||||
ok(!memcmp(data, sections[i].data.code, section->data.size), "Got unexpected section data.\n");
|
||||
ok(data > dxbc_start && data <= dxbc_end - section->data.size,
|
||||
"Data {%p, %zu} is not contained within blob {%p, %zu}.\n",
|
||||
data, section->data.size, dxbc_start, dxbc_end - dxbc_start);
|
||||
}
|
||||
vkd3d_test_set_context(NULL);
|
||||
|
||||
pfn_vkd3d_shader_free_dxbc(&dxbc_desc);
|
||||
vkd3d_shader_free_shader_code(&dxbc);
|
||||
}
|
||||
|
||||
START_TEST(vkd3d_shader_api)
|
||||
{
|
||||
setlocale(LC_ALL, "");
|
||||
@ -326,4 +409,5 @@ START_TEST(vkd3d_shader_api)
|
||||
run_test(test_vkd3d_shader_pfns);
|
||||
run_test(test_version);
|
||||
run_test(test_d3dbc);
|
||||
run_test(test_dxbc);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user