Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions layers/core_checks/cc_image_layout.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* Copyright (c) 2015-2025 The Khronos Group Inc.
* Copyright (c) 2015-2025 Valve Corporation
* Copyright (c) 2015-2025 LunarG, Inc.
/* Copyright (c) 2015-2026 The Khronos Group Inc.
* Copyright (c) 2015-2026 Valve Corporation
* Copyright (c) 2015-2026 LunarG, Inc.
* Copyright (C) 2015-2025 Google Inc.
* Modifications Copyright (C) 2020-2022 Advanced Micro Devices, Inc. All rights reserved.
*
Expand Down Expand Up @@ -835,16 +835,16 @@ void CoreChecks::TransitionBeginRenderPassLayouts(vvl::CommandBuffer &cb_state,
vku::FindStructInPNextChain<VkAttachmentDescriptionStencilLayout>(rpci->pAttachments[i].pNext);
if (attachment_description_stencil_layout) {
const auto stencil_initial_layout = attachment_description_stencil_layout->stencilInitialLayout;
VkImageSubresourceRange sub_range = view_state->normalized_subresource_range;
VkImageSubresourceRange sub_range = view_state->GetRangeGeneratorRange(device_state->extensions);
sub_range.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
cb_state.TrackImageFirstLayout(*image_state, sub_range, 0, 0, initial_layout);
sub_range.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
cb_state.TrackImageFirstLayout(*image_state, sub_range, 0, 0, stencil_initial_layout);
} else {
auto subresource_range = view_state->GetRangeGeneratorRange(device_state->extensions);
// If layoutStencil is kInvalidLayout (meaning no separate depth/stencil layout), image view format has both depth
// and stencil aspects, and subresource has only one of aspect out of depth or stencil, then the missing aspect will
// also be transitioned and thus must be included explicitly
auto subresource_range = view_state->normalized_subresource_range;
if (const VkFormat format = view_state->create_info.format; vkuFormatIsDepthAndStencil(format)) {
if (subresource_range.aspectMask & (VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_DEPTH_BIT)) {
subresource_range.aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
Expand Down
3 changes: 1 addition & 2 deletions layers/state_tracker/cmd_buffer_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1798,11 +1798,10 @@ void CommandBuffer::TrackImageFirstLayout(const vvl::Image &image_state, const V
}
}

// Set image layout for all slices of an image view
void CommandBuffer::SetImageViewLayout(const vvl::ImageView &view_state, VkImageLayout layout, VkImageLayout layoutStencil) {
const vvl::Image *image_state = view_state.image_state.get();

VkImageSubresourceRange sub_range = view_state.normalized_subresource_range;
VkImageSubresourceRange sub_range = view_state.GetRangeGeneratorRange(dev_data.extensions);

if (sub_range.aspectMask == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT) && layoutStencil != kInvalidLayout) {
sub_range.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
Expand Down
12 changes: 9 additions & 3 deletions layers/state_tracker/image_state.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* Copyright (c) 2015-2025 The Khronos Group Inc.
* Copyright (c) 2015-2025 Valve Corporation
* Copyright (c) 2015-2025 LunarG, Inc.
/* Copyright (c) 2015-2026 The Khronos Group Inc.
* Copyright (c) 2015-2026 Valve Corporation
* Copyright (c) 2015-2026 LunarG, Inc.
* Copyright (C) 2015-2025 Google Inc.
* Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
* Modifications Copyright (C) 2022 RasterGrid Kft.
Expand Down Expand Up @@ -317,6 +317,12 @@ class ImageView : public StateObject, public SubStateManager<ImageViewSubState>

static VkImageSubresourceRange NormalizeImageViewSubresourceRange(const Image &image_state,
const VkImageViewCreateInfo &image_view_ci);

// The range that defines indexing space of all possible image layouts for this image view.
// It is used by the RangeGenerator and the image layout maps.
// In the general case, it is different than the number of subresources (described by
// normalized_subresource_range), so when dealing with image layouts this function should
// always be used instead
VkImageSubresourceRange GetRangeGeneratorRange(const DeviceExtensions &extensions) const;

std::string DescribeImageUsage(const Logger& logger) const;
Expand Down
76 changes: 74 additions & 2 deletions tests/unit/image_layout_positive.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2024-2025 Valve Corporation
* Copyright (c) 2024-2025 LunarG, Inc.
* Copyright (c) 2024-2026 Valve Corporation
* Copyright (c) 2024-2026 LunarG, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -802,6 +802,78 @@ TEST_F(PositiveImageLayout, TransitionAll3dImageSlices) {
m_command_buffer.End();
}

TEST_F(PositiveImageLayout, TransitionAll3dImageSlicesUsing2DArrayView) {
// https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/11578
SetTargetApiVersion(VK_API_VERSION_1_3);
AddRequiredFeature(vkt::Feature::dynamicRendering);
AddRequiredFeature(vkt::Feature::synchronization2);
RETURN_IF_SKIP(Init());

const uint32_t image_depth = 10;

VkImageCreateInfo image_ci = vku::InitStructHelper();
image_ci.flags = VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT;
image_ci.imageType = VK_IMAGE_TYPE_3D;
image_ci.format = VK_FORMAT_R8G8B8A8_UNORM;
image_ci.extent = {64, 64, image_depth};
image_ci.mipLevels = 1;
image_ci.arrayLayers = 1;
image_ci.samples = VK_SAMPLE_COUNT_1_BIT;
image_ci.tiling = VK_IMAGE_TILING_OPTIMAL;
image_ci.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
image_ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
vkt::Image image(*m_device, image_ci);

VkImageViewCreateInfo image_view_ci = vku::InitStructHelper();
image_view_ci.image = image;
image_view_ci.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
image_view_ci.format = VK_FORMAT_R8G8B8A8_UNORM;
image_view_ci.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, image_depth};
vkt::ImageView image_view(*m_device, image_view_ci);

RenderPassSingleSubpass rp(*this);
rp.AddAttachmentDescription(VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL);
rp.AddAttachmentReference({0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL});
rp.CreateRenderPass();

VkFramebufferCreateInfo framebuffer_ci = vku::InitStructHelper();
framebuffer_ci.renderPass = rp;
framebuffer_ci.width = 64;
framebuffer_ci.height = 64;
framebuffer_ci.layers = image_depth;
framebuffer_ci.attachmentCount = 1;
framebuffer_ci.pAttachments = &image_view.handle();
vkt::Framebuffer framebuffer(*m_device, framebuffer_ci);

VkImageMemoryBarrier2 layout_transition = vku::InitStructHelper();
layout_transition.dstStageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT;
layout_transition.dstAccessMask = VK_ACCESS_2_MEMORY_READ_BIT | VK_ACCESS_2_MEMORY_WRITE_BIT;
layout_transition.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
layout_transition.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
layout_transition.image = image;
layout_transition.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};

vkt::Buffer buffer(*m_device, 64 * 64 * 64, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);

VkBufferImageCopy region{};
region.imageSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1};
region.imageExtent = {64, 64, 1};

m_command_buffer.Begin();

// Transition image to VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
m_command_buffer.Barrier(layout_transition);

// Transition image to VK_IMAGE_LAYOUT_GENERAL
m_command_buffer.BeginRenderPass(rp, framebuffer, 64, 64);
m_command_buffer.EndRenderPass();

// Expect GENERAL layout. The original issue reported layout mismatch
vk::CmdCopyBufferToImage(m_command_buffer, buffer, image, VK_IMAGE_LAYOUT_GENERAL, 1, &region);

m_command_buffer.End();
}

TEST_F(PositiveImageLayout, DepthSliceTransitionCriteriaNotMet) {
// https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/10453
TEST_DESCRIPTION("Enabled maintenance9 but do not set image flag VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT");
Expand Down