[PATCH 4/7] wined3d: Add initial support for shader buffer views.

Józef Kucia jkucia at codeweavers.com
Thu Mar 24 07:54:40 CDT 2016


Signed-off-by: Józef Kucia <jkucia at codeweavers.com>
---
Tests can still be run with forced SM4.
---
 dlls/d3d10core/tests/device.c  | 32 +++++++++++++++++-
 dlls/d3d11/tests/d3d11.c       |  8 +++++
 dlls/wined3d/context.c         | 18 +++++-----
 dlls/wined3d/view.c            | 76 +++++++++++++++++++++++++++++++++++++++---
 dlls/wined3d/wined3d_private.h |  3 ++
 5 files changed, 123 insertions(+), 14 deletions(-)

diff --git a/dlls/d3d10core/tests/device.c b/dlls/d3d10core/tests/device.c
index ba6f22e..9a87945 100644
--- a/dlls/d3d10core/tests/device.c
+++ b/dlls/d3d10core/tests/device.c
@@ -1394,6 +1394,13 @@ static void test_create_shader_resource_view(void)
 
     expected_refcount = get_refcount((IUnknown *)device) + 1;
     hr = ID3D10Device_CreateShaderResourceView(device, (ID3D10Resource *)buffer, &srv_desc, &srview);
+    /* FIXME: Remove the following if statement once core contexts are supported. */
+    if (hr == E_NOTIMPL)
+    {
+        skip("Buffer resource views are not supported.\n");
+    }
+    else
+    {
     ok(SUCCEEDED(hr), "Failed to create a shader resource view, hr %#x\n", hr);
     refcount = get_refcount((IUnknown *)device);
     ok(refcount >= expected_refcount, "Got unexpected refcount %u, expected >= %u.\n", refcount, expected_refcount);
@@ -1415,6 +1422,7 @@ static void test_create_shader_resource_view(void)
     if (SUCCEEDED(hr)) IUnknown_Release(iface);
 
     ID3D10ShaderResourceView_Release(srview);
+    }
     ID3D10Buffer_Release(buffer);
 
     texture_desc.Width = 512;
@@ -2551,7 +2559,6 @@ float4 main(float4 color : COLOR) : SV_TARGET
     ID3D10BlendState *tmp_blend_state, *blend_state;
     ID3D10RasterizerState *tmp_rs_state, *rs_state;
     ID3D10Predicate *tmp_predicate, *predicate;
-    D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc;
     ID3D10DepthStencilView *tmp_dsv, *dsv;
     D3D10_PRIMITIVE_TOPOLOGY topology;
     D3D10_TEXTURE2D_DESC texture_desc;
@@ -2563,6 +2570,7 @@ float4 main(float4 color : COLOR) : SV_TARGET
     ID3D10PixelShader *tmp_ps, *ps;
     D3D10_RASTERIZER_DESC rs_desc;
     D3D10_BUFFER_DESC buffer_desc;
+    ID3D10Texture2D *srv_texture;
     D3D10_BLEND_DESC blend_desc;
     ID3D10Texture2D *ds_texture;
     float tmp_blend_factor[4];
@@ -2742,6 +2750,7 @@ float4 main(float4 color : COLOR) : SV_TARGET
         ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr);
     }
 
+    /* FIXME: Revert back to buffer views once core contexts are supported.
     srv_desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
     srv_desc.ViewDimension = D3D10_SRV_DIMENSION_BUFFER;
     U(srv_desc).Buffer.ElementOffset = 0;
@@ -2753,6 +2762,25 @@ float4 main(float4 color : COLOR) : SV_TARGET
                 (ID3D10Resource *)buffer[i % D3D10_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT], &srv_desc, &srv[i]);
         ok(SUCCEEDED(hr), "Failed to create shader resource view, hr %#x.\n", hr);
     }
+    */
+    texture_desc.Width = 512;
+    texture_desc.Height = 512;
+    texture_desc.MipLevels = 1;
+    texture_desc.ArraySize = 1;
+    texture_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+    texture_desc.SampleDesc.Count = 1;
+    texture_desc.SampleDesc.Quality = 0;
+    texture_desc.Usage = D3D10_USAGE_DEFAULT;
+    texture_desc.BindFlags = D3D10_BIND_SHADER_RESOURCE;
+    texture_desc.CPUAccessFlags = 0;
+    texture_desc.MiscFlags = 0;
+    hr = ID3D10Device_CreateTexture2D(device, &texture_desc, NULL, &srv_texture);
+    ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
+    for (i = 0; i < D3D10_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; ++i)
+    {
+        hr = ID3D10Device_CreateShaderResourceView(device, (ID3D10Resource *)srv_texture, NULL, &srv[i]);
+        ok(SUCCEEDED(hr), "Failed to create shader resource view, hr %#x.\n", hr);
+    }
 
     sampler_desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR;
     sampler_desc.AddressU = D3D10_TEXTURE_ADDRESS_CLAMP;
@@ -3292,6 +3320,8 @@ float4 main(float4 color : COLOR) : SV_TARGET
     ID3D10GeometryShader_Release(gs);
     ID3D10PixelShader_Release(ps);
 
+    ID3D10Texture2D_Release(srv_texture);
+
     for (i = 0; i < D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT; ++i)
     {
         ID3D10SamplerState_Release(sampler[i]);
diff --git a/dlls/d3d11/tests/d3d11.c b/dlls/d3d11/tests/d3d11.c
index 9348aff..713496b 100644
--- a/dlls/d3d11/tests/d3d11.c
+++ b/dlls/d3d11/tests/d3d11.c
@@ -1858,6 +1858,13 @@ static void test_create_shader_resource_view(void)
 
     expected_refcount = get_refcount((IUnknown *)device) + 1;
     hr = ID3D11Device_CreateShaderResourceView(device, (ID3D11Resource *)buffer, &srv_desc, &srview);
+    /* FIXME: Remove the following if statement once core contexts are supported. */
+    if (hr == E_NOTIMPL)
+    {
+        skip("Buffer resource views are not supported.\n");
+    }
+    else
+    {
     ok(SUCCEEDED(hr), "Failed to create a shader resource view, hr %#x.\n", hr);
     refcount = get_refcount((IUnknown *)device);
     ok(refcount >= expected_refcount, "Got unexpected refcount %u, expected >= %u.\n", refcount, expected_refcount);
@@ -1879,6 +1886,7 @@ static void test_create_shader_resource_view(void)
     if (SUCCEEDED(hr)) IUnknown_Release(iface);
 
     ID3D11ShaderResourceView_Release(srview);
+    }
     ID3D11Buffer_Release(buffer);
 
     texture_desc.Width = 512;
diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c
index 8ae3e32..29f109e 100644
--- a/dlls/wined3d/context.c
+++ b/dlls/wined3d/context.c
@@ -3303,12 +3303,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;
@@ -3323,9 +3317,17 @@ static void context_bind_shader_resources(struct wined3d_context *context, const
                 continue;
             }
 
-            texture = wined3d_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);
+
+            if (view->resource->type == WINED3D_RTYPE_BUFFER)
+            {
+                context_bind_texture(context, view->target, view->object);
+            }
+            else
+            {
+                texture = wined3d_texture_from_resource(view->resource);
+                wined3d_texture_bind(texture, context, FALSE);
+            }
 
             GL_EXTCALL(glBindSampler(shader_types[i].base_idx + entry->bind_idx, sampler_name));
             checkGLcall("glBindSampler");
diff --git a/dlls/wined3d/view.c b/dlls/wined3d/view.c
index 246d8cd..73baf61 100644
--- a/dlls/wined3d/view.c
+++ b/dlls/wined3d/view.c
@@ -182,6 +182,12 @@ ULONG CDECL wined3d_shader_resource_view_decref(struct wined3d_shader_resource_v
         /* 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);
+        if (view->object)
+        {
+            struct wined3d_context *context = context_acquire(view->resource->device, NULL);
+            context->gl_info->gl_ops.gl.p_glDeleteTextures(1, &view->object);
+            context_release(context);
+        }
         wined3d_resource_decref(view->resource);
         HeapFree(GetProcessHeap(), 0, view);
     }
@@ -196,11 +202,71 @@ void * CDECL wined3d_shader_resource_view_get_parent(const struct wined3d_shader
     return view->parent;
 }
 
+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)
+{
+    view->refcount = 1;
+    view->resource = resource;
+    view->parent = parent;
+    view->parent_ops = parent_ops;
+
+    if (resource->type == WINED3D_RTYPE_BUFFER)
+    {
+        struct wined3d_context *context = context_acquire(resource->device, NULL);
+        struct wined3d_buffer *buffer = buffer_from_resource(resource);
+        const struct wined3d_gl_info *gl_info = context->gl_info;
+        const struct wined3d_format *format;
+        struct wined3d_bo_address bo;
+
+        if (!gl_info->supported[ARB_TEXTURE_BUFFER_OBJECT])
+        {
+            FIXME("No hardware support for buffer textures.\n");
+            context_release(context);
+            return E_NOTIMPL;
+        }
+
+        format = wined3d_get_format(gl_info, desc->format_id);
+
+        buffer_get_memory(buffer, context, &bo);
+        if (!bo.buffer_object)
+        {
+            FIXME("Could not get buffer object for buffer %p.\n", buffer);
+            context_release(context);
+            return E_NOTIMPL;
+        }
+        /* Support for buffer offsets can be implemented using ARB_texture_buffer_range. */
+        if (bo.addr)
+            FIXME("Ignoring buffer offset %p.\n", bo.addr);
+
+        view->target = GL_TEXTURE_BUFFER;
+        gl_info->gl_ops.gl.p_glGenTextures(1, &view->object);
+        checkGLcall("glGenTextures");
+
+        context_bind_texture(context, GL_TEXTURE_BUFFER, view->object);
+        GL_EXTCALL(glTexBuffer(GL_TEXTURE_BUFFER, format->glInternal, bo.buffer_object));
+        checkGLcall("glTexBuffer");
+
+        context_invalidate_state(context, STATE_SHADER_RESOURCE_BINDING);
+
+        context_release(context);
+    }
+    else
+    {
+        view->target = GL_NONE;
+        view->object = 0;
+    }
+
+    wined3d_resource_incref(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);
@@ -208,11 +274,11 @@ 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);
+        return hr;
+    }
 
     TRACE("Created shader resource view %p.\n", object);
     *view = object;
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index dc4330f..4a96ce8 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2944,6 +2944,9 @@ struct wined3d_shader_resource_view
     struct wined3d_resource *resource;
     void *parent;
     const struct wined3d_parent_ops *parent_ops;
+
+    GLenum target;
+    GLuint object;
 };
 
 struct wined3d_swapchain_ops
-- 
2.4.10




More information about the wine-patches mailing list