mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-08 09:08:10 +02:00
panvk: Enable YCbCr support for v10+
Signed-off-by: Rebecca Mckeever <rebecca.mckeever@collabora.com> Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32563>
This commit is contained in:
parent
a9759dd0e4
commit
e8c6e22e14
6 changed files with 215 additions and 27 deletions
|
|
@ -450,7 +450,7 @@ Vulkan 1.1 -- all DONE: anv, lvp, nvk, panvk/v10+, radv, tu, vn
|
|||
VK_KHR_maintenance3 DONE (anv, dzn, hasvk, lvp, nvk, panvk, radv, tu, v3dv, vn)
|
||||
VK_KHR_multiview DONE (anv, dzn, hasvk, lvp, nvk, panvk/v10+, radv, tu, v3dv, vn)
|
||||
VK_KHR_relaxed_block_layout DONE (anv, dzn, hasvk, lvp, nvk, panvk, radv, tu, v3dv, vn)
|
||||
VK_KHR_sampler_ycbcr_conversion DONE (anv, hasvk, lvp, nvk, radv, tu, v3dv, vn)
|
||||
VK_KHR_sampler_ycbcr_conversion DONE (anv, hasvk, lvp, nvk, panvk/v10+, radv, tu, v3dv, vn)
|
||||
VK_KHR_shader_draw_parameters DONE (anv, dzn, hasvk, lvp, nvk, radv, tu, vn, panvk)
|
||||
VK_KHR_storage_buffer_storage_class DONE (anv, dzn, hasvk, lvp, nvk, panvk, radv, tu, v3dv, vn)
|
||||
VK_KHR_variable_pointers DONE (anv, hasvk, lvp, nvk, panvk, radv, tu, v3dv, vn)
|
||||
|
|
@ -507,7 +507,7 @@ Vulkan 1.3 -- all DONE: anv, lvp, nvk, radv, tu, vn, v3dv
|
|||
VK_EXT_texel_buffer_alignment DONE (anv, hasvk, lvp, nvk, pvr, radv, tu, v3dv, vn)
|
||||
VK_EXT_texture_compression_astc_hdr DONE (vn)
|
||||
VK_EXT_tooling_info DONE (anv, hasvk, nvk, panvk, pvr, radv, tu, v3dv, vn)
|
||||
VK_EXT_ycbcr_2plane_444_formats DONE (anv, lvp, nvk, vn)
|
||||
VK_EXT_ycbcr_2plane_444_formats DONE (anv, lvp, nvk, panvk/v10+, vn)
|
||||
|
||||
Vulkan 1.4 -- all DONE: anv, lvp, nvk, radv/gfx8+, tu/a7xx+
|
||||
|
||||
|
|
@ -655,7 +655,7 @@ Khronos extensions that are not part of any Vulkan version:
|
|||
VK_EXT_transform_feedback DONE (anv, hasvk, lvp, nvk, radv, tu, vn)
|
||||
VK_EXT_vertex_attribute_divisor DONE (anv, dzn, hasvk, lvp, nvk, radv, tu, v3dv, vn)
|
||||
VK_EXT_vertex_input_dynamic_state DONE (anv, lvp, nvk, radv, tu, vn)
|
||||
VK_EXT_ycbcr_image_arrays DONE (anv, hasvk, lvp, nvk, radv)
|
||||
VK_EXT_ycbcr_image_arrays DONE (anv, hasvk, lvp, nvk, panvk/v10+, radv)
|
||||
VK_ANDROID_external_memory_android_hardware_buffer DONE (anv, radv, tu, vn)
|
||||
VK_ANDROID_native_buffer DONE (anv, radv, tu, v3dv, vn)
|
||||
VK_GOOGLE_decorate_string DONE (anv, hasvk, lvp, nvk, panvk, radv, tu)
|
||||
|
|
|
|||
|
|
@ -4,3 +4,6 @@ storageInputOutput16 on panvk
|
|||
VK_KHR_depth_stencil_resolve on panvk
|
||||
VK_KHR_separate_depth_stencil_layouts on panvk
|
||||
VK_EXT_separate_stencil_usage on panvk
|
||||
samplerYcbcrConversion on panvk/v10+
|
||||
ycbcr2plane444Formats on panvk/v10+
|
||||
ycbcrImageArrays on panvk/v10+
|
||||
|
|
|
|||
|
|
@ -45,6 +45,32 @@
|
|||
#include "vk_object.h"
|
||||
#include "vk_util.h"
|
||||
|
||||
static bool
|
||||
can_be_aliased_to_yuv_plane(const struct panvk_image *image)
|
||||
{
|
||||
if (!(image->vk.create_flags & VK_IMAGE_CREATE_ALIAS_BIT))
|
||||
return false;
|
||||
|
||||
VkFormat format = image->vk.format;
|
||||
|
||||
if (vk_format_is_depth_or_stencil(format) ||
|
||||
vk_format_is_alpha(format) ||
|
||||
vk_format_get_blockwidth(format) != 1 ||
|
||||
vk_format_get_blockheight(format) != 1)
|
||||
return false;
|
||||
|
||||
unsigned block_size = vk_format_get_blocksize(format);
|
||||
|
||||
switch (block_size) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 4:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
panvk_image_can_use_mod(struct panvk_image *image, uint64_t mod)
|
||||
{
|
||||
|
|
@ -102,6 +128,15 @@ panvk_image_can_use_mod(struct panvk_image *image, uint64_t mod)
|
|||
}
|
||||
|
||||
if (mod == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED) {
|
||||
/* Multiplanar YUV with U-interleaving isn't supported by the HW. We
|
||||
* also need to make sure images that can be aliased to planes of
|
||||
* multi-planar images remain compatible with the aliased images, so
|
||||
* don't allow U-interleaving for those either.
|
||||
*/
|
||||
if (vk_format_get_plane_count(image->vk.format) > 1 ||
|
||||
can_be_aliased_to_yuv_plane(image))
|
||||
return false;
|
||||
|
||||
/* If we're dealing with a compressed format that requires non-compressed
|
||||
* views we can't use U_INTERLEAVED tiling because the tiling is different
|
||||
* between compressed and non-compressed formats. If we wanted to support
|
||||
|
|
@ -218,10 +253,12 @@ panvk_image_init_layouts(struct panvk_image *image,
|
|||
image->plane_count = 2;
|
||||
|
||||
for (uint8_t plane = 0; plane < image->plane_count; plane++) {
|
||||
VkFormat format =
|
||||
(image->vk.format == VK_FORMAT_D32_SFLOAT_S8_UINT) ?
|
||||
((plane == 0) ? VK_FORMAT_D32_SFLOAT : VK_FORMAT_S8_UINT) :
|
||||
image->vk.format;
|
||||
VkFormat format;
|
||||
|
||||
if (image->vk.format == VK_FORMAT_D32_SFLOAT_S8_UINT)
|
||||
format = plane == 0 ? VK_FORMAT_D32_SFLOAT : VK_FORMAT_S8_UINT;
|
||||
else
|
||||
format = vk_format_get_plane_format(image->vk.format, plane);
|
||||
|
||||
struct pan_image_explicit_layout plane_layout;
|
||||
if (explicit_info)
|
||||
|
|
@ -233,8 +270,10 @@ panvk_image_init_layouts(struct panvk_image *image,
|
|||
image->planes[plane].layout = (struct pan_image_layout){
|
||||
.format = vk_format_to_pipe_format(format),
|
||||
.dim = panvk_image_type_to_mali_tex_dim(image->vk.image_type),
|
||||
.width = image->vk.extent.width,
|
||||
.height = image->vk.extent.height,
|
||||
.width = vk_format_get_plane_width(image->vk.format, plane,
|
||||
image->vk.extent.width),
|
||||
.height = vk_format_get_plane_height(image->vk.format, plane,
|
||||
image->vk.extent.height),
|
||||
.depth = image->vk.extent.depth,
|
||||
.array_size = image->vk.array_layers,
|
||||
.nr_samples = image->vk.samples,
|
||||
|
|
|
|||
|
|
@ -50,12 +50,16 @@ panvk_meta_copy_get_image_properties(struct panvk_image *img)
|
|||
{
|
||||
uint64_t mod = img->vk.drm_format_mod;
|
||||
enum pipe_format pfmt = vk_format_to_pipe_format(img->vk.format);
|
||||
unsigned blk_sz = util_format_get_blocksize(pfmt);
|
||||
struct vk_meta_copy_image_properties props;
|
||||
memset(&props, 0, sizeof(props));
|
||||
const struct vk_format_ycbcr_info *ycbcr_info =
|
||||
vk_format_get_ycbcr_info(img->vk.format);
|
||||
|
||||
if (drm_is_afbc(mod)) {
|
||||
if (!vk_format_is_depth_or_stencil(img->vk.format)) {
|
||||
if (ycbcr_info) {
|
||||
for (uint32_t p = 0; p < ycbcr_info->n_planes; p++)
|
||||
props.plane[p].view_format = ycbcr_info->planes[p].format;
|
||||
} else if (!vk_format_is_depth_or_stencil(img->vk.format)) {
|
||||
props.color.view_format = img->vk.format;
|
||||
} else {
|
||||
switch (img->vk.format) {
|
||||
|
|
@ -112,7 +116,17 @@ panvk_meta_copy_get_image_properties(struct panvk_image *img)
|
|||
assert(!"Invalid ZS format");
|
||||
break;
|
||||
}
|
||||
} else if (ycbcr_info) {
|
||||
for (uint32_t p = 0; p < ycbcr_info->n_planes; p++) {
|
||||
unsigned blk_sz =
|
||||
vk_format_get_blocksize(ycbcr_info->planes[p].format);
|
||||
|
||||
props.plane[p].view_format =
|
||||
panvk_meta_get_uint_format_for_blk_size(blk_sz);
|
||||
}
|
||||
} else {
|
||||
unsigned blk_sz = util_format_get_blocksize(pfmt);
|
||||
|
||||
props.color.view_format = panvk_meta_get_uint_format_for_blk_size(blk_sz);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -209,6 +209,7 @@ get_device_extensions(const struct panvk_physical_device *device,
|
|||
.KHR_push_descriptor = true,
|
||||
.KHR_relaxed_block_layout = true,
|
||||
.KHR_sampler_mirror_clamp_to_edge = true,
|
||||
.KHR_sampler_ycbcr_conversion = arch >= 10,
|
||||
.KHR_separate_depth_stencil_layouts = true,
|
||||
.KHR_shader_draw_parameters = true,
|
||||
.KHR_shader_expect_assume = true,
|
||||
|
|
@ -250,6 +251,8 @@ get_device_extensions(const struct panvk_physical_device *device,
|
|||
.EXT_shader_module_identifier = true,
|
||||
.EXT_subgroup_size_control = arch >= 10, /* requires vk1.1 */
|
||||
.EXT_tooling_info = true,
|
||||
.EXT_ycbcr_2plane_444_formats = arch >= 10,
|
||||
.EXT_ycbcr_image_arrays = arch >= 10,
|
||||
.GOOGLE_decorate_string = true,
|
||||
.GOOGLE_hlsl_functionality1 = true,
|
||||
.GOOGLE_user_type = true,
|
||||
|
|
@ -298,7 +301,7 @@ get_features(const struct panvk_physical_device *device,
|
|||
.variablePointersStorageBuffer = true,
|
||||
.variablePointers = true,
|
||||
.protectedMemory = false,
|
||||
.samplerYcbcrConversion = false,
|
||||
.samplerYcbcrConversion = arch >= 10,
|
||||
.shaderDrawParameters = true,
|
||||
|
||||
/* Vulkan 1.2 */
|
||||
|
|
@ -421,6 +424,12 @@ get_features(const struct panvk_physical_device *device,
|
|||
|
||||
/* VK_EXT_shader_module_identifier */
|
||||
.shaderModuleIdentifier = true,
|
||||
|
||||
/* VK_EXT_ycbcr_2plane_444_formats */
|
||||
.ycbcr2plane444Formats = arch >= 10,
|
||||
|
||||
/* VK_EXT_ycbcr_image_arrays */
|
||||
.ycbcrImageArrays = arch >= 10,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -1179,8 +1188,8 @@ format_is_supported(struct panvk_physical_device *physical_device,
|
|||
}
|
||||
|
||||
static VkFormatFeatureFlags
|
||||
get_image_format_features(struct panvk_physical_device *physical_device,
|
||||
VkFormat format)
|
||||
get_image_plane_format_features(struct panvk_physical_device *physical_device,
|
||||
VkFormat format)
|
||||
{
|
||||
VkFormatFeatureFlags features = 0;
|
||||
enum pipe_format pfmt = vk_format_to_pipe_format(format);
|
||||
|
|
@ -1193,9 +1202,7 @@ get_image_format_features(struct panvk_physical_device *physical_device,
|
|||
if (fmt.bind & PAN_BIND_SAMPLER_VIEW) {
|
||||
features |= VK_FORMAT_FEATURE_TRANSFER_SRC_BIT |
|
||||
VK_FORMAT_FEATURE_TRANSFER_DST_BIT |
|
||||
VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
|
||||
VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT |
|
||||
VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT;
|
||||
VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
|
||||
|
||||
if (arch >= 10)
|
||||
features |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT;
|
||||
|
|
@ -1231,6 +1238,74 @@ get_image_format_features(struct panvk_physical_device *physical_device,
|
|||
return features;
|
||||
}
|
||||
|
||||
static VkFormatFeatureFlags
|
||||
get_image_format_features(struct panvk_physical_device *physical_device,
|
||||
VkFormat format)
|
||||
{
|
||||
const struct vk_format_ycbcr_info *ycbcr_info =
|
||||
vk_format_get_ycbcr_info(format);
|
||||
const unsigned arch = pan_arch(physical_device->kmod.props.gpu_prod_id);
|
||||
|
||||
/* TODO: Bifrost YCbCr support */
|
||||
if (ycbcr_info && arch <= 7)
|
||||
return 0;
|
||||
|
||||
if (ycbcr_info == NULL)
|
||||
return get_image_plane_format_features(physical_device, format);
|
||||
|
||||
if (unsupported_yuv_format(vk_format_to_pipe_format(format)))
|
||||
return 0;
|
||||
|
||||
/* For multi-plane, we get the feature flags of each plane separately,
|
||||
* then take their intersection as the overall format feature flags
|
||||
*/
|
||||
VkFormatFeatureFlags features = ~0u;
|
||||
bool cosited_chroma = false;
|
||||
for (uint8_t plane = 0; plane < ycbcr_info->n_planes; plane++) {
|
||||
const struct vk_format_ycbcr_plane *plane_info =
|
||||
&ycbcr_info->planes[plane];
|
||||
features &=
|
||||
get_image_plane_format_features(physical_device, plane_info->format);
|
||||
if (plane_info->denominator_scales[0] > 1 ||
|
||||
plane_info->denominator_scales[1] > 1)
|
||||
cosited_chroma = true;
|
||||
}
|
||||
if (features == 0)
|
||||
return 0;
|
||||
|
||||
/* Uh... We really should be able to sample from YCbCr */
|
||||
assert(features & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT);
|
||||
assert(features & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT);
|
||||
|
||||
/* Siting is handled in the YCbCr lowering pass. */
|
||||
features |= VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT;
|
||||
if (cosited_chroma)
|
||||
features |= VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT;
|
||||
|
||||
/* These aren't allowed for YCbCr formats */
|
||||
features &= ~(VK_FORMAT_FEATURE_BLIT_SRC_BIT |
|
||||
VK_FORMAT_FEATURE_BLIT_DST_BIT |
|
||||
VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT |
|
||||
VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT |
|
||||
VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT);
|
||||
|
||||
/* This is supported on all YCbCr formats */
|
||||
features |=
|
||||
VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT;
|
||||
|
||||
if (ycbcr_info->n_planes > 1) {
|
||||
/* DISJOINT_BIT implies that each plane has its own separate binding,
|
||||
* while SEPARATE_RECONSTRUCTION_FILTER_BIT implies that luma and chroma
|
||||
* each have their own, separate filters, so these two bits make sense
|
||||
* for multi-planar formats only.
|
||||
*/
|
||||
features |= VK_FORMAT_FEATURE_DISJOINT_BIT |
|
||||
VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT;
|
||||
}
|
||||
|
||||
return features;
|
||||
}
|
||||
|
||||
static VkFormatFeatureFlags
|
||||
get_buffer_format_features(struct panvk_physical_device *physical_device,
|
||||
VkFormat format)
|
||||
|
|
@ -1316,15 +1391,12 @@ get_image_format_properties(struct panvk_physical_device *physical_device,
|
|||
VkImageUsageFlags stencil_usage =
|
||||
stencil_usage_info ? stencil_usage_info->stencilUsage : info->usage;
|
||||
VkImageUsageFlags all_usage = info->usage | stencil_usage;
|
||||
const struct vk_format_ycbcr_info *ycbcr_info =
|
||||
vk_format_get_ycbcr_info(info->format);
|
||||
|
||||
switch (info->tiling) {
|
||||
case VK_IMAGE_TILING_LINEAR:
|
||||
format_feature_flags =
|
||||
get_image_format_features(physical_device, info->format);
|
||||
break;
|
||||
case VK_IMAGE_TILING_OPTIMAL:
|
||||
format_feature_flags =
|
||||
get_image_format_features(physical_device, info->format);
|
||||
break;
|
||||
case VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT: {
|
||||
const VkPhysicalDeviceImageDrmFormatModifierInfoEXT *mod_info =
|
||||
|
|
@ -1340,18 +1412,35 @@ get_image_format_properties(struct panvk_physical_device *physical_device,
|
|||
*/
|
||||
if (util_format_is_depth_or_stencil(format))
|
||||
goto unsupported;
|
||||
|
||||
format_feature_flags =
|
||||
get_image_format_features(physical_device, info->format);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
unreachable("bad VkPhysicalDeviceImageFormatInfo2");
|
||||
}
|
||||
|
||||
/* For the purposes of these checks, we don't care about all the extra
|
||||
* YCbCr features and we just want the intersection of features available
|
||||
* to all planes of the given format.
|
||||
*/
|
||||
if (ycbcr_info == NULL) {
|
||||
format_feature_flags =
|
||||
get_image_format_features(physical_device, info->format);
|
||||
} else {
|
||||
format_feature_flags = ~0u;
|
||||
assert(ycbcr_info->n_planes > 0);
|
||||
for (uint8_t plane = 0; plane < ycbcr_info->n_planes; plane++) {
|
||||
const VkFormat plane_format = ycbcr_info->planes[plane].format;
|
||||
format_feature_flags &=
|
||||
get_image_format_features(physical_device, plane_format);
|
||||
}
|
||||
}
|
||||
|
||||
if (format_feature_flags == 0)
|
||||
goto unsupported;
|
||||
|
||||
if (ycbcr_info && info->type != VK_IMAGE_TYPE_2D)
|
||||
goto unsupported;
|
||||
|
||||
switch (info->type) {
|
||||
default:
|
||||
unreachable("bad vkimage type");
|
||||
|
|
@ -1378,8 +1467,11 @@ get_image_format_properties(struct panvk_physical_device *physical_device,
|
|||
break;
|
||||
}
|
||||
|
||||
if (ycbcr_info)
|
||||
maxMipLevels = 1;
|
||||
|
||||
if (info->tiling == VK_IMAGE_TILING_OPTIMAL &&
|
||||
info->type == VK_IMAGE_TYPE_2D &&
|
||||
info->type == VK_IMAGE_TYPE_2D && ycbcr_info == NULL &&
|
||||
(format_feature_flags &
|
||||
(VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT |
|
||||
VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) &&
|
||||
|
|
@ -1612,6 +1704,43 @@ panvk_GetPhysicalDeviceImageFormatProperties2(
|
|||
}
|
||||
}
|
||||
|
||||
const struct vk_format_ycbcr_info *ycbcr_info =
|
||||
vk_format_get_ycbcr_info(base_info->format);
|
||||
const unsigned plane_count =
|
||||
vk_format_get_plane_count(base_info->format);
|
||||
|
||||
/* From the Vulkan 1.3.259 spec, VkImageCreateInfo:
|
||||
*
|
||||
* VUID-VkImageCreateInfo-imageCreateFormatFeatures-02260
|
||||
*
|
||||
* "If format is a multi-planar format, and if imageCreateFormatFeatures
|
||||
* (as defined in Image Creation Limits) does not contain
|
||||
* VK_FORMAT_FEATURE_DISJOINT_BIT, then flags must not contain
|
||||
* VK_IMAGE_CREATE_DISJOINT_BIT"
|
||||
*
|
||||
* This is satisfied trivially because we support DISJOINT on all
|
||||
* multi-plane formats. Also,
|
||||
*
|
||||
* VUID-VkImageCreateInfo-format-01577
|
||||
*
|
||||
* "If format is not a multi-planar format, and flags does not include
|
||||
* VK_IMAGE_CREATE_ALIAS_BIT, flags must not contain
|
||||
* VK_IMAGE_CREATE_DISJOINT_BIT"
|
||||
*/
|
||||
if (plane_count == 1 &&
|
||||
!(base_info->flags & VK_IMAGE_CREATE_ALIAS_BIT) &&
|
||||
(base_info->flags & VK_IMAGE_CREATE_DISJOINT_BIT))
|
||||
goto fail;
|
||||
|
||||
if (ycbcr_info &&
|
||||
((base_info->flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT) ||
|
||||
(base_info->flags & VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT)))
|
||||
goto fail;
|
||||
|
||||
if ((base_info->flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT) &&
|
||||
(base_info->usage & VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT))
|
||||
goto fail;
|
||||
|
||||
if (ycbcr_props)
|
||||
ycbcr_props->combinedImageSamplerDescriptorCount = 1;
|
||||
|
||||
|
|
|
|||
|
|
@ -279,7 +279,10 @@ panvk_per_arch(CreateImageView)(VkDevice _device,
|
|||
.dim = panvk_view_type_to_mali_tex_dim(view->vk.view_type),
|
||||
.nr_samples = image->vk.samples,
|
||||
.first_level = view->vk.base_mip_level,
|
||||
.last_level = view->vk.base_mip_level + view->vk.level_count - 1,
|
||||
/* MIPmapping in YUV formats is not supported by the HW. */
|
||||
.last_level = vk_format_get_ycbcr_info(view->vk.format)
|
||||
? view->vk.base_mip_level
|
||||
: view->vk.base_mip_level + view->vk.level_count - 1,
|
||||
.first_layer = view->vk.base_array_layer,
|
||||
.last_layer = view->vk.base_array_layer + view->vk.layer_count - 1,
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue