[PATCH 04/11] wined3d: Introduce wined3d_device_set_unordered_access_view().

Józef Kucia jkucia at codeweavers.com
Wed Nov 23 07:36:05 CST 2016


Signed-off-by: Józef Kucia <jkucia at codeweavers.com>
---

D3D11.0 supports UAVs only in pixel shaders and compute shaders.

---
 dlls/wined3d/context.c         | 45 ++++++++++++++++++++++++++++++++++++++++++
 dlls/wined3d/cs.c              | 38 +++++++++++++++++++++++++++++++++++
 dlls/wined3d/device.c          | 26 ++++++++++++++++++++++++
 dlls/wined3d/glsl_shader.c     | 28 +++++++++++++++++++++++++-
 dlls/wined3d/state.c           | 14 +++++++++++++
 dlls/wined3d/stateblock.c      | 10 ++++++++++
 dlls/wined3d/utils.c           |  2 ++
 dlls/wined3d/view.c            |  8 ++++++++
 dlls/wined3d/wined3d.spec      |  1 +
 dlls/wined3d/wined3d_private.h | 13 ++++++++++--
 include/wine/wined3d.h         |  2 ++
 11 files changed, 184 insertions(+), 3 deletions(-)

diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c
index 88d34e6..2993e0c 100644
--- a/dlls/wined3d/context.c
+++ b/dlls/wined3d/context.c
@@ -3386,6 +3386,45 @@ static void context_bind_shader_resources(struct wined3d_context *context, const
     }
 }
 
+static void context_bind_unordered_access_views(struct wined3d_context *context,
+        const struct wined3d_state *state)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    struct wined3d_unordered_access_view *view;
+    struct wined3d_texture *texture;
+    struct wined3d_shader *shader;
+    struct gl_texture *gl_texture;
+    unsigned int i;
+
+    if (!(shader = state->shader[WINED3D_SHADER_TYPE_PIXEL]))
+        return;
+
+    for (i = 0; i < MAX_UNORDERED_ACCESS_VIEWS; ++i)
+    {
+        if (!shader->reg_maps.uav_resource_info[i].type)
+            continue;
+
+        if (!(view = state->unordered_access_view[i]))
+        {
+            WARN("No unordered access view bound at index %u.\n", i);
+            continue;
+        }
+
+        if (view->resource->type == WINED3D_RTYPE_BUFFER)
+        {
+            FIXME("Buffer unordered access views not implemented.\n");
+            continue;
+        }
+
+        texture = texture_from_resource(view->resource);
+        wined3d_texture_load(texture, context, FALSE);
+        gl_texture = wined3d_texture_get_gl_texture(texture, FALSE);
+        GL_EXTCALL(glBindImageTexture(i, gl_texture->name, view->level_idx, GL_TRUE, 0, GL_READ_WRITE,
+                view->format->glInternal));
+    }
+    checkGLcall("Bind unordered access views");
+}
+
 /* Context activation is done by the caller. */
 BOOL context_apply_draw_state(struct wined3d_context *context,
         const struct wined3d_device *device, const struct wined3d_state *state)
@@ -3462,6 +3501,12 @@ BOOL context_apply_draw_state(struct wined3d_context *context,
         context->update_shader_resource_bindings = 0;
     }
 
+    if (context->update_unordered_access_view_bindings)
+    {
+        context_bind_unordered_access_views(context, state);
+        context->update_unordered_access_view_bindings = 0;
+    }
+
     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
     {
         context_check_fbo_status(context, GL_FRAMEBUFFER);
diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c
index 7af0b81..f41b1a5 100644
--- a/dlls/wined3d/cs.c
+++ b/dlls/wined3d/cs.c
@@ -42,6 +42,7 @@ enum wined3d_cs_op
     WINED3D_CS_OP_SET_CONSTANT_BUFFER,
     WINED3D_CS_OP_SET_TEXTURE,
     WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEW,
+    WINED3D_CS_OP_SET_UNORDERED_ACCESS_VIEW,
     WINED3D_CS_OP_SET_SAMPLER,
     WINED3D_CS_OP_SET_SHADER,
     WINED3D_CS_OP_SET_RASTERIZER_STATE,
@@ -196,6 +197,13 @@ struct wined3d_cs_set_shader_resource_view
     struct wined3d_shader_resource_view *view;
 };
 
