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
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
)
40 GLenum texture_target
;
41 unsigned int view_flags
;
43 enum wined3d_gl_extension extension
;
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
);
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
)
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
));
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
));
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
));
123 format
= wined3d_get_format(adapter
, WINED3DFMT_R32_UINT
, resource
->bind_flags
);
124 element_size
= buffer
->structure_byte_stride
;
128 element_size
= format
->byte_count
;
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
)
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
));
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
);
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
)
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
;
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");
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
);
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");
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
))
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");
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
);
268 wined3d_buffer_load_location(&buffer_gl
->b
, &context_gl
->c
, WINED3D_LOCATION_BUFFER
);
270 view
->target
= GL_TEXTURE_BUFFER
;
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
));
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
;
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
);
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
);
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
);
362 view
->resource
->device
->adapter
->adapter_ops
->adapter_destroy_rendertarget_view(view
);
367 void * CDECL
wined3d_rendertarget_view_get_parent(const struct wined3d_rendertarget_view
*view
)
369 TRACE("view %p.\n", view
);
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
;
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
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
;
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
));
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
);
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
));
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
));
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
);
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
));
543 if (texture_gl
->t
.swapchain
&& texture_gl
->t
.swapchain
->state
.desc
.backbuffer_count
> 1)
545 FIXME("Swapchain views not supported.\n");
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
;
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
)))
573 view
->format_flags
= view
->format
->flags
[resource
->gl_type
];
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
;
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
);
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
)
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
)))
622 wined3d_cs_init_object(resource
->device
->cs
, wined3d_render_target_view_gl_cs_init
, view_gl
);
627 VkImageViewType
vk_image_view_type_from_wined3d(enum wined3d_resource_type type
, uint32_t flags
)
631 case WINED3D_RTYPE_TEXTURE_1D
:
632 if (flags
& WINED3D_VIEW_TEXTURE_ARRAY
)
633 return VK_IMAGE_VIEW_TYPE_1D_ARRAY
;
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
;
643 return VK_IMAGE_VIEW_TYPE_CUBE
;
645 if (flags
& WINED3D_VIEW_TEXTURE_ARRAY
)
646 return VK_IMAGE_VIEW_TYPE_2D_ARRAY
;
648 return VK_IMAGE_VIEW_TYPE_2D
;
650 case WINED3D_RTYPE_TEXTURE_3D
:
651 return VK_IMAGE_VIEW_TYPE_3D
;
654 ERR("Unhandled resource type %s.\n", debug_d3dresourcetype(type
));
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
;
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
;
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
);
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
;
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
;
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
;
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");
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");
822 if (texture_vk
->t
.swapchain
&& texture_vk
->t
.swapchain
->state
.desc
.backbuffer_count
> 1)
824 FIXME("Swapchain views not supported.\n");
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
)
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
)
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
)))
851 wined3d_cs_init_object(resource
->device
->cs
, wined3d_render_target_view_vk_cs_init
, view_vk
);
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
;
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
);
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
);
912 view
->resource
->device
->adapter
->adapter_ops
->adapter_destroy_shader_resource_view(view
);
917 void * CDECL
wined3d_shader_resource_view_get_parent(const struct wined3d_shader_resource_view
*view
)
919 TRACE("view %p.\n", view
);
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
;
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
);
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
);
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
)
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
;
1009 wined3d_resource_incref(view
->resource
= resource
);
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
)
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
)))
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
);
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
)
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
);
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");
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
);
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
)
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
)))
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
);
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
);
1168 if (view_gl
->v
.resource
->type
== WINED3D_RTYPE_BUFFER
)
1170 FIXME("Buffer shader resources not supported.\n");
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
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
;
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
);
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
;
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");
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, ®ion
, 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
);
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
);
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
);
1431 view
->resource
->device
->adapter
->adapter_ops
->adapter_destroy_unordered_access_view(view
);
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
,
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
));
1465 if (!gl_info
->supported
[ARB_CLEAR_BUFFER_OBJECT
])
1467 FIXME("OpenGL implementation does not support ARB_clear_buffer_object.\n");
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
));
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
,
1495 struct wined3d_bo_address dst
, src
;
1496 struct wined3d_context
*context
;
1498 if (!view
->counter_bo
)
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
;
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
;
1520 if (!view
->counter_bo
)
1523 dst_location
= wined3d_buffer_get_memory(buffer
, &dst
, buffer
->locations
);
1526 src
.buffer_object
= view
->counter_bo
;
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
);
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
);
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
)
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
;
1605 wined3d_resource_incref(view
->resource
= resource
);
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
)
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
)))
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
);
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
));
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
));
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
)))
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
;
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
);
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
));
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
);
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");
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
);
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
)
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
)))
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
);
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
);