Signed-off-by: Józef Kucia <jkucia(a)codeweavers.com>
---
dlls/wined3d/shader.c | 24 +++++++++++++++
dlls/wined3d/shader_sm4.c | 69 +++++++++++++++++++++++++-----------------
dlls/wined3d/wined3d_private.h | 4 +++
3 files changed, 70 insertions(+), 27 deletions(-)
diff --git a/dlls/wined3d/shader.c b/dlls/wined3d/shader.c
index c20c1da14bcf..8934c4f5d6d3 100644
--- a/dlls/wined3d/shader.c
+++ b/dlls/wined3d/shader.c
@@ -419,6 +419,15 @@ static const struct wined3d_shader_frontend *shader_select_frontend(enum wined3d
}
}
+static enum wined3d_shader_type shader_get_shader_type(const struct wined3d_shader_desc *desc)
+{
+ if (desc->format == WINED3D_SHADER_BYTE_CODE_FORMAT_SM4)
+ return wined3d_get_sm4_shader_type(desc->byte_code, desc->byte_code_size);
+
+ FIXME("Could not get shader type for byte code format %#x.\n", desc->format);
+ return WINED3D_SHADER_TYPE_INVALID;
+}
+
void string_buffer_clear(struct wined3d_string_buffer *buffer)
{
buffer->buffer[0] = '\0';
@@ -3722,8 +3731,23 @@ static HRESULT geometry_shader_init(struct wined3d_shader *shader, struct wined3
void *parent, const struct wined3d_parent_ops *parent_ops)
{
struct wined3d_stream_output_element *elements = NULL;
+ enum wined3d_shader_type shader_type;
HRESULT hr;
+ if (so_desc)
+ {
+ shader_type = shader_get_shader_type(desc);
+ switch (shader_type)
+ {
+ case WINED3D_SHADER_TYPE_VERTEX:
+ case WINED3D_SHADER_TYPE_DOMAIN:
+ FIXME("Stream output not supported for %s.\n", debug_shader_type(shader_type));
+ return E_NOTIMPL;
+ default:
+ break;
+ }
+ }
+
if (so_desc && !(elements = heap_calloc(so_desc->element_count, sizeof(*elements))))
return E_OUTOFMEMORY;
diff --git a/dlls/wined3d/shader_sm4.c b/dlls/wined3d/shader_sm4.c
index 8eac746ac507..f11af7630253 100644
--- a/dlls/wined3d/shader_sm4.c
+++ b/dlls/wined3d/shader_sm4.c
@@ -1218,6 +1218,43 @@ static enum wined3d_data_type map_data_type(char t)
}
}
+enum wined3d_shader_type wined3d_get_sm4_shader_type(const DWORD *byte_code, size_t byte_code_size)
+{
+ DWORD shader_type;
+
+ if (byte_code_size / sizeof(*byte_code) < 1)
+ {
+ WARN("Invalid byte code size %lu.\n", (long)byte_code_size);
+ return WINED3D_SHADER_TYPE_INVALID;
+ }
+
+ shader_type = byte_code[0] >> 16;
+ switch (shader_type)
+ {
+ case WINED3D_SM4_PS:
+ return WINED3D_SHADER_TYPE_PIXEL;
+ break;
+ case WINED3D_SM4_VS:
+ return WINED3D_SHADER_TYPE_VERTEX;
+ break;
+ case WINED3D_SM4_GS:
+ return WINED3D_SHADER_TYPE_GEOMETRY;
+ break;
+ case WINED3D_SM5_HS:
+ return WINED3D_SHADER_TYPE_HULL;
+ break;
+ case WINED3D_SM5_DS:
+ return WINED3D_SHADER_TYPE_DOMAIN;
+ break;
+ case WINED3D_SM5_CS:
+ return WINED3D_SHADER_TYPE_COMPUTE;
+ break;
+ default:
+ FIXME("Unrecognised shader type %#x.\n", shader_type);
+ return WINED3D_SHADER_TYPE_INVALID;
+ }
+}
+
static void *shader_sm4_init(const DWORD *byte_code, size_t byte_code_size,
const struct wined3d_shader_signature *output_signature)
{
@@ -1251,35 +1288,13 @@ static void *shader_sm4_init(const DWORD *byte_code, size_t byte_code_size,
priv->start = &byte_code[2];
priv->end = &byte_code[token_count];
- switch (version_token >> 16)
+ priv->shader_version.type = wined3d_get_sm4_shader_type(byte_code, byte_code_size);
+ if (priv->shader_version.type == WINED3D_SHADER_TYPE_INVALID)
{
- case WINED3D_SM4_PS:
- priv->shader_version.type = WINED3D_SHADER_TYPE_PIXEL;
- break;
-
- case WINED3D_SM4_VS:
- priv->shader_version.type = WINED3D_SHADER_TYPE_VERTEX;
- break;
-
- case WINED3D_SM4_GS:
- priv->shader_version.type = WINED3D_SHADER_TYPE_GEOMETRY;
- break;
-
- case WINED3D_SM5_HS:
- priv->shader_version.type = WINED3D_SHADER_TYPE_HULL;
- break;
-
- case WINED3D_SM5_DS:
- priv->shader_version.type = WINED3D_SHADER_TYPE_DOMAIN;
- break;
-
- case WINED3D_SM5_CS:
- priv->shader_version.type = WINED3D_SHADER_TYPE_COMPUTE;
- break;
-
- default:
- FIXME("Unrecognised shader type %#x.\n", version_token >> 16);
+ heap_free(priv);
+ return NULL;
}
+
priv->shader_version.major = WINED3D_SM4_VERSION_MAJOR(version_token);
priv->shader_version.minor = WINED3D_SM4_VERSION_MINOR(version_token);
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 8cdc3ef6f937..ed01da02997e 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -929,6 +929,7 @@ enum wined3d_shader_type
WINED3D_SHADER_TYPE_COMPUTE = WINED3D_SHADER_TYPE_GRAPHICS_COUNT,
WINED3D_SHADER_TYPE_COUNT,
+ WINED3D_SHADER_TYPE_INVALID = WINED3D_SHADER_TYPE_COUNT,
};
struct wined3d_shader_version
@@ -1265,6 +1266,9 @@ struct wined3d_shader_frontend
extern const struct wined3d_shader_frontend sm1_shader_frontend DECLSPEC_HIDDEN;
extern const struct wined3d_shader_frontend sm4_shader_frontend DECLSPEC_HIDDEN;
+enum wined3d_shader_type wined3d_get_sm4_shader_type(const DWORD *byte_code,
+ size_t byte_code_size) DECLSPEC_HIDDEN;
+
typedef void (*SHADER_HANDLER)(const struct wined3d_shader_instruction *);
#define WINED3D_SHADER_CAP_VS_CLIPPING 0x00000001
--
2.16.1