diff --git a/dlls/wined3d/shader.c b/dlls/wined3d/shader.c index c20c1da14bc..8934c4f5d6d 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 8eac746ac50..f11af763025 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 e9e3f86b910..9ab1843f24a 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