[PATCH v2 5/6] d3d11: Implement constant buffer offsetting for OpenGL.

Zebediah Figura zfigura at codeweavers.com
Thu Jul 8 17:00:58 CDT 2021


Based on a patch by Kimmo Myllyvirta.

Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
---
I'm working on the Vulkan part; I'll submit it separately.

 dlls/d3d11/device.c            | 147 ++++++++++++++++++++++++---------
 dlls/wined3d/context_gl.c      |   4 +-
 dlls/wined3d/context_vk.c      |   4 +-
 dlls/wined3d/cs.c              |  18 ++--
 dlls/wined3d/device.c          |  16 ++--
 dlls/wined3d/state.c           |   9 +-
 dlls/wined3d/stateblock.c      |  12 ++-
 dlls/wined3d/wined3d.spec      |   2 +-
 dlls/wined3d/wined3d_private.h |   4 +-
 include/wine/wined3d.h         |  14 +++-
 10 files changed, 158 insertions(+), 72 deletions(-)

diff --git a/dlls/d3d11/device.c b/dlls/d3d11/device.c
index fc34421f082..c2ad85217f8 100644
--- a/dlls/d3d11/device.c
+++ b/dlls/d3d11/device.c
@@ -534,8 +534,9 @@ static ULONG STDMETHODCALLTYPE d3d11_device_context_Release(ID3D11DeviceContext1
     return refcount;
 }
 
