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
*texture
)
40 GLenum texture_target
;
41 unsigned int view_flags
;
43 enum wined3d_gl_extension extension
;
47 {GL_TEXTURE_2D
, 0, GL_TEXTURE_2D
},
48 {GL_TEXTURE_2D
, WINED3D_VIEW_TEXTURE_ARRAY
, GL_TEXTURE_2D_ARRAY
},
49 {GL_TEXTURE_2D_ARRAY
, 0, GL_TEXTURE_2D
},
50 {GL_TEXTURE_2D_ARRAY
, WINED3D_VIEW_TEXTURE_ARRAY
, GL_TEXTURE_2D_ARRAY
},
51 {GL_TEXTURE_2D_ARRAY
, WINED3D_VIEW_TEXTURE_CUBE
, GL_TEXTURE_CUBE_MAP
},
52 {GL_TEXTURE_2D_ARRAY
, WINED3D_VIEW_CUBE_ARRAY
, GL_TEXTURE_CUBE_MAP_ARRAY
, ARB_TEXTURE_CUBE_MAP_ARRAY
},
53 {GL_TEXTURE_3D
, 0, GL_TEXTURE_3D
},
57 for (i
= 0; i
< ARRAY_SIZE(view_types
); ++i
)
59 if (view_types
[i
].texture_target
!= texture
->target
|| view_types
[i
].view_flags
!= desc
->flags
)
61 if (gl_info
->supported
[view_types
[i
].extension
])
62 return view_types
[i
].view_target
;
64 FIXME("Extension %#x not supported.\n", view_types
[i
].extension
);
67 FIXME("Unhandled view flags %#x for texture target %#x.\n", desc
->flags
, texture
->target
);
68 return texture
->target
;
71 static void create_texture_view(struct wined3d_gl_view
*view
, GLenum view_target
,
72 const struct wined3d_view_desc
*desc
, struct wined3d_texture
*texture
,
73 const struct wined3d_format
*view_format
)
75 const struct wined3d_gl_info
*gl_info
;
76 unsigned int layer_idx
, layer_count
;
77 struct wined3d_context
*context
;
78 struct gl_texture
*gl_texture
;
80 view
->target
= view_target
;
82 context
= context_acquire(texture
->resource
.device
, NULL
, 0);
83 gl_info
= context
->gl_info
;
85 if (!gl_info
->supported
[ARB_TEXTURE_VIEW
])
87 context_release(context
);
88 FIXME("OpenGL implementation does not support texture views.\n");
92 wined3d_texture_prepare_texture(texture
, context
, FALSE
);
93 gl_texture
= wined3d_texture_get_gl_texture(texture
, FALSE
);
95 layer_idx
= desc
->u
.texture
.layer_idx
;
96 layer_count
= desc
->u
.texture
.layer_count
;
97 if (view_target
== GL_TEXTURE_3D
&& (layer_idx
|| layer_count
!= 1))
99 FIXME("Depth slice (%u-%u) not supported.\n", layer_idx
, layer_count
);
104 gl_info
->gl_ops
.gl
.p_glGenTextures(1, &view
->name
);
105 GL_EXTCALL(glTextureView(view
->name
, view
->target
, gl_texture
->name
, view_format
->glInternal
,
106 desc
->u
.texture
.level_idx
, desc
->u
.texture
.level_count
,
107 layer_idx
, layer_count
));
108 checkGLcall("Create texture view");
110 if (is_stencil_view_format(view_format
))
112 static const GLint swizzle
[] = {GL_ZERO
, GL_RED
, GL_ZERO
, GL_ZERO
};
114 if (!gl_info
->supported
[ARB_STENCIL_TEXTURING
])
116 context_release(context
);
117 FIXME("OpenGL implementation does not support stencil texturing.\n");
121 context_bind_texture(context
, view
->target
, view
->name
);
122 gl_info
->gl_ops
.gl
.p_glTexParameteriv(view
->target
, GL_TEXTURE_SWIZZLE_RGBA
, swizzle
);
123 gl_info
->gl_ops
.gl
.p_glTexParameteri(view
->target
, GL_DEPTH_STENCIL_TEXTURE_MODE
, GL_STENCIL_INDEX
);
124 checkGLcall("Initialize stencil view");
126 context_invalidate_compute_state(context
, STATE_COMPUTE_SHADER_RESOURCE_BINDING
);
127 context_invalidate_state(context
, STATE_GRAPHICS_SHADER_RESOURCE_BINDING
);
130 context_release(context
);
133 static void create_buffer_texture(struct wined3d_gl_view
*view
,
134 struct wined3d_buffer
*buffer
, const struct wined3d_format
*view_format
,
135 unsigned int offset
, unsigned int size
)
137 const struct wined3d_gl_info
*gl_info
;
138 struct wined3d_context
*context
;
140 context
= context_acquire(buffer
->resource
.device
, NULL
, 0);
141 gl_info
= context
->gl_info
;
142 if (!gl_info
->supported
[ARB_TEXTURE_BUFFER_OBJECT
])
144 FIXME("OpenGL implementation does not support buffer textures.\n");
145 context_release(context
);
149 if ((offset
& (gl_info
->limits
.texture_buffer_offset_alignment
- 1)))
151 FIXME("Buffer offset %u is not %u byte aligned.\n",
152 offset
, gl_info
->limits
.texture_buffer_offset_alignment
);
153 context_release(context
);
157 wined3d_buffer_load_location(buffer
, context
, WINED3D_LOCATION_BUFFER
);
159 view
->target
= GL_TEXTURE_BUFFER
;
160 gl_info
->gl_ops
.gl
.p_glGenTextures(1, &view
->name
);
162 context_bind_texture(context
, GL_TEXTURE_BUFFER
, view
->name
);
163 if (gl_info
->supported
[ARB_TEXTURE_BUFFER_RANGE
])
165 GL_EXTCALL(glTexBufferRange(GL_TEXTURE_BUFFER
, view_format
->glInternal
,
166 buffer
->buffer_object
, offset
, size
));
170 if (offset
|| size
!= buffer
->resource
.size
)
171 FIXME("OpenGL implementation does not support ARB_texture_buffer_range.\n");
172 GL_EXTCALL(glTexBuffer(GL_TEXTURE_BUFFER
, view_format
->glInternal
, buffer
->buffer_object
));
174 checkGLcall("Create buffer texture");
176 context_invalidate_compute_state(context
, STATE_COMPUTE_SHADER_RESOURCE_BINDING
);
177 context_invalidate_state(context
, STATE_GRAPHICS_SHADER_RESOURCE_BINDING
);
179 context_release(context
);
182 static void create_buffer_view(struct wined3d_gl_view
*view
,
183 const struct wined3d_view_desc
*desc
, struct wined3d_buffer
*buffer
,
184 const struct wined3d_format
*view_format
)
186 unsigned int offset
, size
;
188 if (desc
->format_id
== WINED3DFMT_UNKNOWN
)
190 offset
= desc
->u
.buffer
.start_idx
* buffer
->desc
.structure_byte_stride
;
191 size
= desc
->u
.buffer
.count
* buffer
->desc
.structure_byte_stride
;
195 offset
= desc
->u
.buffer
.start_idx
* view_format
->byte_count
;
196 size
= desc
->u
.buffer
.count
* view_format
->byte_count
;
199 create_buffer_texture(view
, buffer
, view_format
, offset
, size
);
202 ULONG CDECL
wined3d_rendertarget_view_incref(struct wined3d_rendertarget_view
*view
)
204 ULONG refcount
= InterlockedIncrement(&view
->refcount
);
206 TRACE("%p increasing refcount to %u.\n", view
, refcount
);
211 static void wined3d_rendertarget_view_destroy_object(void *object
)
213 HeapFree(GetProcessHeap(), 0, object
);
216 ULONG CDECL
wined3d_rendertarget_view_decref(struct wined3d_rendertarget_view
*view
)
218 ULONG refcount
= InterlockedDecrement(&view
->refcount
);
220 TRACE("%p decreasing refcount to %u.\n", view
, refcount
);
224 struct wined3d_resource
*resource
= view
->resource
;
225 struct wined3d_device
*device
= resource
->device
;
227 /* Call wined3d_object_destroyed() before releasing the resource,
228 * since releasing the resource may end up destroying the parent. */
229 view
->parent_ops
->wined3d_object_destroyed(view
->parent
);
230 wined3d_cs_destroy_object(device
->cs
, wined3d_rendertarget_view_destroy_object
, view
);
231 wined3d_resource_decref(resource
);
237 void * CDECL
wined3d_rendertarget_view_get_parent(const struct wined3d_rendertarget_view
*view
)
239 TRACE("view %p.\n", view
);
244 void * CDECL
wined3d_rendertarget_view_get_sub_resource_parent(const struct wined3d_rendertarget_view
*view
)
246 struct wined3d_texture
*texture
;
248 TRACE("view %p.\n", view
);
250 if (view
->resource
->type
== WINED3D_RTYPE_BUFFER
)
251 return wined3d_buffer_get_parent(buffer_from_resource(view
->resource
));
253 texture
= texture_from_resource(view
->resource
);
255 return texture
->sub_resources
[view
->sub_resource_idx
].parent
;
258 void CDECL
wined3d_rendertarget_view_set_parent(struct wined3d_rendertarget_view
*view
, void *parent
)
260 TRACE("view %p, parent %p.\n", view
, parent
);
262 view
->parent
= parent
;
265 struct wined3d_resource
* CDECL
wined3d_rendertarget_view_get_resource(const struct wined3d_rendertarget_view
*view
)
267 TRACE("view %p.\n", view
);
269 return view
->resource
;
272 void wined3d_rendertarget_view_get_drawable_size(const struct wined3d_rendertarget_view
*view
,
273 const struct wined3d_context
*context
, unsigned int *width
, unsigned int *height
)
275 const struct wined3d_texture
*texture
;
277 if (view
->resource
->type
!= WINED3D_RTYPE_TEXTURE_2D
)
279 FIXME("Not implemented for %s resources.\n", debug_d3dresourcetype(view
->resource
->type
));
285 texture
= texture_from_resource(view
->resource
);
286 if (texture
->swapchain
)
288 /* The drawable size of an onscreen drawable is the surface size.
289 * (Actually: The window size, but the surface is created in window
291 *width
= context
->current_rt
.texture
->resource
.width
;
292 *height
= context
->current_rt
.texture
->resource
.height
;
294 else if (wined3d_settings
.offscreen_rendering_mode
== ORM_BACKBUFFER
)
296 const struct wined3d_swapchain
*swapchain
= context
->swapchain
;
298 /* The drawable size of a backbuffer / aux buffer offscreen target is
299 * the size of the current context's drawable, which is the size of
300 * the back buffer of the swapchain the active context belongs to. */
301 *width
= swapchain
->desc
.backbuffer_width
;
302 *height
= swapchain
->desc
.backbuffer_height
;
306 struct wined3d_surface
*rt
;
308 /* The drawable size of an FBO target is the OpenGL texture size,
309 * which is the power of two size. */
310 rt
= context
->current_rt
.texture
->sub_resources
[context
->current_rt
.sub_resource_idx
].u
.surface
;
311 *width
= wined3d_texture_get_level_pow2_width(rt
->container
, rt
->texture_level
);
312 *height
= wined3d_texture_get_level_pow2_height(rt
->container
, rt
->texture_level
);
316 static HRESULT
wined3d_rendertarget_view_init(struct wined3d_rendertarget_view
*view
,
317 const struct wined3d_view_desc
*desc
, struct wined3d_resource
*resource
,
318 void *parent
, const struct wined3d_parent_ops
*parent_ops
)
320 const struct wined3d_gl_info
*gl_info
= &resource
->device
->adapter
->gl_info
;
323 view
->parent
= parent
;
324 view
->parent_ops
= parent_ops
;
326 view
->format
= wined3d_get_format(gl_info
, desc
->format_id
, resource
->usage
);
327 view
->format_flags
= view
->format
->flags
[resource
->gl_type
];
329 if (wined3d_format_is_typeless(view
->format
))
331 WARN("Trying to create view for typeless format %s.\n", debug_d3dformat(view
->format
->id
));
335 if (resource
->type
== WINED3D_RTYPE_BUFFER
)
337 view
->sub_resource_idx
= 0;
338 view
->buffer_offset
= desc
->u
.buffer
.start_idx
;
339 view
->width
= desc
->u
.buffer
.count
;
345 struct wined3d_texture
*texture
= texture_from_resource(resource
);
346 unsigned int depth_or_layer_count
;
348 if (resource
->type
== WINED3D_RTYPE_TEXTURE_3D
)
349 depth_or_layer_count
= wined3d_texture_get_level_depth(texture
, desc
->u
.texture
.level_idx
);
351 depth_or_layer_count
= texture
->layer_count
;
353 if (desc
->u
.texture
.level_idx
>= texture
->level_count
354 || desc
->u
.texture
.level_count
!= 1
355 || desc
->u
.texture
.layer_idx
>= depth_or_layer_count
356 || !desc
->u
.texture
.layer_count
357 || desc
->u
.texture
.layer_count
> depth_or_layer_count
- desc
->u
.texture
.layer_idx
)
360 view
->sub_resource_idx
= desc
->u
.texture
.level_idx
;
361 if (resource
->type
!= WINED3D_RTYPE_TEXTURE_3D
)
362 view
->sub_resource_idx
+= desc
->u
.texture
.layer_idx
* texture
->level_count
;
363 view
->buffer_offset
= 0;
364 view
->width
= wined3d_texture_get_level_width(texture
, desc
->u
.texture
.level_idx
);
365 view
->height
= wined3d_texture_get_level_height(texture
, desc
->u
.texture
.level_idx
);
366 view
->depth
= desc
->u
.texture
.layer_count
;
368 wined3d_resource_incref(view
->resource
= resource
);
373 HRESULT CDECL
wined3d_rendertarget_view_create(const struct wined3d_view_desc
*desc
,
374 struct wined3d_resource
*resource
, void *parent
, const struct wined3d_parent_ops
*parent_ops
,
375 struct wined3d_rendertarget_view
**view
)
377 struct wined3d_rendertarget_view
*object
;
380 TRACE("desc %p, resource %p, parent %p, parent_ops %p, view %p.\n",
381 desc
, resource
, parent
, parent_ops
, view
);
383 if (!(object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
))))
384 return E_OUTOFMEMORY
;
386 if (FAILED(hr
= wined3d_rendertarget_view_init(object
, desc
, resource
, parent
, parent_ops
)))
388 HeapFree(GetProcessHeap(), 0, object
);
389 WARN("Failed to initialise view, hr %#x.\n", hr
);
393 TRACE("Created render target view %p.\n", object
);
399 HRESULT CDECL
wined3d_rendertarget_view_create_from_sub_resource(struct wined3d_texture
*texture
,
400 unsigned int sub_resource_idx
, void *parent
, const struct wined3d_parent_ops
*parent_ops
,
401 struct wined3d_rendertarget_view
**view
)
403 struct wined3d_view_desc desc
;
405 TRACE("texture %p, sub_resource_idx %u, parent %p, parent_ops %p, view %p.\n",
406 texture
, sub_resource_idx
, parent
, parent_ops
, view
);
408 desc
.format_id
= texture
->resource
.format
->id
;
410 desc
.u
.texture
.level_idx
= sub_resource_idx
% texture
->level_count
;
411 desc
.u
.texture
.level_count
= 1;
412 desc
.u
.texture
.layer_idx
= sub_resource_idx
/ texture
->level_count
;
413 desc
.u
.texture
.layer_count
= 1;
415 return wined3d_rendertarget_view_create(&desc
, &texture
->resource
, parent
, parent_ops
, view
);
418 ULONG CDECL
wined3d_shader_resource_view_incref(struct wined3d_shader_resource_view
*view
)
420 ULONG refcount
= InterlockedIncrement(&view
->refcount
);
422 TRACE("%p increasing refcount to %u.\n", view
, refcount
);
427 static void wined3d_shader_resource_view_destroy_object(void *object
)
429 struct wined3d_shader_resource_view
*view
= object
;
431 if (view
->gl_view
.name
)
433 const struct wined3d_gl_info
*gl_info
;
434 struct wined3d_context
*context
;
436 context
= context_acquire(view
->resource
->device
, NULL
, 0);
437 gl_info
= context
->gl_info
;
438 gl_info
->gl_ops
.gl
.p_glDeleteTextures(1, &view
->gl_view
.name
);
439 checkGLcall("glDeleteTextures");
440 context_release(context
);
443 HeapFree(GetProcessHeap(), 0, view
);
446 ULONG CDECL
wined3d_shader_resource_view_decref(struct wined3d_shader_resource_view
*view
)
448 ULONG refcount
= InterlockedDecrement(&view
->refcount
);
450 TRACE("%p decreasing refcount to %u.\n", view
, refcount
);
454 struct wined3d_resource
*resource
= view
->resource
;
455 struct wined3d_device
*device
= resource
->device
;
457 /* Call wined3d_object_destroyed() before releasing the resource,
458 * since releasing the resource may end up destroying the parent. */
459 view
->parent_ops
->wined3d_object_destroyed(view
->parent
);
460 wined3d_cs_destroy_object(device
->cs
, wined3d_shader_resource_view_destroy_object
, view
);
461 wined3d_resource_decref(resource
);
467 void * CDECL
wined3d_shader_resource_view_get_parent(const struct wined3d_shader_resource_view
*view
)
469 TRACE("view %p.\n", view
);
474 static void wined3d_shader_resource_view_cs_init(void *object
)
476 struct wined3d_shader_resource_view
*view
= object
;
477 struct wined3d_resource
*resource
= view
->resource
;
478 const struct wined3d_format
*view_format
;
479 const struct wined3d_gl_info
*gl_info
;
480 const struct wined3d_view_desc
*desc
;
483 view_format
= view
->format
;
484 gl_info
= &resource
->device
->adapter
->gl_info
;
487 if (resource
->type
== WINED3D_RTYPE_BUFFER
)
489 struct wined3d_buffer
*buffer
= buffer_from_resource(resource
);
491 create_buffer_view(&view
->gl_view
, desc
, buffer
, view_format
);
495 struct wined3d_texture
*texture
= texture_from_resource(resource
);
497 view_target
= get_texture_view_target(gl_info
, desc
, texture
);
499 if (resource
->format
->id
== view_format
->id
&& texture
->target
== view_target
500 && !desc
->u
.texture
.level_idx
&& desc
->u
.texture
.level_count
== texture
->level_count
501 && !desc
->u
.texture
.layer_idx
&& desc
->u
.texture
.layer_count
== texture
->layer_count
502 && !is_stencil_view_format(view_format
))
504 TRACE("Creating identity shader resource view.\n");
506 else if (texture
->swapchain
&& texture
->swapchain
->desc
.backbuffer_count
> 1)
508 FIXME("Swapchain shader resource views not supported.\n");
510 else if (resource
->format
->typeless_id
== view_format
->typeless_id
511 && resource
->format
->gl_view_class
== view_format
->gl_view_class
)
513 create_texture_view(&view
->gl_view
, view_target
, desc
, texture
, view_format
);
517 FIXME("Shader resource view not supported, resource format %s, view format %s.\n",
518 debug_d3dformat(resource
->format
->id
), debug_d3dformat(view_format
->id
));
523 static HRESULT
wined3d_shader_resource_view_init(struct wined3d_shader_resource_view
*view
,
524 const struct wined3d_view_desc
*desc
, struct wined3d_resource
*resource
,
525 void *parent
, const struct wined3d_parent_ops
*parent_ops
)
527 const struct wined3d_gl_info
*gl_info
= &resource
->device
->adapter
->gl_info
;
528 const struct wined3d_format
*view_format
;
530 view_format
= wined3d_get_format(gl_info
, desc
->format_id
, resource
->usage
);
531 if (resource
->type
== WINED3D_RTYPE_BUFFER
&& desc
->flags
& WINED3D_VIEW_BUFFER_RAW
)
533 if (view_format
->id
!= WINED3DFMT_R32_TYPELESS
)
535 WARN("Invalid format %s for raw buffer view.\n", debug_d3dformat(view_format
->id
));
539 view_format
= wined3d_get_format(gl_info
, WINED3DFMT_R32_UINT
, resource
->usage
);
542 if (wined3d_format_is_typeless(view_format
))
544 WARN("Trying to create view for typeless format %s.\n", debug_d3dformat(view_format
->id
));
548 if (resource
->type
== WINED3D_RTYPE_BUFFER
)
550 struct wined3d_buffer
*buffer
= buffer_from_resource(resource
);
551 unsigned int buffer_size
, element_size
;
553 if (buffer
->desc
.structure_byte_stride
)
555 if (desc
->format_id
!= WINED3DFMT_UNKNOWN
)
557 WARN("Invalid format %s for structured buffer view.\n", debug_d3dformat(desc
->format_id
));
561 view_format
= wined3d_get_format(gl_info
, WINED3DFMT_R32_UINT
, resource
->usage
);
562 element_size
= buffer
->desc
.structure_byte_stride
;
566 element_size
= view_format
->byte_count
;
572 buffer_size
= buffer
->resource
.size
/ element_size
;
573 if (desc
->u
.buffer
.start_idx
>= buffer_size
574 || desc
->u
.buffer
.count
> buffer_size
- desc
->u
.buffer
.start_idx
)
579 struct wined3d_texture
*texture
= texture_from_resource(resource
);
581 if (!desc
->u
.texture
.level_count
582 || desc
->u
.texture
.level_idx
>= texture
->level_count
583 || desc
->u
.texture
.level_count
> texture
->level_count
- desc
->u
.texture
.level_idx
584 || !desc
->u
.texture
.layer_count
585 || desc
->u
.texture
.layer_idx
>= texture
->layer_count
586 || desc
->u
.texture
.layer_count
> texture
->layer_count
- desc
->u
.texture
.layer_idx
)
591 wined3d_resource_incref(view
->resource
= resource
);
592 view
->parent
= parent
;
593 view
->parent_ops
= parent_ops
;
594 view
->format
= view_format
;
597 wined3d_cs_init_object(resource
->device
->cs
, wined3d_shader_resource_view_cs_init
, view
);
602 HRESULT CDECL
wined3d_shader_resource_view_create(const struct wined3d_view_desc
*desc
,
603 struct wined3d_resource
*resource
, void *parent
, const struct wined3d_parent_ops
*parent_ops
,
604 struct wined3d_shader_resource_view
**view
)
606 struct wined3d_shader_resource_view
*object
;
609 TRACE("desc %p, resource %p, parent %p, parent_ops %p, view %p.\n",
610 desc
, resource
, parent
, parent_ops
, view
);
612 if (!(object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
))))
613 return E_OUTOFMEMORY
;
615 if (FAILED(hr
= wined3d_shader_resource_view_init(object
, desc
, resource
, parent
, parent_ops
)))
617 HeapFree(GetProcessHeap(), 0, object
);
618 WARN("Failed to initialise view, hr %#x.\n", hr
);
622 TRACE("Created shader resource view %p.\n", object
);
628 void wined3d_shader_resource_view_bind(struct wined3d_shader_resource_view
*view
,
629 struct wined3d_context
*context
)
631 struct wined3d_texture
*texture
;
633 if (view
->gl_view
.name
)
635 context_bind_texture(context
, view
->gl_view
.target
, view
->gl_view
.name
);
639 if (view
->resource
->type
== WINED3D_RTYPE_BUFFER
)
641 FIXME("Buffer shader resources not supported.\n");
645 texture
= wined3d_texture_from_resource(view
->resource
);
646 wined3d_texture_bind(texture
, context
, FALSE
);
649 ULONG CDECL
wined3d_unordered_access_view_incref(struct wined3d_unordered_access_view
*view
)
651 ULONG refcount
= InterlockedIncrement(&view
->refcount
);
653 TRACE("%p increasing refcount to %u.\n", view
, refcount
);
658 static void wined3d_unordered_access_view_destroy_object(void *object
)
660 HeapFree(GetProcessHeap(), 0, object
);
663 ULONG CDECL
wined3d_unordered_access_view_decref(struct wined3d_unordered_access_view
*view
)
665 ULONG refcount
= InterlockedDecrement(&view
->refcount
);
667 TRACE("%p decreasing refcount to %u.\n", view
, refcount
);
671 struct wined3d_resource
*resource
= view
->resource
;
672 struct wined3d_device
*device
= resource
->device
;
674 /* Call wined3d_object_destroyed() before releasing the resource,
675 * since releasing the resource may end up destroying the parent. */
676 view
->parent_ops
->wined3d_object_destroyed(view
->parent
);
677 wined3d_cs_destroy_object(device
->cs
, wined3d_unordered_access_view_destroy_object
, view
);
678 wined3d_resource_decref(resource
);
684 void * CDECL
wined3d_unordered_access_view_get_parent(const struct wined3d_unordered_access_view
*view
)
686 TRACE("view %p.\n", view
);
691 void wined3d_unordered_access_view_invalidate_location(struct wined3d_unordered_access_view
*view
,
694 struct wined3d_resource
*resource
= view
->resource
;
695 unsigned int i
, sub_resource_idx
, layer_count
;
696 struct wined3d_texture
*texture
;
698 if (resource
->type
== WINED3D_RTYPE_BUFFER
)
700 wined3d_buffer_invalidate_location(buffer_from_resource(resource
), location
);
704 texture
= texture_from_resource(resource
);
706 sub_resource_idx
= view
->desc
.u
.texture
.layer_idx
* texture
->level_count
+ view
->desc
.u
.texture
.level_idx
;
707 layer_count
= (resource
->type
!= WINED3D_RTYPE_TEXTURE_3D
) ? view
->desc
.u
.texture
.layer_count
: 1;
708 for (i
= 0; i
< layer_count
; ++i
, sub_resource_idx
+= texture
->level_count
)
709 wined3d_texture_invalidate_location(texture
, sub_resource_idx
, location
);
712 static void wined3d_unordered_access_view_cs_init(void *object
)
714 struct wined3d_unordered_access_view
*view
= object
;
715 struct wined3d_resource
*resource
= view
->resource
;
716 struct wined3d_view_desc
*desc
= &view
->desc
;
717 const struct wined3d_gl_info
*gl_info
;
719 gl_info
= &resource
->device
->adapter
->gl_info
;
721 if (resource
->type
== WINED3D_RTYPE_BUFFER
)
723 struct wined3d_buffer
*buffer
= buffer_from_resource(resource
);
725 create_buffer_view(&view
->gl_view
, desc
, buffer
, view
->format
);
729 struct wined3d_texture
*texture
= texture_from_resource(resource
);
730 unsigned int depth_or_layer_count
;
732 if (resource
->type
== WINED3D_RTYPE_TEXTURE_3D
)
733 depth_or_layer_count
= wined3d_texture_get_level_depth(texture
, desc
->u
.texture
.level_idx
);
735 depth_or_layer_count
= texture
->layer_count
;
737 if (desc
->u
.texture
.layer_idx
|| desc
->u
.texture
.layer_count
!= depth_or_layer_count
)
739 create_texture_view(&view
->gl_view
, get_texture_view_target(gl_info
, desc
, texture
),
740 desc
, texture
, view
->format
);
745 static HRESULT
wined3d_unordered_access_view_init(struct wined3d_unordered_access_view
*view
,
746 const struct wined3d_view_desc
*desc
, struct wined3d_resource
*resource
,
747 void *parent
, const struct wined3d_parent_ops
*parent_ops
)
749 const struct wined3d_gl_info
*gl_info
= &resource
->device
->adapter
->gl_info
;
752 view
->parent
= parent
;
753 view
->parent_ops
= parent_ops
;
755 view
->format
= wined3d_get_format(gl_info
, desc
->format_id
, resource
->usage
);
758 if (resource
->type
== WINED3D_RTYPE_BUFFER
&& desc
->flags
& WINED3D_VIEW_BUFFER_RAW
)
760 if (view
->format
->id
!= WINED3DFMT_R32_TYPELESS
)
762 WARN("Invalid format %s for raw buffer view.\n", debug_d3dformat(view
->format
->id
));
766 view
->format
= wined3d_get_format(gl_info
, WINED3DFMT_R32_UINT
, resource
->usage
);
769 if (wined3d_format_is_typeless(view
->format
))
771 WARN("Trying to create view for typeless format %s.\n", debug_d3dformat(view
->format
->id
));
775 if (resource
->type
== WINED3D_RTYPE_BUFFER
)
777 struct wined3d_buffer
*buffer
= buffer_from_resource(resource
);
778 unsigned int buffer_size
, element_size
;
780 if (buffer
->desc
.structure_byte_stride
)
782 if (desc
->format_id
!= WINED3DFMT_UNKNOWN
)
784 WARN("Invalid format %s for structured buffer view.\n", debug_d3dformat(desc
->format_id
));
788 view
->format
= wined3d_get_format(gl_info
, WINED3DFMT_R32_UINT
, resource
->usage
);
789 element_size
= buffer
->desc
.structure_byte_stride
;
793 element_size
= view
->format
->byte_count
;
799 buffer_size
= buffer
->resource
.size
/ element_size
;
800 if (desc
->u
.buffer
.start_idx
>= buffer_size
801 || desc
->u
.buffer
.count
> buffer_size
- desc
->u
.buffer
.start_idx
)
806 struct wined3d_texture
*texture
= texture_from_resource(resource
);
807 unsigned int depth_or_layer_count
;
809 if (resource
->type
== WINED3D_RTYPE_TEXTURE_3D
)
810 depth_or_layer_count
= wined3d_texture_get_level_depth(texture
, desc
->u
.texture
.level_idx
);
812 depth_or_layer_count
= texture
->layer_count
;
814 if (desc
->u
.texture
.level_idx
>= texture
->level_count
815 || desc
->u
.texture
.level_count
!= 1
816 || desc
->u
.texture
.layer_idx
>= depth_or_layer_count
817 || !desc
->u
.texture
.layer_count
818 || desc
->u
.texture
.layer_count
> depth_or_layer_count
- desc
->u
.texture
.layer_idx
)
821 wined3d_resource_incref(view
->resource
= resource
);
823 wined3d_cs_init_object(resource
->device
->cs
, wined3d_unordered_access_view_cs_init
, view
);
828 HRESULT CDECL
wined3d_unordered_access_view_create(const struct wined3d_view_desc
*desc
,
829 struct wined3d_resource
*resource
, void *parent
, const struct wined3d_parent_ops
*parent_ops
,
830 struct wined3d_unordered_access_view
**view
)
832 struct wined3d_unordered_access_view
*object
;
835 TRACE("desc %p, resource %p, parent %p, parent_ops %p, view %p.\n",
836 desc
, resource
, parent
, parent_ops
, view
);
838 if (!(object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
))))
839 return E_OUTOFMEMORY
;
841 if (FAILED(hr
= wined3d_unordered_access_view_init(object
, desc
, resource
, parent
, parent_ops
)))
843 HeapFree(GetProcessHeap(), 0, object
);
844 WARN("Failed to initialise view, hr %#x.\n", hr
);
848 TRACE("Created unordered access view %p.\n", object
);