summarylogtreecommitdiffstats
path: root/0005-wined3d-Experimental-support-for-persistent-buffer-t.patch
blob: a039c7e622c88833a7e1bff01b450e959274fe7e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
From 1e4c2e45a18a6eb445c507745f1c7b568c22aca6 Mon Sep 17 00:00:00 2001
From: Andrew Comminos <andrew@comminos.com>
Date: Tue, 6 Mar 2018 15:58:05 -0800
Subject: [PATCH 5/5] wined3d: Experimental support for persistent buffer
 textures.

Fixes missing models in Overwatch.
---
 dlls/wined3d/cs.c   |  6 ++++
 dlls/wined3d/view.c | 79 +++++++++++++++++++++++++++++++++--------------------
 2 files changed, 55 insertions(+), 30 deletions(-)

diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c
index e61b8dedbb..63cdb74e02 100644
--- a/dlls/wined3d/cs.c
+++ b/dlls/wined3d/cs.c
@@ -2493,6 +2493,12 @@ static void wined3d_cs_exec_discard_buffer(struct wined3d_cs *cs, const void *da
         device_invalidate_state(cs->device, STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_COMPUTE));
     }
 
+    if (buffer->bind_flags & WINED3D_BIND_SHADER_RESOURCE)
+    {
+        device_invalidate_state(cs->device, STATE_GRAPHICS_SHADER_RESOURCE_BINDING);
+        device_invalidate_state(cs->device, STATE_COMPUTE_SHADER_RESOURCE_BINDING);
+    }
+
     wined3d_resource_release(&op->buffer->resource);
 }
 
diff --git a/dlls/wined3d/view.c b/dlls/wined3d/view.c
index bed39dbc5f..100b3e34d8 100644
--- a/dlls/wined3d/view.c
+++ b/dlls/wined3d/view.c
@@ -227,9 +227,7 @@ static void create_texture_view(struct wined3d_gl_view *view, GLenum view_target
     context_release(context);
 }
 
-static void create_buffer_texture(struct wined3d_gl_view *view, struct wined3d_context *context,
-        struct wined3d_buffer *buffer, const struct wined3d_format *view_format,
-        unsigned int offset, unsigned int size)
+static void create_buffer_texture(struct wined3d_gl_view *view, struct wined3d_context *context)
 {
     const struct wined3d_gl_info *gl_info = context->gl_info;
 
@@ -239,34 +237,58 @@ static void create_buffer_texture(struct wined3d_gl_view *view, struct wined3d_c
         return;
     }
 
-    if ((offset & (gl_info->limits.texture_buffer_offset_alignment - 1)))
+    view->target = GL_TEXTURE_BUFFER;
+    gl_info->gl_ops.gl.p_glGenTextures(1, &view->name);
+
+    context_invalidate_compute_state(context, STATE_COMPUTE_SHADER_RESOURCE_BINDING);
+    context_invalidate_state(context, STATE_GRAPHICS_SHADER_RESOURCE_BINDING);
+}
+
+static void bind_buffer_texture(struct wined3d_gl_view *view, struct wined3d_context *context,
+        struct wined3d_buffer *buffer, const struct wined3d_format *view_format,
+        unsigned int offset, unsigned int size)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    struct wined3d_bo_address bo_addr;
+    unsigned int addr_offset;
+
+    if (!wined3d_buffer_load_location(buffer, context, WINED3D_LOCATION_BUFFER) &&
+        !wined3d_buffer_load_location(buffer, context, WINED3D_LOCATION_PERSISTENT_MAP))
     {
-        FIXME("Buffer offset %u is not %u byte aligned.\n",
-                offset, gl_info->limits.texture_buffer_offset_alignment);
+        ERR("Failed to load a supported buffer location for %p.\n", buffer);
         return;
     }
 
-    wined3d_buffer_load_location(buffer, context, WINED3D_LOCATION_BUFFER);
 
-    view->target = GL_TEXTURE_BUFFER;
-    gl_info->gl_ops.gl.p_glGenTextures(1, &view->name);
+    if (FAILED(wined3d_buffer_get_memory(buffer, &bo_addr, buffer->locations)))
+    {
+        ERR("Failed to get buffer memory to create a buffer texture.\n");
+        return;
+    }
+
+    // TODO(acomminos): use a special heap for texture buffer alignment?
+    addr_offset = offset + bo_addr.addr;
+
+    if ((addr_offset & (gl_info->limits.texture_buffer_offset_alignment - 1)))
+    {
+        FIXME("Buffer offset %u is not %u byte aligned.\n",
+                offset, gl_info->limits.texture_buffer_offset_alignment);
+        return;
+    }
 
-    context_bind_texture(context, GL_TEXTURE_BUFFER, view->name);
     if (gl_info->supported[ARB_TEXTURE_BUFFER_RANGE])
     {
         GL_EXTCALL(glTexBufferRange(GL_TEXTURE_BUFFER, view_format->glInternal,
-                buffer->buffer_object, offset, size));
+                bo_addr.buffer_object, addr_offset, size));
     }
     else
     {
-        if (offset || size != buffer->resource.size)
+        if (addr_offset || size != buffer->resource.size)
             FIXME("OpenGL implementation does not support ARB_texture_buffer_range.\n");
-        GL_EXTCALL(glTexBuffer(GL_TEXTURE_BUFFER, view_format->glInternal, buffer->buffer_object));
+        GL_EXTCALL(glTexBuffer(GL_TEXTURE_BUFFER, view_format->glInternal, bo_addr.buffer_object));
     }
-    checkGLcall("Create buffer texture");
+    checkGLcall("Bind buffer texture");
 
-    context_invalidate_compute_state(context, STATE_COMPUTE_SHADER_RESOURCE_BINDING);
-    context_invalidate_state(context, STATE_GRAPHICS_SHADER_RESOURCE_BINDING);
 }
 
 static void get_buffer_view_range(const struct wined3d_buffer *buffer,
@@ -285,16 +307,6 @@ static void get_buffer_view_range(const struct wined3d_buffer *buffer,
     }
 }
 
-static void create_buffer_view(struct wined3d_gl_view *view, struct wined3d_context *context,
-        const struct wined3d_view_desc *desc, struct wined3d_buffer *buffer,
-        const struct wined3d_format *view_format)
-{
-    unsigned int offset, size;
-
-    get_buffer_view_range(buffer, desc, view_format, &offset, &size);
-    create_buffer_texture(view, context, buffer, view_format, offset, size);
-}
-
 static void wined3d_view_invalidate_location(struct wined3d_resource *resource,
         const struct wined3d_view_desc *desc, DWORD location)
 {
@@ -711,11 +723,10 @@ static void wined3d_shader_resource_view_cs_init(void *object)
 
     if (resource->type == WINED3D_RTYPE_BUFFER)
     {
-        struct wined3d_buffer *buffer = buffer_from_resource(resource);
         struct wined3d_context *context;
 
         context = context_acquire(resource->device, NULL, 0);
-        create_buffer_view(&view->gl_view, context, desc, buffer, view_format);
+        create_buffer_texture(&view->gl_view, context);
         context_release(context);
     }
     else
@@ -814,7 +825,16 @@ void wined3d_shader_resource_view_bind(struct wined3d_shader_resource_view *view
 
     if (view->gl_view.name)
     {
+        // XXX(acomminos): only rebind buffer texture range when needed (i.e. on discards)
         context_bind_texture(context, view->gl_view.target, view->gl_view.name);
+        if (view->resource->type == WINED3D_RTYPE_BUFFER)
+        {
+            unsigned int offset, size;
+            struct wined3d_buffer *buffer = buffer_from_resource(view->resource);
+            get_buffer_view_range(buffer, &view->desc, view->format, &offset, &size);
+            bind_buffer_texture(&view->gl_view, context, buffer_from_resource(view->resource), view->format, offset, size);
+        }
+
         wined3d_sampler_bind(sampler, unit, NULL, context);
         return;
     }
@@ -1092,12 +1112,11 @@ static void wined3d_unordered_access_view_cs_init(void *object)
 
     if (resource->type == WINED3D_RTYPE_BUFFER)
     {
-        struct wined3d_buffer *buffer = buffer_from_resource(resource);
         struct wined3d_context *context;
 
         context = context_acquire(resource->device, NULL, 0);
         gl_info = context->gl_info;
-        create_buffer_view(&view->gl_view, context, desc, buffer, view->format);
+        create_buffer_texture(&view->gl_view, context);
         if (desc->flags & (WINED3D_VIEW_BUFFER_COUNTER | WINED3D_VIEW_BUFFER_APPEND))
         {
             static const GLuint initial_value = 0;
-- 
2.16.2