Commit 72ea1419 authored by Józef Kucia's avatar Józef Kucia Committed by Alexandre Julliard

wined3d: Accept full DXBC.

In order to make it easier to add shader backends based on external libraries, e.g. vkd3d-shader. Additionally, allows us to easily parse additional DXBC chunks in wined3d. Signed-off-by: 's avatarJózef Kucia <jkucia@codeweavers.com> Signed-off-by: 's avatarHenri Verbeet <hverbeet@codeweavers.com> Signed-off-by: 's avatarAlexandre Julliard <julliard@winehq.org>
parent c4c53538
...@@ -3153,7 +3153,7 @@ static void shader_cleanup(struct wined3d_shader *shader) ...@@ -3153,7 +3153,7 @@ static void shader_cleanup(struct wined3d_shader *shader)
heap_free(shader->signature_strings); heap_free(shader->signature_strings);
shader->device->shader_backend->shader_destroy(shader); shader->device->shader_backend->shader_destroy(shader);
shader_cleanup_reg_maps(&shader->reg_maps); shader_cleanup_reg_maps(&shader->reg_maps);
heap_free(shader->function); heap_free(shader->byte_code);
shader_delete_constant_list(&shader->constantsF); shader_delete_constant_list(&shader->constantsF);
shader_delete_constant_list(&shader->constantsB); shader_delete_constant_list(&shader->constantsB);
shader_delete_constant_list(&shader->constantsI); shader_delete_constant_list(&shader->constantsI);
...@@ -3461,11 +3461,11 @@ HRESULT CDECL wined3d_shader_get_byte_code(const struct wined3d_shader *shader, ...@@ -3461,11 +3461,11 @@ HRESULT CDECL wined3d_shader_get_byte_code(const struct wined3d_shader *shader,
if (!byte_code) if (!byte_code)
{ {
*byte_code_size = shader->functionLength; *byte_code_size = shader->byte_code_size;
return WINED3D_OK; return WINED3D_OK;
} }
if (*byte_code_size < shader->functionLength) if (*byte_code_size < shader->byte_code_size)
{ {
/* MSDN claims (for d3d8 at least) that if *byte_code_size is smaller /* MSDN claims (for d3d8 at least) that if *byte_code_size is smaller
* than the required size we should write the required size and * than the required size we should write the required size and
...@@ -3473,7 +3473,7 @@ HRESULT CDECL wined3d_shader_get_byte_code(const struct wined3d_shader *shader, ...@@ -3473,7 +3473,7 @@ HRESULT CDECL wined3d_shader_get_byte_code(const struct wined3d_shader *shader,
return WINED3DERR_INVALIDCALL; return WINED3DERR_INVALIDCALL;
} }
memcpy(byte_code, shader->function, shader->functionLength); memcpy(byte_code, shader->byte_code, shader->byte_code_size);
return WINED3D_OK; return WINED3D_OK;
} }
...@@ -3693,7 +3693,8 @@ static HRESULT shader_copy_signatures_from_shader_desc(struct wined3d_shader *sh ...@@ -3693,7 +3693,8 @@ static HRESULT shader_copy_signatures_from_shader_desc(struct wined3d_shader *sh
static HRESULT shader_init(struct wined3d_shader *shader, struct wined3d_device *device, static HRESULT 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) const struct wined3d_shader_desc *desc, void *parent, const struct wined3d_parent_ops *parent_ops)
{ {
size_t byte_code_size; enum wined3d_shader_byte_code_format format;
unsigned int max_version;
HRESULT hr; HRESULT hr;
TRACE("byte_code %p, byte_code_size %#lx, format %#x.\n", TRACE("byte_code %p, byte_code_size %#lx, format %#x.\n",
...@@ -3702,20 +3703,11 @@ static HRESULT shader_init(struct wined3d_shader *shader, struct wined3d_device ...@@ -3702,20 +3703,11 @@ static HRESULT shader_init(struct wined3d_shader *shader, struct wined3d_device
if (!desc->byte_code) if (!desc->byte_code)
return WINED3DERR_INVALIDCALL; return WINED3DERR_INVALIDCALL;
if (!(shader->frontend = shader_select_frontend(desc->format)))
{
FIXME("Unable to find frontend for shader.\n");
return WINED3DERR_INVALIDCALL;
}
shader->ref = 1; shader->ref = 1;
shader->device = device; shader->device = device;
shader->parent = parent; shader->parent = parent;
shader->parent_ops = parent_ops; shader->parent_ops = parent_ops;
if (FAILED(hr = shader_copy_signatures_from_shader_desc(shader, desc)))
return hr;
list_init(&shader->linked_programs); list_init(&shader->linked_programs);
list_init(&shader->constantsF); list_init(&shader->constantsF);
list_init(&shader->constantsB); list_init(&shader->constantsB);
...@@ -3724,40 +3716,78 @@ static HRESULT shader_init(struct wined3d_shader *shader, struct wined3d_device ...@@ -3724,40 +3716,78 @@ static HRESULT shader_init(struct wined3d_shader *shader, struct wined3d_device
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);
byte_code_size = desc->byte_code_size; format = desc->format;
if (byte_code_size == ~(size_t)0) if (format == WINED3D_SHADER_BYTE_CODE_FORMAT_DXBC)
{ {
const struct wined3d_shader_frontend *fe = shader->frontend; if (!(shader->byte_code = heap_alloc(desc->byte_code_size)))
struct wined3d_shader_version shader_version;
struct wined3d_shader_instruction ins;
const DWORD *ptr;
void *fe_data;
if (!(fe_data = fe->shader_init(desc->byte_code, byte_code_size, &shader->output_signature)))
{ {
WARN("Failed to initialise frontend data.\n"); hr = E_OUTOFMEMORY;
shader_cleanup(shader); goto fail;
return WINED3DERR_INVALIDCALL;
} }
memcpy(shader->byte_code, desc->byte_code, desc->byte_code_size);
shader->byte_code_size = desc->byte_code_size;
fe->shader_read_header(fe_data, &ptr, &shader_version); max_version = shader_max_version_from_feature_level(device->feature_level);
while (!fe->shader_is_end(fe_data, &ptr)) if (FAILED(hr = shader_extract_from_dxbc(shader, max_version, &format)))
fe->shader_read_instruction(fe_data, &ptr, &ins); goto fail;
}
fe->shader_free(fe_data); else if (FAILED(hr = shader_copy_signatures_from_shader_desc(shader, desc)))
{
goto fail;
}
byte_code_size = (ptr - desc->byte_code) * sizeof(*ptr); if (!(shader->frontend = shader_select_frontend(format)))
{
FIXME("Unable to find frontend for shader.\n");
hr = WINED3DERR_INVALIDCALL;
goto fail;
} }
if (!(shader->function = heap_alloc(byte_code_size))) if (!shader->byte_code)
{ {
shader_cleanup(shader); size_t byte_code_size = desc->byte_code_size;
return E_OUTOFMEMORY;
if (byte_code_size == ~(size_t)0)
{
const struct wined3d_shader_frontend *fe = shader->frontend;
struct wined3d_shader_version shader_version;
struct wined3d_shader_instruction ins;
const DWORD *ptr;
void *fe_data;
if (!(fe_data = fe->shader_init(desc->byte_code, 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);
byte_code_size = (ptr - desc->byte_code) * sizeof(*ptr);
}
if (!(shader->byte_code = heap_alloc(byte_code_size)))
{
hr = E_OUTOFMEMORY;
goto fail;
}
memcpy(shader->byte_code, desc->byte_code, byte_code_size);
shader->byte_code_size = byte_code_size;
shader->function = shader->byte_code;
shader->functionLength = shader->byte_code_size;
} }
memcpy(shader->function, desc->byte_code, byte_code_size);
shader->functionLength = byte_code_size;
return hr; return hr;
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,
...@@ -3820,7 +3850,6 @@ static HRESULT geometry_shader_init_stream_output(struct wined3d_shader *shader, ...@@ -3820,7 +3850,6 @@ static HRESULT geometry_shader_init_stream_output(struct wined3d_shader *shader,
{ {
case WINED3D_SHADER_TYPE_VERTEX: case WINED3D_SHADER_TYPE_VERTEX:
case WINED3D_SHADER_TYPE_DOMAIN: case WINED3D_SHADER_TYPE_DOMAIN:
heap_free(shader->function);
shader->function = NULL; shader->function = NULL;
shader->functionLength = 0; shader->functionLength = 0;
break; break;
......
...@@ -1253,6 +1253,9 @@ struct wined3d_shader_frontend ...@@ -1253,6 +1253,9 @@ struct wined3d_shader_frontend
extern const struct wined3d_shader_frontend sm1_shader_frontend DECLSPEC_HIDDEN; extern const struct wined3d_shader_frontend sm1_shader_frontend DECLSPEC_HIDDEN;
extern const struct wined3d_shader_frontend sm4_shader_frontend DECLSPEC_HIDDEN; extern const struct wined3d_shader_frontend sm4_shader_frontend DECLSPEC_HIDDEN;
HRESULT shader_extract_from_dxbc(struct wined3d_shader *shader,
unsigned int max_shader_version, enum wined3d_shader_byte_code_format *format);
typedef void (*SHADER_HANDLER)(const struct wined3d_shader_instruction *); typedef void (*SHADER_HANDLER)(const struct wined3d_shader_instruction *);
#define WINED3D_SHADER_CAP_VS_CLIPPING 0x00000001 #define WINED3D_SHADER_CAP_VS_CLIPPING 0x00000001
...@@ -4080,8 +4083,10 @@ struct wined3d_shader ...@@ -4080,8 +4083,10 @@ struct wined3d_shader
{ {
LONG ref; LONG ref;
const struct wined3d_shader_limits *limits; const struct wined3d_shader_limits *limits;
DWORD *function; const DWORD *function;
UINT functionLength; unsigned int functionLength;
void *byte_code;
unsigned int byte_code_size;
BOOL load_local_constsF; BOOL load_local_constsF;
const struct wined3d_shader_frontend *frontend; const struct wined3d_shader_frontend *frontend;
void *frontend_data; void *frontend_data;
......
...@@ -858,6 +858,7 @@ enum wined3d_shader_byte_code_format ...@@ -858,6 +858,7 @@ enum wined3d_shader_byte_code_format
{ {
WINED3D_SHADER_BYTE_CODE_FORMAT_SM1 = 0, WINED3D_SHADER_BYTE_CODE_FORMAT_SM1 = 0,
WINED3D_SHADER_BYTE_CODE_FORMAT_SM4 = 1, WINED3D_SHADER_BYTE_CODE_FORMAT_SM4 = 1,
WINED3D_SHADER_BYTE_CODE_FORMAT_DXBC = 2,
}; };
enum wined3d_shader_type enum wined3d_shader_type
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment