wined3d: Pass a wined3d_device_context to wined3d_shader_resource_view_generate_mipma...
[wine.git] / dlls / wined3d / view.c
blob03abaf5710267ea505c128cac7d4bf3eeee0cf00
1 /*
2 * Copyright 2009, 2011 Henri Verbeet for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include "config.h"
21 #include "wine/port.h"
23 #include "wined3d_private.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
27 #define WINED3D_VIEW_CUBE_ARRAY (WINED3D_VIEW_TEXTURE_CUBE | WINED3D_VIEW_TEXTURE_ARRAY)
29 static BOOL is_stencil_view_format(const struct wined3d_format *format)
31 return format->id == WINED3DFMT_X24_TYPELESS_G8_UINT
32 || format->id == WINED3DFMT_X32_TYPELESS_G8X24_UINT;
35 static GLenum get_texture_view_target(const struct wined3d_gl_info *gl_info,
36 const struct wined3d_view_desc *desc, const struct wined3d_texture_gl *texture_gl)
38 static const struct
40 GLenum texture_target;
41 unsigned int view_flags;
42 GLenum view_target;
43 enum wined3d_gl_extension extension;
45 view_types[] =
47 {GL_TEXTURE_CUBE_MAP, 0, GL_TEXTURE_CUBE_MAP},
48 {GL_TEXTURE_RECTANGLE, 0, GL_TEXTURE_RECTANGLE},
49 {GL_TEXTURE_3D, 0, GL_TEXTURE_3D},
51 {GL_TEXTURE_2D, 0, GL_TEXTURE_2D},
52 {GL_TEXTURE_2D, WINED3D_VIEW_TEXTURE_ARRAY, GL_TEXTURE_2D_ARRAY},
53 {GL_TEXTURE_2D_ARRAY, 0, GL_TEXTURE_2D},
54 {GL_TEXTURE_2D_ARRAY, WINED3D_VIEW_TEXTURE_ARRAY, GL_TEXTURE_2D_ARRAY},
55 {GL_TEXTURE_2D_ARRAY, WINED3D_VIEW_TEXTURE_CUBE, GL_TEXTURE_CUBE_MAP},
56 {GL_TEXTURE_2D_ARRAY, WINED3D_VIEW_CUBE_ARRAY, GL_TEXTURE_CUBE_MAP_ARRAY, ARB_TEXTURE_CUBE_MAP_ARRAY},
58 {GL_TEXTURE_2D_MULTISAMPLE, 0, GL_TEXTURE_2D_MULTISAMPLE},
59 {GL_TEXTURE_2D_MULTISAMPLE, WINED3D_VIEW_TEXTURE_ARRAY, GL_TEXTURE_2D_MULTISAMPLE_ARRAY},
60 {GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 0, GL_TEXTURE_2D_MULTISAMPLE},
61 {GL_TEXTURE_2D_MULTISAMPLE_ARRAY, WINED3D_VIEW_TEXTURE_ARRAY, GL_TEXTURE_2D_MULTISAMPLE_ARRAY},
63 {GL_TEXTURE_1D, 0, GL_TEXTURE_1D},
64 {GL_TEXTURE_1D, WINED3D_VIEW_TEXTURE_ARRAY, GL_TEXTURE_1D_ARRAY},
65 {GL_TEXTURE_1D_ARRAY, 0, GL_TEXTURE_1D},
66 {GL_TEXTURE_1D_ARRAY, WINED3D_VIEW_TEXTURE_ARRAY, GL_TEXTURE_1D_ARRAY},
68 unsigned int flags = desc->flags & (WINED3D_VIEW_BUFFER_RAW | WINED3D_VIEW_BUFFER_APPEND
69 | WINED3D_VIEW_BUFFER_COUNTER | WINED3D_VIEW_TEXTURE_CUBE | WINED3D_VIEW_TEXTURE_ARRAY);
70 unsigned int i;
72 for (i = 0; i < ARRAY_SIZE(view_types); ++i)
74 if (view_types[i].texture_target != texture_gl->target || view_types[i].view_flags != flags)
75 continue;
76 if (gl_info->supported[view_types[i].extension])
77 return view_types[i].view_target;
79 FIXME("Extension %#x not supported.\n", view_types[i].extension);
82 FIXME("Unhandled view flags %#x for texture target %#x.\n", flags, texture_gl->target);
83 return texture_gl->target;
86 static const struct wined3d_format *validate_resource_view(const struct wined3d_view_desc *desc,
87 struct wined3d_resource *resource, BOOL mip_slice, BOOL allow_srgb_toggle)
89 const struct wined3d_adapter *adapter = resource->device->adapter;
90 const struct wined3d_format *format;
92 format = wined3d_get_format(adapter, desc->format_id, resource->bind_flags);
93 if (resource->type == WINED3D_RTYPE_BUFFER && (desc->flags & WINED3D_VIEW_BUFFER_RAW))
95 if (format->id != WINED3DFMT_R32_TYPELESS)
97 WARN("Invalid format %s for raw buffer view.\n", debug_d3dformat(format->id));
98 return NULL;
101 format = wined3d_get_format(adapter, WINED3DFMT_R32_UINT, resource->bind_flags);
104 if (wined3d_format_is_typeless(format))
106 WARN("Trying to create view for typeless format %s.\n", debug_d3dformat(format->id));
107 return NULL;
110 if (resource->type == WINED3D_RTYPE_BUFFER)
112 struct wined3d_buffer *buffer = buffer_from_resource(resource);
113 unsigned int buffer_size, element_size;
115 if (buffer->structure_byte_stride)
117 if (desc->format_id != WINED3DFMT_UNKNOWN)
119 WARN("Invalid format %s for structured buffer view.\n", debug_d3dformat(desc->format_id));
120 return NULL;
123 format = wined3d_get_format(adapter, WINED3DFMT_R32_UINT, resource->bind_flags);
124 element_size = buffer->structure_byte_stride;
126 else
128 element_size = format->byte_count;
131 if (!element_size)
132 return NULL;
134 buffer_size = buffer->resource.size / element_size;
135 if (desc->u.buffer.start_idx >= buffer_size
136 || desc->u.buffer.count > buffer_size - desc->u.buffer.start_idx)
137 return NULL;
139 else
141 struct wined3d_texture *texture = texture_from_resource(resource);
142 unsigned int depth_or_layer_count;
144 if (resource->format->id != format->id && !wined3d_format_is_typeless(resource->format)
145 && (!allow_srgb_toggle || !wined3d_formats_are_srgb_variants(resource->format->id, format->id)))
147 WARN("Trying to create incompatible view for non typeless format %s.\n",
148 debug_d3dformat(format->id));
149 return NULL;
152 if (mip_slice && resource->type == WINED3D_RTYPE_TEXTURE_3D)
153 depth_or_layer_count = wined3d_texture_get_level_depth(texture, desc->u.texture.level_idx);
154 else
155 depth_or_layer_count = texture->layer_count;
157 if (!desc->u.texture.level_count
158 || (mip_slice && desc->u.texture.level_count != 1)
159 || desc->u.texture.level_idx >= texture->level_count
160 || desc->u.texture.level_count > texture->level_count - desc->u.texture.level_idx
161 || !desc->u.texture.layer_count
162 || desc->u.texture.layer_idx >= depth_or_layer_count
163 || desc->u.texture.layer_count > depth_or_layer_count - desc->u.texture.layer_idx)
164 return NULL;
167 return format;
170 static void create_texture_view(struct wined3d_gl_view *view, GLenum view_target,
171 const struct wined3d_view_desc *desc, struct wined3d_texture_gl *texture_gl,
172 const struct wined3d_format *view_format)
174 const struct wined3d_format_gl *view_format_gl;
175 unsigned int level_idx, layer_idx, layer_count;
176 const struct wined3d_gl_info *gl_info;
177 struct wined3d_context_gl *context_gl;
178 struct wined3d_context *context;
179 GLuint texture_name;
181 view_format_gl = wined3d_format_gl(view_format);
182 view->target = view_target;
184 context = context_acquire(texture_gl->t.resource.device, NULL, 0);
185 context_gl = wined3d_context_gl(context);
186 gl_info = context_gl->gl_info;
188 if (!gl_info->supported[ARB_TEXTURE_VIEW])
190 context_release(context);
191 FIXME("OpenGL implementation does not support texture views.\n");
192 return;
195 wined3d_texture_gl_prepare_texture(texture_gl, context_gl, FALSE);
196 texture_name = wined3d_texture_gl_get_texture_name(texture_gl, context, FALSE);
198 level_idx = desc->u.texture.level_idx;
199 layer_idx = desc->u.texture.layer_idx;
200 layer_count = desc->u.texture.layer_count;
201 if (view_target == GL_TEXTURE_3D)
203 if (layer_idx || layer_count != wined3d_texture_get_level_depth(&texture_gl->t, level_idx))
204 FIXME("Depth slice (%u-%u) not supported.\n", layer_idx, layer_count);
205 layer_idx = 0;
206 layer_count = 1;
209 gl_info->gl_ops.gl.p_glGenTextures(1, &view->name);
210 GL_EXTCALL(glTextureView(view->name, view->target, texture_name, view_format_gl->internal,
211 level_idx, desc->u.texture.level_count, layer_idx, layer_count));
212 checkGLcall("create texture view");
214 if (is_stencil_view_format(view_format))
216 static const GLint swizzle[] = {GL_ZERO, GL_RED, GL_ZERO, GL_ZERO};
218 if (!gl_info->supported[ARB_STENCIL_TEXTURING])
220 context_release(context);
221 FIXME("OpenGL implementation does not support stencil texturing.\n");
222 return;
225 wined3d_context_gl_bind_texture(context_gl, view->target, view->name);
226 gl_info->gl_ops.gl.p_glTexParameteriv(view->target, GL_TEXTURE_SWIZZLE_RGBA, swizzle);
227 gl_info->gl_ops.gl.p_glTexParameteri(view->target, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_STENCIL_INDEX);
228 checkGLcall("initialize stencil view");
230 context_invalidate_compute_state(context, STATE_COMPUTE_SHADER_RESOURCE_BINDING);
231 context_invalidate_state(context, STATE_GRAPHICS_SHADER_RESOURCE_BINDING);
233 else if (!is_identity_fixup(view_format->color_fixup) && can_use_texture_swizzle(context->d3d_info, view_format))
235 GLint swizzle[4];
237 wined3d_context_gl_bind_texture(context_gl, view->target, view->name);
238 wined3d_gl_texture_swizzle_from_color_fixup(swizzle, view_format->color_fixup);
239 gl_info->gl_ops.gl.p_glTexParameteriv(view->target, GL_TEXTURE_SWIZZLE_RGBA, swizzle);
240 checkGLcall("set format swizzle");
242 context_invalidate_compute_state(context, STATE_COMPUTE_SHADER_RESOURCE_BINDING);
243 context_invalidate_state(context, STATE_GRAPHICS_SHADER_RESOURCE_BINDING);
246 context_release(context);
249 static void create_buffer_texture(struct wined3d_gl_view *view, struct wined3d_context_gl *context_gl,
250 struct wined3d_buffer_gl *buffer_gl, const struct wined3d_format_gl *view_format_gl,
251 unsigned int offset, unsigned int size)
253 const struct wined3d_gl_info *gl_info = context_gl->gl_info;
255 if (!gl_info->supported[ARB_TEXTURE_BUFFER_OBJECT])
257 FIXME("OpenGL implementation does not support buffer textures.\n");
258 return;
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 wined3d_buffer_load_location(&buffer_gl->b, &context_gl->c, WINED3D_LOCATION_BUFFER);
270 view->target = GL_TEXTURE_BUFFER;
271 if (!view->name)
272 gl_info->gl_ops.gl.p_glGenTextures(1, &view->name);
274 wined3d_context_gl_bind_texture(context_gl, GL_TEXTURE_BUFFER, view->name);
275 if (gl_info->supported[ARB_TEXTURE_BUFFER_RANGE])
277 GL_EXTCALL(glTexBufferRange(GL_TEXTURE_BUFFER, view_format_gl->internal, buffer_gl->bo.id, offset, size));
279 else
281 if (offset || size != buffer_gl->b.resource.size)
282 FIXME("OpenGL implementation does not support ARB_texture_buffer_range.\n");
283 GL_EXTCALL(glTexBuffer(GL_TEXTURE_BUFFER, view_format_gl->internal, buffer_gl->bo.id));
285 checkGLcall("Create buffer texture");
287 context_invalidate_compute_state(&context_gl->c, STATE_COMPUTE_SHADER_RESOURCE_BINDING);
288 context_invalidate_state(&context_gl->c, STATE_GRAPHICS_SHADER_RESOURCE_BINDING);
291 static void get_buffer_view_range(const struct wined3d_buffer *buffer,
292 const struct wined3d_view_desc *desc, const struct wined3d_format *view_format,
293 unsigned int *offset, unsigned int *size)
295 if (desc->format_id == WINED3DFMT_UNKNOWN)
297 *offset = desc->u.buffer.start_idx * buffer->structure_byte_stride;
298 *size = desc->u.buffer.count * buffer->structure_byte_stride;
300 else
302 *offset = desc->u.buffer.start_idx * view_format->byte_count;
303 *size = desc->u.buffer.count * view_format->byte_count;
307 static void create_buffer_view(struct wined3d_gl_view *view, struct wined3d_context *context,
308 const struct wined3d_view_desc *desc, struct wined3d_buffer *buffer,
309 const struct wined3d_format *view_format)
311 unsigned int offset, size;
313 get_buffer_view_range(buffer, desc, view_format, &offset, &size);
314 create_buffer_texture(view, wined3d_context_gl(context),
315 wined3d_buffer_gl(buffer), wined3d_format_gl(view_format), offset, size);
318 static void wined3d_view_invalidate_location(struct wined3d_resource *resource,
319 const struct wined3d_view_desc *desc, DWORD location)
321 unsigned int i, sub_resource_idx, layer_count;
322 struct wined3d_texture *texture;
324 if (resource->type == WINED3D_RTYPE_BUFFER)
326 wined3d_buffer_invalidate_location(buffer_from_resource(resource), location);
327 return;
330 texture = texture_from_resource(resource);
332 sub_resource_idx = desc->u.texture.layer_idx * texture->level_count + desc->u.texture.level_idx;
333 layer_count = resource->type != WINED3D_RTYPE_TEXTURE_3D ? desc->u.texture.layer_count : 1;
334 for (i = 0; i < layer_count; ++i, sub_resource_idx += texture->level_count)
335 wined3d_texture_invalidate_location(texture, sub_resource_idx, location);
338 ULONG CDECL wined3d_rendertarget_view_incref(struct wined3d_rendertarget_view *view)
340 ULONG refcount = InterlockedIncrement(&view->refcount);
342 TRACE("%p increasing refcount to %u.\n", view, refcount);
344 return refcount;
347 void wined3d_rendertarget_view_cleanup(struct wined3d_rendertarget_view *view)
349 /* Call wined3d_object_destroyed() before releasing the resource,
350 * since releasing the resource may end up destroying the parent. */
351 view->parent_ops->wined3d_object_destroyed(view->parent);
352 wined3d_resource_decref(view->resource);
355 ULONG CDECL wined3d_rendertarget_view_decref(struct wined3d_rendertarget_view *view)
357 ULONG refcount = InterlockedDecrement(&view->refcount);
359 TRACE("%p decreasing refcount to %u.\n", view, refcount);
361 if (!refcount)
362 view->resource->device->adapter->adapter_ops->adapter_destroy_rendertarget_view(view);
364 return refcount;
367 void * CDECL wined3d_rendertarget_view_get_parent(const struct wined3d_rendertarget_view *view)
369 TRACE("view %p.\n", view);
371 return view->parent;
374 void * CDECL wined3d_rendertarget_view_get_sub_resource_parent(const struct wined3d_rendertarget_view *view)
376 struct wined3d_texture *texture;
378 TRACE("view %p.\n", view);
380 if (view->resource->type == WINED3D_RTYPE_BUFFER)
381 return wined3d_buffer_get_parent(buffer_from_resource(view->resource));
383 texture = texture_from_resource(view->resource);
385 return texture->sub_resources[view->sub_resource_idx].parent;
388 void CDECL wined3d_rendertarget_view_set_parent(struct wined3d_rendertarget_view *view, void *parent)
390 TRACE("view %p, parent %p.\n", view, parent);
392 view->parent = parent;
395 struct wined3d_resource * CDECL wined3d_rendertarget_view_get_resource(const struct wined3d_rendertarget_view *view)
397 TRACE("view %p.\n", view);
399 return view->resource;
402 void wined3d_rendertarget_view_get_drawable_size(const struct wined3d_rendertarget_view *view,
403 const struct wined3d_context *context, unsigned int *width, unsigned int *height)
405 const struct wined3d_texture *texture;
407 if (view->resource->type != WINED3D_RTYPE_TEXTURE_2D)
409 *width = view->width;
410 *height = view->height;
411 return;
414 texture = texture_from_resource(view->resource);
415 if (texture->swapchain)
417 /* The drawable size of an onscreen drawable is the surface size.
418 * (Actually: The window size, but the surface is created in window
419 * size.) */
420 *width = texture->resource.width;
421 *height = texture->resource.height;
423 else if (wined3d_settings.offscreen_rendering_mode == ORM_BACKBUFFER)
425 const struct wined3d_swapchain_desc *desc = &context->swapchain->state.desc;
427 /* The drawable size of a backbuffer / aux buffer offscreen target is
428 * the size of the current context's drawable, which is the size of
429 * the back buffer of the swapchain the active context belongs to. */
430 *width = desc->backbuffer_width;
431 *height = desc->backbuffer_height;
433 else
435 unsigned int level_idx = view->sub_resource_idx % texture->level_count;
437 /* The drawable size of an FBO target is the OpenGL texture size,
438 * which is the power of two size. */
439 *width = wined3d_texture_get_level_pow2_width(texture, level_idx);
440 *height = wined3d_texture_get_level_pow2_height(texture, level_idx);
444 void wined3d_rendertarget_view_prepare_location(struct wined3d_rendertarget_view *view,
445 struct wined3d_context *context, DWORD location)
447 struct wined3d_resource *resource = view->resource;
448 unsigned int i, sub_resource_idx, layer_count;
449 struct wined3d_texture *texture;
451 if (resource->type == WINED3D_RTYPE_BUFFER)
453 FIXME("Not implemented for resources %s.\n", debug_d3dresourcetype(resource->type));
454 return;
457 texture = texture_from_resource(resource);
458 sub_resource_idx = view->sub_resource_idx;
459 layer_count = resource->type != WINED3D_RTYPE_TEXTURE_3D ? view->layer_count : 1;
460 for (i = 0; i < layer_count; ++i, sub_resource_idx += texture->level_count)
461 wined3d_texture_prepare_location(texture, sub_resource_idx, context, location);
464 void wined3d_rendertarget_view_load_location(struct wined3d_rendertarget_view *view,
465 struct wined3d_context *context, DWORD location)
467 struct wined3d_resource *resource = view->resource;
468 unsigned int i, sub_resource_idx, layer_count;
469 struct wined3d_texture *texture;
471 if (resource->type == WINED3D_RTYPE_BUFFER)
473 wined3d_buffer_load_location(buffer_from_resource(resource), context, location);
474 return;
477 texture = texture_from_resource(resource);
478 sub_resource_idx = view->sub_resource_idx;
479 layer_count = resource->type != WINED3D_RTYPE_TEXTURE_3D ? view->layer_count : 1;
480 for (i = 0; i < layer_count; ++i, sub_resource_idx += texture->level_count)
481 wined3d_texture_load_location(texture, sub_resource_idx, context, location);
484 void wined3d_rendertarget_view_validate_location(struct wined3d_rendertarget_view *view, DWORD location)
486 struct wined3d_resource *resource = view->resource;
487 unsigned int i, sub_resource_idx, layer_count;
488 struct wined3d_texture *texture;
490 if (resource->type == WINED3D_RTYPE_BUFFER)
492 FIXME("Not implemented for resources %s.\n", debug_d3dresourcetype(resource->type));
493 return;
496 texture = texture_from_resource(resource);
497 sub_resource_idx = view->sub_resource_idx;
498 layer_count = resource->type != WINED3D_RTYPE_TEXTURE_3D ? view->layer_count : 1;
499 for (i = 0; i < layer_count; ++i, sub_resource_idx += texture->level_count)
500 wined3d_texture_validate_location(texture, sub_resource_idx, location);
503 void wined3d_rendertarget_view_invalidate_location(struct wined3d_rendertarget_view *view, DWORD location)
505 wined3d_view_invalidate_location(view->resource, &view->desc, location);
508 static void wined3d_render_target_view_gl_cs_init(void *object)
510 struct wined3d_rendertarget_view_gl *view_gl = object;
511 struct wined3d_resource *resource = view_gl->v.resource;
512 const struct wined3d_view_desc *desc = &view_gl->v.desc;
514 TRACE("view_gl %p.\n", view_gl);
516 if (resource->type == WINED3D_RTYPE_BUFFER)
518 FIXME("Not implemented for resources %s.\n", debug_d3dresourcetype(resource->type));
520 else
522 struct wined3d_texture_gl *texture_gl = wined3d_texture_gl(texture_from_resource(resource));
523 unsigned int depth_or_layer_count;
525 if (resource->type == WINED3D_RTYPE_TEXTURE_3D)
526 depth_or_layer_count = wined3d_texture_get_level_depth(&texture_gl->t, desc->u.texture.level_idx);
527 else
528 depth_or_layer_count = texture_gl->t.layer_count;
530 if (resource->format->id != view_gl->v.format->id
531 || (view_gl->v.layer_count != 1 && view_gl->v.layer_count != depth_or_layer_count))
533 GLenum resource_class, view_class;
535 resource_class = wined3d_format_gl(resource->format)->view_class;
536 view_class = wined3d_format_gl(view_gl->v.format)->view_class;
537 if (resource_class != view_class)
539 FIXME("Render target view not supported, resource format %s, view format %s.\n",
540 debug_d3dformat(resource->format->id), debug_d3dformat(view_gl->v.format->id));
541 return;
543 if (texture_gl->t.swapchain && texture_gl->t.swapchain->state.desc.backbuffer_count > 1)
545 FIXME("Swapchain views not supported.\n");
546 return;
549 create_texture_view(&view_gl->gl_view, texture_gl->target, desc, texture_gl, view_gl->v.format);
554 static HRESULT wined3d_rendertarget_view_init(struct wined3d_rendertarget_view *view,
555 const struct wined3d_view_desc *desc, struct wined3d_resource *resource,
556 void *parent, const struct wined3d_parent_ops *parent_ops)
558 BOOL allow_srgb_toggle = FALSE;
560 view->refcount = 1;
561 view->parent = parent;
562 view->parent_ops = parent_ops;
564 if (resource->type != WINED3D_RTYPE_BUFFER)
566 struct wined3d_texture *texture = texture_from_resource(resource);
568 if (texture->swapchain)
569 allow_srgb_toggle = TRUE;
571 if (!(view->format = validate_resource_view(desc, resource, TRUE, allow_srgb_toggle)))
572 return E_INVALIDARG;
573 view->format_flags = view->format->flags[resource->gl_type];
574 view->desc = *desc;
576 if (resource->type == WINED3D_RTYPE_BUFFER)
578 view->sub_resource_idx = 0;
579 view->layer_count = 1;
580 view->width = desc->u.buffer.count;
581 view->height = 1;
583 else
585 struct wined3d_texture *texture = texture_from_resource(resource);
587 view->sub_resource_idx = desc->u.texture.level_idx;
588 if (resource->type != WINED3D_RTYPE_TEXTURE_3D)
589 view->sub_resource_idx += desc->u.texture.layer_idx * texture->level_count;
590 view->layer_count = desc->u.texture.layer_count;
591 view->width = wined3d_texture_get_level_width(texture, desc->u.texture.level_idx);
592 view->height = wined3d_texture_get_level_height(texture, desc->u.texture.level_idx);
595 wined3d_resource_incref(view->resource = resource);
597 return WINED3D_OK;
600 HRESULT wined3d_rendertarget_view_no3d_init(struct wined3d_rendertarget_view *view_no3d,
601 const struct wined3d_view_desc *desc, struct wined3d_resource *resource,
602 void *parent, const struct wined3d_parent_ops *parent_ops)
604 TRACE("view_no3d %p, desc %s, resource %p, parent %p, parent_ops %p.\n",
605 view_no3d, wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops);
607 return wined3d_rendertarget_view_init(view_no3d, desc, resource, parent, parent_ops);
610 HRESULT wined3d_rendertarget_view_gl_init(struct wined3d_rendertarget_view_gl *view_gl,
611 const struct wined3d_view_desc *desc, struct wined3d_resource *resource,
612 void *parent, const struct wined3d_parent_ops *parent_ops)
614 HRESULT hr;
616 TRACE("view_gl %p, desc %s, resource %p, parent %p, parent_ops %p.\n",
617 view_gl, wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops);
619 if (FAILED(hr = wined3d_rendertarget_view_init(&view_gl->v, desc, resource, parent, parent_ops)))
620 return hr;
622 wined3d_cs_init_object(resource->device->cs, wined3d_render_target_view_gl_cs_init, view_gl);
624 return hr;
627 VkImageViewType vk_image_view_type_from_wined3d(enum wined3d_resource_type type, uint32_t flags)
629 switch (type)
631 case WINED3D_RTYPE_TEXTURE_1D:
632 if (flags & WINED3D_VIEW_TEXTURE_ARRAY)
633 return VK_IMAGE_VIEW_TYPE_1D_ARRAY;
634 else
635 return VK_IMAGE_VIEW_TYPE_1D;
637 case WINED3D_RTYPE_TEXTURE_2D:
638 if (flags & WINED3D_VIEW_TEXTURE_CUBE)
640 if (flags & WINED3D_VIEW_TEXTURE_ARRAY)
641 return VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
642 else
643 return VK_IMAGE_VIEW_TYPE_CUBE;
645 if (flags & WINED3D_VIEW_TEXTURE_ARRAY)
646 return VK_IMAGE_VIEW_TYPE_2D_ARRAY;
647 else
648 return VK_IMAGE_VIEW_TYPE_2D;
650 case WINED3D_RTYPE_TEXTURE_3D:
651 return VK_IMAGE_VIEW_TYPE_3D;
653 default:
654 ERR("Unhandled resource type %s.\n", debug_d3dresourcetype(type));
655 return ~0u;
659 static VkBufferView wined3d_view_vk_create_vk_buffer_view(struct wined3d_context_vk *context_vk,
660 const struct wined3d_view_desc *desc, struct wined3d_buffer_vk *buffer_vk,
661 const struct wined3d_format_vk *view_format_vk)
663 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
664 VkBufferViewCreateInfo create_info;
665 struct wined3d_device_vk *device_vk;
666 VkBufferView vk_buffer_view;
667 unsigned int offset, size;
668 VkResult vr;
670 get_buffer_view_range(&buffer_vk->b, desc, &view_format_vk->f, &offset, &size);
671 wined3d_buffer_prepare_location(&buffer_vk->b, &context_vk->c, WINED3D_LOCATION_BUFFER);
673 create_info.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO;
674 create_info.pNext = NULL;
675 create_info.flags = 0;
676 create_info.buffer = buffer_vk->bo.vk_buffer;
677 create_info.format = view_format_vk->vk_format;
678 create_info.offset = buffer_vk->bo.buffer_offset + offset;
679 create_info.range = size;
681 device_vk = wined3d_device_vk(buffer_vk->b.resource.device);
682 if ((vr = VK_CALL(vkCreateBufferView(device_vk->vk_device, &create_info, NULL, &vk_buffer_view))) < 0)
684 ERR("Failed to create buffer view, vr %s.\n", wined3d_debug_vkresult(vr));
685 return VK_NULL_HANDLE;
688 return vk_buffer_view;
691 static VkImageView wined3d_view_vk_create_vk_image_view(struct wined3d_context_vk *context_vk,
692 const struct wined3d_view_desc *desc, struct wined3d_texture_vk *texture_vk,
693 const struct wined3d_format_vk *view_format_vk, struct color_fixup_desc fixup, bool rtv)
695 const struct wined3d_resource *resource = &texture_vk->t.resource;
696 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
697 const struct wined3d_format_vk *format_vk;
698 struct wined3d_device_vk *device_vk;
699 VkImageViewCreateInfo create_info;
700 VkImageView vk_image_view;
701 VkResult vr;
703 device_vk = wined3d_device_vk(resource->device);
705 if (!wined3d_texture_vk_prepare_texture(texture_vk, context_vk))
707 ERR("Failed to prepare texture.\n");
708 return VK_NULL_HANDLE;
711 /* Depth formats are a little complicated. For example, the typeless
712 * format corresponding to depth/stencil view format WINED3DFMT_D32_FLOAT
713 * is WINED3DFMT_R32_TYPELESS, and the corresponding shader resource view
714 * format would be WINED3DFMT_R32_FLOAT. Vulkan depth/stencil formats are
715 * only compatible with themselves, so it's not possible to create e.g. a
716 * VK_FORMAT_R32_SFLOAT view on a VK_FORMAT_D32_SFLOAT image. In order to
717 * make it work, we create Vulkan images for WINED3DFMT_R32_TYPELESS
718 * resources with either a depth format (VK_FORMAT_D32_SFLOAT) or a colour
719 * format, depending on whether the bind flags include
720 * WINED3D_BIND_DEPTH_STENCIL or not. In order to then create a Vulkan
721 * view on the image, we then replace the view format here with the
722 * underlying resource format. However, that means it's still not possible
723 * to create e.g. a WINED3DFMT_R32_UINT view on a WINED3DFMT_R32_TYPELESS
724 * depth/stencil resource. */
725 if (resource->bind_flags & WINED3D_BIND_DEPTH_STENCIL)
726 format_vk = wined3d_format_vk(resource->format);
727 else
728 format_vk = view_format_vk;
730 create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
731 create_info.pNext = NULL;
732 create_info.flags = 0;
733 create_info.image = texture_vk->image.vk_image;
734 create_info.viewType = vk_image_view_type_from_wined3d(resource->type, desc->flags);
735 if (rtv && create_info.viewType == VK_IMAGE_VIEW_TYPE_3D)
737 if (desc->u.texture.layer_count > 1)
738 create_info.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
739 else
740 create_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
742 create_info.format = format_vk->vk_format;
743 if (is_stencil_view_format(&view_format_vk->f))
745 create_info.components.r = VK_COMPONENT_SWIZZLE_ZERO;
746 create_info.components.g = VK_COMPONENT_SWIZZLE_R;
747 create_info.components.b = VK_COMPONENT_SWIZZLE_ZERO;
748 create_info.components.a = VK_COMPONENT_SWIZZLE_ZERO;
750 else if (is_identity_fixup(fixup) || !can_use_texture_swizzle(context_vk->c.d3d_info, &format_vk->f))
752 create_info.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
753 create_info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
754 create_info.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
755 create_info.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
757 else
759 wined3d_vk_swizzle_from_color_fixup(&create_info.components, fixup);
761 if ((resource->bind_flags & WINED3D_BIND_DEPTH_STENCIL)
762 && (view_format_vk->f.red_size || view_format_vk->f.green_size))
764 create_info.subresourceRange.aspectMask = 0;
765 if (view_format_vk->f.red_size)
766 create_info.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
767 if (view_format_vk->f.green_size)
768 create_info.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
770 else
772 create_info.subresourceRange.aspectMask = vk_aspect_mask_from_format(&format_vk->f);
774 create_info.subresourceRange.baseMipLevel = desc->u.texture.level_idx;
775 create_info.subresourceRange.levelCount = desc->u.texture.level_count;
776 create_info.subresourceRange.baseArrayLayer = desc->u.texture.layer_idx;
777 create_info.subresourceRange.layerCount = desc->u.texture.layer_count;
778 if ((vr = VK_CALL(vkCreateImageView(device_vk->vk_device, &create_info, NULL, &vk_image_view))) < 0)
780 ERR("Failed to create Vulkan image view, vr %s.\n", wined3d_debug_vkresult(vr));
781 return VK_NULL_HANDLE;
784 return vk_image_view;
787 static void wined3d_render_target_view_vk_cs_init(void *object)
789 struct wined3d_rendertarget_view_vk *view_vk = object;
790 struct wined3d_view_desc *desc = &view_vk->v.desc;
791 const struct wined3d_format_vk *format_vk;
792 struct wined3d_texture_vk *texture_vk;
793 struct wined3d_resource *resource;
794 struct wined3d_context *context;
795 uint32_t default_flags = 0;
797 TRACE("view_vk %p.\n", view_vk);
799 resource = view_vk->v.resource;
800 if (resource->type == WINED3D_RTYPE_BUFFER)
802 FIXME("Buffer views not implemented.\n");
803 return;
806 texture_vk = wined3d_texture_vk(texture_from_resource(resource));
807 format_vk = wined3d_format_vk(view_vk->v.format);
809 if (texture_vk->t.layer_count > 1)
810 default_flags |= WINED3D_VIEW_TEXTURE_ARRAY;
812 if (resource->format->id == format_vk->f.id && desc->flags == default_flags
813 && !desc->u.texture.level_idx && desc->u.texture.level_count == texture_vk->t.level_count
814 && !desc->u.texture.layer_idx && desc->u.texture.layer_count == texture_vk->t.layer_count
815 && !is_stencil_view_format(&format_vk->f) && resource->type != WINED3D_RTYPE_TEXTURE_3D
816 && is_identity_fixup(format_vk->f.color_fixup))
818 TRACE("Creating identity render target view.\n");
819 return;
822 if (texture_vk->t.swapchain && texture_vk->t.swapchain->state.desc.backbuffer_count > 1)
824 FIXME("Swapchain views not supported.\n");
825 return;
828 context = context_acquire(resource->device, NULL, 0);
829 view_vk->vk_image_view = wined3d_view_vk_create_vk_image_view(wined3d_context_vk(context),
830 desc, texture_vk, format_vk, COLOR_FIXUP_IDENTITY, true);
831 context_release(context);
833 if (!view_vk->vk_image_view)
834 return;
836 TRACE("Created image view 0x%s.\n", wine_dbgstr_longlong(view_vk->vk_image_view));
839 HRESULT wined3d_rendertarget_view_vk_init(struct wined3d_rendertarget_view_vk *view_vk,
840 const struct wined3d_view_desc *desc, struct wined3d_resource *resource,
841 void *parent, const struct wined3d_parent_ops *parent_ops)
843 HRESULT hr;
845 TRACE("view_vk %p, desc %s, resource %p, parent %p, parent_ops %p.\n",
846 view_vk, wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops);
848 if (FAILED(hr = wined3d_rendertarget_view_init(&view_vk->v, desc, resource, parent, parent_ops)))
849 return hr;
851 wined3d_cs_init_object(resource->device->cs, wined3d_render_target_view_vk_cs_init, view_vk);
853 return hr;
856 HRESULT CDECL wined3d_rendertarget_view_create(const struct wined3d_view_desc *desc,
857 struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops,
858 struct wined3d_rendertarget_view **view)
860 const struct wined3d_adapter_ops *adapter_ops;
862 TRACE("desc %s, resource %p, parent %p, parent_ops %p, view %p.\n",
863 wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops, view);
865 adapter_ops = resource->device->adapter->adapter_ops;
866 return adapter_ops->adapter_create_rendertarget_view(desc, resource, parent, parent_ops, view);
869 HRESULT CDECL wined3d_rendertarget_view_create_from_sub_resource(struct wined3d_texture *texture,
870 unsigned int sub_resource_idx, void *parent, const struct wined3d_parent_ops *parent_ops,
871 struct wined3d_rendertarget_view **view)
873 struct wined3d_view_desc desc;
875 TRACE("texture %p, sub_resource_idx %u, parent %p, parent_ops %p, view %p.\n",
876 texture, sub_resource_idx, parent, parent_ops, view);
878 desc.format_id = texture->resource.format->id;
879 desc.flags = 0;
880 desc.u.texture.level_idx = sub_resource_idx % texture->level_count;
881 desc.u.texture.level_count = 1;
882 desc.u.texture.layer_idx = sub_resource_idx / texture->level_count;
883 desc.u.texture.layer_count = 1;
885 return wined3d_rendertarget_view_create(&desc, &texture->resource, parent, parent_ops, view);
888 ULONG CDECL wined3d_shader_resource_view_incref(struct wined3d_shader_resource_view *view)
890 ULONG refcount = InterlockedIncrement(&view->refcount);
892 TRACE("%p increasing refcount to %u.\n", view, refcount);
894 return refcount;
897 void wined3d_shader_resource_view_cleanup(struct wined3d_shader_resource_view *view)
899 /* Call wined3d_object_destroyed() before releasing the resource,
900 * since releasing the resource may end up destroying the parent. */
901 view->parent_ops->wined3d_object_destroyed(view->parent);
902 wined3d_resource_decref(view->resource);
905 ULONG CDECL wined3d_shader_resource_view_decref(struct wined3d_shader_resource_view *view)
907 ULONG refcount = InterlockedDecrement(&view->refcount);
909 TRACE("%p decreasing refcount to %u.\n", view, refcount);
911 if (!refcount)
912 view->resource->device->adapter->adapter_ops->adapter_destroy_shader_resource_view(view);
914 return refcount;
917 void * CDECL wined3d_shader_resource_view_get_parent(const struct wined3d_shader_resource_view *view)
919 TRACE("view %p.\n", view);
921 return view->parent;
924 void wined3d_shader_resource_view_gl_update(struct wined3d_shader_resource_view_gl *srv_gl,
925 struct wined3d_context_gl *context_gl)
927 create_buffer_view(&srv_gl->gl_view, &context_gl->c, &srv_gl->v.desc,
928 buffer_from_resource(srv_gl->v.resource), srv_gl->v.format);
929 srv_gl->bo_user.valid = true;
932 static void wined3d_shader_resource_view_gl_cs_init(void *object)
934 struct wined3d_shader_resource_view_gl *view_gl = object;
935 struct wined3d_resource *resource = view_gl->v.resource;
936 const struct wined3d_format *view_format;
937 const struct wined3d_gl_info *gl_info;
938 const struct wined3d_view_desc *desc;
939 GLenum view_target;
941 TRACE("view_gl %p.\n", view_gl);
943 view_format = view_gl->v.format;
944 gl_info = &resource->device->adapter->gl_info;
945 desc = &view_gl->v.desc;
947 if (resource->type == WINED3D_RTYPE_BUFFER)
949 struct wined3d_buffer *buffer = buffer_from_resource(resource);
950 struct wined3d_context *context;
952 context = context_acquire(resource->device, NULL, 0);
953 create_buffer_view(&view_gl->gl_view, context, desc, buffer, view_format);
954 view_gl->bo_user.valid = true;
955 list_add_head(&wined3d_buffer_gl(buffer)->bo.users, &view_gl->bo_user.entry);
956 context_release(context);
958 else
960 struct wined3d_texture_gl *texture_gl = wined3d_texture_gl(texture_from_resource(resource));
961 GLenum resource_class, view_class;
963 resource_class = wined3d_format_gl(resource->format)->view_class;
964 view_class = wined3d_format_gl(view_format)->view_class;
965 view_target = get_texture_view_target(gl_info, desc, texture_gl);
967 if (resource->format->id == view_format->id && texture_gl->target == view_target
968 && !desc->u.texture.level_idx && desc->u.texture.level_count == texture_gl->t.level_count
969 && !desc->u.texture.layer_idx && desc->u.texture.layer_count == texture_gl->t.layer_count
970 && !is_stencil_view_format(view_format))
972 TRACE("Creating identity shader resource view.\n");
974 else if (texture_gl->t.swapchain && texture_gl->t.swapchain->state.desc.backbuffer_count > 1)
976 FIXME("Swapchain shader resource views not supported.\n");
978 else if (resource->format->typeless_id == view_format->typeless_id
979 && resource_class == view_class)
981 create_texture_view(&view_gl->gl_view, view_target, desc, texture_gl, view_format);
983 else if (wined3d_format_is_depth_view(resource->format->id, view_format->id))
985 create_texture_view(&view_gl->gl_view, view_target, desc, texture_gl, resource->format);
987 else
989 FIXME("Shader resource view not supported, resource format %s, view format %s.\n",
990 debug_d3dformat(resource->format->id), debug_d3dformat(view_format->id));
995 static HRESULT wined3d_shader_resource_view_init(struct wined3d_shader_resource_view *view,
996 const struct wined3d_view_desc *desc, struct wined3d_resource *resource,
997 void *parent, const struct wined3d_parent_ops *parent_ops)
999 view->refcount = 1;
1000 view->parent = parent;
1001 view->parent_ops = parent_ops;
1003 if (!(resource->bind_flags & WINED3D_BIND_SHADER_RESOURCE))
1004 return E_INVALIDARG;
1005 if (!(view->format = validate_resource_view(desc, resource, FALSE, FALSE)))
1006 return E_INVALIDARG;
1007 view->desc = *desc;
1009 wined3d_resource_incref(view->resource = resource);
1011 return WINED3D_OK;
1014 HRESULT wined3d_shader_resource_view_gl_init(struct wined3d_shader_resource_view_gl *view_gl,
1015 const struct wined3d_view_desc *desc, struct wined3d_resource *resource,
1016 void *parent, const struct wined3d_parent_ops *parent_ops)
1018 HRESULT hr;
1020 TRACE("view_gl %p, desc %s, resource %p, parent %p, parent_ops %p.\n",
1021 view_gl, wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops);
1023 if (FAILED(hr = wined3d_shader_resource_view_init(&view_gl->v, desc, resource, parent, parent_ops)))
1024 return hr;
1026 list_init(&view_gl->bo_user.entry);
1027 wined3d_cs_init_object(resource->device->cs, wined3d_shader_resource_view_gl_cs_init, view_gl);
1029 return hr;
1032 void wined3d_shader_resource_view_vk_update(struct wined3d_shader_resource_view_vk *srv_vk,
1033 struct wined3d_context_vk *context_vk)
1035 const struct wined3d_format_vk *view_format_vk = wined3d_format_vk(srv_vk->v.format);
1036 const struct wined3d_view_desc *desc = &srv_vk->v.desc;
1037 struct wined3d_resource *resource = srv_vk->v.resource;
1038 struct wined3d_view_vk *view_vk = &srv_vk->view_vk;
1039 struct wined3d_buffer_vk *buffer_vk;
1040 VkBufferView vk_buffer_view;
1042 buffer_vk = wined3d_buffer_vk(buffer_from_resource(resource));
1043 wined3d_context_vk_destroy_vk_buffer_view(context_vk, view_vk->u.vk_buffer_view, view_vk->command_buffer_id);
1044 if ((vk_buffer_view = wined3d_view_vk_create_vk_buffer_view(context_vk, desc, buffer_vk, view_format_vk)))
1046 view_vk->u.vk_buffer_view = vk_buffer_view;
1047 view_vk->bo_user.valid = true;
1051 static void wined3d_shader_resource_view_vk_cs_init(void *object)
1053 struct wined3d_shader_resource_view_vk *srv_vk = object;
1054 struct wined3d_view_desc *desc = &srv_vk->v.desc;
1055 struct wined3d_texture_vk *texture_vk;
1056 const struct wined3d_format *format;
1057 struct wined3d_buffer_vk *buffer_vk;
1058 struct wined3d_resource *resource;
1059 struct wined3d_context *context;
1060 VkBufferView vk_buffer_view;
1061 uint32_t default_flags = 0;
1062 VkImageView vk_image_view;
1064 TRACE("srv_vk %p.\n", srv_vk);
1066 resource = srv_vk->v.resource;
1067 format = srv_vk->v.format;
1069 if (resource->type == WINED3D_RTYPE_BUFFER)
1071 buffer_vk = wined3d_buffer_vk(buffer_from_resource(resource));
1073 context = context_acquire(resource->device, NULL, 0);
1074 vk_buffer_view = wined3d_view_vk_create_vk_buffer_view(wined3d_context_vk(context),
1075 desc, buffer_vk, wined3d_format_vk(format));
1076 context_release(context);
1078 if (!vk_buffer_view)
1079 return;
1081 TRACE("Created buffer view 0x%s.\n", wine_dbgstr_longlong(vk_buffer_view));
1083 srv_vk->view_vk.u.vk_buffer_view = vk_buffer_view;
1084 srv_vk->view_vk.bo_user.valid = true;
1085 list_add_head(&buffer_vk->bo.users, &srv_vk->view_vk.bo_user.entry);
1087 return;
1090 texture_vk = wined3d_texture_vk(texture_from_resource(resource));
1092 if (texture_vk->t.layer_count > 1)
1093 default_flags |= WINED3D_VIEW_TEXTURE_ARRAY;
1095 if (resource->format->id == format->id && desc->flags == default_flags
1096 && !desc->u.texture.level_idx && desc->u.texture.level_count == texture_vk->t.level_count
1097 && !desc->u.texture.layer_idx && desc->u.texture.layer_count == texture_vk->t.layer_count
1098 && !(resource->bind_flags & WINED3D_BIND_DEPTH_STENCIL))
1100 TRACE("Creating identity shader resource view.\n");
1101 return;
1104 if (texture_vk->t.swapchain && texture_vk->t.swapchain->state.desc.backbuffer_count > 1)
1105 FIXME("Swapchain shader resource views not supported.\n");
1107 context = context_acquire(resource->device, NULL, 0);
1108 vk_image_view = wined3d_view_vk_create_vk_image_view(wined3d_context_vk(context),
1109 desc, texture_vk, wined3d_format_vk(format), format->color_fixup, false);
1110 context_release(context);
1112 if (!vk_image_view)
1113 return;
1115 TRACE("Created image view 0x%s.\n", wine_dbgstr_longlong(vk_image_view));
1117 srv_vk->view_vk.u.vk_image_info.imageView = vk_image_view;
1118 srv_vk->view_vk.u.vk_image_info.sampler = VK_NULL_HANDLE;
1119 srv_vk->view_vk.u.vk_image_info.imageLayout = texture_vk->layout;
1122 HRESULT wined3d_shader_resource_view_vk_init(struct wined3d_shader_resource_view_vk *view_vk,
1123 const struct wined3d_view_desc *desc, struct wined3d_resource *resource,
1124 void *parent, const struct wined3d_parent_ops *parent_ops)
1126 HRESULT hr;
1128 TRACE("view_vk %p, desc %s, resource %p, parent %p, parent_ops %p.\n",
1129 view_vk, wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops);
1131 if (FAILED(hr = wined3d_shader_resource_view_init(&view_vk->v, desc, resource, parent, parent_ops)))
1132 return hr;
1134 list_init(&view_vk->view_vk.bo_user.entry);
1135 wined3d_cs_init_object(resource->device->cs, wined3d_shader_resource_view_vk_cs_init, view_vk);
1137 return hr;
1140 HRESULT CDECL wined3d_shader_resource_view_create(const struct wined3d_view_desc *desc,
1141 struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops,
1142 struct wined3d_shader_resource_view **view)
1144 const struct wined3d_adapter_ops *adapter_ops;
1146 TRACE("desc %s, resource %p, parent %p, parent_ops %p, view %p.\n",
1147 wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops, view);
1149 adapter_ops = resource->device->adapter->adapter_ops;
1150 return adapter_ops->adapter_create_shader_resource_view(desc, resource, parent, parent_ops, view);
1153 void wined3d_shader_resource_view_gl_bind(struct wined3d_shader_resource_view_gl *view_gl,
1154 unsigned int unit, struct wined3d_sampler_gl *sampler_gl, struct wined3d_context_gl *context_gl)
1156 const struct wined3d_gl_info *gl_info = context_gl->gl_info;
1157 struct wined3d_texture_gl *texture_gl;
1159 wined3d_context_gl_active_texture(context_gl, gl_info, unit);
1161 if (view_gl->gl_view.name)
1163 wined3d_context_gl_bind_texture(context_gl, view_gl->gl_view.target, view_gl->gl_view.name);
1164 wined3d_sampler_gl_bind(sampler_gl, unit, NULL, context_gl);
1165 return;
1168 if (view_gl->v.resource->type == WINED3D_RTYPE_BUFFER)
1170 FIXME("Buffer shader resources not supported.\n");
1171 return;
1174 texture_gl = wined3d_texture_gl(wined3d_texture_from_resource(view_gl->v.resource));
1175 wined3d_texture_gl_bind(texture_gl, context_gl, FALSE);
1176 wined3d_sampler_gl_bind(sampler_gl, unit, texture_gl, context_gl);
1179 /* Context activation is done by the caller. */
1180 static void shader_resource_view_gl_bind_and_dirtify(struct wined3d_shader_resource_view_gl *view_gl,
1181 struct wined3d_context_gl *context_gl)
1183 if (context_gl->active_texture < ARRAY_SIZE(context_gl->rev_tex_unit_map))
1185 unsigned int active_sampler = context_gl->rev_tex_unit_map[context_gl->active_texture];
1186 if (active_sampler != WINED3D_UNMAPPED_STAGE)
1187 context_invalidate_state(&context_gl->c, STATE_SAMPLER(active_sampler));
1189 /* FIXME: Ideally we'd only do this when touching a binding that's used by
1190 * a shader. */
1191 context_invalidate_compute_state(&context_gl->c, STATE_COMPUTE_SHADER_RESOURCE_BINDING);
1192 context_invalidate_state(&context_gl->c, STATE_GRAPHICS_SHADER_RESOURCE_BINDING);
1194 wined3d_context_gl_bind_texture(context_gl, view_gl->gl_view.target, view_gl->gl_view.name);
1197 void wined3d_shader_resource_view_gl_generate_mipmap(struct wined3d_shader_resource_view_gl *view_gl,
1198 struct wined3d_context_gl *context_gl)
1200 unsigned int i, j, layer_count, level_count, base_level, base_layer;
1201 const struct wined3d_gl_info *gl_info = context_gl->gl_info;
1202 struct wined3d_texture_gl *texture_gl;
1203 struct gl_texture *gl_tex;
1204 DWORD location;
1205 BOOL srgb;
1207 TRACE("view_gl %p.\n", view_gl);
1209 layer_count = view_gl->v.desc.u.texture.layer_count;
1210 level_count = view_gl->v.desc.u.texture.level_count;
1211 base_level = view_gl->v.desc.u.texture.level_idx;
1212 base_layer = view_gl->v.desc.u.texture.layer_idx;
1214 texture_gl = wined3d_texture_gl(texture_from_resource(view_gl->v.resource));
1215 srgb = !!(texture_gl->t.flags & WINED3D_TEXTURE_IS_SRGB);
1216 location = srgb ? WINED3D_LOCATION_TEXTURE_SRGB : WINED3D_LOCATION_TEXTURE_RGB;
1217 for (i = 0; i < layer_count; ++i)
1219 if (!wined3d_texture_load_location(&texture_gl->t,
1220 (base_layer + i) * level_count + base_level, &context_gl->c, location))
1221 ERR("Failed to load source layer %u.\n", base_layer + i);
1224 if (view_gl->gl_view.name)
1226 shader_resource_view_gl_bind_and_dirtify(view_gl, context_gl);
1228 else
1230 wined3d_texture_gl_bind_and_dirtify(texture_gl, context_gl, srgb);
1231 gl_info->gl_ops.gl.p_glTexParameteri(texture_gl->target, GL_TEXTURE_BASE_LEVEL, base_level);
1232 gl_info->gl_ops.gl.p_glTexParameteri(texture_gl->target, GL_TEXTURE_MAX_LEVEL, base_level + level_count - 1);
1235 if (gl_info->supported[ARB_SAMPLER_OBJECTS])
1236 GL_EXTCALL(glBindSampler(context_gl->active_texture, 0));
1237 gl_tex = wined3d_texture_gl_get_gl_texture(texture_gl, srgb);
1238 if (context_gl->c.d3d_info->wined3d_creation_flags & WINED3D_SRGB_READ_WRITE_CONTROL)
1240 gl_info->gl_ops.gl.p_glTexParameteri(texture_gl->target,
1241 GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT);
1242 gl_tex->sampler_desc.srgb_decode = FALSE;
1245 gl_info->fbo_ops.glGenerateMipmap(texture_gl->target);
1246 checkGLcall("glGenerateMipMap()");
1248 for (i = 0; i < layer_count; ++i)
1250 for (j = 1; j < level_count; ++j)
1252 wined3d_texture_validate_location(&texture_gl->t,
1253 (base_layer + i) * level_count + base_level + j, location);
1254 wined3d_texture_invalidate_location(&texture_gl->t,
1255 (base_layer + i) * level_count + base_level + j, ~location);
1259 if (!view_gl->gl_view.name)
1261 gl_tex->base_level = base_level;
1262 gl_info->gl_ops.gl.p_glTexParameteri(texture_gl->target,
1263 GL_TEXTURE_MAX_LEVEL, texture_gl->t.level_count - 1);
1267 void wined3d_shader_resource_view_vk_generate_mipmap(struct wined3d_shader_resource_view_vk *srv_vk,
1268 struct wined3d_context_vk *context_vk)
1270 unsigned int i, j, layer_count, level_count, base_level, base_layer;
1271 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1272 VkImageSubresourceRange vk_src_range, vk_dst_range;
1273 struct wined3d_texture_vk *texture_vk;
1274 VkCommandBuffer vk_command_buffer;
1275 VkImageBlit region;
1277 TRACE("srv_vk %p.\n", srv_vk);
1279 layer_count = srv_vk->v.desc.u.texture.layer_count;
1280 level_count = srv_vk->v.desc.u.texture.level_count;
1281 base_level = srv_vk->v.desc.u.texture.level_idx;
1282 base_layer = srv_vk->v.desc.u.texture.layer_idx;
1284 texture_vk = wined3d_texture_vk(texture_from_resource(srv_vk->v.resource));
1285 for (i = 0; i < layer_count; ++i)
1287 if (!wined3d_texture_load_location(&texture_vk->t,
1288 (base_layer + i) * level_count + base_level, &context_vk->c, WINED3D_LOCATION_TEXTURE_RGB))
1289 ERR("Failed to load source layer %u.\n", base_layer + i);
1292 if (context_vk->c.d3d_info->wined3d_creation_flags & WINED3D_SRGB_READ_WRITE_CONTROL)
1293 FIXME("Unhandled sRGB read/write control.\n");
1295 if (wined3d_format_vk(srv_vk->v.format)->vk_format != wined3d_format_vk(texture_vk->t.resource.format)->vk_format)
1296 FIXME("Ignoring view format %s.\n", debug_d3dformat(srv_vk->v.format->id));
1298 if (wined3d_resource_get_sample_count(&texture_vk->t.resource) > 1)
1299 FIXME("Unhandled multi-sampled resource.\n");
1301 if (!(vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk)))
1303 ERR("Failed to get command buffer.\n");
1304 return;
1307 vk_src_range.aspectMask = vk_aspect_mask_from_format(texture_vk->t.resource.format);
1308 vk_src_range.baseMipLevel = base_level;
1309 vk_src_range.levelCount = 1;
1310 vk_src_range.baseArrayLayer = base_layer;
1311 vk_src_range.layerCount = layer_count;
1313 vk_dst_range = vk_src_range;
1314 ++vk_dst_range.baseMipLevel;
1316 wined3d_context_vk_image_barrier(context_vk, vk_command_buffer,
1317 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
1318 vk_access_mask_from_bind_flags(texture_vk->t.resource.bind_flags),
1319 VK_ACCESS_TRANSFER_READ_BIT,
1320 texture_vk->layout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1321 texture_vk->image.vk_image, &vk_src_range);
1322 wined3d_context_vk_image_barrier(context_vk, vk_command_buffer,
1323 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
1324 vk_access_mask_from_bind_flags(texture_vk->t.resource.bind_flags),
1325 VK_ACCESS_TRANSFER_WRITE_BIT,
1326 texture_vk->layout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1327 texture_vk->image.vk_image, &vk_dst_range);
1329 region.srcSubresource.aspectMask = vk_src_range.aspectMask;
1330 region.srcSubresource.mipLevel = vk_src_range.baseMipLevel;
1331 region.srcSubresource.baseArrayLayer = vk_src_range.baseArrayLayer;
1332 region.srcSubresource.layerCount = vk_src_range.layerCount;
1333 region.srcOffsets[0].x = 0;
1334 region.srcOffsets[0].y = 0;
1335 region.srcOffsets[0].z = 0;
1337 region.dstSubresource.aspectMask = vk_dst_range.aspectMask;
1338 region.dstSubresource.mipLevel = vk_dst_range.baseMipLevel;
1339 region.dstSubresource.baseArrayLayer = vk_dst_range.baseArrayLayer;
1340 region.dstSubresource.layerCount = vk_dst_range.layerCount;
1341 region.dstOffsets[0].x = 0;
1342 region.dstOffsets[0].y = 0;
1343 region.dstOffsets[0].z = 0;
1345 for (i = 1; i < level_count; ++i)
1347 region.srcOffsets[1].x = wined3d_texture_get_level_width(&texture_vk->t, vk_src_range.baseMipLevel);
1348 region.srcOffsets[1].y = wined3d_texture_get_level_height(&texture_vk->t, vk_src_range.baseMipLevel);
1349 region.srcOffsets[1].z = wined3d_texture_get_level_depth(&texture_vk->t, vk_src_range.baseMipLevel);
1351 region.dstOffsets[1].x = wined3d_texture_get_level_width(&texture_vk->t, vk_dst_range.baseMipLevel);
1352 region.dstOffsets[1].y = wined3d_texture_get_level_height(&texture_vk->t, vk_dst_range.baseMipLevel);
1353 region.dstOffsets[1].z = wined3d_texture_get_level_depth(&texture_vk->t, vk_dst_range.baseMipLevel);
1355 VK_CALL(vkCmdBlitImage(vk_command_buffer, texture_vk->image.vk_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1356 texture_vk->image.vk_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region, VK_FILTER_LINEAR));
1358 wined3d_context_vk_image_barrier(context_vk, vk_command_buffer,
1359 VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
1360 VK_ACCESS_TRANSFER_READ_BIT,
1361 vk_access_mask_from_bind_flags(texture_vk->t.resource.bind_flags),
1362 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, texture_vk->layout,
1363 texture_vk->image.vk_image, &vk_src_range);
1365 if (i == level_count - 1)
1367 wined3d_context_vk_image_barrier(context_vk, vk_command_buffer,
1368 VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
1369 VK_ACCESS_TRANSFER_WRITE_BIT,
1370 vk_access_mask_from_bind_flags(texture_vk->t.resource.bind_flags),
1371 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, texture_vk->layout,
1372 texture_vk->image.vk_image, &vk_dst_range);
1374 else
1376 region.srcSubresource.mipLevel = ++vk_src_range.baseMipLevel;
1377 region.dstSubresource.mipLevel = ++vk_dst_range.baseMipLevel;
1379 wined3d_context_vk_image_barrier(context_vk, vk_command_buffer,
1380 VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
1381 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
1382 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1383 texture_vk->image.vk_image, &vk_src_range);
1384 wined3d_context_vk_image_barrier(context_vk, vk_command_buffer,
1385 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
1386 vk_access_mask_from_bind_flags(texture_vk->t.resource.bind_flags),
1387 VK_ACCESS_TRANSFER_WRITE_BIT,
1388 texture_vk->layout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1389 texture_vk->image.vk_image, &vk_dst_range);
1393 for (i = 0; i < layer_count; ++i)
1395 for (j = 1; j < level_count; ++j)
1397 wined3d_texture_validate_location(&texture_vk->t,
1398 (base_layer + i) * level_count + base_level + j, WINED3D_LOCATION_TEXTURE_RGB);
1399 wined3d_texture_invalidate_location(&texture_vk->t,
1400 (base_layer + i) * level_count + base_level + j, ~WINED3D_LOCATION_TEXTURE_RGB);
1404 wined3d_context_vk_reference_texture(context_vk, texture_vk);
1407 ULONG CDECL wined3d_unordered_access_view_incref(struct wined3d_unordered_access_view *view)
1409 ULONG refcount = InterlockedIncrement(&view->refcount);
1411 TRACE("%p increasing refcount to %u.\n", view, refcount);
1413 return refcount;
1416 void wined3d_unordered_access_view_cleanup(struct wined3d_unordered_access_view *view)
1418 /* Call wined3d_object_destroyed() before releasing the resource,
1419 * since releasing the resource may end up destroying the parent. */
1420 view->parent_ops->wined3d_object_destroyed(view->parent);
1421 wined3d_resource_decref(view->resource);
1424 ULONG CDECL wined3d_unordered_access_view_decref(struct wined3d_unordered_access_view *view)
1426 ULONG refcount = InterlockedDecrement(&view->refcount);
1428 TRACE("%p decreasing refcount to %u.\n", view, refcount);
1430 if (!refcount)
1431 view->resource->device->adapter->adapter_ops->adapter_destroy_unordered_access_view(view);
1433 return refcount;
1436 void * CDECL wined3d_unordered_access_view_get_parent(const struct wined3d_unordered_access_view *view)
1438 TRACE("view %p.\n", view);
1440 return view->parent;
1443 void wined3d_unordered_access_view_invalidate_location(struct wined3d_unordered_access_view *view,
1444 DWORD location)
1446 wined3d_view_invalidate_location(view->resource, &view->desc, location);
1449 void wined3d_unordered_access_view_gl_clear_uint(struct wined3d_unordered_access_view_gl *view_gl,
1450 const struct wined3d_uvec4 *clear_value, struct wined3d_context_gl *context_gl)
1452 const struct wined3d_gl_info *gl_info = context_gl->gl_info;
1453 const struct wined3d_format_gl *format;
1454 struct wined3d_buffer_gl *buffer_gl;
1455 struct wined3d_resource *resource;
1456 unsigned int offset, size;
1458 resource = view_gl->v.resource;
1459 if (resource->type != WINED3D_RTYPE_BUFFER)
1461 FIXME("Not implemented for %s resources.\n", debug_d3dresourcetype(resource->type));
1462 return;
1465 if (!gl_info->supported[ARB_CLEAR_BUFFER_OBJECT])
1467 FIXME("OpenGL implementation does not support ARB_clear_buffer_object.\n");
1468 return;
1471 format = wined3d_format_gl(view_gl->v.format);
1472 if (format->f.id != WINED3DFMT_R32_UINT && format->f.id != WINED3DFMT_R32_SINT
1473 && format->f.id != WINED3DFMT_R32G32B32A32_UINT
1474 && format->f.id != WINED3DFMT_R32G32B32A32_SINT)
1476 FIXME("Not implemented for format %s.\n", debug_d3dformat(format->f.id));
1477 return;
1480 buffer_gl = wined3d_buffer_gl(buffer_from_resource(resource));
1481 wined3d_buffer_load_location(&buffer_gl->b, &context_gl->c, WINED3D_LOCATION_BUFFER);
1482 wined3d_unordered_access_view_invalidate_location(&view_gl->v, ~WINED3D_LOCATION_BUFFER);
1484 get_buffer_view_range(&buffer_gl->b, &view_gl->v.desc, &format->f, &offset, &size);
1485 wined3d_context_gl_bind_bo(context_gl, buffer_gl->bo.binding, buffer_gl->bo.id);
1486 GL_EXTCALL(glClearBufferSubData(buffer_gl->bo.binding, format->internal,
1487 offset, size, format->format, format->type, clear_value));
1488 wined3d_context_gl_reference_bo(context_gl, &buffer_gl->bo);
1489 checkGLcall("clear unordered access view");
1492 void wined3d_unordered_access_view_set_counter(struct wined3d_unordered_access_view *view,
1493 unsigned int value)
1495 struct wined3d_bo_address dst, src;
1496 struct wined3d_context *context;
1498 if (!view->counter_bo)
1499 return;
1501 context = context_acquire(view->resource->device, NULL, 0);
1503 src.buffer_object = 0;
1504 src.addr = (void *)&value;
1506 dst.buffer_object = view->counter_bo;
1507 dst.addr = NULL;
1509 wined3d_context_copy_bo_address(context, &dst, &src, sizeof(uint32_t));
1511 context_release(context);
1514 void wined3d_unordered_access_view_copy_counter(struct wined3d_unordered_access_view *view,
1515 struct wined3d_buffer *buffer, unsigned int offset, struct wined3d_context *context)
1517 struct wined3d_bo_address dst, src;
1518 DWORD dst_location;
1520 if (!view->counter_bo)
1521 return;
1523 dst_location = wined3d_buffer_get_memory(buffer, &dst, buffer->locations);
1524 dst.addr += offset;
1526 src.buffer_object = view->counter_bo;
1527 src.addr = NULL;
1529 wined3d_context_copy_bo_address(context, &dst, &src, sizeof(uint32_t));
1531 wined3d_buffer_invalidate_location(buffer, ~dst_location);
1534 void wined3d_unordered_access_view_gl_update(struct wined3d_unordered_access_view_gl *uav_gl,
1535 struct wined3d_context_gl *context_gl)
1537 create_buffer_view(&uav_gl->gl_view, &context_gl->c, &uav_gl->v.desc,
1538 buffer_from_resource(uav_gl->v.resource), uav_gl->v.format);
1539 uav_gl->bo_user.valid = true;
1542 static void wined3d_unordered_access_view_gl_cs_init(void *object)
1544 struct wined3d_unordered_access_view_gl *view_gl = object;
1545 struct wined3d_resource *resource = view_gl->v.resource;
1546 struct wined3d_view_desc *desc = &view_gl->v.desc;
1547 const struct wined3d_gl_info *gl_info;
1549 TRACE("view_gl %p.\n", view_gl);
1551 gl_info = &resource->device->adapter->gl_info;
1553 if (resource->type == WINED3D_RTYPE_BUFFER)
1555 struct wined3d_buffer *buffer = buffer_from_resource(resource);
1556 struct wined3d_context_gl *context_gl;
1558 context_gl = wined3d_context_gl(context_acquire(resource->device, NULL, 0));
1559 create_buffer_view(&view_gl->gl_view, &context_gl->c, desc, buffer, view_gl->v.format);
1560 view_gl->bo_user.valid = true;
1561 list_add_head(&wined3d_buffer_gl(buffer)->bo.users, &view_gl->bo_user.entry);
1562 if (desc->flags & (WINED3D_VIEW_BUFFER_COUNTER | WINED3D_VIEW_BUFFER_APPEND))
1564 struct wined3d_bo_gl *bo = &view_gl->counter_bo;
1566 view_gl->v.counter_bo = (uintptr_t)bo;
1567 wined3d_context_gl_create_bo(context_gl, sizeof(uint32_t), GL_ATOMIC_COUNTER_BUFFER,
1568 GL_STATIC_DRAW, true, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_CLIENT_STORAGE_BIT, bo);
1569 wined3d_unordered_access_view_set_counter(&view_gl->v, 0);
1571 context_release(&context_gl->c);
1573 else
1575 struct wined3d_texture_gl *texture_gl = wined3d_texture_gl(texture_from_resource(resource));
1576 unsigned int depth_or_layer_count;
1578 if (resource->type == WINED3D_RTYPE_TEXTURE_3D)
1579 depth_or_layer_count = wined3d_texture_get_level_depth(&texture_gl->t, desc->u.texture.level_idx);
1580 else
1581 depth_or_layer_count = texture_gl->t.layer_count;
1583 if (desc->u.texture.layer_idx || desc->u.texture.layer_count != depth_or_layer_count)
1585 create_texture_view(&view_gl->gl_view, get_texture_view_target(gl_info, desc, texture_gl),
1586 desc, texture_gl, view_gl->v.format);
1591 static HRESULT wined3d_unordered_access_view_init(struct wined3d_unordered_access_view *view,
1592 const struct wined3d_view_desc *desc, struct wined3d_resource *resource,
1593 void *parent, const struct wined3d_parent_ops *parent_ops)
1595 view->refcount = 1;
1596 view->parent = parent;
1597 view->parent_ops = parent_ops;
1599 if (!(resource->bind_flags & WINED3D_BIND_UNORDERED_ACCESS))
1600 return E_INVALIDARG;
1601 if (!(view->format = validate_resource_view(desc, resource, TRUE, FALSE)))
1602 return E_INVALIDARG;
1603 view->desc = *desc;
1605 wined3d_resource_incref(view->resource = resource);
1607 return WINED3D_OK;
1610 HRESULT wined3d_unordered_access_view_gl_init(struct wined3d_unordered_access_view_gl *view_gl,
1611 const struct wined3d_view_desc *desc, struct wined3d_resource *resource,
1612 void *parent, const struct wined3d_parent_ops *parent_ops)
1614 HRESULT hr;
1616 TRACE("view_gl %p, desc %s, resource %p, parent %p, parent_ops %p.\n",
1617 view_gl, wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops);
1619 if (FAILED(hr = wined3d_unordered_access_view_init(&view_gl->v, desc, resource, parent, parent_ops)))
1620 return hr;
1622 list_init(&view_gl->bo_user.entry);
1623 wined3d_cs_init_object(resource->device->cs, wined3d_unordered_access_view_gl_cs_init, view_gl);
1625 return hr;
1628 void wined3d_unordered_access_view_vk_clear_uint(struct wined3d_unordered_access_view_vk *view_vk,
1629 const struct wined3d_uvec4 *clear_value, struct wined3d_context_vk *context_vk)
1631 const struct wined3d_vk_info *vk_info;
1632 const struct wined3d_format *format;
1633 struct wined3d_buffer_vk *buffer_vk;
1634 struct wined3d_resource *resource;
1635 VkCommandBuffer vk_command_buffer;
1636 VkBufferMemoryBarrier vk_barrier;
1637 VkAccessFlags access_mask;
1638 unsigned int offset, size;
1640 TRACE("view_vk %p, clear_value %s, context_vk %p.\n", view_vk, debug_uvec4(clear_value), context_vk);
1642 resource = view_vk->v.resource;
1643 if (resource->type != WINED3D_RTYPE_BUFFER)
1645 FIXME("Not implemented for %s resources.\n", debug_d3dresourcetype(resource->type));
1646 return;
1649 format = view_vk->v.format;
1650 if (format->id != WINED3DFMT_R32_UINT && format->id != WINED3DFMT_R32_SINT)
1652 FIXME("Not implemented for format %s.\n", debug_d3dformat(format->id));
1653 return;
1656 vk_info = context_vk->vk_info;
1657 buffer_vk = wined3d_buffer_vk(buffer_from_resource(resource));
1658 wined3d_buffer_load_location(&buffer_vk->b, &context_vk->c, WINED3D_LOCATION_BUFFER);
1659 wined3d_buffer_invalidate_location(&buffer_vk->b, ~WINED3D_LOCATION_BUFFER);
1661 get_buffer_view_range(&buffer_vk->b, &view_vk->v.desc, format, &offset, &size);
1663 if (!(vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk)))
1664 return;
1665 wined3d_context_vk_end_current_render_pass(context_vk);
1667 access_mask = vk_access_mask_from_bind_flags(buffer_vk->b.resource.bind_flags);
1668 vk_barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
1669 vk_barrier.pNext = NULL;
1670 vk_barrier.srcAccessMask = access_mask;
1671 vk_barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
1672 vk_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1673 vk_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1674 vk_barrier.buffer = buffer_vk->bo.vk_buffer;
1675 vk_barrier.offset = buffer_vk->bo.buffer_offset + offset;
1676 vk_barrier.size = size;
1677 VK_CALL(vkCmdPipelineBarrier(vk_command_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
1678 VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 1, &vk_barrier, 0, NULL));
1680 VK_CALL(vkCmdFillBuffer(vk_command_buffer, buffer_vk->bo.vk_buffer,
1681 buffer_vk->bo.buffer_offset + offset, size, clear_value->x));
1683 vk_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
1684 vk_barrier.dstAccessMask = access_mask;
1685 VK_CALL(vkCmdPipelineBarrier(vk_command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
1686 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, NULL, 1, &vk_barrier, 0, NULL));
1688 wined3d_context_vk_reference_bo(context_vk, &buffer_vk->bo);
1691 void wined3d_unordered_access_view_vk_update(struct wined3d_unordered_access_view_vk *uav_vk,
1692 struct wined3d_context_vk *context_vk)
1694 const struct wined3d_format_vk *view_format_vk = wined3d_format_vk(uav_vk->v.format);
1695 const struct wined3d_view_desc *desc = &uav_vk->v.desc;
1696 struct wined3d_resource *resource = uav_vk->v.resource;
1697 struct wined3d_view_vk *view_vk = &uav_vk->view_vk;
1698 struct wined3d_buffer_vk *buffer_vk;
1699 VkBufferView vk_buffer_view;
1701 buffer_vk = wined3d_buffer_vk(buffer_from_resource(resource));
1702 wined3d_context_vk_destroy_vk_buffer_view(context_vk, view_vk->u.vk_buffer_view, view_vk->command_buffer_id);
1703 if ((vk_buffer_view = wined3d_view_vk_create_vk_buffer_view(context_vk, desc, buffer_vk, view_format_vk)))
1705 view_vk->u.vk_buffer_view = vk_buffer_view;
1706 view_vk->bo_user.valid = true;
1710 static void wined3d_unordered_access_view_vk_cs_init(void *object)
1712 struct wined3d_unordered_access_view_vk *uav_vk = object;
1713 struct wined3d_view_vk *view_vk = &uav_vk->view_vk;
1714 struct wined3d_view_desc *desc = &uav_vk->v.desc;
1715 const struct wined3d_format_vk *format_vk;
1716 const struct wined3d_vk_info *vk_info;
1717 struct wined3d_texture_vk *texture_vk;
1718 struct wined3d_context_vk *context_vk;
1719 struct wined3d_device_vk *device_vk;
1720 struct wined3d_buffer_vk *buffer_vk;
1721 VkBufferViewCreateInfo create_info;
1722 struct wined3d_resource *resource;
1723 VkBufferView vk_buffer_view;
1724 uint32_t default_flags = 0;
1725 VkImageView vk_image_view;
1726 VkResult vr;
1728 TRACE("uav_vk %p.\n", uav_vk);
1730 resource = uav_vk->v.resource;
1731 device_vk = wined3d_device_vk(resource->device);
1732 format_vk = wined3d_format_vk(uav_vk->v.format);
1734 if (resource->type == WINED3D_RTYPE_BUFFER)
1736 buffer_vk = wined3d_buffer_vk(buffer_from_resource(resource));
1738 context_vk = wined3d_context_vk(context_acquire(&device_vk->d, NULL, 0));
1739 vk_info = context_vk->vk_info;
1741 if ((vk_buffer_view = wined3d_view_vk_create_vk_buffer_view(context_vk, desc, buffer_vk, format_vk)))
1743 TRACE("Created buffer view 0x%s.\n", wine_dbgstr_longlong(vk_buffer_view));
1745 uav_vk->view_vk.u.vk_buffer_view = vk_buffer_view;
1746 uav_vk->view_vk.bo_user.valid = true;
1747 list_add_head(&buffer_vk->bo.users, &view_vk->bo_user.entry);
1750 if (desc->flags & (WINED3D_VIEW_BUFFER_COUNTER | WINED3D_VIEW_BUFFER_APPEND))
1752 if (!wined3d_context_vk_create_bo(context_vk, sizeof(uint32_t), VK_BUFFER_USAGE_TRANSFER_SRC_BIT
1753 | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT,
1754 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &uav_vk->counter_bo))
1756 ERR("Failed to create counter bo.\n");
1757 context_release(&context_vk->c);
1759 return;
1762 wined3d_context_vk_end_current_render_pass(context_vk);
1763 VK_CALL(vkCmdFillBuffer(wined3d_context_vk_get_command_buffer(context_vk),
1764 uav_vk->counter_bo.vk_buffer, uav_vk->counter_bo.buffer_offset, sizeof(uint32_t), 0));
1765 wined3d_context_vk_reference_bo(context_vk, &uav_vk->counter_bo);
1767 create_info.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO;
1768 create_info.pNext = NULL;
1769 create_info.flags = 0;
1770 create_info.buffer = uav_vk->counter_bo.vk_buffer;
1771 create_info.format = VK_FORMAT_R32_UINT;
1772 create_info.offset = uav_vk->counter_bo.buffer_offset;
1773 create_info.range = sizeof(uint32_t);
1774 if ((vr = VK_CALL(vkCreateBufferView(device_vk->vk_device,
1775 &create_info, NULL, &uav_vk->vk_counter_view))) < 0)
1777 ERR("Failed to create counter buffer view, vr %s.\n", wined3d_debug_vkresult(vr));
1779 else
1781 TRACE("Created counter buffer view 0x%s.\n", wine_dbgstr_longlong(uav_vk->vk_counter_view));
1783 uav_vk->v.counter_bo = (uintptr_t)&uav_vk->counter_bo;
1787 context_release(&context_vk->c);
1789 return;
1792 texture_vk = wined3d_texture_vk(texture_from_resource(resource));
1794 if (texture_vk->t.layer_count > 1)
1795 default_flags |= WINED3D_VIEW_TEXTURE_ARRAY;
1797 if (resource->format->id == format_vk->f.id && desc->flags == default_flags
1798 && !desc->u.texture.level_idx && desc->u.texture.level_count == texture_vk->t.level_count
1799 && !desc->u.texture.layer_idx && desc->u.texture.layer_count == texture_vk->t.layer_count
1800 && !(resource->bind_flags & WINED3D_BIND_DEPTH_STENCIL) && resource->type != WINED3D_RTYPE_TEXTURE_3D)
1802 TRACE("Creating identity unordered access view.\n");
1803 return;
1806 if (texture_vk->t.swapchain && texture_vk->t.swapchain->state.desc.backbuffer_count > 1)
1807 FIXME("Swapchain unordered access views not supported.\n");
1809 context_vk = wined3d_context_vk(context_acquire(&device_vk->d, NULL, 0));
1810 vk_image_view = wined3d_view_vk_create_vk_image_view(context_vk, desc,
1811 texture_vk, format_vk, format_vk->f.color_fixup, false);
1812 context_release(&context_vk->c);
1814 if (!vk_image_view)
1815 return;
1817 TRACE("Created image view 0x%s.\n", wine_dbgstr_longlong(vk_image_view));
1819 view_vk->u.vk_image_info.imageView = vk_image_view;
1820 view_vk->u.vk_image_info.sampler = VK_NULL_HANDLE;
1821 view_vk->u.vk_image_info.imageLayout = texture_vk->layout;
1824 HRESULT wined3d_unordered_access_view_vk_init(struct wined3d_unordered_access_view_vk *view_vk,
1825 const struct wined3d_view_desc *desc, struct wined3d_resource *resource,
1826 void *parent, const struct wined3d_parent_ops *parent_ops)
1828 HRESULT hr;
1830 TRACE("view_vk %p, desc %s, resource %p, parent %p, parent_ops %p.\n",
1831 view_vk, wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops);
1833 if (FAILED(hr = wined3d_unordered_access_view_init(&view_vk->v, desc, resource, parent, parent_ops)))
1834 return hr;
1836 list_init(&view_vk->view_vk.bo_user.entry);
1837 wined3d_cs_init_object(resource->device->cs, wined3d_unordered_access_view_vk_cs_init, view_vk);
1839 return hr;
1842 HRESULT CDECL wined3d_unordered_access_view_create(const struct wined3d_view_desc *desc,
1843 struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops,
1844 struct wined3d_unordered_access_view **view)
1846 const struct wined3d_adapter_ops *adapter_ops;
1848 TRACE("desc %s, resource %p, parent %p, parent_ops %p, view %p.\n",
1849 wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops, view);
1851 adapter_ops = resource->device->adapter->adapter_ops;
1852 return adapter_ops->adapter_create_unordered_access_view(desc, resource, parent, parent_ops, view);