wined3d: Respect the BO buffer offset in create_buffer_texture().
[wine.git] / dlls / wined3d / view.c
blob0ea1453176603b10f65f893f30b1548ee4375425
1 /*
2 * Copyright 2009, 2011 Henri Verbeet for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include "config.h"
21 #include "wine/port.h"
23 #include "wined3d_private.h"
24 #include "wined3d_shaders.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
28 #define WINED3D_VIEW_CUBE_ARRAY (WINED3D_VIEW_TEXTURE_CUBE | WINED3D_VIEW_TEXTURE_ARRAY)
30 static BOOL is_stencil_view_format(const struct wined3d_format *format)
32 return format->id == WINED3DFMT_X24_TYPELESS_G8_UINT
33 || format->id == WINED3DFMT_X32_TYPELESS_G8X24_UINT;
36 static GLenum get_texture_view_target(const struct wined3d_gl_info *gl_info,
37 const struct wined3d_view_desc *desc, const struct wined3d_texture_gl *texture_gl)
39 static const struct
41 GLenum texture_target;
42 unsigned int view_flags;
43 GLenum view_target;
44 enum wined3d_gl_extension extension;
46 view_types[] =
48 {GL_TEXTURE_CUBE_MAP, 0, GL_TEXTURE_CUBE_MAP},
49 {GL_TEXTURE_RECTANGLE, 0, GL_TEXTURE_RECTANGLE},
50 {GL_TEXTURE_3D, 0, GL_TEXTURE_3D},
52 {GL_TEXTURE_2D, 0, GL_TEXTURE_2D},
53 {GL_TEXTURE_2D, WINED3D_VIEW_TEXTURE_ARRAY, GL_TEXTURE_2D_ARRAY},
54 {GL_TEXTURE_2D_ARRAY, 0, GL_TEXTURE_2D},
55 {GL_TEXTURE_2D_ARRAY, WINED3D_VIEW_TEXTURE_ARRAY, GL_TEXTURE_2D_ARRAY},
56 {GL_TEXTURE_2D_ARRAY, WINED3D_VIEW_TEXTURE_CUBE, GL_TEXTURE_CUBE_MAP},
57 {GL_TEXTURE_2D_ARRAY, WINED3D_VIEW_CUBE_ARRAY, GL_TEXTURE_CUBE_MAP_ARRAY, ARB_TEXTURE_CUBE_MAP_ARRAY},
59 {GL_TEXTURE_2D_MULTISAMPLE, 0, GL_TEXTURE_2D_MULTISAMPLE},
60 {GL_TEXTURE_2D_MULTISAMPLE, WINED3D_VIEW_TEXTURE_ARRAY, GL_TEXTURE_2D_MULTISAMPLE_ARRAY},
61 {GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 0, GL_TEXTURE_2D_MULTISAMPLE},
62 {GL_TEXTURE_2D_MULTISAMPLE_ARRAY, WINED3D_VIEW_TEXTURE_ARRAY, GL_TEXTURE_2D_MULTISAMPLE_ARRAY},
64 {GL_TEXTURE_1D, 0, GL_TEXTURE_1D},
65 {GL_TEXTURE_1D, WINED3D_VIEW_TEXTURE_ARRAY, GL_TEXTURE_1D_ARRAY},
66 {GL_TEXTURE_1D_ARRAY, 0, GL_TEXTURE_1D},
67 {GL_TEXTURE_1D_ARRAY, WINED3D_VIEW_TEXTURE_ARRAY, GL_TEXTURE_1D_ARRAY},
69 unsigned int flags = desc->flags & (WINED3D_VIEW_BUFFER_RAW | WINED3D_VIEW_BUFFER_APPEND
70 | WINED3D_VIEW_BUFFER_COUNTER | WINED3D_VIEW_TEXTURE_CUBE | WINED3D_VIEW_TEXTURE_ARRAY);
71 unsigned int i;
73 for (i = 0; i < ARRAY_SIZE(view_types); ++i)
75 if (view_types[i].texture_target != texture_gl->target || view_types[i].view_flags != flags)
76 continue;
77 if (gl_info->supported[view_types[i].extension])
78 return view_types[i].view_target;
80 FIXME("Extension %#x not supported.\n", view_types[i].extension);
83 FIXME("Unhandled view flags %#x for texture target %#x.\n", flags, texture_gl->target);
84 return texture_gl->target;
87 static const struct wined3d_format *validate_resource_view(const struct wined3d_view_desc *desc,
88 struct wined3d_resource *resource, BOOL mip_slice, BOOL allow_srgb_toggle)
90 const struct wined3d_adapter *adapter = resource->device->adapter;
91 const struct wined3d_format *format;
93 format = wined3d_get_format(adapter, desc->format_id, resource->bind_flags);
94 if (resource->type == WINED3D_RTYPE_BUFFER && (desc->flags & WINED3D_VIEW_BUFFER_RAW))
96 if (format->id != WINED3DFMT_R32_TYPELESS)
98 WARN("Invalid format %s for raw buffer view.\n", debug_d3dformat(format->id));
99 return NULL;
102 format = wined3d_get_format(adapter, WINED3DFMT_R32_UINT, resource->bind_flags);
105 if (wined3d_format_is_typeless(format))
107 WARN("Trying to create view for typeless format %s.\n", debug_d3dformat(format->id));
108 return NULL;
111 if (resource->type == WINED3D_RTYPE_BUFFER)
113 struct wined3d_buffer *buffer = buffer_from_resource(resource);
114 unsigned int buffer_size, element_size;
116 if (buffer->structure_byte_stride)
118 if (desc->format_id != WINED3DFMT_UNKNOWN)
120 WARN("Invalid format %s for structured buffer view.\n", debug_d3dformat(desc->format_id));
121 return NULL;
124 format = wined3d_get_format(adapter, WINED3DFMT_R32_UINT, resource->bind_flags);
125 element_size = buffer->structure_byte_stride;
127 else
129 element_size = format->byte_count;
132 if (!element_size)
133 return NULL;
135 buffer_size = buffer->resource.size / element_size;
136 if (!wined3d_bound_range(desc->u.buffer.start_idx, desc->u.buffer.count, buffer_size))
137 return NULL;
139 else
141 struct wined3d_texture *texture = texture_from_resource(resource);
142 unsigned int depth_or_layer_count;
144 if (resource->format->id != format->id && !wined3d_format_is_typeless(resource->format)
145 && (!allow_srgb_toggle || !wined3d_formats_are_srgb_variants(resource->format->id, format->id)))
147 WARN("Trying to create incompatible view for non typeless format %s.\n",
148 debug_d3dformat(format->id));
149 return NULL;
152 if (mip_slice && resource->type == WINED3D_RTYPE_TEXTURE_3D)
153 depth_or_layer_count = wined3d_texture_get_level_depth(texture, desc->u.texture.level_idx);
154 else
155 depth_or_layer_count = texture->layer_count;
157 if (!desc->u.texture.level_count
158 || (mip_slice && desc->u.texture.level_count != 1)
159 || !wined3d_bound_range(desc->u.texture.level_idx, desc->u.texture.level_count, texture->level_count)
160 || !desc->u.texture.layer_count
161 || !wined3d_bound_range(desc->u.texture.layer_idx, desc->u.texture.layer_count, depth_or_layer_count))
162 return NULL;
165 return format;
168 static void create_texture_view(struct wined3d_gl_view *view, GLenum view_target,
169 const struct wined3d_view_desc *desc, struct wined3d_texture_gl *texture_gl,
170 const struct wined3d_format *view_format)
172 const struct wined3d_format_gl *view_format_gl;
173 unsigned int level_idx, layer_idx, layer_count;
174 const struct wined3d_gl_info *gl_info;
175 struct wined3d_context_gl *context_gl;
176 struct wined3d_context *context;
177 GLuint texture_name;
179 view_format_gl = wined3d_format_gl(view_format);
180 view->target = view_target;
182 context = context_acquire(texture_gl->t.resource.device, NULL, 0);
183 context_gl = wined3d_context_gl(context);
184 gl_info = context_gl->gl_info;
186 if (!gl_info->supported[ARB_TEXTURE_VIEW])
188 context_release(context);
189 FIXME("OpenGL implementation does not support texture views.\n");
190 return;
193 wined3d_texture_gl_prepare_texture(texture_gl, context_gl, FALSE);
194 texture_name = wined3d_texture_gl_get_texture_name(texture_gl, context, FALSE);
196 level_idx = desc->u.texture.level_idx;
197 layer_idx = desc->u.texture.layer_idx;
198 layer_count = desc->u.texture.layer_count;
199 if (view_target == GL_TEXTURE_3D)
201 if (layer_idx || layer_count != wined3d_texture_get_level_depth(&texture_gl->t, level_idx))
202 FIXME("Depth slice (%u-%u) not supported.\n", layer_idx, layer_count);
203 layer_idx = 0;
204 layer_count = 1;
207 gl_info->gl_ops.gl.p_glGenTextures(1, &view->name);
208 GL_EXTCALL(glTextureView(view->name, view->target, texture_name, view_format_gl->internal,
209 level_idx, desc->u.texture.level_count, layer_idx, layer_count));
210 checkGLcall("create texture view");
212 if (is_stencil_view_format(view_format))
214 static const GLint swizzle[] = {GL_ZERO, GL_RED, GL_ZERO, GL_ZERO};
216 if (!gl_info->supported[ARB_STENCIL_TEXTURING])
218 context_release(context);
219 FIXME("OpenGL implementation does not support stencil texturing.\n");
220 return;
223 wined3d_context_gl_bind_texture(context_gl, view->target, view->name);
224 gl_info->gl_ops.gl.p_glTexParameteriv(view->target, GL_TEXTURE_SWIZZLE_RGBA, swizzle);
225 gl_info->gl_ops.gl.p_glTexParameteri(view->target, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_STENCIL_INDEX);
226 checkGLcall("initialize stencil view");
228 context_invalidate_compute_state(context, STATE_COMPUTE_SHADER_RESOURCE_BINDING);
229 context_invalidate_state(context, STATE_GRAPHICS_SHADER_RESOURCE_BINDING);
231 else if (!is_identity_fixup(view_format->color_fixup) && can_use_texture_swizzle(context->d3d_info, view_format))
233 GLint swizzle[4];
235 wined3d_context_gl_bind_texture(context_gl, view->target, view->name);
236 wined3d_gl_texture_swizzle_from_color_fixup(swizzle, view_format->color_fixup);
237 gl_info->gl_ops.gl.p_glTexParameteriv(view->target, GL_TEXTURE_SWIZZLE_RGBA, swizzle);
238 checkGLcall("set format swizzle");
240 context_invalidate_compute_state(context, STATE_COMPUTE_SHADER_RESOURCE_BINDING);
241 context_invalidate_state(context, STATE_GRAPHICS_SHADER_RESOURCE_BINDING);
244 context_release(context);
247 static void create_buffer_texture(struct wined3d_gl_view *view, struct wined3d_context_gl *context_gl,
248 struct wined3d_buffer *buffer, const struct wined3d_format_gl *view_format_gl,
249 unsigned int offset, unsigned int size)
251 const struct wined3d_gl_info *gl_info = context_gl->gl_info;
252 const struct wined3d_bo_gl *bo_gl;
254 if (!gl_info->supported[ARB_TEXTURE_BUFFER_OBJECT])
256 FIXME("OpenGL implementation does not support buffer textures.\n");
257 return;
260 wined3d_buffer_load_location(buffer, &context_gl->c, WINED3D_LOCATION_BUFFER);
261 bo_gl = wined3d_bo_gl(buffer->buffer_object);
262 offset += bo_gl->b.buffer_offset;
264 if ((offset & (gl_info->limits.texture_buffer_offset_alignment - 1)))
266 FIXME("Buffer offset %u is not %u byte aligned.\n",
267 offset, gl_info->limits.texture_buffer_offset_alignment);
268 return;
271 view->target = GL_TEXTURE_BUFFER;
272 if (!view->name)
273 gl_info->gl_ops.gl.p_glGenTextures(1, &view->name);
275 wined3d_context_gl_bind_texture(context_gl, GL_TEXTURE_BUFFER, view->name);
276 if (gl_info->supported[ARB_TEXTURE_BUFFER_RANGE])
278 GL_EXTCALL(glTexBufferRange(GL_TEXTURE_BUFFER, view_format_gl->internal, bo_gl->id, offset, size));
280 else
282 if (offset || size != buffer->resource.size)
283 FIXME("OpenGL implementation does not support ARB_texture_buffer_range.\n");
284 GL_EXTCALL(glTexBuffer(GL_TEXTURE_BUFFER, view_format_gl->internal, bo_gl->id));
286 checkGLcall("Create buffer texture");
288 context_invalidate_compute_state(&context_gl->c, STATE_COMPUTE_SHADER_RESOURCE_BINDING);
289 context_invalidate_state(&context_gl->c, STATE_GRAPHICS_SHADER_RESOURCE_BINDING);
292 static void get_buffer_view_range(const struct wined3d_buffer *buffer,
293 const struct wined3d_view_desc *desc, const struct wined3d_format *view_format,
294 unsigned int *offset, unsigned int *size)
296 if (desc->format_id == WINED3DFMT_UNKNOWN)
298 *offset = desc->u.buffer.start_idx * buffer->structure_byte_stride;
299 *size = desc->u.buffer.count * buffer->structure_byte_stride;
301 else
303 *offset = desc->u.buffer.start_idx * view_format->byte_count;
304 *size = desc->u.buffer.count * view_format->byte_count;
308 static void create_buffer_view(struct wined3d_gl_view *view, struct wined3d_context *context,
309 const struct wined3d_view_desc *desc, struct wined3d_buffer *buffer,
310 const struct wined3d_format *view_format)
312 unsigned int offset, size;
314 get_buffer_view_range(buffer, desc, view_format, &offset, &size);
315 create_buffer_texture(view, wined3d_context_gl(context), buffer, wined3d_format_gl(view_format), offset, size);
318 static void wined3d_view_invalidate_location(struct wined3d_resource *resource,
319 const struct wined3d_view_desc *desc, DWORD location)
321 unsigned int i, sub_resource_idx, layer_count;
322 struct wined3d_texture *texture;
324 if (resource->type == WINED3D_RTYPE_BUFFER)
326 wined3d_buffer_invalidate_location(buffer_from_resource(resource), location);
327 return;
330 texture = texture_from_resource(resource);
332 sub_resource_idx = desc->u.texture.layer_idx * texture->level_count + desc->u.texture.level_idx;
333 layer_count = resource->type != WINED3D_RTYPE_TEXTURE_3D ? desc->u.texture.layer_count : 1;
334 for (i = 0; i < layer_count; ++i, sub_resource_idx += texture->level_count)
335 wined3d_texture_invalidate_location(texture, sub_resource_idx, location);
338 static void wined3d_view_load_location(struct wined3d_resource *resource,
339 const struct wined3d_view_desc *desc, struct wined3d_context *context, DWORD location)
341 unsigned int i, sub_resource_idx, layer_count;
342 struct wined3d_texture *texture;
344 if (resource->type == WINED3D_RTYPE_BUFFER)
346 wined3d_buffer_load_location(buffer_from_resource(resource), context, location);
347 return;
350 texture = texture_from_resource(resource);
351 sub_resource_idx = desc->u.texture.layer_idx * texture->level_count + desc->u.texture.level_idx;
352 layer_count = resource->type != WINED3D_RTYPE_TEXTURE_3D ? desc->u.texture.layer_count : 1;
353 for (i = 0; i < layer_count; ++i, sub_resource_idx += texture->level_count)
354 wined3d_texture_load_location(texture, sub_resource_idx, context, location);
357 ULONG CDECL wined3d_rendertarget_view_incref(struct wined3d_rendertarget_view *view)
359 ULONG refcount = InterlockedIncrement(&view->refcount);
361 TRACE("%p increasing refcount to %u.\n", view, refcount);
363 return refcount;
366 void wined3d_rendertarget_view_cleanup(struct wined3d_rendertarget_view *view)
368 /* Call wined3d_object_destroyed() before releasing the resource,
369 * since releasing the resource may end up destroying the parent. */
370 view->parent_ops->wined3d_object_destroyed(view->parent);
371 wined3d_resource_decref(view->resource);
374 ULONG CDECL wined3d_rendertarget_view_decref(struct wined3d_rendertarget_view *view)
376 ULONG refcount = InterlockedDecrement(&view->refcount);
378 TRACE("%p decreasing refcount to %u.\n", view, refcount);
380 if (!refcount)
382 wined3d_mutex_lock();
383 view->resource->device->adapter->adapter_ops->adapter_destroy_rendertarget_view(view);
384 wined3d_mutex_unlock();
387 return refcount;
390 void * CDECL wined3d_rendertarget_view_get_parent(const struct wined3d_rendertarget_view *view)
392 TRACE("view %p.\n", view);
394 return view->parent;
397 void * CDECL wined3d_rendertarget_view_get_sub_resource_parent(const struct wined3d_rendertarget_view *view)
399 struct wined3d_texture *texture;
401 TRACE("view %p.\n", view);
403 if (view->resource->type == WINED3D_RTYPE_BUFFER)
404 return wined3d_buffer_get_parent(buffer_from_resource(view->resource));
406 texture = texture_from_resource(view->resource);
408 return texture->sub_resources[view->sub_resource_idx].parent;
411 void CDECL wined3d_rendertarget_view_set_parent(struct wined3d_rendertarget_view *view, void *parent)
413 TRACE("view %p, parent %p.\n", view, parent);
415 view->parent = parent;
418 struct wined3d_resource * CDECL wined3d_rendertarget_view_get_resource(const struct wined3d_rendertarget_view *view)
420 TRACE("view %p.\n", view);
422 return view->resource;
425 void wined3d_rendertarget_view_get_drawable_size(const struct wined3d_rendertarget_view *view,
426 const struct wined3d_context *context, unsigned int *width, unsigned int *height)
428 const struct wined3d_texture *texture;
430 if (view->resource->type != WINED3D_RTYPE_TEXTURE_2D)
432 *width = view->width;
433 *height = view->height;
434 return;
437 texture = texture_from_resource(view->resource);
438 if (texture->swapchain)
440 /* The drawable size of an onscreen drawable is the surface size.
441 * (Actually: The window size, but the surface is created in window
442 * size.) */
443 *width = texture->resource.width;
444 *height = texture->resource.height;
446 else if (wined3d_settings.offscreen_rendering_mode == ORM_BACKBUFFER)
448 const struct wined3d_swapchain_desc *desc = &context->swapchain->state.desc;
450 /* The drawable size of a backbuffer / aux buffer offscreen target is
451 * the size of the current context's drawable, which is the size of
452 * the back buffer of the swapchain the active context belongs to. */
453 *width = desc->backbuffer_width;
454 *height = desc->backbuffer_height;
456 else
458 unsigned int level_idx = view->sub_resource_idx % texture->level_count;
460 /* The drawable size of an FBO target is the OpenGL texture size,
461 * which is the power of two size. */
462 *width = wined3d_texture_get_level_pow2_width(texture, level_idx);
463 *height = wined3d_texture_get_level_pow2_height(texture, level_idx);
467 void wined3d_rendertarget_view_prepare_location(struct wined3d_rendertarget_view *view,
468 struct wined3d_context *context, DWORD location)
470 struct wined3d_resource *resource = view->resource;
471 unsigned int i, sub_resource_idx, layer_count;
472 struct wined3d_texture *texture;
474 if (resource->type == WINED3D_RTYPE_BUFFER)
476 FIXME("Not implemented for resources %s.\n", debug_d3dresourcetype(resource->type));
477 return;
480 texture = texture_from_resource(resource);
481 sub_resource_idx = view->sub_resource_idx;
482 layer_count = resource->type != WINED3D_RTYPE_TEXTURE_3D ? view->layer_count : 1;
483 for (i = 0; i < layer_count; ++i, sub_resource_idx += texture->level_count)
484 wined3d_texture_prepare_location(texture, sub_resource_idx, context, location);
487 void wined3d_rendertarget_view_load_location(struct wined3d_rendertarget_view *view,
488 struct wined3d_context *context, DWORD location)
490 wined3d_view_load_location(view->resource, &view->desc, context, location);
493 void wined3d_rendertarget_view_validate_location(struct wined3d_rendertarget_view *view, DWORD location)
495 struct wined3d_resource *resource = view->resource;
496 unsigned int i, sub_resource_idx, layer_count;
497 struct wined3d_texture *texture;
499 if (resource->type == WINED3D_RTYPE_BUFFER)
501 FIXME("Not implemented for resources %s.\n", debug_d3dresourcetype(resource->type));
502 return;
505 texture = texture_from_resource(resource);
506 sub_resource_idx = view->sub_resource_idx;
507 layer_count = resource->type != WINED3D_RTYPE_TEXTURE_3D ? view->layer_count : 1;
508 for (i = 0; i < layer_count; ++i, sub_resource_idx += texture->level_count)
509 wined3d_texture_validate_location(texture, sub_resource_idx, location);
512 void wined3d_rendertarget_view_invalidate_location(struct wined3d_rendertarget_view *view, DWORD location)
514 wined3d_view_invalidate_location(view->resource, &view->desc, location);
517 static void wined3d_render_target_view_gl_cs_init(void *object)
519 struct wined3d_rendertarget_view_gl *view_gl = object;
520 struct wined3d_resource *resource = view_gl->v.resource;
521 const struct wined3d_view_desc *desc = &view_gl->v.desc;
523 TRACE("view_gl %p.\n", view_gl);
525 if (resource->type == WINED3D_RTYPE_BUFFER)
527 FIXME("Not implemented for resources %s.\n", debug_d3dresourcetype(resource->type));
529 else
531 struct wined3d_texture_gl *texture_gl = wined3d_texture_gl(texture_from_resource(resource));
532 unsigned int depth_or_layer_count;
534 if (resource->type == WINED3D_RTYPE_TEXTURE_3D)
535 depth_or_layer_count = wined3d_texture_get_level_depth(&texture_gl->t, desc->u.texture.level_idx);
536 else
537 depth_or_layer_count = texture_gl->t.layer_count;
539 if (resource->format->id != view_gl->v.format->id
540 || (view_gl->v.layer_count != 1 && view_gl->v.layer_count != depth_or_layer_count))
542 GLenum resource_class, view_class;
544 resource_class = wined3d_format_gl(resource->format)->view_class;
545 view_class = wined3d_format_gl(view_gl->v.format)->view_class;
546 if (resource_class != view_class)
548 FIXME("Render target view not supported, resource format %s, view format %s.\n",
549 debug_d3dformat(resource->format->id), debug_d3dformat(view_gl->v.format->id));
550 return;
552 if (texture_gl->t.swapchain && texture_gl->t.swapchain->state.desc.backbuffer_count > 1)
554 FIXME("Swapchain views not supported.\n");
555 return;
558 create_texture_view(&view_gl->gl_view, texture_gl->target, desc, texture_gl, view_gl->v.format);
563 static HRESULT wined3d_rendertarget_view_init(struct wined3d_rendertarget_view *view,
564 const struct wined3d_view_desc *desc, struct wined3d_resource *resource,
565 void *parent, const struct wined3d_parent_ops *parent_ops)
567 BOOL allow_srgb_toggle = FALSE;
569 view->refcount = 1;
570 view->parent = parent;
571 view->parent_ops = parent_ops;
573 if (resource->type != WINED3D_RTYPE_BUFFER)
575 struct wined3d_texture *texture = texture_from_resource(resource);
577 if (texture->swapchain)
578 allow_srgb_toggle = TRUE;
580 if (!(view->format = validate_resource_view(desc, resource, TRUE, allow_srgb_toggle)))
581 return E_INVALIDARG;
582 view->format_flags = view->format->flags[resource->gl_type];
583 view->desc = *desc;
585 if (resource->type == WINED3D_RTYPE_BUFFER)
587 view->sub_resource_idx = 0;
588 view->layer_count = 1;
589 view->width = desc->u.buffer.count;
590 view->height = 1;
592 else
594 struct wined3d_texture *texture = texture_from_resource(resource);
596 view->sub_resource_idx = desc->u.texture.level_idx;
597 if (resource->type != WINED3D_RTYPE_TEXTURE_3D)
598 view->sub_resource_idx += desc->u.texture.layer_idx * texture->level_count;
599 view->layer_count = desc->u.texture.layer_count;
600 view->width = wined3d_texture_get_level_width(texture, desc->u.texture.level_idx);
601 view->height = wined3d_texture_get_level_height(texture, desc->u.texture.level_idx);
604 wined3d_resource_incref(view->resource = resource);
606 return WINED3D_OK;
609 HRESULT wined3d_rendertarget_view_no3d_init(struct wined3d_rendertarget_view *view_no3d,
610 const struct wined3d_view_desc *desc, struct wined3d_resource *resource,
611 void *parent, const struct wined3d_parent_ops *parent_ops)
613 TRACE("view_no3d %p, desc %s, resource %p, parent %p, parent_ops %p.\n",
614 view_no3d, wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops);
616 return wined3d_rendertarget_view_init(view_no3d, desc, resource, parent, parent_ops);
619 HRESULT wined3d_rendertarget_view_gl_init(struct wined3d_rendertarget_view_gl *view_gl,
620 const struct wined3d_view_desc *desc, struct wined3d_resource *resource,
621 void *parent, const struct wined3d_parent_ops *parent_ops)
623 HRESULT hr;
625 TRACE("view_gl %p, desc %s, resource %p, parent %p, parent_ops %p.\n",
626 view_gl, wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops);
628 if (FAILED(hr = wined3d_rendertarget_view_init(&view_gl->v, desc, resource, parent, parent_ops)))
629 return hr;
631 wined3d_cs_init_object(resource->device->cs, wined3d_render_target_view_gl_cs_init, view_gl);
633 return hr;
636 VkImageViewType vk_image_view_type_from_wined3d(enum wined3d_resource_type type, uint32_t flags)
638 switch (type)
640 case WINED3D_RTYPE_TEXTURE_1D:
641 if (flags & WINED3D_VIEW_TEXTURE_ARRAY)
642 return VK_IMAGE_VIEW_TYPE_1D_ARRAY;
643 else
644 return VK_IMAGE_VIEW_TYPE_1D;
646 case WINED3D_RTYPE_TEXTURE_2D:
647 if (flags & WINED3D_VIEW_TEXTURE_CUBE)
649 if (flags & WINED3D_VIEW_TEXTURE_ARRAY)
650 return VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
651 else
652 return VK_IMAGE_VIEW_TYPE_CUBE;
654 if (flags & WINED3D_VIEW_TEXTURE_ARRAY)
655 return VK_IMAGE_VIEW_TYPE_2D_ARRAY;
656 else
657 return VK_IMAGE_VIEW_TYPE_2D;
659 case WINED3D_RTYPE_TEXTURE_3D:
660 return VK_IMAGE_VIEW_TYPE_3D;
662 default:
663 ERR("Unhandled resource type %s.\n", debug_d3dresourcetype(type));
664 return ~0u;
668 static VkBufferView wined3d_view_vk_create_vk_buffer_view(struct wined3d_context_vk *context_vk,
669 const struct wined3d_view_desc *desc, struct wined3d_buffer_vk *buffer_vk,
670 const struct wined3d_format_vk *view_format_vk)
672 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
673 VkBufferViewCreateInfo create_info;
674 struct wined3d_device_vk *device_vk;
675 VkBufferView vk_buffer_view;
676 unsigned int offset, size;
677 struct wined3d_bo_vk *bo;
678 VkResult vr;
680 get_buffer_view_range(&buffer_vk->b, desc, &view_format_vk->f, &offset, &size);
681 wined3d_buffer_prepare_location(&buffer_vk->b, &context_vk->c, WINED3D_LOCATION_BUFFER);
682 bo = wined3d_bo_vk(buffer_vk->b.buffer_object);
684 create_info.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO;
685 create_info.pNext = NULL;
686 create_info.flags = 0;
687 create_info.buffer = bo->vk_buffer;
688 create_info.format = view_format_vk->vk_format;
689 create_info.offset = bo->b.buffer_offset + offset;
690 create_info.range = size;
692 device_vk = wined3d_device_vk(buffer_vk->b.resource.device);
693 if ((vr = VK_CALL(vkCreateBufferView(device_vk->vk_device, &create_info, NULL, &vk_buffer_view))) < 0)
695 ERR("Failed to create buffer view, vr %s.\n", wined3d_debug_vkresult(vr));
696 return VK_NULL_HANDLE;
699 return vk_buffer_view;
702 static VkImageView wined3d_view_vk_create_vk_image_view(struct wined3d_context_vk *context_vk,
703 const struct wined3d_view_desc *desc, struct wined3d_texture_vk *texture_vk,
704 const struct wined3d_format_vk *view_format_vk, struct color_fixup_desc fixup, bool rtv)
706 const struct wined3d_resource *resource = &texture_vk->t.resource;
707 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
708 const struct wined3d_format_vk *format_vk;
709 struct wined3d_device_vk *device_vk;
710 VkImageViewCreateInfo create_info;
711 VkImageView vk_image_view;
712 VkResult vr;
714 device_vk = wined3d_device_vk(resource->device);
716 if (!wined3d_texture_vk_prepare_texture(texture_vk, context_vk))
718 ERR("Failed to prepare texture.\n");
719 return VK_NULL_HANDLE;
722 /* Depth formats are a little complicated. For example, the typeless
723 * format corresponding to depth/stencil view format WINED3DFMT_D32_FLOAT
724 * is WINED3DFMT_R32_TYPELESS, and the corresponding shader resource view
725 * format would be WINED3DFMT_R32_FLOAT. Vulkan depth/stencil formats are
726 * only compatible with themselves, so it's not possible to create e.g. a
727 * VK_FORMAT_R32_SFLOAT view on a VK_FORMAT_D32_SFLOAT image. In order to
728 * make it work, we create Vulkan images for WINED3DFMT_R32_TYPELESS
729 * resources with either a depth format (VK_FORMAT_D32_SFLOAT) or a colour
730 * format, depending on whether the bind flags include
731 * WINED3D_BIND_DEPTH_STENCIL or not. In order to then create a Vulkan
732 * view on the image, we then replace the view format here with the
733 * underlying resource format. However, that means it's still not possible
734 * to create e.g. a WINED3DFMT_R32_UINT view on a WINED3DFMT_R32_TYPELESS
735 * depth/stencil resource. */
736 if (resource->bind_flags & WINED3D_BIND_DEPTH_STENCIL)
737 format_vk = wined3d_format_vk(resource->format);
738 else
739 format_vk = view_format_vk;
741 create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
742 create_info.pNext = NULL;
743 create_info.flags = 0;
744 create_info.image = texture_vk->image.vk_image;
745 create_info.viewType = vk_image_view_type_from_wined3d(resource->type, desc->flags);
746 if (rtv && create_info.viewType == VK_IMAGE_VIEW_TYPE_3D)
748 if (desc->u.texture.layer_count > 1)
749 create_info.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
750 else
751 create_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
753 create_info.format = format_vk->vk_format;
754 if (is_stencil_view_format(&view_format_vk->f))
756 create_info.components.r = VK_COMPONENT_SWIZZLE_ZERO;
757 create_info.components.g = VK_COMPONENT_SWIZZLE_R;
758 create_info.components.b = VK_COMPONENT_SWIZZLE_ZERO;
759 create_info.components.a = VK_COMPONENT_SWIZZLE_ZERO;
761 else if (is_identity_fixup(fixup) || !can_use_texture_swizzle(context_vk->c.d3d_info, &format_vk->f))
763 create_info.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
764 create_info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
765 create_info.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
766 create_info.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
768 else
770 wined3d_vk_swizzle_from_color_fixup(&create_info.components, fixup);
772 if ((resource->bind_flags & WINED3D_BIND_DEPTH_STENCIL)
773 && (view_format_vk->f.red_size || view_format_vk->f.green_size))
775 create_info.subresourceRange.aspectMask = 0;
776 if (view_format_vk->f.red_size)
777 create_info.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
778 if (view_format_vk->f.green_size)
779 create_info.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
781 else
783 create_info.subresourceRange.aspectMask = vk_aspect_mask_from_format(&format_vk->f);
785 create_info.subresourceRange.baseMipLevel = desc->u.texture.level_idx;
786 create_info.subresourceRange.levelCount = desc->u.texture.level_count;
787 if (create_info.viewType == VK_IMAGE_VIEW_TYPE_3D)
789 if (desc->u.texture.layer_idx || (desc->u.texture.layer_count != texture_vk->t.resource.depth
790 && desc->u.texture.layer_count != ~0u))
791 WARN("Partial 3D texture views are not supported.\n");
792 create_info.subresourceRange.baseArrayLayer = 0;
793 create_info.subresourceRange.layerCount = 1;
795 else
797 create_info.subresourceRange.baseArrayLayer = desc->u.texture.layer_idx;
798 create_info.subresourceRange.layerCount = desc->u.texture.layer_count;
800 if ((vr = VK_CALL(vkCreateImageView(device_vk->vk_device, &create_info, NULL, &vk_image_view))) < 0)
802 ERR("Failed to create Vulkan image view, vr %s.\n", wined3d_debug_vkresult(vr));
803 return VK_NULL_HANDLE;
806 return vk_image_view;
809 static void wined3d_render_target_view_vk_cs_init(void *object)
811 struct wined3d_rendertarget_view_vk *view_vk = object;
812 struct wined3d_view_desc *desc = &view_vk->v.desc;
813 const struct wined3d_format_vk *format_vk;
814 struct wined3d_texture_vk *texture_vk;
815 struct wined3d_resource *resource;
816 struct wined3d_context *context;
817 uint32_t default_flags = 0;
819 TRACE("view_vk %p.\n", view_vk);
821 resource = view_vk->v.resource;
822 if (resource->type == WINED3D_RTYPE_BUFFER)
824 FIXME("Buffer views not implemented.\n");
825 return;
828 texture_vk = wined3d_texture_vk(texture_from_resource(resource));
829 format_vk = wined3d_format_vk(view_vk->v.format);
831 if (texture_vk->t.layer_count > 1)
832 default_flags |= WINED3D_VIEW_TEXTURE_ARRAY;
834 if (resource->format->id == format_vk->f.id && desc->flags == default_flags
835 && !desc->u.texture.level_idx && desc->u.texture.level_count == texture_vk->t.level_count
836 && !desc->u.texture.layer_idx && desc->u.texture.layer_count == texture_vk->t.layer_count
837 && !is_stencil_view_format(&format_vk->f) && resource->type != WINED3D_RTYPE_TEXTURE_3D
838 && is_identity_fixup(format_vk->f.color_fixup))
840 TRACE("Creating identity render target view.\n");
841 return;
844 if (texture_vk->t.swapchain && texture_vk->t.swapchain->state.desc.backbuffer_count > 1)
846 FIXME("Swapchain views not supported.\n");
847 return;
850 context = context_acquire(resource->device, NULL, 0);
851 view_vk->vk_image_view = wined3d_view_vk_create_vk_image_view(wined3d_context_vk(context),
852 desc, texture_vk, format_vk, COLOR_FIXUP_IDENTITY, true);
853 context_release(context);
855 if (!view_vk->vk_image_view)
856 return;
858 TRACE("Created image view 0x%s.\n", wine_dbgstr_longlong(view_vk->vk_image_view));
861 HRESULT wined3d_rendertarget_view_vk_init(struct wined3d_rendertarget_view_vk *view_vk,
862 const struct wined3d_view_desc *desc, struct wined3d_resource *resource,
863 void *parent, const struct wined3d_parent_ops *parent_ops)
865 HRESULT hr;
867 TRACE("view_vk %p, desc %s, resource %p, parent %p, parent_ops %p.\n",
868 view_vk, wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops);
870 if (FAILED(hr = wined3d_rendertarget_view_init(&view_vk->v, desc, resource, parent, parent_ops)))
871 return hr;
873 wined3d_cs_init_object(resource->device->cs, wined3d_render_target_view_vk_cs_init, view_vk);
875 return hr;
878 HRESULT CDECL wined3d_rendertarget_view_create(const struct wined3d_view_desc *desc,
879 struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops,
880 struct wined3d_rendertarget_view **view)
882 const struct wined3d_adapter_ops *adapter_ops;
884 TRACE("desc %s, resource %p, parent %p, parent_ops %p, view %p.\n",
885 wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops, view);
887 adapter_ops = resource->device->adapter->adapter_ops;
888 return adapter_ops->adapter_create_rendertarget_view(desc, resource, parent, parent_ops, view);
891 HRESULT CDECL wined3d_rendertarget_view_create_from_sub_resource(struct wined3d_texture *texture,
892 unsigned int sub_resource_idx, void *parent, const struct wined3d_parent_ops *parent_ops,
893 struct wined3d_rendertarget_view **view)
895 struct wined3d_view_desc desc;
897 TRACE("texture %p, sub_resource_idx %u, parent %p, parent_ops %p, view %p.\n",
898 texture, sub_resource_idx, parent, parent_ops, view);
900 desc.format_id = texture->resource.format->id;
901 desc.flags = 0;
902 desc.u.texture.level_idx = sub_resource_idx % texture->level_count;
903 desc.u.texture.level_count = 1;
904 desc.u.texture.layer_idx = sub_resource_idx / texture->level_count;
905 desc.u.texture.layer_count = 1;
907 return wined3d_rendertarget_view_create(&desc, &texture->resource, parent, parent_ops, view);
910 ULONG CDECL wined3d_shader_resource_view_incref(struct wined3d_shader_resource_view *view)
912 ULONG refcount = InterlockedIncrement(&view->refcount);
914 TRACE("%p increasing refcount to %u.\n", view, refcount);
916 return refcount;
919 void wined3d_shader_resource_view_cleanup(struct wined3d_shader_resource_view *view)
921 /* Call wined3d_object_destroyed() before releasing the resource,
922 * since releasing the resource may end up destroying the parent. */
923 view->parent_ops->wined3d_object_destroyed(view->parent);
924 wined3d_resource_decref(view->resource);
927 ULONG CDECL wined3d_shader_resource_view_decref(struct wined3d_shader_resource_view *view)
929 ULONG refcount = InterlockedDecrement(&view->refcount);
931 TRACE("%p decreasing refcount to %u.\n", view, refcount);
933 if (!refcount)
935 wined3d_mutex_lock();
936 view->resource->device->adapter->adapter_ops->adapter_destroy_shader_resource_view(view);
937 wined3d_mutex_unlock();
940 return refcount;
943 void * CDECL wined3d_shader_resource_view_get_parent(const struct wined3d_shader_resource_view *view)
945 TRACE("view %p.\n", view);
947 return view->parent;
950 void wined3d_shader_resource_view_gl_update(struct wined3d_shader_resource_view_gl *srv_gl,
951 struct wined3d_context_gl *context_gl)
953 create_buffer_view(&srv_gl->gl_view, &context_gl->c, &srv_gl->v.desc,
954 buffer_from_resource(srv_gl->v.resource), srv_gl->v.format);
955 srv_gl->bo_user.valid = true;
958 static void wined3d_shader_resource_view_gl_cs_init(void *object)
960 struct wined3d_shader_resource_view_gl *view_gl = object;
961 struct wined3d_resource *resource = view_gl->v.resource;
962 const struct wined3d_format *view_format;
963 const struct wined3d_gl_info *gl_info;
964 const struct wined3d_view_desc *desc;
965 GLenum view_target;
967 TRACE("view_gl %p.\n", view_gl);
969 view_format = view_gl->v.format;
970 gl_info = &resource->device->adapter->gl_info;
971 desc = &view_gl->v.desc;
973 if (resource->type == WINED3D_RTYPE_BUFFER)
975 struct wined3d_buffer *buffer = buffer_from_resource(resource);
976 struct wined3d_context *context;
978 context = context_acquire(resource->device, NULL, 0);
979 create_buffer_view(&view_gl->gl_view, context, desc, buffer, view_format);
980 view_gl->bo_user.valid = true;
981 list_add_head(&buffer->buffer_object->users, &view_gl->bo_user.entry);
982 context_release(context);
984 else
986 struct wined3d_texture_gl *texture_gl = wined3d_texture_gl(texture_from_resource(resource));
987 GLenum resource_class, view_class;
989 resource_class = wined3d_format_gl(resource->format)->view_class;
990 view_class = wined3d_format_gl(view_format)->view_class;
991 view_target = get_texture_view_target(gl_info, desc, texture_gl);
993 if (resource->format->id == view_format->id && texture_gl->target == view_target
994 && !desc->u.texture.level_idx && desc->u.texture.level_count == texture_gl->t.level_count
995 && !desc->u.texture.layer_idx && desc->u.texture.layer_count == texture_gl->t.layer_count
996 && !is_stencil_view_format(view_format))
998 TRACE("Creating identity shader resource view.\n");
1000 else if (texture_gl->t.swapchain && texture_gl->t.swapchain->state.desc.backbuffer_count > 1)
1002 FIXME("Swapchain shader resource views not supported.\n");
1004 else if (resource->format->typeless_id == view_format->typeless_id
1005 && resource_class == view_class)
1007 create_texture_view(&view_gl->gl_view, view_target, desc, texture_gl, view_format);
1009 else if (wined3d_format_is_depth_view(resource->format->id, view_format->id))
1011 create_texture_view(&view_gl->gl_view, view_target, desc, texture_gl, resource->format);
1013 else
1015 FIXME("Shader resource view not supported, resource format %s, view format %s.\n",
1016 debug_d3dformat(resource->format->id), debug_d3dformat(view_format->id));
1021 static HRESULT wined3d_shader_resource_view_init(struct wined3d_shader_resource_view *view,
1022 const struct wined3d_view_desc *desc, struct wined3d_resource *resource,
1023 void *parent, const struct wined3d_parent_ops *parent_ops)
1025 view->refcount = 1;
1026 view->parent = parent;
1027 view->parent_ops = parent_ops;
1029 if (!(resource->bind_flags & WINED3D_BIND_SHADER_RESOURCE))
1030 return E_INVALIDARG;
1031 if (!(view->format = validate_resource_view(desc, resource, FALSE, FALSE)))
1032 return E_INVALIDARG;
1033 view->desc = *desc;
1035 wined3d_resource_incref(view->resource = resource);
1037 return WINED3D_OK;
1040 HRESULT wined3d_shader_resource_view_gl_init(struct wined3d_shader_resource_view_gl *view_gl,
1041 const struct wined3d_view_desc *desc, struct wined3d_resource *resource,
1042 void *parent, const struct wined3d_parent_ops *parent_ops)
1044 HRESULT hr;
1046 TRACE("view_gl %p, desc %s, resource %p, parent %p, parent_ops %p.\n",
1047 view_gl, wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops);
1049 if (FAILED(hr = wined3d_shader_resource_view_init(&view_gl->v, desc, resource, parent, parent_ops)))
1050 return hr;
1052 list_init(&view_gl->bo_user.entry);
1053 wined3d_cs_init_object(resource->device->cs, wined3d_shader_resource_view_gl_cs_init, view_gl);
1055 return hr;
1058 void wined3d_shader_resource_view_vk_update(struct wined3d_shader_resource_view_vk *srv_vk,
1059 struct wined3d_context_vk *context_vk)
1061 const struct wined3d_format_vk *view_format_vk = wined3d_format_vk(srv_vk->v.format);
1062 const struct wined3d_view_desc *desc = &srv_vk->v.desc;
1063 struct wined3d_resource *resource = srv_vk->v.resource;
1064 struct wined3d_view_vk *view_vk = &srv_vk->view_vk;
1065 struct wined3d_buffer_vk *buffer_vk;
1066 VkBufferView vk_buffer_view;
1068 buffer_vk = wined3d_buffer_vk(buffer_from_resource(resource));
1069 wined3d_context_vk_destroy_vk_buffer_view(context_vk, view_vk->u.vk_buffer_view, view_vk->command_buffer_id);
1070 if ((vk_buffer_view = wined3d_view_vk_create_vk_buffer_view(context_vk, desc, buffer_vk, view_format_vk)))
1072 view_vk->u.vk_buffer_view = vk_buffer_view;
1073 view_vk->bo_user.valid = true;
1077 static void wined3d_shader_resource_view_vk_cs_init(void *object)
1079 struct wined3d_shader_resource_view_vk *srv_vk = object;
1080 struct wined3d_view_desc *desc = &srv_vk->v.desc;
1081 struct wined3d_texture_vk *texture_vk;
1082 const struct wined3d_format *format;
1083 struct wined3d_buffer_vk *buffer_vk;
1084 struct wined3d_resource *resource;
1085 struct wined3d_context *context;
1086 VkBufferView vk_buffer_view;
1087 uint32_t default_flags = 0;
1088 VkImageView vk_image_view;
1089 struct wined3d_bo_vk *bo;
1091 TRACE("srv_vk %p.\n", srv_vk);
1093 resource = srv_vk->v.resource;
1094 format = srv_vk->v.format;
1096 if (resource->type == WINED3D_RTYPE_BUFFER)
1098 buffer_vk = wined3d_buffer_vk(buffer_from_resource(resource));
1100 context = context_acquire(resource->device, NULL, 0);
1101 vk_buffer_view = wined3d_view_vk_create_vk_buffer_view(wined3d_context_vk(context),
1102 desc, buffer_vk, wined3d_format_vk(format));
1103 context_release(context);
1105 if (!vk_buffer_view)
1106 return;
1107 bo = wined3d_bo_vk(buffer_vk->b.buffer_object);
1109 TRACE("Created buffer view 0x%s.\n", wine_dbgstr_longlong(vk_buffer_view));
1111 srv_vk->view_vk.u.vk_buffer_view = vk_buffer_view;
1112 srv_vk->view_vk.bo_user.valid = true;
1113 list_add_head(&bo->b.users, &srv_vk->view_vk.bo_user.entry);
1115 return;
1118 texture_vk = wined3d_texture_vk(texture_from_resource(resource));
1120 if (texture_vk->t.layer_count > 1)
1121 default_flags |= WINED3D_VIEW_TEXTURE_ARRAY;
1123 if (resource->format->id == format->id && desc->flags == default_flags
1124 && !desc->u.texture.level_idx && desc->u.texture.level_count == texture_vk->t.level_count
1125 && !desc->u.texture.layer_idx && desc->u.texture.layer_count == texture_vk->t.layer_count
1126 && !(resource->bind_flags & WINED3D_BIND_DEPTH_STENCIL))
1128 TRACE("Creating identity shader resource view.\n");
1129 return;
1132 if (texture_vk->t.swapchain && texture_vk->t.swapchain->state.desc.backbuffer_count > 1)
1133 FIXME("Swapchain shader resource views not supported.\n");
1135 context = context_acquire(resource->device, NULL, 0);
1136 vk_image_view = wined3d_view_vk_create_vk_image_view(wined3d_context_vk(context),
1137 desc, texture_vk, wined3d_format_vk(format), format->color_fixup, false);
1138 context_release(context);
1140 if (!vk_image_view)
1141 return;
1143 TRACE("Created image view 0x%s.\n", wine_dbgstr_longlong(vk_image_view));
1145 srv_vk->view_vk.u.vk_image_info.imageView = vk_image_view;
1146 srv_vk->view_vk.u.vk_image_info.sampler = VK_NULL_HANDLE;
1147 srv_vk->view_vk.u.vk_image_info.imageLayout = texture_vk->layout;
1150 HRESULT wined3d_shader_resource_view_vk_init(struct wined3d_shader_resource_view_vk *view_vk,
1151 const struct wined3d_view_desc *desc, struct wined3d_resource *resource,
1152 void *parent, const struct wined3d_parent_ops *parent_ops)
1154 HRESULT hr;
1156 TRACE("view_vk %p, desc %s, resource %p, parent %p, parent_ops %p.\n",
1157 view_vk, wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops);
1159 if (FAILED(hr = wined3d_shader_resource_view_init(&view_vk->v, desc, resource, parent, parent_ops)))
1160 return hr;
1162 list_init(&view_vk->view_vk.bo_user.entry);
1163 wined3d_cs_init_object(resource->device->cs, wined3d_shader_resource_view_vk_cs_init, view_vk);
1165 return hr;
1168 HRESULT CDECL wined3d_shader_resource_view_create(const struct wined3d_view_desc *desc,
1169 struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops,
1170 struct wined3d_shader_resource_view **view)
1172 const struct wined3d_adapter_ops *adapter_ops;
1174 TRACE("desc %s, resource %p, parent %p, parent_ops %p, view %p.\n",
1175 wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops, view);
1177 adapter_ops = resource->device->adapter->adapter_ops;
1178 return adapter_ops->adapter_create_shader_resource_view(desc, resource, parent, parent_ops, view);
1181 void wined3d_shader_resource_view_gl_bind(struct wined3d_shader_resource_view_gl *view_gl,
1182 unsigned int unit, struct wined3d_sampler_gl *sampler_gl, struct wined3d_context_gl *context_gl)
1184 const struct wined3d_gl_info *gl_info = context_gl->gl_info;
1185 struct wined3d_texture_gl *texture_gl;
1187 wined3d_context_gl_active_texture(context_gl, gl_info, unit);
1189 if (view_gl->gl_view.name)
1191 wined3d_context_gl_bind_texture(context_gl, view_gl->gl_view.target, view_gl->gl_view.name);
1192 wined3d_sampler_gl_bind(sampler_gl, unit, NULL, context_gl);
1193 return;
1196 if (view_gl->v.resource->type == WINED3D_RTYPE_BUFFER)
1198 FIXME("Buffer shader resources not supported.\n");
1199 return;
1202 texture_gl = wined3d_texture_gl(wined3d_texture_from_resource(view_gl->v.resource));
1203 wined3d_texture_gl_bind(texture_gl, context_gl, FALSE);
1204 wined3d_sampler_gl_bind(sampler_gl, unit, texture_gl, context_gl);
1207 /* Context activation is done by the caller. */
1208 static void shader_resource_view_gl_bind_and_dirtify(struct wined3d_shader_resource_view_gl *view_gl,
1209 struct wined3d_context_gl *context_gl)
1211 if (context_gl->active_texture < ARRAY_SIZE(context_gl->rev_tex_unit_map))
1213 unsigned int active_sampler = context_gl->rev_tex_unit_map[context_gl->active_texture];
1214 if (active_sampler != WINED3D_UNMAPPED_STAGE)
1215 context_invalidate_state(&context_gl->c, STATE_SAMPLER(active_sampler));
1217 /* FIXME: Ideally we'd only do this when touching a binding that's used by
1218 * a shader. */
1219 context_invalidate_compute_state(&context_gl->c, STATE_COMPUTE_SHADER_RESOURCE_BINDING);
1220 context_invalidate_state(&context_gl->c, STATE_GRAPHICS_SHADER_RESOURCE_BINDING);
1222 wined3d_context_gl_bind_texture(context_gl, view_gl->gl_view.target, view_gl->gl_view.name);
1225 void wined3d_shader_resource_view_gl_generate_mipmap(struct wined3d_shader_resource_view_gl *view_gl,
1226 struct wined3d_context_gl *context_gl)
1228 unsigned int i, j, layer_count, level_count, base_level, base_layer, sub_resource_idx;
1229 const struct wined3d_gl_info *gl_info = context_gl->gl_info;
1230 struct wined3d_texture_gl *texture_gl;
1231 struct gl_texture *gl_tex;
1232 DWORD location;
1233 BOOL srgb;
1235 TRACE("view_gl %p.\n", view_gl);
1237 layer_count = view_gl->v.desc.u.texture.layer_count;
1238 level_count = view_gl->v.desc.u.texture.level_count;
1239 base_level = view_gl->v.desc.u.texture.level_idx;
1240 base_layer = view_gl->v.desc.u.texture.layer_idx;
1242 texture_gl = wined3d_texture_gl(texture_from_resource(view_gl->v.resource));
1243 srgb = !!(texture_gl->t.flags & WINED3D_TEXTURE_IS_SRGB);
1244 location = srgb ? WINED3D_LOCATION_TEXTURE_SRGB : WINED3D_LOCATION_TEXTURE_RGB;
1245 for (i = 0; i < layer_count; ++i)
1247 sub_resource_idx = (base_layer + i) * texture_gl->t.level_count + base_level;
1248 if (!wined3d_texture_load_location(&texture_gl->t, sub_resource_idx, &context_gl->c, location))
1249 ERR("Failed to load source layer %u.\n", base_layer + i);
1252 if (view_gl->gl_view.name)
1254 shader_resource_view_gl_bind_and_dirtify(view_gl, context_gl);
1256 else
1258 wined3d_texture_gl_bind_and_dirtify(texture_gl, context_gl, srgb);
1259 gl_info->gl_ops.gl.p_glTexParameteri(texture_gl->target, GL_TEXTURE_BASE_LEVEL, base_level);
1260 gl_info->gl_ops.gl.p_glTexParameteri(texture_gl->target, GL_TEXTURE_MAX_LEVEL, base_level + level_count - 1);
1263 if (gl_info->supported[ARB_SAMPLER_OBJECTS])
1264 GL_EXTCALL(glBindSampler(context_gl->active_texture, 0));
1265 gl_tex = wined3d_texture_gl_get_gl_texture(texture_gl, srgb);
1266 if (context_gl->c.d3d_info->wined3d_creation_flags & WINED3D_SRGB_READ_WRITE_CONTROL)
1268 gl_info->gl_ops.gl.p_glTexParameteri(texture_gl->target,
1269 GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT);
1270 gl_tex->sampler_desc.srgb_decode = FALSE;
1273 gl_info->fbo_ops.glGenerateMipmap(texture_gl->target);
1274 checkGLcall("glGenerateMipMap()");
1276 for (i = 0; i < layer_count; ++i)
1278 for (j = 1; j < level_count; ++j)
1280 sub_resource_idx = (base_layer + i) * texture_gl->t.level_count + base_level + j;
1281 wined3d_texture_validate_location(&texture_gl->t, sub_resource_idx, location);
1282 wined3d_texture_invalidate_location(&texture_gl->t, sub_resource_idx, ~location);
1286 if (!view_gl->gl_view.name)
1288 gl_tex->base_level = base_level;
1289 gl_info->gl_ops.gl.p_glTexParameteri(texture_gl->target,
1290 GL_TEXTURE_MAX_LEVEL, texture_gl->t.level_count - 1);
1294 void wined3d_shader_resource_view_vk_generate_mipmap(struct wined3d_shader_resource_view_vk *srv_vk,
1295 struct wined3d_context_vk *context_vk)
1297 unsigned int i, j, layer_count, level_count, base_level, base_layer, sub_resource_idx;
1298 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1299 VkImageSubresourceRange vk_src_range, vk_dst_range;
1300 struct wined3d_texture_vk *texture_vk;
1301 VkCommandBuffer vk_command_buffer;
1302 VkImageBlit region;
1304 TRACE("srv_vk %p.\n", srv_vk);
1306 layer_count = srv_vk->v.desc.u.texture.layer_count;
1307 level_count = srv_vk->v.desc.u.texture.level_count;
1308 base_level = srv_vk->v.desc.u.texture.level_idx;
1309 base_layer = srv_vk->v.desc.u.texture.layer_idx;
1311 texture_vk = wined3d_texture_vk(texture_from_resource(srv_vk->v.resource));
1312 for (i = 0; i < layer_count; ++i)
1314 sub_resource_idx = (base_layer + i) * texture_vk->t.level_count + base_level;
1315 if (!wined3d_texture_load_location(&texture_vk->t, sub_resource_idx,
1316 &context_vk->c, WINED3D_LOCATION_TEXTURE_RGB))
1317 ERR("Failed to load source layer %u.\n", base_layer + i);
1320 if (context_vk->c.d3d_info->wined3d_creation_flags & WINED3D_SRGB_READ_WRITE_CONTROL)
1321 FIXME("Unhandled sRGB read/write control.\n");
1323 if (wined3d_format_vk(srv_vk->v.format)->vk_format != wined3d_format_vk(texture_vk->t.resource.format)->vk_format)
1324 FIXME("Ignoring view format %s.\n", debug_d3dformat(srv_vk->v.format->id));
1326 if (wined3d_resource_get_sample_count(&texture_vk->t.resource) > 1)
1327 FIXME("Unhandled multi-sampled resource.\n");
1329 if (!(vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk)))
1331 ERR("Failed to get command buffer.\n");
1332 return;
1335 vk_src_range.aspectMask = vk_aspect_mask_from_format(texture_vk->t.resource.format);
1336 vk_src_range.baseMipLevel = base_level;
1337 vk_src_range.levelCount = 1;
1338 vk_src_range.baseArrayLayer = base_layer;
1339 vk_src_range.layerCount = layer_count;
1341 vk_dst_range = vk_src_range;
1342 ++vk_dst_range.baseMipLevel;
1344 wined3d_context_vk_image_barrier(context_vk, vk_command_buffer,
1345 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
1346 vk_access_mask_from_bind_flags(texture_vk->t.resource.bind_flags),
1347 VK_ACCESS_TRANSFER_READ_BIT,
1348 texture_vk->layout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1349 texture_vk->image.vk_image, &vk_src_range);
1350 wined3d_context_vk_image_barrier(context_vk, vk_command_buffer,
1351 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
1352 vk_access_mask_from_bind_flags(texture_vk->t.resource.bind_flags),
1353 VK_ACCESS_TRANSFER_WRITE_BIT,
1354 texture_vk->layout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1355 texture_vk->image.vk_image, &vk_dst_range);
1357 region.srcSubresource.aspectMask = vk_src_range.aspectMask;
1358 region.srcSubresource.mipLevel = vk_src_range.baseMipLevel;
1359 region.srcSubresource.baseArrayLayer = vk_src_range.baseArrayLayer;
1360 region.srcSubresource.layerCount = vk_src_range.layerCount;
1361 region.srcOffsets[0].x = 0;
1362 region.srcOffsets[0].y = 0;
1363 region.srcOffsets[0].z = 0;
1365 region.dstSubresource.aspectMask = vk_dst_range.aspectMask;
1366 region.dstSubresource.mipLevel = vk_dst_range.baseMipLevel;
1367 region.dstSubresource.baseArrayLayer = vk_dst_range.baseArrayLayer;
1368 region.dstSubresource.layerCount = vk_dst_range.layerCount;
1369 region.dstOffsets[0].x = 0;
1370 region.dstOffsets[0].y = 0;
1371 region.dstOffsets[0].z = 0;
1373 for (i = 1; i < level_count; ++i)
1375 region.srcOffsets[1].x = wined3d_texture_get_level_width(&texture_vk->t, vk_src_range.baseMipLevel);
1376 region.srcOffsets[1].y = wined3d_texture_get_level_height(&texture_vk->t, vk_src_range.baseMipLevel);
1377 region.srcOffsets[1].z = wined3d_texture_get_level_depth(&texture_vk->t, vk_src_range.baseMipLevel);
1379 region.dstOffsets[1].x = wined3d_texture_get_level_width(&texture_vk->t, vk_dst_range.baseMipLevel);
1380 region.dstOffsets[1].y = wined3d_texture_get_level_height(&texture_vk->t, vk_dst_range.baseMipLevel);
1381 region.dstOffsets[1].z = wined3d_texture_get_level_depth(&texture_vk->t, vk_dst_range.baseMipLevel);
1383 VK_CALL(vkCmdBlitImage(vk_command_buffer, texture_vk->image.vk_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1384 texture_vk->image.vk_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region, VK_FILTER_LINEAR));
1386 wined3d_context_vk_image_barrier(context_vk, vk_command_buffer,
1387 VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
1388 VK_ACCESS_TRANSFER_READ_BIT,
1389 vk_access_mask_from_bind_flags(texture_vk->t.resource.bind_flags),
1390 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, texture_vk->layout,
1391 texture_vk->image.vk_image, &vk_src_range);
1393 if (i == level_count - 1)
1395 wined3d_context_vk_image_barrier(context_vk, vk_command_buffer,
1396 VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
1397 VK_ACCESS_TRANSFER_WRITE_BIT,
1398 vk_access_mask_from_bind_flags(texture_vk->t.resource.bind_flags),
1399 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, texture_vk->layout,
1400 texture_vk->image.vk_image, &vk_dst_range);
1402 else
1404 region.srcSubresource.mipLevel = ++vk_src_range.baseMipLevel;
1405 region.dstSubresource.mipLevel = ++vk_dst_range.baseMipLevel;
1407 wined3d_context_vk_image_barrier(context_vk, vk_command_buffer,
1408 VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
1409 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
1410 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1411 texture_vk->image.vk_image, &vk_src_range);
1412 wined3d_context_vk_image_barrier(context_vk, vk_command_buffer,
1413 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
1414 vk_access_mask_from_bind_flags(texture_vk->t.resource.bind_flags),
1415 VK_ACCESS_TRANSFER_WRITE_BIT,
1416 texture_vk->layout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1417 texture_vk->image.vk_image, &vk_dst_range);
1421 for (i = 0; i < layer_count; ++i)
1423 for (j = 1; j < level_count; ++j)
1425 sub_resource_idx = (base_layer + i) * texture_vk->t.level_count + base_level + j;
1426 wined3d_texture_validate_location(&texture_vk->t, sub_resource_idx, WINED3D_LOCATION_TEXTURE_RGB);
1427 wined3d_texture_invalidate_location(&texture_vk->t, sub_resource_idx, ~WINED3D_LOCATION_TEXTURE_RGB);
1431 wined3d_context_vk_reference_texture(context_vk, texture_vk);
1434 ULONG CDECL wined3d_unordered_access_view_incref(struct wined3d_unordered_access_view *view)
1436 ULONG refcount = InterlockedIncrement(&view->refcount);
1438 TRACE("%p increasing refcount to %u.\n", view, refcount);
1440 return refcount;
1443 void wined3d_unordered_access_view_cleanup(struct wined3d_unordered_access_view *view)
1445 /* Call wined3d_object_destroyed() before releasing the resource,
1446 * since releasing the resource may end up destroying the parent. */
1447 view->parent_ops->wined3d_object_destroyed(view->parent);
1448 wined3d_resource_decref(view->resource);
1451 ULONG CDECL wined3d_unordered_access_view_decref(struct wined3d_unordered_access_view *view)
1453 ULONG refcount = InterlockedDecrement(&view->refcount);
1455 TRACE("%p decreasing refcount to %u.\n", view, refcount);
1457 if (!refcount)
1459 wined3d_mutex_lock();
1460 view->resource->device->adapter->adapter_ops->adapter_destroy_unordered_access_view(view);
1461 wined3d_mutex_unlock();
1464 return refcount;
1467 void * CDECL wined3d_unordered_access_view_get_parent(const struct wined3d_unordered_access_view *view)
1469 TRACE("view %p.\n", view);
1471 return view->parent;
1474 void wined3d_unordered_access_view_invalidate_location(struct wined3d_unordered_access_view *view,
1475 DWORD location)
1477 wined3d_view_invalidate_location(view->resource, &view->desc, location);
1480 void wined3d_unordered_access_view_gl_clear(struct wined3d_unordered_access_view_gl *view_gl,
1481 const struct wined3d_uvec4 *clear_value, struct wined3d_context_gl *context_gl, bool fp)
1483 const struct wined3d_gl_info *gl_info = context_gl->gl_info;
1484 const struct wined3d_format_gl *format_gl;
1485 struct wined3d_resource *resource;
1486 struct wined3d_buffer *buffer;
1487 struct wined3d_bo_gl *bo_gl;
1488 unsigned int offset, size;
1490 resource = view_gl->v.resource;
1491 if (resource->type != WINED3D_RTYPE_BUFFER)
1493 unsigned int layer_count, level_count, base_level, base_layer;
1494 unsigned int sub_resource_idx, width, height, depth, i, j;
1495 struct wined3d_texture_gl *texture_gl;
1496 const void *data = clear_value;
1497 GLenum gl_format, gl_type;
1498 uint32_t packed;
1500 if (!gl_info->supported[ARB_CLEAR_TEXTURE])
1502 FIXME("OpenGL implementation does not support ARB_clear_texture.\n");
1503 return;
1506 format_gl = wined3d_format_gl(resource->format);
1507 texture_gl = wined3d_texture_gl(texture_from_resource(resource));
1508 layer_count = view_gl->v.desc.u.texture.layer_count;
1509 level_count = view_gl->v.desc.u.texture.level_count;
1510 base_layer = view_gl->v.desc.u.texture.layer_idx;
1511 base_level = view_gl->v.desc.u.texture.level_idx;
1513 if (format_gl->f.byte_count <= 4 && !fp)
1515 gl_format = format_gl->format;
1516 gl_type = format_gl->type;
1517 packed = wined3d_format_pack(&format_gl->f, clear_value);
1518 data = &packed;
1520 else if (resource->format_flags & WINED3DFMT_FLAG_INTEGER)
1522 gl_format = GL_RGBA_INTEGER;
1523 gl_type = GL_UNSIGNED_INT;
1525 else
1527 gl_format = GL_RGBA;
1528 gl_type = GL_FLOAT;
1531 for (i = 0; i < layer_count; ++i)
1533 for (j = 0; j < level_count; ++j)
1535 sub_resource_idx = (base_layer + i) * texture_gl->t.level_count + base_level + j;
1536 wined3d_texture_prepare_location(&texture_gl->t, sub_resource_idx,
1537 &context_gl->c, WINED3D_LOCATION_TEXTURE_RGB);
1539 width = wined3d_texture_get_level_width(&texture_gl->t, base_level + j);
1540 height = wined3d_texture_get_level_height(&texture_gl->t, base_level + j);
1541 depth = wined3d_texture_get_level_depth(&texture_gl->t, base_level + j);
1543 switch (texture_gl->target)
1545 case GL_TEXTURE_1D_ARRAY:
1546 GL_EXTCALL(glClearTexSubImage(texture_gl->texture_rgb.name, base_level + j,
1547 0, base_layer + i, 0, width, 1, 1, gl_format, gl_type, data));
1548 break;
1550 case GL_TEXTURE_2D_ARRAY:
1551 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
1552 case GL_TEXTURE_CUBE_MAP:
1553 case GL_TEXTURE_CUBE_MAP_ARRAY:
1554 GL_EXTCALL(glClearTexSubImage(texture_gl->texture_rgb.name, base_level + j,
1555 0, 0, base_layer + i, width, height, 1, gl_format, gl_type, data));
1556 break;
1558 default:
1559 GL_EXTCALL(glClearTexSubImage(texture_gl->texture_rgb.name, base_level + j,
1560 0, 0, 0, width, height, depth, gl_format, gl_type, data));
1561 break;
1564 wined3d_texture_validate_location(&texture_gl->t, sub_resource_idx, WINED3D_LOCATION_TEXTURE_RGB);
1565 wined3d_texture_invalidate_location(&texture_gl->t, sub_resource_idx, ~WINED3D_LOCATION_TEXTURE_RGB);
1569 return;
1572 if (!gl_info->supported[ARB_CLEAR_BUFFER_OBJECT])
1574 FIXME("OpenGL implementation does not support ARB_clear_buffer_object.\n");
1575 return;
1578 format_gl = wined3d_format_gl(view_gl->v.format);
1579 if (format_gl->f.id != WINED3DFMT_R32_UINT && format_gl->f.id != WINED3DFMT_R32_SINT
1580 && format_gl->f.id != WINED3DFMT_R32G32B32A32_UINT
1581 && format_gl->f.id != WINED3DFMT_R32G32B32A32_SINT)
1583 FIXME("Not implemented for format %s.\n", debug_d3dformat(format_gl->f.id));
1584 return;
1587 if (fp)
1589 FIXME("Floating-point buffer clears not implemented.\n");
1590 return;
1593 buffer = buffer_from_resource(resource);
1594 wined3d_buffer_load_location(buffer, &context_gl->c, WINED3D_LOCATION_BUFFER);
1595 wined3d_unordered_access_view_invalidate_location(&view_gl->v, ~WINED3D_LOCATION_BUFFER);
1597 bo_gl = wined3d_bo_gl(buffer->buffer_object);
1598 get_buffer_view_range(buffer, &view_gl->v.desc, &format_gl->f, &offset, &size);
1599 wined3d_context_gl_bind_bo(context_gl, bo_gl->binding, bo_gl->id);
1600 GL_EXTCALL(glClearBufferSubData(bo_gl->binding, format_gl->internal,
1601 offset, size, format_gl->format, format_gl->type, clear_value));
1602 wined3d_context_gl_reference_bo(context_gl, bo_gl);
1603 checkGLcall("clear unordered access view");
1606 void wined3d_unordered_access_view_set_counter(struct wined3d_unordered_access_view *view,
1607 unsigned int value)
1609 struct wined3d_bo_address dst, src;
1610 struct wined3d_context *context;
1612 if (!view->counter_bo)
1613 return;
1615 context = context_acquire(view->resource->device, NULL, 0);
1617 src.buffer_object = 0;
1618 src.addr = (void *)&value;
1620 dst.buffer_object = view->counter_bo;
1621 dst.addr = NULL;
1623 wined3d_context_copy_bo_address(context, &dst, &src, sizeof(uint32_t));
1625 context_release(context);
1628 void wined3d_unordered_access_view_copy_counter(struct wined3d_unordered_access_view *view,
1629 struct wined3d_buffer *buffer, unsigned int offset, struct wined3d_context *context)
1631 struct wined3d_const_bo_address src;
1633 if (!view->counter_bo)
1634 return;
1636 src.buffer_object = view->counter_bo;
1637 src.addr = NULL;
1639 wined3d_buffer_copy_bo_address(buffer, context, offset, &src, sizeof(uint32_t));
1642 void wined3d_unordered_access_view_gl_update(struct wined3d_unordered_access_view_gl *uav_gl,
1643 struct wined3d_context_gl *context_gl)
1645 create_buffer_view(&uav_gl->gl_view, &context_gl->c, &uav_gl->v.desc,
1646 buffer_from_resource(uav_gl->v.resource), uav_gl->v.format);
1647 uav_gl->bo_user.valid = true;
1650 static void wined3d_unordered_access_view_gl_cs_init(void *object)
1652 struct wined3d_unordered_access_view_gl *view_gl = object;
1653 struct wined3d_resource *resource = view_gl->v.resource;
1654 struct wined3d_view_desc *desc = &view_gl->v.desc;
1655 const struct wined3d_gl_info *gl_info;
1657 TRACE("view_gl %p.\n", view_gl);
1659 gl_info = &resource->device->adapter->gl_info;
1661 if (resource->type == WINED3D_RTYPE_BUFFER)
1663 struct wined3d_buffer *buffer = buffer_from_resource(resource);
1664 struct wined3d_context_gl *context_gl;
1666 context_gl = wined3d_context_gl(context_acquire(resource->device, NULL, 0));
1667 create_buffer_view(&view_gl->gl_view, &context_gl->c, desc, buffer, view_gl->v.format);
1668 view_gl->bo_user.valid = true;
1669 list_add_head(&buffer->buffer_object->users, &view_gl->bo_user.entry);
1670 if (desc->flags & (WINED3D_VIEW_BUFFER_COUNTER | WINED3D_VIEW_BUFFER_APPEND))
1672 struct wined3d_bo_gl *bo = &view_gl->counter_bo;
1674 view_gl->v.counter_bo = &bo->b;
1675 wined3d_context_gl_create_bo(context_gl, sizeof(uint32_t), GL_ATOMIC_COUNTER_BUFFER,
1676 GL_STATIC_DRAW, true, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_CLIENT_STORAGE_BIT, bo);
1677 wined3d_unordered_access_view_set_counter(&view_gl->v, 0);
1679 context_release(&context_gl->c);
1681 else
1683 struct wined3d_texture_gl *texture_gl = wined3d_texture_gl(texture_from_resource(resource));
1684 unsigned int depth_or_layer_count;
1686 if (resource->type == WINED3D_RTYPE_TEXTURE_3D)
1687 depth_or_layer_count = wined3d_texture_get_level_depth(&texture_gl->t, desc->u.texture.level_idx);
1688 else
1689 depth_or_layer_count = texture_gl->t.layer_count;
1691 if (desc->u.texture.layer_idx || desc->u.texture.layer_count != depth_or_layer_count)
1693 create_texture_view(&view_gl->gl_view, get_texture_view_target(gl_info, desc, texture_gl),
1694 desc, texture_gl, view_gl->v.format);
1699 static HRESULT wined3d_unordered_access_view_init(struct wined3d_unordered_access_view *view,
1700 const struct wined3d_view_desc *desc, struct wined3d_resource *resource,
1701 void *parent, const struct wined3d_parent_ops *parent_ops)
1703 view->refcount = 1;
1704 view->parent = parent;
1705 view->parent_ops = parent_ops;
1707 if (!(resource->bind_flags & WINED3D_BIND_UNORDERED_ACCESS))
1708 return E_INVALIDARG;
1709 if (!(view->format = validate_resource_view(desc, resource, TRUE, FALSE)))
1710 return E_INVALIDARG;
1711 view->desc = *desc;
1713 wined3d_resource_incref(view->resource = resource);
1715 return WINED3D_OK;
1718 HRESULT wined3d_unordered_access_view_gl_init(struct wined3d_unordered_access_view_gl *view_gl,
1719 const struct wined3d_view_desc *desc, struct wined3d_resource *resource,
1720 void *parent, const struct wined3d_parent_ops *parent_ops)
1722 HRESULT hr;
1724 TRACE("view_gl %p, desc %s, resource %p, parent %p, parent_ops %p.\n",
1725 view_gl, wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops);
1727 if (FAILED(hr = wined3d_unordered_access_view_init(&view_gl->v, desc, resource, parent, parent_ops)))
1728 return hr;
1730 list_init(&view_gl->bo_user.entry);
1731 wined3d_cs_init_object(resource->device->cs, wined3d_unordered_access_view_gl_cs_init, view_gl);
1733 return hr;
1736 struct wined3d_uav_clear_constants_vk
1738 VkClearColorValue color;
1739 VkOffset2D offset;
1740 VkExtent2D extent;
1743 static VkPipeline create_uav_pipeline(struct wined3d_context_vk *context_vk,
1744 struct wined3d_pipeline_layout_vk *layout, const DWORD *byte_code, size_t byte_code_size,
1745 enum wined3d_shader_resource_type resource_type)
1747 VkComputePipelineCreateInfo pipeline_info;
1748 struct wined3d_shader_desc shader_desc;
1749 const struct wined3d_vk_info *vk_info;
1750 struct wined3d_context *context;
1751 VkShaderModule shader_module;
1752 VkDevice vk_device;
1753 VkPipeline result;
1754 VkResult vr;
1756 vk_info = context_vk->vk_info;
1757 context = &context_vk->c;
1759 shader_desc.byte_code = byte_code;
1760 shader_desc.byte_code_size = byte_code_size;
1762 shader_module = (VkShaderModule)context->device->adapter->shader_backend->shader_compile(context, &shader_desc,
1763 WINED3D_SHADER_TYPE_COMPUTE);
1764 if (shader_module == VK_NULL_HANDLE)
1766 ERR("Failed to create shader.\n");
1767 return VK_NULL_HANDLE;
1770 pipeline_info.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
1771 pipeline_info.pNext = NULL;
1772 pipeline_info.flags = 0;
1773 pipeline_info.stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
1774 pipeline_info.stage.pNext = NULL;
1775 pipeline_info.stage.flags = 0;
1776 pipeline_info.stage.stage = VK_SHADER_STAGE_COMPUTE_BIT;
1777 pipeline_info.stage.pName = "main";
1778 pipeline_info.stage.pSpecializationInfo = NULL;
1779 pipeline_info.stage.module = shader_module;
1780 pipeline_info.layout = layout->vk_pipeline_layout;
1781 pipeline_info.basePipelineHandle = VK_NULL_HANDLE;
1782 pipeline_info.basePipelineIndex = -1;
1784 vk_device = wined3d_device_vk(context->device)->vk_device;
1786 if ((vr = VK_CALL(vkCreateComputePipelines(vk_device, VK_NULL_HANDLE, 1, &pipeline_info, NULL, &result))) < 0)
1788 ERR("Failed to create Vulkan compute pipeline, vr %s.\n", wined3d_debug_vkresult(vr));
1789 return VK_NULL_HANDLE;
1792 VK_CALL(vkDestroyShaderModule(vk_device, shader_module, NULL));
1793 return result;
1796 void wined3d_device_vk_uav_clear_state_init(struct wined3d_device_vk *device_vk)
1798 struct wined3d_uav_clear_state_vk *state = &device_vk->uav_clear_state;
1799 struct wined3d_context_vk *context_vk = &device_vk->context_vk;
1800 VkDescriptorSetLayoutBinding vk_set_bindings[2];
1802 vk_set_bindings[0].binding = 0;
1803 vk_set_bindings[0].descriptorCount = 1;
1804 vk_set_bindings[0].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
1805 vk_set_bindings[0].pImmutableSamplers = NULL;
1806 vk_set_bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
1808 vk_set_bindings[1].binding = 1;
1809 vk_set_bindings[1].descriptorCount = 1;
1810 vk_set_bindings[1].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
1811 vk_set_bindings[1].pImmutableSamplers = NULL;
1813 vk_set_bindings[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
1814 state->image_layout = wined3d_context_vk_get_pipeline_layout(context_vk, vk_set_bindings, 2);
1816 vk_set_bindings[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
1817 state->buffer_layout = wined3d_context_vk_get_pipeline_layout(context_vk, vk_set_bindings, 2);
1819 #define SHADER_DESC(name) name, sizeof(name)
1820 state->float_pipelines.buffer = create_uav_pipeline(context_vk, state->buffer_layout,
1821 SHADER_DESC(cs_uav_clear_buffer_float_code), WINED3D_SHADER_RESOURCE_BUFFER);
1822 state->uint_pipelines.buffer = create_uav_pipeline(context_vk, state->buffer_layout,
1823 SHADER_DESC(cs_uav_clear_buffer_uint_code), WINED3D_SHADER_RESOURCE_BUFFER);
1824 state->float_pipelines.image_1d = create_uav_pipeline(context_vk, state->image_layout,
1825 SHADER_DESC(cs_uav_clear_1d_float_code), WINED3D_SHADER_RESOURCE_TEXTURE_1D);
1826 state->uint_pipelines.image_1d = create_uav_pipeline(context_vk, state->image_layout,
1827 SHADER_DESC(cs_uav_clear_1d_uint_code), WINED3D_SHADER_RESOURCE_TEXTURE_1D);
1828 state->float_pipelines.image_1d_array = create_uav_pipeline(context_vk, state->image_layout,
1829 SHADER_DESC(cs_uav_clear_1d_array_float_code), WINED3D_SHADER_RESOURCE_TEXTURE_1DARRAY);
1830 state->uint_pipelines.image_1d_array = create_uav_pipeline(context_vk, state->image_layout,
1831 SHADER_DESC(cs_uav_clear_1d_array_uint_code), WINED3D_SHADER_RESOURCE_TEXTURE_1DARRAY);
1832 state->float_pipelines.image_2d = create_uav_pipeline(context_vk, state->image_layout,
1833 SHADER_DESC(cs_uav_clear_2d_float_code), WINED3D_SHADER_RESOURCE_TEXTURE_2D);
1834 state->uint_pipelines.image_2d = create_uav_pipeline(context_vk, state->image_layout,
1835 SHADER_DESC(cs_uav_clear_2d_uint_code), WINED3D_SHADER_RESOURCE_TEXTURE_2D);
1836 state->float_pipelines.image_2d_array = create_uav_pipeline(context_vk, state->image_layout,
1837 SHADER_DESC(cs_uav_clear_2d_array_float_code), WINED3D_SHADER_RESOURCE_TEXTURE_2DARRAY);
1838 state->uint_pipelines.image_2d_array = create_uav_pipeline(context_vk, state->image_layout,
1839 SHADER_DESC(cs_uav_clear_2d_array_uint_code), WINED3D_SHADER_RESOURCE_TEXTURE_2DARRAY);
1840 state->float_pipelines.image_3d = create_uav_pipeline(context_vk, state->image_layout,
1841 SHADER_DESC(cs_uav_clear_3d_float_code), WINED3D_SHADER_RESOURCE_TEXTURE_3D);
1842 state->uint_pipelines.image_3d = create_uav_pipeline(context_vk, state->image_layout,
1843 SHADER_DESC(cs_uav_clear_3d_uint_code), WINED3D_SHADER_RESOURCE_TEXTURE_3D);
1844 #undef SHADER_DESC
1846 state->buffer_group_size.x = 128;
1847 state->buffer_group_size.y = 1;
1848 state->buffer_group_size.z = 1;
1849 state->image_1d_group_size.x = 64;
1850 state->image_1d_group_size.y = 1;
1851 state->image_1d_group_size.z = 1;
1852 state->image_1d_array_group_size.x = 64;
1853 state->image_1d_array_group_size.y = 1;
1854 state->image_1d_array_group_size.z = 1;
1855 state->image_2d_group_size.x = 8;
1856 state->image_2d_group_size.y = 8;
1857 state->image_2d_group_size.z = 1;
1858 state->image_2d_array_group_size.x = 8;
1859 state->image_2d_array_group_size.y = 8;
1860 state->image_2d_array_group_size.z = 1;
1861 state->image_3d_group_size.x = 8;
1862 state->image_3d_group_size.y = 8;
1863 state->image_3d_group_size.z = 1;
1866 void wined3d_device_vk_uav_clear_state_cleanup(struct wined3d_device_vk *device_vk)
1868 struct wined3d_uav_clear_state_vk *state = &device_vk->uav_clear_state;
1869 const struct wined3d_vk_info *vk_info = &device_vk->vk_info;
1871 VK_CALL(vkDestroyPipeline(device_vk->vk_device, state->float_pipelines.buffer, NULL));
1872 VK_CALL(vkDestroyPipeline(device_vk->vk_device, state->float_pipelines.image_1d, NULL));
1873 VK_CALL(vkDestroyPipeline(device_vk->vk_device, state->float_pipelines.image_1d_array, NULL));
1874 VK_CALL(vkDestroyPipeline(device_vk->vk_device, state->float_pipelines.image_2d, NULL));
1875 VK_CALL(vkDestroyPipeline(device_vk->vk_device, state->float_pipelines.image_2d_array, NULL));
1876 VK_CALL(vkDestroyPipeline(device_vk->vk_device, state->float_pipelines.image_3d, NULL));
1878 VK_CALL(vkDestroyPipeline(device_vk->vk_device, state->uint_pipelines.buffer, NULL));
1879 VK_CALL(vkDestroyPipeline(device_vk->vk_device, state->uint_pipelines.image_1d, NULL));
1880 VK_CALL(vkDestroyPipeline(device_vk->vk_device, state->uint_pipelines.image_1d_array, NULL));
1881 VK_CALL(vkDestroyPipeline(device_vk->vk_device, state->uint_pipelines.image_2d, NULL));
1882 VK_CALL(vkDestroyPipeline(device_vk->vk_device, state->uint_pipelines.image_2d_array, NULL));
1883 VK_CALL(vkDestroyPipeline(device_vk->vk_device, state->uint_pipelines.image_3d, NULL));
1886 void wined3d_unordered_access_view_vk_clear(struct wined3d_unordered_access_view_vk *view_vk,
1887 const struct wined3d_uvec4 *clear_value, struct wined3d_context_vk *context_vk, bool fp)
1889 struct wined3d_bo_address cb_source_address, cb_destination_address;
1890 const struct wined3d_format *view_format = view_vk->v.format;
1891 struct wined3d_view_desc *view_desc = &view_vk->v.desc;
1892 struct wined3d_uav_clear_constants_vk constants = {0};
1893 struct wined3d_device *device = context_vk->c.device;
1894 struct wined3d_shader_thread_group_size group_count;
1895 enum wined3d_format_id format_id = view_format->id;
1896 struct wined3d_uav_clear_pipelines_vk *pipelines;
1897 struct wined3d_texture_vk *texture_vk = NULL;
1898 struct wined3d_pipeline_layout_vk *layout;
1899 struct wined3d_uav_clear_state_vk *state;
1900 const struct wined3d_vk_info *vk_info;
1901 VkDescriptorImageInfo vk_image_info;
1902 struct wined3d_device_vk *device_vk;
1903 VkDescriptorBufferInfo buffer_info;
1904 struct wined3d_resource *resource;
1905 VkCommandBuffer vk_command_buffer;
1906 struct wined3d_bo_vk constants_bo;
1907 VkWriteDescriptorSet vk_writes[2];
1908 VkBufferView vk_buffer_view;
1909 VkMemoryBarrier vk_barrier;
1910 VkPipeline vk_pipeline;
1911 DWORD uav_location;
1912 unsigned int level;
1913 bool is_array;
1914 VkResult vr;
1916 device_vk = wined3d_device_vk(device);
1917 state = &device_vk->uav_clear_state;
1918 pipelines = fp ? &state->float_pipelines : &state->uint_pipelines;
1920 resource = view_vk->v.resource;
1921 is_array = view_desc->flags & WINED3D_VIEW_TEXTURE_ARRAY;
1923 switch (resource->type)
1925 case WINED3D_RTYPE_BUFFER:
1926 vk_pipeline = pipelines->buffer;
1927 group_count = state->buffer_group_size;
1928 break;
1929 case WINED3D_RTYPE_TEXTURE_1D:
1930 if (is_array)
1932 vk_pipeline = pipelines->image_1d_array;
1933 group_count = state->image_1d_array_group_size;
1935 else
1937 vk_pipeline = pipelines->image_1d;
1938 group_count = state->image_1d_group_size;
1940 break;
1941 case WINED3D_RTYPE_TEXTURE_2D:
1942 if (is_array)
1944 vk_pipeline = pipelines->image_2d_array;
1945 group_count = state->image_2d_array_group_size;
1947 else
1949 vk_pipeline = pipelines->image_2d;
1950 group_count = state->image_2d_group_size;
1952 break;
1953 case WINED3D_RTYPE_TEXTURE_3D:
1954 vk_pipeline = pipelines->image_3d;
1955 group_count = state->image_3d_group_size;
1956 break;
1958 default:
1959 ERR("Unhandled resource type %s.\n", debug_d3dresourcetype(resource->type));
1960 return;
1963 if (vk_pipeline == VK_NULL_HANDLE)
1965 ERR("Pipeline was not correctly initialized.\n");
1966 return;
1969 vk_writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1970 vk_writes[0].pNext = NULL;
1971 vk_writes[0].dstBinding = 1;
1972 vk_writes[0].dstArrayElement = 0;
1973 vk_writes[0].descriptorCount = 1;
1974 vk_writes[0].pImageInfo = NULL;
1975 vk_writes[0].pTexelBufferView = &vk_buffer_view;
1976 vk_writes[0].pImageInfo = &vk_image_info;
1978 if (resource->type == WINED3D_RTYPE_BUFFER)
1980 uav_location = WINED3D_LOCATION_BUFFER;
1981 layout = state->buffer_layout;
1982 vk_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
1984 constants.extent.width = view_desc->u.buffer.count;
1985 constants.extent.height = 1;
1987 else
1989 texture_vk = wined3d_texture_vk(wined3d_texture_from_resource(resource));
1991 uav_location = WINED3D_LOCATION_TEXTURE_RGB;
1992 layout = state->image_layout;
1993 vk_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
1995 level = view_desc->u.texture.level_idx;
1996 constants.extent.width = wined3d_texture_get_level_width(&texture_vk->t, level);
1997 constants.extent.height = wined3d_texture_get_level_height(&texture_vk->t, level);
1998 group_count.z = (view_desc->u.texture.layer_count + group_count.z - 1) / group_count.z;
2001 group_count.x = (constants.extent.width + group_count.x - 1) / group_count.x;
2002 group_count.y = (constants.extent.height + group_count.y - 1) / group_count.y;
2004 constants.color.uint32[0] = clear_value->x;
2005 constants.color.uint32[1] = clear_value->y;
2006 constants.color.uint32[2] = clear_value->z;
2007 constants.color.uint32[3] = clear_value->w;
2009 if (!fp)
2011 /* Make sure values are truncated, not saturated to some maximum value. */
2012 constants.color.uint32[0] &= wined3d_mask_from_size(view_format->red_size);
2013 constants.color.uint32[1] &= wined3d_mask_from_size(view_format->green_size);
2014 constants.color.uint32[2] &= wined3d_mask_from_size(view_format->blue_size);
2015 constants.color.uint32[3] &= wined3d_mask_from_size(view_format->alpha_size);
2017 if (view_format->id == WINED3DFMT_R11G11B10_FLOAT)
2019 constants.color.uint32[0] |= constants.color.uint32[1] << 11;
2020 constants.color.uint32[0] |= constants.color.uint32[2] << 22;
2021 format_id = WINED3DFMT_R32_UINT;
2023 else
2025 format_id = wined3d_get_typed_format_id(context_vk->c.device->adapter, view_format,
2026 WINED3D_CHANNEL_TYPE_UINT);
2030 if (format_id == WINED3DFMT_UNKNOWN)
2032 ERR("Unsupported format %s.\n", debug_d3dformat(view_format->id));
2033 return;
2036 wined3d_view_load_location(resource, view_desc, &context_vk->c, uav_location);
2037 wined3d_unordered_access_view_invalidate_location(&view_vk->v, ~uav_location);
2039 if (resource->type == WINED3D_RTYPE_BUFFER)
2041 if (format_id == view_format->id)
2042 vk_buffer_view = view_vk->view_vk.u.vk_buffer_view;
2043 else
2045 vk_buffer_view = wined3d_view_vk_create_vk_buffer_view(context_vk, view_desc,
2046 wined3d_buffer_vk(buffer_from_resource(resource)), wined3d_format_vk(
2047 wined3d_get_format(context_vk->c.device->adapter, format_id, WINED3D_BIND_UNORDERED_ACCESS)));
2048 if (vk_buffer_view == VK_NULL_HANDLE)
2049 return;
2052 else
2054 if (format_id == view_format->id)
2056 vk_image_info = view_vk->view_vk.u.vk_image_info;
2057 if (!vk_image_info.imageView)
2059 const VkDescriptorImageInfo *default_info;
2060 if (!(default_info = wined3d_texture_vk_get_default_image_info(texture_vk, context_vk)))
2061 return;
2062 vk_image_info = *default_info;
2065 else
2067 vk_image_info.sampler = VK_NULL_HANDLE;
2068 vk_image_info.imageLayout = texture_vk->layout;
2069 vk_image_info.imageView = wined3d_view_vk_create_vk_image_view(context_vk, view_desc, texture_vk,
2070 wined3d_format_vk(wined3d_get_format(context_vk->c.device->adapter, format_id,
2071 WINED3D_BIND_UNORDERED_ACCESS)),
2072 COLOR_FIXUP_IDENTITY, false);
2074 if (vk_image_info.imageView == VK_NULL_HANDLE)
2075 return;
2079 vk_writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
2080 vk_writes[1].pNext = NULL;
2081 vk_writes[1].dstBinding = 0;
2082 vk_writes[1].dstArrayElement = 0;
2083 vk_writes[1].descriptorCount = 1;
2084 vk_writes[1].pImageInfo = NULL;
2085 vk_writes[1].pTexelBufferView = NULL;
2086 vk_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
2087 vk_writes[1].pBufferInfo = &buffer_info;
2089 if (!wined3d_context_vk_create_bo(context_vk, sizeof(constants), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
2090 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &constants_bo))
2092 ERR("Failed to create constants BO.\n");
2093 goto out;
2096 cb_source_address.buffer_object = NULL;
2097 cb_source_address.addr = (BYTE *)&constants;
2098 cb_destination_address.buffer_object = &constants_bo.b;
2099 cb_destination_address.addr = 0;
2101 adapter_vk_copy_bo_address(&context_vk->c, &cb_destination_address, &cb_source_address, sizeof(constants));
2103 buffer_info.buffer = constants_bo.vk_buffer;
2104 buffer_info.range = constants_bo.size;
2105 buffer_info.offset = constants_bo.b.buffer_offset;
2107 vk_info = context_vk->vk_info;
2109 vr = wined3d_context_vk_create_vk_descriptor_set(context_vk, layout->vk_set_layout, &vk_writes[0].dstSet);
2110 if (vr != VK_SUCCESS)
2112 ERR("Failed to create descriptor set.\n");
2113 wined3d_context_vk_destroy_bo(context_vk, &constants_bo);
2114 goto out;
2117 vk_writes[1].dstSet = vk_writes[0].dstSet;
2119 VK_CALL(vkUpdateDescriptorSets(device_vk->vk_device, 2, vk_writes, 0, NULL));
2121 vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk);
2122 wined3d_context_vk_end_current_render_pass(context_vk);
2124 wined3d_context_vk_reference_unordered_access_view(context_vk, view_vk);
2125 wined3d_context_vk_reference_bo(context_vk, &constants_bo);
2126 wined3d_context_vk_destroy_bo(context_vk, &constants_bo);
2128 vk_barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
2129 vk_barrier.pNext = NULL;
2130 vk_barrier.srcAccessMask = vk_access_mask_from_bind_flags(resource->bind_flags);
2131 vk_barrier.dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
2133 VK_CALL(vkCmdPipelineBarrier(vk_command_buffer,
2134 vk_pipeline_stage_mask_from_bind_flags(resource->bind_flags),
2135 VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
2136 0, 1, &vk_barrier, 0, NULL, 0, NULL));
2137 VK_CALL(vkCmdBindPipeline(vk_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, vk_pipeline));
2138 VK_CALL(vkCmdBindDescriptorSets(vk_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE,
2139 layout->vk_pipeline_layout, 0, 1, &vk_writes[0].dstSet, 0, NULL));
2140 VK_CALL(vkCmdDispatch(vk_command_buffer, group_count.x, group_count.y, group_count.z));
2142 vk_barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
2143 vk_barrier.dstAccessMask = vk_access_mask_from_bind_flags(resource->bind_flags);
2145 VK_CALL(vkCmdPipelineBarrier(vk_command_buffer,
2146 VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
2147 vk_pipeline_stage_mask_from_bind_flags(resource->bind_flags),
2148 0, 1, &vk_barrier, 0, NULL, 0, NULL));
2150 context_invalidate_compute_state(&context_vk->c, STATE_COMPUTE_SHADER);
2152 out:
2153 if (format_id != view_format->id)
2155 if (resource->type == WINED3D_RTYPE_BUFFER)
2156 wined3d_context_vk_destroy_vk_buffer_view(context_vk, vk_buffer_view, view_vk->view_vk.command_buffer_id);
2157 else
2158 wined3d_context_vk_destroy_vk_image_view(context_vk, vk_image_info.imageView,
2159 view_vk->view_vk.command_buffer_id);
2163 void wined3d_unordered_access_view_vk_update(struct wined3d_unordered_access_view_vk *uav_vk,
2164 struct wined3d_context_vk *context_vk)
2166 const struct wined3d_format_vk *view_format_vk = wined3d_format_vk(uav_vk->v.format);
2167 const struct wined3d_view_desc *desc = &uav_vk->v.desc;
2168 struct wined3d_resource *resource = uav_vk->v.resource;
2169 struct wined3d_view_vk *view_vk = &uav_vk->view_vk;
2170 struct wined3d_buffer_vk *buffer_vk;
2171 VkBufferView vk_buffer_view;
2173 buffer_vk = wined3d_buffer_vk(buffer_from_resource(resource));
2174 wined3d_context_vk_destroy_vk_buffer_view(context_vk, view_vk->u.vk_buffer_view, view_vk->command_buffer_id);
2175 if ((vk_buffer_view = wined3d_view_vk_create_vk_buffer_view(context_vk, desc, buffer_vk, view_format_vk)))
2177 view_vk->u.vk_buffer_view = vk_buffer_view;
2178 view_vk->bo_user.valid = true;
2182 static void wined3d_unordered_access_view_vk_cs_init(void *object)
2184 struct wined3d_unordered_access_view_vk *uav_vk = object;
2185 struct wined3d_view_vk *view_vk = &uav_vk->view_vk;
2186 struct wined3d_view_desc *desc = &uav_vk->v.desc;
2187 const struct wined3d_format_vk *format_vk;
2188 const struct wined3d_vk_info *vk_info;
2189 struct wined3d_texture_vk *texture_vk;
2190 struct wined3d_context_vk *context_vk;
2191 struct wined3d_device_vk *device_vk;
2192 struct wined3d_buffer_vk *buffer_vk;
2193 VkBufferViewCreateInfo create_info;
2194 struct wined3d_resource *resource;
2195 VkBufferView vk_buffer_view;
2196 uint32_t default_flags = 0;
2197 VkImageView vk_image_view;
2198 VkResult vr;
2200 TRACE("uav_vk %p.\n", uav_vk);
2202 resource = uav_vk->v.resource;
2203 device_vk = wined3d_device_vk(resource->device);
2204 format_vk = wined3d_format_vk(uav_vk->v.format);
2206 if (resource->type == WINED3D_RTYPE_BUFFER)
2208 buffer_vk = wined3d_buffer_vk(buffer_from_resource(resource));
2210 context_vk = wined3d_context_vk(context_acquire(&device_vk->d, NULL, 0));
2211 vk_info = context_vk->vk_info;
2213 if ((vk_buffer_view = wined3d_view_vk_create_vk_buffer_view(context_vk, desc, buffer_vk, format_vk)))
2215 struct wined3d_bo_vk *bo = wined3d_bo_vk(buffer_vk->b.buffer_object);
2217 TRACE("Created buffer view 0x%s.\n", wine_dbgstr_longlong(vk_buffer_view));
2219 uav_vk->view_vk.u.vk_buffer_view = vk_buffer_view;
2220 uav_vk->view_vk.bo_user.valid = true;
2221 list_add_head(&bo->b.users, &view_vk->bo_user.entry);
2224 if (desc->flags & (WINED3D_VIEW_BUFFER_COUNTER | WINED3D_VIEW_BUFFER_APPEND))
2226 if (!wined3d_context_vk_create_bo(context_vk, sizeof(uint32_t), VK_BUFFER_USAGE_TRANSFER_SRC_BIT
2227 | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT,
2228 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &uav_vk->counter_bo))
2230 ERR("Failed to create counter bo.\n");
2231 context_release(&context_vk->c);
2233 return;
2236 wined3d_context_vk_end_current_render_pass(context_vk);
2237 VK_CALL(vkCmdFillBuffer(wined3d_context_vk_get_command_buffer(context_vk),
2238 uav_vk->counter_bo.vk_buffer, uav_vk->counter_bo.b.buffer_offset, sizeof(uint32_t), 0));
2239 wined3d_context_vk_reference_bo(context_vk, &uav_vk->counter_bo);
2241 create_info.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO;
2242 create_info.pNext = NULL;
2243 create_info.flags = 0;
2244 create_info.buffer = uav_vk->counter_bo.vk_buffer;
2245 create_info.format = VK_FORMAT_R32_UINT;
2246 create_info.offset = uav_vk->counter_bo.b.buffer_offset;
2247 create_info.range = sizeof(uint32_t);
2248 if ((vr = VK_CALL(vkCreateBufferView(device_vk->vk_device,
2249 &create_info, NULL, &uav_vk->vk_counter_view))) < 0)
2251 ERR("Failed to create counter buffer view, vr %s.\n", wined3d_debug_vkresult(vr));
2253 else
2255 TRACE("Created counter buffer view 0x%s.\n", wine_dbgstr_longlong(uav_vk->vk_counter_view));
2257 uav_vk->v.counter_bo = &uav_vk->counter_bo.b;
2261 context_release(&context_vk->c);
2263 return;
2266 texture_vk = wined3d_texture_vk(texture_from_resource(resource));
2268 if (texture_vk->t.layer_count > 1)
2269 default_flags |= WINED3D_VIEW_TEXTURE_ARRAY;
2271 if (resource->format->id == format_vk->f.id && desc->flags == default_flags
2272 && !desc->u.texture.level_idx && desc->u.texture.level_count == texture_vk->t.level_count
2273 && !desc->u.texture.layer_idx && desc->u.texture.layer_count == texture_vk->t.layer_count
2274 && !(resource->bind_flags & WINED3D_BIND_DEPTH_STENCIL) && resource->type != WINED3D_RTYPE_TEXTURE_3D)
2276 TRACE("Creating identity unordered access view.\n");
2277 return;
2280 if (texture_vk->t.swapchain && texture_vk->t.swapchain->state.desc.backbuffer_count > 1)
2281 FIXME("Swapchain unordered access views not supported.\n");
2283 context_vk = wined3d_context_vk(context_acquire(&device_vk->d, NULL, 0));
2284 vk_image_view = wined3d_view_vk_create_vk_image_view(context_vk, desc,
2285 texture_vk, format_vk, format_vk->f.color_fixup, false);
2286 context_release(&context_vk->c);
2288 if (!vk_image_view)
2289 return;
2291 TRACE("Created image view 0x%s.\n", wine_dbgstr_longlong(vk_image_view));
2293 view_vk->u.vk_image_info.imageView = vk_image_view;
2294 view_vk->u.vk_image_info.sampler = VK_NULL_HANDLE;
2295 view_vk->u.vk_image_info.imageLayout = texture_vk->layout;
2298 HRESULT wined3d_unordered_access_view_vk_init(struct wined3d_unordered_access_view_vk *view_vk,
2299 const struct wined3d_view_desc *desc, struct wined3d_resource *resource,
2300 void *parent, const struct wined3d_parent_ops *parent_ops)
2302 HRESULT hr;
2304 TRACE("view_vk %p, desc %s, resource %p, parent %p, parent_ops %p.\n",
2305 view_vk, wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops);
2307 if (FAILED(hr = wined3d_unordered_access_view_init(&view_vk->v, desc, resource, parent, parent_ops)))
2308 return hr;
2310 list_init(&view_vk->view_vk.bo_user.entry);
2311 wined3d_cs_init_object(resource->device->cs, wined3d_unordered_access_view_vk_cs_init, view_vk);
2313 return hr;
2316 HRESULT CDECL wined3d_unordered_access_view_create(const struct wined3d_view_desc *desc,
2317 struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops,
2318 struct wined3d_unordered_access_view **view)
2320 const struct wined3d_adapter_ops *adapter_ops;
2322 TRACE("desc %s, resource %p, parent %p, parent_ops %p, view %p.\n",
2323 wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops, view);
2325 adapter_ops = resource->device->adapter->adapter_ops;
2326 return adapter_ops->adapter_create_unordered_access_view(desc, resource, parent, parent_ops, view);