wined3d: Move shader parsing to shader_set_function().

The idea is that we will have wined3d_shader objects that represent shaders
not yet in d3d form (specifically, in HLSL form or containing only an FFP
settings struct.) Hence we need to make it possible to delay d3d shader parsing,
but still keep the rest of shader_init().
This commit is contained in:
Elizabeth Figura 2024-09-19 18:19:05 -05:00 committed by Alexandre Julliard
parent d2bed27bfe
commit 2eb7397e23
Notes: Alexandre Julliard 2024-11-19 23:22:30 +01:00
Approved-by: Jan Sikorski (@jsikorski)
Approved-by: Alexandre Julliard (@julliard)
Merge-Request: https://gitlab.winehq.org/wine/wine/merge_requests/6813

View file

@ -2316,7 +2316,7 @@ static void shader_trace(const void *code, size_t size, enum vkd3d_shader_source
vkd3d_shader_free_shader_code(&d3d_asm); vkd3d_shader_free_shader_code(&d3d_asm);
} }
static HRESULT shader_set_function(struct wined3d_shader *shader, static HRESULT shader_set_function(struct wined3d_shader *shader, const struct wined3d_shader_desc *desc,
enum wined3d_shader_type type, const struct wined3d_stream_output_desc *so_desc, unsigned int float_const_count) enum wined3d_shader_type type, const struct wined3d_stream_output_desc *so_desc, unsigned int float_const_count)
{ {
const struct wined3d_d3d_info *d3d_info = &shader->device->adapter->d3d_info; const struct wined3d_d3d_info *d3d_info = &shader->device->adapter->d3d_info;
@ -2327,8 +2327,88 @@ static HRESULT shader_set_function(struct wined3d_shader *shader,
unsigned int backend_version; unsigned int backend_version;
HRESULT hr; HRESULT hr;
TRACE("shader %p, type %s, float_const_count %u.\n", TRACE("shader %p, byte_code %p, size %#Ix, type %s, float_const_count %u.\n",
shader, debug_shader_type(type), float_const_count); shader, desc->byte_code, desc->byte_code_size, debug_shader_type(type), float_const_count);
if (!desc->byte_code)
return WINED3DERR_INVALIDCALL;
if (desc->byte_code_size == ~(size_t)0)
{
struct wined3d_shader_version shader_version;
const struct wined3d_shader_frontend *fe;
struct wined3d_shader_instruction ins;
const DWORD *ptr;
void *fe_data;
shader->source_type = VKD3D_SHADER_SOURCE_D3D_BYTECODE;
if (!(shader->frontend = shader_select_frontend(shader->source_type)))
{
FIXME("Unable to find frontend for shader.\n");
shader_cleanup(shader);
return WINED3DERR_INVALIDCALL;
}
fe = shader->frontend;
if (!(fe_data = fe->shader_init(desc->byte_code, desc->byte_code_size, &shader->output_signature)))
{
WARN("Failed to initialise frontend data.\n");
shader_cleanup(shader);
return WINED3DERR_INVALIDCALL;
}
fe->shader_read_header(fe_data, &ptr, &shader_version);
while (!fe->shader_is_end(fe_data, &ptr))
fe->shader_read_instruction(fe_data, &ptr, &ins);
fe->shader_free(fe_data);
shader->byte_code_size = (ptr - desc->byte_code) * sizeof(*ptr);
if (!(shader->byte_code = malloc(shader->byte_code_size)))
{
shader_cleanup(shader);
return E_OUTOFMEMORY;
}
memcpy(shader->byte_code, desc->byte_code, shader->byte_code_size);
shader->function = shader->byte_code;
shader->functionLength = shader->byte_code_size;
}
else
{
unsigned int max_version;
if (!(shader->byte_code = malloc(desc->byte_code_size)))
{
shader_cleanup(shader);
return E_OUTOFMEMORY;
}
memcpy(shader->byte_code, desc->byte_code, desc->byte_code_size);
shader->byte_code_size = desc->byte_code_size;
max_version = shader_max_version_from_feature_level(shader->device->cs->c.state->feature_level);
if (FAILED(hr = wined3d_shader_extract_from_dxbc(shader, max_version, &shader->source_type)))
{
shader_cleanup(shader);
return hr;
}
if (!(shader->frontend = shader_select_frontend(shader->source_type)))
{
FIXME("Unable to find frontend for shader.\n");
shader_cleanup(shader);
return WINED3DERR_INVALIDCALL;
}
}
if (TRACE_ON(d3d_shader))
{
if (shader->source_type == VKD3D_SHADER_SOURCE_D3D_BYTECODE)
shader_trace(shader->function, shader->functionLength, shader->source_type);
else
shader_trace(shader->byte_code, shader->byte_code_size, shader->source_type);
}
if (type == WINED3D_SHADER_TYPE_GEOMETRY) if (type == WINED3D_SHADER_TYPE_GEOMETRY)
{ {
@ -2661,16 +2741,9 @@ bool vshader_get_input(const struct wined3d_shader *shader,
return false; return false;
} }
static HRESULT shader_init(struct wined3d_shader *shader, struct wined3d_device *device, static void shader_init(struct wined3d_shader *shader, struct wined3d_device *device,
const struct wined3d_shader_desc *desc, void *parent, const struct wined3d_parent_ops *parent_ops) void *parent, const struct wined3d_parent_ops *parent_ops)
{ {
HRESULT hr;
TRACE("byte_code %p, byte_code_size %#lx.\n", desc->byte_code, (long)desc->byte_code_size);
if (!desc->byte_code)
return WINED3DERR_INVALIDCALL;
shader->ref = 1; shader->ref = 1;
shader->device = device; shader->device = device;
shader->parent = parent; shader->parent = parent;
@ -2683,87 +2756,6 @@ static HRESULT shader_init(struct wined3d_shader *shader, struct wined3d_device
shader->lconst_inf_or_nan = FALSE; shader->lconst_inf_or_nan = FALSE;
list_init(&shader->reg_maps.indexable_temps); list_init(&shader->reg_maps.indexable_temps);
list_init(&shader->shader_list_entry); list_init(&shader->shader_list_entry);
if (desc->byte_code_size == ~(size_t)0)
{
struct wined3d_shader_version shader_version;
const struct wined3d_shader_frontend *fe;
struct wined3d_shader_instruction ins;
const DWORD *ptr;
void *fe_data;
shader->source_type = VKD3D_SHADER_SOURCE_D3D_BYTECODE;
if (!(shader->frontend = shader_select_frontend(shader->source_type)))
{
FIXME("Unable to find frontend for shader.\n");
hr = WINED3DERR_INVALIDCALL;
goto fail;
}
fe = shader->frontend;
if (!(fe_data = fe->shader_init(desc->byte_code, desc->byte_code_size, &shader->output_signature)))
{
WARN("Failed to initialise frontend data.\n");
hr = WINED3DERR_INVALIDCALL;
goto fail;
}
fe->shader_read_header(fe_data, &ptr, &shader_version);
while (!fe->shader_is_end(fe_data, &ptr))
fe->shader_read_instruction(fe_data, &ptr, &ins);
fe->shader_free(fe_data);
shader->byte_code_size = (ptr - desc->byte_code) * sizeof(*ptr);
if (!(shader->byte_code = malloc(shader->byte_code_size)))
{
hr = E_OUTOFMEMORY;
goto fail;
}
memcpy(shader->byte_code, desc->byte_code, shader->byte_code_size);
shader->function = shader->byte_code;
shader->functionLength = shader->byte_code_size;
}
else
{
unsigned int max_version;
if (!(shader->byte_code = malloc(desc->byte_code_size)))
{
hr = E_OUTOFMEMORY;
goto fail;
}
memcpy(shader->byte_code, desc->byte_code, desc->byte_code_size);
shader->byte_code_size = desc->byte_code_size;
max_version = shader_max_version_from_feature_level(device->cs->c.state->feature_level);
if (FAILED(hr = wined3d_shader_extract_from_dxbc(shader, max_version, &shader->source_type)))
goto fail;
if (!(shader->frontend = shader_select_frontend(shader->source_type)))
{
FIXME("Unable to find frontend for shader.\n");
hr = WINED3DERR_INVALIDCALL;
goto fail;
}
}
if (TRACE_ON(d3d_shader))
{
if (shader->source_type == VKD3D_SHADER_SOURCE_D3D_BYTECODE)
shader_trace(shader->function, shader->functionLength, shader->source_type);
else
shader_trace(shader->byte_code, shader->byte_code_size, shader->source_type);
}
return WINED3D_OK;
fail:
shader_cleanup(shader);
return hr;
} }
static HRESULT vertex_shader_init(struct wined3d_shader *shader, struct wined3d_device *device, static HRESULT vertex_shader_init(struct wined3d_shader *shader, struct wined3d_device *device,
@ -2771,10 +2763,9 @@ static HRESULT vertex_shader_init(struct wined3d_shader *shader, struct wined3d_
{ {
HRESULT hr; HRESULT hr;
if (FAILED(hr = shader_init(shader, device, desc, parent, parent_ops))) shader_init(shader, device, parent, parent_ops);
return hr;
if (FAILED(hr = shader_set_function(shader, if (FAILED(hr = shader_set_function(shader, desc,
WINED3D_SHADER_TYPE_VERTEX, NULL, device->adapter->d3d_info.limits.vs_uniform_count))) WINED3D_SHADER_TYPE_VERTEX, NULL, device->adapter->d3d_info.limits.vs_uniform_count)))
{ {
shader_cleanup(shader); shader_cleanup(shader);
@ -2790,10 +2781,9 @@ static HRESULT geometry_shader_init(struct wined3d_shader *shader, struct wined3
{ {
HRESULT hr; HRESULT hr;
if (FAILED(hr = shader_init(shader, device, desc, parent, parent_ops))) shader_init(shader, device, parent, parent_ops);
return hr;
if (FAILED(hr = shader_set_function(shader, WINED3D_SHADER_TYPE_GEOMETRY, so_desc, 0))) if (FAILED(hr = shader_set_function(shader, desc, WINED3D_SHADER_TYPE_GEOMETRY, so_desc, 0)))
goto fail; goto fail;
return WINED3D_OK; return WINED3D_OK;
@ -3120,10 +3110,9 @@ static HRESULT pixel_shader_init(struct wined3d_shader *shader, struct wined3d_d
const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info; const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info;
HRESULT hr; HRESULT hr;
if (FAILED(hr = shader_init(shader, device, desc, parent, parent_ops))) shader_init(shader, device, parent, parent_ops);
return hr;
if (FAILED(hr = shader_set_function(shader, if (FAILED(hr = shader_set_function(shader, desc,
WINED3D_SHADER_TYPE_PIXEL, NULL, d3d_info->limits.ps_uniform_count))) WINED3D_SHADER_TYPE_PIXEL, NULL, d3d_info->limits.ps_uniform_count)))
{ {
shader_cleanup(shader); shader_cleanup(shader);
@ -3168,14 +3157,9 @@ HRESULT CDECL wined3d_shader_create_cs(struct wined3d_device *device, const stru
if (!(object = calloc(1, sizeof(*object)))) if (!(object = calloc(1, sizeof(*object))))
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
if (FAILED(hr = shader_init(object, device, desc, parent, parent_ops))) shader_init(object, device, parent, parent_ops);
{
WARN("Failed to initialize compute shader, hr %#lx.\n", hr);
free(object);
return hr;
}
if (FAILED(hr = shader_set_function(object, WINED3D_SHADER_TYPE_COMPUTE, NULL, 0))) if (FAILED(hr = shader_set_function(object, desc, WINED3D_SHADER_TYPE_COMPUTE, NULL, 0)))
{ {
shader_cleanup(object); shader_cleanup(object);
free(object); free(object);
@ -3202,14 +3186,9 @@ HRESULT CDECL wined3d_shader_create_ds(struct wined3d_device *device, const stru
if (!(object = calloc(1, sizeof(*object)))) if (!(object = calloc(1, sizeof(*object))))
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
if (FAILED(hr = shader_init(object, device, desc, parent, parent_ops))) shader_init(object, device, parent, parent_ops);
{
WARN("Failed to initialize domain shader, hr %#lx.\n", hr);
free(object);
return hr;
}
if (FAILED(hr = shader_set_function(object, WINED3D_SHADER_TYPE_DOMAIN, NULL, 0))) if (FAILED(hr = shader_set_function(object, desc, WINED3D_SHADER_TYPE_DOMAIN, NULL, 0)))
{ {
shader_cleanup(object); shader_cleanup(object);
free(object); free(object);
@ -3264,14 +3243,9 @@ HRESULT CDECL wined3d_shader_create_hs(struct wined3d_device *device, const stru
if (!(object = calloc(1, sizeof(*object)))) if (!(object = calloc(1, sizeof(*object))))
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
if (FAILED(hr = shader_init(object, device, desc, parent, parent_ops))) shader_init(object, device, parent, parent_ops);
{
WARN("Failed to initialize hull shader, hr %#lx.\n", hr);
free(object);
return hr;
}
if (FAILED(hr = shader_set_function(object, WINED3D_SHADER_TYPE_HULL, NULL, 0))) if (FAILED(hr = shader_set_function(object, desc, WINED3D_SHADER_TYPE_HULL, NULL, 0)))
{ {
shader_cleanup(object); shader_cleanup(object);
free(object); free(object);