+struct wined3d_cs_set_unordered_access_view
+{
+    enum wined3d_cs_op opcode;
+    unsigned int view_idx;
+    struct wined3d_unordered_access_view *view;
+};
+
 struct wined3d_cs_set_sampler
 {
     enum wined3d_cs_op opcode;
@@ -934,6 +942,35 @@ static void wined3d_cs_exec_set_shader_resource_view(struct wined3d_cs *cs, cons
     device_invalidate_state(cs->device, STATE_SHADER_RESOURCE_BINDING);
 }
 
+void wined3d_cs_emit_set_unordered_access_view(struct wined3d_cs *cs, unsigned int view_idx,
+        struct wined3d_unordered_access_view *view)
+{
+    struct wined3d_cs_set_unordered_access_view *op;
+
+    op = cs->ops->require_space(cs, sizeof(*op));
+    op->opcode = WINED3D_CS_OP_SET_UNORDERED_ACCESS_VIEW;
+    op->view_idx = view_idx;
+    op->view = view;
+
+    cs->ops->submit(cs);
+}
+
+static void wined3d_cs_exec_set_unordered_access_view(struct wined3d_cs *cs, const void *data)
+{
+    const struct wined3d_cs_set_unordered_access_view *op = data;
+    struct wined3d_unordered_access_view *prev;
+
+    prev = cs->state.unordered_access_view[op->view_idx];
+    cs->state.unordered_access_view[op->view_idx] = op->view;
+
+    if (op->view)
+        InterlockedIncrement(&op->view->resource->bind_count);
+    if (prev)
+        InterlockedDecrement(&prev->resource->bind_count);
+
+    device_invalidate_state(cs->device, STATE_UNORDERED_ACCESS_VIEW_BINDING);
+}
+
 void wined3d_cs_emit_set_shader_resource_view(struct wined3d_cs *cs, enum wined3d_shader_type type,
         UINT view_idx, struct wined3d_shader_resource_view *view)
 {
@@ -1393,6 +1430,7 @@ static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void
     /* WINED3D_CS_OP_SET_CONSTANT_BUFFER        */ wined3d_cs_exec_set_constant_buffer,
     /* WINED3D_CS_OP_SET_TEXTURE                */ wined3d_cs_exec_set_texture,
     /* WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEW   */ wined3d_cs_exec_set_shader_resource_view,
+    /* WINED3D_CS_OP_SET_UNORDERED_ACCESS_VIEW  */ wined3d_cs_exec_set_unordered_access_view,
     /* WINED3D_CS_OP_SET_SAMPLER                */ wined3d_cs_exec_set_sampler,
     /* WINED3D_CS_OP_SET_SHADER                 */ wined3d_cs_exec_set_shader,
     /* WINED3D_CS_OP_SET_RASTERIZER_STATE       */ wined3d_cs_exec_set_rasterizer_state,
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 90ac18a..5b64978 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -2857,6 +2857,32 @@ struct wined3d_sampler * CDECL wined3d_device_get_gs_sampler(const struct wined3
     return device->state.sampler[WINED3D_SHADER_TYPE_GEOMETRY][idx];
 }
 
+void CDECL wined3d_device_set_unordered_access_view(struct wined3d_device *device,
+        unsigned int idx, struct wined3d_unordered_access_view *uav)
+{
+    struct wined3d_unordered_access_view *prev;
+
+    TRACE("device %p, idx %u, uav %p.\n", device, idx, uav);
+
+    if (idx >= MAX_UNORDERED_ACCESS_VIEWS)
+    {
+        WARN("Invalid UAV index %u.\n", idx);
+        return;
+    }
+
+    prev = device->update_state->unordered_access_view[idx];
+    if (uav == prev)
+        return;
+
+    if (uav)
+        wined3d_unordered_access_view_incref(uav);
+    device->update_state->unordered_access_view[idx] = uav;
+    if (!device->recording)
+        wined3d_cs_emit_set_unordered_access_view(device->cs, idx, uav);
+    if (prev)
+        wined3d_unordered_access_view_decref(prev);
+}
+
 /* Context activation is done by the caller. */
 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
 static HRESULT process_vertices_strided(const struct wined3d_device *device, DWORD dwDestIndex, DWORD dwCount,
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index 747883b..f0df045 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -574,7 +574,7 @@ static void shader_glsl_load_samplers(const struct wined3d_gl_info *gl_info,
             GL_EXTCALL(glUniform1i(name_loc, mapped_unit));
         }
     }
-    checkGLcall("glUniform1i");
+    checkGLcall("Load sampler bindings");
     string_buffer_release(&priv->string_buffers, sampler_name);
 }
 
@@ -599,6 +599,31 @@ static void shader_glsl_load_icb(const struct wined3d_gl_info *gl_info, struct s
 }
 
 /* Context activation is done by the caller. */
+static void shader_glsl_load_images(const struct wined3d_gl_info *gl_info, struct shader_glsl_priv *priv,
+        GLuint program_id, const struct wined3d_shader_reg_maps *reg_maps)
+{
+    struct wined3d_string_buffer *name = string_buffer_get(&priv->string_buffers);
+    GLint location;
+    unsigned int i;
+
+    for (i = 0; i < MAX_UNORDERED_ACCESS_VIEWS; ++i)
+    {
+        if (!reg_maps->uav_resource_info[i].type)
+            continue;
+
+        string_buffer_sprintf(name, "ps_image%u", i);
+        location = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer));
+        if (location == -1)
+            continue;
+
+        TRACE("Loading image %s on unit %u.\n", name->buffer, i);
+        GL_EXTCALL(glUniform1i(location, i));
+    }
+    checkGLcall("Load image bindings");
+    string_buffer_release(&priv->string_buffers, name);
+}
+
+/* Context activation is done by the caller. */
 static inline void walk_constant_heap(const struct wined3d_gl_info *gl_info, const struct wined3d_vec4 *constants,
         const GLint *constant_locations, const struct constant_heap *heap, unsigned char *stack, DWORD version)
 {
@@ -8077,6 +8102,7 @@ static void set_glsl_shader_program(const struct wined3d_context *context, const
 
             shader_glsl_init_uniform_block_bindings(gl_info, priv, program_id, &pshader->reg_maps);
             shader_glsl_load_icb(gl_info, priv, program_id, &pshader->reg_maps);
+            shader_glsl_load_images(gl_info, priv, program_id, &pshader->reg_maps);
         }
         else
         {
diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c
index cd3763c..0c25861 100644
--- a/dlls/wined3d/state.c
+++ b/dlls/wined3d/state.c
@@ -4964,6 +4964,18 @@ static void state_shader_resource_binding(struct wined3d_context *context,
     context->update_shader_resource_bindings = 1;
 }
 
+static void state_uav_binding(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id)
+{
+    TRACE("context %p, state %p, state_id %#x.\n", context, state, state_id);
+    context->update_unordered_access_view_bindings = 1;
+}
+
+static void state_uav_warn(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    WARN("ARB_image_load_store is not supported by OpenGL implementation.\n");
+}
+
 const struct StateEntryTemplate misc_state_template[] =
 {
     { STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_VERTEX),  { STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_VERTEX),  state_cb,           }, ARB_UNIFORM_BUFFER_OBJECT       },
@@ -4973,6 +4985,8 @@ const struct StateEntryTemplate misc_state_template[] =
     { STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_PIXEL),   { STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_PIXEL),   state_cb,           }, ARB_UNIFORM_BUFFER_OBJECT       },
     { STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_PIXEL),   { STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_PIXEL),   state_cb_warn,      }, WINED3D_GL_EXT_NONE             },
     { STATE_SHADER_RESOURCE_BINDING,                      { STATE_SHADER_RESOURCE_BINDING,                      state_shader_resource_binding}, WINED3D_GL_EXT_NONE    },