-static void d3d11_device_context_get_constant_buffers(ID3D11DeviceContext1 *iface,
-        enum wined3d_shader_type type, UINT start_slot, UINT buffer_count, ID3D11Buffer **buffers)
+static void d3d11_device_context_get_constant_buffers(ID3D11DeviceContext1 *iface, enum wined3d_shader_type type,
+        unsigned int start_slot, unsigned int buffer_count, ID3D11Buffer **buffers,
+        unsigned int *offsets, unsigned int *counts)
 {
     struct d3d11_device_context *context = impl_from_ID3D11DeviceContext1(iface);
     unsigned int i;
@@ -543,17 +544,23 @@ static void d3d11_device_context_get_constant_buffers(ID3D11DeviceContext1 *ifac
     wined3d_mutex_lock();
     for (i = 0; i < buffer_count; ++i)
     {
-        struct wined3d_buffer *wined3d_buffer;
+        struct wined3d_constant_buffer_state state;
         struct d3d_buffer *buffer_impl;
 
-        if (!(wined3d_buffer = wined3d_device_context_get_constant_buffer(context->wined3d_context,
-                type, start_slot + i)))
+        wined3d_device_context_get_constant_buffer(context->wined3d_context, type, start_slot + i, &state);
+
+        if (offsets)
+            offsets[i] = state.offset / sizeof(struct wined3d_vec4);
+        if (counts)
+            counts[i] = state.size / sizeof(struct wined3d_vec4);
+
+        if (!state.buffer)
         {
             buffers[i] = NULL;
             continue;
         }
 
-        buffer_impl = wined3d_buffer_get_parent(wined3d_buffer);
+        buffer_impl = wined3d_buffer_get_parent(state.buffer);
         buffers[i] = &buffer_impl->ID3D11Buffer_iface;
         ID3D11Buffer_AddRef(buffers[i]);
     }
@@ -561,9 +568,11 @@ static void d3d11_device_context_get_constant_buffers(ID3D11DeviceContext1 *ifac
 }
 
 static void d3d11_device_context_set_constant_buffers(ID3D11DeviceContext1 *iface, enum wined3d_shader_type type,
-        unsigned int start_slot, unsigned int buffer_count, ID3D11Buffer *const *buffers)
+        unsigned int start_slot, unsigned int buffer_count, ID3D11Buffer *const *buffers,
+        const unsigned int *offsets, const unsigned int *counts)
 {
-    struct wined3d_buffer *wined3d_buffers[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT];
+    static const unsigned int alignment = D3D11_COMMONSHADER_CONSTANT_BUFFER_PARTIAL_UPDATE_EXTENTS_BYTE_ALIGNMENT;
+    struct wined3d_constant_buffer_state wined3d_buffers[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT];
     struct d3d11_device_context *context = impl_from_ID3D11DeviceContext1(iface);
     unsigned int i;
 
@@ -573,11 +582,31 @@ static void d3d11_device_context_set_constant_buffers(ID3D11DeviceContext1 *ifac
         return;
     }
 
+    if (!offsets != !counts)
+    {
+        WARN("Got offsets pointer %p but counts pointer %p; ignoring call.\n", offsets, counts);
+        return;
+    }
+
     for (i = 0; i < buffer_count; ++i)
     {
         struct d3d_buffer *buffer = unsafe_impl_from_ID3D11Buffer(buffers[i]);
 
-        wined3d_buffers[i] = buffer ? buffer->wined3d_buffer : NULL;
+        if (offsets && (offsets[i] & (alignment - 1)))
+        {
+            WARN("Offset %u is not aligned.\n", offsets[i]);
+            return;
+        }
+
+        if (counts && (counts[i] & (alignment - 1)))
+        {
+            WARN("Count %u is not aligned.\n", counts[i]);
+            return;
+        }
+
+        wined3d_buffers[i].buffer = buffer ? buffer->wined3d_buffer : NULL;
+        wined3d_buffers[i].offset = (offsets ? offsets[i] : 0) * sizeof(struct wined3d_vec4);
+        wined3d_buffers[i].size = (counts ? counts[i] : WINED3D_MAX_CONSTANT_BUFFER_SIZE) * sizeof(struct wined3d_vec4);
     }
 
     wined3d_mutex_lock();
@@ -684,7 +713,7 @@ static void STDMETHODCALLTYPE d3d11_device_context_VSSetConstantBuffers(ID3D11De
             iface, start_slot, buffer_count, buffers);
 
     d3d11_device_context_set_constant_buffers(iface, WINED3D_SHADER_TYPE_VERTEX, start_slot,
-            buffer_count, buffers);
+            buffer_count, buffers, NULL, NULL);
 }
 
 static void STDMETHODCALLTYPE d3d11_device_context_PSSetShaderResources(ID3D11DeviceContext1 *iface,
@@ -822,7 +851,7 @@ static void STDMETHODCALLTYPE d3d11_device_context_PSSetConstantBuffers(ID3D11De
             iface, start_slot, buffer_count, buffers);
 
     d3d11_device_context_set_constant_buffers(iface, WINED3D_SHADER_TYPE_PIXEL, start_slot,
-            buffer_count, buffers);
+            buffer_count, buffers, NULL, NULL);
 }
 
 static void STDMETHODCALLTYPE d3d11_device_context_IASetInputLayout(ID3D11DeviceContext1 *iface,
@@ -926,7 +955,7 @@ static void STDMETHODCALLTYPE d3d11_device_context_GSSetConstantBuffers(ID3D11De
             iface, start_slot, buffer_count, buffers);
 
     d3d11_device_context_set_constant_buffers(iface, WINED3D_SHADER_TYPE_GEOMETRY, start_slot,
-            buffer_count, buffers);
+            buffer_count, buffers, NULL, NULL);
 }
 
 static void STDMETHODCALLTYPE d3d11_device_context_GSSetShader(ID3D11DeviceContext1 *iface,
@@ -1604,7 +1633,7 @@ static void STDMETHODCALLTYPE d3d11_device_context_HSSetConstantBuffers(ID3D11De
             iface, start_slot, buffer_count, buffers);
 
     d3d11_device_context_set_constant_buffers(iface, WINED3D_SHADER_TYPE_HULL, start_slot,
-            buffer_count, buffers);
+            buffer_count, buffers, NULL, NULL);
 }
 
 static void STDMETHODCALLTYPE d3d11_device_context_DSSetShaderResources(ID3D11DeviceContext1 *iface,
@@ -1650,7 +1679,7 @@ static void STDMETHODCALLTYPE d3d11_device_context_DSSetConstantBuffers(ID3D11De
             iface, start_slot, buffer_count, buffers);
 
     d3d11_device_context_set_constant_buffers(iface, WINED3D_SHADER_TYPE_DOMAIN, start_slot,
-            buffer_count, buffers);
+            buffer_count, buffers, NULL, NULL);
 }
 
 static void STDMETHODCALLTYPE d3d11_device_context_CSSetShaderResources(ID3D11DeviceContext1 *iface,
@@ -1725,7 +1754,7 @@ static void STDMETHODCALLTYPE d3d11_device_context_CSSetConstantBuffers(ID3D11De
             iface, start_slot, buffer_count, buffers);
 
     d3d11_device_context_set_constant_buffers(iface, WINED3D_SHADER_TYPE_COMPUTE, start_slot,
-            buffer_count, buffers);
+            buffer_count, buffers, NULL, NULL);
 }
 
 static void STDMETHODCALLTYPE d3d11_device_context_VSGetConstantBuffers(ID3D11DeviceContext1 *iface,
@@ -1735,7 +1764,7 @@ static void STDMETHODCALLTYPE d3d11_device_context_VSGetConstantBuffers(ID3D11De
             iface, start_slot, buffer_count, buffers);
 
     d3d11_device_context_get_constant_buffers(iface, WINED3D_SHADER_TYPE_VERTEX, start_slot,
-            buffer_count, buffers);
+            buffer_count, buffers, NULL, NULL);
 }
 
 static void STDMETHODCALLTYPE d3d11_device_context_PSGetShaderResources(ID3D11DeviceContext1 *iface,
@@ -1861,7 +1890,7 @@ static void STDMETHODCALLTYPE d3d11_device_context_PSGetConstantBuffers(ID3D11De
             iface, start_slot, buffer_count, buffers);
 
     d3d11_device_context_get_constant_buffers(iface, WINED3D_SHADER_TYPE_PIXEL, start_slot,
-            buffer_count, buffers);
+            buffer_count, buffers, NULL, NULL);
 }
 
 static void STDMETHODCALLTYPE d3d11_device_context_IAGetInputLayout(ID3D11DeviceContext1 *iface,
@@ -1956,7 +1985,7 @@ static void STDMETHODCALLTYPE d3d11_device_context_GSGetConstantBuffers(ID3D11De
             iface, start_slot, buffer_count, buffers);
 
     d3d11_device_context_get_constant_buffers(iface, WINED3D_SHADER_TYPE_GEOMETRY, start_slot,
-            buffer_count, buffers);
+            buffer_count, buffers, NULL, NULL);
 }
 
 static void STDMETHODCALLTYPE d3d11_device_context_GSGetShader(ID3D11DeviceContext1 *iface,
@@ -2476,7 +2505,7 @@ static void STDMETHODCALLTYPE d3d11_device_context_HSGetConstantBuffers(ID3D11De
             iface, start_slot, buffer_count, buffers);
 
     d3d11_device_context_get_constant_buffers(iface, WINED3D_SHADER_TYPE_HULL, start_slot,
-            buffer_count, buffers);
+            buffer_count, buffers, NULL, NULL);
 }
 
 static void STDMETHODCALLTYPE d3d11_device_context_DSGetShaderResources(ID3D11DeviceContext1 *iface,
@@ -2570,7 +2599,7 @@ static void STDMETHODCALLTYPE d3d11_device_context_DSGetConstantBuffers(ID3D11De
             iface, start_slot, buffer_count, buffers);
 
     d3d11_device_context_get_constant_buffers(iface, WINED3D_SHADER_TYPE_DOMAIN, start_slot,
-            buffer_count, buffers);
+            buffer_count, buffers, NULL, NULL);
 }
 
 static void STDMETHODCALLTYPE d3d11_device_context_CSGetShaderResources(ID3D11DeviceContext1 *iface,
@@ -2690,7 +2719,7 @@ static void STDMETHODCALLTYPE d3d11_device_context_CSGetConstantBuffers(ID3D11De
             iface, start_slot, buffer_count, buffers);
 
     d3d11_device_context_get_constant_buffers(iface, WINED3D_SHADER_TYPE_COMPUTE, start_slot,
-            buffer_count, buffers);
+            buffer_count, buffers, NULL, NULL);
 }
 
 static void STDMETHODCALLTYPE d3d11_device_context_ClearState(ID3D11DeviceContext1 *iface)
