[PATCH v2 5/5] wined3d: Create texture views for shader resource views.

Józef Kucia jkucia at codeweavers.com
Tue Jun 7 06:24:39 CDT 2016


Signed-off-by: Józef Kucia <jkucia at codeweavers.com>
---
Version 2:
* Use the GL view class to decide if a GL texture view should be created.
* Use "flags" instead of "view_type" from "wined3d_shader_resource_view_desc".
* Forbid to create views for typeless formats.
* Do not "hide" context_acquire() in declarations.
---
 dlls/wined3d/context.c         |  11 +--
 dlls/wined3d/utils.c           |   1 +
 dlls/wined3d/view.c            | 164 +++++++++++++++++++++++++++++++++++++++--
 dlls/wined3d/wined3d_private.h |   7 ++
 4 files changed, 168 insertions(+), 15 deletions(-)

diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c
index 389ae98..04265d0 100644
--- a/dlls/wined3d/context.c
+++ b/dlls/wined3d/context.c
@@ -3292,7 +3292,6 @@ static void context_bind_shader_resources(struct wined3d_context *context, const
     struct wined3d_shader_sampler_map_entry *entry;
     struct wined3d_shader_resource_view *view;
     struct wined3d_sampler *sampler;
-    struct wined3d_texture *texture;
     struct wined3d_shader *shader;
     unsigned int i, j, count;
     GLuint sampler_name;
@@ -3332,12 +3331,6 @@ static void context_bind_shader_resources(struct wined3d_context *context, const
                 continue;
             }
 
-            if (view->resource->type == WINED3D_RTYPE_BUFFER)
-            {
-                FIXME("Buffer shader resources not supported.\n");
-                continue;
-            }
-
             if (entry->sampler_idx == WINED3D_SAMPLER_DEFAULT)
                 sampler_name = device->default_sampler;
             else if ((sampler = state->sampler[shader_types[i].type][entry->sampler_idx]))
@@ -3345,12 +3338,10 @@ static void context_bind_shader_resources(struct wined3d_context *context, const
             else
                 sampler_name = device->null_sampler;
 
-            texture = texture_from_resource(view->resource);
             context_active_texture(context, gl_info, shader_types[i].base_idx + entry->bind_idx);
-            wined3d_texture_bind(texture, context, FALSE);
-
             GL_EXTCALL(glBindSampler(shader_types[i].base_idx + entry->bind_idx, sampler_name));
             checkGLcall("glBindSampler");
+            wined3d_shader_resource_view_bind(view, context);
         }
     }
 }
diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c
index aa2c775..878de10 100644
--- a/dlls/wined3d/utils.c
+++ b/dlls/wined3d/utils.c
@@ -1667,6 +1667,7 @@ static BOOL init_format_base_info(struct wined3d_gl_info *gl_info)
         format->block_width = typeless_format->block_width;
         format->block_height = typeless_format->block_height;
         format->block_byte_count = typeless_format->block_byte_count;
