2 * Copyright 2018 Collabora Ltd.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * on the rights to use, copy, modify, merge, publish, distribute, sub
8 * license, and/or sell copies of the Software, and to permit persons to whom
9 * the Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE.
24 #include "zink_resource.h"
26 #include "zink_batch.h"
27 #include "zink_context.h"
28 #include "zink_screen.h"
30 #include "util/slab.h"
31 #include "util/u_debug.h"
32 #include "util/format/u_format.h"
33 #include "util/u_transfer_helper.h"
34 #include "util/u_inlines.h"
35 #include "util/u_memory.h"
37 #include "frontend/sw_winsys.h"
40 zink_resource_destroy(struct pipe_screen
*pscreen
,
41 struct pipe_resource
*pres
)
43 struct zink_screen
*screen
= zink_screen(pscreen
);
44 struct zink_resource
*res
= zink_resource(pres
);
45 if (pres
->target
== PIPE_BUFFER
)
46 vkDestroyBuffer(screen
->dev
, res
->buffer
, NULL
);
48 vkDestroyImage(screen
->dev
, res
->image
, NULL
);
50 vkFreeMemory(screen
->dev
, res
->mem
, NULL
);
55 get_memory_type_index(struct zink_screen
*screen
,
56 const VkMemoryRequirements
*reqs
,
57 VkMemoryPropertyFlags props
)
59 for (uint32_t i
= 0u; i
< VK_MAX_MEMORY_TYPES
; i
++) {
60 if (((reqs
->memoryTypeBits
>> i
) & 1) == 1) {
61 if ((screen
->mem_props
.memoryTypes
[i
].propertyFlags
& props
) == props
) {
68 unreachable("Unsupported memory-type");
72 static VkImageAspectFlags
73 aspect_from_format(enum pipe_format fmt
)
75 if (util_format_is_depth_or_stencil(fmt
)) {
76 VkImageAspectFlags aspect
= 0;
77 const struct util_format_description
*desc
= util_format_description(fmt
);
78 if (util_format_has_depth(desc
))
79 aspect
|= VK_IMAGE_ASPECT_DEPTH_BIT
;
80 if (util_format_has_stencil(desc
))
81 aspect
|= VK_IMAGE_ASPECT_STENCIL_BIT
;
84 return VK_IMAGE_ASPECT_COLOR_BIT
;
87 static struct pipe_resource
*
88 resource_create(struct pipe_screen
*pscreen
,
89 const struct pipe_resource
*templ
,
90 struct winsys_handle
*whandle
,
91 unsigned external_usage
)
93 struct zink_screen
*screen
= zink_screen(pscreen
);
94 struct zink_resource
*res
= CALLOC_STRUCT(zink_resource
);
98 pipe_reference_init(&res
->base
.reference
, 1);
99 res
->base
.screen
= pscreen
;
101 VkMemoryRequirements reqs
;
102 VkMemoryPropertyFlags flags
= 0;
104 res
->internal_format
= templ
->format
;
105 if (templ
->target
== PIPE_BUFFER
) {
106 VkBufferCreateInfo bci
= {};
107 bci
.sType
= VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO
;
108 bci
.size
= templ
->width0
;
110 bci
.usage
= VK_BUFFER_USAGE_TRANSFER_SRC_BIT
|
111 VK_BUFFER_USAGE_TRANSFER_DST_BIT
;
113 if (templ
->bind
& PIPE_BIND_VERTEX_BUFFER
)
114 bci
.usage
|= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT
;
116 if (templ
->bind
& PIPE_BIND_INDEX_BUFFER
)
117 bci
.usage
|= VK_BUFFER_USAGE_INDEX_BUFFER_BIT
;
119 if (templ
->bind
& PIPE_BIND_CONSTANT_BUFFER
)
120 bci
.usage
|= VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT
;
122 if (templ
->bind
& PIPE_BIND_SHADER_BUFFER
)
123 bci
.usage
|= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
;
125 if (templ
->bind
& PIPE_BIND_COMMAND_ARGS_BUFFER
)
126 bci
.usage
|= VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT
;
128 if (templ
->bind
== (PIPE_BIND_STREAM_OUTPUT
| PIPE_BIND_CUSTOM
)) {
129 bci
.usage
|= VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT
;
130 } else if (templ
->bind
& PIPE_BIND_STREAM_OUTPUT
) {
131 bci
.usage
|= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT
| VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT
;
134 if (vkCreateBuffer(screen
->dev
, &bci
, NULL
, &res
->buffer
) !=
140 vkGetBufferMemoryRequirements(screen
->dev
, res
->buffer
, &reqs
);
141 flags
|= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
;
143 res
->format
= zink_get_format(screen
, templ
->format
);
145 VkImageCreateInfo ici
= {};
146 ici
.sType
= VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO
;
147 ici
.flags
= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT
;
149 switch (templ
->target
) {
150 case PIPE_TEXTURE_1D
:
151 case PIPE_TEXTURE_1D_ARRAY
:
152 ici
.imageType
= VK_IMAGE_TYPE_1D
;
155 case PIPE_TEXTURE_CUBE
:
156 case PIPE_TEXTURE_CUBE_ARRAY
:
157 ici
.flags
|= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT
;
159 case PIPE_TEXTURE_2D
:
160 case PIPE_TEXTURE_2D_ARRAY
:
161 case PIPE_TEXTURE_RECT
:
162 ici
.imageType
= VK_IMAGE_TYPE_2D
;
165 case PIPE_TEXTURE_3D
:
166 ici
.imageType
= VK_IMAGE_TYPE_3D
;
167 if (templ
->bind
& PIPE_BIND_RENDER_TARGET
)
168 ici
.flags
|= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT
;
172 unreachable("PIPE_BUFFER should already be handled");
175 unreachable("Unknown target");
178 ici
.format
= res
->format
;
179 ici
.extent
.width
= templ
->width0
;
180 ici
.extent
.height
= templ
->height0
;
181 ici
.extent
.depth
= templ
->depth0
;
182 ici
.mipLevels
= templ
->last_level
+ 1;
183 ici
.arrayLayers
= MAX2(templ
->array_size
, 1);
184 ici
.samples
= templ
->nr_samples
? templ
->nr_samples
: VK_SAMPLE_COUNT_1_BIT
;
185 ici
.tiling
= templ
->bind
& PIPE_BIND_LINEAR
? VK_IMAGE_TILING_LINEAR
: VK_IMAGE_TILING_OPTIMAL
;
187 if (templ
->target
== PIPE_TEXTURE_CUBE
||
188 templ
->target
== PIPE_TEXTURE_CUBE_ARRAY
)
189 ici
.arrayLayers
*= 6;
191 if (templ
->bind
& PIPE_BIND_SHARED
)
192 ici
.tiling
= VK_IMAGE_TILING_LINEAR
;
194 if (templ
->usage
== PIPE_USAGE_STAGING
)
195 ici
.tiling
= VK_IMAGE_TILING_LINEAR
;
197 /* sadly, gallium doesn't let us know if it'll ever need this, so we have to assume */
198 ici
.usage
= VK_IMAGE_USAGE_TRANSFER_SRC_BIT
|
199 VK_IMAGE_USAGE_TRANSFER_DST_BIT
|
200 VK_IMAGE_USAGE_SAMPLED_BIT
;
202 if (templ
->bind
& PIPE_BIND_SHADER_IMAGE
)
203 ici
.usage
|= VK_IMAGE_USAGE_STORAGE_BIT
;
205 if (templ
->bind
& PIPE_BIND_RENDER_TARGET
)
206 ici
.usage
|= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
;
208 if (templ
->bind
& PIPE_BIND_DEPTH_STENCIL
)
209 ici
.usage
|= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
;
211 if (templ
->flags
& PIPE_RESOURCE_FLAG_SPARSE
)
212 ici
.usage
|= VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT
;
214 if (templ
->bind
& PIPE_BIND_STREAM_OUTPUT
)
215 ici
.usage
|= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT
;
217 ici
.sharingMode
= VK_SHARING_MODE_EXCLUSIVE
;
218 ici
.initialLayout
= VK_IMAGE_LAYOUT_UNDEFINED
;
219 res
->layout
= VK_IMAGE_LAYOUT_UNDEFINED
;
221 VkResult result
= vkCreateImage(screen
->dev
, &ici
, NULL
, &res
->image
);
222 if (result
!= VK_SUCCESS
) {
227 res
->optimial_tiling
= ici
.tiling
!= VK_IMAGE_TILING_LINEAR
;
228 res
->aspect
= aspect_from_format(templ
->format
);
230 vkGetImageMemoryRequirements(screen
->dev
, res
->image
, &reqs
);
231 if (templ
->usage
== PIPE_USAGE_STAGING
|| (screen
->winsys
&& (templ
->bind
& (PIPE_BIND_SCANOUT
|PIPE_BIND_DISPLAY_TARGET
|PIPE_BIND_SHARED
))))
232 flags
|= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
;
234 flags
|= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
;
237 VkMemoryAllocateInfo mai
= {};
238 mai
.sType
= VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO
;
239 mai
.allocationSize
= reqs
.size
;
240 mai
.memoryTypeIndex
= get_memory_type_index(screen
, &reqs
, flags
);
242 VkExportMemoryAllocateInfo emai
= {};
243 if (templ
->bind
& PIPE_BIND_SHARED
) {
244 emai
.sType
= VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO
;
245 emai
.handleTypes
= VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT
;
249 VkImportMemoryFdInfoKHR imfi
= {
250 VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR
,
254 if (whandle
&& whandle
->type
== WINSYS_HANDLE_TYPE_FD
) {
256 imfi
.handleType
= VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT
;
257 imfi
.fd
= whandle
->handle
;
262 if (vkAllocateMemory(screen
->dev
, &mai
, NULL
, &res
->mem
) != VK_SUCCESS
)
266 res
->size
= reqs
.size
;
268 if (templ
->target
== PIPE_BUFFER
)
269 vkBindBufferMemory(screen
->dev
, res
->buffer
, res
->mem
, res
->offset
);
271 vkBindImageMemory(screen
->dev
, res
->image
, res
->mem
, res
->offset
);
273 if (screen
->winsys
&& (templ
->bind
& (PIPE_BIND_DISPLAY_TARGET
|
275 PIPE_BIND_SHARED
))) {
276 struct sw_winsys
*winsys
= screen
->winsys
;
277 res
->dt
= winsys
->displaytarget_create(screen
->winsys
,
289 if (templ
->target
== PIPE_BUFFER
)
290 vkDestroyBuffer(screen
->dev
, res
->buffer
, NULL
);
292 vkDestroyImage(screen
->dev
, res
->image
, NULL
);
299 static struct pipe_resource
*
300 zink_resource_create(struct pipe_screen
*pscreen
,
301 const struct pipe_resource
*templ
)
303 return resource_create(pscreen
, templ
, NULL
, 0);
307 zink_resource_get_handle(struct pipe_screen
*pscreen
,
308 struct pipe_context
*context
,
309 struct pipe_resource
*tex
,
310 struct winsys_handle
*whandle
,
313 struct zink_resource
*res
= zink_resource(tex
);
314 struct zink_screen
*screen
= zink_screen(pscreen
);
315 VkMemoryGetFdInfoKHR fd_info
= {};
318 if (res
->base
.target
!= PIPE_BUFFER
) {
319 VkImageSubresource sub_res
= {};
320 VkSubresourceLayout sub_res_layout
= {};
322 sub_res
.aspectMask
= res
->aspect
;
324 vkGetImageSubresourceLayout(screen
->dev
, res
->image
, &sub_res
, &sub_res_layout
);
326 whandle
->stride
= sub_res_layout
.rowPitch
;
329 if (whandle
->type
== WINSYS_HANDLE_TYPE_FD
) {
330 fd_info
.sType
= VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR
;
331 fd_info
.memory
= res
->mem
;
332 fd_info
.handleType
= VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT
;
333 VkResult result
= (*screen
->vk_GetMemoryFdKHR
)(screen
->dev
, &fd_info
, &fd
);
334 if (result
!= VK_SUCCESS
)
336 whandle
->handle
= fd
;
341 static struct pipe_resource
*
342 zink_resource_from_handle(struct pipe_screen
*pscreen
,
343 const struct pipe_resource
*templ
,
344 struct winsys_handle
*whandle
,
347 return resource_create(pscreen
, templ
, whandle
, usage
);
351 zink_transfer_copy_bufimage(struct zink_context
*ctx
,
352 struct zink_resource
*res
,
353 struct zink_resource
*staging_res
,
354 struct zink_transfer
*trans
,
357 struct zink_batch
*batch
= zink_batch_no_rp(ctx
);
360 if (res
->layout
!= VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
) {
361 zink_resource_barrier(batch
->cmdbuf
, res
, res
->aspect
,
362 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
);
365 if (res
->layout
!= VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
) {
366 zink_resource_barrier(batch
->cmdbuf
, res
, res
->aspect
,
367 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
);
371 VkBufferImageCopy copyRegion
= {};
372 copyRegion
.bufferOffset
= staging_res
->offset
;
373 copyRegion
.bufferRowLength
= 0;
374 copyRegion
.bufferImageHeight
= 0;
375 copyRegion
.imageSubresource
.mipLevel
= trans
->base
.level
;
376 copyRegion
.imageSubresource
.layerCount
= 1;
377 if (res
->base
.array_size
> 1) {
378 copyRegion
.imageSubresource
.baseArrayLayer
= trans
->base
.box
.z
;
379 copyRegion
.imageSubresource
.layerCount
= trans
->base
.box
.depth
;
380 copyRegion
.imageExtent
.depth
= 1;
382 copyRegion
.imageOffset
.z
= trans
->base
.box
.z
;
383 copyRegion
.imageExtent
.depth
= trans
->base
.box
.depth
;
385 copyRegion
.imageOffset
.x
= trans
->base
.box
.x
;
386 copyRegion
.imageOffset
.y
= trans
->base
.box
.y
;
388 copyRegion
.imageExtent
.width
= trans
->base
.box
.width
;
389 copyRegion
.imageExtent
.height
= trans
->base
.box
.height
;
391 zink_batch_reference_resoure(batch
, res
);
392 zink_batch_reference_resoure(batch
, staging_res
);
394 /* we're using u_transfer_helper_deinterleave, which means we'll be getting PIPE_TRANSFER_* usage
395 * to indicate whether to copy either the depth or stencil aspects
397 unsigned aspects
= 0;
398 assert((trans
->base
.usage
& (PIPE_TRANSFER_DEPTH_ONLY
| PIPE_TRANSFER_STENCIL_ONLY
)) !=
399 (PIPE_TRANSFER_DEPTH_ONLY
| PIPE_TRANSFER_STENCIL_ONLY
));
400 if (trans
->base
.usage
& PIPE_TRANSFER_DEPTH_ONLY
)
401 aspects
= VK_IMAGE_ASPECT_DEPTH_BIT
;
402 else if (trans
->base
.usage
& PIPE_TRANSFER_STENCIL_ONLY
)
403 aspects
= VK_IMAGE_ASPECT_STENCIL_BIT
;
405 aspects
= aspect_from_format(res
->base
.format
);
408 int aspect
= 1 << u_bit_scan(&aspects
);
409 copyRegion
.imageSubresource
.aspectMask
= aspect
;
412 vkCmdCopyBufferToImage(batch
->cmdbuf
, staging_res
->buffer
, res
->image
, res
->layout
, 1, ©Region
);
414 vkCmdCopyImageToBuffer(batch
->cmdbuf
, res
->image
, res
->layout
, staging_res
->buffer
, 1, ©Region
);
421 zink_transfer_map(struct pipe_context
*pctx
,
422 struct pipe_resource
*pres
,
425 const struct pipe_box
*box
,
426 struct pipe_transfer
**transfer
)
428 struct zink_context
*ctx
= zink_context(pctx
);
429 struct zink_screen
*screen
= zink_screen(pctx
->screen
);
430 struct zink_resource
*res
= zink_resource(pres
);
432 struct zink_transfer
*trans
= slab_alloc(&ctx
->transfer_pool
);
436 memset(trans
, 0, sizeof(*trans
));
437 pipe_resource_reference(&trans
->base
.resource
, pres
);
439 trans
->base
.resource
= pres
;
440 trans
->base
.level
= level
;
441 trans
->base
.usage
= usage
;
442 trans
->base
.box
= *box
;
445 if (pres
->target
== PIPE_BUFFER
) {
446 if (usage
& PIPE_TRANSFER_READ
) {
447 /* need to wait for rendering to finish
448 * TODO: optimize/fix this to be much less obtrusive
451 struct pipe_fence_handle
*fence
= NULL
;
452 pctx
->flush(pctx
, &fence
, PIPE_FLUSH_HINT_FINISH
);
454 pctx
->screen
->fence_finish(pctx
->screen
, NULL
, fence
,
455 PIPE_TIMEOUT_INFINITE
);
456 pctx
->screen
->fence_reference(pctx
->screen
, &fence
, NULL
);
461 VkResult result
= vkMapMemory(screen
->dev
, res
->mem
, res
->offset
, res
->size
, 0, &ptr
);
462 if (result
!= VK_SUCCESS
)
465 trans
->base
.stride
= 0;
466 trans
->base
.layer_stride
= 0;
467 ptr
= ((uint8_t *)ptr
) + box
->x
;
469 if (res
->optimial_tiling
|| ((res
->base
.usage
!= PIPE_USAGE_STAGING
))) {
470 enum pipe_format format
= pres
->format
;
471 if (usage
& PIPE_TRANSFER_DEPTH_ONLY
)
472 format
= util_format_get_depth_only(pres
->format
);
473 else if (usage
& PIPE_TRANSFER_STENCIL_ONLY
)
474 format
= PIPE_FORMAT_S8_UINT
;
475 trans
->base
.stride
= util_format_get_stride(format
, box
->width
);
476 trans
->base
.layer_stride
= util_format_get_2d_size(format
,
480 struct pipe_resource templ
= *pres
;
481 templ
.format
= format
;
482 templ
.usage
= PIPE_USAGE_STAGING
;
483 templ
.target
= PIPE_BUFFER
;
485 templ
.width0
= trans
->base
.layer_stride
* box
->depth
;
486 templ
.height0
= templ
.depth0
= 0;
487 templ
.last_level
= 0;
488 templ
.array_size
= 1;
491 trans
->staging_res
= zink_resource_create(pctx
->screen
, &templ
);
492 if (!trans
->staging_res
)
495 struct zink_resource
*staging_res
= zink_resource(trans
->staging_res
);
497 if (usage
& PIPE_TRANSFER_READ
) {
498 struct zink_context
*ctx
= zink_context(pctx
);
499 bool ret
= zink_transfer_copy_bufimage(ctx
, res
,
505 /* need to wait for rendering to finish */
506 struct pipe_fence_handle
*fence
= NULL
;
507 pctx
->flush(pctx
, &fence
, PIPE_FLUSH_HINT_FINISH
);
509 pctx
->screen
->fence_finish(pctx
->screen
, NULL
, fence
,
510 PIPE_TIMEOUT_INFINITE
);
511 pctx
->screen
->fence_reference(pctx
->screen
, &fence
, NULL
);
515 VkResult result
= vkMapMemory(screen
->dev
, staging_res
->mem
,
517 staging_res
->size
, 0, &ptr
);
518 if (result
!= VK_SUCCESS
)
522 assert(!res
->optimial_tiling
);
523 VkResult result
= vkMapMemory(screen
->dev
, res
->mem
, res
->offset
, res
->size
, 0, &ptr
);
524 if (result
!= VK_SUCCESS
)
526 VkImageSubresource isr
= {
531 VkSubresourceLayout srl
;
532 vkGetImageSubresourceLayout(screen
->dev
, res
->image
, &isr
, &srl
);
533 trans
->base
.stride
= srl
.rowPitch
;
534 trans
->base
.layer_stride
= srl
.arrayPitch
;
535 ptr
= ((uint8_t *)ptr
) + box
->z
* srl
.depthPitch
+
536 box
->y
* srl
.rowPitch
+
541 *transfer
= &trans
->base
;
546 zink_transfer_unmap(struct pipe_context
*pctx
,
547 struct pipe_transfer
*ptrans
)
549 struct zink_context
*ctx
= zink_context(pctx
);
550 struct zink_screen
*screen
= zink_screen(pctx
->screen
);
551 struct zink_resource
*res
= zink_resource(ptrans
->resource
);
552 struct zink_transfer
*trans
= (struct zink_transfer
*)ptrans
;
553 if (trans
->staging_res
) {
554 struct zink_resource
*staging_res
= zink_resource(trans
->staging_res
);
555 vkUnmapMemory(screen
->dev
, staging_res
->mem
);
557 if (trans
->base
.usage
& PIPE_TRANSFER_WRITE
) {
558 struct zink_context
*ctx
= zink_context(pctx
);
560 zink_transfer_copy_bufimage(ctx
, res
, staging_res
, trans
, true);
563 pipe_resource_reference(&trans
->staging_res
, NULL
);
565 vkUnmapMemory(screen
->dev
, res
->mem
);
567 pipe_resource_reference(&trans
->base
.resource
, NULL
);
568 slab_free(&ctx
->transfer_pool
, ptrans
);
571 static struct pipe_resource
*
572 zink_resource_get_separate_stencil(struct pipe_resource
*pres
)
574 /* For packed depth-stencil, we treat depth as the primary resource
575 * and store S8 as the "second plane" resource.
577 if (pres
->next
&& pres
->next
->format
== PIPE_FORMAT_S8_UINT
)
585 zink_get_depth_stencil_resources(struct pipe_resource
*res
,
586 struct zink_resource
**out_z
,
587 struct zink_resource
**out_s
)
590 if (out_z
) *out_z
= NULL
;
591 if (out_s
) *out_s
= NULL
;
595 if (res
->format
!= PIPE_FORMAT_S8_UINT
) {
596 if (out_z
) *out_z
= zink_resource(res
);
597 if (out_s
) *out_s
= zink_resource(zink_resource_get_separate_stencil(res
));
599 if (out_z
) *out_z
= NULL
;
600 if (out_s
) *out_s
= zink_resource(res
);
605 zink_resource_set_separate_stencil(struct pipe_resource
*pres
,
606 struct pipe_resource
*stencil
)
608 assert(util_format_has_depth(util_format_description(pres
->format
)));
609 pipe_resource_reference(&pres
->next
, stencil
);
612 static enum pipe_format
613 zink_resource_get_internal_format(struct pipe_resource
*pres
)
615 struct zink_resource
*res
= zink_resource(pres
);
616 return res
->internal_format
;
619 static const struct u_transfer_vtbl transfer_vtbl
= {
620 .resource_create
= zink_resource_create
,
621 .resource_destroy
= zink_resource_destroy
,
622 .transfer_map
= zink_transfer_map
,
623 .transfer_unmap
= zink_transfer_unmap
,
624 .transfer_flush_region
= u_default_transfer_flush_region
,
625 .get_internal_format
= zink_resource_get_internal_format
,
626 .set_stencil
= zink_resource_set_separate_stencil
,
627 .get_stencil
= zink_resource_get_separate_stencil
,
631 zink_screen_resource_init(struct pipe_screen
*pscreen
)
633 pscreen
->resource_create
= zink_resource_create
;
634 pscreen
->resource_destroy
= zink_resource_destroy
;
635 pscreen
->transfer_helper
= u_transfer_helper_create(&transfer_vtbl
, true, true, false, false);
637 if (zink_screen(pscreen
)->have_KHR_external_memory_fd
) {
638 pscreen
->resource_get_handle
= zink_resource_get_handle
;
639 pscreen
->resource_from_handle
= zink_resource_from_handle
;
644 zink_context_resource_init(struct pipe_context
*pctx
)
646 pctx
->transfer_map
= u_transfer_helper_deinterleave_transfer_map
;
647 pctx
->transfer_unmap
= u_transfer_helper_deinterleave_transfer_unmap
;
649 pctx
->transfer_flush_region
= u_transfer_helper_transfer_flush_region
;
650 pctx
->buffer_subdata
= u_default_buffer_subdata
;
651 pctx
->texture_subdata
= u_default_texture_subdata
;