+    { STATE_UNORDERED_ACCESS_VIEW_BINDING,                { STATE_UNORDERED_ACCESS_VIEW_BINDING,                state_uav_binding   }, ARB_SHADER_IMAGE_LOAD_STORE     },
+    { STATE_UNORDERED_ACCESS_VIEW_BINDING,                { STATE_UNORDERED_ACCESS_VIEW_BINDING,                state_uav_warn      }, WINED3D_GL_EXT_NONE             },
     { STATE_RENDER(WINED3D_RS_SRCBLEND),                  { STATE_RENDER(WINED3D_RS_ALPHABLENDENABLE),          NULL                }, WINED3D_GL_EXT_NONE             },
     { STATE_RENDER(WINED3D_RS_DESTBLEND),                 { STATE_RENDER(WINED3D_RS_ALPHABLENDENABLE),          NULL                }, WINED3D_GL_EXT_NONE             },
     { STATE_RENDER(WINED3D_RS_ALPHABLENDENABLE),          { STATE_RENDER(WINED3D_RS_ALPHABLENDENABLE),          state_blend         }, WINED3D_GL_EXT_NONE             },
diff --git a/dlls/wined3d/stateblock.c b/dlls/wined3d/stateblock.c
index 2fbfa2c..a4a5e8c 100644
--- a/dlls/wined3d/stateblock.c
+++ b/dlls/wined3d/stateblock.c
@@ -424,6 +424,7 @@ ULONG CDECL wined3d_stateblock_incref(struct wined3d_stateblock *stateblock)
 
 void state_unbind_resources(struct wined3d_state *state)
 {
+    struct wined3d_unordered_access_view *uav;
     struct wined3d_shader_resource_view *srv;
     struct wined3d_vertex_declaration *decl;
     struct wined3d_sampler *sampler;
@@ -506,6 +507,15 @@ void state_unbind_resources(struct wined3d_state *state)
             }
         }
     }
