dbghelp: Remove superfluous casts to self.
[wine.git] / dlls / wined3d / view.c
blob0adb0a115dcf500823195c4aeb6846bb75d431a0
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 (!wined3d_bound_range(desc->u.buffer.start_idx, desc->u.buffer.count, buffer_size))
136 return NULL;
138 else
140 struct wined3d_texture *texture = texture_from_resource(resource);
141 unsigned int depth_or_layer_count;
143 if (resource->format->id != format->id && !wined3d_format_is_typeless(resource->format)
144 && (!allow_srgb_toggle || !wined3d_formats_are_srgb_variants(resource->format->id, format->id)))
146 WARN("Trying to create incompatible view for non typeless format %s.\n",
147 debug_d3dformat(format->id));
148 return NULL;
151 if (mip_slice && resource->type == WINED3D_RTYPE_TEXTURE_3D)
152 depth_or_layer_count = wined3d_texture_get_level_depth(texture, desc->u.texture.level_idx);
153 else
154 depth_or_layer_count = texture->layer_count;
156 if (!desc->u.texture.level_count
157 || (mip_slice && desc->u.texture.level_count != 1)
158 || !wined3d_bound_range(desc->u.texture.level_idx, desc->u.texture.level_count, texture->level_count)
159 || !desc->u.texture.layer_count
160 || !wined3d_bound_range(desc->u.texture.layer_idx, desc->u.texture.layer_count, depth_or_layer_count))
161 return NULL;
164 return format;
167 static void create_texture_view(struct wined3d_gl_view *view, GLenum view_target,
168 const struct wined3d_view_desc *desc, struct wined3d_texture_gl *texture_gl,
169 const struct wined3d_format *view_format)
171 const struct wined3d_format_gl *view_format_gl;
172 unsigned int level_idx, layer_idx, layer_count;
173 const struct wined3d_gl_info *gl_info;
174 struct wined3d_context_gl *context_gl;
175 struct wined3d_context *context;
176 GLuint texture_name;
178 view_format_gl = wined3d_format_gl(view_format);
179 view->target = view_target;
181 context = context_acquire(texture_gl->t.resource.device, NULL, 0);
182 context_gl = wined3d_context_gl(context);
183 gl_info = context_gl->gl_info;
185 if (!gl_info->supported[ARB_TEXTURE_VIEW])
187 context_release(context);
188 FIXME("OpenGL implementation does not support texture views.\n");
189 return;
192 wined3d_texture_gl_prepare_texture(texture_gl, context_gl, FALSE);
193 texture_name = wined3d_texture_gl_get_texture_name(texture_gl, context, FALSE);
195 level_idx = desc->u.texture.level_idx;
196 layer_idx = desc->u.texture.layer_idx;
197 layer_count = desc->u.texture.layer_count;
198 if (view_target == GL_TEXTURE_3D)
200 if (layer_idx || layer_count != wined3d_texture_get_level_depth(&texture_gl->t, level_idx))
201 FIXME("Depth slice (%u-%u) not supported.\n", layer_idx, layer_count);
202 layer_idx = 0;
203 layer_count = 1;
206 gl_info->gl_ops.gl.p_glGenTextures(1, &view->name);
207 GL_EXTCALL(glTextureView(view->name, view->target, texture_name, view_format_gl->internal,
208 level_idx, desc->u.texture.level_count, layer_idx, layer_count));
209 checkGLcall("create texture view");
211 if (is_stencil_view_format(view_format))
213 static const GLint swizzle[] = {GL_ZERO, GL_RED, GL_ZERO, GL_ZERO};
215 if (!gl_info->supported[ARB_STENCIL_TEXTURING])
217 context_release(context);
218 FIXME("OpenGL implementation does not support stencil texturing.\n");
219 return;
222 wined3d_context_gl_bind_texture(context_gl, view->target, view->name);
223 gl_info->gl_ops.gl.p_glTexParameteriv(view->target, GL_TEXTURE_SWIZZLE_RGBA, swizzle);
224 gl_info->gl_ops.gl.p_glTexParameteri(view->target, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_STENCIL_INDEX);
225 checkGLcall("initialize stencil view");
227 context_invalidate_compute_state(context, STATE_COMPUTE_SHADER_RESOURCE_BINDING);
228 context_invalidate_state(context, STATE_GRAPHICS_SHADER_RESOURCE_BINDING);
230 else if (!is_identity_fixup(view_format->color_fixup) && can_use_texture_swizzle(context->d3d_info, view_format))
232 GLint swizzle[4];
234 wined3d_context_gl_bind_texture(context_gl, view->target, view->name);
235 wined3d_gl_texture_swizzle_from_color_fixup(swizzle, view_format->color_fixup);
236 gl_info->gl_ops.gl.p_glTexParameteriv(view->target, GL_TEXTURE_SWIZZLE_RGBA, swizzle);
237 checkGLcall("set format swizzle");
239 context_invalidate_compute_state(context, STATE_COMPUTE_SHADER_RESOURCE_BINDING);
240 context_invalidate_state(context, STATE_GRAPHICS_SHADER_RESOURCE_BINDING);
243 context_release(context);
246 static void create_buffer_texture(struct wined3d_gl_view *view, struct wined3d_context_gl *context_gl,
247 struct wined3d_buffer_gl *buffer_gl, const struct wined3d_format_gl *view_format_gl,
248 unsigned int offset, unsigned int size)
250 const struct wined3d_gl_info *gl_info = context_gl->gl_info;
252 if (!gl_info->supported[ARB_TEXTURE_BUFFER_OBJECT])
254 FIXME("OpenGL implementation does not support buffer textures.\n");
255 return;
258 if ((offset & (gl_info->limits.texture_buffer_offset_alignment - 1)))
260 FIXME("Buffer offset %u is not %u byte aligned.\n",
261 offset, gl_info->limits.texture_buffer_offset_alignment);
262 return;
265 wined3d_buffer_load_location(&buffer_gl->b, &context_gl->c, WINED3D_LOCATION_BUFFER);
267 view->target = GL_TEXTURE_BUFFER;
268 if (!view->name)
269 gl_info->gl_ops.gl.p_glGenTextures(1, &view->name);
271 wined3d_context_gl_bind_texture(context_gl, GL_TEXTURE_BUFFER, view->name);
272 if (gl_info->supported[ARB_TEXTURE_BUFFER_RANGE])
274 GL_EXTCALL(glTexBufferRange(GL_TEXTURE_BUFFER, view_format_gl->internal, buffer_gl->bo.id, offset, size));
276 else
278 if (offset || size != buffer_gl->b.resource.size)
279 FIXME("OpenGL implementation does not support ARB_texture_buffer_range.\n");
280 GL_EXTCALL(glTexBuffer(GL_TEXTURE_BUFFER, view_format_gl->internal, buffer_gl->bo.id));
282 checkGLcall("Create buffer texture");
284 context_invalidate_compute_state(&context_gl->c, STATE_COMPUTE_SHADER_RESOURCE_BINDING);
285 context_invalidate_state(&context_gl->c, STATE_GRAPHICS_SHADER_RESOURCE_BINDING);
288 static void get_buffer_view_range(const struct wined3d_buffer *buffer,
289 const struct wined3d_view_desc *desc, const struct wined3d_format *view_format,
290 unsigned int *offset, unsigned int *size)
292 if (desc->format_id == WINED3DFMT_UNKNOWN)
294 *offset = desc->u.buffer.start_idx * buffer->structure_byte_stride;
295 *size = desc->u.buffer.count * buffer->structure_byte_stride;
297 else
299 *offset = desc->u.buffer.start_idx * view_format->byte_count;
300 *size = desc->u.buffer.count * view_format->byte_count;
304 static void create_buffer_view(struct wined3d_gl_view *view, struct wined3d_context *context,
305 const struct wined3d_view_desc *desc, struct wined3d_buffer *buffer,
306 const struct wined3d_format *view_format)
308 unsigned int offset, size;
310 get_buffer_view_range(buffer, desc, view_format, &offset, &size);
311 create_buffer_texture(view, wined3d_context_gl(context),
312 wined3d_buffer_gl(buffer), wined3d_format_gl(view_format), offset, size);
315 static void wined3d_view_invalidate_location(struct wined3d_resource *resource,
316 const struct wined3d_view_desc *desc, DWORD location)
318 unsigned int i, sub_resource_idx, layer_count;
319 struct wined3d_texture *texture;
321 if (resource->type == WINED3D_RTYPE_BUFFER)
323 wined3d_buffer_invalidate_location(buffer_from_resource(resource), location);
324 return;
327 texture = texture_from_resource(resource);
329 sub_resource_idx = desc->u.texture.layer_idx * texture->level_count + desc->u.texture.level_idx;
330 layer_count = resource->type != WINED3D_RTYPE_TEXTURE_3D ? desc->u.texture.layer_count : 1;
331 for (i = 0; i < layer_count; ++i, sub_resource_idx += texture->level_count)
332 wined3d_texture_invalidate_location(texture, sub_resource_idx, location);
335 ULONG CDECL wined3d_rendertarget_view_incref(struct wined3d_rendertarget_view *view)
337 ULONG refcount = InterlockedIncrement(&view->refcount);
339 TRACE("%p increasing refcount to %u.\n", view, refcount);
341 return refcount;
344 void wined3d_rendertarget_view_cleanup(struct wined3d_rendertarget_view *view)
346 /* Call wined3d_object_destroyed() before releasing the resource,
347 * since releasing the resource may end up destroying the parent. */
348 view->parent_ops->wined3d_object_destroyed(view->parent);
349 wined3d_resource_decref(view->resource);
352 ULONG CDECL wined3d_rendertarget_view_decref(struct wined3d_rendertarget_view *view)
354 ULONG refcount = InterlockedDecrement(&view->refcount);
356 TRACE("%p decreasing refcount to %u.\n", view, refcount);
358 if (!refcount)
359 view->resource->device->adapter->adapter_ops->adapter_destroy_rendertarget_view(view);
361 return refcount;
364 void * CDECL wined3d_rendertarget_view_get_parent(const struct wined3d_rendertarget_view *view)
366 TRACE("view %p.\n", view);
368 return view->parent;
371 void * CDECL wined3d_rendertarget_view_get_sub_resource_parent(const struct wined3d_rendertarget_view *view)
373 struct wined3d_texture *texture;
375 TRACE("view %p.\n", view);
377 if (view->resource->type == WINED3D_RTYPE_BUFFER)
378 return wined3d_buffer_get_parent(buffer_from_resource(view->resource));
380 texture = texture_from_resource(view->resource);
382 return texture->sub_resources[view->sub_resource_idx].parent;
385 void CDECL wined3d_rendertarget_view_set_parent(struct wined3d_rendertarget_view *view, void *parent)
387 TRACE("view %p, parent %p.\n", view, parent);
389 view->parent = parent;
392 struct wined3d_resource * CDECL wined3d_rendertarget_view_get_resource(const struct wined3d_rendertarget_view *view)
394 TRACE("view %p.\n", view);
396 return view->resource;
399 void wined3d_rendertarget_view_get_drawable_size(const struct wined3d_rendertarget_view *view,
400 const struct wined3d_context *context, unsigned int *width, unsigned int *height)
402 const struct wined3d_texture *texture;
404 if (view->resource->type != WINED3D_RTYPE_TEXTURE_2D)
406 *width = view->width;
407 *height = view->height;
408 return;
411 texture = texture_from_resource(view->resource);
412 if (texture->swapchain)
414 /* The drawable size of an onscreen drawable is the surface size.
415 * (Actually: The window size, but the surface is created in window
416 * size.) */
417 *width = texture->resource.width;
418 *height = texture->resource.height;
420 else if (wined3d_settings.offscreen_rendering_mode == ORM_BACKBUFFER)
422 const struct wined3d_swapchain_desc *desc = &context->swapchain->state.desc;
424 /* The drawable size of a backbuffer / aux buffer offscreen target is
425 * the size of the current context's drawable, which is the size of
426 * the back buffer of the swapchain the active context belongs to. */
427 *width = desc->backbuffer_width;
428 *height = desc->backbuffer_height;
430 else
432 unsigned int level_idx = view->sub_resource_idx % texture->level_count;
434 /* The drawable size of an FBO target is the OpenGL texture size,
435 * which is the power of two size. */
436 *width = wined3d_texture_get_level_pow2_width(texture, level_idx);
437 *height = wined3d_texture_get_level_pow2_height(texture, level_idx);
441 void wined3d_rendertarget_view_prepare_location(struct wined3d_rendertarget_view *view,
442 struct wined3d_context *context, DWORD location)
444 struct wined3d_resource *resource = view->resource;
445 unsigned int i, sub_resource_idx, layer_count;
446 struct wined3d_texture *texture;
448 if (resource->type == WINED3D_RTYPE_BUFFER)
450 FIXME("Not implemented for resources %s.\n", debug_d3dresourcetype(resource->type));
451 return;
454 texture = texture_from_resource(resource);
455 sub_resource_idx = view->sub_resource_idx;
456 layer_count = resource->type != WINED3D_RTYPE_TEXTURE_3D ? view->layer_count : 1;
457 for (i = 0; i < layer_count; ++i, sub_resource_idx += texture->level_count)
458 wined3d_texture_prepare_location(texture, sub_resource_idx, context, location);
461 void wined3d_rendertarget_view_load_location(struct wined3d_rendertarget_view *view,
462 struct wined3d_context *context, DWORD location)
464 struct wined3d_resource *resource = view->resource;
465 unsigned int i, sub_resource_idx, layer_count;
466 struct wined3d_texture *texture;
468 if (resource->type == WINED3D_RTYPE_BUFFER)
470 wined3d_buffer_load_location(buffer_from_resource(resource), context, location);
471 return;
474 texture = texture_from_resource(resource);
475 sub_resource_idx = view->sub_resource_idx;
476 layer_count = resource->type != WINED3D_RTYPE_TEXTURE_3D ? view->layer_count : 1;
477 for (i = 0; i < layer_count; ++i, sub_resource_idx += texture->level_count)
478 wined3d_texture_load_location(texture, sub_resource_idx, context, location);
481 void wined3d_rendertarget_view_validate_location(struct wined3d_rendertarget_view *view, DWORD location)
483 struct wined3d_resource *resource = view->resource;
484 unsigned int i, sub_resource_idx, layer_count;
485 struct wined3d_texture *texture;
487 if (resource->type == WINED3D_RTYPE_BUFFER)
489 FIXME("Not implemented for resources %s.\n", debug_d3dresourcetype(resource->type));
490 return;
493 texture = texture_from_resource(resource);
494 sub_resource_idx = view->sub_resource_idx;
495 layer_count = resource->type != WINED3D_RTYPE_TEXTURE_3D ? view->layer_count : 1;
496 for (i = 0; i < layer_count; ++i, sub_resource_idx += texture->level_count)
497 wined3d_texture_validate_location(texture, sub_resource_idx, location);
500 void wined3d_rendertarget_view_invalidate_location(struct wined3d_rendertarget_view *view, DWORD location)
502 wined3d_view_invalidate_location(view->resource, &view->desc, location);
505 static void wined3d_render_target_view_gl_cs_init(void *object)
507 struct wined3d_rendertarget_view_gl *view_gl = object;
508 struct wined3d_resource *resource = view_gl->v.resource;
509 const struct wined3d_view_desc *desc = &view_gl->v.desc;
511 TRACE("view_gl %p.\n", view_gl);
513 if (resource->type == WINED3D_RTYPE_BUFFER)
515 FIXME("Not implemented for resources %s.\n", debug_d3dresourcetype(resource->type));
517 else
519 struct wined3d_texture_gl *texture_gl = wined3d_texture_gl(texture_from_resource(resource));
520 unsigned int depth_or_layer_count;
522 if (resource->type == WINED3D_RTYPE_TEXTURE_3D)
523 depth_or_layer_count = wined3d_texture_get_level_depth(&texture_gl->t, desc->u.texture.level_idx);
524 else
525 depth_or_layer_count = texture_gl->t.layer_count;
527 if (resource->format->id != view_gl->v.format->id
528 || (view_gl->v.layer_count != 1 && view_gl->v.layer_count != depth_or_layer_count))
530 GLenum resource_class, view_class;
532 resource_class = wined3d_format_gl(resource->format)->view_class;
533 view_class = wined3d_format_gl(view_gl->v.format)->view_class;
534 if (resource_class != view_class)
536 FIXME("Render target view not supported, resource format %s, view format %s.\n",
537 debug_d3dformat(resource->format->id), debug_d3dformat(view_gl->v.format->id));
538 return;
540 if (texture_gl->t.swapchain && texture_gl->t.swapchain->state.desc.backbuffer_count > 1)
542 FIXME("Swapchain views not supported.\n");
543 return;
546 create_texture_view(&view_gl->gl_view, texture_gl->target, desc, texture_gl, view_gl->v.format);
551 static HRESULT wined3d_rendertarget_view_init(struct wined3d_rendertarget_view *view,
552 const struct wined3d_view_desc *desc, struct wined3d_resource *resource,
553 void *parent, const struct wined3d_parent_ops *parent_ops)
555 BOOL allow_srgb_toggle = FALSE;
557 view->refcount = 1;
558 view->parent = parent;
559 view->parent_ops = parent_ops;
561 if (resource->type != WINED3D_RTYPE_BUFFER)
563 struct wined3d_texture *texture = texture_from_resource(resource);
565 if (texture->swapchain)
566 allow_srgb_toggle = TRUE;
568 if (!(view->format = validate_resource_view(desc, resource, TRUE, allow_srgb_toggle)))
569 return E_INVALIDARG;
570 view->format_flags = view->format->flags[resource->gl_type];
571 view->desc = *desc;
573 if (resource->type == WINED3D_RTYPE_BUFFER)
575 view->sub_resource_idx = 0;
576 view->layer_count = 1;
577 view->width = desc->u.buffer.count;
578 view->height = 1;
580 else
582 struct wined3d_texture *texture = texture_from_resource(resource);
584 view->sub_resource_idx = desc->u.texture.level_idx;
585 if (resource->type != WINED3D_RTYPE_TEXTURE_3D)
586 view->sub_resource_idx += desc->u.texture.layer_idx * texture->level_count;
587 view->layer_count = desc->u.texture.layer_count;
588 view->width = wined3d_texture_get_level_width(texture, desc->u.texture.level_idx);
589 view->height = wined3d_texture_get_level_height(texture, desc->u.texture.level_idx);
592 wined3d_resource_incref(view->resource = resource);
594 return WINED3D_OK;
597 HRESULT wined3d_rendertarget_view_no3d_init(struct wined3d_rendertarget_view *view_no3d,
598 const struct wined3d_view_desc *desc, struct wined3d_resource *resource,
599 void *parent, const struct wined3d_parent_ops *parent_ops)
601 TRACE("view_no3d %p, desc %s, resource %p, parent %p, parent_ops %p.\n",
602 view_no3d, wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops);
604 return wined3d_rendertarget_view_init(view_no3d, desc, resource, parent, parent_ops);
607 HRESULT wined3d_rendertarget_view_gl_init(struct wined3d_rendertarget_view_gl *view_gl,
608 const struct wined3d_view_desc *desc, struct wined3d_resource *resource,
609 void *parent, const struct wined3d_parent_ops *parent_ops)
611 HRESULT hr;
613 TRACE("view_gl %p, desc %s, resource %p, parent %p, parent_ops %p.\n",
614 view_gl, wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops);
616 if (FAILED(hr = wined3d_rendertarget_view_init(&view_gl->v, desc, resource, parent, parent_ops)))
617 return hr;
619 wined3d_cs_init_object(resource->device->cs, wined3d_render_target_view_gl_cs_init, view_gl);
621 return hr;
624 VkImageViewType vk_image_view_type_from_wined3d(enum wined3d_resource_type type, uint32_t flags)
626 switch (type)
628 case WINED3D_RTYPE_TEXTURE_1D:
629 if (flags & WINED3D_VIEW_TEXTURE_ARRAY)
630 return VK_IMAGE_VIEW_TYPE_1D_ARRAY;
631 else
632 return VK_IMAGE_VIEW_TYPE_1D;
634 case WINED3D_RTYPE_TEXTURE_2D:
635 if (flags & WINED3D_VIEW_TEXTURE_CUBE)
637 if (flags & WINED3D_VIEW_TEXTURE_ARRAY)
638 return VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
639 else
640 return VK_IMAGE_VIEW_TYPE_CUBE;
642 if (flags & WINED3D_VIEW_TEXTURE_ARRAY)
643 return VK_IMAGE_VIEW_TYPE_2D_ARRAY;
644 else
645 return VK_IMAGE_VIEW_TYPE_2D;
647 case WINED3D_RTYPE_TEXTURE_3D:
648 return VK_IMAGE_VIEW_TYPE_3D;
650 default:
651 ERR("Unhandled resource type %s.\n", debug_d3dresourcetype(type));
652 return ~0u;
656 static VkBufferView wined3d_view_vk_create_vk_buffer_view(struct wined3d_context_vk *context_vk,
657 const struct wined3d_view_desc *desc, struct wined3d_buffer_vk *buffer_vk,
658 const struct wined3d_format_vk *view_format_vk)
660 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
661 VkBufferViewCreateInfo create_info;
662 struct wined3d_device_vk *device_vk;
663 VkBufferView vk_buffer_view;
664 unsigned int offset, size;
665 VkResult vr;
667 get_buffer_view_range(&buffer_vk->b, desc, &view_format_vk->f, &offset, &size);
668 wined3d_buffer_prepare_location(&buffer_vk->b, &context_vk->c, WINED3D_LOCATION_BUFFER);
670 create_info.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO;
671 create_info.pNext = NULL;
672 create_info.flags = 0;
673 create_info.buffer = buffer_vk->bo.vk_buffer;
674 create_info.format = view_format_vk->vk_format;
675 create_info.offset = buffer_vk->bo.buffer_offset + offset;
676 create_info.range = size;
678 device_vk = wined3d_device_vk(buffer_vk->b.resource.device);
679 if ((vr = VK_CALL(vkCreateBufferView(device_vk->vk_device, &create_info, NULL, &vk_buffer_view))) < 0)
681 ERR("Failed to create buffer view, vr %s.\n", wined3d_debug_vkresult(vr));
682 return VK_NULL_HANDLE;
685 return vk_buffer_view;
688 static VkImageView wined3d_view_vk_create_vk_image_view(struct wined3d_context_vk *context_vk,
689 const struct wined3d_view_desc *desc, struct wined3d_texture_vk *texture_vk,
690 const struct wined3d_format_vk *view_format_vk, struct color_fixup_desc fixup, bool rtv)
692 const struct wined3d_resource *resource = &texture_vk->t.resource;
693 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
694 const struct wined3d_format_vk *format_vk;
695 struct wined3d_device_vk *device_vk;
696 VkImageViewCreateInfo create_info;
697 VkImageView vk_image_view;
698 VkResult vr;
700 device_vk = wined3d_device_vk(resource->device);
702 if (!wined3d_texture_vk_prepare_texture(texture_vk, context_vk))
704 ERR("Failed to prepare texture.\n");
705 return VK_NULL_HANDLE;
708 /* Depth formats are a little complicated. For example, the typeless
709 * format corresponding to depth/stencil view format WINED3DFMT_D32_FLOAT
710 * is WINED3DFMT_R32_TYPELESS, and the corresponding shader resource view
711 * format would be WINED3DFMT_R32_FLOAT. Vulkan depth/stencil formats are
712 * only compatible with themselves, so it's not possible to create e.g. a
713 * VK_FORMAT_R32_SFLOAT view on a VK_FORMAT_D32_SFLOAT image. In order to
714 * make it work, we create Vulkan images for WINED3DFMT_R32_TYPELESS
715 * resources with either a depth format (VK_FORMAT_D32_SFLOAT) or a colour
716 * format, depending on whether the bind flags include
717 * WINED3D_BIND_DEPTH_STENCIL or not. In order to then create a Vulkan
718 * view on the image, we then replace the view format here with the
719 * underlying resource format. However, that means it's still not possible
720 * to create e.g. a WINED3DFMT_R32_UINT view on a WINED3DFMT_R32_TYPELESS
721 * depth/stencil resource. */
722 if (resource->bind_flags & WINED3D_BIND_DEPTH_STENCIL)
723 format_vk = wined3d_format_vk(resource->format);
724 else
725 format_vk = view_format_vk;
727 create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
728 create_info.pNext = NULL;
729 create_info.flags = 0;
730 create_info.image = texture_vk->image.vk_image;
731 create_info.viewType = vk_image_view_type_from_wined3d(resource->type, desc->flags);
732 if (rtv && create_info.viewType == VK_IMAGE_VIEW_TYPE_3D)
734 if (desc->u.texture.layer_count > 1)
735 create_info.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
736 else
737 create_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
739 create_info.format = format_vk->vk_format;
740 if (is_stencil_view_format(&view_format_vk->f))
742 create_info.components.r = VK_COMPONENT_SWIZZLE_ZERO;
743 create_info.components.g = VK_COMPONENT_SWIZZLE_R;
744 create_info.components.b = VK_COMPONENT_SWIZZLE_ZERO;
745 create_info.components.a = VK_COMPONENT_SWIZZLE_ZERO;
747 else if (is_identity_fixup(fixup) || !can_use_texture_swizzle(context_vk->c.d3d_info, &format_vk->f))
749 create_info.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
750 create_info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
751 create_info.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
752 create_info.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
754 else
756 wined3d_vk_swizzle_from_color_fixup(&create_info.components, fixup);
758 if ((resource->bind_flags & WINED3D_BIND_DEPTH_STENCIL)
759 && (view_format_vk->f.red_size || view_format_vk->f.green_size))
761 create_info.subresourceRange.aspectMask = 0;
762 if (view_format_vk->f.red_size)
763 create_info.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
764 if (view_format_vk->f.green_size)
765 create_info.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
767 else
769 create_info.subresourceRange.aspectMask = vk_aspect_mask_from_format(&format_vk->f);
771 create_info.subresourceRange.baseMipLevel = desc->u.texture.level_idx;
772 create_info.subresourceRange.levelCount = desc->u.texture.level_count;
773 if (create_info.viewType == VK_IMAGE_VIEW_TYPE_3D)
775 if (desc->u.texture.layer_idx || (desc->u.texture.layer_count != texture_vk->t.resource.depth
776 && desc->u.texture.layer_count != ~0u))
777 WARN("Partial 3D texture views are not supported.\n");
778 create_info.subresourceRange.baseArrayLayer = 0;
779 create_info.subresourceRange.layerCount = 1;
781 else
783 create_info.subresourceRange.baseArrayLayer = desc->u.texture.layer_idx;
784 create_info.subresourceRange.layerCount = desc->u.texture.layer_count;
786 if ((vr = VK_CALL(vkCreateImageView(device_vk->vk_device, &create_info, NULL, &vk_image_view))) < 0)
788 ERR("Failed to create Vulkan image view, vr %s.\n", wined3d_debug_vkresult(vr));
789 return VK_NULL_HANDLE;
792 return vk_image_view;
795 static void wined3d_render_target_view_vk_cs_init(void *object)
797 struct wined3d_rendertarget_view_vk *view_vk = object;
798 struct wined3d_view_desc *desc = &view_vk->v.desc;
799 const struct wined3d_format_vk *format_vk;
800 struct wined3d_texture_vk *texture_vk;
801 struct wined3d_resource *resource;
802 struct wined3d_context *context;
803 uint32_t default_flags = 0;
805 TRACE("view_vk %p.\n", view_vk);
807 resource = view_vk->v.resource;
808 if (resource->type == WINED3D_RTYPE_BUFFER)
810 FIXME("Buffer views not implemented.\n");
811 return;
814 texture_vk = wined3d_texture_vk(texture_from_resource(resource));
815 format_vk = wined3d_format_vk(view_vk->v.format);
817 if (texture_vk->t.layer_count > 1)
818 default_flags |= WINED3D_VIEW_TEXTURE_ARRAY;
820 if (resource->format->id == format_vk->f.id && desc->flags == default_flags
821 && !desc->u.texture.level_idx && desc->u.texture.level_count == texture_vk->t.level_count
822 && !desc->u.texture.layer_idx && desc->u.texture.layer_count == texture_vk->t.layer_count
823 && !is_stencil_view_format(&format_vk->f) && resource->type != WINED3D_RTYPE_TEXTURE_3D
824 && is_identity_fixup(format_vk->f.color_fixup))
826 TRACE("Creating identity render target view.\n");
827 return;
830 if (texture_vk->t.swapchain && texture_vk->t.swapchain->state.desc.backbuffer_count > 1)
832 FIXME("Swapchain views not supported.\n");
833 return;
836 context = context_acquire(resource->device, NULL, 0);
837 view_vk->vk_image_view = wined3d_view_vk_create_vk_image_view(wined3d_context_vk(context),
838 desc, texture_vk, format_vk, COLOR_FIXUP_IDENTITY, true);
839 context_release(context);
841 if (!view_vk->vk_image_view)
842 return;
844 TRACE("Created image view 0x%s.\n", wine_dbgstr_longlong(view_vk->vk_image_view));
847 HRESULT wined3d_rendertarget_view_vk_init(struct wined3d_rendertarget_view_vk *view_vk,
848 const struct wined3d_view_desc *desc, struct wined3d_resource *resource,
849 void *parent, const struct wined3d_parent_ops *parent_ops)
851 HRESULT hr;
853 TRACE("view_vk %p, desc %s, resource %p, parent %p, parent_ops %p.\n",
854 view_vk, wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops);
856 if (FAILED(hr = wined3d_rendertarget_view_init(&view_vk->v, desc, resource, parent, parent_ops)))
857 return hr;
859 wined3d_cs_init_object(resource->device->cs, wined3d_render_target_view_vk_cs_init, view_vk);
861 return hr;
864 HRESULT CDECL wined3d_rendertarget_view_create(const struct wined3d_view_desc *desc,
865 struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops,
866 struct wined3d_rendertarget_view **view)
868 const struct wined3d_adapter_ops *adapter_ops;
870 TRACE("desc %s, resource %p, parent %p, parent_ops %p, view %p.\n",
871 wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops, view);
873 adapter_ops = resource->device->adapter->adapter_ops;
874 return adapter_ops->adapter_create_rendertarget_view(desc, resource, parent, parent_ops, view);
877 HRESULT CDECL wined3d_rendertarget_view_create_from_sub_resource(struct wined3d_texture *texture,
878 unsigned int sub_resource_idx, void *parent, const struct wined3d_parent_ops *parent_ops,
879 struct wined3d_rendertarget_view **view)
881 struct wined3d_view_desc desc;
883 TRACE("texture %p, sub_resource_idx %u, parent %p, parent_ops %p, view %p.\n",
884 texture, sub_resource_idx, parent, parent_ops, view);
886 desc.format_id = texture->resource.format->id;
887 desc.flags = 0;
888 desc.u.texture.level_idx = sub_resource_idx % texture->level_count;
889 desc.u.texture.level_count = 1;
890 desc.u.texture.layer_idx = sub_resource_idx / texture->level_count;
891 desc.u.texture.layer_count = 1;
893 return wined3d_rendertarget_view_create(&desc, &texture->resource, parent, parent_ops, view);
896 ULONG CDECL wined3d_shader_resource_view_incref(struct wined3d_shader_resource_view *view)
898 ULONG refcount = InterlockedIncrement(&view->refcount);
900 TRACE("%p increasing refcount to %u.\n", view, refcount);
902 return refcount;
905 void wined3d_shader_resource_view_cleanup(struct wined3d_shader_resource_view *view)
907 /* Call wined3d_object_destroyed() before releasing the resource,
908 * since releasing the resource may end up destroying the parent. */
909 view->parent_ops->wined3d_object_destroyed(view->parent);
910 wined3d_resource_decref(view->resource);
913 ULONG CDECL wined3d_shader_resource_view_decref(struct wined3d_shader_resource_view *view)
915 ULONG refcount = InterlockedDecrement(&view->refcount);
917 TRACE("%p decreasing refcount to %u.\n", view, refcount);
919 if (!refcount)
920 view->resource->device->adapter->adapter_ops->adapter_destroy_shader_resource_view(view);
922 return refcount;
925 void * CDECL wined3d_shader_resource_view_get_parent(const struct wined3d_shader_resource_view *view)
927 TRACE("view %p.\n", view);
929 return view->parent;
932 void wined3d_shader_resource_view_gl_update(struct wined3d_shader_resource_view_gl *srv_gl,
933 struct wined3d_context_gl *context_gl)
935 create_buffer_view(&srv_gl->gl_view, &context_gl->c, &srv_gl->v.desc,
936 buffer_from_resource(srv_gl->v.resource), srv_gl->v.format);
937 srv_gl->bo_user.valid = true;
940 static void wined3d_shader_resource_view_gl_cs_init(void *object)
942 struct wined3d_shader_resource_view_gl *view_gl = object;
943 struct wined3d_resource *resource = view_gl->v.resource;
944 const struct wined3d_format *view_format;
945 const struct wined3d_gl_info *gl_info;
946 const struct wined3d_view_desc *desc;
947 GLenum view_target;
949 TRACE("view_gl %p.\n", view_gl);
951 view_format = view_gl->v.format;
952 gl_info = &resource->device->adapter->gl_info;
953 desc = &view_gl->v.desc;
955 if (resource->type == WINED3D_RTYPE_BUFFER)
957 struct wined3d_buffer *buffer = buffer_from_resource(resource);
958 struct wined3d_context *context;
960 context = context_acquire(resource->device, NULL, 0);
961 create_buffer_view(&view_gl->gl_view, context, desc, buffer, view_format);
962 view_gl->bo_user.valid = true;
963 list_add_head(&wined3d_buffer_gl(buffer)->bo.users, &view_gl->bo_user.entry);
964 context_release(context);
966 else
968 struct wined3d_texture_gl *texture_gl = wined3d_texture_gl(texture_from_resource(resource));
969 GLenum resource_class, view_class;
971 resource_class = wined3d_format_gl(resource->format)->view_class;
972 view_class = wined3d_format_gl(view_format)->view_class;
973 view_target = get_texture_view_target(gl_info, desc, texture_gl);
975 if (resource->format->id == view_format->id && texture_gl->target == view_target
976 && !desc->u.texture.level_idx && desc->u.texture.level_count == texture_gl->t.level_count
977 && !desc->u.texture.layer_idx && desc->u.texture.layer_count == texture_gl->t.layer_count
978 && !is_stencil_view_format(view_format))
980 TRACE("Creating identity shader resource view.\n");
982 else if (texture_gl->t.swapchain && texture_gl->t.swapchain->state.desc.backbuffer_count > 1)
984 FIXME("Swapchain shader resource views not supported.\n");
986 else if (resource->format->typeless_id == view_format->typeless_id
987 && resource_class == view_class)
989 create_texture_view(&view_gl->gl_view, view_target, desc, texture_gl, view_format);
991 else if (wined3d_format_is_depth_view(resource->format->id, view_format->id))
993 create_texture_view(&view_gl->gl_view, view_target, desc, texture_gl, resource->format);
995 else
997 FIXME("Shader resource view not supported, resource format %s, view format %s.\n",
998 debug_d3dformat(resource->format->id), debug_d3dformat(view_format->id));
1003 static HRESULT wined3d_shader_resource_view_init(struct wined3d_shader_resource_view *view,
1004 const struct wined3d_view_desc *desc, struct wined3d_resource *resource,
1005 void *parent, const struct wined3d_parent_ops *parent_ops)
1007 view->refcount = 1;
1008 view->parent = parent;
1009 view->parent_ops = parent_ops;
1011 if (!(resource->bind_flags & WINED3D_BIND_SHADER_RESOURCE))
1012 return E_INVALIDARG;
1013 if (!(view->format = validate_resource_view(desc, resource, FALSE, FALSE)))
1014 return E_INVALIDARG;
1015 view->desc = *desc;
1017 wined3d_resource_incref(view->resource = resource);
1019 return WINED3D_OK;
1022 HRESULT wined3d_shader_resource_view_gl_init(struct wined3d_shader_resource_view_gl *view_gl,
1023 const struct wined3d_view_desc *desc, struct wined3d_resource *resource,
1024 void *parent, const struct wined3d_parent_ops *parent_ops)
1026 HRESULT hr;
1028 TRACE("view_gl %p, desc %s, resource %p, parent %p, parent_ops %p.\n",
1029 view_gl, wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops);
1031 if (FAILED(hr = wined3d_shader_resource_view_init(&view_gl->v, desc, resource, parent, parent_ops)))
1032 return hr;
1034 list_init(&view_gl->bo_user.entry);
1035 wined3d_cs_init_object(resource->device->cs, wined3d_shader_resource_view_gl_cs_init, view_gl);
1037 return hr;
1040 void wined3d_shader_resource_view_vk_update(struct wined3d_shader_resource_view_vk *srv_vk,
1041 struct wined3d_context_vk *context_vk)
1043 const struct wined3d_format_vk *view_format_vk = wined3d_format_vk(srv_vk->v.format);
1044 const struct wined3d_view_desc *desc = &srv_vk->v.desc;
1045 struct wined3d_resource *resource = srv_vk->v.resource;
1046 struct wined3d_view_vk *view_vk = &srv_vk->view_vk;
1047 struct wined3d_buffer_vk *buffer_vk;
1048 VkBufferView vk_buffer_view;
1050 buffer_vk = wined3d_buffer_vk(buffer_from_resource(resource));
1051 wined3d_context_vk_destroy_vk_buffer_view(context_vk, view_vk->u.vk_buffer_view, view_vk->command_buffer_id);
1052 if ((vk_buffer_view = wined3d_view_vk_create_vk_buffer_view(context_vk, desc, buffer_vk, view_format_vk)))
1054 view_vk->u.vk_buffer_view = vk_buffer_view;
1055 view_vk->bo_user.valid = true;
1059 static void wined3d_shader_resource_view_vk_cs_init(void *object)
1061 struct wined3d_shader_resource_view_vk *srv_vk = object;
1062 struct wined3d_view_desc *desc = &srv_vk->v.desc;
1063 struct wined3d_texture_vk *texture_vk;
1064 const struct wined3d_format *format;
1065 struct wined3d_buffer_vk *buffer_vk;
1066 struct wined3d_resource *resource;
1067 struct wined3d_context *context;
1068 VkBufferView vk_buffer_view;
1069 uint32_t default_flags = 0;
1070 VkImageView vk_image_view;
1072 TRACE("srv_vk %p.\n", srv_vk);
1074 resource = srv_vk->v.resource;
1075 format = srv_vk->v.format;
1077 if (resource->type == WINED3D_RTYPE_BUFFER)
1079 buffer_vk = wined3d_buffer_vk(buffer_from_resource(resource));
1081 context = context_acquire(resource->device, NULL, 0);
1082 vk_buffer_view = wined3d_view_vk_create_vk_buffer_view(wined3d_context_vk(context),
1083 desc, buffer_vk, wined3d_format_vk(format));
1084 context_release(context);
1086 if (!vk_buffer_view)
1087 return;
1089 TRACE("Created buffer view 0x%s.\n", wine_dbgstr_longlong(vk_buffer_view));
1091 srv_vk->view_vk.u.vk_buffer_view = vk_buffer_view;
1092 srv_vk->view_vk.bo_user.valid = true;
1093 list_add_head(&buffer_vk->bo.users, &srv_vk->view_vk.bo_user.entry);
1095 return;
1098 texture_vk = wined3d_texture_vk(texture_from_resource(resource));
1100 if (texture_vk->t.layer_count > 1)
1101 default_flags |= WINED3D_VIEW_TEXTURE_ARRAY;
1103 if (resource->format->id == format->id && desc->flags == default_flags
1104 && !desc->u.texture.level_idx && desc->u.texture.level_count == texture_vk->t.level_count
1105 && !desc->u.texture.layer_idx && desc->u.texture.layer_count == texture_vk->t.layer_count
1106 && !(resource->bind_flags & WINED3D_BIND_DEPTH_STENCIL))
1108 TRACE("Creating identity shader resource view.\n");
1109 return;
1112 if (texture_vk->t.swapchain && texture_vk->t.swapchain->state.desc.backbuffer_count > 1)
1113 FIXME("Swapchain shader resource views not supported.\n");
1115 context = context_acquire(resource->device, NULL, 0);
1116 vk_image_view = wined3d_view_vk_create_vk_image_view(wined3d_context_vk(context),
1117 desc, texture_vk, wined3d_format_vk(format), format->color_fixup, false);
1118 context_release(context);
1120 if (!vk_image_view)
1121 return;
1123 TRACE("Created image view 0x%s.\n", wine_dbgstr_longlong(vk_image_view));
1125 srv_vk->view_vk.u.vk_image_info.imageView = vk_image_view;
1126 srv_vk->view_vk.u.vk_image_info.sampler = VK_NULL_HANDLE;
1127 srv_vk->view_vk.u.vk_image_info.imageLayout = texture_vk->layout;
1130 HRESULT wined3d_shader_resource_view_vk_init(struct wined3d_shader_resource_view_vk *view_vk,
1131 const struct wined3d_view_desc *desc, struct wined3d_resource *resource,
1132 void *parent, const struct wined3d_parent_ops *parent_ops)
1134 HRESULT hr;
1136 TRACE("view_vk %p, desc %s, resource %p, parent %p, parent_ops %p.\n",
1137 view_vk, wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops);
1139 if (FAILED(hr = wined3d_shader_resource_view_init(&view_vk->v, desc, resource, parent, parent_ops)))
1140 return hr;
1142 list_init(&view_vk->view_vk.bo_user.entry);
1143 wined3d_cs_init_object(resource->device->cs, wined3d_shader_resource_view_vk_cs_init, view_vk);
1145 return hr;
1148 HRESULT CDECL wined3d_shader_resource_view_create(const struct wined3d_view_desc *desc,
1149 struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops,
1150 struct wined3d_shader_resource_view **view)
1152 const struct wined3d_adapter_ops *adapter_ops;
1154 TRACE("desc %s, resource %p, parent %p, parent_ops %p, view %p.\n",
1155 wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops, view);
1157 adapter_ops = resource->device->adapter->adapter_ops;
1158 return adapter_ops->adapter_create_shader_resource_view(desc, resource, parent, parent_ops, view);
1161 void wined3d_shader_resource_view_gl_bind(struct wined3d_shader_resource_view_gl *view_gl,
1162 unsigned int unit, struct wined3d_sampler_gl *sampler_gl, struct wined3d_context_gl *context_gl)
1164 const struct wined3d_gl_info *gl_info = context_gl->gl_info;
1165 struct wined3d_texture_gl *texture_gl;
1167 wined3d_context_gl_active_texture(context_gl, gl_info, unit);
1169 if (view_gl->gl_view.name)
1171 wined3d_context_gl_bind_texture(context_gl, view_gl->gl_view.target, view_gl->gl_view.name);
1172 wined3d_sampler_gl_bind(sampler_gl, unit, NULL, context_gl);
1173 return;
1176 if (view_gl->v.resource->type == WINED3D_RTYPE_BUFFER)
1178 FIXME("Buffer shader resources not supported.\n");
1179 return;
1182 texture_gl = wined3d_texture_gl(wined3d_texture_from_resource(view_gl->v.resource));
1183 wined3d_texture_gl_bind(texture_gl, context_gl, FALSE);
1184 wined3d_sampler_gl_bind(sampler_gl, unit, texture_gl, context_gl);
1187 /* Context activation is done by the caller. */
1188 static void shader_resource_view_gl_bind_and_dirtify(struct wined3d_shader_resource_view_gl *view_gl,
1189 struct wined3d_context_gl *context_gl)
1191 if (context_gl->active_texture < ARRAY_SIZE(context_gl->rev_tex_unit_map))
1193 unsigned int active_sampler = context_gl->rev_tex_unit_map[context_gl->active_texture];
1194 if (active_sampler != WINED3D_UNMAPPED_STAGE)
1195 context_invalidate_state(&context_gl->c, STATE_SAMPLER(active_sampler));
1197 /* FIXME: Ideally we'd only do this when touching a binding that's used by
1198 * a shader. */
1199 context_invalidate_compute_state(&context_gl->c, STATE_COMPUTE_SHADER_RESOURCE_BINDING);
1200 context_invalidate_state(&context_gl->c, STATE_GRAPHICS_SHADER_RESOURCE_BINDING);
1202 wined3d_context_gl_bind_texture(context_gl, view_gl->gl_view.target, view_gl->gl_view.name);
1205 void wined3d_shader_resource_view_gl_generate_mipmap(struct wined3d_shader_resource_view_gl *view_gl,
1206 struct wined3d_context_gl *context_gl)
1208 unsigned int i, j, layer_count, level_count, base_level, base_layer, sub_resource_idx;
1209 const struct wined3d_gl_info *gl_info = context_gl->gl_info;
1210 struct wined3d_texture_gl *texture_gl;
1211 struct gl_texture *gl_tex;
1212 DWORD location;
1213 BOOL srgb;
1215 TRACE("view_gl %p.\n", view_gl);
1217 layer_count = view_gl->v.desc.u.texture.layer_count;
1218 level_count = view_gl->v.desc.u.texture.level_count;
1219 base_level = view_gl->v.desc.u.texture.level_idx;
1220 base_layer = view_gl->v.desc.u.texture.layer_idx;
1222 texture_gl = wined3d_texture_gl(texture_from_resource(view_gl->v.resource));
1223 srgb = !!(texture_gl->t.flags & WINED3D_TEXTURE_IS_SRGB);
1224 location = srgb ? WINED3D_LOCATION_TEXTURE_SRGB : WINED3D_LOCATION_TEXTURE_RGB;
1225 for (i = 0; i < layer_count; ++i)
1227 sub_resource_idx = (base_layer + i) * texture_gl->t.level_count + base_level;
1228 if (!wined3d_texture_load_location(&texture_gl->t, sub_resource_idx, &context_gl->c, location))
1229 ERR("Failed to load source layer %u.\n", base_layer + i);
1232 if (view_gl->gl_view.name)
1234 shader_resource_view_gl_bind_and_dirtify(view_gl, context_gl);
1236 else
1238 wined3d_texture_gl_bind_and_dirtify(texture_gl, context_gl, srgb);
1239 gl_info->gl_ops.gl.p_glTexParameteri(texture_gl->target, GL_TEXTURE_BASE_LEVEL, base_level);
1240 gl_info->gl_ops.gl.p_glTexParameteri(texture_gl->target, GL_TEXTURE_MAX_LEVEL, base_level + level_count - 1);
1243 if (gl_info->supported[ARB_SAMPLER_OBJECTS])
1244 GL_EXTCALL(glBindSampler(context_gl->active_texture, 0));
1245 gl_tex = wined3d_texture_gl_get_gl_texture(texture_gl, srgb);
1246 if (context_gl->c.d3d_info->wined3d_creation_flags & WINED3D_SRGB_READ_WRITE_CONTROL)
1248 gl_info->gl_ops.gl.p_glTexParameteri(texture_gl->target,
1249 GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT);
1250 gl_tex->sampler_desc.srgb_decode = FALSE;
1253 gl_info->fbo_ops.glGenerateMipmap(texture_gl->target);
1254 checkGLcall("glGenerateMipMap()");
1256 for (i = 0; i < layer_count; ++i)
1258 for (j = 1; j < level_count; ++j)
1260 sub_resource_idx = (base_layer + i) * texture_gl->t.level_count + base_level + j;
1261 wined3d_texture_validate_location(&texture_gl->t, sub_resource_idx, location);
1262 wined3d_texture_invalidate_location(&texture_gl->t, sub_resource_idx, ~location);
1266 if (!view_gl->gl_view.name)
1268 gl_tex->base_level = base_level;
1269 gl_info->gl_ops.gl.p_glTexParameteri(texture_gl->target,
1270 GL_TEXTURE_MAX_LEVEL, texture_gl->t.level_count - 1);
1274 void wined3d_shader_resource_view_vk_generate_mipmap(struct wined3d_shader_resource_view_vk *srv_vk,
1275 struct wined3d_context_vk *context_vk)
1277 unsigned int i, j, layer_count, level_count, base_level, base_layer, sub_resource_idx;
1278 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1279 VkImageSubresourceRange vk_src_range, vk_dst_range;
1280 struct wined3d_texture_vk *texture_vk;
1281 VkCommandBuffer vk_command_buffer;
1282 VkImageBlit region;
1284 TRACE("srv_vk %p.\n", srv_vk);
1286 layer_count = srv_vk->v.desc.u.texture.layer_count;
1287 level_count = srv_vk->v.desc.u.texture.level_count;
1288 base_level = srv_vk->v.desc.u.texture.level_idx;
1289 base_layer = srv_vk->v.desc.u.texture.layer_idx;
1291 texture_vk = wined3d_texture_vk(texture_from_resource(srv_vk->v.resource));
1292 for (i = 0; i < layer_count; ++i)
1294 sub_resource_idx = (base_layer + i) * texture_vk->t.level_count + base_level;
1295 if (!wined3d_texture_load_location(&texture_vk->t, sub_resource_idx,
1296 &context_vk->c, WINED3D_LOCATION_TEXTURE_RGB))
1297 ERR("Failed to load source layer %u.\n", base_layer + i);
1300 if (context_vk->c.d3d_info->wined3d_creation_flags & WINED3D_SRGB_READ_WRITE_CONTROL)
1301 FIXME("Unhandled sRGB read/write control.\n");
1303 if (wined3d_format_vk(srv_vk->v.format)->vk_format != wined3d_format_vk(texture_vk->t.resource.format)->vk_format)
1304 FIXME("Ignoring view format %s.\n", debug_d3dformat(srv_vk->v.format->id));
1306 if (wined3d_resource_get_sample_count(&texture_vk->t.resource) > 1)
1307 FIXME("Unhandled multi-sampled resource.\n");
1309 if (!(vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk)))
1311 ERR("Failed to get command buffer.\n");
1312 return;
1315 vk_src_range.aspectMask = vk_aspect_mask_from_format(texture_vk->t.resource.format);
1316 vk_src_range.baseMipLevel = base_level;
1317 vk_src_range.levelCount = 1;
1318 vk_src_range.baseArrayLayer = base_layer;
1319 vk_src_range.layerCount = layer_count;
1321 vk_dst_range = vk_src_range;
1322 ++vk_dst_range.baseMipLevel;
1324 wined3d_context_vk_image_barrier(context_vk, vk_command_buffer,
1325 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
1326 vk_access_mask_from_bind_flags(texture_vk->t.resource.bind_flags),
1327 VK_ACCESS_TRANSFER_READ_BIT,
1328 texture_vk->layout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1329 texture_vk->image.vk_image, &vk_src_range);
1330 wined3d_context_vk_image_barrier(context_vk, vk_command_buffer,
1331 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
1332 vk_access_mask_from_bind_flags(texture_vk->t.resource.bind_flags),
1333 VK_ACCESS_TRANSFER_WRITE_BIT,
1334 texture_vk->layout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1335 texture_vk->image.vk_image, &vk_dst_range);
1337 region.srcSubresource.aspectMask = vk_src_range.aspectMask;
1338 region.srcSubresource.mipLevel = vk_src_range.baseMipLevel;
1339 region.srcSubresource.baseArrayLayer = vk_src_range.baseArrayLayer;
1340 region.srcSubresource.layerCount = vk_src_range.layerCount;
1341 region.srcOffsets[0].x = 0;
1342 region.srcOffsets[0].y = 0;
1343 region.srcOffsets[0].z = 0;
1345 region.dstSubresource.aspectMask = vk_dst_range.aspectMask;
1346 region.dstSubresource.mipLevel = vk_dst_range.baseMipLevel;
1347 region.dstSubresource.baseArrayLayer = vk_dst_range.baseArrayLayer;
1348 region.dstSubresource.layerCount = vk_dst_range.layerCount;
1349 region.dstOffsets[0].x = 0;
1350 region.dstOffsets[0].y = 0;
1351 region.dstOffsets[0].z = 0;
1353 for (i = 1; i < level_count; ++i)
1355 region.srcOffsets[1].x = wined3d_texture_get_level_width(&texture_vk->t, vk_src_range.baseMipLevel);
1356 region.srcOffsets[1].y = wined3d_texture_get_level_height(&texture_vk->t, vk_src_range.baseMipLevel);
1357 region.srcOffsets[1].z = wined3d_texture_get_level_depth(&texture_vk->t, vk_src_range.baseMipLevel);
1359 region.dstOffsets[1].x = wined3d_texture_get_level_width(&texture_vk->t, vk_dst_range.baseMipLevel);
1360 region.dstOffsets[1].y = wined3d_texture_get_level_height(&texture_vk->t, vk_dst_range.baseMipLevel);
1361 region.dstOffsets[1].z = wined3d_texture_get_level_depth(&texture_vk->t, vk_dst_range.baseMipLevel);
1363 VK_CALL(vkCmdBlitImage(vk_command_buffer, texture_vk->image.vk_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1364 texture_vk->image.vk_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region, VK_FILTER_LINEAR));
1366 wined3d_context_vk_image_barrier(context_vk, vk_command_buffer,
1367 VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
1368 VK_ACCESS_TRANSFER_READ_BIT,
1369 vk_access_mask_from_bind_flags(texture_vk->t.resource.bind_flags),
1370 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, texture_vk->layout,
1371 texture_vk->image.vk_image, &vk_src_range);
1373 if (i == level_count - 1)
1375 wined3d_context_vk_image_barrier(context_vk, vk_command_buffer,
1376 VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
1377 VK_ACCESS_TRANSFER_WRITE_BIT,
1378 vk_access_mask_from_bind_flags(texture_vk->t.resource.bind_flags),
1379 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, texture_vk->layout,
1380 texture_vk->image.vk_image, &vk_dst_range);
1382 else
1384 region.srcSubresource.mipLevel = ++vk_src_range.baseMipLevel;
1385 region.dstSubresource.mipLevel = ++vk_dst_range.baseMipLevel;
1387 wined3d_context_vk_image_barrier(context_vk, vk_command_buffer,
1388 VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
1389 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
1390 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1391 texture_vk->image.vk_image, &vk_src_range);
1392 wined3d_context_vk_image_barrier(context_vk, vk_command_buffer,
1393 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
1394 vk_access_mask_from_bind_flags(texture_vk->t.resource.bind_flags),
1395 VK_ACCESS_TRANSFER_WRITE_BIT,
1396 texture_vk->layout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1397 texture_vk->image.vk_image, &vk_dst_range);
1401 for (i = 0; i < layer_count; ++i)
1403 for (j = 1; j < level_count; ++j)
1405 sub_resource_idx = (base_layer + i) * texture_vk->t.level_count + base_level + j;
1406 wined3d_texture_validate_location(&texture_vk->t, sub_resource_idx, WINED3D_LOCATION_TEXTURE_RGB);
1407 wined3d_texture_invalidate_location(&texture_vk->t, sub_resource_idx, ~WINED3D_LOCATION_TEXTURE_RGB);
1411 wined3d_context_vk_reference_texture(context_vk, texture_vk);
1414 ULONG CDECL wined3d_unordered_access_view_incref(struct wined3d_unordered_access_view *view)
1416 ULONG refcount = InterlockedIncrement(&view->refcount);
1418 TRACE("%p increasing refcount to %u.\n", view, refcount);
1420 return refcount;
1423 void wined3d_unordered_access_view_cleanup(struct wined3d_unordered_access_view *view)
1425 /* Call wined3d_object_destroyed() before releasing the resource,
1426 * since releasing the resource may end up destroying the parent. */
1427 view->parent_ops->wined3d_object_destroyed(view->parent);
1428 wined3d_resource_decref(view->resource);
1431 ULONG CDECL wined3d_unordered_access_view_decref(struct wined3d_unordered_access_view *view)
1433 ULONG refcount = InterlockedDecrement(&view->refcount);
1435 TRACE("%p decreasing refcount to %u.\n", view, refcount);
1437 if (!refcount)
1438 view->resource->device->adapter->adapter_ops->adapter_destroy_unordered_access_view(view);
1440 return refcount;
1443 void * CDECL wined3d_unordered_access_view_get_parent(const struct wined3d_unordered_access_view *view)
1445 TRACE("view %p.\n", view);
1447 return view->parent;
1450 void wined3d_unordered_access_view_invalidate_location(struct wined3d_unordered_access_view *view,
1451 DWORD location)
1453 wined3d_view_invalidate_location(view->resource, &view->desc, location);
1456 void wined3d_unordered_access_view_gl_clear(struct wined3d_unordered_access_view_gl *view_gl,
1457 const struct wined3d_uvec4 *clear_value, struct wined3d_context_gl *context_gl, bool fp)
1459 const struct wined3d_gl_info *gl_info = context_gl->gl_info;
1460 const struct wined3d_format_gl *format_gl;
1461 struct wined3d_buffer_gl *buffer_gl;
1462 struct wined3d_resource *resource;
1463 unsigned int offset, size;
1465 resource = view_gl->v.resource;
1466 if (resource->type != WINED3D_RTYPE_BUFFER)
1468 unsigned int layer_count, level_count, base_level, base_layer;
1469 unsigned int sub_resource_idx, width, height, depth, i, j;
1470 struct wined3d_texture_gl *texture_gl;
1471 const void *data = clear_value;
1472 GLenum gl_format, gl_type;
1473 uint32_t packed;
1475 if (!gl_info->supported[ARB_CLEAR_TEXTURE])
1477 FIXME("OpenGL implementation does not support ARB_clear_texture.\n");
1478 return;
1481 format_gl = wined3d_format_gl(resource->format);
1482 texture_gl = wined3d_texture_gl(texture_from_resource(resource));
1483 layer_count = view_gl->v.desc.u.texture.layer_count;
1484 level_count = view_gl->v.desc.u.texture.level_count;
1485 base_layer = view_gl->v.desc.u.texture.layer_idx;
1486 base_level = view_gl->v.desc.u.texture.level_idx;
1488 if (format_gl->f.byte_count <= 4 && !fp)
1490 gl_format = format_gl->format;
1491 gl_type = format_gl->type;
1492 packed = wined3d_format_pack(&format_gl->f, clear_value);
1493 data = &packed;
1495 else if (resource->format_flags & WINED3DFMT_FLAG_INTEGER)
1497 gl_format = GL_RGBA_INTEGER;
1498 gl_type = GL_UNSIGNED_INT;
1500 else
1502 gl_format = GL_RGBA;
1503 gl_type = GL_FLOAT;
1506 for (i = 0; i < layer_count; ++i)
1508 for (j = 0; j < level_count; ++j)
1510 sub_resource_idx = (base_layer + i) * texture_gl->t.level_count + base_level + j;
1511 wined3d_texture_prepare_location(&texture_gl->t, sub_resource_idx,
1512 &context_gl->c, WINED3D_LOCATION_TEXTURE_RGB);
1514 width = wined3d_texture_get_level_width(&texture_gl->t, base_level + j);
1515 height = wined3d_texture_get_level_height(&texture_gl->t, base_level + j);
1516 depth = wined3d_texture_get_level_depth(&texture_gl->t, base_level + j);
1518 switch (texture_gl->target)
1520 case GL_TEXTURE_1D_ARRAY:
1521 GL_EXTCALL(glClearTexSubImage(texture_gl->texture_rgb.name, base_level + j,
1522 0, base_layer + i, 0, width, 1, 1, gl_format, gl_type, data));
1523 break;
1525 case GL_TEXTURE_2D_ARRAY:
1526 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
1527 case GL_TEXTURE_CUBE_MAP:
1528 case GL_TEXTURE_CUBE_MAP_ARRAY:
1529 GL_EXTCALL(glClearTexSubImage(texture_gl->texture_rgb.name, base_level + j,
1530 0, 0, base_layer + i, width, height, 1, gl_format, gl_type, data));
1531 break;
1533 default:
1534 GL_EXTCALL(glClearTexSubImage(texture_gl->texture_rgb.name, base_level + j,
1535 0, 0, 0, width, height, depth, gl_format, gl_type, data));
1536 break;
1539 wined3d_texture_validate_location(&texture_gl->t, sub_resource_idx, WINED3D_LOCATION_TEXTURE_RGB);
1540 wined3d_texture_invalidate_location(&texture_gl->t, sub_resource_idx, ~WINED3D_LOCATION_TEXTURE_RGB);
1544 return;
1547 if (!gl_info->supported[ARB_CLEAR_BUFFER_OBJECT])
1549 FIXME("OpenGL implementation does not support ARB_clear_buffer_object.\n");
1550 return;
1553 format_gl = wined3d_format_gl(view_gl->v.format);
1554 if (format_gl->f.id != WINED3DFMT_R32_UINT && format_gl->f.id != WINED3DFMT_R32_SINT
1555 && format_gl->f.id != WINED3DFMT_R32G32B32A32_UINT
1556 && format_gl->f.id != WINED3DFMT_R32G32B32A32_SINT)
1558 FIXME("Not implemented for format %s.\n", debug_d3dformat(format_gl->f.id));
1559 return;
1562 if (fp)
1564 FIXME("Floating-point buffer clears not implemented.\n");
1565 return;
1568 buffer_gl = wined3d_buffer_gl(buffer_from_resource(resource));
1569 wined3d_buffer_load_location(&buffer_gl->b, &context_gl->c, WINED3D_LOCATION_BUFFER);
1570 wined3d_unordered_access_view_invalidate_location(&view_gl->v, ~WINED3D_LOCATION_BUFFER);
1572 get_buffer_view_range(&buffer_gl->b, &view_gl->v.desc, &format_gl->f, &offset, &size);
1573 wined3d_context_gl_bind_bo(context_gl, buffer_gl->bo.binding, buffer_gl->bo.id);
1574 GL_EXTCALL(glClearBufferSubData(buffer_gl->bo.binding, format_gl->internal,
1575 offset, size, format_gl->format, format_gl->type, clear_value));
1576 wined3d_context_gl_reference_bo(context_gl, &buffer_gl->bo);
1577 checkGLcall("clear unordered access view");
1580 void wined3d_unordered_access_view_set_counter(struct wined3d_unordered_access_view *view,
1581 unsigned int value)
1583 struct wined3d_bo_address dst, src;
1584 struct wined3d_context *context;
1586 if (!view->counter_bo)
1587 return;
1589 context = context_acquire(view->resource->device, NULL, 0);
1591 src.buffer_object = 0;
1592 src.addr = (void *)&value;
1594 dst.buffer_object = view->counter_bo;
1595 dst.addr = NULL;
1597 wined3d_context_copy_bo_address(context, &dst, &src, sizeof(uint32_t));
1599 context_release(context);
1602 void wined3d_unordered_access_view_copy_counter(struct wined3d_unordered_access_view *view,
1603 struct wined3d_buffer *buffer, unsigned int offset, struct wined3d_context *context)
1605 struct wined3d_const_bo_address src;
1607 if (!view->counter_bo)
1608 return;
1610 src.buffer_object = view->counter_bo;
1611 src.addr = NULL;
1613 wined3d_buffer_copy_bo_address(buffer, context, offset, &src, sizeof(uint32_t));
1616 void wined3d_unordered_access_view_gl_update(struct wined3d_unordered_access_view_gl *uav_gl,
1617 struct wined3d_context_gl *context_gl)
1619 create_buffer_view(&uav_gl->gl_view, &context_gl->c, &uav_gl->v.desc,
1620 buffer_from_resource(uav_gl->v.resource), uav_gl->v.format);
1621 uav_gl->bo_user.valid = true;
1624 static void wined3d_unordered_access_view_gl_cs_init(void *object)
1626 struct wined3d_unordered_access_view_gl *view_gl = object;
1627 struct wined3d_resource *resource = view_gl->v.resource;
1628 struct wined3d_view_desc *desc = &view_gl->v.desc;
1629 const struct wined3d_gl_info *gl_info;
1631 TRACE("view_gl %p.\n", view_gl);
1633 gl_info = &resource->device->adapter->gl_info;
1635 if (resource->type == WINED3D_RTYPE_BUFFER)
1637 struct wined3d_buffer *buffer = buffer_from_resource(resource);
1638 struct wined3d_context_gl *context_gl;
1640 context_gl = wined3d_context_gl(context_acquire(resource->device, NULL, 0));
1641 create_buffer_view(&view_gl->gl_view, &context_gl->c, desc, buffer, view_gl->v.format);
1642 view_gl->bo_user.valid = true;
1643 list_add_head(&wined3d_buffer_gl(buffer)->bo.users, &view_gl->bo_user.entry);
1644 if (desc->flags & (WINED3D_VIEW_BUFFER_COUNTER | WINED3D_VIEW_BUFFER_APPEND))
1646 struct wined3d_bo_gl *bo = &view_gl->counter_bo;
1648 view_gl->v.counter_bo = (uintptr_t)bo;
1649 wined3d_context_gl_create_bo(context_gl, sizeof(uint32_t), GL_ATOMIC_COUNTER_BUFFER,
1650 GL_STATIC_DRAW, true, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_CLIENT_STORAGE_BIT, bo);
1651 wined3d_unordered_access_view_set_counter(&view_gl->v, 0);
1653 context_release(&context_gl->c);
1655 else
1657 struct wined3d_texture_gl *texture_gl = wined3d_texture_gl(texture_from_resource(resource));
1658 unsigned int depth_or_layer_count;
1660 if (resource->type == WINED3D_RTYPE_TEXTURE_3D)
1661 depth_or_layer_count = wined3d_texture_get_level_depth(&texture_gl->t, desc->u.texture.level_idx);
1662 else
1663 depth_or_layer_count = texture_gl->t.layer_count;
1665 if (desc->u.texture.layer_idx || desc->u.texture.layer_count != depth_or_layer_count)
1667 create_texture_view(&view_gl->gl_view, get_texture_view_target(gl_info, desc, texture_gl),
1668 desc, texture_gl, view_gl->v.format);
1673 static HRESULT wined3d_unordered_access_view_init(struct wined3d_unordered_access_view *view,
1674 const struct wined3d_view_desc *desc, struct wined3d_resource *resource,
1675 void *parent, const struct wined3d_parent_ops *parent_ops)
1677 view->refcount = 1;
1678 view->parent = parent;
1679 view->parent_ops = parent_ops;
1681 if (!(resource->bind_flags & WINED3D_BIND_UNORDERED_ACCESS))
1682 return E_INVALIDARG;
1683 if (!(view->format = validate_resource_view(desc, resource, TRUE, FALSE)))
1684 return E_INVALIDARG;
1685 view->desc = *desc;
1687 wined3d_resource_incref(view->resource = resource);
1689 return WINED3D_OK;
1692 HRESULT wined3d_unordered_access_view_gl_init(struct wined3d_unordered_access_view_gl *view_gl,
1693 const struct wined3d_view_desc *desc, struct wined3d_resource *resource,
1694 void *parent, const struct wined3d_parent_ops *parent_ops)
1696 HRESULT hr;
1698 TRACE("view_gl %p, desc %s, resource %p, parent %p, parent_ops %p.\n",
1699 view_gl, wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops);
1701 if (FAILED(hr = wined3d_unordered_access_view_init(&view_gl->v, desc, resource, parent, parent_ops)))
1702 return hr;
1704 list_init(&view_gl->bo_user.entry);
1705 wined3d_cs_init_object(resource->device->cs, wined3d_unordered_access_view_gl_cs_init, view_gl);
1707 return hr;
1710 void wined3d_unordered_access_view_vk_clear(struct wined3d_unordered_access_view_vk *view_vk,
1711 const struct wined3d_uvec4 *clear_value, struct wined3d_context_vk *context_vk, bool fp)
1713 const struct wined3d_vk_info *vk_info;
1714 const struct wined3d_format *format;
1715 struct wined3d_buffer_vk *buffer_vk;
1716 struct wined3d_resource *resource;
1717 VkCommandBuffer vk_command_buffer;
1718 VkBufferMemoryBarrier vk_barrier;
1719 VkAccessFlags access_mask;
1720 unsigned int offset, size;
1722 TRACE("view_vk %p, clear_value %s, context_vk %p, fp %#x.\n", view_vk, debug_uvec4(clear_value), context_vk, fp);
1724 resource = view_vk->v.resource;
1725 if (resource->type != WINED3D_RTYPE_BUFFER)
1727 FIXME("Not implemented for %s resources.\n", debug_d3dresourcetype(resource->type));
1728 return;
1731 format = view_vk->v.format;
1732 if (format->id != WINED3DFMT_R32_UINT && format->id != WINED3DFMT_R32_SINT)
1734 FIXME("Not implemented for format %s.\n", debug_d3dformat(format->id));
1735 return;
1738 vk_info = context_vk->vk_info;
1739 buffer_vk = wined3d_buffer_vk(buffer_from_resource(resource));
1740 wined3d_buffer_load_location(&buffer_vk->b, &context_vk->c, WINED3D_LOCATION_BUFFER);
1741 wined3d_buffer_invalidate_location(&buffer_vk->b, ~WINED3D_LOCATION_BUFFER);
1743 get_buffer_view_range(&buffer_vk->b, &view_vk->v.desc, format, &offset, &size);
1745 if (!(vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk)))
1746 return;
1747 wined3d_context_vk_end_current_render_pass(context_vk);
1749 access_mask = vk_access_mask_from_bind_flags(buffer_vk->b.resource.bind_flags);
1750 vk_barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
1751 vk_barrier.pNext = NULL;
1752 vk_barrier.srcAccessMask = access_mask;
1753 vk_barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
1754 vk_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1755 vk_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1756 vk_barrier.buffer = buffer_vk->bo.vk_buffer;
1757 vk_barrier.offset = buffer_vk->bo.buffer_offset + offset;
1758 vk_barrier.size = size;
1759 VK_CALL(vkCmdPipelineBarrier(vk_command_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
1760 VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 1, &vk_barrier, 0, NULL));
1762 VK_CALL(vkCmdFillBuffer(vk_command_buffer, buffer_vk->bo.vk_buffer,
1763 buffer_vk->bo.buffer_offset + offset, size, clear_value->x));
1765 vk_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
1766 vk_barrier.dstAccessMask = access_mask;
1767 VK_CALL(vkCmdPipelineBarrier(vk_command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
1768 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, NULL, 1, &vk_barrier, 0, NULL));
1770 wined3d_context_vk_reference_bo(context_vk, &buffer_vk->bo);
1773 void wined3d_unordered_access_view_vk_update(struct wined3d_unordered_access_view_vk *uav_vk,
1774 struct wined3d_context_vk *context_vk)
1776 const struct wined3d_format_vk *view_format_vk = wined3d_format_vk(uav_vk->v.format);
1777 const struct wined3d_view_desc *desc = &uav_vk->v.desc;
1778 struct wined3d_resource *resource = uav_vk->v.resource;
1779 struct wined3d_view_vk *view_vk = &uav_vk->view_vk;
1780 struct wined3d_buffer_vk *buffer_vk;
1781 VkBufferView vk_buffer_view;
1783 buffer_vk = wined3d_buffer_vk(buffer_from_resource(resource));
1784 wined3d_context_vk_destroy_vk_buffer_view(context_vk, view_vk->u.vk_buffer_view, view_vk->command_buffer_id);
1785 if ((vk_buffer_view = wined3d_view_vk_create_vk_buffer_view(context_vk, desc, buffer_vk, view_format_vk)))
1787 view_vk->u.vk_buffer_view = vk_buffer_view;
1788 view_vk->bo_user.valid = true;
1792 static void wined3d_unordered_access_view_vk_cs_init(void *object)
1794 struct wined3d_unordered_access_view_vk *uav_vk = object;
1795 struct wined3d_view_vk *view_vk = &uav_vk->view_vk;
1796 struct wined3d_view_desc *desc = &uav_vk->v.desc;
1797 const struct wined3d_format_vk *format_vk;
1798 const struct wined3d_vk_info *vk_info;
1799 struct wined3d_texture_vk *texture_vk;
1800 struct wined3d_context_vk *context_vk;
1801 struct wined3d_device_vk *device_vk;
1802 struct wined3d_buffer_vk *buffer_vk;
1803 VkBufferViewCreateInfo create_info;
1804 struct wined3d_resource *resource;
1805 VkBufferView vk_buffer_view;
1806 uint32_t default_flags = 0;
1807 VkImageView vk_image_view;
1808 VkResult vr;
1810 TRACE("uav_vk %p.\n", uav_vk);
1812 resource = uav_vk->v.resource;
1813 device_vk = wined3d_device_vk(resource->device);
1814 format_vk = wined3d_format_vk(uav_vk->v.format);
1816 if (resource->type == WINED3D_RTYPE_BUFFER)
1818 buffer_vk = wined3d_buffer_vk(buffer_from_resource(resource));
1820 context_vk = wined3d_context_vk(context_acquire(&device_vk->d, NULL, 0));
1821 vk_info = context_vk->vk_info;
1823 if ((vk_buffer_view = wined3d_view_vk_create_vk_buffer_view(context_vk, desc, buffer_vk, format_vk)))
1825 TRACE("Created buffer view 0x%s.\n", wine_dbgstr_longlong(vk_buffer_view));
1827 uav_vk->view_vk.u.vk_buffer_view = vk_buffer_view;
1828 uav_vk->view_vk.bo_user.valid = true;
1829 list_add_head(&buffer_vk->bo.users, &view_vk->bo_user.entry);
1832 if (desc->flags & (WINED3D_VIEW_BUFFER_COUNTER | WINED3D_VIEW_BUFFER_APPEND))
1834 if (!wined3d_context_vk_create_bo(context_vk, sizeof(uint32_t), VK_BUFFER_USAGE_TRANSFER_SRC_BIT
1835 | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT,
1836 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &uav_vk->counter_bo))
1838 ERR("Failed to create counter bo.\n");
1839 context_release(&context_vk->c);
1841 return;
1844 wined3d_context_vk_end_current_render_pass(context_vk);
1845 VK_CALL(vkCmdFillBuffer(wined3d_context_vk_get_command_buffer(context_vk),
1846 uav_vk->counter_bo.vk_buffer, uav_vk->counter_bo.buffer_offset, sizeof(uint32_t), 0));
1847 wined3d_context_vk_reference_bo(context_vk, &uav_vk->counter_bo);
1849 create_info.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO;
1850 create_info.pNext = NULL;
1851 create_info.flags = 0;
1852 create_info.buffer = uav_vk->counter_bo.vk_buffer;
1853 create_info.format = VK_FORMAT_R32_UINT;
1854 create_info.offset = uav_vk->counter_bo.buffer_offset;
1855 create_info.range = sizeof(uint32_t);
1856 if ((vr = VK_CALL(vkCreateBufferView(device_vk->vk_device,
1857 &create_info, NULL, &uav_vk->vk_counter_view))) < 0)
1859 ERR("Failed to create counter buffer view, vr %s.\n", wined3d_debug_vkresult(vr));
1861 else
1863 TRACE("Created counter buffer view 0x%s.\n", wine_dbgstr_longlong(uav_vk->vk_counter_view));
1865 uav_vk->v.counter_bo = (uintptr_t)&uav_vk->counter_bo;
1869 context_release(&context_vk->c);
1871 return;
1874 texture_vk = wined3d_texture_vk(texture_from_resource(resource));
1876 if (texture_vk->t.layer_count > 1)
1877 default_flags |= WINED3D_VIEW_TEXTURE_ARRAY;
1879 if (resource->format->id == format_vk->f.id && desc->flags == default_flags
1880 && !desc->u.texture.level_idx && desc->u.texture.level_count == texture_vk->t.level_count
1881 && !desc->u.texture.layer_idx && desc->u.texture.layer_count == texture_vk->t.layer_count
1882 && !(resource->bind_flags & WINED3D_BIND_DEPTH_STENCIL) && resource->type != WINED3D_RTYPE_TEXTURE_3D)
1884 TRACE("Creating identity unordered access view.\n");
1885 return;
1888 if (texture_vk->t.swapchain && texture_vk->t.swapchain->state.desc.backbuffer_count > 1)
1889 FIXME("Swapchain unordered access views not supported.\n");
1891 context_vk = wined3d_context_vk(context_acquire(&device_vk->d, NULL, 0));
1892 vk_image_view = wined3d_view_vk_create_vk_image_view(context_vk, desc,
1893 texture_vk, format_vk, format_vk->f.color_fixup, false);
1894 context_release(&context_vk->c);
1896 if (!vk_image_view)
1897 return;
1899 TRACE("Created image view 0x%s.\n", wine_dbgstr_longlong(vk_image_view));
1901 view_vk->u.vk_image_info.imageView = vk_image_view;
1902 view_vk->u.vk_image_info.sampler = VK_NULL_HANDLE;
1903 view_vk->u.vk_image_info.imageLayout = texture_vk->layout;
1906 HRESULT wined3d_unordered_access_view_vk_init(struct wined3d_unordered_access_view_vk *view_vk,
1907 const struct wined3d_view_desc *desc, struct wined3d_resource *resource,
1908 void *parent, const struct wined3d_parent_ops *parent_ops)
1910 HRESULT hr;
1912 TRACE("view_vk %p, desc %s, resource %p, parent %p, parent_ops %p.\n",
1913 view_vk, wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops);
1915 if (FAILED(hr = wined3d_unordered_access_view_init(&view_vk->v, desc, resource, parent, parent_ops)))
1916 return hr;
1918 list_init(&view_vk->view_vk.bo_user.entry);
1919 wined3d_cs_init_object(resource->device->cs, wined3d_unordered_access_view_vk_cs_init, view_vk);
1921 return hr;
1924 HRESULT CDECL wined3d_unordered_access_view_create(const struct wined3d_view_desc *desc,
1925 struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops,
1926 struct wined3d_unordered_access_view **view)
1928 const struct wined3d_adapter_ops *adapter_ops;
1930 TRACE("desc %s, resource %p, parent %p, parent_ops %p, view %p.\n",
1931 wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops, view);
1933 adapter_ops = resource->device->adapter->adapter_ops;
1934 return adapter_ops->adapter_create_unordered_access_view(desc, resource, parent, parent_ops, view);