Signed-off-by: Józef Kucia <jkucia(a)codeweavers.com>
---
Mainly for vkd3d-shader backend.
---
dlls/d3d11/shader.c | 92 ++++------------------------------
dlls/wined3d/glsl_shader.c | 40 ++++++++-------
dlls/wined3d/shader.c | 57 ++++++++++++++++++++-
dlls/wined3d/wined3d_private.h | 1 +
include/wine/wined3d.h | 6 +--
5 files changed, 93 insertions(+), 103 deletions(-)
diff --git a/dlls/d3d11/shader.c b/dlls/d3d11/shader.c
index 455ff9f7c8c8..259ac331dbfe 100644
--- a/dlls/d3d11/shader.c
+++ b/dlls/d3d11/shader.c
@@ -24,21 +24,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(d3d11);
-static HRESULT osgn_handler(const char *data, DWORD data_size, DWORD tag, void *context)
-{
- struct wined3d_shader_signature *signature = context;
-
- if (tag != TAG_OSGN && tag != TAG_OSG5)
- return S_OK;
-
- if (signature->elements)
- {
- FIXME("Multiple input signatures.\n");
- shader_free_signature(signature);
- }
- return shader_parse_signature(tag, data, data_size, signature);
-}
-
static const char *shader_get_string(const char *data, size_t data_size, DWORD offset)
{
size_t len, max_len;
@@ -1073,18 +1058,14 @@ static const struct wined3d_parent_ops d3d_geometry_shader_wined3d_parent_ops =
d3d_geometry_shader_wined3d_object_destroyed,
};
-static HRESULT wined3d_so_elements_from_d3d11_so_entries(struct wined3d_stream_output_element *elements,
- const D3D11_SO_DECLARATION_ENTRY *entries, unsigned int entry_count,
- const unsigned int *buffer_strides, unsigned int buffer_stride_count,
- const struct wined3d_shader_signature *os, D3D_FEATURE_LEVEL feature_level)
+static HRESULT validate_stream_output_entries(const D3D11_SO_DECLARATION_ENTRY *entries, unsigned int entry_count,
+ const unsigned int *buffer_strides, unsigned int buffer_stride_count, D3D_FEATURE_LEVEL feature_level)
{
- unsigned int i, j, mask;
+ unsigned int i, j;
for (i = 0; i < entry_count; ++i)
{
- struct wined3d_stream_output_element *e = &elements[i];
const D3D11_SO_DECLARATION_ENTRY *f = &entries[i];
- struct wined3d_shader_signature_element *output;
TRACE("Stream: %u, semantic: %s, semantic idx: %u, start component: %u, "
"component count %u, output slot %u.\n",
@@ -1112,11 +1093,6 @@ static HRESULT wined3d_so_elements_from_d3d11_so_entries(struct wined3d_stream_o
return E_INVALIDARG;
}
- e->stream_idx = f->Stream;
- e->component_idx = f->StartComponent;
- e->component_count = f->ComponentCount;
- e->output_slot = f->OutputSlot;
-
if (!f->SemanticName)
{
if (f->SemanticIndex)
@@ -1129,10 +1105,8 @@ static HRESULT wined3d_so_elements_from_d3d11_so_entries(struct wined3d_stream_o
WARN("Invalid stream output gap %u-%u.\n", f->StartComponent, f->ComponentCount);
return E_INVALIDARG;
}
-
- e->register_idx = WINED3D_STREAM_OUTPUT_GAP;
}
- else if ((output = shader_find_signature_element(os, f->SemanticName, f->SemanticIndex, f->Stream)))
+ else
{
if (f->StartComponent > 3 || f->ComponentCount > 4 || !f->ComponentCount
|| f->StartComponent + f->ComponentCount > 4)
@@ -1140,29 +1114,6 @@ static HRESULT wined3d_so_elements_from_d3d11_so_entries(struct wined3d_stream_o
WARN("Invalid component range %u-%u.\n", f->StartComponent, f->ComponentCount);
return E_INVALIDARG;
}
-
- for (j = 0; j < 4; ++j)
- {
- if ((1u << j) & output->mask)
- break;
- }
- e->component_idx += j;
- mask = ((1u << e->component_count) - 1) << e->component_idx;
- if ((output->mask & 0xff & mask) != mask)
- {
- WARN("Invalid component range %u-%u (mask %#x), output mask %#x.\n",
- e->component_idx, e->component_count, mask, output->mask & 0xff);
- return E_INVALIDARG;
- }
-
- e->register_idx = output->register_idx;
- TRACE("Register idx: %u, register component idx %u, register mask %#x.\n",
- e->register_idx, e->component_idx, mask);
- }
- else
- {
- WARN("Failed to find output signature element for stream output entry.\n");
- return E_INVALIDARG;
}
}
@@ -1255,7 +1206,6 @@ static HRESULT d3d_geometry_shader_init(struct d3d_geometry_shader *shader,
unsigned int rasterizer_stream)
{
struct wined3d_stream_output_desc so_desc;
- struct wined3d_shader_signature signature;
struct wined3d_shader_desc desc;
unsigned int i;
HRESULT hr;
@@ -1292,40 +1242,22 @@ static HRESULT d3d_geometry_shader_init(struct d3d_geometry_shader *shader,
}
}
+ if (FAILED(hr = validate_stream_output_entries(so_entries, so_entry_count,
+ buffer_strides, buffer_stride_count, device->feature_level)))
+ return hr;
+
desc.byte_code = byte_code;
desc.byte_code_size = byte_code_length;
memset(&so_desc, 0, sizeof(so_desc));
if (so_entries)
{
+ so_desc.elements = (const struct wined3d_stream_output_element *)so_entries;
so_desc.element_count = so_entry_count;
for (i = 0; i < min(buffer_stride_count, ARRAY_SIZE(so_desc.buffer_strides)); ++i)
so_desc.buffer_strides[i] = buffer_strides[i];
so_desc.buffer_stride_count = buffer_stride_count;
so_desc.rasterizer_stream_idx = rasterizer_stream;
-
- if (!(so_desc.elements = heap_calloc(so_entry_count, sizeof(*so_desc.elements))))
- {
- ERR("Failed to allocate wined3d stream output element array memory.\n");
- return E_OUTOFMEMORY;
- }
-
- memset(&signature, 0, sizeof(signature));
- if (FAILED(hr = parse_dxbc(byte_code, byte_code_length, osgn_handler, &signature)))
- {
- ERR("Failed to parse input signature.\n");
- heap_free(so_desc.elements);
- return E_FAIL;
- }
- hr = wined3d_so_elements_from_d3d11_so_entries(so_desc.elements,
- so_entries, so_entry_count, buffer_strides, buffer_stride_count,
- &signature, device->feature_level);
- shader_free_signature(&signature);
- if (FAILED(hr))
- {
- heap_free(so_desc.elements);
- return hr;
- }
}
shader->ID3D11GeometryShader_iface.lpVtbl = &d3d11_geometry_shader_vtbl;
@@ -1334,10 +1266,8 @@ static HRESULT d3d_geometry_shader_init(struct d3d_geometry_shader *shader,
wined3d_mutex_lock();
wined3d_private_store_init(&shader->private_store);
- hr = wined3d_shader_create_gs(device->wined3d_device, &desc, so_entries ? &so_desc : NULL,
- shader, &d3d_geometry_shader_wined3d_parent_ops, &shader->wined3d_shader);
- heap_free(so_desc.elements);
- if (FAILED(hr))
+ if (FAILED(hr = wined3d_shader_create_gs(device->wined3d_device, &desc, so_entries ? &so_desc : NULL,
+ shader, &d3d_geometry_shader_wined3d_parent_ops, &shader->wined3d_shader)))
{
WARN("Failed to create wined3d geometry shader, hr %#x.\n", hr);
wined3d_private_store_cleanup(&shader->private_store);
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index db6760ebc303..ba2c62165b53 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -818,9 +818,10 @@ static void append_transform_feedback_skip_components(const char **varyings,
}
}
-static BOOL shader_glsl_generate_transform_feedback_varyings(const struct wined3d_stream_output_desc *so_desc,
- struct wined3d_string_buffer *buffer, const char **varyings, unsigned int *varying_count,
- char *strings, unsigned int *strings_length, GLenum buffer_mode)
+static BOOL shader_glsl_generate_transform_feedback_varyings(struct wined3d_string_buffer *buffer,
+ const char **varyings, unsigned int *varying_count,
+ char *strings, unsigned int *strings_length, GLenum buffer_mode,
+ const struct wined3d_stream_output_desc *so_desc, const unsigned int *output_register_idx)
{
unsigned int i, buffer_idx, count, length, highest_output_slot, stride;
BOOL have_varyings_to_record = FALSE;
@@ -847,7 +848,7 @@ static BOOL shader_glsl_generate_transform_feedback_varyings(const struct wined3
stride += e->component_count;
- if (e->register_idx == WINED3D_STREAM_OUTPUT_GAP)
+ if (!e->semantic_name)
{
append_transform_feedback_skip_components(varyings, &count,
&strings, &length, buffer, e->component_count);
@@ -865,12 +866,12 @@ static BOOL shader_glsl_generate_transform_feedback_varyings(const struct wined3
}
string_buffer_sprintf(buffer, "shader_in_out.reg%u_%u_%u",
- e->register_idx, e->component_idx, e->component_idx + e->component_count - 1);
+ output_register_idx[i], e->component_idx, e->component_idx + e->component_count - 1);
append_transform_feedback_varying(varyings, &count, &strings, &length, buffer);
}
else
{
- string_buffer_sprintf(buffer, "shader_in_out.reg%u", e->register_idx);
+ string_buffer_sprintf(buffer, "shader_in_out.reg%u", output_register_idx[i]);
append_transform_feedback_varying(varyings, &count, &strings, &length, buffer);
}
@@ -906,6 +907,7 @@ static BOOL shader_glsl_generate_transform_feedback_varyings(const struct wined3
static void shader_glsl_init_transform_feedback(const struct wined3d_context *context,
struct shader_glsl_priv *priv, GLuint program_id, struct wined3d_shader *shader)
{
+ const unsigned int *output_register_idx = shader->u.gs.output_register_idx;
const struct wined3d_stream_output_desc *so_desc = &shader->u.gs.so_desc;
const struct wined3d_gl_info *gl_info = context->gl_info;
struct wined3d_string_buffer *buffer;
@@ -927,7 +929,7 @@ static void shader_glsl_init_transform_feedback(const struct wined3d_context *co
for (i = 0; i < so_desc->element_count; ++i)
{
- if (so_desc->elements[i].register_idx == WINED3D_STREAM_OUTPUT_GAP)
+ if (!so_desc->elements[i].semantic_name)
{
FIXME("ARB_transform_feedback3 is needed for stream output gaps.\n");
return;
@@ -960,7 +962,7 @@ static void shader_glsl_init_transform_feedback(const struct wined3d_context *co
buffer = string_buffer_get(&priv->string_buffers);
- if (!shader_glsl_generate_transform_feedback_varyings(so_desc, buffer, NULL, &count, NULL, &length, mode))
+ if (!shader_glsl_generate_transform_feedback_varyings(buffer, NULL, &count, NULL, &length, mode, so_desc, output_register_idx))
{
FIXME("No varyings to record, disabling transform feedback.\n");
shader->u.gs.so_desc.element_count = 0;
@@ -982,7 +984,7 @@ static void shader_glsl_init_transform_feedback(const struct wined3d_context *co
return;
}
- shader_glsl_generate_transform_feedback_varyings(so_desc, buffer, varyings, NULL, strings, NULL, mode);
+ shader_glsl_generate_transform_feedback_varyings(buffer, varyings, NULL, strings, NULL, mode, so_desc, output_register_idx);
GL_EXTCALL(glTransformFeedbackVaryings(program_id, count, varyings, mode));
checkGLcall("glTransformFeedbackVaryings");
@@ -7421,7 +7423,8 @@ static GLuint shader_glsl_generate_vs3_rasterizer_input_setup(struct shader_glsl
}
static void shader_glsl_generate_stream_output_setup(struct shader_glsl_priv *priv,
- const struct wined3d_shader *shader, const struct wined3d_stream_output_desc *so_desc)
+ const struct wined3d_shader *shader, const struct wined3d_stream_output_desc *so_desc,
+ const unsigned int *output_register_idx)
{
struct wined3d_string_buffer *buffer = &priv->shader_buffer;
unsigned int i;
@@ -7436,7 +7439,7 @@ static void shader_glsl_generate_stream_output_setup(struct shader_glsl_priv *pr
FIXME("Unhandled stream %u.\n", e->stream_idx);
continue;
}
- if (e->register_idx == WINED3D_STREAM_OUTPUT_GAP)
+ if (!e->semantic_name)
continue;
if (e->component_idx || e->component_count != 4)
@@ -7446,11 +7449,11 @@ static void shader_glsl_generate_stream_output_setup(struct shader_glsl_priv *pr
else
shader_addline(buffer, "vec%u", e->component_count);
shader_addline(buffer, " reg%u_%u_%u;\n",
- e->register_idx, e->component_idx, e->component_idx + e->component_count - 1);
+ output_register_idx[i], e->component_idx, e->component_idx + e->component_count - 1);
}
else
{
- shader_addline(buffer, "vec4 reg%u;\n", e->register_idx);
+ shader_addline(buffer, "vec4 reg%u;\n", output_register_idx[i]);
}
}
shader_addline(buffer, "} shader_out;\n");
@@ -7466,7 +7469,7 @@ static void shader_glsl_generate_stream_output_setup(struct shader_glsl_priv *pr
FIXME("Unhandled stream %u.\n", e->stream_idx);
continue;
}
- if (e->register_idx == WINED3D_STREAM_OUTPUT_GAP)
+ if (!e->semantic_name)
continue;
if (e->component_idx || e->component_count != 4)
@@ -7477,13 +7480,13 @@ static void shader_glsl_generate_stream_output_setup(struct shader_glsl_priv *pr
write_mask = ((1u << e->component_count) - 1) << e->component_idx;
shader_glsl_write_mask_to_str(write_mask, str_mask);
shader_addline(buffer, "shader_out.reg%u_%u_%u = outputs[%u]%s;\n",
- e->register_idx, e->component_idx, e->component_idx + e->component_count - 1,
- e->register_idx, str_mask);
+ output_register_idx[i], e->component_idx, e->component_idx + e->component_count - 1,
+ output_register_idx[i], str_mask);
}
else
{
shader_addline(buffer, "shader_out.reg%u = outputs[%u];\n",
- e->register_idx, e->register_idx);
+ output_register_idx[i], output_register_idx[i]);
}
}
shader_addline(buffer, "}\n");
@@ -8529,7 +8532,8 @@ static GLuint shader_glsl_generate_geometry_shader(const struct wined3d_context
if (is_rasterization_disabled(shader))
{
- shader_glsl_generate_stream_output_setup(priv, shader, &shader->u.gs.so_desc);
+ shader_glsl_generate_stream_output_setup(priv, shader,
+ &shader->u.gs.so_desc, shader->u.gs.output_register_idx);
}
else
{
diff --git a/dlls/wined3d/shader.c b/dlls/wined3d/shader.c
index e11a37cf078f..a52b9a1c83a9 100644
--- a/dlls/wined3d/shader.c
+++ b/dlls/wined3d/shader.c
@@ -3144,7 +3144,8 @@ static void shader_cleanup(struct wined3d_shader *shader)
}
else if (shader->reg_maps.shader_version.type == WINED3D_SHADER_TYPE_GEOMETRY)
{
- heap_free(shader->u.gs.so_desc.elements);
+ heap_free((void *)shader->u.gs.so_desc.elements);
+ heap_free(shader->u.gs.output_register_idx);
}
heap_free(shader->patch_constant_signature.elements);
@@ -3728,12 +3729,31 @@ static HRESULT vertex_shader_init(struct wined3d_shader *shader, struct wined3d_
return WINED3D_OK;
}
+static struct wined3d_shader_signature_element *shader_find_signature_element(const struct wined3d_shader_signature *s,
+ unsigned int stream_idx, const char *semantic_name, unsigned int semantic_idx)
+{
+ struct wined3d_shader_signature_element *e = s->elements;
+ unsigned int i;
+
+ for (i = 0; i < s->element_count; ++i)
+ {
+ if (e[i].stream_idx == stream_idx
+ && !strcasecmp(e[i].semantic_name, semantic_name)
+ && e[i].semantic_idx == semantic_idx)
+ return &e[i];
+ }
+
+ return NULL;
+}
+
static HRESULT geometry_shader_init_stream_output(struct wined3d_shader *shader,
const struct wined3d_stream_output_desc *so_desc)
{
const struct wined3d_shader_frontend *fe = shader->frontend;
+ const struct wined3d_shader_signature_element *output;
struct wined3d_stream_output_element *elements;
struct wined3d_shader_version shader_version;
+ unsigned int i, j, mask;
const DWORD *ptr;
void *fe_data;
HRESULT hr;
@@ -3772,6 +3792,9 @@ static HRESULT geometry_shader_init_stream_output(struct wined3d_shader *shader,
return hr;
}
+ if (!(shader->u.gs.output_register_idx = heap_calloc(so_desc->element_count, sizeof(*shader->u.gs.output_register_idx))))
+ return E_OUTOFMEMORY;
+
if (!(elements = heap_calloc(so_desc->element_count, sizeof(*elements))))
return E_OUTOFMEMORY;
@@ -3779,6 +3802,38 @@ static HRESULT geometry_shader_init_stream_output(struct wined3d_shader *shader,
shader->u.gs.so_desc.elements = elements;
memcpy(elements, so_desc->elements, so_desc->element_count * sizeof(*elements));
+ for (i = 0; i < so_desc->element_count; ++i)
+ {
+ struct wined3d_stream_output_element *e = &elements[i];
+
+ if (!e->semantic_name)
+ continue;
+ if (!(output = shader_find_signature_element(&shader->output_signature,
+ e->stream_idx, e->semantic_name, e->semantic_idx)))
+ {
+ WARN("Failed to find output signature element for stream output entry.\n");
+ return E_INVALIDARG;
+ }
+
+ e->semantic_name = output->semantic_name;
+ shader->u.gs.output_register_idx[i] = output->register_idx;
+
+ for (j = 0; j < 4; ++j)
+ {
+ if ((1u << j) & output->mask)
+ break;
+ }
+ e->component_idx += j;
+
+ mask = ((1u << e->component_count) - 1) << e->component_idx;
+ if ((output->mask & 0xff & mask) != mask)
+ {
+ WARN("Invalid component range %u-%u (mask %#x), output mask %#x.\n",
+ e->component_idx, e->component_count, mask, output->mask & 0xff);
+ return E_INVALIDARG;
+ }
+ }
+
return WINED3D_OK;
}
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 66a2ee4e418e..f44dccbe6c1e 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -4191,6 +4191,7 @@ struct wined3d_geometry_shader
unsigned int instance_count;
struct wined3d_stream_output_desc so_desc;
+ unsigned int *output_register_idx;
};
struct wined3d_pixel_shader
diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h
index e09e4e1fce2d..a58dd87ee7d0 100644
--- a/include/wine/wined3d.h
+++ b/include/wine/wined3d.h
@@ -1574,7 +1574,6 @@ enum wined3d_shader_type
#define WINED3D_OUTPUT_SLOT_UNUSED 0xfffffffe
#define WINED3D_MAX_STREAM_OUTPUT_BUFFERS 4
-#define WINED3D_STREAM_OUTPUT_GAP 0xffffffff
#define WINED3D_NO_RASTERIZER_STREAM 0xffffffff
#define WINED3D_VIEW_BUFFER_RAW 0x00000001
@@ -2060,7 +2059,8 @@ struct wined3d_shader_desc
struct wined3d_stream_output_element
{
unsigned int stream_idx;
- unsigned int register_idx;
+ const char *semantic_name;
+ unsigned int semantic_idx;
BYTE component_idx;
BYTE component_count;
BYTE output_slot;
@@ -2068,7 +2068,7 @@ struct wined3d_stream_output_element
struct wined3d_stream_output_desc
{
- struct wined3d_stream_output_element *elements;
+ const struct wined3d_stream_output_element *elements;
unsigned int element_count;
unsigned int buffer_strides[WINED3D_MAX_STREAM_OUTPUT_BUFFERS];
unsigned int buffer_stride_count;
--
2.19.2