buffer_validation.cpp revision cf2ce8673669ca1111e333bdea272c4dd57cb5c2
1584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski/* Copyright (c) 2015-2017 The Khronos Group Inc.
2584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski * Copyright (c) 2015-2017 Valve Corporation
3584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski * Copyright (c) 2015-2017 LunarG, Inc.
4584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski * Copyright (C) 2015-2017 Google Inc.
5584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski *
6584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski * Licensed under the Apache License, Version 2.0 (the "License");
7584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski * you may not use this file except in compliance with the License.
8584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski * You may obtain a copy of the License at
9584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski *
10584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski *     http://www.apache.org/licenses/LICENSE-2.0
11584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski *
12584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski * Unless required by applicable law or agreed to in writing, software
13584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski * distributed under the License is distributed on an "AS IS" BASIS,
14584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski * See the License for the specific language governing permissions and
16584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski * limitations under the License.
17584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski *
18584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski * Author: Mark Lobodzinski <mark@lunarg.com>
19e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton * Author: Dave Houlton <daveh@lunarg.com>
20584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski */
21584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski
22584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski// Allow use of STL min and max functions in Windows
23584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski#define NOMINMAX
24584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski
258dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski#include <sstream>
268dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
278dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski#include "vk_enum_string_helper.h"
288dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski#include "vk_layer_data.h"
298dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski#include "vk_layer_utils.h"
308dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski#include "vk_layer_logging.h"
318dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
32584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski#include "buffer_validation.h"
33c06c9b88f5f5bcc7033ba41d5547b048fa6015a4Mark Lobodzinski
34e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisvoid SetLayout(layer_data *device_data, GLOBAL_CB_NODE *pCB, ImageSubresourcePair imgpair, const VkImageLayout &layout) {
350d2fd381af11d2202d3856cb2da2c7122a0294efChris Forbes    if (pCB->imageLayoutMap.find(imgpair) != pCB->imageLayoutMap.end()) {
3655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        pCB->imageLayoutMap[imgpair].layout = layout;
3755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    } else {
3855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        assert(imgpair.hasSubresource);
3955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        IMAGE_CMD_BUF_LAYOUT_NODE node;
4055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        if (!FindCmdBufLayout(device_data, pCB, imgpair.image, imgpair.subresource, node)) {
4155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski            node.initialLayout = layout;
4255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        }
4355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        SetLayout(device_data, pCB, imgpair, {node.initialLayout, layout});
4455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    }
4555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski}
4655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinskitemplate <class OBJECT, class LAYOUT>
47e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisvoid SetLayout(layer_data *device_data, OBJECT *pObject, VkImage image, VkImageSubresource range, const LAYOUT &layout) {
4855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    ImageSubresourcePair imgpair = {image, true, range};
4955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    SetLayout(device_data, pObject, imgpair, layout, VK_IMAGE_ASPECT_COLOR_BIT);
5055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    SetLayout(device_data, pObject, imgpair, layout, VK_IMAGE_ASPECT_DEPTH_BIT);
5155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    SetLayout(device_data, pObject, imgpair, layout, VK_IMAGE_ASPECT_STENCIL_BIT);
5255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    SetLayout(device_data, pObject, imgpair, layout, VK_IMAGE_ASPECT_METADATA_BIT);
5355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski}
5455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski
5555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinskitemplate <class OBJECT, class LAYOUT>
56e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisvoid SetLayout(layer_data *device_data, OBJECT *pObject, ImageSubresourcePair imgpair, const LAYOUT &layout,
5755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski               VkImageAspectFlags aspectMask) {
5855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    if (imgpair.subresource.aspectMask & aspectMask) {
5955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        imgpair.subresource.aspectMask = aspectMask;
6055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        SetLayout(device_data, pObject, imgpair, layout);
6155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    }
6255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski}
6355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski
6451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour// Set the layout in supplied map
65440bdd357701497c3442e3515f12ac1cfffc180aTony Barbourvoid SetLayout(std::unordered_map<ImageSubresourcePair, IMAGE_LAYOUT_NODE> &imageLayoutMap, ImageSubresourcePair imgpair,
66440bdd357701497c3442e3515f12ac1cfffc180aTony Barbour               VkImageLayout layout) {
6751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    imageLayoutMap[imgpair].layout = layout;
6851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour}
6951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour
700db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlisbool FindLayoutVerifyNode(layer_data const *device_data, GLOBAL_CB_NODE const *pCB, ImageSubresourcePair imgpair,
7155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                          IMAGE_CMD_BUF_LAYOUT_NODE &node, const VkImageAspectFlags aspectMask) {
7255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
7355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski
7455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    if (!(imgpair.subresource.aspectMask & aspectMask)) {
7555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        return false;
7655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    }
7755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    VkImageAspectFlags oldAspectMask = imgpair.subresource.aspectMask;
7855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    imgpair.subresource.aspectMask = aspectMask;
7955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    auto imgsubIt = pCB->imageLayoutMap.find(imgpair);
8055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    if (imgsubIt == pCB->imageLayoutMap.end()) {
8155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        return false;
8255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    }
8355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    if (node.layout != VK_IMAGE_LAYOUT_MAX_ENUM && node.layout != imgsubIt->second.layout) {
8455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
8555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                reinterpret_cast<uint64_t &>(imgpair.image), __LINE__, DRAWSTATE_INVALID_LAYOUT, "DS",
8655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                "Cannot query for VkImage 0x%" PRIx64 " layout when combined aspect mask %d has multiple layout types: %s and %s",
8755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                reinterpret_cast<uint64_t &>(imgpair.image), oldAspectMask, string_VkImageLayout(node.layout),
8855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                string_VkImageLayout(imgsubIt->second.layout));
8955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    }
9055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    if (node.initialLayout != VK_IMAGE_LAYOUT_MAX_ENUM && node.initialLayout != imgsubIt->second.initialLayout) {
9155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
9255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                reinterpret_cast<uint64_t &>(imgpair.image), __LINE__, DRAWSTATE_INVALID_LAYOUT, "DS",
9355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                "Cannot query for VkImage 0x%" PRIx64
9455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                " layout when combined aspect mask %d has multiple initial layout types: %s and %s",
9555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                reinterpret_cast<uint64_t &>(imgpair.image), oldAspectMask, string_VkImageLayout(node.initialLayout),
9655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                string_VkImageLayout(imgsubIt->second.initialLayout));
9755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    }
9855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    node = imgsubIt->second;
9955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    return true;
10055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski}
10155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski
1020db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlisbool FindLayoutVerifyLayout(layer_data const *device_data, ImageSubresourcePair imgpair, VkImageLayout &layout,
10355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                            const VkImageAspectFlags aspectMask) {
10455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    if (!(imgpair.subresource.aspectMask & aspectMask)) {
10555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        return false;
10655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    }
10755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
10855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    VkImageAspectFlags oldAspectMask = imgpair.subresource.aspectMask;
10955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    imgpair.subresource.aspectMask = aspectMask;
11055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    auto imgsubIt = (*core_validation::GetImageLayoutMap(device_data)).find(imgpair);
11155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    if (imgsubIt == (*core_validation::GetImageLayoutMap(device_data)).end()) {
11255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        return false;
11355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    }
11455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    if (layout != VK_IMAGE_LAYOUT_MAX_ENUM && layout != imgsubIt->second.layout) {
11555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
11655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                reinterpret_cast<uint64_t &>(imgpair.image), __LINE__, DRAWSTATE_INVALID_LAYOUT, "DS",
11755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                "Cannot query for VkImage 0x%" PRIx64 " layout when combined aspect mask %d has multiple layout types: %s and %s",
11855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                reinterpret_cast<uint64_t &>(imgpair.image), oldAspectMask, string_VkImageLayout(layout),
11955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                string_VkImageLayout(imgsubIt->second.layout));
12055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    }
12155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    layout = imgsubIt->second.layout;
12255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    return true;
12355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski}
12455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski
12555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski// Find layout(s) on the command buffer level
1260db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlisbool FindCmdBufLayout(layer_data const *device_data, GLOBAL_CB_NODE const *pCB, VkImage image, VkImageSubresource range,
12755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                      IMAGE_CMD_BUF_LAYOUT_NODE &node) {
12855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    ImageSubresourcePair imgpair = {image, true, range};
12955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    node = IMAGE_CMD_BUF_LAYOUT_NODE(VK_IMAGE_LAYOUT_MAX_ENUM, VK_IMAGE_LAYOUT_MAX_ENUM);
13055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    FindLayoutVerifyNode(device_data, pCB, imgpair, node, VK_IMAGE_ASPECT_COLOR_BIT);
13155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    FindLayoutVerifyNode(device_data, pCB, imgpair, node, VK_IMAGE_ASPECT_DEPTH_BIT);
13255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    FindLayoutVerifyNode(device_data, pCB, imgpair, node, VK_IMAGE_ASPECT_STENCIL_BIT);
13355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    FindLayoutVerifyNode(device_data, pCB, imgpair, node, VK_IMAGE_ASPECT_METADATA_BIT);
13455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    if (node.layout == VK_IMAGE_LAYOUT_MAX_ENUM) {
13555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        imgpair = {image, false, VkImageSubresource()};
13655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        auto imgsubIt = pCB->imageLayoutMap.find(imgpair);
13755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        if (imgsubIt == pCB->imageLayoutMap.end()) return false;
13855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        // TODO: This is ostensibly a find function but it changes state here
13955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        node = imgsubIt->second;
14055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    }
14155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    return true;
14255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski}
14355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski
14455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski// Find layout(s) on the global level
145e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisbool FindGlobalLayout(layer_data *device_data, ImageSubresourcePair imgpair, VkImageLayout &layout) {
14655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    layout = VK_IMAGE_LAYOUT_MAX_ENUM;
14755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    FindLayoutVerifyLayout(device_data, imgpair, layout, VK_IMAGE_ASPECT_COLOR_BIT);
14855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    FindLayoutVerifyLayout(device_data, imgpair, layout, VK_IMAGE_ASPECT_DEPTH_BIT);
14955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    FindLayoutVerifyLayout(device_data, imgpair, layout, VK_IMAGE_ASPECT_STENCIL_BIT);
15055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    FindLayoutVerifyLayout(device_data, imgpair, layout, VK_IMAGE_ASPECT_METADATA_BIT);
15155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    if (layout == VK_IMAGE_LAYOUT_MAX_ENUM) {
15255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        imgpair = {imgpair.image, false, VkImageSubresource()};
15355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        auto imgsubIt = (*core_validation::GetImageLayoutMap(device_data)).find(imgpair);
15455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        if (imgsubIt == (*core_validation::GetImageLayoutMap(device_data)).end()) return false;
15555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        layout = imgsubIt->second.layout;
15655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    }
15755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    return true;
15855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski}
15955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski
160e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisbool FindLayouts(layer_data *device_data, VkImage image, std::vector<VkImageLayout> &layouts) {
16155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    auto sub_data = (*core_validation::GetImageSubresourceMap(device_data)).find(image);
16255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    if (sub_data == (*core_validation::GetImageSubresourceMap(device_data)).end()) return false;
1639a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto image_state = GetImageState(device_data, image);
16455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    if (!image_state) return false;
16555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    bool ignoreGlobal = false;
16655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    // TODO: Make this robust for >1 aspect mask. Now it will just say ignore potential errors in this case.
16755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    if (sub_data->second.size() >= (image_state->createInfo.arrayLayers * image_state->createInfo.mipLevels + 1)) {
16855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        ignoreGlobal = true;
16955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    }
17055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    for (auto imgsubpair : sub_data->second) {
17155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        if (ignoreGlobal && !imgsubpair.hasSubresource) continue;
17255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        auto img_data = (*core_validation::GetImageLayoutMap(device_data)).find(imgsubpair);
17355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        if (img_data != (*core_validation::GetImageLayoutMap(device_data)).end()) {
17455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski            layouts.push_back(img_data->second.layout);
17555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        }
17655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    }
17755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    return true;
17855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski}
179440bdd357701497c3442e3515f12ac1cfffc180aTony Barbourbool FindLayout(const std::unordered_map<ImageSubresourcePair, IMAGE_LAYOUT_NODE> &imageLayoutMap, ImageSubresourcePair imgpair,
180440bdd357701497c3442e3515f12ac1cfffc180aTony Barbour                VkImageLayout &layout, const VkImageAspectFlags aspectMask) {
18151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    if (!(imgpair.subresource.aspectMask & aspectMask)) {
18251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour        return false;
18351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    }
18451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    imgpair.subresource.aspectMask = aspectMask;
18551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    auto imgsubIt = imageLayoutMap.find(imgpair);
18651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    if (imgsubIt == imageLayoutMap.end()) {
18751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour        return false;
18851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    }
18951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    layout = imgsubIt->second.layout;
19051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    return true;
191440bdd357701497c3442e3515f12ac1cfffc180aTony Barbour}
19251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour
19351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour// find layout in supplied map
194440bdd357701497c3442e3515f12ac1cfffc180aTony Barbourbool FindLayout(const std::unordered_map<ImageSubresourcePair, IMAGE_LAYOUT_NODE> &imageLayoutMap, ImageSubresourcePair imgpair,
195440bdd357701497c3442e3515f12ac1cfffc180aTony Barbour                VkImageLayout &layout) {
19651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    layout = VK_IMAGE_LAYOUT_MAX_ENUM;
19751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    FindLayout(imageLayoutMap, imgpair, layout, VK_IMAGE_ASPECT_COLOR_BIT);
19851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    FindLayout(imageLayoutMap, imgpair, layout, VK_IMAGE_ASPECT_DEPTH_BIT);
19951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    FindLayout(imageLayoutMap, imgpair, layout, VK_IMAGE_ASPECT_STENCIL_BIT);
20051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    FindLayout(imageLayoutMap, imgpair, layout, VK_IMAGE_ASPECT_METADATA_BIT);
20151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    if (layout == VK_IMAGE_LAYOUT_MAX_ENUM) {
20251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour        imgpair = {imgpair.image, false, VkImageSubresource()};
20351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour        auto imgsubIt = imageLayoutMap.find(imgpair);
20451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour        if (imgsubIt == imageLayoutMap.end()) return false;
20551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour        layout = imgsubIt->second.layout;
20651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    }
20751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    return true;
20851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour}
20955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski
21055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski// Set the layout on the global level
211e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisvoid SetGlobalLayout(layer_data *device_data, ImageSubresourcePair imgpair, const VkImageLayout &layout) {
21255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    VkImage &image = imgpair.image;
21355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    (*core_validation::GetImageLayoutMap(device_data))[imgpair].layout = layout;
21455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    auto &image_subresources = (*core_validation::GetImageSubresourceMap(device_data))[image];
21555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    auto subresource = std::find(image_subresources.begin(), image_subresources.end(), imgpair);
21655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    if (subresource == image_subresources.end()) {
21755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        image_subresources.push_back(imgpair);
21855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    }
21955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski}
22055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski
22155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski// Set the layout on the cmdbuf level
222e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisvoid SetLayout(layer_data *device_data, GLOBAL_CB_NODE *pCB, ImageSubresourcePair imgpair, const IMAGE_CMD_BUF_LAYOUT_NODE &node) {
22355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    pCB->imageLayoutMap[imgpair] = node;
22455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski}
225a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis// Set image layout for given VkImageSubresourceRange struct
226a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlisvoid SetImageLayout(layer_data *device_data, GLOBAL_CB_NODE *cb_node, const IMAGE_STATE *image_state,
227a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis                    VkImageSubresourceRange image_subresource_range, const VkImageLayout &layout) {
228a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis    assert(image_state);
229a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis    for (uint32_t level_index = 0; level_index < image_subresource_range.levelCount; ++level_index) {
230a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis        uint32_t level = image_subresource_range.baseMipLevel + level_index;
231a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis        for (uint32_t layer_index = 0; layer_index < image_subresource_range.layerCount; layer_index++) {
232a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis            uint32_t layer = image_subresource_range.baseArrayLayer + layer_index;
233a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis            VkImageSubresource sub = {image_subresource_range.aspectMask, level, layer};
23455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski            // TODO: If ImageView was created with depth or stencil, transition both layouts as the aspectMask is ignored and both
23555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski            // are used. Verify that the extra implicit layout is OK for descriptor set layout validation
236a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis            if (image_subresource_range.aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
23716769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton                if (FormatIsDepthAndStencil(image_state->createInfo.format)) {
23855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                    sub.aspectMask |= (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);
23955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                }
24055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski            }
241a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis            SetLayout(device_data, cb_node, image_state->image, sub, layout);
24255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        }
24355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    }
24455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski}
245a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis// Set image layout for given VkImageSubresourceLayers struct
246a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlisvoid SetImageLayout(layer_data *device_data, GLOBAL_CB_NODE *cb_node, const IMAGE_STATE *image_state,
247a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis                    VkImageSubresourceLayers image_subresource_layers, const VkImageLayout &layout) {
248a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis    // Transfer VkImageSubresourceLayers into VkImageSubresourceRange struct
249a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis    VkImageSubresourceRange image_subresource_range;
250a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis    image_subresource_range.aspectMask = image_subresource_layers.aspectMask;
251a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis    image_subresource_range.baseArrayLayer = image_subresource_layers.baseArrayLayer;
252a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis    image_subresource_range.layerCount = image_subresource_layers.layerCount;
253a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis    image_subresource_range.baseMipLevel = image_subresource_layers.mipLevel;
254a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis    image_subresource_range.levelCount = 1;
255a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis    SetImageLayout(device_data, cb_node, image_state, image_subresource_range, layout);
256a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis}
257a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis// Set image layout for all slices of an image view
258a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlisvoid SetImageViewLayout(layer_data *device_data, GLOBAL_CB_NODE *cb_node, VkImageView imageView, const VkImageLayout &layout) {
259a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis    auto view_state = GetImageViewState(device_data, imageView);
260a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis    assert(view_state);
261a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis
262a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis    SetImageLayout(device_data, cb_node, GetImageState(device_data, view_state->create_info.image),
263a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis                   view_state->create_info.subresourceRange, layout);
264a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis}
26555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski
266e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisbool VerifyFramebufferAndRenderPassLayouts(layer_data *device_data, GLOBAL_CB_NODE *pCB,
26755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                                           const VkRenderPassBeginInfo *pRenderPassBegin,
26855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                                           const FRAMEBUFFER_STATE *framebuffer_state) {
2693251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
2709a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto const pRenderPassInfo = GetRenderPassState(device_data, pRenderPassBegin->renderPass)->createInfo.ptr();
27155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    auto const &framebufferInfo = framebuffer_state->createInfo;
27255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    const auto report_data = core_validation::GetReportData(device_data);
27355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    if (pRenderPassInfo->attachmentCount != framebufferInfo.attachmentCount) {
2743251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
2753251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        reinterpret_cast<uint64_t>(pCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS",
2763251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "You cannot start a render pass using a framebuffer "
2773251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "with a different number of attachments.");
27855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    }
27955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    for (uint32_t i = 0; i < pRenderPassInfo->attachmentCount; ++i) {
28055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        const VkImageView &image_view = framebufferInfo.pAttachments[i];
2819a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto view_state = GetImageViewState(device_data, image_view);
28255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        assert(view_state);
28355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        const VkImage &image = view_state->create_info.image;
28455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        const VkImageSubresourceRange &subRange = view_state->create_info.subresourceRange;
2855f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlis        auto initial_layout = pRenderPassInfo->pAttachments[i].initialLayout;
28655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        // TODO: Do not iterate over every possibility - consolidate where possible
28755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        for (uint32_t j = 0; j < subRange.levelCount; j++) {
28855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski            uint32_t level = subRange.baseMipLevel + j;
28955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski            for (uint32_t k = 0; k < subRange.layerCount; k++) {
29055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                uint32_t layer = subRange.baseArrayLayer + k;
29155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                VkImageSubresource sub = {subRange.aspectMask, level, layer};
29255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                IMAGE_CMD_BUF_LAYOUT_NODE node;
29355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                if (!FindCmdBufLayout(device_data, pCB, image, sub, node)) {
2945f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlis                    // Missing layouts will be added during state update
29555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                    continue;
29655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                }
2975f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlis                if (initial_layout != VK_IMAGE_LAYOUT_UNDEFINED && initial_layout != node.layout) {
2983251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                    skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
2993251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS",
3003251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    "You cannot start a render pass using attachment %u "
3013251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    "where the render pass initial layout is %s and the previous "
3023251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    "known layout of the attachment is %s. The layouts must match, or "
3033251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    "the render pass initial layout for the attachment must be "
3043251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    "VK_IMAGE_LAYOUT_UNDEFINED",
3053251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    i, string_VkImageLayout(initial_layout), string_VkImageLayout(node.layout));
30655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                }
30755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski            }
30855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        }
30955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    }
3103251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
31155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski}
31255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski
313e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisvoid TransitionAttachmentRefLayout(layer_data *device_data, GLOBAL_CB_NODE *pCB, FRAMEBUFFER_STATE *pFramebuffer,
31455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                                   VkAttachmentReference ref) {
31555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    if (ref.attachment != VK_ATTACHMENT_UNUSED) {
31655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        auto image_view = pFramebuffer->createInfo.pAttachments[ref.attachment];
31755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        SetImageViewLayout(device_data, pCB, image_view, ref.layout);
31855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    }
31955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski}
32055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski
3215f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlisvoid TransitionSubpassLayouts(layer_data *device_data, GLOBAL_CB_NODE *pCB, const RENDER_PASS_STATE *render_pass_state,
322e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlis                              const int subpass_index, FRAMEBUFFER_STATE *framebuffer_state) {
3235f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlis    assert(render_pass_state);
32455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski
32555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    if (framebuffer_state) {
3265f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlis        auto const &subpass = render_pass_state->createInfo.pSubpasses[subpass_index];
32755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) {
32855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski            TransitionAttachmentRefLayout(device_data, pCB, framebuffer_state, subpass.pInputAttachments[j]);
32955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        }
33055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) {
33155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski            TransitionAttachmentRefLayout(device_data, pCB, framebuffer_state, subpass.pColorAttachments[j]);
33255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        }
33355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        if (subpass.pDepthStencilAttachment) {
33455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski            TransitionAttachmentRefLayout(device_data, pCB, framebuffer_state, *subpass.pDepthStencilAttachment);
33555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        }
33655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    }
33755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski}
33855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski
339e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinskibool ValidateImageAspectLayout(layer_data *device_data, GLOBAL_CB_NODE *pCB, const VkImageMemoryBarrier *mem_barrier,
340e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski                               uint32_t level, uint32_t layer, VkImageAspectFlags aspect) {
34155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    if (!(mem_barrier->subresourceRange.aspectMask & aspect)) {
34255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        return false;
34355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    }
34455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    VkImageSubresource sub = {aspect, level, layer};
34555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    IMAGE_CMD_BUF_LAYOUT_NODE node;
34655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    if (!FindCmdBufLayout(device_data, pCB, mem_barrier->image, sub, node)) {
34755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        return false;
34855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    }
34955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    bool skip = false;
35055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    if (mem_barrier->oldLayout == VK_IMAGE_LAYOUT_UNDEFINED) {
35155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        // TODO: Set memory invalid which is in mem_tracker currently
35255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    } else if (node.layout != mem_barrier->oldLayout) {
3530620f54d857b76b4866f3835bc1aea96e525699cMark Lobodzinski        skip |=
3540620f54d857b76b4866f3835bc1aea96e525699cMark Lobodzinski            log_msg(core_validation::GetReportData(device_data), VK_DEBUG_REPORT_ERROR_BIT_EXT,
3550620f54d857b76b4866f3835bc1aea96e525699cMark Lobodzinski                    VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t>(pCB->commandBuffer), __LINE__,
3560620f54d857b76b4866f3835bc1aea96e525699cMark Lobodzinski                    DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
3570620f54d857b76b4866f3835bc1aea96e525699cMark Lobodzinski                    "For image 0x%" PRIxLEAST64 " you cannot transition the layout of aspect %d from %s when current layout is %s.",
3580620f54d857b76b4866f3835bc1aea96e525699cMark Lobodzinski                    reinterpret_cast<const uint64_t &>(mem_barrier->image), aspect, string_VkImageLayout(mem_barrier->oldLayout),
3590620f54d857b76b4866f3835bc1aea96e525699cMark Lobodzinski                    string_VkImageLayout(node.layout));
36055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    }
36155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    return skip;
36255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski}
36355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski
3645f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlis// Transition the layout state for renderpass attachments based on the BeginRenderPass() call. This includes:
3655f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlis// 1. Transition into initialLayout state
3665f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlis// 2. Transition from initialLayout to layout used in subpass 0
3675f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlisvoid TransitionBeginRenderPassLayouts(layer_data *device_data, GLOBAL_CB_NODE *cb_state, const RENDER_PASS_STATE *render_pass_state,
3685f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlis                                      FRAMEBUFFER_STATE *framebuffer_state) {
3695f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlis    // First transition into initialLayout
3705f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlis    auto const rpci = render_pass_state->createInfo.ptr();
3715f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlis    for (uint32_t i = 0; i < rpci->attachmentCount; ++i) {
3725f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlis        VkImageView image_view = framebuffer_state->createInfo.pAttachments[i];
3735f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlis        SetImageViewLayout(device_data, cb_state, image_view, rpci->pAttachments[i].initialLayout);
3745f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlis    }
3755f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlis    // Now transition for first subpass (index 0)
3765f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlis    TransitionSubpassLayouts(device_data, cb_state, render_pass_state, 0, framebuffer_state);
3775f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlis}
3785f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlis
379e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinskivoid TransitionImageAspectLayout(layer_data *device_data, GLOBAL_CB_NODE *pCB, const VkImageMemoryBarrier *mem_barrier,
380e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski                                 uint32_t level, uint32_t layer, VkImageAspectFlags aspect) {
381e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski    if (!(mem_barrier->subresourceRange.aspectMask & aspect)) {
382e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski        return;
383e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski    }
384e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski    VkImageSubresource sub = {aspect, level, layer};
385e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski    IMAGE_CMD_BUF_LAYOUT_NODE node;
386e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski    if (!FindCmdBufLayout(device_data, pCB, mem_barrier->image, sub, node)) {
387e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski        SetLayout(device_data, pCB, mem_barrier->image, sub,
388e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski                  IMAGE_CMD_BUF_LAYOUT_NODE(mem_barrier->oldLayout, mem_barrier->newLayout));
389e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski        return;
390e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski    }
391e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski    if (mem_barrier->oldLayout == VK_IMAGE_LAYOUT_UNDEFINED) {
392e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski        // TODO: Set memory invalid
393e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski    }
394e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski    SetLayout(device_data, pCB, mem_barrier->image, sub, mem_barrier->newLayout);
395e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski}
396e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski
39765b2f2c31703462c8ad1fcf4543c459df8a028ccDave Houltonbool VerifyAspectsPresent(VkImageAspectFlags aspect_mask, VkFormat format) {
398e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton    if ((aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT) != 0) {
39916769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton        if (!FormatIsColor(format)) return false;
400e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton    }
401e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton    if ((aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) != 0) {
40216769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton        if (!FormatHasDepth(format)) return false;
403e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton    }
404e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton    if ((aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT) != 0) {
40516769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton        if (!FormatHasStencil(format)) return false;
406e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton    }
407e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton    return true;
408e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton}
409e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton
410a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen// Verify an ImageMemoryBarrier's old/new ImageLayouts are compatible with the Image's ImageUsageFlags.
411a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblenbool ValidateBarrierLayoutToImageUsage(layer_data *device_data, const VkImageMemoryBarrier *img_barrier, bool new_not_old,
412a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen                                       VkImageUsageFlags usage_flags, const char *func_name) {
413a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen    const auto report_data = core_validation::GetReportData(device_data);
414a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen    bool skip = false;
415a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen    const VkImageLayout layout = (new_not_old) ? img_barrier->newLayout : img_barrier->oldLayout;
416a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen    UNIQUE_VALIDATION_ERROR_CODE msg_code = VALIDATION_ERROR_UNDEFINED;  // sentinel value meaning "no error"
417a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen
418a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen    switch (layout) {
419a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen        case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
420a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen            if ((usage_flags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) == 0) {
421a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen                msg_code = VALIDATION_ERROR_00303;
422a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen            }
423a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen            break;
424a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen        case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
425a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen            if ((usage_flags & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) == 0) {
426a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen                msg_code = VALIDATION_ERROR_00304;
427a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen            }
428a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen            break;
429a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen        case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
430a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen            if ((usage_flags & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) == 0) {
431a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen                msg_code = VALIDATION_ERROR_00305;
432a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen            }
433a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen            break;
434a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen        case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
435a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen            if ((usage_flags & (VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) == 0) {
436a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen                msg_code = VALIDATION_ERROR_00306;
437a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen            }
438a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen            break;
439a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen        case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
440a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen            if ((usage_flags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) == 0) {
441a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen                msg_code = VALIDATION_ERROR_00307;
442a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen            }
443a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen            break;
444a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen        case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
445a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen            if ((usage_flags & VK_IMAGE_USAGE_TRANSFER_DST_BIT) == 0) {
446a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen                msg_code = VALIDATION_ERROR_00308;
447a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen            }
448a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen            break;
449a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen        default:
450a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen            // Other VkImageLayout values do not have VUs defined in this context.
451a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen            break;
452a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen    }
453a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen
454a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen    if (msg_code != VALIDATION_ERROR_UNDEFINED) {
455fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski        skip |=
456fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski            log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
457fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                    reinterpret_cast<const uint64_t &>(img_barrier->image), __LINE__, msg_code, "DS",
458fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                    "%s: Image barrier 0x%p %sLayout=%s is not compatible with image 0x%" PRIx64 " usage flags 0x%" PRIx32 ". %s",
459fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                    func_name, img_barrier, ((new_not_old) ? "new" : "old"), string_VkImageLayout(layout),
460fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                    reinterpret_cast<const uint64_t &>(img_barrier->image), usage_flags, validation_error_map[msg_code]);
461a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen    }
462a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen    return skip;
463a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen}
464a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen
465a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen// Verify image barriers are compatible with the images they reference.
466a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblenbool ValidateBarriersToImages(layer_data *device_data, VkCommandBuffer cmdBuffer, uint32_t imageMemoryBarrierCount,
467a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen                              const VkImageMemoryBarrier *pImageMemoryBarriers, const char *func_name) {
4689a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    GLOBAL_CB_NODE *pCB = GetCBNode(device_data, cmdBuffer);
46955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    bool skip = false;
470a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen
471a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen    for (uint32_t i = 0; i < imageMemoryBarrierCount; ++i) {
472a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen        auto img_barrier = &pImageMemoryBarriers[i];
473a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen        if (!img_barrier) continue;
47455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski
47595b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski        VkImageCreateInfo *image_create_info = &(GetImageState(device_data, img_barrier->image)->createInfo);
476c7455116cef9c14f8405aae43bc0247f2c256f96Tobin Ehlis        // For a Depth/Stencil image both aspects MUST be set
477c7455116cef9c14f8405aae43bc0247f2c256f96Tobin Ehlis        if (FormatIsDepthAndStencil(image_create_info->format)) {
478c7455116cef9c14f8405aae43bc0247f2c256f96Tobin Ehlis            auto const aspect_mask = img_barrier->subresourceRange.aspectMask;
479c7455116cef9c14f8405aae43bc0247f2c256f96Tobin Ehlis            auto const ds_mask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
480c7455116cef9c14f8405aae43bc0247f2c256f96Tobin Ehlis            if ((aspect_mask & ds_mask) != (ds_mask)) {
481c7455116cef9c14f8405aae43bc0247f2c256f96Tobin Ehlis                skip |=
482c7455116cef9c14f8405aae43bc0247f2c256f96Tobin Ehlis                    log_msg(core_validation::GetReportData(device_data), VK_DEBUG_REPORT_ERROR_BIT_EXT,
483c7455116cef9c14f8405aae43bc0247f2c256f96Tobin Ehlis                            VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, reinterpret_cast<const uint64_t &>(img_barrier->image), __LINE__,
484c7455116cef9c14f8405aae43bc0247f2c256f96Tobin Ehlis                            VALIDATION_ERROR_00302, "DS",
485c7455116cef9c14f8405aae43bc0247f2c256f96Tobin Ehlis                            "%s: Image barrier 0x%p references image 0x%" PRIx64
486c7455116cef9c14f8405aae43bc0247f2c256f96Tobin Ehlis                            " of format %s that must have the depth and stencil aspects set, but its "
487c7455116cef9c14f8405aae43bc0247f2c256f96Tobin Ehlis                            "aspectMask is 0x%" PRIx32 ". %s",
488c7455116cef9c14f8405aae43bc0247f2c256f96Tobin Ehlis                            func_name, img_barrier, reinterpret_cast<const uint64_t &>(img_barrier->image),
489c7455116cef9c14f8405aae43bc0247f2c256f96Tobin Ehlis                            string_VkFormat(image_create_info->format), aspect_mask, validation_error_map[VALIDATION_ERROR_00302]);
490c7455116cef9c14f8405aae43bc0247f2c256f96Tobin Ehlis            }
491c7455116cef9c14f8405aae43bc0247f2c256f96Tobin Ehlis        }
49295b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski        uint32_t level_count = ResolveRemainingLevels(&img_barrier->subresourceRange, image_create_info->mipLevels);
49395b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski        uint32_t layer_count = ResolveRemainingLayers(&img_barrier->subresourceRange, image_create_info->arrayLayers);
494a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen
495a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen        for (uint32_t j = 0; j < level_count; j++) {
496a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen            uint32_t level = img_barrier->subresourceRange.baseMipLevel + j;
497a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen            for (uint32_t k = 0; k < layer_count; k++) {
498a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen                uint32_t layer = img_barrier->subresourceRange.baseArrayLayer + k;
499a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen                skip |= ValidateImageAspectLayout(device_data, pCB, img_barrier, level, layer, VK_IMAGE_ASPECT_COLOR_BIT);
500a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen                skip |= ValidateImageAspectLayout(device_data, pCB, img_barrier, level, layer, VK_IMAGE_ASPECT_DEPTH_BIT);
501a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen                skip |= ValidateImageAspectLayout(device_data, pCB, img_barrier, level, layer, VK_IMAGE_ASPECT_STENCIL_BIT);
502a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen                skip |= ValidateImageAspectLayout(device_data, pCB, img_barrier, level, layer, VK_IMAGE_ASPECT_METADATA_BIT);
50355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski            }
50455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        }
505a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen
506a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen        IMAGE_STATE *image_state = GetImageState(device_data, img_barrier->image);
507a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen        if (image_state) {
508a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen            VkImageUsageFlags usage_flags = image_state->createInfo.usage;
509a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen            skip |= ValidateBarrierLayoutToImageUsage(device_data, img_barrier, false, usage_flags, func_name);
510a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen            skip |= ValidateBarrierLayoutToImageUsage(device_data, img_barrier, true, usage_flags, func_name);
511a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen        }
51255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    }
51355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    return skip;
51455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski}
51555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski
516e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinskivoid TransitionImageLayouts(layer_data *device_data, VkCommandBuffer cmdBuffer, uint32_t memBarrierCount,
517e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski                            const VkImageMemoryBarrier *pImgMemBarriers) {
518e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski    GLOBAL_CB_NODE *pCB = GetCBNode(device_data, cmdBuffer);
519e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski
520e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski    for (uint32_t i = 0; i < memBarrierCount; ++i) {
521e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski        auto mem_barrier = &pImgMemBarriers[i];
522e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski        if (!mem_barrier) continue;
523e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski
52495b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski        VkImageCreateInfo *image_create_info = &(GetImageState(device_data, mem_barrier->image)->createInfo);
52595b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski        uint32_t level_count = ResolveRemainingLevels(&mem_barrier->subresourceRange, image_create_info->mipLevels);
52695b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski        uint32_t layer_count = ResolveRemainingLayers(&mem_barrier->subresourceRange, image_create_info->arrayLayers);
52795b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski
52895b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski        for (uint32_t j = 0; j < level_count; j++) {
529e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski            uint32_t level = mem_barrier->subresourceRange.baseMipLevel + j;
53095b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski            for (uint32_t k = 0; k < layer_count; k++) {
531e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski                uint32_t layer = mem_barrier->subresourceRange.baseArrayLayer + k;
532e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski                TransitionImageAspectLayout(device_data, pCB, mem_barrier, level, layer, VK_IMAGE_ASPECT_COLOR_BIT);
533e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski                TransitionImageAspectLayout(device_data, pCB, mem_barrier, level, layer, VK_IMAGE_ASPECT_DEPTH_BIT);
534e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski                TransitionImageAspectLayout(device_data, pCB, mem_barrier, level, layer, VK_IMAGE_ASPECT_STENCIL_BIT);
535e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski                TransitionImageAspectLayout(device_data, pCB, mem_barrier, level, layer, VK_IMAGE_ASPECT_METADATA_BIT);
536e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski            }
537e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski        }
538e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski    }
539e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski}
540e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski
5410db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlisbool VerifyImageLayout(layer_data const *device_data, GLOBAL_CB_NODE const *cb_node, IMAGE_STATE *image_state,
542fab4fd84d0d187bc73b5bc6709d8ed6370bb7cc3Tobin Ehlis                       VkImageSubresourceLayers subLayers, VkImageLayout explicit_layout, VkImageLayout optimal_layout,
5430db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlis                       const char *caller, UNIQUE_VALIDATION_ERROR_CODE msg_code, bool *error) {
54455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    const auto report_data = core_validation::GetReportData(device_data);
545fab4fd84d0d187bc73b5bc6709d8ed6370bb7cc3Tobin Ehlis    const auto image = image_state->image;
5463251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
54755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski
54855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    for (uint32_t i = 0; i < subLayers.layerCount; ++i) {
54955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        uint32_t layer = i + subLayers.baseArrayLayer;
55055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        VkImageSubresource sub = {subLayers.aspectMask, subLayers.mipLevel, layer};
55155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        IMAGE_CMD_BUF_LAYOUT_NODE node;
552a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis        if (FindCmdBufLayout(device_data, cb_node, image, sub, node)) {
553a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis            if (node.layout != explicit_layout) {
5540db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlis                *error = true;
555a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis                // TODO: Improve log message in the next pass
5563251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
5573251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
5583251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                "%s: Cannot use image 0x%" PRIxLEAST64
5593251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                " with specific layout %s that doesn't match the actual current layout %s.",
5603251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                caller, reinterpret_cast<const uint64_t &>(image), string_VkImageLayout(explicit_layout),
5613251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                string_VkImageLayout(node.layout));
562a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis            }
56355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        }
56455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    }
565fab4fd84d0d187bc73b5bc6709d8ed6370bb7cc3Tobin Ehlis    // If optimal_layout is not UNDEFINED, check that layout matches optimal for this case
566fab4fd84d0d187bc73b5bc6709d8ed6370bb7cc3Tobin Ehlis    if ((VK_IMAGE_LAYOUT_UNDEFINED != optimal_layout) && (explicit_layout != optimal_layout)) {
567fab4fd84d0d187bc73b5bc6709d8ed6370bb7cc3Tobin Ehlis        if (VK_IMAGE_LAYOUT_GENERAL == explicit_layout) {
56855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski            if (image_state->createInfo.tiling != VK_IMAGE_TILING_LINEAR) {
56955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                // LAYOUT_GENERAL is allowed, but may not be performance optimal, flag as perf warning.
5703251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT,
5713251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t>(cb_node->commandBuffer),
5723251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
5733251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                "%s: For optimal performance image 0x%" PRIxLEAST64 " layout should be %s instead of GENERAL.",
5743251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                caller, reinterpret_cast<const uint64_t &>(image), string_VkImageLayout(optimal_layout));
57555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski            }
57655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        } else {
5770db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlis            *error = true;
5783251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
5793251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, msg_code, "DS",
5803251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "%s: Layout for image 0x%" PRIxLEAST64 " is %s but can only be %s or VK_IMAGE_LAYOUT_GENERAL. %s",
5813251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            caller, reinterpret_cast<const uint64_t &>(image), string_VkImageLayout(explicit_layout),
5823251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            string_VkImageLayout(optimal_layout), validation_error_map[msg_code]);
58355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        }
58455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    }
5853251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
58655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski}
58755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski
588e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisvoid TransitionFinalSubpassLayouts(layer_data *device_data, GLOBAL_CB_NODE *pCB, const VkRenderPassBeginInfo *pRenderPassBegin,
589e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlis                                   FRAMEBUFFER_STATE *framebuffer_state) {
5909a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto renderPass = GetRenderPassState(device_data, pRenderPassBegin->renderPass);
59155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    if (!renderPass) return;
59255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski
59355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    const VkRenderPassCreateInfo *pRenderPassInfo = renderPass->createInfo.ptr();
59455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    if (framebuffer_state) {
59555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        for (uint32_t i = 0; i < pRenderPassInfo->attachmentCount; ++i) {
59655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski            auto image_view = framebuffer_state->createInfo.pAttachments[i];
59755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski            SetImageViewLayout(device_data, pCB, image_view, pRenderPassInfo->pAttachments[i].finalLayout);
59855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        }
59955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    }
60055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski}
60155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski
602e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisbool PreCallValidateCreateImage(layer_data *device_data, const VkImageCreateInfo *pCreateInfo,
6038dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                                const VkAllocationCallbacks *pAllocator, VkImage *pImage) {
6043251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
6058dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
6068dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
6073c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes    if (pCreateInfo->format == VK_FORMAT_UNDEFINED) {
6083251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
6093251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        VALIDATION_ERROR_00715, "IMAGE", "vkCreateImage: VkFormat for image must not be VK_FORMAT_UNDEFINED. %s",
6103251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        validation_error_map[VALIDATION_ERROR_00715]);
6113c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes
6123251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        return skip;
6133c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes    }
6143c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes
6153c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes    const VkFormatProperties *properties = GetFormatProperties(device_data, pCreateInfo->format);
6163c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes
6173c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes    if ((pCreateInfo->tiling == VK_IMAGE_TILING_LINEAR) && (properties->linearTilingFeatures == 0)) {
6183c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes        std::stringstream ss;
6193c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes        ss << "vkCreateImage format parameter (" << string_VkFormat(pCreateInfo->format) << ") is an unsupported format";
6203251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
6213251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        VALIDATION_ERROR_02150, "IMAGE", "%s. %s", ss.str().c_str(), validation_error_map[VALIDATION_ERROR_02150]);
6223c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes
6233251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        return skip;
6243c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes    }
6253c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes
6263c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes    if ((pCreateInfo->tiling == VK_IMAGE_TILING_OPTIMAL) && (properties->optimalTilingFeatures == 0)) {
6273c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes        std::stringstream ss;
6283c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes        ss << "vkCreateImage format parameter (" << string_VkFormat(pCreateInfo->format) << ") is an unsupported format";
6293251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
6303251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        VALIDATION_ERROR_02155, "IMAGE", "%s. %s", ss.str().c_str(), validation_error_map[VALIDATION_ERROR_02155]);
6313c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes
6323251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        return skip;
6333c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes    }
6348dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
6353c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes    // Validate that format supports usage as color attachment
6363c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes    if (pCreateInfo->usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {
6373c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes        if ((pCreateInfo->tiling == VK_IMAGE_TILING_OPTIMAL) &&
6383c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes            ((properties->optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) == 0)) {
6398dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski            std::stringstream ss;
6403c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes            ss << "vkCreateImage: VkFormat for TILING_OPTIMAL image (" << string_VkFormat(pCreateInfo->format)
6413c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes               << ") does not support requested Image usage type VK_IMAGE_USAGE_COLOR_ATTACHMENT";
6423251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |=
6438dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
6443c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes                        VALIDATION_ERROR_02158, "IMAGE", "%s. %s", ss.str().c_str(), validation_error_map[VALIDATION_ERROR_02158]);
6458dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski        }
6463c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes        if ((pCreateInfo->tiling == VK_IMAGE_TILING_LINEAR) &&
6473c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes            ((properties->linearTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) == 0)) {
6488dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski            std::stringstream ss;
6493c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes            ss << "vkCreateImage: VkFormat for TILING_LINEAR image (" << string_VkFormat(pCreateInfo->format)
6503c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes               << ") does not support requested Image usage type VK_IMAGE_USAGE_COLOR_ATTACHMENT";
6513251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |=
6528dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
6533c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes                        VALIDATION_ERROR_02153, "IMAGE", "%s. %s", ss.str().c_str(), validation_error_map[VALIDATION_ERROR_02153]);
6548dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski        }
6553c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes    }
6568dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
6573c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes    // Validate that format supports usage as depth/stencil attachment
6583c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes    if (pCreateInfo->usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
6593c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes        if ((pCreateInfo->tiling == VK_IMAGE_TILING_OPTIMAL) &&
6603c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes            ((properties->optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) == 0)) {
6613c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes            std::stringstream ss;
6623c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes            ss << "vkCreateImage: VkFormat for TILING_OPTIMAL image (" << string_VkFormat(pCreateInfo->format)
6633c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes               << ") does not support requested Image usage type VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT";
6643251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |=
6653c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes                log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
6663c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes                        VALIDATION_ERROR_02159, "IMAGE", "%s. %s", ss.str().c_str(), validation_error_map[VALIDATION_ERROR_02159]);
6678dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski        }
6683c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes        if ((pCreateInfo->tiling == VK_IMAGE_TILING_LINEAR) &&
6693c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes            ((properties->linearTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) == 0)) {
6703c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes            std::stringstream ss;
6713c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes            ss << "vkCreateImage: VkFormat for TILING_LINEAR image (" << string_VkFormat(pCreateInfo->format)
6723c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes               << ") does not support requested Image usage type VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT";
6733251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |=
6743c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes                log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
6753c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes                        VALIDATION_ERROR_02154, "IMAGE", "%s. %s", ss.str().c_str(), validation_error_map[VALIDATION_ERROR_02154]);
6768dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski        }
6778dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    }
6788dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
679d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski    const VkImageFormatProperties *ImageFormatProperties = GetImageFormatProperties(
680d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski        device_data, pCreateInfo->format, pCreateInfo->imageType, pCreateInfo->tiling, pCreateInfo->usage, pCreateInfo->flags);
6818dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
682d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski    VkDeviceSize imageGranularity = GetPhysicalDeviceProperties(device_data)->limits.bufferImageGranularity;
6838dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    imageGranularity = imageGranularity == 1 ? 0 : imageGranularity;
68460f59be7ded9ccf2d57c36b2e0974cc2798cf844Tobin Ehlis    // TODO : This is also covering 2918 & 2919. Break out into separate checks
685a9991b9f53d0be4fecc63bdbdf3de9950070a3a5Mark Lobodzinski    if ((pCreateInfo->extent.width <= 0) || (pCreateInfo->extent.height <= 0) || (pCreateInfo->extent.depth <= 0)) {
6863251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 0, __LINE__,
6873251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        VALIDATION_ERROR_02917, "Image",
6883251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "CreateImage extent is 0 for at least one required dimension for image: "
6893251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "Width = %d Height = %d Depth = %d. %s",
6903251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        pCreateInfo->extent.width, pCreateInfo->extent.height, pCreateInfo->extent.depth,
6913251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        validation_error_map[VALIDATION_ERROR_02917]);
6928dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    }
6938dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
6948dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    // TODO: VALIDATION_ERROR_02125 VALIDATION_ERROR_02126 VALIDATION_ERROR_02128 VALIDATION_ERROR_00720
6958dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    // All these extent-related VUs should be checked here
696d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski    if ((pCreateInfo->extent.depth > ImageFormatProperties->maxExtent.depth) ||
697d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski        (pCreateInfo->extent.width > ImageFormatProperties->maxExtent.width) ||
698d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski        (pCreateInfo->extent.height > ImageFormatProperties->maxExtent.height)) {
6993251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 0, __LINE__,
7003251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
7013251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "CreateImage extents exceed allowable limits for format: "
7023251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "Width = %d Height = %d Depth = %d:  Limits for Width = %d Height = %d Depth = %d for format %s.",
7033251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        pCreateInfo->extent.width, pCreateInfo->extent.height, pCreateInfo->extent.depth,
7043251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        ImageFormatProperties->maxExtent.width, ImageFormatProperties->maxExtent.height,
7053251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        ImageFormatProperties->maxExtent.depth, string_VkFormat(pCreateInfo->format));
7068dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    }
7078dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
708cf2ce8673669ca1111e333bdea272c4dd57cb5c2Dave Houlton    uint64_t totalSize =
709cf2ce8673669ca1111e333bdea272c4dd57cb5c2Dave Houlton        ((uint64_t)pCreateInfo->extent.width * (uint64_t)pCreateInfo->extent.height * (uint64_t)pCreateInfo->extent.depth *
710cf2ce8673669ca1111e333bdea272c4dd57cb5c2Dave Houlton             (uint64_t)pCreateInfo->arrayLayers * (uint64_t)pCreateInfo->samples * (uint64_t)FormatSize(pCreateInfo->format) +
711cf2ce8673669ca1111e333bdea272c4dd57cb5c2Dave Houlton         (uint64_t)imageGranularity) &
712cf2ce8673669ca1111e333bdea272c4dd57cb5c2Dave Houlton        ~(uint64_t)imageGranularity;
7138dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
714d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski    if (totalSize > ImageFormatProperties->maxResourceSize) {
7153251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 0, __LINE__,
7163251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
7173251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "CreateImage resource size exceeds allowable maximum "
7183251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "Image resource size = 0x%" PRIxLEAST64 ", maximum resource size = 0x%" PRIxLEAST64 " ",
7193251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        totalSize, ImageFormatProperties->maxResourceSize);
7208dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    }
7218dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
7228dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    // TODO: VALIDATION_ERROR_02132
723d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski    if (pCreateInfo->mipLevels > ImageFormatProperties->maxMipLevels) {
7243251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 0, __LINE__,
7253251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
7263251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "CreateImage mipLevels=%d exceeds allowable maximum supported by format of %d", pCreateInfo->mipLevels,
7273251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        ImageFormatProperties->maxMipLevels);
7288dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    }
7298dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
730d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski    if (pCreateInfo->arrayLayers > ImageFormatProperties->maxArrayLayers) {
7313251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(
7328dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski            report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 0, __LINE__, VALIDATION_ERROR_02133,
7338dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski            "Image", "CreateImage arrayLayers=%d exceeds allowable maximum supported by format of %d. %s", pCreateInfo->arrayLayers,
734d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski            ImageFormatProperties->maxArrayLayers, validation_error_map[VALIDATION_ERROR_02133]);
7358dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    }
7368dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
737d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski    if ((pCreateInfo->samples & ImageFormatProperties->sampleCounts) == 0) {
7383251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 0, __LINE__,
7393251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        VALIDATION_ERROR_02138, "Image", "CreateImage samples %s is not supported by format 0x%.8X. %s",
7403251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        string_VkSampleCountFlagBits(pCreateInfo->samples), ImageFormatProperties->sampleCounts,
7413251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        validation_error_map[VALIDATION_ERROR_02138]);
7428dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    }
7438dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
7448dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    if (pCreateInfo->initialLayout != VK_IMAGE_LAYOUT_UNDEFINED && pCreateInfo->initialLayout != VK_IMAGE_LAYOUT_PREINITIALIZED) {
7453251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 0, __LINE__,
7463251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        VALIDATION_ERROR_00731, "Image",
7473251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "vkCreateImage parameter, pCreateInfo->initialLayout, must be VK_IMAGE_LAYOUT_UNDEFINED or "
7483251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "VK_IMAGE_LAYOUT_PREINITIALIZED. %s",
7493251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        validation_error_map[VALIDATION_ERROR_00731]);
7508dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    }
7518dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
75201363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski    if ((pCreateInfo->flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT) && (!GetEnabledFeatures(device_data)->sparseBinding)) {
7533251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
7543251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        VALIDATION_ERROR_02143, "DS",
7553251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "vkCreateImage(): the sparseBinding device feature is disabled: Images cannot be created with the "
7563251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "VK_IMAGE_CREATE_SPARSE_BINDING_BIT set. %s",
7573251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        validation_error_map[VALIDATION_ERROR_02143]);
75801363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski    }
75901363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski
7607e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski    if ((pCreateInfo->flags & VK_IMAGE_CREATE_SPARSE_ALIASED_BIT) && (!GetEnabledFeatures(device_data)->sparseResidencyAliased)) {
7613251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
7623251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        DRAWSTATE_INVALID_FEATURE, "DS",
7633251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "vkCreateImage(): the sparseResidencyAliased device feature is disabled: Images cannot be created with the "
7643251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "VK_IMAGE_CREATE_SPARSE_ALIASED_BIT set.");
7657e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski    }
7667e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski
7673251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
7688dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski}
7698dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
770e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisvoid PostCallRecordCreateImage(layer_data *device_data, const VkImageCreateInfo *pCreateInfo, VkImage *pImage) {
771c06c9b88f5f5bcc7033ba41d5547b048fa6015a4Mark Lobodzinski    IMAGE_LAYOUT_NODE image_state;
772c06c9b88f5f5bcc7033ba41d5547b048fa6015a4Mark Lobodzinski    image_state.layout = pCreateInfo->initialLayout;
773c06c9b88f5f5bcc7033ba41d5547b048fa6015a4Mark Lobodzinski    image_state.format = pCreateInfo->format;
774920311b6aa5614a545cad59521770d0898a75d65Mark Lobodzinski    GetImageMap(device_data)->insert(std::make_pair(*pImage, std::unique_ptr<IMAGE_STATE>(new IMAGE_STATE(*pImage, pCreateInfo))));
775c06c9b88f5f5bcc7033ba41d5547b048fa6015a4Mark Lobodzinski    ImageSubresourcePair subpair{*pImage, false, VkImageSubresource()};
776920311b6aa5614a545cad59521770d0898a75d65Mark Lobodzinski    (*core_validation::GetImageSubresourceMap(device_data))[*pImage].push_back(subpair);
777920311b6aa5614a545cad59521770d0898a75d65Mark Lobodzinski    (*core_validation::GetImageLayoutMap(device_data))[subpair] = image_state;
778c06c9b88f5f5bcc7033ba41d5547b048fa6015a4Mark Lobodzinski}
7798c59133586421be878d393799b30044497f77727Mark Lobodzinski
780e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisbool PreCallValidateDestroyImage(layer_data *device_data, VkImage image, IMAGE_STATE **image_state, VK_OBJECT *obj_struct) {
7818c59133586421be878d393799b30044497f77727Mark Lobodzinski    const CHECK_DISABLED *disabled = core_validation::GetDisables(device_data);
7829a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    *image_state = core_validation::GetImageState(device_data, image);
783cf2ce8673669ca1111e333bdea272c4dd57cb5c2Dave Houlton    *obj_struct = {reinterpret_cast<uint64_t &>(image), kVulkanObjectTypeImage};
7848c59133586421be878d393799b30044497f77727Mark Lobodzinski    if (disabled->destroy_image) return false;
7858c59133586421be878d393799b30044497f77727Mark Lobodzinski    bool skip = false;
7868c59133586421be878d393799b30044497f77727Mark Lobodzinski    if (*image_state) {
7878c59133586421be878d393799b30044497f77727Mark Lobodzinski        skip |= core_validation::ValidateObjectNotInUse(device_data, *image_state, *obj_struct, VALIDATION_ERROR_00743);
7888c59133586421be878d393799b30044497f77727Mark Lobodzinski    }
7898c59133586421be878d393799b30044497f77727Mark Lobodzinski    return skip;
7908c59133586421be878d393799b30044497f77727Mark Lobodzinski}
7918c59133586421be878d393799b30044497f77727Mark Lobodzinski
792e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisvoid PostCallRecordDestroyImage(layer_data *device_data, VkImage image, IMAGE_STATE *image_state, VK_OBJECT obj_struct) {
7938c59133586421be878d393799b30044497f77727Mark Lobodzinski    core_validation::invalidateCommandBuffers(device_data, image_state->cb_bindings, obj_struct);
7948c59133586421be878d393799b30044497f77727Mark Lobodzinski    // Clean up memory mapping, bindings and range references for image
7958c59133586421be878d393799b30044497f77727Mark Lobodzinski    for (auto mem_binding : image_state->GetBoundMemory()) {
7969a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto mem_info = core_validation::GetMemObjInfo(device_data, mem_binding);
7978c59133586421be878d393799b30044497f77727Mark Lobodzinski        if (mem_info) {
7988c59133586421be878d393799b30044497f77727Mark Lobodzinski            core_validation::RemoveImageMemoryRange(obj_struct.handle, mem_info);
7998c59133586421be878d393799b30044497f77727Mark Lobodzinski        }
8008c59133586421be878d393799b30044497f77727Mark Lobodzinski    }
8017a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski    core_validation::ClearMemoryObjectBindings(device_data, obj_struct.handle, kVulkanObjectTypeImage);
8028c59133586421be878d393799b30044497f77727Mark Lobodzinski    // Remove image from imageMap
8038c59133586421be878d393799b30044497f77727Mark Lobodzinski    core_validation::GetImageMap(device_data)->erase(image);
8048c59133586421be878d393799b30044497f77727Mark Lobodzinski    std::unordered_map<VkImage, std::vector<ImageSubresourcePair>> *imageSubresourceMap =
8058c59133586421be878d393799b30044497f77727Mark Lobodzinski        core_validation::GetImageSubresourceMap(device_data);
8068c59133586421be878d393799b30044497f77727Mark Lobodzinski
8078c59133586421be878d393799b30044497f77727Mark Lobodzinski    const auto &sub_entry = imageSubresourceMap->find(image);
8088c59133586421be878d393799b30044497f77727Mark Lobodzinski    if (sub_entry != imageSubresourceMap->end()) {
8098c59133586421be878d393799b30044497f77727Mark Lobodzinski        for (const auto &pair : sub_entry->second) {
8108c59133586421be878d393799b30044497f77727Mark Lobodzinski            core_validation::GetImageLayoutMap(device_data)->erase(pair);
8118c59133586421be878d393799b30044497f77727Mark Lobodzinski        }
8128c59133586421be878d393799b30044497f77727Mark Lobodzinski        imageSubresourceMap->erase(sub_entry);
8138c59133586421be878d393799b30044497f77727Mark Lobodzinski    }
8148c59133586421be878d393799b30044497f77727Mark Lobodzinski}
815509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski
816e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisbool ValidateImageAttributes(layer_data *device_data, IMAGE_STATE *image_state, VkImageSubresourceRange range) {
817509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski    bool skip = false;
818509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
819509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski
820509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski    if (range.aspectMask != VK_IMAGE_ASPECT_COLOR_BIT) {
821509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski        char const str[] = "vkCmdClearColorImage aspectMasks for all subresource ranges must be set to VK_IMAGE_ASPECT_COLOR_BIT";
822509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
823509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski                        reinterpret_cast<uint64_t &>(image_state->image), __LINE__, DRAWSTATE_INVALID_IMAGE_ASPECT, "IMAGE", str);
824509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski    }
825509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski
82616769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton    if (FormatIsDepthOrStencil(image_state->createInfo.format)) {
827509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski        char const str[] = "vkCmdClearColorImage called with depth/stencil image.";
828509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
829509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski                        reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01088, "IMAGE", "%s. %s", str,
830509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski                        validation_error_map[VALIDATION_ERROR_01088]);
83116769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton    } else if (FormatIsCompressed(image_state->createInfo.format)) {
832509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski        char const str[] = "vkCmdClearColorImage called with compressed image.";
833509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
834509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski                        reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01088, "IMAGE", "%s. %s", str,
835509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski                        validation_error_map[VALIDATION_ERROR_01088]);
836509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski    }
837509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski
838509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski    if (!(image_state->createInfo.usage & VK_IMAGE_USAGE_TRANSFER_DST_BIT)) {
839509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski        char const str[] = "vkCmdClearColorImage called with image created without VK_IMAGE_USAGE_TRANSFER_DST_BIT.";
840509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
841509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski                        reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01084, "IMAGE", "%s. %s", str,
842509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski                        validation_error_map[VALIDATION_ERROR_01084]);
843509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski    }
844509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski    return skip;
845509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski}
846623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski
84795b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinskiuint32_t ResolveRemainingLevels(const VkImageSubresourceRange *range, uint32_t mip_levels) {
84895b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski    // Return correct number of mip levels taking into account VK_REMAINING_MIP_LEVELS
84995b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski    uint32_t mip_level_count = range->levelCount;
85008c7aae3177092f8567e2b5a946457be61616e9aMark Lobodzinski    if (range->levelCount == VK_REMAINING_MIP_LEVELS) {
85195b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski        mip_level_count = mip_levels - range->baseMipLevel;
852623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    }
85395b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski    return mip_level_count;
854623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski}
855623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski
85695b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinskiuint32_t ResolveRemainingLayers(const VkImageSubresourceRange *range, uint32_t layers) {
85795b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski    // Return correct number of layers taking into account VK_REMAINING_ARRAY_LAYERS
85895b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski    uint32_t array_layer_count = range->layerCount;
85995b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski    if (range->layerCount == VK_REMAINING_ARRAY_LAYERS) {
86095b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski        array_layer_count = layers - range->baseArrayLayer;
861623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    }
86295b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski    return array_layer_count;
863623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski}
864623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski
865e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisbool VerifyClearImageLayout(layer_data *device_data, GLOBAL_CB_NODE *cb_node, IMAGE_STATE *image_state,
866623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                            VkImageSubresourceRange range, VkImageLayout dest_image_layout, const char *func_name) {
867623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    bool skip = false;
868623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
869623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski
87095b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski    uint32_t level_count = ResolveRemainingLevels(&range, image_state->createInfo.mipLevels);
87195b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski    uint32_t layer_count = ResolveRemainingLayers(&range, image_state->createInfo.arrayLayers);
872623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski
873623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    if (dest_image_layout != VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
874623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        if (dest_image_layout == VK_IMAGE_LAYOUT_GENERAL) {
875623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski            if (image_state->createInfo.tiling != VK_IMAGE_TILING_LINEAR) {
876623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                // LAYOUT_GENERAL is allowed, but may not be performance optimal, flag as perf warning.
877fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
878fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                                reinterpret_cast<uint64_t &>(image_state->image), __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
879623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                                "%s: Layout for cleared image should be TRANSFER_DST_OPTIMAL instead of GENERAL.", func_name);
880623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski            }
881623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        } else {
882623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski            UNIQUE_VALIDATION_ERROR_CODE error_code = VALIDATION_ERROR_01086;
883623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski            if (strcmp(func_name, "vkCmdClearDepthStencilImage()") == 0) {
884623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                error_code = VALIDATION_ERROR_01101;
885623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski            } else {
886623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                assert(strcmp(func_name, "vkCmdClearColorImage()") == 0);
887623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski            }
888fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
889fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                            reinterpret_cast<uint64_t &>(image_state->image), __LINE__, error_code, "DS",
890fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                            "%s: Layout for cleared image is %s but can only be "
891fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                            "TRANSFER_DST_OPTIMAL or GENERAL. %s",
892fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                            func_name, string_VkImageLayout(dest_image_layout), validation_error_map[error_code]);
893623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        }
894623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    }
895623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski
89695b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski    for (uint32_t level_index = 0; level_index < level_count; ++level_index) {
89795b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski        uint32_t level = level_index + range.baseMipLevel;
89895b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski        for (uint32_t layer_index = 0; layer_index < layer_count; ++layer_index) {
89995b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski            uint32_t layer = layer_index + range.baseArrayLayer;
90095b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski            VkImageSubresource sub = {range.aspectMask, level, layer};
901623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski            IMAGE_CMD_BUF_LAYOUT_NODE node;
90255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski            if (FindCmdBufLayout(device_data, cb_node, image_state->image, sub, node)) {
903623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                if (node.layout != dest_image_layout) {
904623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                    UNIQUE_VALIDATION_ERROR_CODE error_code = VALIDATION_ERROR_01085;
905623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                    if (strcmp(func_name, "vkCmdClearDepthStencilImage()") == 0) {
906623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                        error_code = VALIDATION_ERROR_01100;
907623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                    } else {
908623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                        assert(strcmp(func_name, "vkCmdClearColorImage()") == 0);
909623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                    }
910623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                    skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0,
911623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                                    __LINE__, error_code, "DS",
912623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                                    "%s: Cannot clear an image whose layout is %s and "
913623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                                    "doesn't match the current layout %s. %s",
914623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                                    func_name, string_VkImageLayout(dest_image_layout), string_VkImageLayout(node.layout),
915623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                                    validation_error_map[error_code]);
916623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                }
917623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski            }
918623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        }
919623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    }
920623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski
921623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    return skip;
922623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski}
923623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski
924e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisvoid RecordClearImageLayout(layer_data *device_data, GLOBAL_CB_NODE *cb_node, VkImage image, VkImageSubresourceRange range,
925e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlis                            VkImageLayout dest_image_layout) {
92695b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski    VkImageCreateInfo *image_create_info = &(GetImageState(device_data, image)->createInfo);
92795b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski    uint32_t level_count = ResolveRemainingLevels(&range, image_create_info->mipLevels);
92895b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski    uint32_t layer_count = ResolveRemainingLayers(&range, image_create_info->arrayLayers);
92995b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski
93095b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski    for (uint32_t level_index = 0; level_index < level_count; ++level_index) {
93195b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski        uint32_t level = level_index + range.baseMipLevel;
93295b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski        for (uint32_t layer_index = 0; layer_index < layer_count; ++layer_index) {
93395b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski            uint32_t layer = layer_index + range.baseArrayLayer;
93495b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski            VkImageSubresource sub = {range.aspectMask, level, layer};
935623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski            IMAGE_CMD_BUF_LAYOUT_NODE node;
93655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski            if (!FindCmdBufLayout(device_data, cb_node, image, sub, node)) {
93755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                SetLayout(device_data, cb_node, image, sub, IMAGE_CMD_BUF_LAYOUT_NODE(dest_image_layout, dest_image_layout));
938623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski            }
939623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        }
940623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    }
941623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski}
942623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski
943e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisbool PreCallValidateCmdClearColorImage(layer_data *dev_data, VkCommandBuffer commandBuffer, VkImage image,
944623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                                       VkImageLayout imageLayout, uint32_t rangeCount, const VkImageSubresourceRange *pRanges) {
945623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    bool skip = false;
946623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    // TODO : Verify memory is in VK_IMAGE_STATE_CLEAR state
9479a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto cb_node = GetCBNode(dev_data, commandBuffer);
9489a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto image_state = GetImageState(dev_data, image);
949623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    if (cb_node && image_state) {
950623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        skip |= ValidateMemoryIsBoundToImage(dev_data, image_state, "vkCmdClearColorImage()", VALIDATION_ERROR_02527);
951baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt        skip |= ValidateCmdQueueFlags(dev_data, cb_node, "vkCmdClearColorImage()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT,
952baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt                                      VALIDATION_ERROR_01095);
953623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        skip |= ValidateCmd(dev_data, cb_node, CMD_CLEARCOLORIMAGE, "vkCmdClearColorImage()");
954623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        skip |= insideRenderPass(dev_data, cb_node, "vkCmdClearColorImage()", VALIDATION_ERROR_01096);
955623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        for (uint32_t i = 0; i < rangeCount; ++i) {
956623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski            skip |= ValidateImageAttributes(dev_data, image_state, pRanges[i]);
95708c7aae3177092f8567e2b5a946457be61616e9aMark Lobodzinski            skip |= VerifyClearImageLayout(dev_data, cb_node, image_state, pRanges[i], imageLayout, "vkCmdClearColorImage()");
958623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        }
959623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    }
960623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    return skip;
961623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski}
962623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski
963623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski// This state recording routine is shared between ClearColorImage and ClearDepthStencilImage
964e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisvoid PreCallRecordCmdClearImage(layer_data *dev_data, VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout,
965e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlis                                uint32_t rangeCount, const VkImageSubresourceRange *pRanges, CMD_TYPE cmd_type) {
9669a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto cb_node = GetCBNode(dev_data, commandBuffer);
9679a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto image_state = GetImageState(dev_data, image);
968623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    if (cb_node && image_state) {
969623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        AddCommandBufferBindingImage(dev_data, cb_node, image_state);
970623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        std::function<bool()> function = [=]() {
971623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski            SetImageMemoryValid(dev_data, image_state, true);
972623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski            return false;
973623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        };
974623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        cb_node->validate_functions.push_back(function);
9759a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        core_validation::UpdateCmdBufferLastCmd(cb_node, cmd_type);
976623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        for (uint32_t i = 0; i < rangeCount; ++i) {
977623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski            RecordClearImageLayout(dev_data, cb_node, image, pRanges[i], imageLayout);
978623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        }
979623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    }
980623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski}
981623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski
982e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisbool PreCallValidateCmdClearDepthStencilImage(layer_data *device_data, VkCommandBuffer commandBuffer, VkImage image,
983e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlis                                              VkImageLayout imageLayout, uint32_t rangeCount,
984623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                                              const VkImageSubresourceRange *pRanges) {
985623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    bool skip = false;
9867244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
9877244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski
988623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    // TODO : Verify memory is in VK_IMAGE_STATE_CLEAR state
9899a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto cb_node = GetCBNode(device_data, commandBuffer);
9909a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto image_state = GetImageState(device_data, image);
991623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    if (cb_node && image_state) {
9927244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski        skip |= ValidateMemoryIsBoundToImage(device_data, image_state, "vkCmdClearDepthStencilImage()", VALIDATION_ERROR_02528);
993baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt        skip |= ValidateCmdQueueFlags(device_data, cb_node, "vkCmdClearDepthStencilImage()", VK_QUEUE_GRAPHICS_BIT,
994baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt                                      VALIDATION_ERROR_01110);
9957244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski        skip |= ValidateCmd(device_data, cb_node, CMD_CLEARDEPTHSTENCILIMAGE, "vkCmdClearDepthStencilImage()");
9967244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski        skip |= insideRenderPass(device_data, cb_node, "vkCmdClearDepthStencilImage()", VALIDATION_ERROR_01111);
997623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        for (uint32_t i = 0; i < rangeCount; ++i) {
99808c7aae3177092f8567e2b5a946457be61616e9aMark Lobodzinski            skip |=
99908c7aae3177092f8567e2b5a946457be61616e9aMark Lobodzinski                VerifyClearImageLayout(device_data, cb_node, image_state, pRanges[i], imageLayout, "vkCmdClearDepthStencilImage()");
10007244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski            // Image aspect must be depth or stencil or both
10017244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski            if (((pRanges[i].aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) != VK_IMAGE_ASPECT_DEPTH_BIT) &&
10027244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski                ((pRanges[i].aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) != VK_IMAGE_ASPECT_STENCIL_BIT)) {
10037244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski                char const str[] =
10047244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski                    "vkCmdClearDepthStencilImage aspectMasks for all subresource ranges must be "
10057244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski                    "set to VK_IMAGE_ASPECT_DEPTH_BIT and/or VK_IMAGE_ASPECT_STENCIL_BIT";
10067244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
10077244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski                                (uint64_t)commandBuffer, __LINE__, DRAWSTATE_INVALID_IMAGE_ASPECT, "IMAGE", str);
10087244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski            }
10097244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski        }
101016769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton        if (image_state && !FormatIsDepthOrStencil(image_state->createInfo.format)) {
10117244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski            char const str[] = "vkCmdClearDepthStencilImage called without a depth/stencil image.";
10127244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
10137244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski                            reinterpret_cast<uint64_t &>(image), __LINE__, VALIDATION_ERROR_01103, "IMAGE", "%s. %s", str,
10147244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski                            validation_error_map[VALIDATION_ERROR_01103]);
1015623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        }
1016623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    }
1017623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    return skip;
1018623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski}
1019ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
1020ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski// Returns true if [x, xoffset] and [y, yoffset] overlap
1021ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinskistatic bool RangesIntersect(int32_t start, uint32_t start_offset, int32_t end, uint32_t end_offset) {
1022ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    bool result = false;
1023ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    uint32_t intersection_min = std::max(static_cast<uint32_t>(start), static_cast<uint32_t>(end));
1024ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    uint32_t intersection_max = std::min(static_cast<uint32_t>(start) + start_offset, static_cast<uint32_t>(end) + end_offset);
1025ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
1026ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    if (intersection_max > intersection_min) {
1027ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski        result = true;
1028ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    }
1029ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    return result;
1030ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski}
1031ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
1032ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski// Returns true if two VkImageCopy structures overlap
1033ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinskistatic bool RegionIntersects(const VkImageCopy *src, const VkImageCopy *dst, VkImageType type) {
1034ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    bool result = false;
1035ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    if ((src->srcSubresource.mipLevel == dst->dstSubresource.mipLevel) &&
1036ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski        (RangesIntersect(src->srcSubresource.baseArrayLayer, src->srcSubresource.layerCount, dst->dstSubresource.baseArrayLayer,
1037ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski                         dst->dstSubresource.layerCount))) {
1038ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski        result = true;
1039ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski        switch (type) {
1040ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski            case VK_IMAGE_TYPE_3D:
1041ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski                result &= RangesIntersect(src->srcOffset.z, src->extent.depth, dst->dstOffset.z, dst->extent.depth);
1042ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski            // Intentionally fall through to 2D case
1043ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski            case VK_IMAGE_TYPE_2D:
1044ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski                result &= RangesIntersect(src->srcOffset.y, src->extent.height, dst->dstOffset.y, dst->extent.height);
1045ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski            // Intentionally fall through to 1D case
1046ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski            case VK_IMAGE_TYPE_1D:
1047ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski                result &= RangesIntersect(src->srcOffset.x, src->extent.width, dst->dstOffset.x, dst->extent.width);
1048ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski                break;
1049ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski            default:
1050ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski                // Unrecognized or new IMAGE_TYPE enums will be caught in parameter_validation
1051ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski                assert(false);
1052ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski        }
1053ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    }
1054ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    return result;
1055ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski}
1056ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
10573fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton// Returns non-zero if offset and extent exceed image extents
10583fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houltonstatic const uint32_t x_bit = 1;
10593fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houltonstatic const uint32_t y_bit = 2;
10603fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houltonstatic const uint32_t z_bit = 4;
1061cf2ce8673669ca1111e333bdea272c4dd57cb5c2Dave Houltonstatic uint32_t ExceedsBounds(const VkOffset3D *offset, const VkExtent3D *extent, const VkExtent3D *image_extent) {
10623fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton    uint32_t result = 0;
1063ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    // Extents/depths cannot be negative but checks left in for clarity
10645971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton    if ((offset->z + extent->depth > image_extent->depth) || (offset->z < 0) ||
10655971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        ((offset->z + static_cast<int32_t>(extent->depth)) < 0)) {
10663fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton        result |= z_bit;
10675971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton    }
10685971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton    if ((offset->y + extent->height > image_extent->height) || (offset->y < 0) ||
10695971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        ((offset->y + static_cast<int32_t>(extent->height)) < 0)) {
10703fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton        result |= y_bit;
10715971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton    }
10725971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton    if ((offset->x + extent->width > image_extent->width) || (offset->x < 0) ||
10735971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        ((offset->x + static_cast<int32_t>(extent->width)) < 0)) {
10743fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton        result |= x_bit;
1075ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    }
1076ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    return result;
1077ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski}
1078ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
10796a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski// Test if two VkExtent3D structs are equivalent
10806a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinskistatic inline bool IsExtentEqual(const VkExtent3D *extent, const VkExtent3D *other_extent) {
10816a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    bool result = true;
10826a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    if ((extent->width != other_extent->width) || (extent->height != other_extent->height) ||
10836a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        (extent->depth != other_extent->depth)) {
10846a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        result = false;
10856a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    }
10866a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    return result;
10876a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski}
10886a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
10896a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski// Returns the image extent of a specific subresource.
10906a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinskistatic inline VkExtent3D GetImageSubresourceExtent(const IMAGE_STATE *img, const VkImageSubresourceLayers *subresource) {
10916a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    const uint32_t mip = subresource->mipLevel;
10923fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton
10933fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton    // Return zero extent if mip level doesn't exist
1094cf2ce8673669ca1111e333bdea272c4dd57cb5c2Dave Houlton    if (mip >= img->createInfo.mipLevels) {
1095cf2ce8673669ca1111e333bdea272c4dd57cb5c2Dave Houlton        return VkExtent3D{0, 0, 0};
10963fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton    }
1097cf2ce8673669ca1111e333bdea272c4dd57cb5c2Dave Houlton
10985971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton    // Don't allow mip adjustment to create 0 dim, but pass along a 0 if that's what subresource specified
10993fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton    VkExtent3D extent = img->createInfo.extent;
11005971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton    extent.width = (0 == extent.width ? 0 : std::max(1U, extent.width >> mip));
11015971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton    extent.height = (0 == extent.height ? 0 : std::max(1U, extent.height >> mip));
11025971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton    extent.depth = (0 == extent.depth ? 0 : std::max(1U, extent.depth >> mip));
11033fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton
11043fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton    // For 2D images, the number of layers present becomes the effective depth (for 2D <-> 3D copies)
11053fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton    // In this case the depth extent is not diminished with mip level
1106cf2ce8673669ca1111e333bdea272c4dd57cb5c2Dave Houlton    if (VK_IMAGE_TYPE_2D == img->createInfo.imageType) {
11073fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton        extent.depth = img->createInfo.arrayLayers;
11083fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton    }
11093fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton
11106a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    return extent;
11116a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski}
11126a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
11136a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski// Test if the extent argument has all dimensions set to 0.
11145971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houltonstatic inline bool IsExtentAllZeroes(const VkExtent3D *extent) {
11156a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    return ((extent->width == 0) && (extent->height == 0) && (extent->depth == 0));
11166a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski}
11176a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
11185971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton// Test if the extent argument has any dimensions set to 0.
11195971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houltonstatic inline bool IsExtentSizeZero(const VkExtent3D *extent) {
11205971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton    return ((extent->width == 0) || (extent->height == 0) || (extent->depth == 0));
11215971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton}
11225971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton
11236a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski// Returns the image transfer granularity for a specific image scaled by compressed block size if necessary.
11246a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinskistatic inline VkExtent3D GetScaledItg(layer_data *device_data, const GLOBAL_CB_NODE *cb_node, const IMAGE_STATE *img) {
11256a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    // Default to (0, 0, 0) granularity in case we can't find the real granularity for the physical device.
11266a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    VkExtent3D granularity = {0, 0, 0};
11276a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    auto pPool = GetCommandPoolNode(device_data, cb_node->createInfo.commandPool);
11286a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    if (pPool) {
11296a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        granularity =
11306a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            GetPhysDevProperties(device_data)->queue_family_properties[pPool->queueFamilyIndex].minImageTransferGranularity;
113116769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton        if (FormatIsCompressed(img->createInfo.format)) {
113216769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton            auto block_size = FormatCompressedTexelBlockExtent(img->createInfo.format);
11336a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            granularity.width *= block_size.width;
11346a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            granularity.height *= block_size.height;
11356a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
11366a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    }
11376a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    return granularity;
11386a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski}
11396a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
11406a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski// Test elements of a VkExtent3D structure against alignment constraints contained in another VkExtent3D structure
11416a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinskistatic inline bool IsExtentAligned(const VkExtent3D *extent, const VkExtent3D *granularity) {
11426a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    bool valid = true;
114316769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton    if ((SafeModulo(extent->depth, granularity->depth) != 0) || (SafeModulo(extent->width, granularity->width) != 0) ||
114416769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton        (SafeModulo(extent->height, granularity->height) != 0)) {
11456a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        valid = false;
11466a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    }
11476a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    return valid;
11486a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski}
11496a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
11506a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski// Check elements of a VkOffset3D structure against a queue family's Image Transfer Granularity values
11516a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinskistatic inline bool CheckItgOffset(layer_data *device_data, const GLOBAL_CB_NODE *cb_node, const VkOffset3D *offset,
11526a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                  const VkExtent3D *granularity, const uint32_t i, const char *function, const char *member) {
11536a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
11546a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    bool skip = false;
11556a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    VkExtent3D offset_extent = {};
11566a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    offset_extent.width = static_cast<uint32_t>(abs(offset->x));
11576a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    offset_extent.height = static_cast<uint32_t>(abs(offset->y));
11586a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    offset_extent.depth = static_cast<uint32_t>(abs(offset->z));
11595971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton    if (IsExtentAllZeroes(granularity)) {
11606a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // If the queue family image transfer granularity is (0, 0, 0), then the offset must always be (0, 0, 0)
11615971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        if (IsExtentAllZeroes(&offset_extent) == false) {
1162fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski            skip |=
1163fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1164fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                        reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, DRAWSTATE_IMAGE_TRANSFER_GRANULARITY, "DS",
1165fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                        "%s: pRegion[%d].%s (x=%d, y=%d, z=%d) must be (x=0, y=0, z=0) "
1166fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                        "when the command buffer's queue family image transfer granularity is (w=0, h=0, d=0).",
1167fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                        function, i, member, offset->x, offset->y, offset->z);
11686a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
11696a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    } else {
11706a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // If the queue family image transfer granularity is not (0, 0, 0), then the offset dimensions must always be even
11716a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // integer multiples of the image transfer granularity.
11726a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if (IsExtentAligned(&offset_extent, granularity) == false) {
1173fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski            skip |= log_msg(
1174fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1175fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, DRAWSTATE_IMAGE_TRANSFER_GRANULARITY, "DS",
1176fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                "%s: pRegion[%d].%s (x=%d, y=%d, z=%d) dimensions must be even integer "
1177fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                "multiples of this command buffer's queue family image transfer granularity (w=%d, h=%d, d=%d).",
1178fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                function, i, member, offset->x, offset->y, offset->z, granularity->width, granularity->height, granularity->depth);
11796a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
11806a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    }
11816a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    return skip;
11826a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski}
11836a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
11846a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski// Check elements of a VkExtent3D structure against a queue family's Image Transfer Granularity values
11856a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinskistatic inline bool CheckItgExtent(layer_data *device_data, const GLOBAL_CB_NODE *cb_node, const VkExtent3D *extent,
11866a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                  const VkOffset3D *offset, const VkExtent3D *granularity, const VkExtent3D *subresource_extent,
11876a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                  const uint32_t i, const char *function, const char *member) {
11886a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
11896a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    bool skip = false;
11905971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton    if (IsExtentAllZeroes(granularity)) {
11916a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // If the queue family image transfer granularity is (0, 0, 0), then the extent must always match the image
11926a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // subresource extent.
11936a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if (IsExtentEqual(extent, subresource_extent) == false) {
1194fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski            skip |=
1195fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1196fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                        reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, DRAWSTATE_IMAGE_TRANSFER_GRANULARITY, "DS",
1197fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                        "%s: pRegion[%d].%s (w=%d, h=%d, d=%d) must match the image subresource extents (w=%d, h=%d, d=%d) "
1198fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                        "when the command buffer's queue family image transfer granularity is (w=0, h=0, d=0).",
1199fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                        function, i, member, extent->width, extent->height, extent->depth, subresource_extent->width,
1200fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                        subresource_extent->height, subresource_extent->depth);
12016a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
12026a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    } else {
12036a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // If the queue family image transfer granularity is not (0, 0, 0), then the extent dimensions must always be even
12046a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // integer multiples of the image transfer granularity or the offset + extent dimensions must always match the image
12056a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // subresource extent dimensions.
12066a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        VkExtent3D offset_extent_sum = {};
12076a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        offset_extent_sum.width = static_cast<uint32_t>(abs(offset->x)) + extent->width;
12086a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        offset_extent_sum.height = static_cast<uint32_t>(abs(offset->y)) + extent->height;
12096a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        offset_extent_sum.depth = static_cast<uint32_t>(abs(offset->z)) + extent->depth;
12106a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if ((IsExtentAligned(extent, granularity) == false) && (IsExtentEqual(&offset_extent_sum, subresource_extent) == false)) {
12116a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            skip |=
1212fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1213fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                        reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, DRAWSTATE_IMAGE_TRANSFER_GRANULARITY, "DS",
12146a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                        "%s: pRegion[%d].%s (w=%d, h=%d, d=%d) dimensions must be even integer multiples of this command buffer's "
12156a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                        "queue family image transfer granularity (w=%d, h=%d, d=%d) or offset (x=%d, y=%d, z=%d) + "
12166a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                        "extent (w=%d, h=%d, d=%d) must match the image subresource extents (w=%d, h=%d, d=%d).",
12176a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                        function, i, member, extent->width, extent->height, extent->depth, granularity->width, granularity->height,
12186a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                        granularity->depth, offset->x, offset->y, offset->z, extent->width, extent->height, extent->depth,
12196a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                        subresource_extent->width, subresource_extent->height, subresource_extent->depth);
12206a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
12216a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    }
12226a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    return skip;
12236a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski}
12246a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
12256a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski// Check a uint32_t width or stride value against a queue family's Image Transfer Granularity width value
12266a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinskistatic inline bool CheckItgInt(layer_data *device_data, const GLOBAL_CB_NODE *cb_node, const uint32_t value,
12276a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                               const uint32_t granularity, const uint32_t i, const char *function, const char *member) {
12286a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
12296a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
12306a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    bool skip = false;
123116769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton    if (SafeModulo(value, granularity) != 0) {
1232fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1233fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                        reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, DRAWSTATE_IMAGE_TRANSFER_GRANULARITY, "DS",
12346a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                        "%s: pRegion[%d].%s (%d) must be an even integer multiple of this command buffer's queue family image "
12356a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                        "transfer granularity width (%d).",
12366a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                        function, i, member, value, granularity);
12376a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    }
12386a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    return skip;
12396a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski}
12406a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
12416a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski// Check a VkDeviceSize value against a queue family's Image Transfer Granularity width value
12426a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinskistatic inline bool CheckItgSize(layer_data *device_data, const GLOBAL_CB_NODE *cb_node, const VkDeviceSize value,
12436a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                const uint32_t granularity, const uint32_t i, const char *function, const char *member) {
12446a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
12456a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    bool skip = false;
124616769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton    if (SafeModulo(value, granularity) != 0) {
1247fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1248fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                        reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, DRAWSTATE_IMAGE_TRANSFER_GRANULARITY, "DS",
12496a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                        "%s: pRegion[%d].%s (%" PRIdLEAST64
12506a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                        ") must be an even integer multiple of this command buffer's queue family image transfer "
12516a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                        "granularity width (%d).",
12526a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                        function, i, member, value, granularity);
12536a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    }
12546a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    return skip;
12556a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski}
12566a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
12576a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski// Check valid usage Image Tranfer Granularity requirements for elements of a VkBufferImageCopy structure
12586a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinskibool ValidateCopyBufferImageTransferGranularityRequirements(layer_data *device_data, const GLOBAL_CB_NODE *cb_node,
12596a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                                            const IMAGE_STATE *img, const VkBufferImageCopy *region,
12606a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                                            const uint32_t i, const char *function) {
12616a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    bool skip = false;
126216769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton    if (FormatIsCompressed(img->createInfo.format) == true) {
12636a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // TODO: Add granularity checking for compressed formats
12646a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
12656a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // bufferRowLength must be a multiple of the compressed texel block width
12666a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // bufferImageHeight must be a multiple of the compressed texel block height
12676a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // all members of imageOffset must be a multiple of the corresponding dimensions of the compressed texel block
12686a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // bufferOffset must be a multiple of the compressed texel block size in bytes
12696a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // imageExtent.width must be a multiple of the compressed texel block width or (imageExtent.width + imageOffset.x)
12706a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        //     must equal the image subresource width
12716a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // imageExtent.height must be a multiple of the compressed texel block height or (imageExtent.height + imageOffset.y)
12726a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        //     must equal the image subresource height
12736a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // imageExtent.depth must be a multiple of the compressed texel block depth or (imageExtent.depth + imageOffset.z)
12746a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        //     must equal the image subresource depth
12756a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    } else {
12766a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        VkExtent3D granularity = GetScaledItg(device_data, cb_node, img);
12776a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        skip |= CheckItgSize(device_data, cb_node, region->bufferOffset, granularity.width, i, function, "bufferOffset");
12786a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        skip |= CheckItgInt(device_data, cb_node, region->bufferRowLength, granularity.width, i, function, "bufferRowLength");
12796a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        skip |= CheckItgInt(device_data, cb_node, region->bufferImageHeight, granularity.width, i, function, "bufferImageHeight");
12806a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        skip |= CheckItgOffset(device_data, cb_node, &region->imageOffset, &granularity, i, function, "imageOffset");
12816a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        VkExtent3D subresource_extent = GetImageSubresourceExtent(img, &region->imageSubresource);
12826a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        skip |= CheckItgExtent(device_data, cb_node, &region->imageExtent, &region->imageOffset, &granularity, &subresource_extent,
12836a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                               i, function, "imageExtent");
12846a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    }
12856a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    return skip;
12866a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski}
12876a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
12886a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski// Check valid usage Image Tranfer Granularity requirements for elements of a VkImageCopy structure
12896a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinskibool ValidateCopyImageTransferGranularityRequirements(layer_data *device_data, const GLOBAL_CB_NODE *cb_node,
12906a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                                      const IMAGE_STATE *img, const VkImageCopy *region, const uint32_t i,
12916a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                                      const char *function) {
12926a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    bool skip = false;
12936a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    VkExtent3D granularity = GetScaledItg(device_data, cb_node, img);
12946a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    skip |= CheckItgOffset(device_data, cb_node, &region->srcOffset, &granularity, i, function, "srcOffset");
12956a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    skip |= CheckItgOffset(device_data, cb_node, &region->dstOffset, &granularity, i, function, "dstOffset");
12966a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    VkExtent3D subresource_extent = GetImageSubresourceExtent(img, &region->dstSubresource);
12976a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    skip |= CheckItgExtent(device_data, cb_node, &region->extent, &region->dstOffset, &granularity, &subresource_extent, i,
12986a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                           function, "extent");
12996a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    return skip;
13006a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski}
13016a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
1302e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisbool PreCallValidateCmdCopyImage(layer_data *device_data, GLOBAL_CB_NODE *cb_node, IMAGE_STATE *src_image_state,
13036a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                 IMAGE_STATE *dst_image_state, uint32_t region_count, const VkImageCopy *regions,
13046a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                 VkImageLayout src_image_layout, VkImageLayout dst_image_layout) {
1305ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    bool skip = false;
1306ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
1307ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    VkCommandBuffer command_buffer = cb_node->commandBuffer;
1308ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
13096a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    for (uint32_t i = 0; i < region_count; i++) {
13106a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if (regions[i].srcSubresource.layerCount == 0) {
13116a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            std::stringstream ss;
13126a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            ss << "vkCmdCopyImage: number of layers in pRegions[" << i << "] srcSubresource is zero";
13136a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
13146a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            reinterpret_cast<uint64_t &>(command_buffer), __LINE__, DRAWSTATE_INVALID_IMAGE_ASPECT, "IMAGE", "%s",
13156a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            ss.str().c_str());
13166a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
1317ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
13186a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if (regions[i].dstSubresource.layerCount == 0) {
13196a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            std::stringstream ss;
13206a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            ss << "vkCmdCopyImage: number of layers in pRegions[" << i << "] dstSubresource is zero";
13216a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
13226a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            reinterpret_cast<uint64_t &>(command_buffer), __LINE__, DRAWSTATE_INVALID_IMAGE_ASPECT, "IMAGE", "%s",
13236a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            ss.str().c_str());
13246a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
1325ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
132657eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt        if (!GetDeviceExtensions(device_data)->khr_maintenance1_enabled) {
132757eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt            // For each region the layerCount member of srcSubresource and dstSubresource must match
132857eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt            if (regions[i].srcSubresource.layerCount != regions[i].dstSubresource.layerCount) {
132957eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt                std::stringstream ss;
133057eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt                ss << "vkCmdCopyImage: number of layers in source and destination subresources for pRegions[" << i
133157eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt                   << "] do not match";
133257eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
133357eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt                                reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01198, "IMAGE", "%s. %s",
133457eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt                                ss.str().c_str(), validation_error_map[VALIDATION_ERROR_01198]);
133557eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt            }
13366a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
1337ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
13386a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // For each region, the aspectMask member of srcSubresource and dstSubresource must match
13396a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if (regions[i].srcSubresource.aspectMask != regions[i].dstSubresource.aspectMask) {
13406a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            char const str[] = "vkCmdCopyImage: Src and dest aspectMasks for each region must match";
13416a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
13426a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01197, "IMAGE", "%s. %s", str,
13436a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            validation_error_map[VALIDATION_ERROR_01197]);
13446a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
1345ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
1346e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton        // For each region, the aspectMask member of srcSubresource must be present in the source image
1347e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton        if (!VerifyAspectsPresent(regions[i].srcSubresource.aspectMask, src_image_state->createInfo.format)) {
1348e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton            std::stringstream ss;
1349e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton            ss << "vkCmdCopyImage: pRegion[" << i
1350e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton               << "] srcSubresource.aspectMask cannot specify aspects not present in source image";
1351e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1352e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton                            reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01200, "IMAGE", "%s. %s",
1353e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton                            ss.str().c_str(), validation_error_map[VALIDATION_ERROR_01200]);
1354e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton        }
1355e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton
1356e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton        // For each region, the aspectMask member of dstSubresource must be present in the destination image
1357e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton        if (!VerifyAspectsPresent(regions[i].dstSubresource.aspectMask, dst_image_state->createInfo.format)) {
1358e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton            std::stringstream ss;
1359e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton            ss << "vkCmdCopyImage: pRegion[" << i << "] dstSubresource.aspectMask cannot specify aspects not present in dest image";
1360e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1361e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton                            reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01201, "IMAGE", "%s. %s",
1362e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton                            ss.str().c_str(), validation_error_map[VALIDATION_ERROR_01201]);
1363e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton        }
1364e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton
13656a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // AspectMask must not contain VK_IMAGE_ASPECT_METADATA_BIT
13666a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if ((regions[i].srcSubresource.aspectMask & VK_IMAGE_ASPECT_METADATA_BIT) ||
13676a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            (regions[i].dstSubresource.aspectMask & VK_IMAGE_ASPECT_METADATA_BIT)) {
13686a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            std::stringstream ss;
13696a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            ss << "vkCmdCopyImage: pRegions[" << i << "] may not specify aspectMask containing VK_IMAGE_ASPECT_METADATA_BIT";
13706a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
13716a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01222, "IMAGE", "%s. %s",
13726a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            ss.str().c_str(), validation_error_map[VALIDATION_ERROR_01222]);
13736a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
1374ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
13756a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // For each region, if aspectMask contains VK_IMAGE_ASPECT_COLOR_BIT, it must not contain either of
13766a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // VK_IMAGE_ASPECT_DEPTH_BIT or VK_IMAGE_ASPECT_STENCIL_BIT
13776a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if ((regions[i].srcSubresource.aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) &&
13786a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            (regions[i].srcSubresource.aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))) {
13796a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            char const str[] = "vkCmdCopyImage aspectMask cannot specify both COLOR and DEPTH/STENCIL aspects";
13806a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
13816a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01221, "IMAGE", "%s. %s", str,
13826a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            validation_error_map[VALIDATION_ERROR_01221]);
13836a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
1384ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
138557eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt        if (!GetDeviceExtensions(device_data)->khr_maintenance1_enabled) {
138657eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt            // If either of the calling command's src_image or dst_image parameters are of VkImageType VK_IMAGE_TYPE_3D,
138757eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt            // the baseArrayLayer and layerCount members of both srcSubresource and dstSubresource must be 0 and 1, respectively
138857eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt            if (((src_image_state->createInfo.imageType == VK_IMAGE_TYPE_3D) ||
138957eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt                 (dst_image_state->createInfo.imageType == VK_IMAGE_TYPE_3D)) &&
139057eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt                ((regions[i].srcSubresource.baseArrayLayer != 0) || (regions[i].srcSubresource.layerCount != 1) ||
139157eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt                 (regions[i].dstSubresource.baseArrayLayer != 0) || (regions[i].dstSubresource.layerCount != 1))) {
139257eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt                std::stringstream ss;
139357eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt                ss << "vkCmdCopyImage: src or dstImage type was IMAGE_TYPE_3D, but in subRegion[" << i
139457eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt                   << "] baseArrayLayer was not zero or layerCount was not 1.";
139557eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
139657eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt                                reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01199, "IMAGE", "%s. %s",
139757eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt                                ss.str().c_str(), validation_error_map[VALIDATION_ERROR_01199]);
139857eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt            }
13996a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
1400ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
14016a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // MipLevel must be less than the mipLevels specified in VkImageCreateInfo when the image was created
14026a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if (regions[i].srcSubresource.mipLevel >= src_image_state->createInfo.mipLevels) {
14036a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            std::stringstream ss;
14046a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            ss << "vkCmdCopyImage: pRegions[" << i
14056a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski               << "] specifies a src mipLevel greater than the number specified when the srcImage was created.";
14066a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
14076a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01223, "IMAGE", "%s. %s",
14086a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            ss.str().c_str(), validation_error_map[VALIDATION_ERROR_01223]);
14096a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
14106a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if (regions[i].dstSubresource.mipLevel >= dst_image_state->createInfo.mipLevels) {
14116a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            std::stringstream ss;
14126a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            ss << "vkCmdCopyImage: pRegions[" << i
14136a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski               << "] specifies a dst mipLevel greater than the number specified when the dstImage was created.";
14146a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
14156a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01223, "IMAGE", "%s. %s",
14166a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            ss.str().c_str(), validation_error_map[VALIDATION_ERROR_01223]);
14176a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
1418ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
14196a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // (baseArrayLayer + layerCount) must be less than or equal to the arrayLayers specified in VkImageCreateInfo when the
14206a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // image was created
14216a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if ((regions[i].srcSubresource.baseArrayLayer + regions[i].srcSubresource.layerCount) >
14226a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            src_image_state->createInfo.arrayLayers) {
14236a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            std::stringstream ss;
14246a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            ss << "vkCmdCopyImage: srcImage arrayLayers was " << src_image_state->createInfo.arrayLayers << " but subRegion[" << i
14256a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski               << "] baseArrayLayer + layerCount is "
14266a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski               << (regions[i].srcSubresource.baseArrayLayer + regions[i].srcSubresource.layerCount);
14276a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
14286a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01224, "IMAGE", "%s. %s",
14296a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            ss.str().c_str(), validation_error_map[VALIDATION_ERROR_01224]);
14306a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
14316a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if ((regions[i].dstSubresource.baseArrayLayer + regions[i].dstSubresource.layerCount) >
14326a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            dst_image_state->createInfo.arrayLayers) {
14336a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            std::stringstream ss;
14346a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            ss << "vkCmdCopyImage: dstImage arrayLayers was " << dst_image_state->createInfo.arrayLayers << " but subRegion[" << i
14356a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski               << "] baseArrayLayer + layerCount is "
14366a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski               << (regions[i].dstSubresource.baseArrayLayer + regions[i].dstSubresource.layerCount);
14376a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
14386a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01224, "IMAGE", "%s. %s",
14396a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            ss.str().c_str(), validation_error_map[VALIDATION_ERROR_01224]);
14406a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
1441ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
144257eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt        // Check region extents for 1D-1D, 2D-2D, and 3D-3D copies
144357eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt        if (src_image_state->createInfo.imageType == dst_image_state->createInfo.imageType) {
144457eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt            // The source region specified by a given element of regions must be a region that is contained within srcImage
14453fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton            VkExtent3D img_extent = GetImageSubresourceExtent(src_image_state, &(regions[i].srcSubresource));
14463fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton            if (0 != ExceedsBounds(&regions[i].srcOffset, &regions[i].extent, &img_extent)) {
144757eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt                std::stringstream ss;
14483fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton                ss << "vkCmdCopyImage: Source pRegion[" << i << "] with mipLevel [ " << regions[i].srcSubresource.mipLevel
14493fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton                   << " ], offset [ " << regions[i].srcOffset.x << ", " << regions[i].srcOffset.y << ", " << regions[i].srcOffset.z
14503fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton                   << " ], extent [ " << regions[i].extent.width << ", " << regions[i].extent.height << ", "
14513fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton                   << regions[i].extent.depth << " ] exceeds the source image dimensions";
145257eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
145357eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt                                reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01175, "IMAGE", "%s. %s",
145457eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt                                ss.str().c_str(), validation_error_map[VALIDATION_ERROR_01175]);
145557eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt            }
1456ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
145757eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt            // The destination region specified by a given element of regions must be a region that is contained within dst_image
14583fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton            img_extent = GetImageSubresourceExtent(dst_image_state, &(regions[i].dstSubresource));
14593fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton            if (0 != ExceedsBounds(&regions[i].dstOffset, &regions[i].extent, &img_extent)) {
146057eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt                std::stringstream ss;
14613fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton                ss << "vkCmdCopyImage: Dest pRegion[" << i << "] with mipLevel [ " << regions[i].dstSubresource.mipLevel
14623fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton                   << " ], offset [ " << regions[i].dstOffset.x << ", " << regions[i].dstOffset.y << ", " << regions[i].dstOffset.z
14633fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton                   << " ], extent [ " << regions[i].extent.width << ", " << regions[i].extent.height << ", "
14643fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton                   << regions[i].extent.depth << " ] exceeds the destination image dimensions";
146557eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
146657eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt                                reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01176, "IMAGE", "%s. %s",
146757eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt                                ss.str().c_str(), validation_error_map[VALIDATION_ERROR_01176]);
146857eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt            }
14696a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
1470ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
14713fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton        // Each dimension offset + extent limits must fall with image subresource extent
14723fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton        VkExtent3D subresource_extent = GetImageSubresourceExtent(src_image_state, &(regions[i].srcSubresource));
14733fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton        uint32_t extent_check = ExceedsBounds(&(regions[i].srcOffset), &regions[i].extent, &subresource_extent);
14743fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton        if (extent_check & x_bit) {
14753fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
14763fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton                            reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01202, "IMAGE",
14773fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton                            "vkCmdCopyImage: Source image pRegion %1d x-dimension offset [%1d] + extent [%1d] exceeds subResource "
14783fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton                            "width [%1d]. %s",
14793fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton                            i, regions[i].srcOffset.x, regions[i].extent.width, subresource_extent.width,
14803fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton                            validation_error_map[VALIDATION_ERROR_01202]);
14813fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton        }
14823fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton
14833fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton        if (extent_check & y_bit) {
14843fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
14853fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton                            reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01203, "IMAGE",
14863fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton                            "vkCmdCopyImage: Source image pRegion %1d y-dimension offset [%1d] + extent [%1d] exceeds subResource "
14873fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton                            "height [%1d]. %s",
14883fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton                            i, regions[i].srcOffset.y, regions[i].extent.height, subresource_extent.height,
14893fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton                            validation_error_map[VALIDATION_ERROR_01203]);
14903fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton        }
14913fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton        if (extent_check & z_bit) {
14923fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
14933fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton                            reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01204, "IMAGE",
14943fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton                            "vkCmdCopyImage: Source image pRegion %1d z-dimension offset [%1d] + extent [%1d] exceeds subResource "
14953fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton                            "depth [%1d]. %s",
14963fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton                            i, regions[i].srcOffset.z, regions[i].extent.depth, subresource_extent.depth,
14973fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton                            validation_error_map[VALIDATION_ERROR_01204]);
14983fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton        }
14993fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton
15003fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton        subresource_extent = GetImageSubresourceExtent(dst_image_state, &(regions[i].dstSubresource));
15013fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton        extent_check = ExceedsBounds(&(regions[i].dstOffset), &regions[i].extent, &subresource_extent);
15023fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton        if (extent_check & x_bit) {
15033fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
15043fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton                            reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01205, "IMAGE",
15053fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton                            "vkCmdCopyImage: Dest image pRegion %1d x-dimension offset [%1d] + extent [%1d] exceeds subResource "
15063fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton                            "width [%1d]. %s",
15073fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton                            i, regions[i].dstOffset.x, regions[i].extent.width, subresource_extent.width,
15083fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton                            validation_error_map[VALIDATION_ERROR_01205]);
15093fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton        }
15103fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton        if (extent_check & y_bit) {
15113fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
15123fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton                            reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01206, "IMAGE",
15133fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton                            "vkCmdCopyImage: Dest image pRegion %1d y-dimension offset [%1d] + extent [%1d] exceeds subResource "
15143fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton                            "height [%1d]. %s",
15153fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton                            i, regions[i].dstOffset.y, regions[i].extent.height, subresource_extent.height,
15163fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton                            validation_error_map[VALIDATION_ERROR_01206]);
15173fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton        }
15183fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton        if (extent_check & z_bit) {
15193fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
15203fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton                            reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01207, "IMAGE",
15213fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton                            "vkCmdCopyImage: Dest image pRegion %1d z-dimension offset [%1d] + extent [%1d] exceeds subResource "
15223fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton                            "depth [%1d]. %s",
15233fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton                            i, regions[i].dstOffset.z, regions[i].extent.depth, subresource_extent.depth,
15243fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton                            validation_error_map[VALIDATION_ERROR_01207]);
15253fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton        }
15263fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton
15276a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // The union of all source regions, and the union of all destination regions, specified by the elements of regions,
15286a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // must not overlap in memory
15296a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if (src_image_state->image == dst_image_state->image) {
15306a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            for (uint32_t j = 0; j < region_count; j++) {
15316a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                if (RegionIntersects(&regions[i], &regions[j], src_image_state->createInfo.imageType)) {
15326a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                    std::stringstream ss;
15336a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                    ss << "vkCmdCopyImage: pRegions[" << i << "] src overlaps with pRegions[" << j << "].";
15346a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                    skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
15356a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                    reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01177, "IMAGE",
15366a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                    "%s. %s", ss.str().c_str(), validation_error_map[VALIDATION_ERROR_01177]);
1537ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski                }
1538ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski            }
1539ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski        }
15406a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    }
1541ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
15426a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    // The formats of src_image and dst_image must be compatible. Formats are considered compatible if their texel size in bytes
15436a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    // is the same between both formats. For example, VK_FORMAT_R8G8B8A8_UNORM is compatible with VK_FORMAT_R32_UINT because
15446a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    // because both texels are 4 bytes in size. Depth/stencil formats must match exactly.
1545cf2ce8673669ca1111e333bdea272c4dd57cb5c2Dave Houlton    if (FormatIsDepthOrStencil(src_image_state->createInfo.format) || FormatIsDepthOrStencil(dst_image_state->createInfo.format)) {
15466a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if (src_image_state->createInfo.format != dst_image_state->createInfo.format) {
15476a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            char const str[] = "vkCmdCopyImage called with unmatched source and dest image depth/stencil formats.";
15486a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            skip |=
15496a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
15506a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                        reinterpret_cast<uint64_t &>(command_buffer), __LINE__, DRAWSTATE_MISMATCHED_IMAGE_FORMAT, "IMAGE", str);
15516a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
15526a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    } else {
155316769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton        size_t srcSize = FormatSize(src_image_state->createInfo.format);
155416769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton        size_t destSize = FormatSize(dst_image_state->createInfo.format);
15556a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if (srcSize != destSize) {
15566a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            char const str[] = "vkCmdCopyImage called with unmatched source and dest image format sizes.";
15576a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
15586a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01184, "IMAGE", "%s. %s", str,
15596a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            validation_error_map[VALIDATION_ERROR_01184]);
1560ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski        }
1561ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    }
15626a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
156392c9c5dfbd0dec1d76ca18faa487fa8c2d302a65Dave Houlton    // Source and dest image sample counts must match
156492c9c5dfbd0dec1d76ca18faa487fa8c2d302a65Dave Houlton    if (src_image_state->createInfo.samples != dst_image_state->createInfo.samples) {
156592c9c5dfbd0dec1d76ca18faa487fa8c2d302a65Dave Houlton        char const str[] = "vkCmdCopyImage() called on image pair with non-identical sample counts.";
156692c9c5dfbd0dec1d76ca18faa487fa8c2d302a65Dave Houlton        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1567e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton                        reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01185, "IMAGE", "%s %s", str,
1568e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton                        validation_error_map[VALIDATION_ERROR_01185]);
156992c9c5dfbd0dec1d76ca18faa487fa8c2d302a65Dave Houlton    }
157092c9c5dfbd0dec1d76ca18faa487fa8c2d302a65Dave Houlton
15716a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    skip |= ValidateMemoryIsBoundToImage(device_data, src_image_state, "vkCmdCopyImage()", VALIDATION_ERROR_02533);
15726a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    skip |= ValidateMemoryIsBoundToImage(device_data, dst_image_state, "vkCmdCopyImage()", VALIDATION_ERROR_02534);
15736a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    // Validate that SRC & DST images have correct usage flags set
15746a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    skip |= ValidateImageUsageFlags(device_data, src_image_state, VK_IMAGE_USAGE_TRANSFER_SRC_BIT, true, VALIDATION_ERROR_01178,
15756a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                    "vkCmdCopyImage()", "VK_IMAGE_USAGE_TRANSFER_SRC_BIT");
15766a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    skip |= ValidateImageUsageFlags(device_data, dst_image_state, VK_IMAGE_USAGE_TRANSFER_DST_BIT, true, VALIDATION_ERROR_01181,
15776a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                    "vkCmdCopyImage()", "VK_IMAGE_USAGE_TRANSFER_DST_BIT");
1578baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt    skip |= ValidateCmdQueueFlags(device_data, cb_node, "vkCmdCopyImage()",
1579baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt                                  VK_QUEUE_TRANSFER_BIT | VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, VALIDATION_ERROR_01193);
15806a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    skip |= ValidateCmd(device_data, cb_node, CMD_COPYIMAGE, "vkCmdCopyImage()");
15816a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    skip |= insideRenderPass(device_data, cb_node, "vkCmdCopyImage()", VALIDATION_ERROR_01194);
15820db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlis    bool hit_error = false;
15836a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    for (uint32_t i = 0; i < region_count; ++i) {
1584fab4fd84d0d187bc73b5bc6709d8ed6370bb7cc3Tobin Ehlis        skip |= VerifyImageLayout(device_data, cb_node, src_image_state, regions[i].srcSubresource, src_image_layout,
15850db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlis                                  VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, "vkCmdCopyImage()", VALIDATION_ERROR_01180, &hit_error);
1586fab4fd84d0d187bc73b5bc6709d8ed6370bb7cc3Tobin Ehlis        skip |= VerifyImageLayout(device_data, cb_node, dst_image_state, regions[i].dstSubresource, dst_image_layout,
15870db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlis                                  VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, "vkCmdCopyImage()", VALIDATION_ERROR_01183, &hit_error);
15886a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        skip |= ValidateCopyImageTransferGranularityRequirements(device_data, cb_node, dst_image_state, &regions[i], i,
15896a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                                                 "vkCmdCopyImage()");
15906a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    }
15916a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
1592ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    return skip;
1593ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski}
1594a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski
15956a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinskivoid PreCallRecordCmdCopyImage(layer_data *device_data, GLOBAL_CB_NODE *cb_node, IMAGE_STATE *src_image_state,
1596a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis                               IMAGE_STATE *dst_image_state, uint32_t region_count, const VkImageCopy *regions,
1597a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis                               VkImageLayout src_image_layout, VkImageLayout dst_image_layout) {
1598a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis    // Make sure that all image slices are updated to correct layout
1599a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis    for (uint32_t i = 0; i < region_count; ++i) {
1600a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis        SetImageLayout(device_data, cb_node, src_image_state, regions[i].srcSubresource, src_image_layout);
1601a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis        SetImageLayout(device_data, cb_node, dst_image_state, regions[i].dstSubresource, dst_image_layout);
1602a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis    }
16036a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    // Update bindings between images and cmd buffer
16046a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    AddCommandBufferBindingImage(device_data, cb_node, src_image_state);
16056a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    AddCommandBufferBindingImage(device_data, cb_node, dst_image_state);
16063f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton    std::function<bool()> function = [=]() { return ValidateImageMemoryIsValid(device_data, src_image_state, "vkCmdCopyImage()"); };
16076a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    cb_node->validate_functions.push_back(function);
16086a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    function = [=]() {
16096a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        SetImageMemoryValid(device_data, dst_image_state, true);
16106a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        return false;
16116a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    };
16126a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    cb_node->validate_functions.push_back(function);
16136a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    core_validation::UpdateCmdBufferLastCmd(cb_node, CMD_COPYIMAGE);
16146a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski}
16156a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
1616a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski// Returns true if sub_rect is entirely contained within rect
1617a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinskistatic inline bool ContainsRect(VkRect2D rect, VkRect2D sub_rect) {
1618a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski    if ((sub_rect.offset.x < rect.offset.x) || (sub_rect.offset.x + sub_rect.extent.width > rect.offset.x + rect.extent.width) ||
1619a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski        (sub_rect.offset.y < rect.offset.y) || (sub_rect.offset.y + sub_rect.extent.height > rect.offset.y + rect.extent.height))
1620a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski        return false;
1621a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski    return true;
1622a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski}
1623a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski
1624e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisbool PreCallValidateCmdClearAttachments(layer_data *device_data, VkCommandBuffer commandBuffer, uint32_t attachmentCount,
1625e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlis                                        const VkClearAttachment *pAttachments, uint32_t rectCount, const VkClearRect *pRects) {
16269a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    GLOBAL_CB_NODE *cb_node = GetCBNode(device_data, commandBuffer);
1627a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
1628a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski
1629a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski    bool skip = false;
1630a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski    if (cb_node) {
1631baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt        skip |=
1632baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt            ValidateCmdQueueFlags(device_data, cb_node, "vkCmdClearAttachments()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_01121);
1633a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski        skip |= ValidateCmd(device_data, cb_node, CMD_CLEARATTACHMENTS, "vkCmdClearAttachments()");
16349a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        core_validation::UpdateCmdBufferLastCmd(cb_node, CMD_CLEARATTACHMENTS);
1635a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski        // Warn if this is issued prior to Draw Cmd and clearing the entire attachment
1636b68b13ed4952bce61f6ebb0023542660c26b0562Chris Forbes        if (!cb_node->hasDrawCmd && (cb_node->activeRenderPassBeginInfo.renderArea.extent.width == pRects[0].rect.extent.width) &&
1637a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski            (cb_node->activeRenderPassBeginInfo.renderArea.extent.height == pRects[0].rect.extent.height)) {
1638a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski            // There are times where app needs to use ClearAttachments (generally when reusing a buffer inside of a render pass)
16398e0190bd5904b8a8f044dae2c6ae23a891eb5e11Mark Lobodzinski            // This warning should be made more specific. It'd be best to avoid triggering this test if it's a use that must call
16408e0190bd5904b8a8f044dae2c6ae23a891eb5e11Mark Lobodzinski            // CmdClearAttachments.
164173f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski            skip |=
164273f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                log_msg(report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
164373f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                        reinterpret_cast<uint64_t &>(commandBuffer), 0, DRAWSTATE_CLEAR_CMD_BEFORE_DRAW, "DS",
164473f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                        "vkCmdClearAttachments() issued on command buffer object 0x%p prior to any Draw Cmds."
164573f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                        " It is recommended you use RenderPass LOAD_OP_CLEAR on Attachments prior to any Draw.",
164673f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                        commandBuffer);
1647a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski        }
1648a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski        skip |= outsideRenderPass(device_data, cb_node, "vkCmdClearAttachments()", VALIDATION_ERROR_01122);
1649a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski    }
1650a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski
1651a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski    // Validate that attachment is in reference list of active subpass
1652a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski    if (cb_node->activeRenderPass) {
1653a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski        const VkRenderPassCreateInfo *renderpass_create_info = cb_node->activeRenderPass->createInfo.ptr();
1654a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski        const VkSubpassDescription *subpass_desc = &renderpass_create_info->pSubpasses[cb_node->activeSubpass];
16559a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto framebuffer = GetFramebufferState(device_data, cb_node->activeFramebuffer);
1656a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski
1657a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski        for (uint32_t i = 0; i < attachmentCount; i++) {
1658a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski            auto clear_desc = &pAttachments[i];
1659a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski            VkImageView image_view = VK_NULL_HANDLE;
1660a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski
166173f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski            if (0 == clear_desc->aspectMask) {
166273f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1663fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                                reinterpret_cast<uint64_t>(commandBuffer), __LINE__, VALIDATION_ERROR_01128, "IMAGE", "%s",
166473f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                validation_error_map[VALIDATION_ERROR_01128]);
166573f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski            } else if (clear_desc->aspectMask & VK_IMAGE_ASPECT_METADATA_BIT) {
166673f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1667fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                                reinterpret_cast<uint64_t>(commandBuffer), __LINE__, VALIDATION_ERROR_01126, "IMAGE", "%s",
166873f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                validation_error_map[VALIDATION_ERROR_01126]);
166973f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski            } else if (clear_desc->aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) {
1670a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                if (clear_desc->colorAttachment >= subpass_desc->colorAttachmentCount) {
167173f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                    skip |=
167273f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                        log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1673fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                                reinterpret_cast<uint64_t>(commandBuffer), __LINE__, VALIDATION_ERROR_01114, "DS",
167473f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                "vkCmdClearAttachments() color attachment index %d out of range for active subpass %d. %s",
167573f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                clear_desc->colorAttachment, cb_node->activeSubpass, validation_error_map[VALIDATION_ERROR_01114]);
1676a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                } else if (subpass_desc->pColorAttachments[clear_desc->colorAttachment].attachment == VK_ATTACHMENT_UNUSED) {
1677a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                    skip |= log_msg(report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT,
1678fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                                    VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t>(commandBuffer),
1679fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                                    __LINE__, DRAWSTATE_MISSING_ATTACHMENT_REFERENCE, "DS",
168073f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                    "vkCmdClearAttachments() color attachment index %d is VK_ATTACHMENT_UNUSED; ignored.",
168173f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                    clear_desc->colorAttachment);
1682a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                } else {
1683a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                    image_view = framebuffer->createInfo
168473f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                     .pAttachments[subpass_desc->pColorAttachments[clear_desc->colorAttachment].attachment];
1685a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                }
168673f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                if ((clear_desc->aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) ||
168773f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                    (clear_desc->aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT)) {
168873f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                    char const str[] =
168973f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                        "vkCmdClearAttachments aspectMask [%d] must set only VK_IMAGE_ASPECT_COLOR_BIT of a color attachment. %s";
169073f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                    skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1691fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                                    reinterpret_cast<uint64_t>(commandBuffer), __LINE__, VALIDATION_ERROR_01125, "IMAGE", str, i,
169273f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                    validation_error_map[VALIDATION_ERROR_01125]);
169373f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                }
169473f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski            } else {  // Must be depth and/or stencil
169573f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                if (((clear_desc->aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) != VK_IMAGE_ASPECT_DEPTH_BIT) &&
169673f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                    ((clear_desc->aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) != VK_IMAGE_ASPECT_STENCIL_BIT)) {
169773f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                    char const str[] = "vkCmdClearAttachments aspectMask [%d] is not a valid combination of bits. %s";
169873f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                    skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1699fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                                    reinterpret_cast<uint64_t>(commandBuffer), __LINE__, VALIDATION_ERROR_01127, "IMAGE", str, i,
170073f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                    validation_error_map[VALIDATION_ERROR_01127]);
170173f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                }
170273f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                if (!subpass_desc->pDepthStencilAttachment ||
170373f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                    (subpass_desc->pDepthStencilAttachment->attachment == VK_ATTACHMENT_UNUSED)) {
170473f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                    skip |= log_msg(
170573f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                        report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1706fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                        reinterpret_cast<uint64_t>(commandBuffer), __LINE__, DRAWSTATE_MISSING_ATTACHMENT_REFERENCE, "DS",
170773f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                        "vkCmdClearAttachments() depth/stencil clear with no depth/stencil attachment in subpass; ignored");
1708a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                } else {
1709a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                    image_view = framebuffer->createInfo.pAttachments[subpass_desc->pDepthStencilAttachment->attachment];
1710a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                }
1711a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski            }
1712a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski            if (image_view) {
17139a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis                auto image_view_state = GetImageViewState(device_data, image_view);
1714a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                for (uint32_t j = 0; j < rectCount; j++) {
171573f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                    // The rectangular region specified by a given element of pRects must be contained within the render area of
171673f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                    // the current render pass instance
17178e0190bd5904b8a8f044dae2c6ae23a891eb5e11Mark Lobodzinski                    // TODO: This check should be moved to CmdExecuteCommands or QueueSubmit to cover secondary CB cases
17188e0190bd5904b8a8f044dae2c6ae23a891eb5e11Mark Lobodzinski                    if ((cb_node->createInfo.level == VK_COMMAND_BUFFER_LEVEL_PRIMARY) &&
17198e0190bd5904b8a8f044dae2c6ae23a891eb5e11Mark Lobodzinski                        (false == ContainsRect(cb_node->activeRenderPassBeginInfo.renderArea, pRects[j].rect))) {
1720fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1721fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                                        reinterpret_cast<uint64_t>(commandBuffer), __LINE__, VALIDATION_ERROR_01115, "DS",
172273f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                        "vkCmdClearAttachments(): The area defined by pRects[%d] is not contained in the area of "
172373f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                        "the current render pass instance. %s",
172473f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                        j, validation_error_map[VALIDATION_ERROR_01115]);
1725a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                    }
1726a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                    // The layers specified by a given element of pRects must be contained within every attachment that
1727a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                    // pAttachments refers to
1728a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                    auto attachment_base_array_layer = image_view_state->create_info.subresourceRange.baseArrayLayer;
1729a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                    auto attachment_layer_count = image_view_state->create_info.subresourceRange.layerCount;
1730a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                    if ((pRects[j].baseArrayLayer < attachment_base_array_layer) || pRects[j].layerCount > attachment_layer_count) {
1731a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                        skip |=
1732fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                            log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1733fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                                    reinterpret_cast<uint64_t>(commandBuffer), __LINE__, VALIDATION_ERROR_01116, "DS",
173473f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                    "vkCmdClearAttachments(): The layers defined in pRects[%d] are not contained in the layers of "
173573f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                    "pAttachment[%d]. %s",
173673f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                    j, i, validation_error_map[VALIDATION_ERROR_01116]);
1737a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                    }
1738a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                }
1739a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski            }
1740a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski        }
1741a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski    }
1742a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski    return skip;
174360568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski}
174460568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski
1745e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisbool PreCallValidateCmdResolveImage(layer_data *device_data, GLOBAL_CB_NODE *cb_node, IMAGE_STATE *src_image_state,
174654c03b0fa365789b242e680223bd30c940f1abb3Mark Lobodzinski                                    IMAGE_STATE *dst_image_state, uint32_t regionCount, const VkImageResolve *pRegions) {
174725f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
174860568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    bool skip = false;
174960568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    if (cb_node && src_image_state && dst_image_state) {
175060568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        skip |= ValidateMemoryIsBoundToImage(device_data, src_image_state, "vkCmdResolveImage()", VALIDATION_ERROR_02541);
175160568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        skip |= ValidateMemoryIsBoundToImage(device_data, dst_image_state, "vkCmdResolveImage()", VALIDATION_ERROR_02542);
1752baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt        skip |= ValidateCmdQueueFlags(device_data, cb_node, "vkCmdResolveImage()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_01334);
175360568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        skip |= ValidateCmd(device_data, cb_node, CMD_RESOLVEIMAGE, "vkCmdResolveImage()");
175460568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        skip |= insideRenderPass(device_data, cb_node, "vkCmdResolveImage()", VALIDATION_ERROR_01335);
175525f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski
175625f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski        // For each region, the number of layers in the image subresource should not be zero
175725f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski        // For each region, src and dest image aspect must be color only
175825f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski        for (uint32_t i = 0; i < regionCount; i++) {
175925f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski            if (pRegions[i].srcSubresource.layerCount == 0) {
176025f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                char const str[] = "vkCmdResolveImage: number of layers in source subresource is zero";
176154c03b0fa365789b242e680223bd30c940f1abb3Mark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
176225f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                                reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, DRAWSTATE_MISMATCHED_IMAGE_ASPECT,
176325f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                                "IMAGE", str);
176425f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski            }
176525f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski            if (pRegions[i].dstSubresource.layerCount == 0) {
176625f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                char const str[] = "vkCmdResolveImage: number of layers in destination subresource is zero";
176754c03b0fa365789b242e680223bd30c940f1abb3Mark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
176825f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                                reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, DRAWSTATE_MISMATCHED_IMAGE_ASPECT,
176925f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                                "IMAGE", str);
177025f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski            }
177154c03b0fa365789b242e680223bd30c940f1abb3Mark Lobodzinski            if (pRegions[i].srcSubresource.layerCount != pRegions[i].dstSubresource.layerCount) {
177254c03b0fa365789b242e680223bd30c940f1abb3Mark Lobodzinski                skip |= log_msg(
177354c03b0fa365789b242e680223bd30c940f1abb3Mark Lobodzinski                    report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
177454c03b0fa365789b242e680223bd30c940f1abb3Mark Lobodzinski                    reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_01339, "IMAGE",
177554c03b0fa365789b242e680223bd30c940f1abb3Mark Lobodzinski                    "vkCmdResolveImage: layerCount in source and destination subresource of pRegions[%d] does not match. %s", i,
177654c03b0fa365789b242e680223bd30c940f1abb3Mark Lobodzinski                    validation_error_map[VALIDATION_ERROR_01339]);
177754c03b0fa365789b242e680223bd30c940f1abb3Mark Lobodzinski            }
177825f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski            if ((pRegions[i].srcSubresource.aspectMask != VK_IMAGE_ASPECT_COLOR_BIT) ||
177925f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                (pRegions[i].dstSubresource.aspectMask != VK_IMAGE_ASPECT_COLOR_BIT)) {
178025f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                char const str[] =
178125f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                    "vkCmdResolveImage: src and dest aspectMasks for each region must specify only VK_IMAGE_ASPECT_COLOR_BIT";
178225f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
178325f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                                reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_01338, "IMAGE",
178425f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                                "%s. %s", str, validation_error_map[VALIDATION_ERROR_01338]);
178525f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski            }
178625f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski        }
178725f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski
178825f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski        if (src_image_state->createInfo.format != dst_image_state->createInfo.format) {
178925f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski            char const str[] = "vkCmdResolveImage called with unmatched source and dest formats.";
179054c03b0fa365789b242e680223bd30c940f1abb3Mark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
179125f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                            reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, DRAWSTATE_MISMATCHED_IMAGE_FORMAT,
179225f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                            "IMAGE", str);
179325f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski        }
179425f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski        if (src_image_state->createInfo.imageType != dst_image_state->createInfo.imageType) {
179525f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski            char const str[] = "vkCmdResolveImage called with unmatched source and dest image types.";
179654c03b0fa365789b242e680223bd30c940f1abb3Mark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
179725f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                            reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, DRAWSTATE_MISMATCHED_IMAGE_TYPE, "IMAGE",
179825f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                            str);
179925f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski        }
180025f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski        if (src_image_state->createInfo.samples == VK_SAMPLE_COUNT_1_BIT) {
180125f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski            char const str[] = "vkCmdResolveImage called with source sample count less than 2.";
180225f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
180325f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                            reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_01320, "IMAGE", "%s. %s",
180425f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                            str, validation_error_map[VALIDATION_ERROR_01320]);
180525f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski        }
180625f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski        if (dst_image_state->createInfo.samples != VK_SAMPLE_COUNT_1_BIT) {
180725f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski            char const str[] = "vkCmdResolveImage called with dest sample count greater than 1.";
180825f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
180925f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                            reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_01321, "IMAGE", "%s. %s",
181025f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                            str, validation_error_map[VALIDATION_ERROR_01321]);
181125f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski        }
181260568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    } else {
181360568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        assert(0);
181460568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    }
181560568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    return skip;
181660568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski}
181760568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski
1818e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisvoid PreCallRecordCmdResolveImage(layer_data *device_data, GLOBAL_CB_NODE *cb_node, IMAGE_STATE *src_image_state,
1819e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlis                                  IMAGE_STATE *dst_image_state) {
182060568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    // Update bindings between images and cmd buffer
182160568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    AddCommandBufferBindingImage(device_data, cb_node, src_image_state);
182260568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    AddCommandBufferBindingImage(device_data, cb_node, dst_image_state);
182360568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski
182460568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    std::function<bool()> function = [=]() {
182560568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        return ValidateImageMemoryIsValid(device_data, src_image_state, "vkCmdResolveImage()");
182660568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    };
182760568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    cb_node->validate_functions.push_back(function);
182860568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    function = [=]() {
182960568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        SetImageMemoryValid(device_data, dst_image_state, true);
183060568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        return false;
183160568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    };
183260568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    cb_node->validate_functions.push_back(function);
18339a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    core_validation::UpdateCmdBufferLastCmd(cb_node, CMD_RESOLVEIMAGE);
183460568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski}
183560568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski
1836e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisbool PreCallValidateCmdBlitImage(layer_data *device_data, GLOBAL_CB_NODE *cb_node, IMAGE_STATE *src_image_state,
1837055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                                 IMAGE_STATE *dst_image_state, uint32_t regionCount, const VkImageBlit *pRegions, VkFilter filter) {
1838055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
1839055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski
184060568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    bool skip = false;
184160568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    if (cb_node && src_image_state && dst_image_state) {
184260568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        skip |= ValidateImageSampleCount(device_data, src_image_state, VK_SAMPLE_COUNT_1_BIT, "vkCmdBlitImage(): srcImage",
1843055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                                         VALIDATION_ERROR_02194);
184460568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        skip |= ValidateImageSampleCount(device_data, dst_image_state, VK_SAMPLE_COUNT_1_BIT, "vkCmdBlitImage(): dstImage",
1845055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                                         VALIDATION_ERROR_02195);
184660568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        skip |= ValidateMemoryIsBoundToImage(device_data, src_image_state, "vkCmdBlitImage()", VALIDATION_ERROR_02539);
184760568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        skip |= ValidateMemoryIsBoundToImage(device_data, dst_image_state, "vkCmdBlitImage()", VALIDATION_ERROR_02540);
184860568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        skip |= ValidateImageUsageFlags(device_data, src_image_state, VK_IMAGE_USAGE_TRANSFER_SRC_BIT, true, VALIDATION_ERROR_02182,
1849055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                                        "vkCmdBlitImage()", "VK_IMAGE_USAGE_TRANSFER_SRC_BIT");
185060568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        skip |= ValidateImageUsageFlags(device_data, dst_image_state, VK_IMAGE_USAGE_TRANSFER_DST_BIT, true, VALIDATION_ERROR_02186,
1851055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                                        "vkCmdBlitImage()", "VK_IMAGE_USAGE_TRANSFER_DST_BIT");
1852baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt        skip |= ValidateCmdQueueFlags(device_data, cb_node, "vkCmdBlitImage()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_01299);
185360568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        skip |= ValidateCmd(device_data, cb_node, CMD_BLITIMAGE, "vkCmdBlitImage()");
185460568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        skip |= insideRenderPass(device_data, cb_node, "vkCmdBlitImage()", VALIDATION_ERROR_01300);
1855055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski
1856055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski        for (uint32_t i = 0; i < regionCount; i++) {
1857d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski            // Warn for zero-sized regions
1858055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski            if ((pRegions[i].srcOffsets[0].x == pRegions[i].srcOffsets[1].x) ||
1859055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                (pRegions[i].srcOffsets[0].y == pRegions[i].srcOffsets[1].y) ||
1860055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                (pRegions[i].srcOffsets[0].z == pRegions[i].srcOffsets[1].z)) {
1861055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                std::stringstream ss;
1862055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                ss << "vkCmdBlitImage: pRegions[" << i << "].srcOffsets specify a zero-volume area.";
1863055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1864055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                                reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, DRAWSTATE_INVALID_EXTENTS, "IMAGE",
1865055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                                "%s", ss.str().c_str());
1866055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski            }
1867055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski            if ((pRegions[i].dstOffsets[0].x == pRegions[i].dstOffsets[1].x) ||
1868055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                (pRegions[i].dstOffsets[0].y == pRegions[i].dstOffsets[1].y) ||
1869055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                (pRegions[i].dstOffsets[0].z == pRegions[i].dstOffsets[1].z)) {
1870055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                std::stringstream ss;
1871055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                ss << "vkCmdBlitImage: pRegions[" << i << "].dstOffsets specify a zero-volume area.";
1872055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1873055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                                reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, DRAWSTATE_INVALID_EXTENTS, "IMAGE",
1874055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                                "%s", ss.str().c_str());
1875055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski            }
1876d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski            if (pRegions[i].srcSubresource.layerCount == 0) {
1877d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski                char const str[] = "vkCmdBlitImage: number of layers in source subresource is zero";
1878d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
18793f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                                reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, DRAWSTATE_MISMATCHED_IMAGE_ASPECT,
18803f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                                "IMAGE", str);
1881d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski            }
1882d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski            if (pRegions[i].dstSubresource.layerCount == 0) {
1883d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski                char const str[] = "vkCmdBlitImage: number of layers in destination subresource is zero";
1884d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
18853f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                                reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, DRAWSTATE_MISMATCHED_IMAGE_ASPECT,
18863f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                                "IMAGE", str);
1887d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski            }
1888d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski
1889d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski            // Check that src/dst layercounts match
1890d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski            if (pRegions[i].srcSubresource.layerCount != pRegions[i].dstSubresource.layerCount) {
1891d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski                skip |=
1892d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski                    log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1893d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski                            reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_01304, "IMAGE",
1894d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski                            "vkCmdBlitImage: layerCount in source and destination subresource of pRegions[%d] does not match. %s",
1895d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski                            i, validation_error_map[VALIDATION_ERROR_01304]);
1896d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski            }
18978068cb0f90422b6789d0c120f0831f55eb76b71aMark Lobodzinski
18988068cb0f90422b6789d0c120f0831f55eb76b71aMark Lobodzinski            if (pRegions[i].srcSubresource.aspectMask != pRegions[i].dstSubresource.aspectMask) {
18998068cb0f90422b6789d0c120f0831f55eb76b71aMark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
19008068cb0f90422b6789d0c120f0831f55eb76b71aMark Lobodzinski                                reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_01303, "IMAGE",
19018068cb0f90422b6789d0c120f0831f55eb76b71aMark Lobodzinski                                "vkCmdBlitImage: aspectMask members for pRegion[%d] do not match. %s", i,
19028068cb0f90422b6789d0c120f0831f55eb76b71aMark Lobodzinski                                validation_error_map[VALIDATION_ERROR_01303]);
19038068cb0f90422b6789d0c120f0831f55eb76b71aMark Lobodzinski            }
1904055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski        }
1905055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski
1906055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski        VkFormat src_format = src_image_state->createInfo.format;
1907055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski        VkFormat dst_format = dst_image_state->createInfo.format;
1908055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski
1909055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski        // Validate consistency for unsigned formats
191016769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton        if (FormatIsUInt(src_format) != FormatIsUInt(dst_format)) {
1911055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski            std::stringstream ss;
1912055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski            ss << "vkCmdBlitImage: If one of srcImage and dstImage images has unsigned integer format, "
1913055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski               << "the other one must also have unsigned integer format.  "
1914055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski               << "Source format is " << string_VkFormat(src_format) << " Destination format is " << string_VkFormat(dst_format);
1915055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1916055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                            reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_02191, "IMAGE", "%s. %s",
1917055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                            ss.str().c_str(), validation_error_map[VALIDATION_ERROR_02191]);
1918055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski        }
1919055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski
1920055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski        // Validate consistency for signed formats
192116769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton        if (FormatIsSInt(src_format) != FormatIsSInt(dst_format)) {
1922055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski            std::stringstream ss;
1923055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski            ss << "vkCmdBlitImage: If one of srcImage and dstImage images has signed integer format, "
1924055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski               << "the other one must also have signed integer format.  "
1925055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski               << "Source format is " << string_VkFormat(src_format) << " Destination format is " << string_VkFormat(dst_format);
1926055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1927055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                            reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_02190, "IMAGE", "%s. %s",
1928055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                            ss.str().c_str(), validation_error_map[VALIDATION_ERROR_02190]);
1929055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski        }
1930055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski
1931055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski        // Validate aspect bits and formats for depth/stencil images
193216769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton        if (FormatIsDepthOrStencil(src_format) || FormatIsDepthOrStencil(dst_format)) {
1933055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski            if (src_format != dst_format) {
1934055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                std::stringstream ss;
1935055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                ss << "vkCmdBlitImage: If one of srcImage and dstImage images has a format of depth, stencil or depth "
1936055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                   << "stencil, the other one must have exactly the same format.  "
1937055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                   << "Source format is " << string_VkFormat(src_format) << " Destination format is "
1938055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                   << string_VkFormat(dst_format);
1939055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1940055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                                reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_02192, "IMAGE",
1941055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                                "%s. %s", ss.str().c_str(), validation_error_map[VALIDATION_ERROR_02192]);
1942055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski            }
1943055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski
1944055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski            for (uint32_t i = 0; i < regionCount; i++) {
1945055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                VkImageAspectFlags srcAspect = pRegions[i].srcSubresource.aspectMask;
1946055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski
194716769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton                if (FormatIsDepthAndStencil(src_format)) {
1948055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                    if ((srcAspect != VK_IMAGE_ASPECT_DEPTH_BIT) && (srcAspect != VK_IMAGE_ASPECT_STENCIL_BIT)) {
1949055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                        std::stringstream ss;
1950055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                        ss << "vkCmdBlitImage: Combination depth/stencil image formats must have only one of "
1951055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                              "VK_IMAGE_ASPECT_DEPTH_BIT "
1952055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                           << "and VK_IMAGE_ASPECT_STENCIL_BIT set in srcImage and dstImage";
1953055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1954055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                                        reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__,
1955055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                                        DRAWSTATE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
1956055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                    }
195716769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton                } else if (FormatIsStencilOnly(src_format)) {
1958055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                    if (srcAspect != VK_IMAGE_ASPECT_STENCIL_BIT) {
1959055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                        std::stringstream ss;
1960055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                        ss << "vkCmdBlitImage: Stencil-only image formats must have only the VK_IMAGE_ASPECT_STENCIL_BIT "
1961055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                           << "set in both the srcImage and dstImage";
1962055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1963055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                                        reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__,
1964055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                                        DRAWSTATE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
1965055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                    }
196616769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton                } else if (FormatIsDepthOnly(src_format)) {
1967055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                    if (srcAspect != VK_IMAGE_ASPECT_DEPTH_BIT) {
1968055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                        std::stringstream ss;
1969055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                        ss << "vkCmdBlitImage: Depth-only image formats must have only the VK_IMAGE_ASPECT_DEPTH "
1970055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                           << "set in both the srcImage and dstImage";
1971055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1972055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                                        reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__,
1973055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                                        DRAWSTATE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
1974055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                    }
1975055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                }
1976055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski            }
1977055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski        }
1978055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski
1979055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski        // Validate filter
198016769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton        if (FormatIsDepthOrStencil(src_format) && (filter != VK_FILTER_NEAREST)) {
1981055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski            std::stringstream ss;
1982055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski            ss << "vkCmdBlitImage: If the format of srcImage is a depth, stencil, or depth stencil "
1983055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski               << "then filter must be VK_FILTER_NEAREST.";
1984055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1985055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                            reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_02193, "IMAGE", "%s. %s",
1986055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                            ss.str().c_str(), validation_error_map[VALIDATION_ERROR_02193]);
1987055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski        }
198860568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    } else {
198960568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        assert(0);
199060568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    }
199160568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    return skip;
199260568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski}
199360568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski
1994e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisvoid PreCallRecordCmdBlitImage(layer_data *device_data, GLOBAL_CB_NODE *cb_node, IMAGE_STATE *src_image_state,
1995e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlis                               IMAGE_STATE *dst_image_state) {
199660568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    // Update bindings between images and cmd buffer
199760568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    AddCommandBufferBindingImage(device_data, cb_node, src_image_state);
199860568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    AddCommandBufferBindingImage(device_data, cb_node, dst_image_state);
199960568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski
200060568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    std::function<bool()> function = [=]() { return ValidateImageMemoryIsValid(device_data, src_image_state, "vkCmdBlitImage()"); };
200160568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    cb_node->validate_functions.push_back(function);
200260568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    function = [=]() {
200360568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        SetImageMemoryValid(device_data, dst_image_state, true);
200460568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        return false;
200560568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    };
200660568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    cb_node->validate_functions.push_back(function);
20079a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    core_validation::UpdateCmdBufferLastCmd(cb_node, CMD_BLITIMAGE);
200860568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski}
200960568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski
201051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour// This validates that the initial layout specified in the command buffer for
201151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour// the IMAGE is the same
201251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour// as the global IMAGE layout
2013440bdd357701497c3442e3515f12ac1cfffc180aTony Barbourbool ValidateCmdBufImageLayouts(layer_data *device_data, GLOBAL_CB_NODE *pCB,
2014440bdd357701497c3442e3515f12ac1cfffc180aTony Barbour                                std::unordered_map<ImageSubresourcePair, IMAGE_LAYOUT_NODE> &imageLayoutMap) {
201590e629846621a0d870212dc0cebfbc83431cc5b8Mark Lobodzinski    bool skip = false;
201651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    const debug_report_data *report_data = core_validation::GetReportData(device_data);
2017788ff59d81fc816f451414dcf2a9d6c29456ff63Mark Lobodzinski    for (auto cb_image_data : pCB->imageLayoutMap) {
2018788ff59d81fc816f451414dcf2a9d6c29456ff63Mark Lobodzinski        VkImageLayout imageLayout;
201951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour
2020521b2f3957b3b31aeb2dbcc7529b54e06c9dc9ecJeremy Hayes        if (FindLayout(imageLayoutMap, cb_image_data.first, imageLayout)) {
2021788ff59d81fc816f451414dcf2a9d6c29456ff63Mark Lobodzinski            if (cb_image_data.second.initialLayout == VK_IMAGE_LAYOUT_UNDEFINED) {
2022788ff59d81fc816f451414dcf2a9d6c29456ff63Mark Lobodzinski                // TODO: Set memory invalid which is in mem_tracker currently
2023788ff59d81fc816f451414dcf2a9d6c29456ff63Mark Lobodzinski            } else if (imageLayout != cb_image_data.second.initialLayout) {
2024788ff59d81fc816f451414dcf2a9d6c29456ff63Mark Lobodzinski                if (cb_image_data.first.hasSubresource) {
20253f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                    skip |= log_msg(
20263f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                        report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
20273f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                        reinterpret_cast<uint64_t &>(pCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
20283f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                        "Cannot submit cmd buffer using image (0x%" PRIx64
20293f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                        ") [sub-resource: aspectMask 0x%X array layer %u, mip level %u], "
20303f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                        "with layout %s when first use is %s.",
20313f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                        reinterpret_cast<const uint64_t &>(cb_image_data.first.image), cb_image_data.first.subresource.aspectMask,
20323f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                        cb_image_data.first.subresource.arrayLayer, cb_image_data.first.subresource.mipLevel,
20333f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                        string_VkImageLayout(imageLayout), string_VkImageLayout(cb_image_data.second.initialLayout));
2034788ff59d81fc816f451414dcf2a9d6c29456ff63Mark Lobodzinski                } else {
20353f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                    skip |=
20363f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                        log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
20373f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                                reinterpret_cast<uint64_t &>(pCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
20383f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                                "Cannot submit cmd buffer using image (0x%" PRIx64
20393f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                                ") with layout %s when "
20403f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                                "first use is %s.",
20413f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                                reinterpret_cast<const uint64_t &>(cb_image_data.first.image), string_VkImageLayout(imageLayout),
20423f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                                string_VkImageLayout(cb_image_data.second.initialLayout));
2043788ff59d81fc816f451414dcf2a9d6c29456ff63Mark Lobodzinski                }
2044788ff59d81fc816f451414dcf2a9d6c29456ff63Mark Lobodzinski            }
204551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour            SetLayout(imageLayoutMap, cb_image_data.first, cb_image_data.second.layout);
2046788ff59d81fc816f451414dcf2a9d6c29456ff63Mark Lobodzinski        }
2047788ff59d81fc816f451414dcf2a9d6c29456ff63Mark Lobodzinski    }
204890e629846621a0d870212dc0cebfbc83431cc5b8Mark Lobodzinski    return skip;
2049788ff59d81fc816f451414dcf2a9d6c29456ff63Mark Lobodzinski}
2050940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski
205151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbourvoid UpdateCmdBufImageLayouts(layer_data *device_data, GLOBAL_CB_NODE *pCB) {
205251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    for (auto cb_image_data : pCB->imageLayoutMap) {
205351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour        VkImageLayout imageLayout;
205451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour        FindGlobalLayout(device_data, cb_image_data.first, imageLayout);
205551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour        SetGlobalLayout(device_data, cb_image_data.first, cb_image_data.second.layout);
205651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    }
205751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour}
205851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour
2059940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski// Print readable FlagBits in FlagMask
2060940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinskistatic std::string string_VkAccessFlags(VkAccessFlags accessMask) {
2061940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski    std::string result;
2062940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski    std::string separator;
2063940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski
2064940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski    if (accessMask == 0) {
2065940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski        result = "[None]";
2066940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski    } else {
2067940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski        result = "[";
2068940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski        for (auto i = 0; i < 32; i++) {
2069940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski            if (accessMask & (1 << i)) {
2070940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski                result = result + separator + string_VkAccessFlagBits((VkAccessFlagBits)(1 << i));
2071940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski                separator = " | ";
2072940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski            }
2073940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski        }
2074940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski        result = result + "]";
2075940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski    }
2076940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski    return result;
2077940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski}
2078940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski
20798fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski// AccessFlags MUST have 'required_bit' set, and may have one or more of 'optional_bits' set. If required_bit is zero, accessMask
20808fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski// must have at least one of 'optional_bits' set
2081940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski// TODO: Add tracking to ensure that at least one barrier has been set for these layout transitions
20828fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinskistatic bool ValidateMaskBits(core_validation::layer_data *device_data, VkCommandBuffer cmdBuffer, const VkAccessFlags &accessMask,
20838fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                             const VkImageLayout &layout, VkAccessFlags required_bit, VkAccessFlags optional_bits,
20848fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                             const char *type) {
20858fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
20868fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski    bool skip = false;
2087940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski
2088940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski    if ((accessMask & required_bit) || (!required_bit && (accessMask & optional_bits))) {
2089940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski        if (accessMask & ~(required_bit | optional_bits)) {
2090940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski            // TODO: Verify against Valid Use
2091fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
2092fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                            reinterpret_cast<uint64_t>(cmdBuffer), __LINE__, DRAWSTATE_INVALID_BARRIER, "DS",
20938fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                            "Additional bits in %s accessMask 0x%X %s are specified when layout is %s.", type, accessMask,
20948fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                            string_VkAccessFlags(accessMask).c_str(), string_VkImageLayout(layout));
2095940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski        }
2096940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski    } else {
2097940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski        if (!required_bit) {
2098fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
2099fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                            reinterpret_cast<uint64_t>(cmdBuffer), __LINE__, DRAWSTATE_INVALID_BARRIER, "DS",
21008fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                            "%s AccessMask %d %s must contain at least one of access bits %d "
21018fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                            "%s when layout is %s, unless the app has previously added a "
21028fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                            "barrier for this transition.",
21038fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                            type, accessMask, string_VkAccessFlags(accessMask).c_str(), optional_bits,
21048fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                            string_VkAccessFlags(optional_bits).c_str(), string_VkImageLayout(layout));
2105940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski        } else {
2106940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski            std::string opt_bits;
2107940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski            if (optional_bits != 0) {
2108940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski                std::stringstream ss;
2109940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski                ss << optional_bits;
2110940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski                opt_bits = "and may have optional bits " + ss.str() + ' ' + string_VkAccessFlags(optional_bits);
2111940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski            }
2112fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
2113fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                            reinterpret_cast<uint64_t>(cmdBuffer), __LINE__, DRAWSTATE_INVALID_BARRIER, "DS",
21148fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                            "%s AccessMask %d %s must have required access bit %d %s %s when "
21158fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                            "layout is %s, unless the app has previously added a barrier for "
21168fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                            "this transition.",
21178fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                            type, accessMask, string_VkAccessFlags(accessMask).c_str(), required_bit,
21188fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                            string_VkAccessFlags(required_bit).c_str(), opt_bits.c_str(), string_VkImageLayout(layout));
2119940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski        }
2120940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski    }
21218fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski    return skip;
2122940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski}
2123940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski
21248fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinskibool ValidateMaskBitsFromLayouts(core_validation::layer_data *device_data, VkCommandBuffer cmdBuffer,
21258fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                                 const VkAccessFlags &accessMask, const VkImageLayout &layout, const char *type) {
21268fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
2127940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski
21288fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski    bool skip = false;
2129940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski    switch (layout) {
21308fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski        case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: {
21318fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            skip |= ValidateMaskBits(device_data, cmdBuffer, accessMask, layout, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
21328fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                                     VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, type);
21338fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            break;
2134940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski        }
21358fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski        case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: {
21368fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            skip |= ValidateMaskBits(device_data, cmdBuffer, accessMask, layout, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
21378fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                                     VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, type);
21388fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            break;
21398fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski        }
21408fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski        case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: {
21418fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            skip |= ValidateMaskBits(device_data, cmdBuffer, accessMask, layout, VK_ACCESS_TRANSFER_WRITE_BIT, 0, type);
21428fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            break;
21438fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski        }
21448fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski        case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL: {
21458fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            skip |= ValidateMaskBits(
21468fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                device_data, cmdBuffer, accessMask, layout, 0,
21478fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
21488fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                type);
21498fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            break;
21508fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski        }
21518fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski        case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: {
21528fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            skip |= ValidateMaskBits(device_data, cmdBuffer, accessMask, layout, 0,
21538fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                                     VK_ACCESS_INPUT_ATTACHMENT_READ_BIT | VK_ACCESS_SHADER_READ_BIT, type);
21548fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            break;
21558fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski        }
21568fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski        case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: {
21578fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            skip |= ValidateMaskBits(device_data, cmdBuffer, accessMask, layout, VK_ACCESS_TRANSFER_READ_BIT, 0, type);
21588fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            break;
21598fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski        }
21608fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski        case VK_IMAGE_LAYOUT_UNDEFINED: {
21618fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            if (accessMask != 0) {
21628fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                // TODO: Verify against Valid Use section spec
2163fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
2164fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                                reinterpret_cast<uint64_t>(cmdBuffer), __LINE__, DRAWSTATE_INVALID_BARRIER, "DS",
21658fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                                "Additional bits in %s accessMask 0x%X %s are specified when layout is %s.", type, accessMask,
21668fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                                string_VkAccessFlags(accessMask).c_str(), string_VkImageLayout(layout));
21678fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            }
21688fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            break;
21698fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski        }
21706e3442c40be4c735b830775a753bb449c331e15dChris Forbes        case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR:
2171cf2ce8673669ca1111e333bdea272c4dd57cb5c2Dave Houlton        // Notes: QueuePresentKHR performs automatic visibility operations,
2172cf2ce8673669ca1111e333bdea272c4dd57cb5c2Dave Houlton        // so the app is /NOT/ required to include VK_ACCESS_MEMORY_READ_BIT
2173cf2ce8673669ca1111e333bdea272c4dd57cb5c2Dave Houlton        // when transitioning to this layout.
2174cf2ce8673669ca1111e333bdea272c4dd57cb5c2Dave Houlton        //
2175cf2ce8673669ca1111e333bdea272c4dd57cb5c2Dave Houlton        // When transitioning /from/ this layout, the application needs to
2176cf2ce8673669ca1111e333bdea272c4dd57cb5c2Dave Houlton        // avoid only a WAR hazard -- any writes need to be ordered after
2177cf2ce8673669ca1111e333bdea272c4dd57cb5c2Dave Houlton        // the PE's reads. There is no need for a memory dependency for this
2178cf2ce8673669ca1111e333bdea272c4dd57cb5c2Dave Houlton        // case.
2179cf2ce8673669ca1111e333bdea272c4dd57cb5c2Dave Houlton        /* fallthrough */
21806e3442c40be4c735b830775a753bb449c331e15dChris Forbes
21818fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski        case VK_IMAGE_LAYOUT_GENERAL:
21828fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski        default: { break; }
2183940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski    }
21848fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski    return skip;
2185940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski}
2186d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski
2187d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski// ValidateLayoutVsAttachmentDescription is a general function where we can validate various state associated with the
2188374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski// VkAttachmentDescription structs that are used by the sub-passes of a renderpass. Initial check is to make sure that READ_ONLY
2189374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski// layout attachments don't have CLEAR as their loadOp.
2190d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinskibool ValidateLayoutVsAttachmentDescription(const debug_report_data *report_data, const VkImageLayout first_layout,
2191374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                           const uint32_t attachment, const VkAttachmentDescription &attachment_description) {
2192374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski    bool skip = false;
2193d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski    // Verify that initial loadOp on READ_ONLY attachments is not CLEAR
2194d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski    if (attachment_description.loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR) {
2195d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski        if ((first_layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL) ||
2196d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            (first_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)) {
21975b9ab1fb8720c30edfbe8dd974e2364425471ad5Mark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
21985b9ab1fb8720c30edfbe8dd974e2364425471ad5Mark Lobodzinski                            VALIDATION_ERROR_02351, "DS", "Cannot clear attachment %d with invalid first layout %s. %s", attachment,
2199374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                            string_VkImageLayout(first_layout), validation_error_map[VALIDATION_ERROR_02351]);
2200d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski        }
2201d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski    }
2202374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski    return skip;
2203d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski}
2204d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski
2205374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinskibool ValidateLayouts(core_validation::layer_data *device_data, VkDevice device, const VkRenderPassCreateInfo *pCreateInfo) {
2206374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
2207d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski    bool skip = false;
2208d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski
2209d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski    // Track when we're observing the first use of an attachment
2210d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski    std::vector<bool> attach_first_use(pCreateInfo->attachmentCount, true);
2211d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski    for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) {
2212d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski        const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i];
2213d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski        for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) {
2214d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            auto attach_index = subpass.pColorAttachments[j].attachment;
2215d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            if (attach_index == VK_ATTACHMENT_UNUSED) continue;
2216d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski
2217d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            switch (subpass.pColorAttachments[j].layout) {
2218374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
2219374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    // This is ideal.
2220374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    break;
2221d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski
2222374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                case VK_IMAGE_LAYOUT_GENERAL:
2223374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    // May not be optimal; TODO: reconsider this warning based on other constraints?
2224374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    skip |= log_msg(report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT,
2225374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                    VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
2226374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                    "Layout for color attachment is GENERAL but should be COLOR_ATTACHMENT_OPTIMAL.");
2227374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    break;
2228374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski
2229374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                default:
2230374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
2231374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                    __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
2232374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                    "Layout for color attachment is %s but can only be COLOR_ATTACHMENT_OPTIMAL or GENERAL.",
2233374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                    string_VkImageLayout(subpass.pColorAttachments[j].layout));
2234d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            }
2235d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski
2236d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            if (attach_first_use[attach_index]) {
2237374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                skip |= ValidateLayoutVsAttachmentDescription(report_data, subpass.pColorAttachments[j].layout, attach_index,
2238374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                                              pCreateInfo->pAttachments[attach_index]);
2239d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            }
2240d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            attach_first_use[attach_index] = false;
2241d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski        }
2242d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski        if (subpass.pDepthStencilAttachment && subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) {
2243d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            switch (subpass.pDepthStencilAttachment->layout) {
2244374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
2245374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
2246374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    // These are ideal.
2247374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    break;
2248374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski
2249374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                case VK_IMAGE_LAYOUT_GENERAL:
2250374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    // May not be optimal; TODO: reconsider this warning based on other constraints? GENERAL can be better than
2251374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    // doing a bunch of transitions.
2252374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    skip |= log_msg(report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT,
2253374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                    VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
2254374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                    "GENERAL layout for depth attachment may not give optimal performance.");
2255374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    break;
2256374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski
2257374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                default:
2258374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    // No other layouts are acceptable
2259374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
2260374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                    __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
2261374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                    "Layout for depth attachment is %s but can only be DEPTH_STENCIL_ATTACHMENT_OPTIMAL, "
2262374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                    "DEPTH_STENCIL_READ_ONLY_OPTIMAL or GENERAL.",
2263374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                    string_VkImageLayout(subpass.pDepthStencilAttachment->layout));
2264d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            }
2265d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski
2266d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            auto attach_index = subpass.pDepthStencilAttachment->attachment;
2267d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            if (attach_first_use[attach_index]) {
2268374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                skip |= ValidateLayoutVsAttachmentDescription(report_data, subpass.pDepthStencilAttachment->layout, attach_index,
2269374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                                              pCreateInfo->pAttachments[attach_index]);
2270d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            }
2271d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            attach_first_use[attach_index] = false;
2272d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski        }
2273d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski        for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) {
2274d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            auto attach_index = subpass.pInputAttachments[j].attachment;
2275d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            if (attach_index == VK_ATTACHMENT_UNUSED) continue;
2276d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski
2277d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            switch (subpass.pInputAttachments[j].layout) {
2278374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
2279374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
2280374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    // These are ideal.
2281374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    break;
2282d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski
2283374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                case VK_IMAGE_LAYOUT_GENERAL:
2284374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    // May not be optimal. TODO: reconsider this warning based on other constraints.
2285374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    skip |= log_msg(report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT,
2286374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                    VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
2287374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                    "Layout for input attachment is GENERAL but should be READ_ONLY_OPTIMAL.");
2288374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    break;
2289374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski
2290374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                default:
2291374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    // No other layouts are acceptable
2292fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                    skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
2293fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                                    __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
2294374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                    "Layout for input attachment is %s but can only be READ_ONLY_OPTIMAL or GENERAL.",
2295374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                    string_VkImageLayout(subpass.pInputAttachments[j].layout));
2296d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            }
2297d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski
2298d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            if (attach_first_use[attach_index]) {
2299374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                skip |= ValidateLayoutVsAttachmentDescription(report_data, subpass.pInputAttachments[j].layout, attach_index,
2300374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                                              pCreateInfo->pAttachments[attach_index]);
2301d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            }
2302d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            attach_first_use[attach_index] = false;
2303d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski        }
2304d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski    }
2305d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski    return skip;
2306d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski}
2307c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski
2308c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski// For any image objects that overlap mapped memory, verify that their layouts are PREINIT or GENERAL
230909cd2c76808f1485206baeda9864f7ed907d7e05Mark Lobodzinskibool ValidateMapImageLayouts(core_validation::layer_data *device_data, VkDevice device, DEVICE_MEM_INFO const *mem_info,
231009cd2c76808f1485206baeda9864f7ed907d7e05Mark Lobodzinski                             VkDeviceSize offset, VkDeviceSize end_offset) {
231109cd2c76808f1485206baeda9864f7ed907d7e05Mark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
231209cd2c76808f1485206baeda9864f7ed907d7e05Mark Lobodzinski    bool skip = false;
231309cd2c76808f1485206baeda9864f7ed907d7e05Mark Lobodzinski    // Iterate over all bound image ranges and verify that for any that overlap the map ranges, the layouts are
231409cd2c76808f1485206baeda9864f7ed907d7e05Mark Lobodzinski    // VK_IMAGE_LAYOUT_PREINITIALIZED or VK_IMAGE_LAYOUT_GENERAL
2315c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski    // TODO : This can be optimized if we store ranges based on starting address and early exit when we pass our range
2316c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski    for (auto image_handle : mem_info->bound_images) {
2317c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski        auto img_it = mem_info->bound_ranges.find(image_handle);
2318c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski        if (img_it != mem_info->bound_ranges.end()) {
231909cd2c76808f1485206baeda9864f7ed907d7e05Mark Lobodzinski            if (rangesIntersect(device_data, &img_it->second, offset, end_offset)) {
2320c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski                std::vector<VkImageLayout> layouts;
232109cd2c76808f1485206baeda9864f7ed907d7e05Mark Lobodzinski                if (FindLayouts(device_data, VkImage(image_handle), layouts)) {
2322c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski                    for (auto layout : layouts) {
2323c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski                        if (layout != VK_IMAGE_LAYOUT_PREINITIALIZED && layout != VK_IMAGE_LAYOUT_GENERAL) {
2324fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                            skip |= log_msg(
2325fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                                report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
2326fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                                reinterpret_cast<const uint64_t &>(mem_info->mem), __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
2327fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                                "Mapping an image with layout %s can result in undefined behavior if this memory is "
2328fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                                "used by the device. Only GENERAL or PREINITIALIZED should be used.",
2329fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                                string_VkImageLayout(layout));
2330c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski                        }
2331c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski                    }
2332c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski                }
2333c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski            }
2334c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski        }
2335c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski    }
233609cd2c76808f1485206baeda9864f7ed907d7e05Mark Lobodzinski    return skip;
2337c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski}
23383683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski
23393683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski// Helper function to validate correct usage bits set for buffers or images. Verify that (actual & desired) flags != 0 or, if strict
23403683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski// is true, verify that (actual & desired) flags == desired
2341abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinskistatic bool validate_usage_flags(layer_data *device_data, VkFlags actual, VkFlags desired, VkBool32 strict, uint64_t obj_handle,
23427a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski                                 VulkanObjectType obj_type, int32_t const msgCode, char const *func_name, char const *usage_str) {
2343abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
23443683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski
23453683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    bool correct_usage = false;
2346abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinski    bool skip = false;
23477a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski    const char *type_str = object_string[obj_type];
23483683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    if (strict) {
23493683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski        correct_usage = ((actual & desired) == desired);
23503683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    } else {
23513683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski        correct_usage = ((actual & desired) != 0);
23523683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    }
23533683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    if (!correct_usage) {
23543683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski        if (msgCode == -1) {
23553683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski            // TODO: Fix callers with msgCode == -1 to use correct validation checks.
235602a510945ff39f3d9e486e456aca5bfa6ea0c43aMark Lobodzinski            skip = log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, get_debug_report_enum[obj_type], obj_handle, __LINE__,
23577a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski                           MEMTRACK_INVALID_USAGE_FLAG, "MEM",
23587a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski                           "Invalid usage flag for %s 0x%" PRIxLEAST64
23597a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski                           " used by %s. In this case, %s should have %s set during creation.",
23607a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski                           type_str, obj_handle, func_name, type_str, usage_str);
23613683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski        } else {
23623683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski            const char *valid_usage = (msgCode == -1) ? "" : validation_error_map[msgCode];
23637a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski            skip = log_msg(
236402a510945ff39f3d9e486e456aca5bfa6ea0c43aMark Lobodzinski                report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, get_debug_report_enum[obj_type], obj_handle, __LINE__, msgCode, "MEM",
23657a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski                "Invalid usage flag for %s 0x%" PRIxLEAST64 " used by %s. In this case, %s should have %s set during creation. %s",
23667a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski                type_str, obj_handle, func_name, type_str, usage_str, valid_usage);
23673683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski        }
23683683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    }
2369abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinski    return skip;
23703683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski}
23713683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski
23723683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski// Helper function to validate usage flags for buffers. For given buffer_state send actual vs. desired usage off to helper above
23733683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski// where an error will be flagged if usage is not correct
23740bcfcca3af64ac0214112949aa68496914b8d7a9Chris Forbesbool ValidateImageUsageFlags(layer_data *device_data, IMAGE_STATE const *image_state, VkFlags desired, bool strict,
23753683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski                             int32_t const msgCode, char const *func_name, char const *usage_string) {
2376abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinski    return validate_usage_flags(device_data, image_state->createInfo.usage, desired, strict,
23777a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski                                reinterpret_cast<const uint64_t &>(image_state->image), kVulkanObjectTypeImage, msgCode, func_name,
23787a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski                                usage_string);
23793683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski}
23803683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski
23813683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski// Helper function to validate usage flags for buffers. For given buffer_state send actual vs. desired usage off to helper above
23823683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski// where an error will be flagged if usage is not correct
23830bcfcca3af64ac0214112949aa68496914b8d7a9Chris Forbesbool ValidateBufferUsageFlags(layer_data *device_data, BUFFER_STATE const *buffer_state, VkFlags desired, bool strict,
23843683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski                              int32_t const msgCode, char const *func_name, char const *usage_string) {
2385abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinski    return validate_usage_flags(device_data, buffer_state->createInfo.usage, desired, strict,
23867a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski                                reinterpret_cast<const uint64_t &>(buffer_state->buffer), kVulkanObjectTypeBuffer, msgCode,
23877a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski                                func_name, usage_string);
23883683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski}
23893683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski
2390abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinskibool PreCallValidateCreateBuffer(layer_data *device_data, const VkBufferCreateInfo *pCreateInfo) {
23913683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    bool skip = false;
239201363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
239301363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski
23943683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    // TODO: Add check for VALIDATION_ERROR_00658
23953683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    // TODO: Add check for VALIDATION_ERROR_00667
23963683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    // TODO: Add check for VALIDATION_ERROR_00668
23973683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    // TODO: Add check for VALIDATION_ERROR_00669
239801363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski
239901363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski    if ((pCreateInfo->flags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT) && (!GetEnabledFeatures(device_data)->sparseBinding)) {
240001363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
240101363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski                        VALIDATION_ERROR_00666, "DS",
240201363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski                        "vkCreateBuffer(): the sparseBinding device feature is disabled: Buffers cannot be created with the "
240301363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski                        "VK_BUFFER_CREATE_SPARSE_BINDING_BIT set. %s",
240401363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski                        validation_error_map[VALIDATION_ERROR_00666]);
240501363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski    }
2406f575247dabffb70e4de1a6f9522db3f09a55492eMark Lobodzinski
2407f575247dabffb70e4de1a6f9522db3f09a55492eMark Lobodzinski    if ((pCreateInfo->flags & VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT) && (!GetEnabledFeatures(device_data)->sparseResidencyBuffer)) {
2408f575247dabffb70e4de1a6f9522db3f09a55492eMark Lobodzinski        skip |=
2409f575247dabffb70e4de1a6f9522db3f09a55492eMark Lobodzinski            log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
2410f575247dabffb70e4de1a6f9522db3f09a55492eMark Lobodzinski                    DRAWSTATE_INVALID_FEATURE, "DS",
2411f575247dabffb70e4de1a6f9522db3f09a55492eMark Lobodzinski                    "vkCreateBuffer(): the sparseResidencyBuffer device feature is disabled: Buffers cannot be created with the "
2412f575247dabffb70e4de1a6f9522db3f09a55492eMark Lobodzinski                    "VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT set.");
2413f575247dabffb70e4de1a6f9522db3f09a55492eMark Lobodzinski    }
24147e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski
24157e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski    if ((pCreateInfo->flags & VK_BUFFER_CREATE_SPARSE_ALIASED_BIT) && (!GetEnabledFeatures(device_data)->sparseResidencyAliased)) {
24167e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski        skip |=
24177e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski            log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
24187e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski                    DRAWSTATE_INVALID_FEATURE, "DS",
24197e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski                    "vkCreateBuffer(): the sparseResidencyAliased device feature is disabled: Buffers cannot be created with the "
24207e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski                    "VK_BUFFER_CREATE_SPARSE_ALIASED_BIT set.");
24217e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski    }
24223683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    return skip;
24233683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski}
24243683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski
24253683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinskivoid PostCallRecordCreateBuffer(layer_data *device_data, const VkBufferCreateInfo *pCreateInfo, VkBuffer *pBuffer) {
24263683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    // TODO : This doesn't create deep copy of pQueueFamilyIndices so need to fix that if/when we want that data to be valid
24273683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    GetBufferMap(device_data)
24283683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski        ->insert(std::make_pair(*pBuffer, std::unique_ptr<BUFFER_STATE>(new BUFFER_STATE(*pBuffer, pCreateInfo))));
24293683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski}
24303683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski
2431abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinskibool PreCallValidateCreateBufferView(layer_data *device_data, const VkBufferViewCreateInfo *pCreateInfo) {
2432abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinski    bool skip = false;
2433abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinski    BUFFER_STATE *buffer_state = GetBufferState(device_data, pCreateInfo->buffer);
24343683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    // If this isn't a sparse buffer, it needs to have memory backing it at CreateBufferView time
24353683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    if (buffer_state) {
2436abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinski        skip |= ValidateMemoryIsBoundToBuffer(device_data, buffer_state, "vkCreateBufferView()", VALIDATION_ERROR_02522);
24373683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski        // In order to create a valid buffer view, the buffer must have been created with at least one of the following flags:
24383683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski        // UNIFORM_TEXEL_BUFFER_BIT or STORAGE_TEXEL_BUFFER_BIT
2439abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinski        skip |= ValidateBufferUsageFlags(
2440abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinski            device_data, buffer_state, VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT, false,
24413683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski            VALIDATION_ERROR_00694, "vkCreateBufferView()", "VK_BUFFER_USAGE_[STORAGE|UNIFORM]_TEXEL_BUFFER_BIT");
24423683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    }
2443abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinski    return skip;
24443683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski}
24453683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski
24463683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinskivoid PostCallRecordCreateBufferView(layer_data *device_data, const VkBufferViewCreateInfo *pCreateInfo, VkBufferView *pView) {
24473683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    (*GetBufferViewMap(device_data))[*pView] = std::unique_ptr<BUFFER_VIEW_STATE>(new BUFFER_VIEW_STATE(*pView, pCreateInfo));
24483683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski}
24491c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski
24501c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski// For the given format verify that the aspect masks make sense
24511c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinskibool ValidateImageAspectMask(layer_data *device_data, VkImage image, VkFormat format, VkImageAspectFlags aspect_mask,
24521c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                             const char *func_name) {
24531c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
24541c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    bool skip = false;
245516769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton    if (FormatIsColor(format)) {
24561c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        if ((aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT) != VK_IMAGE_ASPECT_COLOR_BIT) {
24571c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, (uint64_t)image,
24581c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            __LINE__, VALIDATION_ERROR_00741, "IMAGE",
24591c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            "%s: Color image formats must have the VK_IMAGE_ASPECT_COLOR_BIT set. %s", func_name,
24601c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            validation_error_map[VALIDATION_ERROR_00741]);
24611c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        } else if ((aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT) != aspect_mask) {
24621c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, (uint64_t)image,
24631c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            __LINE__, VALIDATION_ERROR_00741, "IMAGE",
24641c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            "%s: Color image formats must have ONLY the VK_IMAGE_ASPECT_COLOR_BIT set. %s", func_name,
24651c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            validation_error_map[VALIDATION_ERROR_00741]);
24661c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        }
246716769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton    } else if (FormatIsDepthAndStencil(format)) {
24681c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        if ((aspect_mask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) == 0) {
24691c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, (uint64_t)image,
24701c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            __LINE__, VALIDATION_ERROR_00741, "IMAGE",
24711c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            "%s: Depth/stencil image formats must have "
24721c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            "at least one of VK_IMAGE_ASPECT_DEPTH_BIT "
24731c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            "and VK_IMAGE_ASPECT_STENCIL_BIT set. %s",
24741c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            func_name, validation_error_map[VALIDATION_ERROR_00741]);
24751c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        } else if ((aspect_mask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) != aspect_mask) {
24761c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, (uint64_t)image,
24771c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            __LINE__, VALIDATION_ERROR_00741, "IMAGE",
24781c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            "%s: Combination depth/stencil image formats can have only the VK_IMAGE_ASPECT_DEPTH_BIT and "
24791c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            "VK_IMAGE_ASPECT_STENCIL_BIT set. %s",
24801c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            func_name, validation_error_map[VALIDATION_ERROR_00741]);
24811c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        }
248216769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton    } else if (FormatIsDepthOnly(format)) {
24831c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        if ((aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) != VK_IMAGE_ASPECT_DEPTH_BIT) {
24841c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, (uint64_t)image,
24851c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            __LINE__, VALIDATION_ERROR_00741, "IMAGE",
24861c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            "%s: Depth-only image formats must have the VK_IMAGE_ASPECT_DEPTH_BIT set. %s", func_name,
24871c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            validation_error_map[VALIDATION_ERROR_00741]);
24881c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        } else if ((aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) != aspect_mask) {
24891c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, (uint64_t)image,
24901c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            __LINE__, VALIDATION_ERROR_00741, "IMAGE",
24911c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            "%s: Depth-only image formats can have only the VK_IMAGE_ASPECT_DEPTH_BIT set. %s", func_name,
24921c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            validation_error_map[VALIDATION_ERROR_00741]);
24931c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        }
249416769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton    } else if (FormatIsStencilOnly(format)) {
24951c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        if ((aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT) != VK_IMAGE_ASPECT_STENCIL_BIT) {
24961c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, (uint64_t)image,
24971c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            __LINE__, VALIDATION_ERROR_00741, "IMAGE",
24981c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            "%s: Stencil-only image formats must have the VK_IMAGE_ASPECT_STENCIL_BIT set. %s", func_name,
24991c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            validation_error_map[VALIDATION_ERROR_00741]);
25001c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        } else if ((aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT) != aspect_mask) {
25011c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, (uint64_t)image,
25021c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            __LINE__, VALIDATION_ERROR_00741, "IMAGE",
25031c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            "%s: Stencil-only image formats can have only the VK_IMAGE_ASPECT_STENCIL_BIT set. %s", func_name,
25041c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            validation_error_map[VALIDATION_ERROR_00741]);
25051c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        }
25061c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    }
25071c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    return skip;
25081c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski}
25091c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski
25101c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinskibool ValidateImageSubrangeLevelLayerCounts(layer_data *device_data, const VkImageSubresourceRange &subresourceRange,
25111c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                                           const char *func_name) {
25121c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
25131c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    bool skip = false;
25141c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    if (subresourceRange.levelCount == 0) {
2515fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
25161c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                        VALIDATION_ERROR_00768, "IMAGE", "%s called with 0 in subresourceRange.levelCount. %s", func_name,
25171c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                        validation_error_map[VALIDATION_ERROR_00768]);
25181c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    }
25191c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    if (subresourceRange.layerCount == 0) {
2520fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
25211c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                        VALIDATION_ERROR_00769, "IMAGE", "%s called with 0 in subresourceRange.layerCount. %s", func_name,
25221c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                        validation_error_map[VALIDATION_ERROR_00769]);
25231c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    }
25241c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    return skip;
25251c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski}
25261c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski
25271c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinskibool PreCallValidateCreateImageView(layer_data *device_data, const VkImageViewCreateInfo *create_info) {
25281c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
25291c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    bool skip = false;
25301c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    IMAGE_STATE *image_state = GetImageState(device_data, create_info->image);
25311c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    if (image_state) {
25321c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        skip |= ValidateImageUsageFlags(
25331c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            device_data, image_state,
25341c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT |
25351c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
25361c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            false, -1, "vkCreateImageView()",
25371c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            "VK_IMAGE_USAGE_[SAMPLED|STORAGE|COLOR_ATTACHMENT|DEPTH_STENCIL_ATTACHMENT|INPUT_ATTACHMENT]_BIT");
25381c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        // If this isn't a sparse image, it needs to have memory backing it at CreateImageView time
25391c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        skip |= ValidateMemoryIsBoundToImage(device_data, image_state, "vkCreateImageView()", VALIDATION_ERROR_02524);
25401c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        // Checks imported from image layer
2541b831ab1eb11c80b51fb33c1c390298421d65b540Jeremy Hayes        if ((create_info->subresourceRange.baseMipLevel + create_info->subresourceRange.levelCount) >
2542b831ab1eb11c80b51fb33c1c390298421d65b540Jeremy Hayes            image_state->createInfo.mipLevels) {
25431c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            std::stringstream ss;
25441c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            ss << "vkCreateImageView called with baseMipLevel " << create_info->subresourceRange.baseMipLevel << " for image "
25451c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski               << create_info->image << " that only has " << image_state->createInfo.mipLevels << " mip levels.";
25461c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            skip |=
2547fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
25481c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                        VALIDATION_ERROR_00768, "IMAGE", "%s %s", ss.str().c_str(), validation_error_map[VALIDATION_ERROR_00768]);
25491c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        }
255057eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt        if (!GetDeviceExtensions(device_data)->khr_maintenance1_enabled) {
255157eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt            if (create_info->subresourceRange.baseArrayLayer >= image_state->createInfo.arrayLayers) {
255257eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt                std::stringstream ss;
255357eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt                ss << "vkCreateImageView called with baseArrayLayer " << create_info->subresourceRange.baseArrayLayer
255457eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt                   << " for image " << create_info->image << " that only has " << image_state->createInfo.arrayLayers
255557eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt                   << " array layers.";
255657eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
255757eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt                                VALIDATION_ERROR_00769, "IMAGE", "%s %s", ss.str().c_str(),
255857eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt                                validation_error_map[VALIDATION_ERROR_00769]);
255957eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt            }
25601c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        }
25611c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        // TODO: Need new valid usage language for levelCount == 0 & layerCount == 0
25621c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        skip |= ValidateImageSubrangeLevelLayerCounts(device_data, create_info->subresourceRange, "vkCreateImageView()");
25631c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski
25641c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        VkImageCreateFlags image_flags = image_state->createInfo.flags;
25651c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        VkFormat image_format = image_state->createInfo.format;
25661c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        VkFormat view_format = create_info->format;
25671c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        VkImageAspectFlags aspect_mask = create_info->subresourceRange.aspectMask;
25681c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski
25691c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        // Validate VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT state
25701c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        if (image_flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) {
25711c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            // Format MUST be compatible (in the same format compatibility class) as the format the image was created with
257216769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton            if (FormatCompatibilityClass(image_format) != FormatCompatibilityClass(view_format)) {
25731c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                std::stringstream ss;
25741c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                ss << "vkCreateImageView(): ImageView format " << string_VkFormat(view_format)
25751c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                   << " is not in the same format compatibility class as image (" << (uint64_t)create_info->image << ")  format "
25761c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                   << string_VkFormat(image_format) << ".  Images created with the VK_IMAGE_CREATE_MUTABLE_FORMAT BIT "
25771c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                   << "can support ImageViews with differing formats but they must be in the same compatibility class.";
2578fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
25791c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                                VALIDATION_ERROR_02171, "IMAGE", "%s %s", ss.str().c_str(),
25801c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                                validation_error_map[VALIDATION_ERROR_02171]);
25811c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            }
25821c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        } else {
25831c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            // Format MUST be IDENTICAL to the format the image was created with
25841c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            if (image_format != view_format) {
25851c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                std::stringstream ss;
25861c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                ss << "vkCreateImageView() format " << string_VkFormat(view_format) << " differs from image "
25871c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                   << (uint64_t)create_info->image << " format " << string_VkFormat(image_format)
25881c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                   << ".  Formats MUST be IDENTICAL unless VK_IMAGE_CREATE_MUTABLE_FORMAT BIT was set on image creation.";
2589fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
25901c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                                VALIDATION_ERROR_02172, "IMAGE", "%s %s", ss.str().c_str(),
25911c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                                validation_error_map[VALIDATION_ERROR_02172]);
25921c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            }
25931c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        }
25941c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski
25951c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        // Validate correct image aspect bits for desired formats and format consistency
25961c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        skip |= ValidateImageAspectMask(device_data, image_state->image, image_format, aspect_mask, "vkCreateImageView()");
25971c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    }
25981c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    return skip;
25991c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski}
26001c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski
2601d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinskivoid PostCallRecordCreateImageView(layer_data *device_data, const VkImageViewCreateInfo *create_info, VkImageView view) {
2602d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski    auto image_view_map = GetImageViewMap(device_data);
2603d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski    (*image_view_map)[view] = std::unique_ptr<IMAGE_VIEW_STATE>(new IMAGE_VIEW_STATE(view, create_info));
2604d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski
2605d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski    auto image_state = GetImageState(device_data, create_info->image);
2606e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton    auto &sub_res_range = (*image_view_map)[view].get()->create_info.subresourceRange;
260795b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski    sub_res_range.levelCount = ResolveRemainingLevels(&sub_res_range, image_state->createInfo.mipLevels);
260895b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski    sub_res_range.layerCount = ResolveRemainingLayers(&sub_res_range, image_state->createInfo.arrayLayers);
26091c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski}
26106a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
2611c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinskibool PreCallValidateCmdCopyBuffer(layer_data *device_data, GLOBAL_CB_NODE *cb_node, BUFFER_STATE *src_buffer_state,
2612c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski                                  BUFFER_STATE *dst_buffer_state) {
2613c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    bool skip = false;
2614c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    skip |= ValidateMemoryIsBoundToBuffer(device_data, src_buffer_state, "vkCmdCopyBuffer()", VALIDATION_ERROR_02531);
2615c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    skip |= ValidateMemoryIsBoundToBuffer(device_data, dst_buffer_state, "vkCmdCopyBuffer()", VALIDATION_ERROR_02532);
2616c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    // Validate that SRC & DST buffers have correct usage flags set
2617c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    skip |= ValidateBufferUsageFlags(device_data, src_buffer_state, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, true, VALIDATION_ERROR_01164,
2618c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski                                     "vkCmdCopyBuffer()", "VK_BUFFER_USAGE_TRANSFER_SRC_BIT");
2619c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    skip |= ValidateBufferUsageFlags(device_data, dst_buffer_state, VK_BUFFER_USAGE_TRANSFER_DST_BIT, true, VALIDATION_ERROR_01165,
2620c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski                                     "vkCmdCopyBuffer()", "VK_BUFFER_USAGE_TRANSFER_DST_BIT");
2621baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt    skip |= ValidateCmdQueueFlags(device_data, cb_node, "vkCmdCopyBuffer()",
2622baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt                                  VK_QUEUE_TRANSFER_BIT | VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, VALIDATION_ERROR_01171);
2623c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    skip |= ValidateCmd(device_data, cb_node, CMD_COPYBUFFER, "vkCmdCopyBuffer()");
2624c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    skip |= insideRenderPass(device_data, cb_node, "vkCmdCopyBuffer()", VALIDATION_ERROR_01172);
2625c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    return skip;
2626c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski}
26276a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
2628c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinskivoid PreCallRecordCmdCopyBuffer(layer_data *device_data, GLOBAL_CB_NODE *cb_node, BUFFER_STATE *src_buffer_state,
2629c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski                                BUFFER_STATE *dst_buffer_state) {
2630c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    // Update bindings between buffers and cmd buffer
2631c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    AddCommandBufferBindingBuffer(device_data, cb_node, src_buffer_state);
2632c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    AddCommandBufferBindingBuffer(device_data, cb_node, dst_buffer_state);
2633c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski
2634c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    std::function<bool()> function = [=]() {
2635c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski        return ValidateBufferMemoryIsValid(device_data, src_buffer_state, "vkCmdCopyBuffer()");
2636c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    };
2637c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    cb_node->validate_functions.push_back(function);
2638c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    function = [=]() {
2639c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski        SetBufferMemoryValid(device_data, dst_buffer_state, true);
2640c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski        return false;
2641c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    };
2642c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    cb_node->validate_functions.push_back(function);
2643c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    core_validation::UpdateCmdBufferLastCmd(cb_node, CMD_COPYBUFFER);
2644c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski}
2645842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski
2646842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinskistatic bool validateIdleBuffer(layer_data *device_data, VkBuffer buffer) {
2647842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
2648842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    bool skip = false;
2649842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    auto buffer_state = GetBufferState(device_data, buffer);
2650842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    if (!buffer_state) {
2651842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, (uint64_t)(buffer),
2652842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski                        __LINE__, DRAWSTATE_DOUBLE_DESTROY, "DS",
2653842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski                        "Cannot free buffer 0x%" PRIxLEAST64 " that has not been allocated.", (uint64_t)(buffer));
2654842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    } else {
2655842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski        if (buffer_state->in_use.load()) {
2656842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, (uint64_t)(buffer),
2657842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski                            __LINE__, VALIDATION_ERROR_00676, "DS",
2658842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski                            "Cannot free buffer 0x%" PRIxLEAST64 " that is in use by a command buffer. %s", (uint64_t)(buffer),
2659842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski                            validation_error_map[VALIDATION_ERROR_00676]);
2660842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski        }
2661842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    }
2662842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    return skip;
2663842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski}
2664842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski
2665842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinskibool PreCallValidateDestroyImageView(layer_data *device_data, VkImageView image_view, IMAGE_VIEW_STATE **image_view_state,
2666842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski                                     VK_OBJECT *obj_struct) {
2667842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    *image_view_state = GetImageViewState(device_data, image_view);
26687a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski    *obj_struct = {reinterpret_cast<uint64_t &>(image_view), kVulkanObjectTypeImageView};
2669842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    if (GetDisables(device_data)->destroy_image_view) return false;
2670842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    bool skip = false;
2671842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    if (*image_view_state) {
2672842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski        skip |= ValidateObjectNotInUse(device_data, *image_view_state, *obj_struct, VALIDATION_ERROR_00776);
2673842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    }
2674842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    return skip;
2675842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski}
2676842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski
2677842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinskivoid PostCallRecordDestroyImageView(layer_data *device_data, VkImageView image_view, IMAGE_VIEW_STATE *image_view_state,
2678842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski                                    VK_OBJECT obj_struct) {
2679842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    // Any bound cmd buffers are now invalid
2680842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    invalidateCommandBuffers(device_data, image_view_state->cb_bindings, obj_struct);
2681842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    (*GetImageViewMap(device_data)).erase(image_view);
2682842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski}
2683842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski
2684842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinskibool PreCallValidateDestroyBuffer(layer_data *device_data, VkBuffer buffer, BUFFER_STATE **buffer_state, VK_OBJECT *obj_struct) {
2685842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    *buffer_state = GetBufferState(device_data, buffer);
2686cf2ce8673669ca1111e333bdea272c4dd57cb5c2Dave Houlton    *obj_struct = {reinterpret_cast<uint64_t &>(buffer), kVulkanObjectTypeBuffer};
2687842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    if (GetDisables(device_data)->destroy_buffer) return false;
2688842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    bool skip = false;
2689842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    if (*buffer_state) {
2690842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski        skip |= validateIdleBuffer(device_data, buffer);
2691842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    }
2692842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    return skip;
2693842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski}
2694842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski
2695842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinskivoid PostCallRecordDestroyBuffer(layer_data *device_data, VkBuffer buffer, BUFFER_STATE *buffer_state, VK_OBJECT obj_struct) {
2696842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    invalidateCommandBuffers(device_data, buffer_state->cb_bindings, obj_struct);
2697842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    for (auto mem_binding : buffer_state->GetBoundMemory()) {
2698842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski        auto mem_info = GetMemObjInfo(device_data, mem_binding);
2699842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski        if (mem_info) {
2700842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski            core_validation::RemoveBufferMemoryRange(reinterpret_cast<uint64_t &>(buffer), mem_info);
2701842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski        }
2702842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    }
27037a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski    ClearMemoryObjectBindings(device_data, reinterpret_cast<uint64_t &>(buffer), kVulkanObjectTypeBuffer);
2704842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    GetBufferMap(device_data)->erase(buffer_state->buffer);
2705842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski}
2706842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski
2707842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinskibool PreCallValidateDestroyBufferView(layer_data *device_data, VkBufferView buffer_view, BUFFER_VIEW_STATE **buffer_view_state,
2708842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski                                      VK_OBJECT *obj_struct) {
2709842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    *buffer_view_state = GetBufferViewState(device_data, buffer_view);
2710cf2ce8673669ca1111e333bdea272c4dd57cb5c2Dave Houlton    *obj_struct = {reinterpret_cast<uint64_t &>(buffer_view), kVulkanObjectTypeBufferView};
2711842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    if (GetDisables(device_data)->destroy_buffer_view) return false;
2712842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    bool skip = false;
2713842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    if (*buffer_view_state) {
2714842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski        skip |= ValidateObjectNotInUse(device_data, *buffer_view_state, *obj_struct, VALIDATION_ERROR_00701);
2715842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    }
2716842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    return skip;
2717842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski}
2718842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski
2719842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinskivoid PostCallRecordDestroyBufferView(layer_data *device_data, VkBufferView buffer_view, BUFFER_VIEW_STATE *buffer_view_state,
2720842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski                                     VK_OBJECT obj_struct) {
2721842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    // Any bound cmd buffers are now invalid
2722842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    invalidateCommandBuffers(device_data, buffer_view_state->cb_bindings, obj_struct);
2723842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    GetBufferViewMap(device_data)->erase(buffer_view);
2724842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski}
272523bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski
272623bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinskibool PreCallValidateCmdFillBuffer(layer_data *device_data, GLOBAL_CB_NODE *cb_node, BUFFER_STATE *buffer_state) {
272723bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski    bool skip = false;
272823bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski    skip |= ValidateMemoryIsBoundToBuffer(device_data, buffer_state, "vkCmdFillBuffer()", VALIDATION_ERROR_02529);
2729baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt    skip |= ValidateCmdQueueFlags(device_data, cb_node, "vkCmdFillBuffer()",
2730baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt                                  VK_QUEUE_TRANSFER_BIT | VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, VALIDATION_ERROR_01141);
273123bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski    skip |= ValidateCmd(device_data, cb_node, CMD_FILLBUFFER, "vkCmdFillBuffer()");
273223bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski    // Validate that DST buffer has correct usage flags set
273323bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski    skip |= ValidateBufferUsageFlags(device_data, buffer_state, VK_BUFFER_USAGE_TRANSFER_DST_BIT, true, VALIDATION_ERROR_01137,
273423bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski                                     "vkCmdFillBuffer()", "VK_BUFFER_USAGE_TRANSFER_DST_BIT");
273523bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski    skip |= insideRenderPass(device_data, cb_node, "vkCmdFillBuffer()", VALIDATION_ERROR_01142);
273623bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski    return skip;
273723bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski}
273823bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski
273923bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinskivoid PreCallRecordCmdFillBuffer(layer_data *device_data, GLOBAL_CB_NODE *cb_node, BUFFER_STATE *buffer_state) {
274023bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski    std::function<bool()> function = [=]() {
274123bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski        SetBufferMemoryValid(device_data, buffer_state, true);
274223bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski        return false;
274323bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski    };
274423bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski    cb_node->validate_functions.push_back(function);
274523bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski    // Update bindings between buffer and cmd buffer
274623bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski    AddCommandBufferBindingBuffer(device_data, cb_node, buffer_state);
274723bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski    core_validation::UpdateCmdBufferLastCmd(cb_node, CMD_FILLBUFFER);
274823bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski}
2749877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski
275071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinskibool ValidateBufferImageCopyData(const debug_report_data *report_data, uint32_t regionCount, const VkBufferImageCopy *pRegions,
275171c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                                 IMAGE_STATE *image_state, const char *function) {
2752877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski    bool skip = false;
2753877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski
2754877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski    for (uint32_t i = 0; i < regionCount; i++) {
27555971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        if (image_state->createInfo.imageType == VK_IMAGE_TYPE_1D) {
27565971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            if ((pRegions[i].imageOffset.y != 0) || (pRegions[i].imageExtent.height != 1)) {
27575971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
27585971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01746, "IMAGE",
27595971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                "%s(): pRegion[%d] imageOffset.y is %d and imageExtent.height is %d. For 1D images these "
27605971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                "must be 0 and 1, respectively. %s",
27615971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                function, i, pRegions[i].imageOffset.y, pRegions[i].imageExtent.height,
27625971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                validation_error_map[VALIDATION_ERROR_01746]);
2763877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski            }
27645971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        }
2765877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski
27665971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        if ((image_state->createInfo.imageType == VK_IMAGE_TYPE_1D) || (image_state->createInfo.imageType == VK_IMAGE_TYPE_2D)) {
27675971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            if ((pRegions[i].imageOffset.z != 0) || (pRegions[i].imageExtent.depth != 1)) {
2768877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
27695971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01747, "IMAGE",
27705971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                "%s(): pRegion[%d] imageOffset.z is %d and imageExtent.depth is %d. For 1D and 2D images these "
27715971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                "must be 0 and 1, respectively. %s",
27725971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                function, i, pRegions[i].imageOffset.z, pRegions[i].imageExtent.depth,
27735971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                validation_error_map[VALIDATION_ERROR_01747]);
2774877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski            }
27755971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        }
2776877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski
27775971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        if (image_state->createInfo.imageType == VK_IMAGE_TYPE_3D) {
27785971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            if ((0 != pRegions[i].imageSubresource.baseArrayLayer) || (1 != pRegions[i].imageSubresource.layerCount)) {
2779877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
27805971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01281, "IMAGE",
27815971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                "%s(): pRegion[%d] imageSubresource.baseArrayLayer is %d and imageSubresource.layerCount is "
27825971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                "%d. For 3D images these must be 0 and 1, respectively. %s",
27835971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                function, i, pRegions[i].imageSubresource.baseArrayLayer, pRegions[i].imageSubresource.layerCount,
27845971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                validation_error_map[VALIDATION_ERROR_01281]);
2785877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski            }
27865971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        }
2787877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski
27885971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        // If the the calling command's VkImage parameter's format is not a depth/stencil format,
27895971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        // then bufferOffset must be a multiple of the calling command's VkImage parameter's texel size
279016769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton        auto texel_size = FormatSize(image_state->createInfo.format);
2791cf2ce8673669ca1111e333bdea272c4dd57cb5c2Dave Houlton        if (!FormatIsDepthAndStencil(image_state->createInfo.format) && SafeModulo(pRegions[i].bufferOffset, texel_size) != 0) {
27925971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
27935971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                            reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01263, "IMAGE",
27945971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                            "%s(): pRegion[%d] bufferOffset 0x%" PRIxLEAST64
27955971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                            " must be a multiple of this format's texel size (" PRINTF_SIZE_T_SPECIFIER "). %s",
27965971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                            function, i, pRegions[i].bufferOffset, texel_size, validation_error_map[VALIDATION_ERROR_01263]);
27975971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        }
27985971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton
27995971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        //  BufferOffset must be a multiple of 4
280016769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton        if (SafeModulo(pRegions[i].bufferOffset, 4) != 0) {
28015971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
28025971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                            reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01264, "IMAGE",
28035971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                            "%s(): pRegion[%d] bufferOffset 0x%" PRIxLEAST64 " must be a multiple of 4. %s", function, i,
28045971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                            pRegions[i].bufferOffset, validation_error_map[VALIDATION_ERROR_01264]);
28055971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        }
28065971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton
28075971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        //  BufferRowLength must be 0, or greater than or equal to the width member of imageExtent
28085971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        if ((pRegions[i].bufferRowLength != 0) && (pRegions[i].bufferRowLength < pRegions[i].imageExtent.width)) {
28095971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            skip |= log_msg(
28105971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
28115971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01265, "IMAGE",
28125971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                "%s(): pRegion[%d] bufferRowLength (%d) must be zero or greater-than-or-equal-to imageExtent.width (%d). %s",
28135971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                function, i, pRegions[i].bufferRowLength, pRegions[i].imageExtent.width,
28145971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                validation_error_map[VALIDATION_ERROR_01265]);
28155971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        }
28165971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton
28175971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        //  BufferImageHeight must be 0, or greater than or equal to the height member of imageExtent
28185971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        if ((pRegions[i].bufferImageHeight != 0) && (pRegions[i].bufferImageHeight < pRegions[i].imageExtent.height)) {
28195971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            skip |= log_msg(
28205971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
28215971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01266, "IMAGE",
28225971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                "%s(): pRegion[%d] bufferImageHeight (%d) must be zero or greater-than-or-equal-to imageExtent.height (%d). %s",
28235971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                function, i, pRegions[i].bufferImageHeight, pRegions[i].imageExtent.height,
28245971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                validation_error_map[VALIDATION_ERROR_01266]);
28255971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        }
28265971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton
28275971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        // subresource aspectMask must have exactly 1 bit set
28285971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        const int num_bits = sizeof(VkFlags) * CHAR_BIT;
28295971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        std::bitset<num_bits> aspect_mask_bits(pRegions[i].imageSubresource.aspectMask);
28305971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        if (aspect_mask_bits.count() != 1) {
28315971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
28325971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                            reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01280, "IMAGE",
28335971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                            "%s: aspectMasks for imageSubresource in each region must have only a single bit set. %s", function,
28345971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                            validation_error_map[VALIDATION_ERROR_01280]);
28355971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        }
28365971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton
28375971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        // image subresource aspect bit must match format
2838e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton        if (!VerifyAspectsPresent(pRegions[i].imageSubresource.aspectMask, image_state->createInfo.format)) {
28395971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            skip |= log_msg(
28405971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
28415971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01279, "IMAGE",
28425971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                "%s(): pRegion[%d] subresource aspectMask 0x%x specifies aspects that are not present in image format 0x%x. %s",
28435971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                function, i, pRegions[i].imageSubresource.aspectMask, image_state->createInfo.format,
28445971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                validation_error_map[VALIDATION_ERROR_01279]);
28455971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        }
28465971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton
28475971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        // Checks that apply only to compressed images
28485971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        // TODO: there is a comment in ValidateCopyBufferImageTransferGranularityRequirements() in core_validation.cpp that
28495971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        //       reserves a place for these compressed image checks.  This block of code could move there once the image
28505971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        //       stuff is moved into core validation.
285116769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton        if (FormatIsCompressed(image_state->createInfo.format)) {
285216769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton            auto block_size = FormatCompressedTexelBlockExtent(image_state->createInfo.format);
2853877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski
28545971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            //  BufferRowLength must be a multiple of block width
285516769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton            if (SafeModulo(pRegions[i].bufferRowLength, block_size.width) != 0) {
2856877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski                skip |= log_msg(
2857877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski                    report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
28585971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                    reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01271, "IMAGE",
28595971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                    "%s(): pRegion[%d] bufferRowLength (%d) must be a multiple of the compressed image's texel width (%d). %s.",
28605971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                    function, i, pRegions[i].bufferRowLength, block_size.width, validation_error_map[VALIDATION_ERROR_01271]);
2861877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski            }
2862877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski
28635971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            //  BufferRowHeight must be a multiple of block height
286416769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton            if (SafeModulo(pRegions[i].bufferImageHeight, block_size.height) != 0) {
2865877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
28665971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01272, "IMAGE",
28675971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                "%s(): pRegion[%d] bufferImageHeight (%d) must be a multiple of the compressed image's texel "
28685971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                "height (%d). %s.",
28695971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                function, i, pRegions[i].bufferImageHeight, block_size.height,
28705971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                validation_error_map[VALIDATION_ERROR_01272]);
2871877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski            }
2872877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski
28735971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            //  image offsets must be multiples of block dimensions
287416769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton            if ((SafeModulo(pRegions[i].imageOffset.x, block_size.width) != 0) ||
287516769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton                (SafeModulo(pRegions[i].imageOffset.y, block_size.height) != 0) ||
287616769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton                (SafeModulo(pRegions[i].imageOffset.z, block_size.depth) != 0)) {
28775971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
28785971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01273, "IMAGE",
28795971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                "%s(): pRegion[%d] imageOffset(x,y) (%d, %d) must be multiples of the compressed image's texel "
28805971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                "width & height (%d, %d). %s.",
28815971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                function, i, pRegions[i].imageOffset.x, pRegions[i].imageOffset.y, block_size.width,
28825971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                block_size.height, validation_error_map[VALIDATION_ERROR_01273]);
2883877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski            }
2884877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski
28855971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            // bufferOffset must be a multiple of block size (linear bytes)
288616769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton            size_t block_size_in_bytes = FormatSize(image_state->createInfo.format);
288716769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton            if (SafeModulo(pRegions[i].bufferOffset, block_size_in_bytes) != 0) {
28885971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
28895971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01274, "IMAGE",
28905971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                "%s(): pRegion[%d] bufferOffset (0x%" PRIxLEAST64
28915971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                ") must be a multiple of the compressed image's texel block "
28925971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                "size (" PRINTF_SIZE_T_SPECIFIER "). %s.",
28935971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                function, i, pRegions[i].bufferOffset, block_size_in_bytes,
28945971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                validation_error_map[VALIDATION_ERROR_01274]);
2895877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski            }
28962cd49094dcd399721f50c123413b8f55693348d7Dave Houlton
28972cd49094dcd399721f50c123413b8f55693348d7Dave Houlton            // imageExtent width must be a multiple of block width, or extent+offset width must equal subresource width
2898045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton            VkExtent3D mip_extent = GetImageSubresourceExtent(image_state, &(pRegions[i].imageSubresource));
289916769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton            if ((SafeModulo(pRegions[i].imageExtent.width, block_size.width) != 0) &&
2900045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                (pRegions[i].imageExtent.width + pRegions[i].imageOffset.x != mip_extent.width)) {
2901045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
2902045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                                reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01275, "IMAGE",
2903045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                                "%s(): pRegion[%d] extent width (%d) must be a multiple of the compressed texture block width "
2904045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                                "(%d), or when added to offset.x (%d) must equal the image subresource width (%d). %s.",
2905045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                                function, i, pRegions[i].imageExtent.width, block_size.width, pRegions[i].imageOffset.x,
2906045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                                mip_extent.width, validation_error_map[VALIDATION_ERROR_01275]);
29072cd49094dcd399721f50c123413b8f55693348d7Dave Houlton            }
29082cd49094dcd399721f50c123413b8f55693348d7Dave Houlton
29092cd49094dcd399721f50c123413b8f55693348d7Dave Houlton            // imageExtent height must be a multiple of block height, or extent+offset height must equal subresource height
291016769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton            if ((SafeModulo(pRegions[i].imageExtent.height, block_size.height) != 0) &&
2911045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                (pRegions[i].imageExtent.height + pRegions[i].imageOffset.y != mip_extent.height)) {
2912045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
2913045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                                reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01276, "IMAGE",
2914045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                                "%s(): pRegion[%d] extent height (%d) must be a multiple of the compressed texture block height "
2915045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                                "(%d), or when added to offset.y (%d) must equal the image subresource height (%d). %s.",
2916045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                                function, i, pRegions[i].imageExtent.height, block_size.height, pRegions[i].imageOffset.y,
2917045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                                mip_extent.height, validation_error_map[VALIDATION_ERROR_01276]);
29182cd49094dcd399721f50c123413b8f55693348d7Dave Houlton            }
29192cd49094dcd399721f50c123413b8f55693348d7Dave Houlton
29202cd49094dcd399721f50c123413b8f55693348d7Dave Houlton            // imageExtent depth must be a multiple of block depth, or extent+offset depth must equal subresource depth
292116769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton            if ((SafeModulo(pRegions[i].imageExtent.depth, block_size.depth) != 0) &&
2922045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                (pRegions[i].imageExtent.depth + pRegions[i].imageOffset.z != mip_extent.depth)) {
2923045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
2924045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                                reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01277, "IMAGE",
2925045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                                "%s(): pRegion[%d] extent width (%d) must be a multiple of the compressed texture block depth "
2926045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                                "(%d), or when added to offset.z (%d) must equal the image subresource depth (%d). %s.",
2927045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                                function, i, pRegions[i].imageExtent.depth, block_size.depth, pRegions[i].imageOffset.z,
2928045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                                mip_extent.depth, validation_error_map[VALIDATION_ERROR_01277]);
29292cd49094dcd399721f50c123413b8f55693348d7Dave Houlton            }
29305971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        }
293171c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    }
293271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
293371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    return skip;
293471c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski}
293571c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
29365971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houltonstatic bool ValidateImageBounds(const debug_report_data *report_data, const IMAGE_STATE *image_state, const uint32_t regionCount,
29375971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                const VkBufferImageCopy *pRegions, const char *func_name, UNIQUE_VALIDATION_ERROR_CODE msg_code) {
293871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    bool skip = false;
29395971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton    const VkImageCreateInfo *image_info = &(image_state->createInfo);
294071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
294171c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    for (uint32_t i = 0; i < regionCount; i++) {
294271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        VkExtent3D extent = pRegions[i].imageExtent;
294371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        VkOffset3D offset = pRegions[i].imageOffset;
294471c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
29455971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        if (IsExtentSizeZero(&extent))  // Warn on zero area subresource
29465971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        {
29475971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
29485971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                            (uint64_t)0, __LINE__, IMAGE_ZERO_AREA_SUBREGION, "IMAGE",
29495971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                            "%s: pRegion[%d] imageExtent of {%1d, %1d, %1d} has zero area", func_name, i, extent.width,
29505971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                            extent.height, extent.depth);
295171c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        }
295271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
29535971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        VkExtent3D image_extent = GetImageSubresourceExtent(image_state, &(pRegions[i].imageSubresource));
29545971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton
29555971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        // If we're using a compressed format, valid extent is rounded up to multiple of block size (per 18.1)
295616769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton        if (FormatIsCompressed(image_info->format)) {
295716769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton            auto block_extent = FormatCompressedTexelBlockExtent(image_info->format);
29585971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            if (image_extent.width % block_extent.width) {
29595971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                image_extent.width += (block_extent.width - (image_extent.width % block_extent.width));
29605971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            }
29615971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            if (image_extent.height % block_extent.height) {
29625971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                image_extent.height += (block_extent.height - (image_extent.height % block_extent.height));
29635971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            }
29645971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            if (image_extent.depth % block_extent.depth) {
29655971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                image_extent.depth += (block_extent.depth - (image_extent.depth % block_extent.depth));
29665971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            }
296771c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        }
296871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
29693fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton        if (0 != ExceedsBounds(&offset, &extent, &image_extent)) {
297071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)0,
29715971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                            __LINE__, msg_code, "IMAGE", "%s: pRegion[%d] exceeds image bounds. %s.", func_name, i,
297271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                            validation_error_map[msg_code]);
2973877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski        }
2974877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski    }
2975877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski
2976877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski    return skip;
2977877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski}
2978877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski
297971c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinskistatic inline bool ValidtateBufferBounds(const debug_report_data *report_data, IMAGE_STATE *image_state, BUFFER_STATE *buff_state,
298071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                                         uint32_t regionCount, const VkBufferImageCopy *pRegions, const char *func_name,
298171c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                                         UNIQUE_VALIDATION_ERROR_CODE msg_code) {
298271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    bool skip = false;
298371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
298471c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    VkDeviceSize buffer_size = buff_state->createInfo.size;
298571c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
298671c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    for (uint32_t i = 0; i < regionCount; i++) {
298771c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        VkExtent3D copy_extent = pRegions[i].imageExtent;
298871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
298971c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        VkDeviceSize buffer_width = (0 == pRegions[i].bufferRowLength ? copy_extent.width : pRegions[i].bufferRowLength);
299071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        VkDeviceSize buffer_height = (0 == pRegions[i].bufferImageHeight ? copy_extent.height : pRegions[i].bufferImageHeight);
299116769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton        VkDeviceSize unit_size = FormatSize(image_state->createInfo.format);  // size (bytes) of texel or block
299271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
29931dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton        // Handle special buffer packing rules for specific depth/stencil formats
29941dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton        if (pRegions[i].imageSubresource.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) {
299516769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton            unit_size = FormatSize(VK_FORMAT_S8_UINT);
29961dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton        } else if (pRegions[i].imageSubresource.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) {
29971dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton            switch (image_state->createInfo.format) {
29981dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton                case VK_FORMAT_D16_UNORM_S8_UINT:
299916769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton                    unit_size = FormatSize(VK_FORMAT_D16_UNORM);
30001dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton                    break;
30011dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton                case VK_FORMAT_D32_SFLOAT_S8_UINT:
300216769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton                    unit_size = FormatSize(VK_FORMAT_D32_SFLOAT);
30031dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton                    break;
30045971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                case VK_FORMAT_X8_D24_UNORM_PACK32:  // Fall through
30051dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton                case VK_FORMAT_D24_UNORM_S8_UINT:
30061dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton                    unit_size = 4;
30071dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton                    break;
30081dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton                default:
30091dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton                    break;
30101dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton            }
30111dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton        }
30121dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton
301316769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton        if (FormatIsCompressed(image_state->createInfo.format)) {
30145971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            // Switch to texel block units, rounding up for any partially-used blocks
301516769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton            auto block_dim = FormatCompressedTexelBlockExtent(image_state->createInfo.format);
30165971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            buffer_width = (buffer_width + block_dim.width - 1) / block_dim.width;
30175971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            buffer_height = (buffer_height + block_dim.height - 1) / block_dim.height;
301871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
30195971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            copy_extent.width = (copy_extent.width + block_dim.width - 1) / block_dim.width;
30205971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            copy_extent.height = (copy_extent.height + block_dim.height - 1) / block_dim.height;
30215971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            copy_extent.depth = (copy_extent.depth + block_dim.depth - 1) / block_dim.depth;
30225971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        }
302371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
30245971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        // Either depth or layerCount may be greater than 1 (not both). This is the number of 'slices' to copy
30255971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        uint32_t z_copies = std::max(copy_extent.depth, pRegions[i].imageSubresource.layerCount);
30265971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        if (IsExtentSizeZero(&copy_extent) || (0 == z_copies)) {
30275971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            // TODO: Issure warning here? Already warned in ValidateImageBounds()...
30285971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        } else {
30295971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            // Calculate buffer offset of final copied byte, + 1.
30305971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            VkDeviceSize max_buffer_offset = (z_copies - 1) * buffer_height * buffer_width;      // offset to slice
30315971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            max_buffer_offset += ((copy_extent.height - 1) * buffer_width) + copy_extent.width;  // add row,col
30325971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            max_buffer_offset *= unit_size;                                                      // convert to bytes
30335971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            max_buffer_offset += pRegions[i].bufferOffset;                                       // add initial offset (bytes)
303471c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
30355971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            if (buffer_size < max_buffer_offset) {
30365971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                skip |=
30375971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                    log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)0,
30385971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                            __LINE__, msg_code, "IMAGE", "%s: pRegion[%d] exceeds buffer size of %" PRIu64 " bytes. %s.", func_name,
30395971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                            i, buffer_size, validation_error_map[msg_code]);
30405971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            }
304171c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        }
304271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    }
304371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
304471c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    return skip;
304571c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski}
304671c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
304771c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinskibool PreCallValidateCmdCopyImageToBuffer(layer_data *device_data, VkImageLayout srcImageLayout, GLOBAL_CB_NODE *cb_node,
3048940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski                                         IMAGE_STATE *src_image_state, BUFFER_STATE *dst_buffer_state, uint32_t regionCount,
3049877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski                                         const VkBufferImageCopy *pRegions, const char *func_name) {
305071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
305171c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    bool skip = ValidateBufferImageCopyData(report_data, regionCount, pRegions, src_image_state, "vkCmdCopyImageToBuffer");
305271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
305371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    // Validate command buffer state
305471c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    if (CB_RECORDING != cb_node->state) {
305571c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
305671c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                        (uint64_t)cb_node->commandBuffer, __LINE__, VALIDATION_ERROR_01258, "DS",
305771c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                        "Cannot call vkCmdCopyImageToBuffer() on command buffer which is not in recording state. %s.",
305871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                        validation_error_map[VALIDATION_ERROR_01258]);
305971c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    } else {
306071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        skip |= ValidateCmdSubpassState(device_data, cb_node, CMD_COPYIMAGETOBUFFER);
306171c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    }
306271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
306371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    // Command pool must support graphics, compute, or transfer operations
306471c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    auto pPool = GetCommandPoolNode(device_data, cb_node->createInfo.commandPool);
306571c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
306671c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    VkQueueFlags queue_flags = GetPhysDevProperties(device_data)->queue_family_properties[pPool->queueFamilyIndex].queueFlags;
306771c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    if (0 == (queue_flags & (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT))) {
306871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
306971c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                        (uint64_t)cb_node->createInfo.commandPool, __LINE__, VALIDATION_ERROR_01259, "DS",
307071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                        "Cannot call vkCmdCopyImageToBuffer() on a command buffer allocated from a pool without graphics, compute, "
307171c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                        "or transfer capabilities. %s.",
307271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                        validation_error_map[VALIDATION_ERROR_01259]);
307371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    }
30745971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton    skip |= ValidateImageBounds(report_data, src_image_state, regionCount, pRegions, "vkCmdCopyBufferToImage()",
307571c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                                VALIDATION_ERROR_01245);
3076940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    skip |= ValidtateBufferBounds(report_data, src_image_state, dst_buffer_state, regionCount, pRegions, "vkCmdCopyImageToBuffer()",
307771c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                                  VALIDATION_ERROR_01246);
307871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
307971c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    skip |= ValidateImageSampleCount(device_data, src_image_state, VK_SAMPLE_COUNT_1_BIT, "vkCmdCopyImageToBuffer(): srcImage",
308071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                                     VALIDATION_ERROR_01249);
308171c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    skip |= ValidateMemoryIsBoundToImage(device_data, src_image_state, "vkCmdCopyImageToBuffer()", VALIDATION_ERROR_02537);
3082940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    skip |= ValidateMemoryIsBoundToBuffer(device_data, dst_buffer_state, "vkCmdCopyImageToBuffer()", VALIDATION_ERROR_02538);
3083d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski
308471c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    // Validate that SRC image & DST buffer have correct usage flags set
308571c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    skip |= ValidateImageUsageFlags(device_data, src_image_state, VK_IMAGE_USAGE_TRANSFER_SRC_BIT, true, VALIDATION_ERROR_01248,
308671c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                                    "vkCmdCopyImageToBuffer()", "VK_IMAGE_USAGE_TRANSFER_SRC_BIT");
3087940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    skip |= ValidateBufferUsageFlags(device_data, dst_buffer_state, VK_BUFFER_USAGE_TRANSFER_DST_BIT, true, VALIDATION_ERROR_01252,
308871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                                     "vkCmdCopyImageToBuffer()", "VK_BUFFER_USAGE_TRANSFER_DST_BIT");
3089d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski    skip |= insideRenderPass(device_data, cb_node, "vkCmdCopyImageToBuffer()", VALIDATION_ERROR_01260);
30900db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlis    bool hit_error = false;
3091d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski    for (uint32_t i = 0; i < regionCount; ++i) {
30920db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlis        skip |=
30930db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlis            VerifyImageLayout(device_data, cb_node, src_image_state, pRegions[i].imageSubresource, srcImageLayout,
30940db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlis                              VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, "vkCmdCopyImageToBuffer()", VALIDATION_ERROR_01251, &hit_error);
3095d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski        skip |= ValidateCopyBufferImageTransferGranularityRequirements(device_data, cb_node, src_image_state, &pRegions[i], i,
3096fab4fd84d0d187bc73b5bc6709d8ed6370bb7cc3Tobin Ehlis                                                                       "vkCmdCopyImageToBuffer()");
3097d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski    }
3098d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski    return skip;
3099d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski}
3100d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski
3101d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinskivoid PreCallRecordCmdCopyImageToBuffer(layer_data *device_data, GLOBAL_CB_NODE *cb_node, IMAGE_STATE *src_image_state,
3102a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis                                       BUFFER_STATE *dst_buffer_state, uint32_t region_count, const VkBufferImageCopy *regions,
3103a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis                                       VkImageLayout src_image_layout) {
3104a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis    // Make sure that all image slices are updated to correct layout
3105a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis    for (uint32_t i = 0; i < region_count; ++i) {
3106a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis        SetImageLayout(device_data, cb_node, src_image_state, regions[i].imageSubresource, src_image_layout);
3107a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis    }
3108d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski    // Update bindings between buffer/image and cmd buffer
3109d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski    AddCommandBufferBindingImage(device_data, cb_node, src_image_state);
3110940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    AddCommandBufferBindingBuffer(device_data, cb_node, dst_buffer_state);
3111d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski
311271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    std::function<bool()> function = [=]() {
311371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        return ValidateImageMemoryIsValid(device_data, src_image_state, "vkCmdCopyImageToBuffer()");
311471c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    };
311571c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    cb_node->validate_functions.push_back(function);
311671c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    function = [=]() {
3117940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski        SetBufferMemoryValid(device_data, dst_buffer_state, true);
311871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        return false;
311971c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    };
312071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    cb_node->validate_functions.push_back(function);
312171c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
312271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    core_validation::UpdateCmdBufferLastCmd(cb_node, CMD_COPYIMAGETOBUFFER);
3123877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski}
3124877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski
312571c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinskibool PreCallValidateCmdCopyBufferToImage(layer_data *device_data, VkImageLayout dstImageLayout, GLOBAL_CB_NODE *cb_node,
3126940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski                                         BUFFER_STATE *src_buffer_state, IMAGE_STATE *dst_image_state, uint32_t regionCount,
3127877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski                                         const VkBufferImageCopy *pRegions, const char *func_name) {
312871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
312971c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    bool skip = ValidateBufferImageCopyData(report_data, regionCount, pRegions, dst_image_state, "vkCmdCopyBufferToImage");
313071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
313171c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    // Validate command buffer state
313271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    if (CB_RECORDING != cb_node->state) {
313371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
313471c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                        (uint64_t)cb_node->commandBuffer, __LINE__, VALIDATION_ERROR_01240, "DS",
313571c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                        "Cannot call vkCmdCopyBufferToImage() on command buffer which is not in recording state. %s.",
313671c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                        validation_error_map[VALIDATION_ERROR_01240]);
313771c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    } else {
313871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        skip |= ValidateCmdSubpassState(device_data, cb_node, CMD_COPYBUFFERTOIMAGE);
313971c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    }
314071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
314171c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    // Command pool must support graphics, compute, or transfer operations
314271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    auto pPool = GetCommandPoolNode(device_data, cb_node->createInfo.commandPool);
314371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    VkQueueFlags queue_flags = GetPhysDevProperties(device_data)->queue_family_properties[pPool->queueFamilyIndex].queueFlags;
314471c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    if (0 == (queue_flags & (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT))) {
314571c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
314671c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                        (uint64_t)cb_node->createInfo.commandPool, __LINE__, VALIDATION_ERROR_01241, "DS",
314771c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                        "Cannot call vkCmdCopyBufferToImage() on a command buffer allocated from a pool without graphics, compute, "
314871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                        "or transfer capabilities. %s.",
314971c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                        validation_error_map[VALIDATION_ERROR_01241]);
315071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    }
31515971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton    skip |= ValidateImageBounds(report_data, dst_image_state, regionCount, pRegions, "vkCmdCopyBufferToImage()",
315271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                                VALIDATION_ERROR_01228);
3153940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    skip |= ValidtateBufferBounds(report_data, dst_image_state, src_buffer_state, regionCount, pRegions, "vkCmdCopyBufferToImage()",
315471c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                                  VALIDATION_ERROR_01227);
315571c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    skip |= ValidateImageSampleCount(device_data, dst_image_state, VK_SAMPLE_COUNT_1_BIT, "vkCmdCopyBufferToImage(): dstImage",
315671c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                                     VALIDATION_ERROR_01232);
3157940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    skip |= ValidateMemoryIsBoundToBuffer(device_data, src_buffer_state, "vkCmdCopyBufferToImage()", VALIDATION_ERROR_02535);
315871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    skip |= ValidateMemoryIsBoundToImage(device_data, dst_image_state, "vkCmdCopyBufferToImage()", VALIDATION_ERROR_02536);
3159940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    skip |= ValidateBufferUsageFlags(device_data, src_buffer_state, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, true, VALIDATION_ERROR_01230,
316071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                                     "vkCmdCopyBufferToImage()", "VK_BUFFER_USAGE_TRANSFER_SRC_BIT");
316171c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    skip |= ValidateImageUsageFlags(device_data, dst_image_state, VK_IMAGE_USAGE_TRANSFER_DST_BIT, true, VALIDATION_ERROR_01231,
316271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                                    "vkCmdCopyBufferToImage()", "VK_IMAGE_USAGE_TRANSFER_DST_BIT");
3163d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski    skip |= insideRenderPass(device_data, cb_node, "vkCmdCopyBufferToImage()", VALIDATION_ERROR_01242);
31640db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlis    bool hit_error = false;
3165d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski    for (uint32_t i = 0; i < regionCount; ++i) {
31660db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlis        skip |=
31670db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlis            VerifyImageLayout(device_data, cb_node, dst_image_state, pRegions[i].imageSubresource, dstImageLayout,
31680db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlis                              VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, "vkCmdCopyBufferToImage()", VALIDATION_ERROR_01234, &hit_error);
3169d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski        skip |= ValidateCopyBufferImageTransferGranularityRequirements(device_data, cb_node, dst_image_state, &pRegions[i], i,
3170d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski                                                                       "vkCmdCopyBufferToImage()");
3171d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski    }
3172d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski    return skip;
3173d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski}
3174d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski
3175940f70f1340803d185c67633b05ef048d277952eMark Lobodzinskivoid PreCallRecordCmdCopyBufferToImage(layer_data *device_data, GLOBAL_CB_NODE *cb_node, BUFFER_STATE *src_buffer_state,
3176a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis                                       IMAGE_STATE *dst_image_state, uint32_t region_count, const VkBufferImageCopy *regions,
3177a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis                                       VkImageLayout dst_image_layout) {
3178a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis    // Make sure that all image slices are updated to correct layout
3179a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis    for (uint32_t i = 0; i < region_count; ++i) {
3180a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis        SetImageLayout(device_data, cb_node, dst_image_state, regions[i].imageSubresource, dst_image_layout);
3181a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis    }
3182940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    AddCommandBufferBindingBuffer(device_data, cb_node, src_buffer_state);
3183d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski    AddCommandBufferBindingImage(device_data, cb_node, dst_image_state);
318471c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    std::function<bool()> function = [=]() {
318571c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        SetImageMemoryValid(device_data, dst_image_state, true);
318671c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        return false;
318771c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    };
318871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    cb_node->validate_functions.push_back(function);
3189940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    function = [=]() { return ValidateBufferMemoryIsValid(device_data, src_buffer_state, "vkCmdCopyBufferToImage()"); };
319071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    cb_node->validate_functions.push_back(function);
319171c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
319271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    core_validation::UpdateCmdBufferLastCmd(cb_node, CMD_COPYBUFFERTOIMAGE);
3193877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski}
3194e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen
3195e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblenbool PreCallValidateGetImageSubresourceLayout(layer_data *device_data, VkImage image, const VkImageSubresource *pSubresource) {
3196e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    const auto report_data = core_validation::GetReportData(device_data);
3197e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    bool skip = false;
3198e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    const VkImageAspectFlags sub_aspect = pSubresource->aspectMask;
3199e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen
3200e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    // VU 00733: The aspectMask member of pSubresource must only have a single bit set
3201e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    const int num_bits = sizeof(sub_aspect) * CHAR_BIT;
3202e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    std::bitset<num_bits> aspect_mask_bits(sub_aspect);
3203e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    if (aspect_mask_bits.count() != 1) {
3204fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
3205fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                        reinterpret_cast<uint64_t &>(image), __LINE__, VALIDATION_ERROR_00733, "IMAGE",
3206e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen                        "vkGetImageSubresourceLayout(): VkImageSubresource.aspectMask must have exactly 1 bit set. %s",
3207e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen                        validation_error_map[VALIDATION_ERROR_00733]);
3208e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    }
3209e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen
3210e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    IMAGE_STATE *image_entry = GetImageState(device_data, image);
3211e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    if (!image_entry) {
3212e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen        return skip;
3213e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    }
3214e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen
3215e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    // VU 00732: image must have been created with tiling equal to VK_IMAGE_TILING_LINEAR
3216e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    if (image_entry->createInfo.tiling != VK_IMAGE_TILING_LINEAR) {
3217fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
3218fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                        reinterpret_cast<uint64_t &>(image), __LINE__, VALIDATION_ERROR_00732, "IMAGE",
3219e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen                        "vkGetImageSubresourceLayout(): Image must have tiling of VK_IMAGE_TILING_LINEAR. %s",
3220e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen                        validation_error_map[VALIDATION_ERROR_00732]);
3221e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    }
3222e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen
3223e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    // VU 00739: mipLevel must be less than the mipLevels specified in VkImageCreateInfo when the image was created
3224e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    if (pSubresource->mipLevel >= image_entry->createInfo.mipLevels) {
3225fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
3226fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                        reinterpret_cast<uint64_t &>(image), __LINE__, VALIDATION_ERROR_00739, "IMAGE",
3227e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen                        "vkGetImageSubresourceLayout(): pSubresource.mipLevel (%d) must be less than %d. %s",
3228e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen                        pSubresource->mipLevel, image_entry->createInfo.mipLevels, validation_error_map[VALIDATION_ERROR_00739]);
3229e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    }
3230e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen
3231e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    // VU 00740: arrayLayer must be less than the arrayLayers specified in VkImageCreateInfo when the image was created
3232e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    if (pSubresource->arrayLayer >= image_entry->createInfo.arrayLayers) {
3233fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski        skip |=
3234fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski            log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
3235fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                    reinterpret_cast<uint64_t &>(image), __LINE__, VALIDATION_ERROR_00740, "IMAGE",
3236fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                    "vkGetImageSubresourceLayout(): pSubresource.arrayLayer (%d) must be less than %d. %s",
3237fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                    pSubresource->arrayLayer, image_entry->createInfo.arrayLayers, validation_error_map[VALIDATION_ERROR_00740]);
3238e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    }
3239e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen
3240e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    // VU 00741: subresource's aspect must be compatible with image's format.
3241e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    const VkFormat img_format = image_entry->createInfo.format;
324216769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton    if (FormatIsColor(img_format)) {
3243e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen        if (sub_aspect != VK_IMAGE_ASPECT_COLOR_BIT) {
3244e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen            skip |= log_msg(
3245fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
3246fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                reinterpret_cast<uint64_t &>(image), __LINE__, VALIDATION_ERROR_00741, "IMAGE",
3247e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen                "vkGetImageSubresourceLayout(): For color formats, VkImageSubresource.aspectMask must be VK_IMAGE_ASPECT_COLOR. %s",
3248e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen                validation_error_map[VALIDATION_ERROR_00741]);
3249e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen        }
325016769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton    } else if (FormatIsDepthOrStencil(img_format)) {
3251e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen        if ((sub_aspect != VK_IMAGE_ASPECT_DEPTH_BIT) && (sub_aspect != VK_IMAGE_ASPECT_STENCIL_BIT)) {
3252fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
3253fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski                            reinterpret_cast<uint64_t &>(image), __LINE__, VALIDATION_ERROR_00741, "IMAGE",
3254e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen                            "vkGetImageSubresourceLayout(): For depth/stencil formats, VkImageSubresource.aspectMask must be "
3255e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen                            "either VK_IMAGE_ASPECT_DEPTH_BIT or VK_IMAGE_ASPECT_STENCIL_BIT. %s",
3256e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen                            validation_error_map[VALIDATION_ERROR_00741]);
3257e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen        }
3258e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    }
3259e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    return skip;
3260e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen}
3261