include/mscvpdb.h: Use flexible array members for the rest of structures.
[wine.git] / dlls / wined3d / view.c
blob91b88c2037df10b05ef5a993484ab2961f13efd9
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 "wined3d_private.h"
21 #include "wined3d_gl.h"
22 #include "wined3d_vk.h"
24 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
26 #define WINED3D_VIEW_CUBE_ARRAY (WINED3D_VIEW_TEXTURE_CUBE | WINED3D_VIEW_TEXTURE_ARRAY)
28 static BOOL is_stencil_view_format(const struct wined3d_format *format)
30 return format->id == WINED3DFMT_X24_TYPELESS_G8_UINT
31 || format->id == WINED3DFMT_X32_TYPELESS_G8X24_UINT;
34 static GLenum get_texture_view_target(const struct wined3d_gl_info *gl_info,
35 const struct wined3d_view_desc *desc, const struct wined3d_texture_gl *texture_gl)
37 static const struct
39 GLenum texture_target;
40 unsigned int view_flags;
41 GLenum view_target;
42 enum wined3d_gl_extension extension;
44 view_types[] =
46 {GL_TEXTURE_CUBE_MAP, 0, GL_TEXTURE_CUBE_MAP},
47 {GL_TEXTURE_3D, 0, GL_TEXTURE_3D},
49 {GL_TEXTURE_2D, 0, GL_TEXTURE_2D},
50 {GL_TEXTURE_2D, WINED3D_VIEW_TEXTURE_ARRAY, GL_TEXTURE_2D_ARRAY},
51 {GL_TEXTURE_2D_ARRAY, 0, GL_TEXTURE_2D},
52 {GL_TEXTURE_2D_ARRAY, WINED3D_VIEW_TEXTURE_ARRAY, GL_TEXTURE_2D_ARRAY},
53 {GL_TEXTURE_2D_ARRAY, WINED3D_VIEW_TEXTURE_CUBE, GL_TEXTURE_CUBE_MAP},
54 {GL_TEXTURE_2D_ARRAY, WINED3D_VIEW_CUBE_ARRAY, GL_TEXTURE_CUBE_MAP_ARRAY, ARB_TEXTURE_CUBE_MAP_ARRAY},
56 {GL_TEXTURE_2D_MULTISAMPLE, 0, GL_TEXTURE_2D_MULTISAMPLE},
57 {GL_TEXTURE_2D_MULTISAMPLE, WINED3D_VIEW_TEXTURE_ARRAY, GL_TEXTURE_2D_MULTISAMPLE_ARRAY},
58 {GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 0, GL_TEXTURE_2D_MULTISAMPLE},
59 {GL_TEXTURE_2D_MULTISAMPLE_ARRAY, WINED3D_VIEW_TEXTURE_ARRAY, GL_TEXTURE_2D_MULTISAMPLE_ARRAY},
61 {GL_TEXTURE_1D, 0, GL_TEXTURE_1D},
62 {GL_TEXTURE_1D, WINED3D_VIEW_TEXTURE_ARRAY, GL_TEXTURE_1D_ARRAY},
63 {GL_TEXTURE_1D_ARRAY, 0, GL_TEXTURE_1D},
64 {GL_TEXTURE_1D_ARRAY, WINED3D_VIEW_TEXTURE_ARRAY, GL_TEXTURE_1D_ARRAY},
66 unsigned int flags = desc->flags & (WINED3D_VIEW_BUFFER_RAW | WINED3D_VIEW_BUFFER_APPEND
67 | WINED3D_VIEW_BUFFER_COUNTER | WINED3D_VIEW_TEXTURE_CUBE | WINED3D_VIEW_TEXTURE_ARRAY);
68 unsigned int i;
70 for (i = 0; i < ARRAY_SIZE(view_types); ++i)
72 if (view_types[i].texture_target != texture_gl->target || view_types[i].view_flags != flags)
73 continue;
74 if (gl_info->supported[view_types[i].extension])
75 return view_types[i].view_target;
77 FIXME("Extension %#x not supported.\n", view_types[i].extension);
80 FIXME("Unhandled view flags %#x for texture target %#x.\n", flags, texture_gl->target);
81 return texture_gl->target;
84 static const struct wined3d_format *validate_resource_view(const struct wined3d_view_desc *desc,
85 struct wined3d_resource *resource, BOOL mip_slice, BOOL allow_srgb_toggle)
87 const struct wined3d_adapter *adapter = resource->device->adapter;
88 const struct wined3d_format *format;
90 format = wined3d_get_format(adapter, desc->format_id, resource->bind_flags);
91 if (resource->type == WINED3D_RTYPE_BUFFER && (desc->flags & WINED3D_VIEW_BUFFER_RAW))
93 if (format->id != WINED3DFMT_R32_TYPELESS)
95 WARN("Invalid format %s for raw buffer view.\n", debug_d3dformat(format->id));
96 return NULL;
99 format = wined3d_get_format(adapter, WINED3DFMT_R32_UINT, resource->bind_flags);
102 if (wined3d_format_is_typeless(format))
104 WARN("Trying to create view for typeless format %s.\n", debug_d3dformat(format->id));
105 return NULL;
108 if (resource->type == WINED3D_RTYPE_BUFFER)
110 struct wined3d_buffer *buffer = buffer_from_resource(resource);
111 unsigned int buffer_size, element_size;
113 if (buffer->structure_byte_stride)
115 if (desc->format_id != WINED3DFMT_UNKNOWN)
117 WARN("Invalid format %s for structured buffer view.\n", debug_d3dformat(desc->format_id));
118 return NULL;
121 format = wined3d_get_format(adapter, WINED3DFMT_R32_UINT, resource->bind_flags);
122 element_size = buffer->structure_byte_stride;
124 else
126 element_size = format->byte_count;
129 if (!element_size)
130 return NULL;
132 buffer_size = buffer->resource.size / element_size;
133 if (!wined3d_bound_range(desc->u.buffer.start_idx, desc->u.buffer.count, buffer_size))
134 return NULL;
136 else
138 struct wined3d_texture *texture = texture_from_resource(resource);
139 unsigned int depth_or_layer_count;
141 if (resource->format->id != format->id && !wined3d_format_is_typeless(resource->format)
142 && (!allow_srgb_toggle || !wined3d_formats_are_srgb_variants(resource->format->id, format->id)))
144 WARN("Trying to create incompatible view for non typeless format %s.\n",
145 debug_d3dformat(format->id));
146 return NULL;
149 if (mip_slice && resource->type == WINED3D_RTYPE_TEXTURE_3D)
150 depth_or_layer_count = wined3d_texture_get_level_depth(texture, desc->u.texture.level_idx);
151 else
152 depth_or_layer_count = texture->layer_count;
154 if (!desc->u.texture.level_count
155 || (mip_slice && desc->u.texture.level_count != 1)
156 || !wined3d_bound_range(desc->u.texture.level_idx, desc->u.texture.level_count, texture->level_count)
157 || !desc->u.texture.layer_count
158 || !wined3d_bound_range(desc->u.texture.layer_idx, desc->u.texture.layer_count, depth_or_layer_count))
159 return NULL;
162 return format;
165 static void create_texture_view(struct wined3d_gl_view *view, GLenum view_target,
166 const struct wined3d_view_desc *desc, struct wined3d_texture_gl *texture_gl,
167 const struct wined3d_format *view_format)
169 const struct wined3d_format_gl *view_format_gl;
170 unsigned int level_idx, layer_idx, layer_count;
171 const struct wined3d_gl_info *gl_info;
172 struct wined3d_context_gl *context_gl;
173 struct wined3d_context *context;
174 GLuint texture_name;
176 view_format_gl = wined3d_format_gl(view_format);
177 view->target = view_target;
179 context = context_acquire(texture_gl->t.resource.device, NULL, 0);
180 context_gl = wined3d_context_gl(context);
181 gl_info = context_gl->gl_info;
183 if (!gl_info->supported[ARB_TEXTURE_VIEW])
185 context_release(context);
186 FIXME("OpenGL implementation does not support texture views.\n");
187 return;
190 wined3d_texture_gl_prepare_texture(texture_gl, context_gl, FALSE);
191 texture_name = wined3d_texture_gl_get_texture_name(texture_gl, context, FALSE);
193 level_idx = desc->u.texture.level_idx;
194 layer_idx = desc->u.texture.layer_idx;
195 layer_count = desc->u.texture.layer_count;
196 if (view_target == GL_TEXTURE_3D)
198 if (layer_idx || layer_count != wined3d_texture_get_level_depth(&texture_gl->t, level_idx))
199 FIXME("Depth slice (%u-%u) not supported.\n", layer_idx, layer_count);
200 layer_idx = 0;
201 layer_count = 1;
204 gl_info->gl_ops.gl.p_glGenTextures(1, &view->name);
205 GL_EXTCALL(glTextureView(view->name, view->target, texture_name, view_format_gl->internal,
206 level_idx, desc->u.texture.level_count, layer_idx, layer_count));
207 checkGLcall("create texture view");
209 if (is_stencil_view_format(view_format))
211 static const GLint swizzle[] = {GL_ZERO, GL_RED, GL_ZERO, GL_ZERO};
213 if (!gl_info->supported[ARB_STENCIL_TEXTURING])
215 context_release(context);
216 FIXME("OpenGL implementation does not support stencil texturing.\n");
217 return;
220 wined3d_context_gl_bind_texture(context_gl, view->target, view->name);
221 gl_info->gl_ops.gl.p_glTexParameteriv(view->target, GL_TEXTURE_SWIZZLE_RGBA, swizzle);
222 gl_info->gl_ops.gl.p_glTexParameteri(view->target, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_STENCIL_INDEX);
223 checkGLcall("initialize stencil view");
225 context_invalidate_compute_state(context, STATE_COMPUTE_SHADER_RESOURCE_BINDING);
226 context_invalidate_state(context, STATE_GRAPHICS_SHADER_RESOURCE_BINDING);
228 else if (!is_identity_fixup(view_format->color_fixup) && can_use_texture_swizzle(context->d3d_info, view_format))
230 GLint swizzle[4];
232 wined3d_context_gl_bind_texture(context_gl, view->target, view->name);
233 wined3d_gl_texture_swizzle_from_color_fixup(swizzle, view_format->color_fixup);
234 gl_info->gl_ops.gl.p_glTexParameteriv(view->target, GL_TEXTURE_SWIZZLE_RGBA, swizzle);
235 checkGLcall("set format swizzle");
237 context_invalidate_compute_state(context, STATE_COMPUTE_SHADER_RESOURCE_BINDING);
238 context_invalidate_state(context, STATE_GRAPHICS_SHADER_RESOURCE_BINDING);
241 context_release(context);
244 static void create_buffer_texture(struct wined3d_gl_view *view, struct wined3d_context_gl *context_gl,
245 struct wined3d_buffer *buffer, const struct wined3d_format_gl *view_format_gl,
246 unsigned int offset, unsigned int size)
248 const struct wined3d_gl_info *gl_info = context_gl->gl_info;
249 const struct wined3d_bo_gl *bo_gl;
251 if (!gl_info->supported[ARB_TEXTURE_BUFFER_OBJECT])
253 FIXME("OpenGL implementation does not support buffer textures.\n");
254 return;
257 wined3d_buffer_load_location(buffer, &context_gl->c, WINED3D_LOCATION_BUFFER);
258 bo_gl = wined3d_bo_gl(buffer->buffer_object);
259 offset += bo_gl->b.buffer_offset;
261 if ((offset & (gl_info->limits.texture_buffer_offset_alignment - 1)))
263 FIXME("Buffer offset %u is not %u byte aligned.\n",
264 offset, gl_info->limits.texture_buffer_offset_alignment);
265 return;
268 view->target = GL_TEXTURE_BUFFER;
269 if (!view->name)
271 gl_info->gl_ops.gl.p_glGenTextures(1, &view->name);
273 else if (gl_info->supported[ARB_BINDLESS_TEXTURE])
275 /* If we already bound this view to a shader, we acquired a handle to
276 * it, and it's now immutable. This means we can't bind a new buffer
277 * storage to it, so recreate the texture. */
278 gl_info->gl_ops.gl.p_glDeleteTextures(1, &view->name);
279 gl_info->gl_ops.gl.p_glGenTextures(1, &view->name);
282 wined3d_context_gl_bind_texture(context_gl, GL_TEXTURE_BUFFER, view->name);
283 if (gl_info->supported[ARB_TEXTURE_BUFFER_RANGE])
285 GL_EXTCALL(glTexBufferRange(GL_TEXTURE_BUFFER, view_format_gl->internal, bo_gl->id, offset, size));
287 else
289 if (offset || size != buffer->resource.size)
290 FIXME("OpenGL implementation does not support ARB_texture_buffer_range.\n");
291 GL_EXTCALL(glTexBuffer(GL_TEXTURE_BUFFER, view_format_gl->internal, bo_gl->id));
293 checkGLcall("Create buffer texture");
295 context_invalidate_compute_state(&context_gl->c, STATE_COMPUTE_SHADER_RESOURCE_BINDING);
296 context_invalidate_state(&context_gl->c, STATE_GRAPHICS_SHADER_RESOURCE_BINDING);
299 static void get_buffer_view_range(const struct wined3d_buffer *buffer,
300 const struct wined3d_view_desc *desc, const struct wined3d_format *view_format,
301 unsigned int *offset, unsigned int *size)
303 if (desc->format_id == WINED3DFMT_UNKNOWN)
305 *offset = desc->u.buffer.start_idx * buffer->structure_byte_stride;
306 *size = desc->u.buffer.count * buffer->structure_byte_stride;
308 else
310 *offset = desc->u.buffer.start_idx * view_format->byte_count;
311 *size = desc->u.buffer.count * view_format->byte_count;
315 static void create_buffer_view(struct wined3d_gl_view *view, struct wined3d_context *context,
316 const struct wined3d_view_desc *desc, struct wined3d_buffer *buffer,
317 const struct wined3d_format *view_format)
319 unsigned int offset, size;
321 get_buffer_view_range(buffer, desc, view_format, &offset, &size);
322 create_buffer_texture(view, wined3d_context_gl(context), buffer, wined3d_format_gl(view_format), offset, size);
325 static void wined3d_view_invalidate_location(struct wined3d_resource *resource,
326 const struct wined3d_view_desc *desc, DWORD location)
328 unsigned int i, sub_resource_idx;
329 struct wined3d_texture *texture;
331 if (resource->type == WINED3D_RTYPE_BUFFER)
333 wined3d_buffer_invalidate_location(buffer_from_resource(resource), location);
334 return;
337 texture = texture_from_resource(resource);
338 if (resource->type == WINED3D_RTYPE_TEXTURE_3D)
340 wined3d_texture_invalidate_location(texture, desc->u.texture.level_idx, location);
341 return;
344 sub_resource_idx = desc->u.texture.layer_idx * texture->level_count + desc->u.texture.level_idx;
345 for (i = 0; i < desc->u.texture.layer_count; ++i, sub_resource_idx += texture->level_count)
346 wined3d_texture_invalidate_location(texture, sub_resource_idx, location);
349 static void wined3d_view_load_location(struct wined3d_resource *resource,
350 const struct wined3d_view_desc *desc, struct wined3d_context *context, DWORD location)
352 unsigned int i, sub_resource_idx;
353 struct wined3d_texture *texture;
355 if (resource->type == WINED3D_RTYPE_BUFFER)
357 wined3d_buffer_load_location(buffer_from_resource(resource), context, location);
358 return;
361 texture = texture_from_resource(resource);
362 if (resource->type == WINED3D_RTYPE_TEXTURE_3D)
364 wined3d_texture_load_location(texture, desc->u.texture.level_idx, context, location);
365 return;
368 sub_resource_idx = desc->u.texture.layer_idx * texture->level_count + desc->u.texture.level_idx;
369 for (i = 0; i < desc->u.texture.layer_count; ++i, sub_resource_idx += texture->level_count)
370 wined3d_texture_load_location(texture, sub_resource_idx, context, location);
373 ULONG CDECL wined3d_rendertarget_view_incref(struct wined3d_rendertarget_view *view)
375 unsigned int refcount = InterlockedIncrement(&view->refcount);
377 TRACE("%p increasing refcount to %u.\n", view, refcount);
379 return refcount;
382 void wined3d_rendertarget_view_cleanup(struct wined3d_rendertarget_view *view)
384 view->parent_ops->wined3d_object_destroyed(view->parent);
387 ULONG CDECL wined3d_rendertarget_view_decref(struct wined3d_rendertarget_view *view)
389 unsigned int refcount = InterlockedDecrement(&view->refcount);
391 TRACE("%p decreasing refcount to %u.\n", view, refcount);
393 if (!refcount)
395 struct wined3d_resource *resource = view->resource;
397 /* Release the resource after destroying the view.
398 * See wined3d_shader_resource_view_decref(). */
399 wined3d_mutex_lock();
400 resource->device->adapter->adapter_ops->adapter_destroy_rendertarget_view(view);
401 wined3d_mutex_unlock();
402 wined3d_resource_decref(resource);
405 return refcount;
408 void * CDECL wined3d_rendertarget_view_get_parent(const struct wined3d_rendertarget_view *view)
410 TRACE("view %p.\n", view);
412 return view->parent;
415 void * CDECL wined3d_rendertarget_view_get_sub_resource_parent(const struct wined3d_rendertarget_view *view)
417 struct wined3d_texture *texture;
419 TRACE("view %p.\n", view);
421 if (view->resource->type == WINED3D_RTYPE_BUFFER)
422 return wined3d_buffer_get_parent(buffer_from_resource(view->resource));
424 texture = texture_from_resource(view->resource);
426 return texture->sub_resources[view->sub_resource_idx].parent;
429 void CDECL wined3d_rendertarget_view_set_parent(struct wined3d_rendertarget_view *view,
430 void *parent, const struct wined3d_parent_ops *parent_ops)
432 TRACE("view %p, parent %p, parent_ops %p.\n", view, parent, parent_ops);
434 view->parent = parent;
435 view->parent_ops = parent_ops;
438 struct wined3d_resource * CDECL wined3d_rendertarget_view_get_resource(const struct wined3d_rendertarget_view *view)
440 TRACE("view %p.\n", view);
442 return view->resource;
445 void wined3d_rendertarget_view_get_drawable_size(const struct wined3d_rendertarget_view *view,
446 const struct wined3d_context *context, unsigned int *width, unsigned int *height)
448 const struct wined3d_texture *texture;
450 if (view->resource->type != WINED3D_RTYPE_TEXTURE_2D)
452 *width = view->width;
453 *height = view->height;
454 return;
457 texture = texture_from_resource(view->resource);
458 if (texture->swapchain)
460 /* The drawable size of an onscreen drawable is the surface size.
461 * (Actually: The window size, but the surface is created in window
462 * size.) */
463 *width = texture->resource.width;
464 *height = texture->resource.height;
466 else
468 unsigned int level_idx = view->sub_resource_idx % texture->level_count;
470 /* The drawable size of an FBO target is the OpenGL texture size,
471 * which is the power of two size. */
472 *width = wined3d_texture_get_level_width(texture, level_idx);
473 *height = wined3d_texture_get_level_height(texture, level_idx);
477 void wined3d_rendertarget_view_prepare_location(struct wined3d_rendertarget_view *view,
478 struct wined3d_context *context, uint32_t location)
480 struct wined3d_resource *resource = view->resource;
481 unsigned int i, sub_resource_idx, layer_count;
482 struct wined3d_texture *texture;
484 if (resource->type == WINED3D_RTYPE_BUFFER)
486 FIXME("Not implemented for resources %s.\n", debug_d3dresourcetype(resource->type));
487 return;
490 texture = texture_from_resource(resource);
491 sub_resource_idx = view->sub_resource_idx;
492 layer_count = resource->type != WINED3D_RTYPE_TEXTURE_3D ? view->layer_count : 1;
493 for (i = 0; i < layer_count; ++i, sub_resource_idx += texture->level_count)
494 wined3d_texture_prepare_location(texture, sub_resource_idx, context, location);
497 void wined3d_rendertarget_view_load_location(struct wined3d_rendertarget_view *view,
498 struct wined3d_context *context, uint32_t location)
500 wined3d_view_load_location(view->resource, &view->desc, context, location);
503 void wined3d_rendertarget_view_validate_location(struct wined3d_rendertarget_view *view, uint32_t location)
505 struct wined3d_resource *resource = view->resource;
506 unsigned int i, sub_resource_idx, layer_count;
507 struct wined3d_texture *texture;
509 if (resource->type == WINED3D_RTYPE_BUFFER)
511 FIXME("Not implemented for resources %s.\n", debug_d3dresourcetype(resource->type));
512 return;
515 texture = texture_from_resource(resource);
516 sub_resource_idx = view->sub_resource_idx;
517 layer_count = resource->type != WINED3D_RTYPE_TEXTURE_3D ? view->layer_count : 1;
518 for (i = 0; i < layer_count; ++i, sub_resource_idx += texture->level_count)
519 wined3d_texture_validate_location(texture, sub_resource_idx, location);
522 void wined3d_rendertarget_view_invalidate_location(struct wined3d_rendertarget_view *view, uint32_t location)
524 wined3d_view_invalidate_location(view->resource, &view->desc, location);
527 /* Note: This may return 0 if the selected layers do not have a location in common. */
528 DWORD wined3d_rendertarget_view_get_locations(const struct wined3d_rendertarget_view *view)
530 struct wined3d_resource *resource = view->resource;
531 unsigned int i, sub_resource_idx, layer_count;
532 const struct wined3d_texture *texture;
533 DWORD ret = ~0u;
535 if (resource->type == WINED3D_RTYPE_BUFFER)
536 return buffer_from_resource(resource)->locations;
538 texture = texture_from_resource(resource);
539 sub_resource_idx = view->sub_resource_idx;
540 layer_count = resource->type != WINED3D_RTYPE_TEXTURE_3D ? view->layer_count : 1;
541 for (i = 0; i < layer_count; ++i, sub_resource_idx += texture->level_count)
542 ret &= texture->sub_resources[sub_resource_idx].locations;
544 if (!ret)
545 WARN("View %p (texture %p) layers do not have a location in common.\n", view, texture);
547 return ret;
550 void wined3d_rendertarget_view_get_box(struct wined3d_rendertarget_view *view,
551 struct wined3d_box *box)
553 if (view->resource->type != WINED3D_RTYPE_TEXTURE_3D)
555 wined3d_box_set(box, 0, 0, view->width, view->height, 0, 1);
557 else
559 struct wined3d_texture *texture = texture_from_resource(view->resource);
560 wined3d_texture_get_level_box(texture, view->sub_resource_idx, box);
564 static void wined3d_render_target_view_gl_cs_init(void *object)
566 struct wined3d_rendertarget_view_gl *view_gl = object;
567 struct wined3d_resource *resource = view_gl->v.resource;
568 const struct wined3d_view_desc *desc = &view_gl->v.desc;
570 TRACE("view_gl %p.\n", view_gl);
572 if (resource->type == WINED3D_RTYPE_BUFFER)
574 FIXME("Not implemented for resources %s.\n", debug_d3dresourcetype(resource->type));
576 else
578 struct wined3d_texture_gl *texture_gl = wined3d_texture_gl(texture_from_resource(resource));
579 unsigned int depth_or_layer_count;
581 if (resource->type == WINED3D_RTYPE_TEXTURE_3D)
582 depth_or_layer_count = wined3d_texture_get_level_depth(&texture_gl->t, desc->u.texture.level_idx);
583 else
584 depth_or_layer_count = texture_gl->t.layer_count;
586 if (resource->format->id != view_gl->v.format->id
587 || (view_gl->v.layer_count != 1 && view_gl->v.layer_count != depth_or_layer_count))
589 GLenum resource_class, view_class;
591 resource_class = wined3d_format_gl(resource->format)->view_class;
592 view_class = wined3d_format_gl(view_gl->v.format)->view_class;
593 if (resource_class != view_class)
595 FIXME("Render target view not supported, resource format %s, view format %s.\n",
596 debug_d3dformat(resource->format->id), debug_d3dformat(view_gl->v.format->id));
597 return;
599 if (texture_gl->t.swapchain && texture_gl->t.swapchain->state.desc.backbuffer_count > 1)
601 FIXME("Swapchain views not supported.\n");
602 return;
605 create_texture_view(&view_gl->gl_view, texture_gl->target, desc, texture_gl, view_gl->v.format);
610 static HRESULT wined3d_rendertarget_view_init(struct wined3d_rendertarget_view *view,
611 const struct wined3d_view_desc *desc, struct wined3d_resource *resource,
612 void *parent, const struct wined3d_parent_ops *parent_ops)
614 BOOL allow_srgb_toggle = FALSE;
616 view->refcount = 1;
617 view->parent = parent;
618 view->parent_ops = parent_ops;
620 if (resource->type != WINED3D_RTYPE_BUFFER)
622 struct wined3d_texture *texture = texture_from_resource(resource);
624 if (texture->swapchain)
625 allow_srgb_toggle = TRUE;
627 if (!(view->format = validate_resource_view(desc, resource, TRUE, allow_srgb_toggle)))
628 return E_INVALIDARG;
629 view->format_attrs = view->format->attrs;
630 view->format_caps = view->format->caps[resource->gl_type];
631 view->desc = *desc;
633 if (resource->type == WINED3D_RTYPE_BUFFER)
635 view->sub_resource_idx = 0;
636 view->layer_count = 1;
637 view->width = desc->u.buffer.count;
638 view->height = 1;
640 else
642 struct wined3d_texture *texture = texture_from_resource(resource);
644 view->sub_resource_idx = desc->u.texture.level_idx;
645 if (resource->type != WINED3D_RTYPE_TEXTURE_3D)
646 view->sub_resource_idx += desc->u.texture.layer_idx * texture->level_count;
647 view->layer_count = desc->u.texture.layer_count;
648 view->width = wined3d_texture_get_level_width(texture, desc->u.texture.level_idx);
649 view->height = wined3d_texture_get_level_height(texture, desc->u.texture.level_idx);
652 wined3d_resource_incref(view->resource = resource);
654 return WINED3D_OK;
657 HRESULT wined3d_rendertarget_view_no3d_init(struct wined3d_rendertarget_view *view_no3d,
658 const struct wined3d_view_desc *desc, struct wined3d_resource *resource,
659 void *parent, const struct wined3d_parent_ops *parent_ops)
661 TRACE("view_no3d %p, desc %s, resource %p, parent %p, parent_ops %p.\n",
662 view_no3d, wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops);
664 return wined3d_rendertarget_view_init(view_no3d, desc, resource, parent, parent_ops);
667 HRESULT wined3d_rendertarget_view_gl_init(struct wined3d_rendertarget_view_gl *view_gl,
668 const struct wined3d_view_desc *desc, struct wined3d_resource *resource,
669 void *parent, const struct wined3d_parent_ops *parent_ops)
671 HRESULT hr;
673 TRACE("view_gl %p, desc %s, resource %p, parent %p, parent_ops %p.\n",
674 view_gl, wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops);
676 if (FAILED(hr = wined3d_rendertarget_view_init(&view_gl->v, desc, resource, parent, parent_ops)))
677 return hr;
679 wined3d_cs_init_object(resource->device->cs, wined3d_render_target_view_gl_cs_init, view_gl);
681 return hr;
684 VkImageViewType vk_image_view_type_from_wined3d(enum wined3d_resource_type type, uint32_t flags)
686 switch (type)
688 case WINED3D_RTYPE_TEXTURE_1D:
689 if (flags & WINED3D_VIEW_TEXTURE_ARRAY)
690 return VK_IMAGE_VIEW_TYPE_1D_ARRAY;
691 else
692 return VK_IMAGE_VIEW_TYPE_1D;
694 case WINED3D_RTYPE_TEXTURE_2D:
695 if (flags & WINED3D_VIEW_TEXTURE_CUBE)
697 if (flags & WINED3D_VIEW_TEXTURE_ARRAY)
698 return VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
699 else
700 return VK_IMAGE_VIEW_TYPE_CUBE;
702 if (flags & WINED3D_VIEW_TEXTURE_ARRAY)
703 return VK_IMAGE_VIEW_TYPE_2D_ARRAY;
704 else
705 return VK_IMAGE_VIEW_TYPE_2D;
707 case WINED3D_RTYPE_TEXTURE_3D:
708 return VK_IMAGE_VIEW_TYPE_3D;
710 default:
711 ERR("Unhandled resource type %s.\n", debug_d3dresourcetype(type));
712 return ~0u;
716 static VkBufferView wined3d_view_vk_create_vk_buffer_view(struct wined3d_context_vk *context_vk,
717 const struct wined3d_view_desc *desc, struct wined3d_buffer_vk *buffer_vk,
718 const struct wined3d_format_vk *view_format_vk)
720 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
721 VkBufferViewCreateInfo create_info;
722 struct wined3d_device_vk *device_vk;
723 VkBufferView vk_buffer_view;
724 unsigned int offset, size;
725 struct wined3d_bo_vk *bo;
726 VkResult vr;
728 get_buffer_view_range(&buffer_vk->b, desc, &view_format_vk->f, &offset, &size);
729 wined3d_buffer_prepare_location(&buffer_vk->b, &context_vk->c, WINED3D_LOCATION_BUFFER);
730 bo = wined3d_bo_vk(buffer_vk->b.buffer_object);
732 create_info.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO;
733 create_info.pNext = NULL;
734 create_info.flags = 0;
735 create_info.buffer = bo->vk_buffer;
736 create_info.format = view_format_vk->vk_format;
737 create_info.offset = bo->b.buffer_offset + offset;
738 create_info.range = size;
740 device_vk = wined3d_device_vk(buffer_vk->b.resource.device);
741 if ((vr = VK_CALL(vkCreateBufferView(device_vk->vk_device, &create_info, NULL, &vk_buffer_view))) < 0)
743 ERR("Failed to create buffer view, vr %s.\n", wined3d_debug_vkresult(vr));
744 return VK_NULL_HANDLE;
747 return vk_buffer_view;
750 static VkImageView wined3d_view_vk_create_vk_image_view(struct wined3d_context_vk *context_vk,
751 const struct wined3d_view_desc *desc, struct wined3d_texture_vk *texture_vk,
752 const struct wined3d_format_vk *view_format_vk, struct color_fixup_desc fixup, bool rtv,
753 VkImageUsageFlags usage)
755 const struct wined3d_resource *resource = &texture_vk->t.resource;
756 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
757 const struct wined3d_format_vk *format_vk;
758 VkImageViewUsageCreateInfoKHR usage_info;
759 struct wined3d_device_vk *device_vk;
760 VkImageViewCreateInfo create_info;
761 VkImageView vk_image_view;
762 VkResult vr;
764 device_vk = wined3d_device_vk(resource->device);
766 if (!wined3d_texture_vk_prepare_texture(texture_vk, context_vk))
768 ERR("Failed to prepare texture.\n");
769 return VK_NULL_HANDLE;
772 /* Depth formats are a little complicated. For example, the typeless
773 * format corresponding to depth/stencil view format WINED3DFMT_D32_FLOAT
774 * is WINED3DFMT_R32_TYPELESS, and the corresponding shader resource view
775 * format would be WINED3DFMT_R32_FLOAT. Vulkan depth/stencil formats are
776 * only compatible with themselves, so it's not possible to create e.g. a
777 * VK_FORMAT_R32_SFLOAT view on a VK_FORMAT_D32_SFLOAT image. In order to
778 * make it work, we create Vulkan images for WINED3DFMT_R32_TYPELESS
779 * resources with either a depth format (VK_FORMAT_D32_SFLOAT) or a colour
780 * format, depending on whether the bind flags include
781 * WINED3D_BIND_DEPTH_STENCIL or not. In order to then create a Vulkan
782 * view on the image, we then replace the view format here with the
783 * underlying resource format. However, that means it's still not possible
784 * to create e.g. a WINED3DFMT_R32_UINT view on a WINED3DFMT_R32_TYPELESS
785 * depth/stencil resource. */
786 if (resource->bind_flags & WINED3D_BIND_DEPTH_STENCIL)
787 format_vk = wined3d_format_vk(resource->format);
788 else
789 format_vk = view_format_vk;
791 create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
792 create_info.pNext = NULL;
793 create_info.flags = 0;
794 create_info.image = texture_vk->image.vk_image;
795 create_info.viewType = vk_image_view_type_from_wined3d(resource->type, desc->flags);
796 if (rtv && create_info.viewType == VK_IMAGE_VIEW_TYPE_3D)
798 if (desc->u.texture.layer_count > 1)
799 create_info.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
800 else
801 create_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
803 create_info.format = format_vk->vk_format;
804 if (is_stencil_view_format(&view_format_vk->f))
806 create_info.components.r = VK_COMPONENT_SWIZZLE_ZERO;
807 create_info.components.g = VK_COMPONENT_SWIZZLE_R;
808 create_info.components.b = VK_COMPONENT_SWIZZLE_ZERO;
809 create_info.components.a = VK_COMPONENT_SWIZZLE_ZERO;
811 else if (is_identity_fixup(fixup) || !can_use_texture_swizzle(context_vk->c.d3d_info, &format_vk->f))
813 create_info.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
814 create_info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
815 create_info.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
816 create_info.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
818 else
820 wined3d_vk_swizzle_from_color_fixup(&create_info.components, fixup);
822 if ((resource->bind_flags & WINED3D_BIND_DEPTH_STENCIL)
823 && (view_format_vk->f.red_size || view_format_vk->f.green_size))
825 create_info.subresourceRange.aspectMask = 0;
826 if (view_format_vk->f.red_size)
827 create_info.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
828 if (view_format_vk->f.green_size)
829 create_info.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
831 else
833 create_info.subresourceRange.aspectMask = vk_aspect_mask_from_format(&format_vk->f);
835 create_info.subresourceRange.baseMipLevel = desc->u.texture.level_idx;
836 create_info.subresourceRange.levelCount = desc->u.texture.level_count;
837 if (create_info.viewType == VK_IMAGE_VIEW_TYPE_3D)
839 if (desc->u.texture.layer_idx || (desc->u.texture.layer_count != texture_vk->t.resource.depth
840 && desc->u.texture.layer_count != ~0u))
841 WARN("Partial 3D texture views are not supported.\n");
842 create_info.subresourceRange.baseArrayLayer = 0;
843 create_info.subresourceRange.layerCount = 1;
845 else
847 create_info.subresourceRange.baseArrayLayer = desc->u.texture.layer_idx;
848 create_info.subresourceRange.layerCount = desc->u.texture.layer_count;
850 if (vk_info->supported[WINED3D_VK_KHR_MAINTENANCE2] || vk_info->api_version >= VK_API_VERSION_1_1)
852 usage_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO_KHR;
853 usage_info.pNext = NULL;
854 usage_info.usage = usage;
855 create_info.pNext = &usage_info;
857 if ((vr = VK_CALL(vkCreateImageView(device_vk->vk_device, &create_info, NULL, &vk_image_view))) < 0)
859 ERR("Failed to create Vulkan image view, vr %s.\n", wined3d_debug_vkresult(vr));
860 return VK_NULL_HANDLE;
863 return vk_image_view;
866 static void wined3d_render_target_view_vk_cs_init(void *object)
868 struct wined3d_rendertarget_view_vk *view_vk = object;
869 struct wined3d_view_desc *desc = &view_vk->v.desc;
870 const struct wined3d_format_vk *format_vk;
871 struct wined3d_texture_vk *texture_vk;
872 struct wined3d_resource *resource;
873 struct wined3d_context *context;
874 VkImageUsageFlags vk_usage = 0;
875 uint32_t default_flags = 0;
877 TRACE("view_vk %p.\n", view_vk);
879 resource = view_vk->v.resource;
880 if (resource->type == WINED3D_RTYPE_BUFFER)
882 FIXME("Buffer views not implemented.\n");
883 return;
886 texture_vk = wined3d_texture_vk(texture_from_resource(resource));
887 format_vk = wined3d_format_vk(view_vk->v.format);
889 if (texture_vk->t.layer_count > 1)
890 default_flags |= WINED3D_VIEW_TEXTURE_ARRAY;
892 if (resource->format->id == format_vk->f.id && desc->flags == default_flags
893 && !desc->u.texture.level_idx && desc->u.texture.level_count == texture_vk->t.level_count
894 && !desc->u.texture.layer_idx && desc->u.texture.layer_count == texture_vk->t.layer_count
895 && !is_stencil_view_format(&format_vk->f) && resource->type != WINED3D_RTYPE_TEXTURE_3D
896 && is_identity_fixup(format_vk->f.color_fixup))
898 TRACE("Creating identity render target view.\n");
899 return;
902 if (texture_vk->t.swapchain && texture_vk->t.swapchain->state.desc.backbuffer_count > 1)
904 FIXME("Swapchain views not supported.\n");
905 return;
908 if (resource->bind_flags & WINED3D_BIND_RENDER_TARGET)
909 vk_usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
910 if (resource->bind_flags & WINED3D_BIND_DEPTH_STENCIL)
911 vk_usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
913 context = context_acquire(resource->device, NULL, 0);
914 view_vk->vk_image_view = wined3d_view_vk_create_vk_image_view(wined3d_context_vk(context),
915 desc, texture_vk, format_vk, COLOR_FIXUP_IDENTITY, true, vk_usage);
916 context_release(context);
918 if (!view_vk->vk_image_view)
919 return;
921 TRACE("Created image view 0x%s.\n", wine_dbgstr_longlong(view_vk->vk_image_view));
924 HRESULT wined3d_rendertarget_view_vk_init(struct wined3d_rendertarget_view_vk *view_vk,
925 const struct wined3d_view_desc *desc, struct wined3d_resource *resource,
926 void *parent, const struct wined3d_parent_ops *parent_ops)
928 HRESULT hr;
930 TRACE("view_vk %p, desc %s, resource %p, parent %p, parent_ops %p.\n",
931 view_vk, wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops);
933 if (FAILED(hr = wined3d_rendertarget_view_init(&view_vk->v, desc, resource, parent, parent_ops)))
934 return hr;
936 wined3d_cs_init_object(resource->device->cs, wined3d_render_target_view_vk_cs_init, view_vk);
938 return hr;
941 HRESULT CDECL wined3d_rendertarget_view_create(const struct wined3d_view_desc *desc,
942 struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops,
943 struct wined3d_rendertarget_view **view)
945 const struct wined3d_adapter_ops *adapter_ops;
947 TRACE("desc %s, resource %p, parent %p, parent_ops %p, view %p.\n",
948 wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops, view);
950 adapter_ops = resource->device->adapter->adapter_ops;
951 return adapter_ops->adapter_create_rendertarget_view(desc, resource, parent, parent_ops, view);
954 HRESULT CDECL wined3d_rendertarget_view_create_from_sub_resource(struct wined3d_texture *texture,
955 unsigned int sub_resource_idx, void *parent, const struct wined3d_parent_ops *parent_ops,
956 struct wined3d_rendertarget_view **view)
958 struct wined3d_view_desc desc;
960 TRACE("texture %p, sub_resource_idx %u, parent %p, parent_ops %p, view %p.\n",
961 texture, sub_resource_idx, parent, parent_ops, view);
963 desc.format_id = texture->resource.format->id;
964 desc.flags = 0;
965 desc.u.texture.level_idx = sub_resource_idx % texture->level_count;
966 desc.u.texture.level_count = 1;
967 desc.u.texture.layer_idx = sub_resource_idx / texture->level_count;
968 desc.u.texture.layer_count = 1;
970 return wined3d_rendertarget_view_create(&desc, &texture->resource, parent, parent_ops, view);
973 ULONG CDECL wined3d_shader_resource_view_incref(struct wined3d_shader_resource_view *view)
975 unsigned int refcount;
977 if (view->desc.flags & WINED3D_VIEW_FORWARD_REFERENCE)
978 return wined3d_resource_incref(view->resource);
980 refcount = InterlockedIncrement(&view->refcount);
981 TRACE("%p increasing refcount to %u.\n", view, refcount);
983 return refcount;
986 void wined3d_shader_resource_view_cleanup(struct wined3d_shader_resource_view *view)
988 view->parent_ops->wined3d_object_destroyed(view->parent);
991 void wined3d_shader_resource_view_destroy(struct wined3d_shader_resource_view *view)
993 wined3d_mutex_lock();
994 view->resource->device->adapter->adapter_ops->adapter_destroy_shader_resource_view(view);
995 wined3d_mutex_unlock();
998 ULONG CDECL wined3d_shader_resource_view_decref(struct wined3d_shader_resource_view *view)
1000 unsigned int refcount;
1002 if (view->desc.flags & WINED3D_VIEW_FORWARD_REFERENCE)
1003 return wined3d_resource_decref(view->resource);
1005 refcount = InterlockedDecrement(&view->refcount);
1006 TRACE("%p decreasing refcount to %u.\n", view, refcount);
1008 if (!refcount)
1010 struct wined3d_resource *resource = view->resource;
1012 /* Release the resource after destroying the view:
1013 * - adapter_destroy_shader_resource_view() needs a reference to the
1014 * device, which the resource implicitly provides.
1015 * - We shouldn't free buffer resources until after we've removed the
1016 * view from its bo_user list. */
1017 wined3d_shader_resource_view_destroy(view);
1018 wined3d_resource_decref(resource);
1021 return refcount;
1024 void * CDECL wined3d_shader_resource_view_get_parent(const struct wined3d_shader_resource_view *view)
1026 TRACE("view %p.\n", view);
1028 return view->parent;
1031 void wined3d_shader_resource_view_gl_update(struct wined3d_shader_resource_view_gl *srv_gl,
1032 struct wined3d_context_gl *context_gl)
1034 struct wined3d_buffer *buffer = buffer_from_resource(srv_gl->v.resource);
1036 assert(!srv_gl->bo_user.valid);
1038 create_buffer_view(&srv_gl->gl_view, &context_gl->c, &srv_gl->v.desc, buffer, srv_gl->v.format);
1039 srv_gl->bo_user.valid = true;
1040 list_add_head(&buffer->buffer_object->users, &srv_gl->bo_user.entry);
1043 static void wined3d_shader_resource_view_gl_cs_init(void *object)
1045 struct wined3d_shader_resource_view_gl *view_gl = object;
1046 struct wined3d_resource *resource = view_gl->v.resource;
1047 const struct wined3d_format *view_format;
1048 const struct wined3d_gl_info *gl_info;
1049 const struct wined3d_view_desc *desc;
1050 GLenum view_target;
1052 TRACE("view_gl %p.\n", view_gl);
1054 view_format = view_gl->v.format;
1055 gl_info = &wined3d_adapter_gl(resource->device->adapter)->gl_info;
1056 desc = &view_gl->v.desc;
1058 if (resource->type == WINED3D_RTYPE_BUFFER)
1060 struct wined3d_buffer *buffer = buffer_from_resource(resource);
1061 struct wined3d_context *context;
1063 context = context_acquire(resource->device, NULL, 0);
1064 create_buffer_view(&view_gl->gl_view, context, desc, buffer, view_format);
1065 view_gl->bo_user.valid = true;
1066 list_add_head(&buffer->buffer_object->users, &view_gl->bo_user.entry);
1067 context_release(context);
1069 else
1071 struct wined3d_texture_gl *texture_gl = wined3d_texture_gl(texture_from_resource(resource));
1072 GLenum resource_class, view_class;
1074 resource_class = wined3d_format_gl(resource->format)->view_class;
1075 view_class = wined3d_format_gl(view_format)->view_class;
1076 view_target = get_texture_view_target(gl_info, desc, texture_gl);
1078 if (resource->format->id == view_format->id && texture_gl->target == view_target
1079 && !desc->u.texture.level_idx && desc->u.texture.level_count == texture_gl->t.level_count
1080 && !desc->u.texture.layer_idx && desc->u.texture.layer_count == texture_gl->t.layer_count
1081 && !is_stencil_view_format(view_format))
1083 TRACE("Creating identity shader resource view.\n");
1085 else if (texture_gl->t.swapchain && texture_gl->t.swapchain->state.desc.backbuffer_count > 1)
1087 FIXME("Swapchain shader resource views not supported.\n");
1089 else if (resource->format->typeless_id == view_format->typeless_id
1090 && resource_class == view_class)
1092 create_texture_view(&view_gl->gl_view, view_target, desc, texture_gl, view_format);
1094 else if (wined3d_format_is_depth_view(resource->format->id, view_format->id))
1096 create_texture_view(&view_gl->gl_view, view_target, desc, texture_gl, resource->format);
1098 else
1100 FIXME("Shader resource view not supported, resource format %s, view format %s.\n",
1101 debug_d3dformat(resource->format->id), debug_d3dformat(view_format->id));
1106 static HRESULT wined3d_shader_resource_view_init(struct wined3d_shader_resource_view *view,
1107 const struct wined3d_view_desc *desc, struct wined3d_resource *resource,
1108 void *parent, const struct wined3d_parent_ops *parent_ops)
1110 view->refcount = 1;
1111 view->parent = parent;
1112 view->parent_ops = parent_ops;
1114 if (!(resource->bind_flags & WINED3D_BIND_SHADER_RESOURCE))
1115 return E_INVALIDARG;
1116 if (!(view->format = validate_resource_view(desc, resource, FALSE, FALSE)))
1117 return E_INVALIDARG;
1118 view->desc = *desc;
1120 /* If WINED3D_VIEW_FORWARD_REFERENCE, the view shouldn't take a reference
1121 * to the resource. However, the reference to the view returned by this
1122 * function should translate to a resource reference, so we increment the
1123 * resource's reference count anyway. */
1124 wined3d_resource_incref(view->resource = resource);
1126 return WINED3D_OK;
1129 HRESULT wined3d_shader_resource_view_gl_init(struct wined3d_shader_resource_view_gl *view_gl,
1130 const struct wined3d_view_desc *desc, struct wined3d_resource *resource,
1131 void *parent, const struct wined3d_parent_ops *parent_ops)
1133 HRESULT hr;
1135 TRACE("view_gl %p, desc %s, resource %p, parent %p, parent_ops %p.\n",
1136 view_gl, wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops);
1138 if (FAILED(hr = wined3d_shader_resource_view_init(&view_gl->v, desc, resource, parent, parent_ops)))
1139 return hr;
1141 list_init(&view_gl->bo_user.entry);
1142 wined3d_cs_init_object(resource->device->cs, wined3d_shader_resource_view_gl_cs_init, view_gl);
1144 return hr;
1147 void wined3d_shader_resource_view_vk_update_buffer(struct wined3d_shader_resource_view_vk *srv_vk,
1148 struct wined3d_context_vk *context_vk)
1150 const struct wined3d_format_vk *view_format_vk = wined3d_format_vk(srv_vk->v.format);
1151 const struct wined3d_view_desc *desc = &srv_vk->v.desc;
1152 struct wined3d_resource *resource = srv_vk->v.resource;
1153 struct wined3d_view_vk *view_vk = &srv_vk->view_vk;
1154 struct wined3d_buffer_vk *buffer_vk;
1155 VkBufferView vk_buffer_view;
1157 assert(!view_vk->bo_user.valid);
1159 buffer_vk = wined3d_buffer_vk(buffer_from_resource(resource));
1160 wined3d_context_vk_destroy_vk_buffer_view(context_vk, view_vk->u.vk_buffer_view, view_vk->command_buffer_id);
1161 if ((vk_buffer_view = wined3d_view_vk_create_vk_buffer_view(context_vk, desc, buffer_vk, view_format_vk)))
1163 view_vk->u.vk_buffer_view = vk_buffer_view;
1164 view_vk->bo_user.valid = true;
1165 list_add_head(&buffer_vk->b.buffer_object->users, &view_vk->bo_user.entry);
1169 void wined3d_shader_resource_view_vk_update_layout(struct wined3d_shader_resource_view_vk *srv_vk,
1170 VkImageLayout layout)
1172 srv_vk->view_vk.u.vk_image_info.imageLayout = layout;
1175 static void wined3d_shader_resource_view_vk_cs_init(void *object)
1177 struct wined3d_shader_resource_view_vk *srv_vk = object;
1178 struct wined3d_view_desc *desc = &srv_vk->v.desc;
1179 struct wined3d_texture_vk *texture_vk;
1180 const struct wined3d_format *format;
1181 struct wined3d_buffer_vk *buffer_vk;
1182 struct wined3d_resource *resource;
1183 struct wined3d_context *context;
1184 VkBufferView vk_buffer_view;
1185 uint32_t default_flags = 0;
1186 VkImageView vk_image_view;
1187 struct wined3d_bo_vk *bo;
1189 TRACE("srv_vk %p.\n", srv_vk);
1191 resource = srv_vk->v.resource;
1192 format = srv_vk->v.format;
1194 if (resource->type == WINED3D_RTYPE_BUFFER)
1196 buffer_vk = wined3d_buffer_vk(buffer_from_resource(resource));
1198 context = context_acquire(resource->device, NULL, 0);
1199 vk_buffer_view = wined3d_view_vk_create_vk_buffer_view(wined3d_context_vk(context),
1200 desc, buffer_vk, wined3d_format_vk(format));
1201 context_release(context);
1203 if (!vk_buffer_view)
1204 return;
1205 bo = wined3d_bo_vk(buffer_vk->b.buffer_object);
1207 TRACE("Created buffer view 0x%s.\n", wine_dbgstr_longlong(vk_buffer_view));
1209 srv_vk->view_vk.u.vk_buffer_view = vk_buffer_view;
1210 srv_vk->view_vk.bo_user.valid = true;
1211 list_add_head(&bo->b.users, &srv_vk->view_vk.bo_user.entry);
1213 return;
1216 texture_vk = wined3d_texture_vk(texture_from_resource(resource));
1218 if (texture_vk->t.layer_count > 1)
1219 default_flags |= WINED3D_VIEW_TEXTURE_ARRAY;
1221 if (resource->format->id == format->id && desc->flags == default_flags
1222 && !desc->u.texture.level_idx && desc->u.texture.level_count == texture_vk->t.level_count
1223 && !desc->u.texture.layer_idx && desc->u.texture.layer_count == texture_vk->t.layer_count
1224 && !(resource->bind_flags & WINED3D_BIND_DEPTH_STENCIL))
1226 TRACE("Creating identity shader resource view.\n");
1227 return;
1230 if (texture_vk->t.swapchain && texture_vk->t.swapchain->state.desc.backbuffer_count > 1)
1231 FIXME("Swapchain shader resource views not supported.\n");
1233 context = context_acquire(resource->device, NULL, 0);
1234 vk_image_view = wined3d_view_vk_create_vk_image_view(wined3d_context_vk(context),
1235 desc, texture_vk, wined3d_format_vk(format), format->color_fixup, false, VK_IMAGE_USAGE_SAMPLED_BIT);
1236 context_release(context);
1238 if (!vk_image_view)
1239 return;
1241 TRACE("Created image view 0x%s.\n", wine_dbgstr_longlong(vk_image_view));
1243 srv_vk->view_vk.u.vk_image_info.imageView = vk_image_view;
1244 srv_vk->view_vk.u.vk_image_info.sampler = VK_NULL_HANDLE;
1245 if (texture_vk->layout == VK_IMAGE_LAYOUT_GENERAL)
1246 srv_vk->view_vk.u.vk_image_info.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
1247 else
1248 srv_vk->view_vk.u.vk_image_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
1251 HRESULT wined3d_shader_resource_view_vk_init(struct wined3d_shader_resource_view_vk *view_vk,
1252 const struct wined3d_view_desc *desc, struct wined3d_resource *resource,
1253 void *parent, const struct wined3d_parent_ops *parent_ops)
1255 HRESULT hr;
1257 TRACE("view_vk %p, desc %s, resource %p, parent %p, parent_ops %p.\n",
1258 view_vk, wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops);
1260 if (FAILED(hr = wined3d_shader_resource_view_init(&view_vk->v, desc, resource, parent, parent_ops)))
1261 return hr;
1263 list_init(&view_vk->view_vk.bo_user.entry);
1264 wined3d_cs_init_object(resource->device->cs, wined3d_shader_resource_view_vk_cs_init, view_vk);
1266 return hr;
1269 HRESULT CDECL wined3d_shader_resource_view_create(const struct wined3d_view_desc *desc,
1270 struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops,
1271 struct wined3d_shader_resource_view **view)
1273 const struct wined3d_adapter_ops *adapter_ops;
1275 TRACE("desc %s, resource %p, parent %p, parent_ops %p, view %p.\n",
1276 wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops, view);
1278 adapter_ops = resource->device->adapter->adapter_ops;
1279 return adapter_ops->adapter_create_shader_resource_view(desc, resource, parent, parent_ops, view);
1282 void wined3d_shader_resource_view_gl_bind(struct wined3d_shader_resource_view_gl *view_gl,
1283 unsigned int unit, struct wined3d_sampler_gl *sampler_gl, struct wined3d_context_gl *context_gl)
1285 const struct wined3d_gl_info *gl_info = context_gl->gl_info;
1286 struct wined3d_texture_gl *texture_gl;
1288 wined3d_context_gl_active_texture(context_gl, gl_info, unit);
1290 if (view_gl->gl_view.name)
1292 wined3d_context_gl_bind_texture(context_gl, view_gl->gl_view.target, view_gl->gl_view.name);
1293 wined3d_sampler_gl_bind(sampler_gl, unit, NULL, context_gl);
1294 return;
1297 if (view_gl->v.resource->type == WINED3D_RTYPE_BUFFER)
1299 FIXME("Buffer shader resources not supported.\n");
1300 return;
1303 texture_gl = wined3d_texture_gl(wined3d_texture_from_resource(view_gl->v.resource));
1304 wined3d_texture_gl_bind(texture_gl, context_gl, sampler_gl->s.desc.srgb_decode);
1305 wined3d_sampler_gl_bind(sampler_gl, unit, texture_gl, context_gl);
1308 /* Context activation is done by the caller. */
1309 static void shader_resource_view_gl_bind_and_dirtify(struct wined3d_shader_resource_view_gl *view_gl,
1310 struct wined3d_context_gl *context_gl)
1312 /* FIXME: Ideally we'd only do this when touching a binding that's used by
1313 * a shader. */
1314 context_invalidate_compute_state(&context_gl->c, STATE_COMPUTE_SHADER_RESOURCE_BINDING);
1315 context_invalidate_state(&context_gl->c, STATE_GRAPHICS_SHADER_RESOURCE_BINDING);
1317 wined3d_context_gl_bind_texture(context_gl, view_gl->gl_view.target, view_gl->gl_view.name);
1320 GLuint64 wined3d_shader_resource_view_gl_get_bindless_handle(struct wined3d_shader_resource_view_gl *view_gl,
1321 struct wined3d_sampler_gl *sampler_gl, struct wined3d_context_gl *context_gl)
1323 const struct wined3d_gl_info *gl_info = context_gl->gl_info;
1324 GLuint64 handle;
1325 GLuint name;
1327 if (view_gl->gl_view.name)
1329 name = view_gl->gl_view.name;
1331 else if (view_gl->v.resource->type == WINED3D_RTYPE_BUFFER)
1333 FIXME("Buffer shader resources not supported.\n");
1334 return 0;
1336 else
1338 struct wined3d_texture_gl *texture_gl = wined3d_texture_gl(wined3d_texture_from_resource(view_gl->v.resource));
1339 name = wined3d_texture_gl_prepare_gl_texture(texture_gl, context_gl, FALSE);
1342 handle = GL_EXTCALL(glGetTextureSamplerHandleARB(name, sampler_gl->name));
1343 checkGLcall("glGetTextureSamplerHandleARB");
1344 /* It is an error to make a handle resident if it is already resident. */
1345 if (!GL_EXTCALL(glIsTextureHandleResidentARB(handle)))
1346 GL_EXTCALL(glMakeTextureHandleResidentARB(handle));
1347 checkGLcall("glMakeTextureHandleResidentARB");
1348 return handle;
1351 void wined3d_shader_resource_view_gl_generate_mipmap(struct wined3d_shader_resource_view_gl *view_gl,
1352 struct wined3d_context_gl *context_gl)
1354 unsigned int i, j, layer_count, level_count, base_level, base_layer, sub_resource_idx;
1355 const struct wined3d_gl_info *gl_info = context_gl->gl_info;
1356 struct wined3d_texture_gl *texture_gl;
1357 struct gl_texture *gl_tex;
1358 DWORD location;
1359 BOOL srgb;
1361 TRACE("view_gl %p.\n", view_gl);
1363 layer_count = view_gl->v.desc.u.texture.layer_count;
1364 level_count = view_gl->v.desc.u.texture.level_count;
1365 base_level = view_gl->v.desc.u.texture.level_idx;
1366 base_layer = view_gl->v.desc.u.texture.layer_idx;
1368 texture_gl = wined3d_texture_gl(texture_from_resource(view_gl->v.resource));
1369 srgb = !!(texture_gl->t.flags & WINED3D_TEXTURE_IS_SRGB);
1370 location = srgb ? WINED3D_LOCATION_TEXTURE_SRGB : WINED3D_LOCATION_TEXTURE_RGB;
1371 for (i = 0; i < layer_count; ++i)
1373 sub_resource_idx = (base_layer + i) * texture_gl->t.level_count + base_level;
1374 if (!wined3d_texture_load_location(&texture_gl->t, sub_resource_idx, &context_gl->c, location))
1375 ERR("Failed to load source layer %u.\n", base_layer + i);
1378 if (view_gl->gl_view.name)
1380 shader_resource_view_gl_bind_and_dirtify(view_gl, context_gl);
1382 else
1384 wined3d_texture_gl_bind_and_dirtify(texture_gl, context_gl, srgb);
1385 gl_info->gl_ops.gl.p_glTexParameteri(texture_gl->target, GL_TEXTURE_BASE_LEVEL, base_level);
1386 gl_info->gl_ops.gl.p_glTexParameteri(texture_gl->target, GL_TEXTURE_MAX_LEVEL, base_level + level_count - 1);
1389 if (gl_info->supported[ARB_SAMPLER_OBJECTS])
1390 GL_EXTCALL(glBindSampler(context_gl->active_texture, 0));
1391 gl_tex = wined3d_texture_gl_get_gl_texture(texture_gl, srgb);
1392 if (context_gl->c.d3d_info->wined3d_creation_flags & WINED3D_SRGB_READ_WRITE_CONTROL
1393 && gl_info->supported[EXT_TEXTURE_SRGB_DECODE])
1395 gl_info->gl_ops.gl.p_glTexParameteri(texture_gl->target,
1396 GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT);
1397 gl_tex->sampler_desc.srgb_decode = FALSE;
1400 gl_info->fbo_ops.glGenerateMipmap(texture_gl->target);
1401 checkGLcall("glGenerateMipMap()");
1403 for (i = 0; i < layer_count; ++i)
1405 for (j = 1; j < level_count; ++j)
1407 sub_resource_idx = (base_layer + i) * texture_gl->t.level_count + base_level + j;
1408 wined3d_texture_validate_location(&texture_gl->t, sub_resource_idx, location);
1409 wined3d_texture_invalidate_location(&texture_gl->t, sub_resource_idx, ~location);
1413 if (!view_gl->gl_view.name)
1415 gl_tex->sampler_desc.mip_base_level = base_level;
1416 gl_info->gl_ops.gl.p_glTexParameteri(texture_gl->target,
1417 GL_TEXTURE_MAX_LEVEL, texture_gl->t.level_count - 1);
1421 void wined3d_shader_resource_view_vk_generate_mipmap(struct wined3d_shader_resource_view_vk *srv_vk,
1422 struct wined3d_context_vk *context_vk)
1424 unsigned int i, j, layer_count, level_count, base_level, base_layer, sub_resource_idx;
1425 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1426 VkImageSubresourceRange vk_src_range, vk_dst_range;
1427 struct wined3d_texture_vk *texture_vk;
1428 VkCommandBuffer vk_command_buffer;
1429 VkImageBlit region;
1431 TRACE("srv_vk %p.\n", srv_vk);
1433 layer_count = srv_vk->v.desc.u.texture.layer_count;
1434 level_count = srv_vk->v.desc.u.texture.level_count;
1435 base_level = srv_vk->v.desc.u.texture.level_idx;
1436 base_layer = srv_vk->v.desc.u.texture.layer_idx;
1438 texture_vk = wined3d_texture_vk(texture_from_resource(srv_vk->v.resource));
1439 for (i = 0; i < layer_count; ++i)
1441 sub_resource_idx = (base_layer + i) * texture_vk->t.level_count + base_level;
1442 if (!wined3d_texture_load_location(&texture_vk->t, sub_resource_idx,
1443 &context_vk->c, WINED3D_LOCATION_TEXTURE_RGB))
1444 ERR("Failed to load source layer %u.\n", base_layer + i);
1447 if (context_vk->c.d3d_info->wined3d_creation_flags & WINED3D_SRGB_READ_WRITE_CONTROL)
1448 FIXME("Unhandled sRGB read/write control.\n");
1450 if (wined3d_format_vk(srv_vk->v.format)->vk_format != wined3d_format_vk(texture_vk->t.resource.format)->vk_format)
1451 FIXME("Ignoring view format %s.\n", debug_d3dformat(srv_vk->v.format->id));
1453 if (wined3d_resource_get_sample_count(&texture_vk->t.resource) > 1)
1454 FIXME("Unhandled multi-sampled resource.\n");
1456 if (!(vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk)))
1458 ERR("Failed to get command buffer.\n");
1459 return;
1462 vk_src_range.aspectMask = vk_aspect_mask_from_format(texture_vk->t.resource.format);
1463 vk_src_range.baseMipLevel = base_level;
1464 vk_src_range.levelCount = 1;
1465 vk_src_range.baseArrayLayer = base_layer;
1466 vk_src_range.layerCount = layer_count;
1468 vk_dst_range = vk_src_range;
1469 ++vk_dst_range.baseMipLevel;
1471 wined3d_context_vk_image_barrier(context_vk, vk_command_buffer,
1472 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
1473 vk_access_mask_from_bind_flags(texture_vk->t.resource.bind_flags),
1474 VK_ACCESS_TRANSFER_READ_BIT,
1475 texture_vk->layout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1476 texture_vk->image.vk_image, &vk_src_range);
1477 wined3d_context_vk_image_barrier(context_vk, vk_command_buffer,
1478 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
1479 vk_access_mask_from_bind_flags(texture_vk->t.resource.bind_flags),
1480 VK_ACCESS_TRANSFER_WRITE_BIT,
1481 texture_vk->layout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1482 texture_vk->image.vk_image, &vk_dst_range);
1484 region.srcSubresource.aspectMask = vk_src_range.aspectMask;
1485 region.srcSubresource.mipLevel = vk_src_range.baseMipLevel;
1486 region.srcSubresource.baseArrayLayer = vk_src_range.baseArrayLayer;
1487 region.srcSubresource.layerCount = vk_src_range.layerCount;
1488 region.srcOffsets[0].x = 0;
1489 region.srcOffsets[0].y = 0;
1490 region.srcOffsets[0].z = 0;
1492 region.dstSubresource.aspectMask = vk_dst_range.aspectMask;
1493 region.dstSubresource.mipLevel = vk_dst_range.baseMipLevel;
1494 region.dstSubresource.baseArrayLayer = vk_dst_range.baseArrayLayer;
1495 region.dstSubresource.layerCount = vk_dst_range.layerCount;
1496 region.dstOffsets[0].x = 0;
1497 region.dstOffsets[0].y = 0;
1498 region.dstOffsets[0].z = 0;
1500 for (i = 1; i < level_count; ++i)
1502 region.srcOffsets[1].x = wined3d_texture_get_level_width(&texture_vk->t, vk_src_range.baseMipLevel);
1503 region.srcOffsets[1].y = wined3d_texture_get_level_height(&texture_vk->t, vk_src_range.baseMipLevel);
1504 region.srcOffsets[1].z = wined3d_texture_get_level_depth(&texture_vk->t, vk_src_range.baseMipLevel);
1506 region.dstOffsets[1].x = wined3d_texture_get_level_width(&texture_vk->t, vk_dst_range.baseMipLevel);
1507 region.dstOffsets[1].y = wined3d_texture_get_level_height(&texture_vk->t, vk_dst_range.baseMipLevel);
1508 region.dstOffsets[1].z = wined3d_texture_get_level_depth(&texture_vk->t, vk_dst_range.baseMipLevel);
1510 VK_CALL(vkCmdBlitImage(vk_command_buffer, texture_vk->image.vk_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1511 texture_vk->image.vk_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region, VK_FILTER_LINEAR));
1513 wined3d_context_vk_image_barrier(context_vk, vk_command_buffer,
1514 VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
1515 VK_ACCESS_TRANSFER_READ_BIT,
1516 vk_access_mask_from_bind_flags(texture_vk->t.resource.bind_flags),
1517 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, texture_vk->layout,
1518 texture_vk->image.vk_image, &vk_src_range);
1520 if (i == level_count - 1)
1522 wined3d_context_vk_image_barrier(context_vk, vk_command_buffer,
1523 VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
1524 VK_ACCESS_TRANSFER_WRITE_BIT,
1525 vk_access_mask_from_bind_flags(texture_vk->t.resource.bind_flags),
1526 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, texture_vk->layout,
1527 texture_vk->image.vk_image, &vk_dst_range);
1529 else
1531 region.srcSubresource.mipLevel = ++vk_src_range.baseMipLevel;
1532 region.dstSubresource.mipLevel = ++vk_dst_range.baseMipLevel;
1534 wined3d_context_vk_image_barrier(context_vk, vk_command_buffer,
1535 VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
1536 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
1537 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1538 texture_vk->image.vk_image, &vk_src_range);
1539 wined3d_context_vk_image_barrier(context_vk, vk_command_buffer,
1540 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
1541 vk_access_mask_from_bind_flags(texture_vk->t.resource.bind_flags),
1542 VK_ACCESS_TRANSFER_WRITE_BIT,
1543 texture_vk->layout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1544 texture_vk->image.vk_image, &vk_dst_range);
1548 for (i = 0; i < layer_count; ++i)
1550 for (j = 1; j < level_count; ++j)
1552 sub_resource_idx = (base_layer + i) * texture_vk->t.level_count + base_level + j;
1553 wined3d_texture_validate_location(&texture_vk->t, sub_resource_idx, WINED3D_LOCATION_TEXTURE_RGB);
1554 wined3d_texture_invalidate_location(&texture_vk->t, sub_resource_idx, ~WINED3D_LOCATION_TEXTURE_RGB);
1558 wined3d_context_vk_reference_texture(context_vk, texture_vk);
1561 ULONG CDECL wined3d_unordered_access_view_incref(struct wined3d_unordered_access_view *view)
1563 unsigned int refcount = InterlockedIncrement(&view->refcount);
1565 TRACE("%p increasing refcount to %u.\n", view, refcount);
1567 return refcount;
1570 void wined3d_unordered_access_view_cleanup(struct wined3d_unordered_access_view *view)
1572 view->parent_ops->wined3d_object_destroyed(view->parent);
1575 ULONG CDECL wined3d_unordered_access_view_decref(struct wined3d_unordered_access_view *view)
1577 unsigned int refcount = InterlockedDecrement(&view->refcount);
1579 TRACE("%p decreasing refcount to %u.\n", view, refcount);
1581 if (!refcount)
1583 struct wined3d_resource *resource = view->resource;
1585 /* Release the resource after destroying the view.
1586 * See wined3d_shader_resource_view_decref(). */
1587 wined3d_mutex_lock();
1588 resource->device->adapter->adapter_ops->adapter_destroy_unordered_access_view(view);
1589 wined3d_mutex_unlock();
1590 wined3d_resource_decref(resource);
1593 return refcount;
1596 void * CDECL wined3d_unordered_access_view_get_parent(const struct wined3d_unordered_access_view *view)
1598 TRACE("view %p.\n", view);
1600 return view->parent;
1603 void wined3d_unordered_access_view_invalidate_location(struct wined3d_unordered_access_view *view,
1604 uint32_t location)
1606 wined3d_view_invalidate_location(view->resource, &view->desc, location);
1609 void wined3d_unordered_access_view_gl_clear(struct wined3d_unordered_access_view_gl *view_gl,
1610 const struct wined3d_uvec4 *clear_value, struct wined3d_context_gl *context_gl, bool fp)
1612 const struct wined3d_gl_info *gl_info = context_gl->gl_info;
1613 const struct wined3d_format_gl *format_gl;
1614 struct wined3d_resource *resource;
1615 struct wined3d_buffer *buffer;
1616 struct wined3d_bo_gl *bo_gl;
1617 unsigned int offset, size;
1619 resource = view_gl->v.resource;
1620 if (resource->type != WINED3D_RTYPE_BUFFER)
1622 unsigned int layer_count, level_count, base_level, base_layer;
1623 unsigned int sub_resource_idx, width, height, depth, i, j;
1624 struct wined3d_texture_gl *texture_gl;
1625 const void *data = clear_value;
1626 GLenum gl_format, gl_type;
1627 uint32_t packed;
1629 if (!gl_info->supported[ARB_CLEAR_TEXTURE])
1631 FIXME("OpenGL implementation does not support ARB_clear_texture.\n");
1632 return;
1635 format_gl = wined3d_format_gl(resource->format);
1636 texture_gl = wined3d_texture_gl(texture_from_resource(resource));
1637 level_count = view_gl->v.desc.u.texture.level_count;
1638 base_level = view_gl->v.desc.u.texture.level_idx;
1640 if (resource->type == WINED3D_RTYPE_TEXTURE_3D)
1642 layer_count = 1;
1643 base_layer = 0;
1645 else
1647 layer_count = view_gl->v.desc.u.texture.layer_count;
1648 base_layer = view_gl->v.desc.u.texture.layer_idx;
1651 if (format_gl->f.byte_count <= 4 && !fp)
1653 gl_format = format_gl->format;
1654 gl_type = format_gl->type;
1655 packed = wined3d_format_pack(&format_gl->f, clear_value);
1656 data = &packed;
1658 else if (resource->format_attrs & WINED3D_FORMAT_ATTR_INTEGER)
1660 gl_format = GL_RGBA_INTEGER;
1661 gl_type = GL_UNSIGNED_INT;
1663 else
1665 gl_format = GL_RGBA;
1666 gl_type = GL_FLOAT;
1669 for (i = 0; i < layer_count; ++i)
1671 for (j = 0; j < level_count; ++j)
1673 sub_resource_idx = (base_layer + i) * texture_gl->t.level_count + base_level + j;
1674 wined3d_texture_prepare_location(&texture_gl->t, sub_resource_idx,
1675 &context_gl->c, WINED3D_LOCATION_TEXTURE_RGB);
1677 width = wined3d_texture_get_level_width(&texture_gl->t, base_level + j);
1678 height = wined3d_texture_get_level_height(&texture_gl->t, base_level + j);
1679 depth = wined3d_texture_get_level_depth(&texture_gl->t, base_level + j);
1681 switch (texture_gl->target)
1683 case GL_TEXTURE_1D_ARRAY:
1684 GL_EXTCALL(glClearTexSubImage(texture_gl->texture_rgb.name, base_level + j,
1685 0, base_layer + i, 0, width, 1, 1, gl_format, gl_type, data));
1686 break;
1688 case GL_TEXTURE_2D_ARRAY:
1689 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
1690 case GL_TEXTURE_CUBE_MAP:
1691 case GL_TEXTURE_CUBE_MAP_ARRAY:
1692 GL_EXTCALL(glClearTexSubImage(texture_gl->texture_rgb.name, base_level + j,
1693 0, 0, base_layer + i, width, height, 1, gl_format, gl_type, data));
1694 break;
1696 default:
1697 GL_EXTCALL(glClearTexSubImage(texture_gl->texture_rgb.name, base_level + j,
1698 0, 0, 0, width, height, depth, gl_format, gl_type, data));
1699 break;
1702 wined3d_texture_validate_location(&texture_gl->t, sub_resource_idx, WINED3D_LOCATION_TEXTURE_RGB);
1703 wined3d_texture_invalidate_location(&texture_gl->t, sub_resource_idx, ~WINED3D_LOCATION_TEXTURE_RGB);
1707 return;
1710 if (!gl_info->supported[ARB_CLEAR_BUFFER_OBJECT])
1712 FIXME("OpenGL implementation does not support ARB_clear_buffer_object.\n");
1713 return;
1716 format_gl = wined3d_format_gl(view_gl->v.format);
1717 if (format_gl->f.id != WINED3DFMT_R32_UINT && format_gl->f.id != WINED3DFMT_R32_SINT
1718 && format_gl->f.id != WINED3DFMT_R32G32B32A32_UINT
1719 && format_gl->f.id != WINED3DFMT_R32G32B32A32_SINT)
1721 FIXME("Not implemented for format %s.\n", debug_d3dformat(format_gl->f.id));
1722 return;
1725 if (fp)
1727 FIXME("Floating-point buffer clears not implemented.\n");
1728 return;
1731 buffer = buffer_from_resource(resource);
1732 get_buffer_view_range(buffer, &view_gl->v.desc, &format_gl->f, &offset, &size);
1734 if (!offset && size == buffer->resource.size)
1736 wined3d_buffer_prepare_location(buffer, &context_gl->c, WINED3D_LOCATION_BUFFER);
1738 else
1740 wined3d_buffer_acquire_bo_for_write(buffer, &context_gl->c);
1741 wined3d_buffer_load_location(buffer, &context_gl->c, WINED3D_LOCATION_BUFFER);
1743 wined3d_unordered_access_view_invalidate_location(&view_gl->v, ~WINED3D_LOCATION_BUFFER);
1745 bo_gl = wined3d_bo_gl(buffer->buffer_object);
1746 wined3d_context_gl_bind_bo(context_gl, bo_gl->binding, bo_gl->id);
1747 GL_EXTCALL(glClearBufferSubData(bo_gl->binding, format_gl->internal,
1748 bo_gl->b.buffer_offset + offset, size, format_gl->format, format_gl->type, clear_value));
1749 wined3d_context_gl_reference_bo(context_gl, bo_gl);
1750 checkGLcall("clear unordered access view");
1753 void wined3d_unordered_access_view_set_counter(struct wined3d_unordered_access_view *view,
1754 unsigned int value)
1756 struct wined3d_bo_address dst, src;
1757 struct wined3d_context *context;
1758 struct wined3d_range range;
1760 if (!view->counter_bo)
1761 return;
1763 context = context_acquire(view->resource->device, NULL, 0);
1765 src.buffer_object = 0;
1766 src.addr = (void *)&value;
1768 dst.buffer_object = view->counter_bo;
1769 dst.addr = NULL;
1771 range.offset = 0;
1772 range.size = sizeof(value);
1773 wined3d_context_copy_bo_address(context, &dst, &src, 1, &range, WINED3D_MAP_WRITE | WINED3D_MAP_DISCARD);
1775 context_release(context);
1778 void wined3d_unordered_access_view_copy_counter(struct wined3d_unordered_access_view *view,
1779 struct wined3d_buffer *buffer, unsigned int offset, struct wined3d_context *context)
1781 struct wined3d_const_bo_address src;
1783 if (!view->counter_bo)
1784 return;
1786 src.buffer_object = view->counter_bo;
1787 src.addr = NULL;
1789 wined3d_buffer_copy_bo_address(buffer, context, offset, &src, sizeof(uint32_t));
1792 void wined3d_unordered_access_view_gl_update(struct wined3d_unordered_access_view_gl *uav_gl,
1793 struct wined3d_context_gl *context_gl)
1795 struct wined3d_buffer *buffer = buffer_from_resource(uav_gl->v.resource);
1797 assert(!uav_gl->bo_user.valid);
1798 create_buffer_view(&uav_gl->gl_view, &context_gl->c, &uav_gl->v.desc, buffer, uav_gl->v.format);
1799 uav_gl->bo_user.valid = true;
1800 list_add_head(&buffer->buffer_object->users, &uav_gl->bo_user.entry);
1803 static void wined3d_unordered_access_view_gl_cs_init(void *object)
1805 struct wined3d_unordered_access_view_gl *view_gl = object;
1806 struct wined3d_resource *resource = view_gl->v.resource;
1807 struct wined3d_view_desc *desc = &view_gl->v.desc;
1808 const struct wined3d_gl_info *gl_info;
1810 TRACE("view_gl %p.\n", view_gl);
1812 gl_info = &wined3d_adapter_gl(resource->device->adapter)->gl_info;
1814 if (resource->type == WINED3D_RTYPE_BUFFER)
1816 struct wined3d_device_gl *device_gl = wined3d_device_gl(resource->device);
1817 struct wined3d_buffer *buffer = buffer_from_resource(resource);
1818 struct wined3d_context_gl *context_gl;
1820 context_gl = wined3d_context_gl(context_acquire(&device_gl->d, NULL, 0));
1821 create_buffer_view(&view_gl->gl_view, &context_gl->c, desc, buffer, view_gl->v.format);
1822 view_gl->bo_user.valid = true;
1823 list_add_head(&buffer->buffer_object->users, &view_gl->bo_user.entry);
1824 if (desc->flags & (WINED3D_VIEW_BUFFER_COUNTER | WINED3D_VIEW_BUFFER_APPEND))
1826 struct wined3d_bo_gl *bo = &view_gl->counter_bo;
1828 view_gl->v.counter_bo = &bo->b;
1829 wined3d_device_gl_create_bo(device_gl, context_gl, sizeof(uint32_t), GL_ATOMIC_COUNTER_BUFFER,
1830 GL_STATIC_DRAW, true, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_CLIENT_STORAGE_BIT, bo);
1831 wined3d_unordered_access_view_set_counter(&view_gl->v, 0);
1833 context_release(&context_gl->c);
1835 else
1837 struct wined3d_texture_gl *texture_gl = wined3d_texture_gl(texture_from_resource(resource));
1838 unsigned int depth_or_layer_count;
1840 if (resource->type == WINED3D_RTYPE_TEXTURE_3D)
1841 depth_or_layer_count = wined3d_texture_get_level_depth(&texture_gl->t, desc->u.texture.level_idx);
1842 else
1843 depth_or_layer_count = texture_gl->t.layer_count;
1845 if (desc->u.texture.layer_idx || desc->u.texture.layer_count != depth_or_layer_count)
1847 create_texture_view(&view_gl->gl_view, get_texture_view_target(gl_info, desc, texture_gl),
1848 desc, texture_gl, view_gl->v.format);
1853 static HRESULT wined3d_unordered_access_view_init(struct wined3d_unordered_access_view *view,
1854 const struct wined3d_view_desc *desc, struct wined3d_resource *resource,
1855 void *parent, const struct wined3d_parent_ops *parent_ops)
1857 view->refcount = 1;
1858 view->parent = parent;
1859 view->parent_ops = parent_ops;
1861 if (!(resource->bind_flags & WINED3D_BIND_UNORDERED_ACCESS))
1862 return E_INVALIDARG;
1863 if (!(view->format = validate_resource_view(desc, resource, TRUE, FALSE)))
1864 return E_INVALIDARG;
1865 view->desc = *desc;
1867 wined3d_resource_incref(view->resource = resource);
1869 return WINED3D_OK;
1872 HRESULT wined3d_unordered_access_view_gl_init(struct wined3d_unordered_access_view_gl *view_gl,
1873 const struct wined3d_view_desc *desc, struct wined3d_resource *resource,
1874 void *parent, const struct wined3d_parent_ops *parent_ops)
1876 HRESULT hr;
1878 TRACE("view_gl %p, desc %s, resource %p, parent %p, parent_ops %p.\n",
1879 view_gl, wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops);
1881 if (FAILED(hr = wined3d_unordered_access_view_init(&view_gl->v, desc, resource, parent, parent_ops)))
1882 return hr;
1884 list_init(&view_gl->bo_user.entry);
1885 wined3d_cs_init_object(resource->device->cs, wined3d_unordered_access_view_gl_cs_init, view_gl);
1887 return hr;
1890 static int compile_hlsl_cs(const struct vkd3d_shader_code *hlsl, struct vkd3d_shader_code *dxbc)
1892 struct vkd3d_shader_hlsl_source_info hlsl_info;
1893 struct vkd3d_shader_compile_info info;
1895 static const struct vkd3d_shader_compile_option options[] =
1897 {VKD3D_SHADER_COMPILE_OPTION_API_VERSION, VKD3D_SHADER_API_VERSION_1_12},
1900 info.type = VKD3D_SHADER_STRUCTURE_TYPE_COMPILE_INFO;
1901 info.next = &hlsl_info;
1902 info.source = *hlsl;
1903 info.source_type = VKD3D_SHADER_SOURCE_HLSL;
1904 info.target_type = VKD3D_SHADER_TARGET_DXBC_TPF;
1905 info.options = options;
1906 info.option_count = ARRAY_SIZE(options);
1907 info.log_level = VKD3D_SHADER_LOG_NONE;
1908 info.source_name = NULL;
1910 hlsl_info.type = VKD3D_SHADER_STRUCTURE_TYPE_HLSL_SOURCE_INFO;
1911 hlsl_info.next = NULL;
1912 hlsl_info.entry_point = "main";
1913 hlsl_info.secondary_code.code = NULL;
1914 hlsl_info.secondary_code.size = 0;
1915 hlsl_info.profile = "cs_5_0";
1917 return vkd3d_shader_compile(&info, dxbc, NULL);
1920 struct wined3d_uav_clear_constants_vk
1922 VkClearColorValue color;
1923 VkOffset2D offset;
1924 VkExtent2D extent;
1927 static VkPipeline create_uav_pipeline(struct wined3d_context_vk *context_vk,
1928 struct wined3d_pipeline_layout_vk *layout, const char *resource_filename,
1929 enum wined3d_shader_resource_type resource_type)
1931 VkComputePipelineCreateInfo pipeline_info;
1932 struct wined3d_shader_desc shader_desc;
1933 const struct wined3d_vk_info *vk_info;
1934 struct vkd3d_shader_code code, dxbc;
1935 struct wined3d_context *context;
1936 VkShaderModule shader_module;
1937 VkDevice vk_device;
1938 void *resource_ptr;
1939 VkPipeline result;
1940 HGLOBAL global;
1941 HMODULE module;
1942 HRSRC resource;
1943 VkResult vr;
1944 int ret;
1946 vk_info = context_vk->vk_info;
1947 context = &context_vk->c;
1949 if (!GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
1950 (const char *)create_uav_pipeline, &module))
1952 ERR("Failed to get a reference to the current module, last error %ld.\n", GetLastError());
1953 return VK_NULL_HANDLE;
1956 if (!(resource = FindResourceA(module, resource_filename, (const char *)RT_RCDATA)))
1958 ERR("Failed to retrieve resource, last error %ld.\n", GetLastError());
1959 return VK_NULL_HANDLE;
1962 if (!(global = LoadResource(module, resource)))
1964 ERR("Failed to load resource, last error %ld.\n", GetLastError());
1965 return VK_NULL_HANDLE;
1968 if (!(resource_ptr = LockResource(global)))
1970 ERR("Failed to lock resource.\n");
1971 FreeResource(resource);
1972 return VK_NULL_HANDLE;
1975 code.code = resource_ptr;
1976 code.size = SizeofResource(module, resource);
1978 if ((ret = compile_hlsl_cs(&code, &dxbc)) < 0)
1980 ERR("Failed to compile shader, ret %d.\n", ret);
1981 FreeResource(resource);
1982 return VK_NULL_HANDLE;
1985 if (FreeResource(resource))
1986 ERR("Failed to free resource.\n");
1988 shader_desc.byte_code = dxbc.code;
1989 shader_desc.byte_code_size = dxbc.size;
1991 shader_module = (VkShaderModule)context->device->adapter->shader_backend->shader_compile(context, &shader_desc,
1992 WINED3D_SHADER_TYPE_COMPUTE);
1993 if (shader_module == VK_NULL_HANDLE)
1995 ERR("Failed to create shader.\n");
1996 vkd3d_shader_free_shader_code(&dxbc);
1997 return VK_NULL_HANDLE;
2000 vkd3d_shader_free_shader_code(&dxbc);
2002 pipeline_info.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
2003 pipeline_info.pNext = NULL;
2004 pipeline_info.flags = 0;
2005 pipeline_info.stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
2006 pipeline_info.stage.pNext = NULL;
2007 pipeline_info.stage.flags = 0;
2008 pipeline_info.stage.stage = VK_SHADER_STAGE_COMPUTE_BIT;
2009 pipeline_info.stage.pName = "main";
2010 pipeline_info.stage.pSpecializationInfo = NULL;
2011 pipeline_info.stage.module = shader_module;
2012 pipeline_info.layout = layout->vk_pipeline_layout;
2013 pipeline_info.basePipelineHandle = VK_NULL_HANDLE;
2014 pipeline_info.basePipelineIndex = -1;
2016 vk_device = wined3d_device_vk(context->device)->vk_device;
2018 if ((vr = VK_CALL(vkCreateComputePipelines(vk_device, VK_NULL_HANDLE, 1, &pipeline_info, NULL, &result))) < 0)
2020 ERR("Failed to create Vulkan compute pipeline, vr %s.\n", wined3d_debug_vkresult(vr));
2021 return VK_NULL_HANDLE;
2024 VK_CALL(vkDestroyShaderModule(vk_device, shader_module, NULL));
2025 return result;
2028 void wined3d_device_vk_uav_clear_state_init(struct wined3d_device_vk *device_vk)
2030 struct wined3d_uav_clear_state_vk *state = &device_vk->uav_clear_state;
2031 struct wined3d_context_vk *context_vk = &device_vk->context_vk;
2032 VkDescriptorSetLayoutBinding vk_set_bindings[2];
2034 vk_set_bindings[0].binding = 0;
2035 vk_set_bindings[0].descriptorCount = 1;
2036 vk_set_bindings[0].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
2037 vk_set_bindings[0].pImmutableSamplers = NULL;
2038 vk_set_bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
2040 vk_set_bindings[1].binding = 1;
2041 vk_set_bindings[1].descriptorCount = 1;
2042 vk_set_bindings[1].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
2043 vk_set_bindings[1].pImmutableSamplers = NULL;
2045 vk_set_bindings[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
2046 state->image_layout = wined3d_context_vk_get_pipeline_layout(context_vk, vk_set_bindings, 2);
2048 vk_set_bindings[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
2049 state->buffer_layout = wined3d_context_vk_get_pipeline_layout(context_vk, vk_set_bindings, 2);
2051 state->float_pipelines.buffer = create_uav_pipeline(context_vk, state->buffer_layout,
2052 "cs_uav_clear_buffer_float_code.hlsl", WINED3D_SHADER_RESOURCE_BUFFER);
2053 state->uint_pipelines.buffer = create_uav_pipeline(context_vk, state->buffer_layout,
2054 "cs_uav_clear_buffer_uint_code.hlsl", WINED3D_SHADER_RESOURCE_BUFFER);
2055 state->float_pipelines.image_1d = create_uav_pipeline(context_vk, state->image_layout,
2056 "cs_uav_clear_1d_float_code.hlsl", WINED3D_SHADER_RESOURCE_TEXTURE_1D);
2057 state->uint_pipelines.image_1d = create_uav_pipeline(context_vk, state->image_layout,
2058 "cs_uav_clear_1d_uint_code.hlsl", WINED3D_SHADER_RESOURCE_TEXTURE_1D);
2059 state->float_pipelines.image_1d_array = create_uav_pipeline(context_vk, state->image_layout,
2060 "cs_uav_clear_1d_array_float_code.hlsl", WINED3D_SHADER_RESOURCE_TEXTURE_1DARRAY);
2061 state->uint_pipelines.image_1d_array = create_uav_pipeline(context_vk, state->image_layout,
2062 "cs_uav_clear_1d_array_uint_code.hlsl", WINED3D_SHADER_RESOURCE_TEXTURE_1DARRAY);
2063 state->float_pipelines.image_2d = create_uav_pipeline(context_vk, state->image_layout,
2064 "cs_uav_clear_2d_float_code.hlsl", WINED3D_SHADER_RESOURCE_TEXTURE_2D);
2065 state->uint_pipelines.image_2d = create_uav_pipeline(context_vk, state->image_layout,
2066 "cs_uav_clear_2d_uint_code.hlsl", WINED3D_SHADER_RESOURCE_TEXTURE_2D);
2067 state->float_pipelines.image_2d_array = create_uav_pipeline(context_vk, state->image_layout,
2068 "cs_uav_clear_2d_array_float_code.hlsl", WINED3D_SHADER_RESOURCE_TEXTURE_2DARRAY);
2069 state->uint_pipelines.image_2d_array = create_uav_pipeline(context_vk, state->image_layout,
2070 "cs_uav_clear_2d_array_uint_code.hlsl", WINED3D_SHADER_RESOURCE_TEXTURE_2DARRAY);
2071 state->float_pipelines.image_3d = create_uav_pipeline(context_vk, state->image_layout,
2072 "cs_uav_clear_3d_float_code.hlsl", WINED3D_SHADER_RESOURCE_TEXTURE_3D);
2073 state->uint_pipelines.image_3d = create_uav_pipeline(context_vk, state->image_layout,
2074 "cs_uav_clear_3d_uint_code.hlsl", WINED3D_SHADER_RESOURCE_TEXTURE_3D);
2076 state->buffer_group_size.x = 128;
2077 state->buffer_group_size.y = 1;
2078 state->buffer_group_size.z = 1;
2079 state->image_1d_group_size.x = 64;
2080 state->image_1d_group_size.y = 1;
2081 state->image_1d_group_size.z = 1;
2082 state->image_1d_array_group_size.x = 64;
2083 state->image_1d_array_group_size.y = 1;
2084 state->image_1d_array_group_size.z = 1;
2085 state->image_2d_group_size.x = 8;
2086 state->image_2d_group_size.y = 8;
2087 state->image_2d_group_size.z = 1;
2088 state->image_2d_array_group_size.x = 8;
2089 state->image_2d_array_group_size.y = 8;
2090 state->image_2d_array_group_size.z = 1;
2091 state->image_3d_group_size.x = 8;
2092 state->image_3d_group_size.y = 8;
2093 state->image_3d_group_size.z = 1;
2096 void wined3d_device_vk_uav_clear_state_cleanup(struct wined3d_device_vk *device_vk)
2098 struct wined3d_uav_clear_state_vk *state = &device_vk->uav_clear_state;
2099 const struct wined3d_vk_info *vk_info = &device_vk->vk_info;
2101 VK_CALL(vkDestroyPipeline(device_vk->vk_device, state->float_pipelines.buffer, NULL));
2102 VK_CALL(vkDestroyPipeline(device_vk->vk_device, state->float_pipelines.image_1d, NULL));
2103 VK_CALL(vkDestroyPipeline(device_vk->vk_device, state->float_pipelines.image_1d_array, NULL));
2104 VK_CALL(vkDestroyPipeline(device_vk->vk_device, state->float_pipelines.image_2d, NULL));
2105 VK_CALL(vkDestroyPipeline(device_vk->vk_device, state->float_pipelines.image_2d_array, NULL));
2106 VK_CALL(vkDestroyPipeline(device_vk->vk_device, state->float_pipelines.image_3d, NULL));
2108 VK_CALL(vkDestroyPipeline(device_vk->vk_device, state->uint_pipelines.buffer, NULL));
2109 VK_CALL(vkDestroyPipeline(device_vk->vk_device, state->uint_pipelines.image_1d, NULL));
2110 VK_CALL(vkDestroyPipeline(device_vk->vk_device, state->uint_pipelines.image_1d_array, NULL));
2111 VK_CALL(vkDestroyPipeline(device_vk->vk_device, state->uint_pipelines.image_2d, NULL));
2112 VK_CALL(vkDestroyPipeline(device_vk->vk_device, state->uint_pipelines.image_2d_array, NULL));
2113 VK_CALL(vkDestroyPipeline(device_vk->vk_device, state->uint_pipelines.image_3d, NULL));
2116 void wined3d_unordered_access_view_vk_clear(struct wined3d_unordered_access_view_vk *view_vk,
2117 const struct wined3d_uvec4 *clear_value, struct wined3d_context_vk *context_vk, bool fp)
2119 struct wined3d_bo_address cb_source_address, cb_destination_address;
2120 const struct wined3d_format *view_format = view_vk->v.format;
2121 struct wined3d_view_desc *view_desc = &view_vk->v.desc;
2122 struct wined3d_uav_clear_constants_vk constants = {0};
2123 struct wined3d_device *device = context_vk->c.device;
2124 struct wined3d_shader_thread_group_size group_count;
2125 enum wined3d_format_id format_id = view_format->id;
2126 struct wined3d_uav_clear_pipelines_vk *pipelines;
2127 struct wined3d_texture_vk *texture_vk = NULL;
2128 struct wined3d_pipeline_layout_vk *layout;
2129 struct wined3d_uav_clear_state_vk *state;
2130 const struct wined3d_vk_info *vk_info;
2131 VkDescriptorImageInfo vk_image_info;
2132 struct wined3d_device_vk *device_vk;
2133 VkDescriptorBufferInfo buffer_info;
2134 struct wined3d_resource *resource;
2135 VkCommandBuffer vk_command_buffer;
2136 struct wined3d_bo_vk constants_bo;
2137 VkWriteDescriptorSet vk_writes[2];
2138 VkBufferView vk_buffer_view;
2139 struct wined3d_range range;
2140 VkMemoryBarrier vk_barrier;
2141 VkPipeline vk_pipeline;
2142 bool is_array;
2144 device_vk = wined3d_device_vk(device);
2145 state = &device_vk->uav_clear_state;
2146 pipelines = fp ? &state->float_pipelines : &state->uint_pipelines;
2148 resource = view_vk->v.resource;
2149 is_array = view_desc->flags & WINED3D_VIEW_TEXTURE_ARRAY;
2151 switch (resource->type)
2153 case WINED3D_RTYPE_BUFFER:
2154 vk_pipeline = pipelines->buffer;
2155 group_count = state->buffer_group_size;
2156 break;
2157 case WINED3D_RTYPE_TEXTURE_1D:
2158 if (is_array)
2160 vk_pipeline = pipelines->image_1d_array;
2161 group_count = state->image_1d_array_group_size;
2163 else
2165 vk_pipeline = pipelines->image_1d;
2166 group_count = state->image_1d_group_size;
2168 break;
2169 case WINED3D_RTYPE_TEXTURE_2D:
2170 if (is_array)
2172 vk_pipeline = pipelines->image_2d_array;
2173 group_count = state->image_2d_array_group_size;
2175 else
2177 vk_pipeline = pipelines->image_2d;
2178 group_count = state->image_2d_group_size;
2180 break;
2181 case WINED3D_RTYPE_TEXTURE_3D:
2182 vk_pipeline = pipelines->image_3d;
2183 group_count = state->image_3d_group_size;
2184 break;
2186 default:
2187 ERR("Unhandled resource type %s.\n", debug_d3dresourcetype(resource->type));
2188 return;
2191 if (vk_pipeline == VK_NULL_HANDLE)
2193 ERR("Pipeline was not correctly initialized.\n");
2194 return;
2197 vk_writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
2198 vk_writes[0].pNext = NULL;
2199 vk_writes[0].dstBinding = 1;
2200 vk_writes[0].dstArrayElement = 0;
2201 vk_writes[0].descriptorCount = 1;
2202 vk_writes[0].pImageInfo = NULL;
2203 vk_writes[0].pTexelBufferView = &vk_buffer_view;
2204 vk_writes[0].pImageInfo = &vk_image_info;
2206 if (resource->type == WINED3D_RTYPE_BUFFER)
2208 struct wined3d_buffer *buffer = buffer_from_resource(resource);
2209 unsigned int offset, size;
2211 layout = state->buffer_layout;
2212 vk_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
2214 if (buffer->structure_byte_stride)
2215 constants.extent.width = view_desc->u.buffer.count * buffer->structure_byte_stride / 4;
2216 else
2217 constants.extent.width = view_desc->u.buffer.count;
2218 constants.extent.height = 1;
2220 get_buffer_view_range(buffer, view_desc, view_format, &offset, &size);
2221 if (!offset && size == buffer->resource.size)
2223 wined3d_buffer_prepare_location(buffer, &context_vk->c, WINED3D_LOCATION_BUFFER);
2225 else
2227 wined3d_buffer_acquire_bo_for_write(buffer, &context_vk->c);
2228 wined3d_buffer_load_location(buffer, &context_vk->c, WINED3D_LOCATION_BUFFER);
2230 wined3d_buffer_validate_location(buffer, WINED3D_LOCATION_BUFFER);
2231 wined3d_buffer_invalidate_location(buffer, ~WINED3D_LOCATION_BUFFER);
2233 else
2235 unsigned int layer_count, level_count, base_level, base_layer, i, j;
2237 texture_vk = wined3d_texture_vk(wined3d_texture_from_resource(resource));
2239 layout = state->image_layout;
2240 vk_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
2242 level_count = view_desc->u.texture.level_count;
2243 base_level = view_desc->u.texture.level_idx;
2244 if (resource->type == WINED3D_RTYPE_TEXTURE_3D)
2246 layer_count = 1;
2247 base_layer = 0;
2249 else
2251 layer_count = view_desc->u.texture.layer_count;
2252 base_layer = view_desc->u.texture.layer_idx;
2255 constants.extent.width = wined3d_texture_get_level_width(&texture_vk->t, base_level);
2256 constants.extent.height = wined3d_texture_get_level_height(&texture_vk->t, base_level);
2257 group_count.z = (view_desc->u.texture.layer_count + group_count.z - 1) / group_count.z;
2259 for (i = 0; i < layer_count; ++i)
2261 for (j = 0; j < level_count; ++j)
2263 unsigned int sub_resource_idx = (base_layer + i) * texture_vk->t.level_count + base_level + j;
2265 wined3d_texture_prepare_location(&texture_vk->t, sub_resource_idx,
2266 &context_vk->c, WINED3D_LOCATION_TEXTURE_RGB);
2267 wined3d_texture_validate_location(&texture_vk->t, sub_resource_idx, WINED3D_LOCATION_TEXTURE_RGB);
2268 wined3d_texture_invalidate_location(&texture_vk->t, sub_resource_idx, ~WINED3D_LOCATION_TEXTURE_RGB);
2273 group_count.x = (constants.extent.width + group_count.x - 1) / group_count.x;
2274 group_count.y = (constants.extent.height + group_count.y - 1) / group_count.y;
2276 constants.color.uint32[0] = clear_value->x;
2277 constants.color.uint32[1] = clear_value->y;
2278 constants.color.uint32[2] = clear_value->z;
2279 constants.color.uint32[3] = clear_value->w;
2281 if (!fp)
2283 /* Make sure values are truncated, not saturated to some maximum value. */
2284 constants.color.uint32[0] &= wined3d_mask_from_size(view_format->red_size);
2285 constants.color.uint32[1] &= wined3d_mask_from_size(view_format->green_size);
2286 constants.color.uint32[2] &= wined3d_mask_from_size(view_format->blue_size);
2287 constants.color.uint32[3] &= wined3d_mask_from_size(view_format->alpha_size);
2289 if (view_format->id == WINED3DFMT_R11G11B10_FLOAT)
2291 constants.color.uint32[0] |= constants.color.uint32[1] << 11;
2292 constants.color.uint32[0] |= constants.color.uint32[2] << 22;
2293 format_id = WINED3DFMT_R32_UINT;
2295 else
2297 format_id = wined3d_get_typed_format_id(context_vk->c.device->adapter, view_format,
2298 WINED3D_CHANNEL_TYPE_UINT);
2302 if (format_id == WINED3DFMT_UNKNOWN)
2304 ERR("Unsupported format %s.\n", debug_d3dformat(view_format->id));
2305 return;
2308 if (resource->type == WINED3D_RTYPE_BUFFER)
2310 if (format_id == view_format->id)
2311 vk_buffer_view = view_vk->view_vk.u.vk_buffer_view;
2312 else
2314 vk_buffer_view = wined3d_view_vk_create_vk_buffer_view(context_vk, view_desc,
2315 wined3d_buffer_vk(buffer_from_resource(resource)), wined3d_format_vk(
2316 wined3d_get_format(context_vk->c.device->adapter, format_id, WINED3D_BIND_UNORDERED_ACCESS)));
2317 if (vk_buffer_view == VK_NULL_HANDLE)
2318 return;
2321 else
2323 if (format_id == view_format->id)
2325 vk_image_info = view_vk->view_vk.u.vk_image_info;
2326 if (!vk_image_info.imageView)
2328 const VkDescriptorImageInfo *default_info;
2329 if (!(default_info = wined3d_texture_vk_get_default_image_info(texture_vk, context_vk)))
2330 return;
2331 vk_image_info = *default_info;
2334 else
2336 vk_image_info.sampler = VK_NULL_HANDLE;
2337 vk_image_info.imageLayout = texture_vk->layout;
2338 vk_image_info.imageView = wined3d_view_vk_create_vk_image_view(context_vk, view_desc, texture_vk,
2339 wined3d_format_vk(wined3d_get_format(context_vk->c.device->adapter, format_id,
2340 WINED3D_BIND_UNORDERED_ACCESS)),
2341 COLOR_FIXUP_IDENTITY, false, VK_IMAGE_USAGE_STORAGE_BIT);
2343 if (vk_image_info.imageView == VK_NULL_HANDLE)
2344 return;
2348 vk_writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
2349 vk_writes[1].pNext = NULL;
2350 vk_writes[1].dstBinding = 0;
2351 vk_writes[1].dstArrayElement = 0;
2352 vk_writes[1].descriptorCount = 1;
2353 vk_writes[1].pImageInfo = NULL;
2354 vk_writes[1].pTexelBufferView = NULL;
2355 vk_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
2356 vk_writes[1].pBufferInfo = &buffer_info;
2358 if (!wined3d_context_vk_create_bo(context_vk, sizeof(constants), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
2359 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &constants_bo))
2361 ERR("Failed to create constants BO.\n");
2362 goto out;
2365 cb_source_address.buffer_object = NULL;
2366 cb_source_address.addr = (BYTE *)&constants;
2367 cb_destination_address.buffer_object = &constants_bo.b;
2368 cb_destination_address.addr = 0;
2370 range.offset = 0;
2371 range.size = sizeof(constants);
2372 adapter_vk_copy_bo_address(&context_vk->c, &cb_destination_address,
2373 &cb_source_address, 1, &range, WINED3D_MAP_WRITE | WINED3D_MAP_DISCARD);
2375 buffer_info.buffer = constants_bo.vk_buffer;
2376 buffer_info.range = constants_bo.size;
2377 buffer_info.offset = constants_bo.b.buffer_offset;
2379 vk_info = context_vk->vk_info;
2381 if (!(vk_writes[0].dstSet = wined3d_context_vk_create_vk_descriptor_set(context_vk, layout->vk_set_layout)))
2383 ERR("Failed to create descriptor set.\n");
2384 wined3d_context_vk_destroy_bo(context_vk, &constants_bo);
2385 goto out;
2388 vk_writes[1].dstSet = vk_writes[0].dstSet;
2390 VK_CALL(vkUpdateDescriptorSets(device_vk->vk_device, 2, vk_writes, 0, NULL));
2392 vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk);
2393 wined3d_context_vk_end_current_render_pass(context_vk);
2395 wined3d_context_vk_reference_unordered_access_view(context_vk, view_vk);
2396 wined3d_context_vk_reference_bo(context_vk, &constants_bo);
2397 wined3d_context_vk_destroy_bo(context_vk, &constants_bo);
2399 vk_barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
2400 vk_barrier.pNext = NULL;
2401 vk_barrier.srcAccessMask = vk_access_mask_from_bind_flags(resource->bind_flags);
2402 vk_barrier.dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
2404 VK_CALL(vkCmdPipelineBarrier(vk_command_buffer,
2405 vk_pipeline_stage_mask_from_bind_flags(resource->bind_flags),
2406 VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
2407 0, 1, &vk_barrier, 0, NULL, 0, NULL));
2408 VK_CALL(vkCmdBindPipeline(vk_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, vk_pipeline));
2409 VK_CALL(vkCmdBindDescriptorSets(vk_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE,
2410 layout->vk_pipeline_layout, 0, 1, &vk_writes[0].dstSet, 0, NULL));
2411 VK_CALL(vkCmdDispatch(vk_command_buffer, group_count.x, group_count.y, group_count.z));
2413 vk_barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
2414 vk_barrier.dstAccessMask = vk_access_mask_from_bind_flags(resource->bind_flags);
2416 VK_CALL(vkCmdPipelineBarrier(vk_command_buffer,
2417 VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
2418 vk_pipeline_stage_mask_from_bind_flags(resource->bind_flags),
2419 0, 1, &vk_barrier, 0, NULL, 0, NULL));
2421 context_invalidate_compute_state(&context_vk->c, STATE_COMPUTE_SHADER);
2423 out:
2424 if (format_id != view_format->id)
2426 if (resource->type == WINED3D_RTYPE_BUFFER)
2427 wined3d_context_vk_destroy_vk_buffer_view(context_vk, vk_buffer_view, view_vk->view_vk.command_buffer_id);
2428 else
2429 wined3d_context_vk_destroy_vk_image_view(context_vk, vk_image_info.imageView,
2430 view_vk->view_vk.command_buffer_id);
2434 void wined3d_unordered_access_view_vk_update(struct wined3d_unordered_access_view_vk *uav_vk,
2435 struct wined3d_context_vk *context_vk)
2437 const struct wined3d_format_vk *view_format_vk = wined3d_format_vk(uav_vk->v.format);
2438 const struct wined3d_view_desc *desc = &uav_vk->v.desc;
2439 struct wined3d_resource *resource = uav_vk->v.resource;
2440 struct wined3d_view_vk *view_vk = &uav_vk->view_vk;
2441 struct wined3d_buffer_vk *buffer_vk;
2442 VkBufferView vk_buffer_view;
2444 assert(!view_vk->bo_user.valid);
2446 buffer_vk = wined3d_buffer_vk(buffer_from_resource(resource));
2447 wined3d_context_vk_destroy_vk_buffer_view(context_vk, view_vk->u.vk_buffer_view, view_vk->command_buffer_id);
2448 if ((vk_buffer_view = wined3d_view_vk_create_vk_buffer_view(context_vk, desc, buffer_vk, view_format_vk)))
2450 view_vk->u.vk_buffer_view = vk_buffer_view;
2451 view_vk->bo_user.valid = true;
2452 list_add_head(&buffer_vk->b.buffer_object->users, &view_vk->bo_user.entry);
2456 static void wined3d_unordered_access_view_vk_cs_init(void *object)
2458 struct wined3d_unordered_access_view_vk *uav_vk = object;
2459 struct wined3d_view_vk *view_vk = &uav_vk->view_vk;
2460 struct wined3d_view_desc *desc = &uav_vk->v.desc;
2461 const struct wined3d_format_vk *format_vk;
2462 const struct wined3d_vk_info *vk_info;
2463 struct wined3d_texture_vk *texture_vk;
2464 struct wined3d_context_vk *context_vk;
2465 struct wined3d_device_vk *device_vk;
2466 struct wined3d_buffer_vk *buffer_vk;
2467 VkBufferViewCreateInfo create_info;
2468 struct wined3d_resource *resource;
2469 VkBufferView vk_buffer_view;
2470 uint32_t default_flags = 0;
2471 VkImageView vk_image_view;
2472 VkResult vr;
2474 TRACE("uav_vk %p.\n", uav_vk);
2476 resource = uav_vk->v.resource;
2477 device_vk = wined3d_device_vk(resource->device);
2478 format_vk = wined3d_format_vk(uav_vk->v.format);
2480 if (resource->type == WINED3D_RTYPE_BUFFER)
2482 buffer_vk = wined3d_buffer_vk(buffer_from_resource(resource));
2484 context_vk = wined3d_context_vk(context_acquire(&device_vk->d, NULL, 0));
2485 vk_info = context_vk->vk_info;
2487 if ((vk_buffer_view = wined3d_view_vk_create_vk_buffer_view(context_vk, desc, buffer_vk, format_vk)))
2489 struct wined3d_bo_vk *bo = wined3d_bo_vk(buffer_vk->b.buffer_object);
2491 TRACE("Created buffer view 0x%s.\n", wine_dbgstr_longlong(vk_buffer_view));
2493 uav_vk->view_vk.u.vk_buffer_view = vk_buffer_view;
2494 uav_vk->view_vk.bo_user.valid = true;
2495 list_add_head(&bo->b.users, &view_vk->bo_user.entry);
2498 if (desc->flags & (WINED3D_VIEW_BUFFER_COUNTER | WINED3D_VIEW_BUFFER_APPEND))
2500 if (!wined3d_context_vk_create_bo(context_vk, sizeof(uint32_t), VK_BUFFER_USAGE_TRANSFER_SRC_BIT
2501 | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT,
2502 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &uav_vk->counter_bo))
2504 ERR("Failed to create counter bo.\n");
2505 context_release(&context_vk->c);
2507 return;
2510 wined3d_context_vk_end_current_render_pass(context_vk);
2511 VK_CALL(vkCmdFillBuffer(wined3d_context_vk_get_command_buffer(context_vk),
2512 uav_vk->counter_bo.vk_buffer, uav_vk->counter_bo.b.buffer_offset, sizeof(uint32_t), 0));
2513 wined3d_context_vk_reference_bo(context_vk, &uav_vk->counter_bo);
2515 create_info.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO;
2516 create_info.pNext = NULL;
2517 create_info.flags = 0;
2518 create_info.buffer = uav_vk->counter_bo.vk_buffer;
2519 create_info.format = VK_FORMAT_R32_UINT;
2520 create_info.offset = uav_vk->counter_bo.b.buffer_offset;
2521 create_info.range = sizeof(uint32_t);
2522 if ((vr = VK_CALL(vkCreateBufferView(device_vk->vk_device,
2523 &create_info, NULL, &uav_vk->vk_counter_view))) < 0)
2525 ERR("Failed to create counter buffer view, vr %s.\n", wined3d_debug_vkresult(vr));
2527 else
2529 TRACE("Created counter buffer view 0x%s.\n", wine_dbgstr_longlong(uav_vk->vk_counter_view));
2531 uav_vk->v.counter_bo = &uav_vk->counter_bo.b;
2535 context_release(&context_vk->c);
2537 return;
2540 texture_vk = wined3d_texture_vk(texture_from_resource(resource));
2542 if (texture_vk->t.layer_count > 1)
2543 default_flags |= WINED3D_VIEW_TEXTURE_ARRAY;
2545 if (resource->format->id == format_vk->f.id && desc->flags == default_flags
2546 && !desc->u.texture.level_idx && desc->u.texture.level_count == texture_vk->t.level_count
2547 && !desc->u.texture.layer_idx && desc->u.texture.layer_count == texture_vk->t.layer_count
2548 && !(resource->bind_flags & WINED3D_BIND_DEPTH_STENCIL) && resource->type != WINED3D_RTYPE_TEXTURE_3D)
2550 TRACE("Creating identity unordered access view.\n");
2551 return;
2554 if (texture_vk->t.swapchain && texture_vk->t.swapchain->state.desc.backbuffer_count > 1)
2555 FIXME("Swapchain unordered access views not supported.\n");
2557 context_vk = wined3d_context_vk(context_acquire(&device_vk->d, NULL, 0));
2558 vk_image_view = wined3d_view_vk_create_vk_image_view(context_vk, desc,
2559 texture_vk, format_vk, format_vk->f.color_fixup, false, VK_IMAGE_USAGE_STORAGE_BIT);
2560 context_release(&context_vk->c);
2562 if (!vk_image_view)
2563 return;
2565 TRACE("Created image view 0x%s.\n", wine_dbgstr_longlong(vk_image_view));
2567 view_vk->u.vk_image_info.imageView = vk_image_view;
2568 view_vk->u.vk_image_info.sampler = VK_NULL_HANDLE;
2569 view_vk->u.vk_image_info.imageLayout = texture_vk->layout;
2572 HRESULT wined3d_unordered_access_view_vk_init(struct wined3d_unordered_access_view_vk *view_vk,
2573 const struct wined3d_view_desc *desc, struct wined3d_resource *resource,
2574 void *parent, const struct wined3d_parent_ops *parent_ops)
2576 HRESULT hr;
2578 TRACE("view_vk %p, desc %s, resource %p, parent %p, parent_ops %p.\n",
2579 view_vk, wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops);
2581 if (FAILED(hr = wined3d_unordered_access_view_init(&view_vk->v, desc, resource, parent, parent_ops)))
2582 return hr;
2584 list_init(&view_vk->view_vk.bo_user.entry);
2585 wined3d_cs_init_object(resource->device->cs, wined3d_unordered_access_view_vk_cs_init, view_vk);
2587 return hr;
2590 HRESULT CDECL wined3d_unordered_access_view_create(const struct wined3d_view_desc *desc,
2591 struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops,
2592 struct wined3d_unordered_access_view **view)
2594 const struct wined3d_adapter_ops *adapter_ops;
2596 TRACE("desc %s, resource %p, parent %p, parent_ops %p, view %p.\n",
2597 wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops, view);
2599 adapter_ops = resource->device->adapter->adapter_ops;
2600 return adapter_ops->adapter_create_unordered_access_view(desc, resource, parent, parent_ops, view);