From 7b01569e4431de9e037d5ae017299061242d2d65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B3zef=20Kucia?= Date: Mon, 15 May 2017 12:05:47 +0200 Subject: [PATCH] wined3d: Recognize SM5+ patch input primitive types. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In D3D11 geometry shaders accept patches as input primitives. This is forbidden in OpenGL as specified in the ARB_tessellation_shaders spec: "we will not allow geometry shaders to receive patches in this extension. That limitation may be relaxed in a future extension." Signed-off-by: Józef Kucia Signed-off-by: Henri Verbeet Signed-off-by: Alexandre Julliard --- dlls/wined3d/device.c | 6 +++ dlls/wined3d/shader.c | 15 +++++--- dlls/wined3d/shader_sm4.c | 67 +++++++++++++++++++++++++++------- dlls/wined3d/utils.c | 3 +- dlls/wined3d/wined3d_private.h | 8 +++- include/wine/wined3d.h | 1 + 6 files changed, 79 insertions(+), 21 deletions(-) diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 61be30eb162..26a1911726d 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -89,6 +89,9 @@ GLenum gl_primitive_type_from_d3d(enum wined3d_primitive_type primitive_type) case WINED3D_PT_TRIANGLESTRIP_ADJ: return GL_TRIANGLE_STRIP_ADJACENCY_ARB; + case WINED3D_PT_PATCH: + return GL_PATCHES; + default: FIXME("Unhandled primitive type %s.\n", debug_d3dprimitivetype(primitive_type)); case WINED3D_PT_UNDEFINED: @@ -130,6 +133,9 @@ static enum wined3d_primitive_type d3d_primitive_type_from_gl(GLenum primitive_t case GL_TRIANGLE_STRIP_ADJACENCY_ARB: return WINED3D_PT_TRIANGLESTRIP_ADJ; + case GL_PATCHES: + return WINED3D_PT_PATCH; + default: FIXME("Unhandled primitive type %s.\n", debug_d3dprimitivetype(primitive_type)); case ~0u: diff --git a/dlls/wined3d/shader.c b/dlls/wined3d/shader.c index 4b9aeccbe6e..71a17185c70 100644 --- a/dlls/wined3d/shader.c +++ b/dlls/wined3d/shader.c @@ -1048,7 +1048,7 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const st else if (ins.handler_idx == WINED3DSIH_DCL_INPUT_PRIMITIVE) { if (shader_version.type == WINED3D_SHADER_TYPE_GEOMETRY) - shader->u.gs.input_type = ins.declaration.primitive_type; + shader->u.gs.input_type = ins.declaration.primitive_type.type; else FIXME("Invalid instruction %#x for shader type %#x.\n", ins.handler_idx, shader_version.type); @@ -1056,7 +1056,7 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const st else if (ins.handler_idx == WINED3DSIH_DCL_OUTPUT_TOPOLOGY) { if (shader_version.type == WINED3D_SHADER_TYPE_GEOMETRY) - shader->u.gs.output_type = ins.declaration.primitive_type; + shader->u.gs.output_type = ins.declaration.primitive_type.type; else FIXME("Invalid instruction %#x for shader type %#x.\n", ins.handler_idx, shader_version.type); @@ -2395,9 +2395,9 @@ static void shader_dump_ins_modifiers(struct wined3d_string_buffer *buffer, } static void shader_dump_primitive_type(struct wined3d_string_buffer *buffer, - enum wined3d_primitive_type primitive_type) + const struct wined3d_shader_primitive_type *primitive_type) { - switch (primitive_type) + switch (primitive_type->type) { case WINED3D_PT_UNDEFINED: shader_addline(buffer, "undefined"); @@ -2432,8 +2432,11 @@ static void shader_dump_primitive_type(struct wined3d_string_buffer *buffer, case WINED3D_PT_TRIANGLESTRIP_ADJ: shader_addline(buffer, "trianglestrip_adj"); break; + case WINED3D_PT_PATCH: + shader_addline(buffer, "patch%u", primitive_type->patch_vertex_count); + break; default: - shader_addline(buffer, "", primitive_type); + shader_addline(buffer, "", primitive_type->type); break; } } @@ -2631,7 +2634,7 @@ static void shader_trace_init(const struct wined3d_shader_frontend *fe, void *fe || ins.handler_idx == WINED3DSIH_DCL_OUTPUT_TOPOLOGY) { shader_addline(&buffer, "%s ", shader_opcode_names[ins.handler_idx]); - shader_dump_primitive_type(&buffer, ins.declaration.primitive_type); + shader_dump_primitive_type(&buffer, &ins.declaration.primitive_type); } else if (ins.handler_idx == WINED3DSIH_DCL_INTERFACE) { diff --git a/dlls/wined3d/shader_sm4.c b/dlls/wined3d/shader_sm4.c index f2f229f56fa..384a7444995 100644 --- a/dlls/wined3d/shader_sm4.c +++ b/dlls/wined3d/shader_sm4.c @@ -44,7 +44,7 @@ WINE_DECLARE_DEBUG_CHANNEL(d3d_bytecode); #define WINED3D_SM4_RESOURCE_TYPE_MASK (0xfu << WINED3D_SM4_RESOURCE_TYPE_SHIFT) #define WINED3D_SM4_PRIMITIVE_TYPE_SHIFT 11 -#define WINED3D_SM4_PRIMITIVE_TYPE_MASK (0x7u << WINED3D_SM4_PRIMITIVE_TYPE_SHIFT) +#define WINED3D_SM4_PRIMITIVE_TYPE_MASK (0x3fu << WINED3D_SM4_PRIMITIVE_TYPE_SHIFT) #define WINED3D_SM4_INDEX_TYPE_SHIFT 11 #define WINED3D_SM4_INDEX_TYPE_MASK (0x1u << WINED3D_SM4_INDEX_TYPE_SHIFT) @@ -342,11 +342,43 @@ enum wined3d_sm4_output_primitive_type enum wined3d_sm4_input_primitive_type { - WINED3D_SM4_INPUT_PT_POINT = 0x1, - WINED3D_SM4_INPUT_PT_LINE = 0x2, - WINED3D_SM4_INPUT_PT_TRIANGLE = 0x3, - WINED3D_SM4_INPUT_PT_LINEADJ = 0x6, - WINED3D_SM4_INPUT_PT_TRIANGLEADJ = 0x7, + WINED3D_SM4_INPUT_PT_POINT = 0x01, + WINED3D_SM4_INPUT_PT_LINE = 0x02, + WINED3D_SM4_INPUT_PT_TRIANGLE = 0x03, + WINED3D_SM4_INPUT_PT_LINEADJ = 0x06, + WINED3D_SM4_INPUT_PT_TRIANGLEADJ = 0x07, + WINED3D_SM5_INPUT_PT_PATCH1 = 0x08, + WINED3D_SM5_INPUT_PT_PATCH2 = 0x09, + WINED3D_SM5_INPUT_PT_PATCH3 = 0x0a, + WINED3D_SM5_INPUT_PT_PATCH4 = 0x0b, + WINED3D_SM5_INPUT_PT_PATCH5 = 0x0c, + WINED3D_SM5_INPUT_PT_PATCH6 = 0x0d, + WINED3D_SM5_INPUT_PT_PATCH7 = 0x0e, + WINED3D_SM5_INPUT_PT_PATCH8 = 0x0f, + WINED3D_SM5_INPUT_PT_PATCH9 = 0x10, + WINED3D_SM5_INPUT_PT_PATCH10 = 0x11, + WINED3D_SM5_INPUT_PT_PATCH11 = 0x12, + WINED3D_SM5_INPUT_PT_PATCH12 = 0x13, + WINED3D_SM5_INPUT_PT_PATCH13 = 0x14, + WINED3D_SM5_INPUT_PT_PATCH14 = 0x15, + WINED3D_SM5_INPUT_PT_PATCH15 = 0x16, + WINED3D_SM5_INPUT_PT_PATCH16 = 0x17, + WINED3D_SM5_INPUT_PT_PATCH17 = 0x18, + WINED3D_SM5_INPUT_PT_PATCH18 = 0x19, + WINED3D_SM5_INPUT_PT_PATCH19 = 0x1a, + WINED3D_SM5_INPUT_PT_PATCH20 = 0x1b, + WINED3D_SM5_INPUT_PT_PATCH21 = 0x1c, + WINED3D_SM5_INPUT_PT_PATCH22 = 0x1d, + WINED3D_SM5_INPUT_PT_PATCH23 = 0x1e, + WINED3D_SM5_INPUT_PT_PATCH24 = 0x1f, + WINED3D_SM5_INPUT_PT_PATCH25 = 0x20, + WINED3D_SM5_INPUT_PT_PATCH26 = 0x21, + WINED3D_SM5_INPUT_PT_PATCH27 = 0x22, + WINED3D_SM5_INPUT_PT_PATCH28 = 0x23, + WINED3D_SM5_INPUT_PT_PATCH29 = 0x24, + WINED3D_SM5_INPUT_PT_PATCH30 = 0x25, + WINED3D_SM5_INPUT_PT_PATCH31 = 0x26, + WINED3D_SM5_INPUT_PT_PATCH32 = 0x27, }; enum wined3d_sm4_swizzle_type @@ -594,11 +626,11 @@ static void shader_sm4_read_dcl_output_topology(struct wined3d_shader_instructio primitive_type = (opcode_token & WINED3D_SM4_PRIMITIVE_TYPE_MASK) >> WINED3D_SM4_PRIMITIVE_TYPE_SHIFT; if (primitive_type >= ARRAY_SIZE(output_primitive_type_table)) - ins->declaration.primitive_type = WINED3D_PT_UNDEFINED; + ins->declaration.primitive_type.type = WINED3D_PT_UNDEFINED; else - ins->declaration.primitive_type = output_primitive_type_table[primitive_type]; + ins->declaration.primitive_type.type = output_primitive_type_table[primitive_type]; - if (ins->declaration.primitive_type == WINED3D_PT_UNDEFINED) + if (ins->declaration.primitive_type.type == WINED3D_PT_UNDEFINED) FIXME("Unhandled output primitive type %#x.\n", primitive_type); } @@ -609,12 +641,21 @@ static void shader_sm4_read_dcl_input_primitive(struct wined3d_shader_instructio enum wined3d_sm4_input_primitive_type primitive_type; primitive_type = (opcode_token & WINED3D_SM4_PRIMITIVE_TYPE_MASK) >> WINED3D_SM4_PRIMITIVE_TYPE_SHIFT; - if (primitive_type >= ARRAY_SIZE(input_primitive_type_table)) - ins->declaration.primitive_type = WINED3D_PT_UNDEFINED; + if (WINED3D_SM5_INPUT_PT_PATCH1 <= primitive_type && primitive_type <= WINED3D_SM5_INPUT_PT_PATCH32) + { + ins->declaration.primitive_type.type = WINED3D_PT_PATCH; + ins->declaration.primitive_type.patch_vertex_count = primitive_type - WINED3D_SM5_INPUT_PT_PATCH1 + 1; + } + else if (primitive_type >= ARRAY_SIZE(input_primitive_type_table)) + { + ins->declaration.primitive_type.type = WINED3D_PT_UNDEFINED; + } else - ins->declaration.primitive_type = input_primitive_type_table[primitive_type]; + { + ins->declaration.primitive_type.type = input_primitive_type_table[primitive_type]; + } - if (ins->declaration.primitive_type == WINED3D_PT_UNDEFINED) + if (ins->declaration.primitive_type.type == WINED3D_PT_UNDEFINED) FIXME("Unhandled input primitive type %#x.\n", primitive_type); } diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c index fb4a8495538..78ada57e4dd 100644 --- a/dlls/wined3d/utils.c +++ b/dlls/wined3d/utils.c @@ -4102,9 +4102,10 @@ const char *debug_d3dprimitivetype(enum wined3d_primitive_type primitive_type) PRIM_TO_STR(WINED3D_PT_LINESTRIP_ADJ); PRIM_TO_STR(WINED3D_PT_TRIANGLELIST_ADJ); PRIM_TO_STR(WINED3D_PT_TRIANGLESTRIP_ADJ); + PRIM_TO_STR(WINED3D_PT_PATCH); #undef PRIM_TO_STR default: - FIXME("Unrecognized %u primitive type!\n", primitive_type); + FIXME("Unrecognized primitive type %#x.\n", primitive_type); return "unrecognized"; } } diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 37666487521..91dd20676b4 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1148,6 +1148,12 @@ struct wined3d_shader_texel_offset signed char u, v, w; }; +struct wined3d_shader_primitive_type +{ + enum wined3d_primitive_type type; + unsigned int patch_vertex_count; +}; + struct wined3d_shader_instruction { const struct wined3d_shader_context *ctx; @@ -1164,7 +1170,7 @@ struct wined3d_shader_instruction { struct wined3d_shader_semantic semantic; struct wined3d_shader_register_semantic register_semantic; - enum wined3d_primitive_type primitive_type; + struct wined3d_shader_primitive_type primitive_type; struct wined3d_shader_dst_param dst; struct wined3d_shader_src_param src; unsigned int count; diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index d58c4b4dfba..7ab0c686bbd 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -72,6 +72,7 @@ enum wined3d_primitive_type WINED3D_PT_LINESTRIP_ADJ = 11, WINED3D_PT_TRIANGLELIST_ADJ = 12, WINED3D_PT_TRIANGLESTRIP_ADJ = 13, + WINED3D_PT_PATCH = 14, }; enum wined3d_device_type