@@ -2839,90 +2868,126 @@ static void STDMETHODCALLTYPE d3d11_device_context_VSSetConstantBuffers1(ID3D11D
         UINT start_slot, UINT buffer_count, ID3D11Buffer * const *buffers, const UINT *first_constant,
         const UINT *num_constants)
 {
-    FIXME("iface %p, start_slot %u, buffer_count %u, buffers %p, first_constant %p, num_constants %p stub!\n",
+    TRACE("iface %p, start_slot %u, buffer_count %u, buffers %p, first_constant %p, num_constants %p.\n",
             iface, start_slot, buffer_count, buffers, first_constant, num_constants);
+
+    d3d11_device_context_set_constant_buffers(iface, WINED3D_SHADER_TYPE_VERTEX, start_slot,
+            buffer_count, buffers, first_constant, num_constants);
 }
 
 static void STDMETHODCALLTYPE d3d11_device_context_HSSetConstantBuffers1(ID3D11DeviceContext1 *iface,
         UINT start_slot, UINT buffer_count, ID3D11Buffer * const *buffers, const UINT *first_constant,
         const UINT *num_constants)
 {
-    FIXME("iface %p, start_slot %u, buffer_count %u, buffers %p, first_constant %p, num_constants %p stub!\n",
+    TRACE("iface %p, start_slot %u, buffer_count %u, buffers %p, first_constant %p, num_constants %p.\n",
             iface, start_slot, buffer_count, buffers, first_constant, num_constants);
+
+    d3d11_device_context_set_constant_buffers(iface, WINED3D_SHADER_TYPE_HULL, start_slot,
+            buffer_count, buffers, first_constant, num_constants);
 }
 
 static void STDMETHODCALLTYPE d3d11_device_context_DSSetConstantBuffers1(ID3D11DeviceContext1 *iface,
         UINT start_slot, UINT buffer_count, ID3D11Buffer * const *buffers, const UINT *first_constant,
         const UINT *num_constants)
 {
-    FIXME("iface %p, start_slot %u, buffer_count %u, buffers %p, first_constant %p, num_constants %p stub!\n",
+    TRACE("iface %p, start_slot %u, buffer_count %u, buffers %p, first_constant %p, num_constants %p.\n",
             iface, start_slot, buffer_count, buffers, first_constant, num_constants);
+
+    d3d11_device_context_set_constant_buffers(iface, WINED3D_SHADER_TYPE_DOMAIN, start_slot,
+            buffer_count, buffers, first_constant, num_constants);
 }
 
 static void STDMETHODCALLTYPE d3d11_device_context_GSSetConstantBuffers1(ID3D11DeviceContext1 *iface,
         UINT start_slot, UINT buffer_count, ID3D11Buffer * const *buffers, const UINT *first_constant,
         const UINT *num_constants)
 {
-    FIXME("iface %p, start_slot %u, buffer_count %u, buffers %p, first_constant %p, num_constants %p stub!\n",
+    TRACE("iface %p, start_slot %u, buffer_count %u, buffers %p, first_constant %p, num_constants %p.\n",
             iface, start_slot, buffer_count, buffers, first_constant, num_constants);
+
+    d3d11_device_context_set_constant_buffers(iface, WINED3D_SHADER_TYPE_GEOMETRY, start_slot,
+            buffer_count, buffers, first_constant, num_constants);
 }
 
 static void STDMETHODCALLTYPE d3d11_device_context_PSSetConstantBuffers1(ID3D11DeviceContext1 *iface,
         UINT start_slot, UINT buffer_count, ID3D11Buffer * const *buffers, const UINT *first_constant,
         const UINT *num_constants)
 {
-    FIXME("iface %p, start_slot %u, buffer_count %u, buffers %p, first_constant %p, num_constants %p stub!\n",
+    TRACE("iface %p, start_slot %u, buffer_count %u, buffers %p, first_constant %p, num_constants %p.\n",
             iface, start_slot, buffer_count, buffers, first_constant, num_constants);
+
+    d3d11_device_context_set_constant_buffers(iface, WINED3D_SHADER_TYPE_PIXEL, start_slot,
+            buffer_count, buffers, first_constant, num_constants);
 }
 
 static void STDMETHODCALLTYPE d3d11_device_context_CSSetConstantBuffers1(ID3D11DeviceContext1 *iface,
         UINT start_slot, UINT buffer_count, ID3D11Buffer * const *buffers, const UINT *first_constant,
         const UINT *num_constants)
 {
-    FIXME("iface %p, start_slot %u, buffer_count %u, buffers %p, first_constant %p, num_constants %p stub!\n",
+    TRACE("iface %p, start_slot %u, buffer_count %u, buffers %p, first_constant %p, num_constants %p.\n",
             iface, start_slot, buffer_count, buffers, first_constant, num_constants);
+
+    d3d11_device_context_set_constant_buffers(iface, WINED3D_SHADER_TYPE_COMPUTE, start_slot,
+            buffer_count, buffers, first_constant, num_constants);
 }
 
 static void STDMETHODCALLTYPE d3d11_device_context_VSGetConstantBuffers1(ID3D11DeviceContext1 *iface,
         UINT start_slot, UINT buffer_count, ID3D11Buffer **buffers, UINT *first_constant, UINT *num_constants)
 {
-    FIXME("iface %p, start_slot %u, buffer_count %u, buffers %p, first_constant %p, num_constants %p stub!\n",
+    TRACE("iface %p, start_slot %u, buffer_count %u, buffers %p, first_constant %p, num_constants %p.\n",
             iface, start_slot, buffer_count, buffers, first_constant, num_constants);
+
+    d3d11_device_context_get_constant_buffers(iface, WINED3D_SHADER_TYPE_VERTEX, start_slot,
+            buffer_count, buffers, first_constant, num_constants);
 }
 
 static void STDMETHODCALLTYPE d3d11_device_context_HSGetConstantBuffers1(ID3D11DeviceContext1 *iface,
         UINT start_slot, UINT buffer_count, ID3D11Buffer **buffers, UINT *first_constant, UINT *num_constants)
 {
-    FIXME("iface %p, start_slot %u, buffer_count %u, buffers %p, first_constant %p, num_constants %p stub!\n",
+    TRACE("iface %p, start_slot %u, buffer_count %u, buffers %p, first_constant %p, num_constants %p.\n",
             iface, start_slot, buffer_count, buffers, first_constant, num_constants);
+
+    d3d11_device_context_get_constant_buffers(iface, WINED3D_SHADER_TYPE_HULL, start_slot,
+            buffer_count, buffers, first_constant, num_constants);
 }
 
 static void STDMETHODCALLTYPE d3d11_device_context_DSGetConstantBuffers1(ID3D11DeviceContext1 *iface,
         UINT start_slot, UINT buffer_count, ID3D11Buffer **buffers, UINT *first_constant, UINT *num_constants)
 {
-    FIXME("iface %p, start_slot %u, buffer_count %u, buffers %p, first_constant %p, num_constants %p stub!\n",
+    TRACE("iface %p, start_slot %u, buffer_count %u, buffers %p, first_constant %p, num_constants %p.\n",
             iface, start_slot, buffer_count, buffers, first_constant, num_constants);
+
+    d3d11_device_context_get_constant_buffers(iface, WINED3D_SHADER_TYPE_DOMAIN, start_slot,
+            buffer_count, buffers, first_constant, num_constants);
 }
 
 static void STDMETHODCALLTYPE d3d11_device_context_GSGetConstantBuffers1(ID3D11DeviceContext1 *iface,
         UINT start_slot, UINT buffer_count, ID3D11Buffer **buffers, UINT *first_constant, UINT *num_constants)
 {
-    FIXME("iface %p, start_slot %u, buffer_count %u, buffers %p, first_constant %p, num_constants %p stub!\n",
+    TRACE("iface %p, start_slot %u, buffer_count %u, buffers %p, first_constant %p, num_constants %p.\n",
             iface, start_slot, buffer_count, buffers, first_constant, num_constants);
+
+    d3d11_device_context_get_constant_buffers(iface, WINED3D_SHADER_TYPE_GEOMETRY, start_slot,
+            buffer_count, buffers, first_constant, num_constants);
 }
 
 static void STDMETHODCALLTYPE d3d11_device_context_PSGetConstantBuffers1(ID3D11DeviceContext1 *iface,
         UINT start_slot, UINT buffer_count, ID3D11Buffer **buffers, UINT *first_constant, UINT *num_constants)
 {
-    FIXME("iface %p, start_slot %u, buffer_count %u, buffers %p, first_constant %p, num_constants %p stub!\n",
+    TRACE("iface %p, start_slot %u, buffer_count %u, buffers %p, first_constant %p, num_constants %p.\n",
             iface, start_slot, buffer_count, buffers, first_constant, num_constants);
+
+    d3d11_device_context_get_constant_buffers(iface, WINED3D_SHADER_TYPE_PIXEL, start_slot,
+            buffer_count, buffers, first_constant, num_constants);
 }
 
 static void STDMETHODCALLTYPE d3d11_device_context_CSGetConstantBuffers1(ID3D11DeviceContext1 *iface,
         UINT start_slot, UINT buffer_count, ID3D11Buffer **buffers, UINT *first_constant, UINT *num_constants)
 {
-    FIXME("iface %p, start_slot %u, buffer_count %u, buffers %p, first_constant %p, num_constants %p stub!\n",
+    TRACE("iface %p, start_slot %u, buffer_count %u, buffers %p, first_constant %p, num_constants %p.\n",
             iface, start_slot, buffer_count, buffers, first_constant, num_constants);
+
+    d3d11_device_context_get_constant_buffers(iface, WINED3D_SHADER_TYPE_COMPUTE, start_slot,
+            buffer_count, buffers, first_constant, num_constants);
 }
 
 static void STDMETHODCALLTYPE d3d11_device_context_SwapDeviceContextState(ID3D11DeviceContext1 *iface,
@@ -4506,17 +4571,19 @@ static void d3d10_device_get_constant_buffers(ID3D10Device1 *iface,
     wined3d_mutex_lock();
     for (i = 0; i < buffer_count; ++i)
     {
-        struct wined3d_buffer *wined3d_buffer;
+        struct wined3d_constant_buffer_state state;
         struct d3d_buffer *buffer_impl;
 
-        if (!(wined3d_buffer = wined3d_device_context_get_constant_buffer(device->immediate_context.wined3d_context,
-                type, start_slot + i)))
+        wined3d_device_context_get_constant_buffer(device->immediate_context.wined3d_context,
+                type, start_slot + i, &state);
+
+        if (!state.buffer)
         {
             buffers[i] = NULL;
             continue;
         }
 
-        buffer_impl = wined3d_buffer_get_parent(wined3d_buffer);
+        buffer_impl = wined3d_buffer_get_parent(state.buffer);
         buffers[i] = &buffer_impl->ID3D10Buffer_iface;
         ID3D10Buffer_AddRef(buffers[i]);
     }
@@ -4526,7 +4593,7 @@ static void d3d10_device_get_constant_buffers(ID3D10Device1 *iface,
 static void d3d10_device_set_constant_buffers(ID3D10Device1 *iface, enum wined3d_shader_type type,
         unsigned int start_slot, unsigned int buffer_count, ID3D10Buffer *const *buffers)
 {
-    struct wined3d_buffer *wined3d_buffers[D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT];
+    struct wined3d_constant_buffer_state wined3d_buffers[D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT];
     struct d3d_device *device = impl_from_ID3D10Device(iface);
     unsigned int i;
 
@@ -4540,7 +4607,9 @@ static void d3d10_device_set_constant_buffers(ID3D10Device1 *iface, enum wined3d
     {
         struct d3d_buffer *buffer = unsafe_impl_from_ID3D10Buffer(buffers[i]);
 
-        wined3d_buffers[i] = buffer ? buffer->wined3d_buffer : NULL;
+        wined3d_buffers[i].buffer = buffer ? buffer->wined3d_buffer : NULL;
+        wined3d_buffers[i].offset = 0;
+        wined3d_buffers[i].size = WINED3D_MAX_CONSTANT_BUFFER_SIZE * sizeof(struct wined3d_vec4);
     }
 
     wined3d_mutex_lock();
diff --git a/dlls/wined3d/context_gl.c b/dlls/wined3d/context_gl.c
index 474003d7553..224c46efb6f 100644
--- a/dlls/wined3d/context_gl.c
+++ b/dlls/wined3d/context_gl.c
@@ -3759,10 +3759,10 @@ static void context_gl_load_shader_resources(struct wined3d_context_gl *context_
 
         for (j = 0; j < WINED3D_MAX_CBS; ++j)
         {
-            if (!state->cb[i][j])
+            if (!state->cb[i][j].buffer)
                 continue;
 
-            buffer_gl = wined3d_buffer_gl(state->cb[i][j]);
+            buffer_gl = wined3d_buffer_gl(state->cb[i][j].buffer);
             wined3d_buffer_load(&buffer_gl->b, &context_gl->c, state);
             wined3d_context_gl_reference_bo(context_gl, &buffer_gl->bo);
             if (!buffer_gl->bo_user.valid)
diff --git a/dlls/wined3d/context_vk.c b/dlls/wined3d/context_vk.c
index cbff3968179..d1a113d1f81 100644
--- a/dlls/wined3d/context_vk.c
+++ b/dlls/wined3d/context_vk.c
@@ -2713,7 +2713,7 @@ static bool wined3d_context_vk_update_descriptors(struct wined3d_context_vk *con
         switch (binding->shader_descriptor_type)
         {
             case WINED3D_SHADER_DESCRIPTOR_TYPE_CBV:
-                if (!(buffer = state->cb[binding->shader_type][binding->resource_idx]))
+                if (!(buffer = state->cb[binding->shader_type][binding->resource_idx].buffer))
                 {
                     if (!wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
                             binding->binding_idx, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
@@ -2988,7 +2988,7 @@ static void wined3d_context_vk_load_shader_resources(struct wined3d_context_vk *
         switch (binding->shader_descriptor_type)
         {
             case WINED3D_SHADER_DESCRIPTOR_TYPE_CBV:
-                if (!(buffer = state->cb[binding->shader_type][binding->resource_idx]))
+                if (!(buffer = state->cb[binding->shader_type][binding->resource_idx].buffer))
                     break;
 
                 buffer_vk = wined3d_buffer_vk(buffer);
diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c
index 434a9c20fb1..3ce12659999 100644
--- a/dlls/wined3d/cs.c
+++ b/dlls/wined3d/cs.c
@@ -280,7 +280,7 @@ struct wined3d_cs_set_constant_buffers
     enum wined3d_shader_type type;
     unsigned int start_idx;
     unsigned int count;
-    struct wined3d_buffer *buffers[1];
+    struct wined3d_constant_buffer_state buffers[1];
 };
 
 struct wined3d_cs_set_texture
@@ -877,8 +877,8 @@ static void acquire_shader_resources(struct wined3d_device_context *context, uns
 
         for (j = 0; j < WINED3D_MAX_CBS; ++j)
         {
-            if (state->cb[i][j])
-                wined3d_device_context_acquire_resource(context, &state->cb[i][j]->resource);
+            if (state->cb[i][j].buffer)
+                wined3d_device_context_acquire_resource(context, &state->cb[i][j].buffer->resource);
         }
 
         for (j = 0; j < shader->reg_maps.sampler_map.count; ++j)
@@ -910,8 +910,8 @@ static void release_shader_resources(const struct wined3d_state *state, unsigned
 
         for (j = 0; j < WINED3D_MAX_CBS; ++j)
         {
-            if (state->cb[i][j])
-                wined3d_resource_release(&state->cb[i][j]->resource);
+            if (state->cb[i][j].buffer)
+                wined3d_resource_release(&state->cb[i][j].buffer->resource);
         }
 
         for (j = 0; j < shader->reg_maps.sampler_map.count; ++j)
@@ -1512,10 +1512,10 @@ static void wined3d_cs_exec_set_constant_buffers(struct wined3d_cs *cs, const vo
 
     for (i = 0; i < op->count; ++i)
     {
-        struct wined3d_buffer *prev = cs->state.cb[op->type][op->start_idx + i];
-        struct wined3d_buffer *buffer = op->buffers[i];
+        struct wined3d_buffer *prev = cs->state.cb[op->type][op->start_idx + i].buffer;
+        struct wined3d_buffer *buffer = op->buffers[i].buffer;
 
-        cs->state.cb[op->type][op->start_idx + i] = buffer;
+        cs->state.cb[op->type][op->start_idx + i] = op->buffers[i];
 
         if (buffer)
             InterlockedIncrement(&buffer->resource.bind_count);
@@ -1528,7 +1528,7 @@ static void wined3d_cs_exec_set_constant_buffers(struct wined3d_cs *cs, const vo
 
 void wined3d_device_context_emit_set_constant_buffers(struct wined3d_device_context *context,
         enum wined3d_shader_type type, unsigned int start_idx, unsigned int count,
-        struct wined3d_buffer *const *buffers)
+        const struct wined3d_constant_buffer_state *buffers)
 {
     struct wined3d_cs_set_constant_buffers *op;
 
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index e4a16e56a56..f08ab0b109d 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -1796,7 +1796,7 @@ struct wined3d_shader * CDECL wined3d_device_context_get_shader(const struct win
 
 void CDECL wined3d_device_context_set_constant_buffers(struct wined3d_device_context *context,
         enum wined3d_shader_type type, unsigned int start_idx, unsigned int count,
-        struct wined3d_buffer *const *buffers)
+        const struct wined3d_constant_buffer_state *buffers)
 {
     struct wined3d_state *state = context->state;
     unsigned int i;
@@ -1815,12 +1815,12 @@ void CDECL wined3d_device_context_set_constant_buffers(struct wined3d_device_con
     wined3d_device_context_emit_set_constant_buffers(context, type, start_idx, count, buffers);
     for (i = 0; i < count; ++i)
     {
-        struct wined3d_buffer *prev = state->cb[type][start_idx + i];
-        struct wined3d_buffer *buffer = buffers[i];
+        struct wined3d_buffer *prev = state->cb[type][start_idx + i].buffer;
+        struct wined3d_buffer *buffer = buffers[i].buffer;
 
         if (buffer)
             wined3d_buffer_incref(buffer);
-        state->cb[type][start_idx + i] = buffer;
+        state->cb[type][start_idx + i] = buffers[i];
         if (prev)
             wined3d_buffer_decref(prev);
     }
@@ -2359,18 +2359,18 @@ void CDECL wined3d_device_context_draw_indexed(struct wined3d_device_context *co
             base_vertex_index, start_index, index_count, start_instance, instance_count, true);
 }
 
-struct wined3d_buffer * CDECL wined3d_device_context_get_constant_buffer(const struct wined3d_device_context *context,
-        enum wined3d_shader_type shader_type, unsigned int idx)
+void CDECL wined3d_device_context_get_constant_buffer(const struct wined3d_device_context *context,
+        enum wined3d_shader_type shader_type, unsigned int idx, struct wined3d_constant_buffer_state *state)
 {
     TRACE("context %p, shader_type %#x, idx %u.\n", context, shader_type, idx);
 
     if (idx >= MAX_CONSTANT_BUFFERS)
     {
         WARN("Invalid constant buffer index %u.\n", idx);
-        return NULL;
+        return;
     }
 
-    return context->state->cb[shader_type][idx];
+    *state = context->state->cb[shader_type][idx];
 }
 
 struct wined3d_shader_resource_view * CDECL wined3d_device_context_get_shader_resource_view(
diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c
index a9183278d86..8316269afcf 100644
--- a/dlls/wined3d/state.c
+++ b/dlls/wined3d/state.c
@@ -4558,14 +4558,17 @@ static void state_cb(struct wined3d_context *context, const struct wined3d_state
     wined3d_gl_limits_get_uniform_block_range(&gl_info->limits, shader_type, &base, &count);
     for (i = 0; i < count; ++i)
     {
-        if (!state->cb[shader_type][i])
+        const struct wined3d_constant_buffer_state *buffer_state = &state->cb[shader_type][i];
+
+        if (!buffer_state->buffer)
         {
             GL_EXTCALL(glBindBufferBase(GL_UNIFORM_BUFFER, base + i, 0));
             continue;
         }
 
-        buffer_gl = wined3d_buffer_gl(state->cb[shader_type][i]);
-        GL_EXTCALL(glBindBufferBase(GL_UNIFORM_BUFFER, base + i, buffer_gl->bo.id));
+        buffer_gl = wined3d_buffer_gl(buffer_state->buffer);
+        GL_EXTCALL(glBindBufferRange(GL_UNIFORM_BUFFER, base + i, buffer_gl->bo.id,
+                buffer_state->offset, buffer_state->size));
         buffer_gl->bo_user.valid = true;
     }
     checkGLcall("bind constant buffers");
diff --git a/dlls/wined3d/stateblock.c b/dlls/wined3d/stateblock.c
index 4cf30941d62..39a19984498 100644
--- a/dlls/wined3d/stateblock.c
+++ b/dlls/wined3d/stateblock.c
@@ -431,9 +431,9 @@ void state_unbind_resources(struct wined3d_state *state)
 
         for (j = 0; j < MAX_CONSTANT_BUFFERS; ++j)
         {
-            if ((buffer = state->cb[i][j]))
+            if ((buffer = state->cb[i][j].buffer))
             {
-                state->cb[i][j] = NULL;
+                state->cb[i][j].buffer = NULL;
                 wined3d_buffer_decref(buffer);
             }
         }
@@ -1829,8 +1829,8 @@ static void init_default_sampler_states(DWORD states[WINED3D_MAX_COMBINED_SAMPLE
 
 static void state_init_default(struct wined3d_state *state, const struct wined3d_d3d_info *d3d_info)
 {
-    unsigned int i;
     struct wined3d_matrix identity;
+    unsigned int i, j;
 
     TRACE("state %p, d3d_info %p.\n", state, d3d_info);
 
@@ -1867,6 +1867,12 @@ static void state_init_default(struct wined3d_state *state, const struct wined3d
 
     for (i = 0; i < WINED3D_MAX_STREAMS; ++i)
         state->streams[i].frequency = 1;
+
+    for (i = 0; i < WINED3D_SHADER_TYPE_COUNT; ++i)
+    {
+        for (j = 0; j < MAX_CONSTANT_BUFFERS; ++j)
+            state->cb[i][j].size = WINED3D_MAX_CONSTANT_BUFFER_SIZE * 16;
+    }
 }
 
 void state_init(struct wined3d_state *state, const struct wined3d_d3d_info *d3d_info,
diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec
index 2d36d0882ff..1bce4def265 100644
--- a/dlls/wined3d/wined3d.spec
+++ b/dlls/wined3d/wined3d.spec
@@ -101,7 +101,7 @@
 @ cdecl wined3d_device_context_flush(ptr)
 @ cdecl wined3d_device_context_generate_mipmaps(ptr ptr)
 @ cdecl wined3d_device_context_get_blend_state(ptr ptr ptr)
-@ cdecl wined3d_device_context_get_constant_buffer(ptr long long)
+@ cdecl wined3d_device_context_get_constant_buffer(ptr long long ptr)
 @ cdecl wined3d_device_context_get_depth_stencil_state(ptr ptr)
 @ cdecl wined3d_device_context_get_depth_stencil_view(ptr)
 @ cdecl wined3d_device_context_get_index_buffer(ptr ptr ptr)
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index fb25e856ead..e8cc9d9e458 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -3693,7 +3693,7 @@ struct wined3d_state
     BOOL predicate_value;
 
     struct wined3d_shader *shader[WINED3D_SHADER_TYPE_COUNT];
-    struct wined3d_buffer *cb[WINED3D_SHADER_TYPE_COUNT][MAX_CONSTANT_BUFFERS];
+    struct wined3d_constant_buffer_state 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[WINED3D_PIPELINE_COUNT][MAX_UNORDERED_ACCESS_VIEWS];
@@ -4804,7 +4804,7 @@ void wined3d_device_context_emit_set_clip_plane(struct wined3d_device_context *c
         const struct wined3d_vec4 *plane) DECLSPEC_HIDDEN;
 void wined3d_device_context_emit_set_constant_buffers(struct wined3d_device_context *context,
         enum wined3d_shader_type type, unsigned int start_idx, unsigned int count,
-        struct wined3d_buffer *const *buffers) DECLSPEC_HIDDEN;
+        const struct wined3d_constant_buffer_state *buffers) DECLSPEC_HIDDEN;
 void wined3d_device_context_emit_set_depth_stencil_state(struct wined3d_device_context *context,
         struct wined3d_depth_stencil_state *state, unsigned int stencil_ref) DECLSPEC_HIDDEN;
 void wined3d_device_context_emit_set_depth_stencil_view(struct wined3d_device_context *context,
diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h
index baa71758d17..7be893b8f21 100644
--- a/include/wine/wined3d.h
+++ b/include/wine/wined3d.h
@@ -1611,6 +1611,7 @@ enum wined3d_pipeline
 #define WINED3D_MAX_VS_CONSTS_F                                 256
 #define WINED3D_MAX_PS_CONSTS_F                                 224
 #define WINED3D_MAX_RENDER_TARGETS                              8
+#define WINED3D_MAX_CONSTANT_BUFFER_SIZE                        4096
 
 struct wined3d_display_mode
 {
@@ -2218,6 +2219,13 @@ struct wined3d_stream_output
     unsigned int offset;
 };
 
+struct wined3d_constant_buffer_state
+{
+    struct wined3d_buffer *buffer;
+    unsigned int offset;
+    unsigned int size;
+};
+
 struct wined3d_parent_ops
 {
     void (__stdcall *wined3d_object_destroyed)(void *parent);
@@ -2457,8 +2465,8 @@ void __cdecl wined3d_device_context_generate_mipmaps(struct wined3d_device_conte
         struct wined3d_shader_resource_view *view);
 struct wined3d_blend_state * __cdecl wined3d_device_context_get_blend_state(
         const struct wined3d_device_context *context, struct wined3d_color *blend_factor, unsigned int *sample_mask);
-struct wined3d_buffer * __cdecl wined3d_device_context_get_constant_buffer(const struct wined3d_device_context *context,
-        enum wined3d_shader_type shader_type, unsigned int idx);
+void __cdecl wined3d_device_context_get_constant_buffer(const struct wined3d_device_context *context,
+        enum wined3d_shader_type shader_type, unsigned int idx, struct wined3d_constant_buffer_state *state);
 struct wined3d_depth_stencil_state * __cdecl wined3d_device_context_get_depth_stencil_state(
         const struct wined3d_device_context *context, unsigned int *stencil_ref);
 struct wined3d_rendertarget_view * __cdecl wined3d_device_context_get_depth_stencil_view(
@@ -2504,7 +2512,7 @@ void __cdecl wined3d_device_context_set_blend_state(struct wined3d_device_contex
         struct wined3d_blend_state *state, const struct wined3d_color *blend_factor, unsigned int sample_mask);
 void __cdecl wined3d_device_context_set_constant_buffers(struct wined3d_device_context *context,
         enum wined3d_shader_type type, unsigned int start_idx, unsigned int count,
-        struct wined3d_buffer *const *buffers);
+        const struct wined3d_constant_buffer_state *buffers);
 void __cdecl wined3d_device_context_set_depth_stencil_state(struct wined3d_device_context *context,
         struct wined3d_depth_stencil_state *depth_stencil_state, unsigned int stencil_ref);
 HRESULT __cdecl wined3d_device_context_set_depth_stencil_view(struct wined3d_device_context *context,
-- 
2.30.2




More information about the wine-devel mailing list