[PATCH 5/5] wined3d: Recognize SM5+ patch input primitive types.

Józef Kucia jkucia at codeweavers.com
Mon May 15 05:05:47 CDT 2017


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 <jkucia at codeweavers.com>
---
 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 61be30e..26a1911 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 5717767..8fb6d0f 100644
--- a/dlls/wined3d/shader.c
+++ b/dlls/wined3d/shader.c
@@ -1047,7 +1047,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);
@@ -1055,7 +1055,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);
@@ -2394,9 +2394,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");
@@ -2431,8 +2431,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, "<unrecognized_primitive_type %#x>", primitive_type);
+            shader_addline(buffer, "<unrecognized_primitive_type %#x>", primitive_type->type);
             break;
     }
 }
@@ -2630,7 +2633,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 3c975f3f..0c2ab52 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)
@@ -341,11 +341,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
@@ -593,11 +625,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);
 }
 
@@ -608,12 +640,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 fb4a849..78ada57 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 38e5a45..308b709 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1147,6 +1147,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;
@@ -1163,7 +1169,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 d58c4b4..7ab0c68 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
-- 
2.10.2




More information about the wine-patches mailing list