+
+    for (i = 0; i < MAX_UNORDERED_ACCESS_VIEWS; ++i)
+    {
+        if ((uav = state->unordered_access_view[i]))
+        {
+            state->unordered_access_view[i] = NULL;
+            wined3d_unordered_access_view_decref(uav);
+        }
+    }
 }
 
 void state_cleanup(struct wined3d_state *state)
diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c
index 1255a9a..c32280c 100644
--- a/dlls/wined3d/utils.c
+++ b/dlls/wined3d/utils.c
@@ -4345,6 +4345,8 @@ const char *debug_d3dstate(DWORD state)
         return wine_dbg_sprintf("STATE_CONSTANT_BUFFER(%s)", debug_shader_type(state - STATE_CONSTANT_BUFFER(0)));
     if (STATE_IS_SHADER_RESOURCE_BINDING(state))
         return "STATE_SHADER_RESOURCE_BINDING";
+    if (STATE_IS_UNORDERED_ACCESS_VIEW_BINDING(state))
+        return "STATE_UNORDERED_ACCESS_VIEW_BINDING";
     if (STATE_IS_TRANSFORM(state))
         return wine_dbg_sprintf("STATE_TRANSFORM(%s)", debug_d3dtstype(state - STATE_TRANSFORM(0)));
     if (STATE_IS_STREAMSRC(state))
diff --git a/dlls/wined3d/view.c b/dlls/wined3d/view.c
index a67c506..59885e5 100644
--- a/dlls/wined3d/view.c
+++ b/dlls/wined3d/view.c
@@ -537,6 +537,14 @@ static HRESULT wined3d_unordered_access_view_init(struct wined3d_unordered_acces
                 || !desc->u.texture.layer_count
                 || desc->u.texture.layer_count > depth_or_layer_count - desc->u.texture.layer_idx)
             return E_INVALIDARG;
+
+        if (desc->u.texture.layer_idx || desc->u.texture.layer_count != depth_or_layer_count)
+        {
+            FIXME("Unordered access view unsupported yet (layers %u-%u).\n",
+                    desc->u.texture.layer_idx, desc->u.texture.layer_count);
+        }
+
+        view->level_idx = desc->u.texture.level_idx;
     }
     wined3d_resource_incref(view->resource = resource);
 
diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec
index b034ba8..34b2d0a 100644
--- a/dlls/wined3d/wined3d.spec
+++ b/dlls/wined3d/wined3d.spec
@@ -145,6 +145,7 @@
 @ cdecl wined3d_device_set_texture(ptr long ptr)
 @ cdecl wined3d_device_set_texture_stage_state(ptr long long long)
 @ cdecl wined3d_device_set_transform(ptr long ptr)
+@ cdecl wined3d_device_set_unordered_access_view(ptr long ptr)
 @ cdecl wined3d_device_set_vertex_declaration(ptr ptr)
 @ cdecl wined3d_device_set_vertex_shader(ptr ptr)
 @ cdecl wined3d_device_set_viewport(ptr ptr)
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 02d2f58..4a68c0e 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1312,7 +1312,10 @@ DWORD get_flexible_vertex_size(DWORD d3dvtVertexType) DECLSPEC_HIDDEN;
 #define STATE_SHADER_RESOURCE_BINDING (STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_COUNT))
 #define STATE_IS_SHADER_RESOURCE_BINDING(a) ((a) == STATE_SHADER_RESOURCE_BINDING)
 
