vkd3d-shader/fx: Implement parsing shader objects.

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
This commit is contained in:
Nikolay Sivov 2024-10-28 00:38:28 +01:00 committed by Henri Verbeet
parent 96c13aeb97
commit 1a8e9ff94e
Notes: Henri Verbeet 2024-10-29 14:59:43 +01:00
Approved-by: Henri Verbeet (@hverbeet)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/1231

View File

@ -499,7 +499,15 @@ enum fx_4_type_constants
FX_4_NUMERIC_COLUMN_MAJOR_MASK = 0x4000, FX_4_NUMERIC_COLUMN_MAJOR_MASK = 0x4000,
/* Object types */ /* Object types */
FX_4_OBJECT_TYPE_STRING = 1, FX_4_OBJECT_TYPE_STRING = 0x1,
FX_4_OBJECT_TYPE_PIXEL_SHADER = 0x5,
FX_4_OBJECT_TYPE_VERTEX_SHADER = 0x6,
FX_4_OBJECT_TYPE_GEOMETRY_SHADER = 0x7,
FX_4_OBJECT_TYPE_GEOMETRY_SHADER_SO = 0x8,
FX_5_OBJECT_TYPE_GEOMETRY_SHADER = 0x1b,
FX_5_OBJECT_TYPE_COMPUTE_SHADER = 0x1c,
FX_5_OBJECT_TYPE_HULL_SHADER = 0x1d,
FX_5_OBJECT_TYPE_DOMAIN_SHADER = 0x1e,
/* Types */ /* Types */
FX_4_TYPE_CLASS_NUMERIC = 1, FX_4_TYPE_CLASS_NUMERIC = 1,
@ -807,11 +815,11 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co
} }
else if (element_type->class == HLSL_CLASS_PIXEL_SHADER) else if (element_type->class == HLSL_CLASS_PIXEL_SHADER)
{ {
put_u32_unaligned(buffer, 5); put_u32_unaligned(buffer, FX_4_OBJECT_TYPE_PIXEL_SHADER);
} }
else if (element_type->class == HLSL_CLASS_VERTEX_SHADER) else if (element_type->class == HLSL_CLASS_VERTEX_SHADER)
{ {
put_u32_unaligned(buffer, 6); put_u32_unaligned(buffer, FX_4_OBJECT_TYPE_VERTEX_SHADER);
} }
else if (element_type->class == HLSL_CLASS_RASTERIZER_STATE) else if (element_type->class == HLSL_CLASS_RASTERIZER_STATE)
{ {
@ -836,15 +844,15 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co
} }
else if (element_type->class == HLSL_CLASS_COMPUTE_SHADER) else if (element_type->class == HLSL_CLASS_COMPUTE_SHADER)
{ {
put_u32_unaligned(buffer, 28); put_u32_unaligned(buffer, FX_5_OBJECT_TYPE_COMPUTE_SHADER);
} }
else if (element_type->class == HLSL_CLASS_HULL_SHADER) else if (element_type->class == HLSL_CLASS_HULL_SHADER)
{ {
put_u32_unaligned(buffer, 29); put_u32_unaligned(buffer, FX_5_OBJECT_TYPE_HULL_SHADER);
} }
else if (element_type->class == HLSL_CLASS_DOMAIN_SHADER) else if (element_type->class == HLSL_CLASS_DOMAIN_SHADER)
{ {
put_u32_unaligned(buffer, 30); put_u32_unaligned(buffer, FX_5_OBJECT_TYPE_DOMAIN_SHADER);
} }
else else
{ {
@ -2919,19 +2927,28 @@ static int fx_2_parse(struct fx_parser *parser)
return -1; return -1;
} }
static void fx_parser_read_unstructured(struct fx_parser *parser, void *dst, uint32_t offset, size_t size) static const void *fx_parser_get_unstructured_ptr(struct fx_parser *parser, uint32_t offset, size_t size)
{ {
const uint8_t *ptr = parser->unstructured.ptr; const uint8_t *ptr = parser->unstructured.ptr;
memset(dst, 0, size);
if (offset >= parser->unstructured.size if (offset >= parser->unstructured.size
|| size > parser->unstructured.size - offset) || size > parser->unstructured.size - offset)
{ {
parser->failed = true; parser->failed = true;
return; return NULL;
} }
ptr += offset; return &ptr[offset];
}
static void fx_parser_read_unstructured(struct fx_parser *parser, void *dst, uint32_t offset, size_t size)
{
const uint8_t *ptr;
memset(dst, 0, size);
if (!(ptr = fx_parser_get_unstructured_ptr(parser, offset, size)))
return;
memcpy(dst, ptr, size); memcpy(dst, ptr, size);
} }
@ -3161,6 +3178,123 @@ static void fx_parse_buffers(struct fx_parser *parser)
} }
} }
static void fx_4_parse_shader_initializer(struct fx_parser *parser, unsigned int object_type)
{
struct vkd3d_shader_compile_info info = { 0 };
struct vkd3d_shader_code output;
uint32_t data_size, offset;
const void *data = NULL;
const char *p, *q, *end;
struct fx_5_shader
{
uint32_t offset;
uint32_t sodecl[4];
uint32_t sodecl_count;
uint32_t rast_stream;
uint32_t iface_bindings_count;
uint32_t iface_bindings;
} shader5;
struct fx_4_gs_so
{
uint32_t offset;
uint32_t sodecl;
} gs_so;
int ret;
static const struct vkd3d_shader_compile_option options[] =
{
{VKD3D_SHADER_COMPILE_OPTION_API_VERSION, VKD3D_SHADER_API_VERSION_1_13},
};
switch (object_type)
{
case FX_4_OBJECT_TYPE_PIXEL_SHADER:
case FX_4_OBJECT_TYPE_VERTEX_SHADER:
case FX_4_OBJECT_TYPE_GEOMETRY_SHADER:
offset = fx_parser_read_u32(parser);
break;
case FX_4_OBJECT_TYPE_GEOMETRY_SHADER_SO:
fx_parser_read_u32s(parser, &gs_so, sizeof(gs_so));
offset = gs_so.offset;
break;
case FX_5_OBJECT_TYPE_GEOMETRY_SHADER:
case FX_5_OBJECT_TYPE_COMPUTE_SHADER:
case FX_5_OBJECT_TYPE_HULL_SHADER:
case FX_5_OBJECT_TYPE_DOMAIN_SHADER:
fx_parser_read_u32s(parser, &shader5, sizeof(shader5));
offset = shader5.offset;
break;
default:
parser->failed = true;
return;
}
fx_parser_read_unstructured(parser, &data_size, offset, sizeof(data_size));
if (data_size)
data = fx_parser_get_unstructured_ptr(parser, offset + 4, data_size);
if (!data)
return;
info.type = VKD3D_SHADER_STRUCTURE_TYPE_COMPILE_INFO;
info.source.code = data;
info.source.size = data_size;
info.source_type = VKD3D_SHADER_SOURCE_DXBC_TPF;
info.target_type = VKD3D_SHADER_TARGET_D3D_ASM;
info.options = options;
info.option_count = ARRAY_SIZE(options);
info.log_level = VKD3D_SHADER_LOG_INFO;
if ((ret = vkd3d_shader_compile(&info, &output, NULL)) < 0)
{
fx_parser_error(parser, VKD3D_SHADER_ERROR_FX_INVALID_DATA,
"Failed to disassemble shader blob.\n");
return;
}
parse_fx_print_indent(parser);
vkd3d_string_buffer_printf(&parser->buffer, "asm {\n");
parse_fx_start_indent(parser);
end = (const char *)output.code + output.size;
for (p = output.code; p < end; p = q)
{
if (!(q = memchr(p, '\n', end - p)))
q = end;
else
++q;
parse_fx_print_indent(parser);
vkd3d_string_buffer_printf(&parser->buffer, "%.*s", (int)(q - p), p);
}
parse_fx_end_indent(parser);
parse_fx_print_indent(parser);
vkd3d_string_buffer_printf(&parser->buffer, "}");
if (object_type == FX_4_OBJECT_TYPE_GEOMETRY_SHADER && gs_so.sodecl)
{
vkd3d_string_buffer_printf(&parser->buffer, "\n/* Stream output declaration: \"%s\" */",
fx_4_get_string(parser, gs_so.sodecl));
}
else if (object_type == FX_5_OBJECT_TYPE_GEOMETRY_SHADER)
{
for (unsigned int i = 0; i < ARRAY_SIZE(shader5.sodecl); ++i)
{
if (shader5.sodecl[i])
vkd3d_string_buffer_printf(&parser->buffer, "\n/* Stream output %u declaration: \"%s\" */",
i, fx_4_get_string(parser, shader5.sodecl[i]));
}
if (shader5.sodecl_count)
vkd3d_string_buffer_printf(&parser->buffer, "\n/* Rasterized stream %u */", shader5.rast_stream);
}
vkd3d_shader_free_shader_code(&output);
}
static void fx_4_parse_objects(struct fx_parser *parser) static void fx_4_parse_objects(struct fx_parser *parser)
{ {
struct fx_4_object_variable struct fx_4_object_variable
@ -3199,6 +3333,18 @@ static void fx_4_parse_objects(struct fx_parser *parser)
value = fx_parser_read_u32(parser); value = fx_parser_read_u32(parser);
fx_4_parse_string_initializer(parser, value); fx_4_parse_string_initializer(parser, value);
break; break;
case FX_4_OBJECT_TYPE_PIXEL_SHADER:
case FX_4_OBJECT_TYPE_VERTEX_SHADER:
case FX_4_OBJECT_TYPE_GEOMETRY_SHADER:
case FX_4_OBJECT_TYPE_GEOMETRY_SHADER_SO:
case FX_5_OBJECT_TYPE_GEOMETRY_SHADER:
case FX_5_OBJECT_TYPE_COMPUTE_SHADER:
case FX_5_OBJECT_TYPE_HULL_SHADER:
case FX_5_OBJECT_TYPE_DOMAIN_SHADER:
parse_fx_start_indent(parser);
fx_4_parse_shader_initializer(parser, type.typeinfo);
parse_fx_end_indent(parser);
break;
default: default:
fx_parser_error(parser, VKD3D_SHADER_ERROR_FX_NOT_IMPLEMENTED, fx_parser_error(parser, VKD3D_SHADER_ERROR_FX_NOT_IMPLEMENTED,
"Parsing object type %u is not implemented.\n", type.typeinfo); "Parsing object type %u is not implemented.\n", type.typeinfo);
@ -3207,6 +3353,7 @@ static void fx_4_parse_objects(struct fx_parser *parser)
vkd3d_string_buffer_printf(&parser->buffer, ",\n"); vkd3d_string_buffer_printf(&parser->buffer, ",\n");
} }
vkd3d_string_buffer_printf(&parser->buffer, "};\n"); vkd3d_string_buffer_printf(&parser->buffer, "};\n");
fx_parse_fx_4_annotations(parser);
} }
} }