+        format->typeless_id = typeless_format->id;
 
         for (j = 0; j < strlen(typed_formats[i].channels); ++j)
         {
diff --git a/dlls/wined3d/view.c b/dlls/wined3d/view.c
index b12edec..1604443 100644
--- a/dlls/wined3d/view.c
+++ b/dlls/wined3d/view.c
@@ -185,6 +185,17 @@ ULONG CDECL wined3d_shader_resource_view_decref(struct wined3d_shader_resource_v
 
     if (!refcount)
     {
+        if (view->object)
+        {
+            const struct wined3d_gl_info *gl_info;
+            struct wined3d_context *context;
+
+            context = context_acquire(view->resource->device, NULL);
+            gl_info = context->gl_info;
+            gl_info->gl_ops.gl.p_glDeleteTextures(1, &view->object);
+            checkGLcall("glDeleteTextures");
+            context_release(context);
+        }
         /* Call wined3d_object_destroyed() before releasing the resource,
          * since releasing the resource may end up destroying the parent. */
         view->parent_ops->wined3d_object_destroyed(view->parent);
@@ -202,11 +213,132 @@ void * CDECL wined3d_shader_resource_view_get_parent(const struct wined3d_shader
     return view->parent;
 }
 
+static void wined3d_shader_resource_view_create_texture_view(struct wined3d_shader_resource_view *view,
+        const struct wined3d_shader_resource_view_desc *desc, struct wined3d_texture *texture,
+        const struct wined3d_format *view_format)
+{
+    const struct wined3d_gl_info *gl_info;
+    struct wined3d_context *context;
+    struct gl_texture *gl_texture;
+
+    context = context_acquire(texture->resource.device, NULL);
+    gl_info = context->gl_info;
+
+    if (!gl_info->supported[ARB_TEXTURE_VIEW])
+    {
+        context_release(context);
+        FIXME("OpenGL implementation does not support texture views.\n");
+        return;
+    }
+
+    wined3d_texture_prepare_texture(texture, context, FALSE);
+    gl_texture = wined3d_texture_get_gl_texture(texture, FALSE);
+
+    gl_info->gl_ops.gl.p_glGenTextures(1, &view->object);
+    GL_EXTCALL(glTextureView(view->object, view->target, gl_texture->name, view_format->glInternal,
+            desc->u.texture.level_idx, desc->u.texture.level_count,
+            desc->u.texture.layer_idx, desc->u.texture.layer_count));
+    checkGLcall("Create texture view");
+
+    context_release(context);
+}
+
+static HRESULT wined3d_shader_resource_view_init(struct wined3d_shader_resource_view *view,
+        const struct wined3d_shader_resource_view_desc *desc, struct wined3d_resource *resource,
+        void *parent, const struct wined3d_parent_ops *parent_ops)
+{
+    static const struct
+    {
+        GLenum texture_target;
+        unsigned int view_flags;
+        GLenum view_target;
+    }
+    view_types[] =
+    {
+        {GL_TEXTURE_2D,       0,                          GL_TEXTURE_2D},
+        {GL_TEXTURE_2D,       WINED3D_VIEW_TEXTURE_ARRAY, GL_TEXTURE_2D_ARRAY},
+        {GL_TEXTURE_2D_ARRAY, 0,                          GL_TEXTURE_2D},
+        {GL_TEXTURE_2D_ARRAY, WINED3D_VIEW_TEXTURE_ARRAY, GL_TEXTURE_2D_ARRAY},
+        {GL_TEXTURE_2D_ARRAY, WINED3D_VIEW_TEXTURE_CUBE,  GL_TEXTURE_CUBE_MAP},
+        {GL_TEXTURE_3D,       0,                          GL_TEXTURE_3D},
+    };
+
+    const struct wined3d_gl_info *gl_info = &resource->device->adapter->gl_info;
+    const struct wined3d_format *view_format;
+
+    view_format = wined3d_get_format(gl_info, desc->format_id);
+    if (view_format->id == view_format->typeless_id)
+    {
+        WARN("Trying to create view for typeless format %s.\n", debug_d3dformat(view_format->id));
+        return E_FAIL;
+    }
+
+    view->refcount = 1;
+    view->parent = parent;
+    view->parent_ops = parent_ops;
+
+    view->target = GL_NONE;
+    view->object = 0;
+
+    if (resource->type == WINED3D_RTYPE_BUFFER)
+    {
+        FIXME("Buffer shader resource views not supported.\n");
+    }
+    else
+    {
+        struct wined3d_texture *texture = texture_from_resource(resource);
+        unsigned int i;
+
+        if (desc->u.texture.level_idx >= texture->level_count
+                || desc->u.texture.level_count > texture->level_count - desc->u.texture.level_idx
+                || desc->u.texture.layer_idx >= texture->layer_count
+                || desc->u.texture.layer_count > texture->layer_count - desc->u.texture.layer_idx)
+            return E_FAIL;
+
+        view->target = texture->target;
+        for (i = 0; i < ARRAY_SIZE(view_types); ++i)
+        {
+            if (view_types[i].texture_target == texture->target && view_types[i].view_flags == desc->flags)
+            {
+                view->target = view_types[i].view_target;
+                break;
+            }
+        }
+        if (i == ARRAY_SIZE(view_types))
+            FIXME("Unhandled view flags %#x for texture target %#x.\n", desc->flags, texture->target);
+
+        if (resource->format->id == view_format->id && texture->target == view->target
+                && !desc->u.texture.level_idx && desc->u.texture.level_count == texture->level_count
+                && !desc->u.texture.layer_idx && desc->u.texture.layer_count == texture->layer_count)
+        {
+            TRACE("Creating identity shader resource view.\n");
+        }
+        else if (texture->swapchain && texture->swapchain->desc.backbuffer_count > 1)
+        {
+            FIXME("Swapchain shader resource views not supported.\n");
+        }
+        else if (resource->format->typeless_id == view_format->typeless_id
+                && resource->format->gl_view_class == view_format->gl_view_class)
+        {
+            wined3d_shader_resource_view_create_texture_view(view, desc, texture, view_format);
+        }
+        else
+        {
+            FIXME("Shader resource view not supported, resource format %s, view format %s.\n",
+                    debug_d3dformat(resource->format->id), debug_d3dformat(view_format->id));
+        }
+    }
+    wined3d_resource_incref(view->resource = resource);
+
+    return WINED3D_OK;
+}
+
 HRESULT CDECL wined3d_shader_resource_view_create(const struct wined3d_shader_resource_view_desc *desc,
         struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops,
         struct wined3d_shader_resource_view **view)
 {
     struct wined3d_shader_resource_view *object;
+    HRESULT hr;
 
     TRACE("desc %p, resource %p, parent %p, parent_ops %p, view %p.\n",
             desc, resource, parent, parent_ops, view);
@@ -214,14 +346,36 @@ HRESULT CDECL wined3d_shader_resource_view_create(const struct wined3d_shader_re
     if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
         return E_OUTOFMEMORY;
 
-    object->refcount = 1;
-    object->resource = resource;
-    wined3d_resource_incref(resource);
-    object->parent = parent;
-    object->parent_ops = parent_ops;
+    if (FAILED(hr = wined3d_shader_resource_view_init(object, desc, resource, parent, parent_ops)))
+    {
+        HeapFree(GetProcessHeap(), 0, object);
+        WARN("Failed to initialise view, hr %#x.\n", hr);
+        return hr;
+    }
 
     TRACE("Created shader resource view %p.\n", object);
     *view = object;
 
     return WINED3D_OK;
 }
+
+void wined3d_shader_resource_view_bind(struct wined3d_shader_resource_view *view,
+        struct wined3d_context *context)
+{
+    struct wined3d_texture *texture;
+
+    if (view->object)
+    {
+        context_bind_texture(context, view->target, view->object);
+        return;
+    }
+
+    if (view->resource->type == WINED3D_RTYPE_BUFFER)
+    {
+        FIXME("Buffer shader resources not supported.\n");
+        return;
+    }
+
+    texture = wined3d_texture_from_resource(view->resource);
+    wined3d_texture_bind(texture, context, FALSE);
+}
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 2d921f3..b4bc901 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -3082,8 +3082,14 @@ struct wined3d_shader_resource_view
     struct wined3d_resource *resource;
     void *parent;
     const struct wined3d_parent_ops *parent_ops;
+
+    GLenum target;
+    GLuint object;
 };
 
+void wined3d_shader_resource_view_bind(struct wined3d_shader_resource_view *view,
+        struct wined3d_context *context) DECLSPEC_HIDDEN;
+
 struct wined3d_swapchain_ops
 {
     void (*swapchain_present)(struct wined3d_swapchain *swapchain,
@@ -3538,6 +3544,7 @@ struct wined3d_format
     void (*convert)(const BYTE *src, BYTE *dst, UINT src_row_pitch, UINT src_slice_pitch,
             UINT dst_row_pitch, UINT dst_slice_pitch, UINT width, UINT height, UINT depth);
 
+    enum wined3d_format_id typeless_id;
     GLenum gl_view_class;
 };
 
-- 
2.7.3




More information about the wine-patches mailing list