-#define STATE_TRANSFORM(a) (STATE_SHADER_RESOURCE_BINDING + (a))
+#define STATE_UNORDERED_ACCESS_VIEW_BINDING (STATE_SHADER_RESOURCE_BINDING + 1)
+#define STATE_IS_UNORDERED_ACCESS_VIEW_BINDING(a) ((a) == STATE_UNORDERED_ACCESS_VIEW_BINDING)
+
+#define STATE_TRANSFORM(a) (STATE_UNORDERED_ACCESS_VIEW_BINDING + (a))
 #define STATE_IS_TRANSFORM(a) ((a) >= STATE_TRANSFORM(1) && (a) <= STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(255)))
 
 #define STATE_STREAMSRC (STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(255)) + 1)
@@ -1499,8 +1502,9 @@ struct wined3d_context
     DWORD hdc_is_private : 1;
     DWORD hdc_has_format : 1;           /* only meaningful if hdc_is_private */
     DWORD update_shader_resource_bindings : 1;
+    DWORD update_unordered_access_view_bindings : 1;
     DWORD destroy_delayed : 1;
-    DWORD padding : 13;
+    DWORD padding : 12;
     DWORD last_swizzle_map; /* MAX_ATTRIBS, 16 */
     DWORD shader_update_mask;
     DWORD constant_update_mask;
@@ -2402,6 +2406,7 @@ struct wined3d_state
     struct wined3d_buffer *cb[WINED3D_SHADER_TYPE_COUNT][MAX_CONSTANT_BUFFERS];
     struct wined3d_sampler *sampler[WINED3D_SHADER_TYPE_COUNT][MAX_SAMPLER_OBJECTS];
     struct wined3d_shader_resource_view *shader_resource_view[WINED3D_SHADER_TYPE_COUNT][MAX_SHADER_RESOURCE_VIEWS];
+    struct wined3d_unordered_access_view *unordered_access_view[MAX_UNORDERED_ACCESS_VIEWS];
 
     BOOL vs_consts_b[WINED3D_MAX_CONSTS_B];
     struct wined3d_ivec4 vs_consts_i[WINED3D_MAX_CONSTS_I];
@@ -3121,6 +3126,8 @@ void wined3d_cs_emit_set_texture_state(struct wined3d_cs *cs, UINT stage,
         enum wined3d_texture_stage_state state, DWORD value) DECLSPEC_HIDDEN;
 void wined3d_cs_emit_set_transform(struct wined3d_cs *cs, enum wined3d_transform_state state,
         const struct wined3d_matrix *matrix) DECLSPEC_HIDDEN;
+void wined3d_cs_emit_set_unordered_access_view(struct wined3d_cs *cs, unsigned int view_idx,
+        struct wined3d_unordered_access_view *view) DECLSPEC_HIDDEN;
 void wined3d_cs_emit_set_vertex_declaration(struct wined3d_cs *cs,
         struct wined3d_vertex_declaration *declaration) DECLSPEC_HIDDEN;
 void wined3d_cs_emit_set_viewport(struct wined3d_cs *cs, const struct wined3d_viewport *viewport) DECLSPEC_HIDDEN;
@@ -3255,6 +3262,8 @@ struct wined3d_unordered_access_view
     const struct wined3d_parent_ops *parent_ops;
 
     const struct wined3d_format *format;
+
+    unsigned int level_idx;
 };
 
 struct wined3d_swapchain_ops
diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h
index c7ecef1..5091dca 100644
--- a/include/wine/wined3d.h
+++ b/include/wine/wined3d.h
@@ -2330,6 +2330,8 @@ void __cdecl wined3d_device_set_texture_stage_state(struct wined3d_device *devic
         UINT stage, enum wined3d_texture_stage_state state, DWORD value);
 void __cdecl wined3d_device_set_transform(struct wined3d_device *device,
         enum wined3d_transform_state state, const struct wined3d_matrix *matrix);
+void __cdecl wined3d_device_set_unordered_access_view(struct wined3d_device *device,
+        unsigned int idx, struct wined3d_unordered_access_view *uav);
 void __cdecl wined3d_device_set_vertex_declaration(struct wined3d_device *device,
         struct wined3d_vertex_declaration *declaration);
 void __cdecl wined3d_device_set_vertex_shader(struct wined3d_device *device, struct wined3d_shader *shader);
-- 
2.7.3




More information about the wine-patches mailing list