buffer_validation.cpp revision a90f5fa414aa0994e67cdb911938e6ae48f2ad6a
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>
19584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski */
20584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski
21584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski// Allow use of STL min and max functions in Windows
22584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski#define NOMINMAX
23584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski
248dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski#include <sstream>
258dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
268dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski#include "vk_enum_string_helper.h"
278dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski#include "vk_layer_data.h"
288dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski#include "vk_layer_utils.h"
298dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski#include "vk_layer_logging.h"
308dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
31584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski#include "buffer_validation.h"
32c06c9b88f5f5bcc7033ba41d5547b048fa6015a4Mark Lobodzinski
33e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisvoid SetLayout(layer_data *device_data, GLOBAL_CB_NODE *pCB, ImageSubresourcePair imgpair, const VkImageLayout &layout) {
3455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    if (std::find(pCB->imageSubresourceMap[imgpair.image].begin(), pCB->imageSubresourceMap[imgpair.image].end(), imgpair) !=
3555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        pCB->imageSubresourceMap[imgpair.image].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
70e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisbool FindLayoutVerifyNode(layer_data *device_data, GLOBAL_CB_NODE *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
102e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisbool FindLayoutVerifyLayout(layer_data *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
126e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisbool FindCmdBufLayout(layer_data *device_data, GLOBAL_CB_NODE *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    auto subresource =
22555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        std::find(pCB->imageSubresourceMap[imgpair.image].begin(), pCB->imageSubresourceMap[imgpair.image].end(), imgpair);
22655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    if (subresource == pCB->imageSubresourceMap[imgpair.image].end()) {
22755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        pCB->imageSubresourceMap[imgpair.image].push_back(imgpair);
22855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    }
22955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski}
23055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski
231e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisvoid SetImageViewLayout(layer_data *device_data, GLOBAL_CB_NODE *pCB, VkImageView imageView, const VkImageLayout &layout) {
2329a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto view_state = GetImageViewState(device_data, imageView);
23355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    assert(view_state);
23455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    auto image = view_state->create_info.image;
23555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    const VkImageSubresourceRange &subRange = view_state->create_info.subresourceRange;
23655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    // TODO: Do not iterate over every possibility - consolidate where possible
23755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    for (uint32_t j = 0; j < subRange.levelCount; j++) {
23855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        uint32_t level = subRange.baseMipLevel + j;
23955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        for (uint32_t k = 0; k < subRange.layerCount; k++) {
24055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski            uint32_t layer = subRange.baseArrayLayer + k;
24155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski            VkImageSubresource sub = {subRange.aspectMask, level, layer};
24255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski            // TODO: If ImageView was created with depth or stencil, transition both layouts as the aspectMask is ignored and both
24355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski            // are used. Verify that the extra implicit layout is OK for descriptor set layout validation
24455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski            if (subRange.aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
24555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                if (vk_format_is_depth_and_stencil(view_state->create_info.format)) {
24655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                    sub.aspectMask |= (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);
24755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                }
24855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski            }
24955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski            SetLayout(device_data, pCB, image, sub, layout);
25055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        }
25155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    }
25255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski}
25355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski
254e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisbool VerifyFramebufferAndRenderPassLayouts(layer_data *device_data, GLOBAL_CB_NODE *pCB,
25555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                                           const VkRenderPassBeginInfo *pRenderPassBegin,
25655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                                           const FRAMEBUFFER_STATE *framebuffer_state) {
25755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    bool skip_call = false;
2589a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto const pRenderPassInfo = GetRenderPassState(device_data, pRenderPassBegin->renderPass)->createInfo.ptr();
25955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    auto const &framebufferInfo = framebuffer_state->createInfo;
26055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    const auto report_data = core_validation::GetReportData(device_data);
26155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    if (pRenderPassInfo->attachmentCount != framebufferInfo.attachmentCount) {
26255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
26355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                             DRAWSTATE_INVALID_RENDERPASS, "DS",
26455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                             "You cannot start a render pass using a framebuffer "
26555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                             "with a different number of attachments.");
26655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    }
26755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    for (uint32_t i = 0; i < pRenderPassInfo->attachmentCount; ++i) {
26855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        const VkImageView &image_view = framebufferInfo.pAttachments[i];
2699a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto view_state = GetImageViewState(device_data, image_view);
27055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        assert(view_state);
27155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        const VkImage &image = view_state->create_info.image;
27255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        const VkImageSubresourceRange &subRange = view_state->create_info.subresourceRange;
27355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        IMAGE_CMD_BUF_LAYOUT_NODE newNode = {pRenderPassInfo->pAttachments[i].initialLayout,
27455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                                             pRenderPassInfo->pAttachments[i].initialLayout};
27555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        // TODO: Do not iterate over every possibility - consolidate where possible
2768295afad70eaa90492f309a07517401f072ffca7Tobin Ehlis        // TODO: Consolidate this with SetImageViewLayout() function above
27755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        for (uint32_t j = 0; j < subRange.levelCount; j++) {
27855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski            uint32_t level = subRange.baseMipLevel + j;
27955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski            for (uint32_t k = 0; k < subRange.layerCount; k++) {
28055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                uint32_t layer = subRange.baseArrayLayer + k;
28155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                VkImageSubresource sub = {subRange.aspectMask, level, layer};
28255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                IMAGE_CMD_BUF_LAYOUT_NODE node;
28355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                if (!FindCmdBufLayout(device_data, pCB, image, sub, node)) {
2848295afad70eaa90492f309a07517401f072ffca7Tobin Ehlis                    // If ImageView was created with depth or stencil, transition both aspects if it's a DS image
2858295afad70eaa90492f309a07517401f072ffca7Tobin Ehlis                    if (subRange.aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
2868295afad70eaa90492f309a07517401f072ffca7Tobin Ehlis                        if (vk_format_is_depth_and_stencil(view_state->create_info.format)) {
2878295afad70eaa90492f309a07517401f072ffca7Tobin Ehlis                            sub.aspectMask |= (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);
2888295afad70eaa90492f309a07517401f072ffca7Tobin Ehlis                        }
2898295afad70eaa90492f309a07517401f072ffca7Tobin Ehlis                    }
29055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                    SetLayout(device_data, pCB, image, sub, newNode);
29155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                    continue;
29255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                }
29355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                if (newNode.layout != VK_IMAGE_LAYOUT_UNDEFINED && newNode.layout != node.layout) {
29455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                    skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
29555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                                         DRAWSTATE_INVALID_RENDERPASS, "DS",
29655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                                         "You cannot start a render pass using attachment %u "
29755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                                         "where the render pass initial layout is %s and the previous "
29855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                                         "known layout of the attachment is %s. The layouts must match, or "
29955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                                         "the render pass initial layout for the attachment must be "
30055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                                         "VK_IMAGE_LAYOUT_UNDEFINED",
30155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                                         i, string_VkImageLayout(newNode.layout), string_VkImageLayout(node.layout));
30255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                }
30355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski            }
30455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        }
30555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    }
30655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    return skip_call;
30755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski}
30855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski
309e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisvoid TransitionAttachmentRefLayout(layer_data *device_data, GLOBAL_CB_NODE *pCB, FRAMEBUFFER_STATE *pFramebuffer,
31055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                                   VkAttachmentReference ref) {
31155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    if (ref.attachment != VK_ATTACHMENT_UNUSED) {
31255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        auto image_view = pFramebuffer->createInfo.pAttachments[ref.attachment];
31355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        SetImageViewLayout(device_data, pCB, image_view, ref.layout);
31455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    }
31555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski}
31655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski
317e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisvoid TransitionSubpassLayouts(layer_data *device_data, GLOBAL_CB_NODE *pCB, const VkRenderPassBeginInfo *pRenderPassBegin,
318e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlis                              const int subpass_index, FRAMEBUFFER_STATE *framebuffer_state) {
3199a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto renderPass = GetRenderPassState(device_data, pRenderPassBegin->renderPass);
32055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    if (!renderPass) return;
32155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski
32255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    if (framebuffer_state) {
32355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        auto const &subpass = renderPass->createInfo.pSubpasses[subpass_index];
32455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) {
32555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski            TransitionAttachmentRefLayout(device_data, pCB, framebuffer_state, subpass.pInputAttachments[j]);
32655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        }
32755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) {
32855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski            TransitionAttachmentRefLayout(device_data, pCB, framebuffer_state, subpass.pColorAttachments[j]);
32955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        }
33055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        if (subpass.pDepthStencilAttachment) {
33155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski            TransitionAttachmentRefLayout(device_data, pCB, framebuffer_state, *subpass.pDepthStencilAttachment);
33255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        }
33355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    }
33455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski}
33555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski
336e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinskibool ValidateImageAspectLayout(layer_data *device_data, GLOBAL_CB_NODE *pCB, const VkImageMemoryBarrier *mem_barrier,
337e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski                               uint32_t level, uint32_t layer, VkImageAspectFlags aspect) {
33855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    if (!(mem_barrier->subresourceRange.aspectMask & aspect)) {
33955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        return false;
34055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    }
34155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    VkImageSubresource sub = {aspect, level, layer};
34255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    IMAGE_CMD_BUF_LAYOUT_NODE node;
34355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    if (!FindCmdBufLayout(device_data, pCB, mem_barrier->image, sub, node)) {
34455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        return false;
34555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    }
34655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    bool skip = false;
34755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    if (mem_barrier->oldLayout == VK_IMAGE_LAYOUT_UNDEFINED) {
34855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        // TODO: Set memory invalid which is in mem_tracker currently
34955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    } else if (node.layout != mem_barrier->oldLayout) {
35055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        skip |= log_msg(core_validation::GetReportData(device_data), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0,
35155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                        0, __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
35255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                        "You cannot transition the layout of aspect %d from %s when current layout is %s.", aspect,
35355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                        string_VkImageLayout(mem_barrier->oldLayout), string_VkImageLayout(node.layout));
35455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    }
35555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    return skip;
35655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski}
35755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski
358e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinskivoid TransitionImageAspectLayout(layer_data *device_data, GLOBAL_CB_NODE *pCB, const VkImageMemoryBarrier *mem_barrier,
359e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski                                 uint32_t level, uint32_t layer, VkImageAspectFlags aspect) {
360e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski    if (!(mem_barrier->subresourceRange.aspectMask & aspect)) {
361e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski        return;
362e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski    }
363e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski    VkImageSubresource sub = {aspect, level, layer};
364e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski    IMAGE_CMD_BUF_LAYOUT_NODE node;
365e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski    if (!FindCmdBufLayout(device_data, pCB, mem_barrier->image, sub, node)) {
366e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski        SetLayout(device_data, pCB, mem_barrier->image, sub,
367e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski                  IMAGE_CMD_BUF_LAYOUT_NODE(mem_barrier->oldLayout, mem_barrier->newLayout));
368e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski        return;
369e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski    }
370e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski    if (mem_barrier->oldLayout == VK_IMAGE_LAYOUT_UNDEFINED) {
371e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski        // TODO: Set memory invalid
372e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski    }
373e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski    SetLayout(device_data, pCB, mem_barrier->image, sub, mem_barrier->newLayout);
374e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski}
375e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski
376a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen// Verify an ImageMemoryBarrier's old/new ImageLayouts are compatible with the Image's ImageUsageFlags.
377a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblenbool ValidateBarrierLayoutToImageUsage(layer_data *device_data, const VkImageMemoryBarrier *img_barrier, bool new_not_old,
378a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen                                       VkImageUsageFlags usage_flags, const char *func_name) {
379a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen    const auto report_data = core_validation::GetReportData(device_data);
380a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen    bool skip = false;
381a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen    const VkImageLayout layout = (new_not_old) ? img_barrier->newLayout : img_barrier->oldLayout;
382a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen    UNIQUE_VALIDATION_ERROR_CODE msg_code = VALIDATION_ERROR_UNDEFINED;  // sentinel value meaning "no error"
383a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen
384a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen    switch (layout) {
385a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen        case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
386a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen            if ((usage_flags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) == 0) {
387a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen                msg_code = VALIDATION_ERROR_00303;
388a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen            }
389a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen            break;
390a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen        case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
391a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen            if ((usage_flags & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) == 0) {
392a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen                msg_code = VALIDATION_ERROR_00304;
393a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen            }
394a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen            break;
395a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen        case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
396a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen            if ((usage_flags & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) == 0) {
397a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen                msg_code = VALIDATION_ERROR_00305;
398a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen            }
399a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen            break;
400a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen        case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
401a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen            if ((usage_flags & (VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) == 0) {
402a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen                msg_code = VALIDATION_ERROR_00306;
403a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen            }
404a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen            break;
405a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen        case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
406a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen            if ((usage_flags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) == 0) {
407a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen                msg_code = VALIDATION_ERROR_00307;
408a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen            }
409a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen            break;
410a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen        case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
411a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen            if ((usage_flags & VK_IMAGE_USAGE_TRANSFER_DST_BIT) == 0) {
412a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen                msg_code = VALIDATION_ERROR_00308;
413a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen            }
414a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen            break;
415a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen        default:
416a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen            // Other VkImageLayout values do not have VUs defined in this context.
417a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen            break;
418a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen    }
419a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen
420a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen    if (msg_code != VALIDATION_ERROR_UNDEFINED) {
421a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, msg_code,
422a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen                        "DS", "%s: Image barrier 0x%p %sLayout=%s is not compatible with image 0x%" PRIx64 " usage flags 0x%" PRIx32
423a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen                              ". %s",
424a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen                        func_name, img_barrier, ((new_not_old) ? "new" : "old"), string_VkImageLayout(layout),
425a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen                        (uint64_t)(img_barrier->image), usage_flags, validation_error_map[msg_code]);
426a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen    }
427a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen    return skip;
428a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen}
429a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen
430a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen// Verify image barriers are compatible with the images they reference.
431a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblenbool ValidateBarriersToImages(layer_data *device_data, VkCommandBuffer cmdBuffer, uint32_t imageMemoryBarrierCount,
432a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen                              const VkImageMemoryBarrier *pImageMemoryBarriers, const char *func_name) {
4339a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    GLOBAL_CB_NODE *pCB = GetCBNode(device_data, cmdBuffer);
43455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    bool skip = false;
435a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen    uint32_t level_count = 0;
436a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen    uint32_t layer_count = 0;
437a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen
438a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen    for (uint32_t i = 0; i < imageMemoryBarrierCount; ++i) {
439a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen        auto img_barrier = &pImageMemoryBarriers[i];
440a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen        if (!img_barrier) continue;
44155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski
44255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        // TODO: Do not iterate over every possibility - consolidate where possible
443a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen        ResolveRemainingLevelsLayers(device_data, &level_count, &layer_count, img_barrier->subresourceRange,
444a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen                                     GetImageState(device_data, img_barrier->image));
445a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen
446a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen        for (uint32_t j = 0; j < level_count; j++) {
447a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen            uint32_t level = img_barrier->subresourceRange.baseMipLevel + j;
448a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen            for (uint32_t k = 0; k < layer_count; k++) {
449a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen                uint32_t layer = img_barrier->subresourceRange.baseArrayLayer + k;
450a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen                skip |= ValidateImageAspectLayout(device_data, pCB, img_barrier, level, layer, VK_IMAGE_ASPECT_COLOR_BIT);
451a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen                skip |= ValidateImageAspectLayout(device_data, pCB, img_barrier, level, layer, VK_IMAGE_ASPECT_DEPTH_BIT);
452a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen                skip |= ValidateImageAspectLayout(device_data, pCB, img_barrier, level, layer, VK_IMAGE_ASPECT_STENCIL_BIT);
453a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen                skip |= ValidateImageAspectLayout(device_data, pCB, img_barrier, level, layer, VK_IMAGE_ASPECT_METADATA_BIT);
45455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski            }
45555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        }
456a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen
457a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen        IMAGE_STATE *image_state = GetImageState(device_data, img_barrier->image);
458a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen        if (image_state) {
459a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen            VkImageUsageFlags usage_flags = image_state->createInfo.usage;
460a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen            skip |= ValidateBarrierLayoutToImageUsage(device_data, img_barrier, false, usage_flags, func_name);
461a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen            skip |= ValidateBarrierLayoutToImageUsage(device_data, img_barrier, true, usage_flags, func_name);
462a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen        }
46355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    }
46455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    return skip;
46555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski}
46655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski
467e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinskivoid TransitionImageLayouts(layer_data *device_data, VkCommandBuffer cmdBuffer, uint32_t memBarrierCount,
468e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski                            const VkImageMemoryBarrier *pImgMemBarriers) {
469e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski    GLOBAL_CB_NODE *pCB = GetCBNode(device_data, cmdBuffer);
470e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski    uint32_t levelCount = 0;
471e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski    uint32_t layerCount = 0;
472e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski
473e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski    for (uint32_t i = 0; i < memBarrierCount; ++i) {
474e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski        auto mem_barrier = &pImgMemBarriers[i];
475e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski        if (!mem_barrier) continue;
476e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski        // TODO: Do not iterate over every possibility - consolidate where possible
477e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski        ResolveRemainingLevelsLayers(device_data, &levelCount, &layerCount, mem_barrier->subresourceRange,
478e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski                                     GetImageState(device_data, mem_barrier->image));
479e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski
480e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski        for (uint32_t j = 0; j < levelCount; j++) {
481e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski            uint32_t level = mem_barrier->subresourceRange.baseMipLevel + j;
482e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski            for (uint32_t k = 0; k < layerCount; k++) {
483e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski                uint32_t layer = mem_barrier->subresourceRange.baseArrayLayer + k;
484e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski                TransitionImageAspectLayout(device_data, pCB, mem_barrier, level, layer, VK_IMAGE_ASPECT_COLOR_BIT);
485e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski                TransitionImageAspectLayout(device_data, pCB, mem_barrier, level, layer, VK_IMAGE_ASPECT_DEPTH_BIT);
486e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski                TransitionImageAspectLayout(device_data, pCB, mem_barrier, level, layer, VK_IMAGE_ASPECT_STENCIL_BIT);
487e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski                TransitionImageAspectLayout(device_data, pCB, mem_barrier, level, layer, VK_IMAGE_ASPECT_METADATA_BIT);
488e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski            }
489e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski        }
490e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski    }
491e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski}
492e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski
493e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisbool VerifySourceImageLayout(layer_data *device_data, GLOBAL_CB_NODE *cb_node, VkImage srcImage, VkImageSubresourceLayers subLayers,
494e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlis                             VkImageLayout srcImageLayout, UNIQUE_VALIDATION_ERROR_CODE msgCode) {
49555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    const auto report_data = core_validation::GetReportData(device_data);
49655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    bool skip_call = false;
49755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski
49855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    for (uint32_t i = 0; i < subLayers.layerCount; ++i) {
49955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        uint32_t layer = i + subLayers.baseArrayLayer;
50055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        VkImageSubresource sub = {subLayers.aspectMask, subLayers.mipLevel, layer};
50155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        IMAGE_CMD_BUF_LAYOUT_NODE node;
50255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        if (!FindCmdBufLayout(device_data, cb_node, srcImage, sub, node)) {
50355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski            SetLayout(device_data, cb_node, srcImage, sub, IMAGE_CMD_BUF_LAYOUT_NODE(srcImageLayout, srcImageLayout));
50455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski            continue;
50555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        }
50655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        if (node.layout != srcImageLayout) {
50755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski            // TODO: Improve log message in the next pass
50855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski            skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0,
50955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                                 __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
51055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                                 "Cannot copy from an image whose source layout is %s "
51155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                                 "and doesn't match the current layout %s.",
51255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                                 string_VkImageLayout(srcImageLayout), string_VkImageLayout(node.layout));
51355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        }
51455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    }
51555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    if (srcImageLayout != VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL) {
51655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        if (srcImageLayout == VK_IMAGE_LAYOUT_GENERAL) {
51755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski            // TODO : Can we deal with image node from the top of call tree and avoid map look-up here?
5189a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            auto image_state = GetImageState(device_data, srcImage);
51955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski            if (image_state->createInfo.tiling != VK_IMAGE_TILING_LINEAR) {
52055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                // LAYOUT_GENERAL is allowed, but may not be performance optimal, flag as perf warning.
52155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                skip_call |= log_msg(report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0,
52255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                                     __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
52355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                                     "Layout for input image should be TRANSFER_SRC_OPTIMAL instead of GENERAL.");
52455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski            }
52555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        } else {
52655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski            skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, msgCode,
52755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                                 "DS", "Layout for input image is %s but can only be TRANSFER_SRC_OPTIMAL or GENERAL. %s",
52855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                                 string_VkImageLayout(srcImageLayout), validation_error_map[msgCode]);
52955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        }
53055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    }
53155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    return skip_call;
53255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski}
53355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski
534e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisbool VerifyDestImageLayout(layer_data *device_data, GLOBAL_CB_NODE *cb_node, VkImage destImage, VkImageSubresourceLayers subLayers,
535e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlis                           VkImageLayout destImageLayout, UNIQUE_VALIDATION_ERROR_CODE msgCode) {
53655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    const auto report_data = core_validation::GetReportData(device_data);
53755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    bool skip_call = false;
53855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski
53955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    for (uint32_t i = 0; i < subLayers.layerCount; ++i) {
54055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        uint32_t layer = i + subLayers.baseArrayLayer;
54155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        VkImageSubresource sub = {subLayers.aspectMask, subLayers.mipLevel, layer};
54255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        IMAGE_CMD_BUF_LAYOUT_NODE node;
54355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        if (!FindCmdBufLayout(device_data, cb_node, destImage, sub, node)) {
54455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski            SetLayout(device_data, cb_node, destImage, sub, IMAGE_CMD_BUF_LAYOUT_NODE(destImageLayout, destImageLayout));
54555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski            continue;
54655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        }
54755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        if (node.layout != destImageLayout) {
54855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski            skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0,
54955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                                 __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
55055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                                 "Cannot copy from an image whose dest layout is %s and "
55155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                                 "doesn't match the current layout %s.",
55255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                                 string_VkImageLayout(destImageLayout), string_VkImageLayout(node.layout));
55355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        }
55455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    }
55555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    if (destImageLayout != VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
55655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        if (destImageLayout == VK_IMAGE_LAYOUT_GENERAL) {
5579a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            auto image_state = GetImageState(device_data, destImage);
55855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski            if (image_state->createInfo.tiling != VK_IMAGE_TILING_LINEAR) {
55955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                // LAYOUT_GENERAL is allowed, but may not be performance optimal, flag as perf warning.
56055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                skip_call |= log_msg(report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0,
56155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                                     __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
56255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                                     "Layout for output image should be TRANSFER_DST_OPTIMAL instead of GENERAL.");
56355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski            }
56455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        } else {
56555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski            skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, msgCode,
56655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                                 "DS", "Layout for output image is %s but can only be TRANSFER_DST_OPTIMAL or GENERAL. %s",
56755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                                 string_VkImageLayout(destImageLayout), validation_error_map[msgCode]);
56855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        }
56955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    }
57055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    return skip_call;
57155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski}
57255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski
573e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisvoid TransitionFinalSubpassLayouts(layer_data *device_data, GLOBAL_CB_NODE *pCB, const VkRenderPassBeginInfo *pRenderPassBegin,
574e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlis                                   FRAMEBUFFER_STATE *framebuffer_state) {
5759a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto renderPass = GetRenderPassState(device_data, pRenderPassBegin->renderPass);
57655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    if (!renderPass) return;
57755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski
57855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    const VkRenderPassCreateInfo *pRenderPassInfo = renderPass->createInfo.ptr();
57955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    if (framebuffer_state) {
58055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        for (uint32_t i = 0; i < pRenderPassInfo->attachmentCount; ++i) {
58155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski            auto image_view = framebuffer_state->createInfo.pAttachments[i];
58255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski            SetImageViewLayout(device_data, pCB, image_view, pRenderPassInfo->pAttachments[i].finalLayout);
58355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        }
58455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    }
58555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski}
58655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski
587e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisbool PreCallValidateCreateImage(layer_data *device_data, const VkImageCreateInfo *pCreateInfo,
5888dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                                const VkAllocationCallbacks *pAllocator, VkImage *pImage) {
5898dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    bool skip_call = false;
5908dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
5918dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
5928dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    if (pCreateInfo->format != VK_FORMAT_UNDEFINED) {
593d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski        const VkFormatProperties *properties = GetFormatProperties(device_data, pCreateInfo->format);
5948dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
595d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski        if ((pCreateInfo->tiling == VK_IMAGE_TILING_LINEAR) && (properties->linearTilingFeatures == 0)) {
5968dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski            std::stringstream ss;
5978dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski            ss << "vkCreateImage format parameter (" << string_VkFormat(pCreateInfo->format) << ") is an unsupported format";
5988dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski            skip_call |=
5998dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
6008dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                        VALIDATION_ERROR_02150, "IMAGE", "%s. %s", ss.str().c_str(), validation_error_map[VALIDATION_ERROR_02150]);
6018dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski        }
6028dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
603d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski        if ((pCreateInfo->tiling == VK_IMAGE_TILING_OPTIMAL) && (properties->optimalTilingFeatures == 0)) {
6048dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski            std::stringstream ss;
6058dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski            ss << "vkCreateImage format parameter (" << string_VkFormat(pCreateInfo->format) << ") is an unsupported format";
6068dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski            skip_call |=
6078dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
6088dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                        VALIDATION_ERROR_02155, "IMAGE", "%s. %s", ss.str().c_str(), validation_error_map[VALIDATION_ERROR_02155]);
6098dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski        }
6108dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
6118dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski        // Validate that format supports usage as color attachment
6128dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski        if (pCreateInfo->usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {
6138dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski            if ((pCreateInfo->tiling == VK_IMAGE_TILING_OPTIMAL) &&
614d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski                ((properties->optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) == 0)) {
6158dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                std::stringstream ss;
6168dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                ss << "vkCreateImage: VkFormat for TILING_OPTIMAL image (" << string_VkFormat(pCreateInfo->format)
6178dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                   << ") does not support requested Image usage type VK_IMAGE_USAGE_COLOR_ATTACHMENT";
6188dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
6198dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                                     __LINE__, VALIDATION_ERROR_02158, "IMAGE", "%s. %s", ss.str().c_str(),
6208dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                                     validation_error_map[VALIDATION_ERROR_02158]);
6218dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski            }
6228dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski            if ((pCreateInfo->tiling == VK_IMAGE_TILING_LINEAR) &&
623d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski                ((properties->linearTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) == 0)) {
6248dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                std::stringstream ss;
6258dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                ss << "vkCreateImage: VkFormat for TILING_LINEAR image (" << string_VkFormat(pCreateInfo->format)
6268dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                   << ") does not support requested Image usage type VK_IMAGE_USAGE_COLOR_ATTACHMENT";
6278dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
6288dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                                     __LINE__, VALIDATION_ERROR_02153, "IMAGE", "%s. %s", ss.str().c_str(),
6298dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                                     validation_error_map[VALIDATION_ERROR_02153]);
6308dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski            }
6318dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski        }
6328dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski        // Validate that format supports usage as depth/stencil attachment
6338dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski        if (pCreateInfo->usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
6348dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski            if ((pCreateInfo->tiling == VK_IMAGE_TILING_OPTIMAL) &&
635d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski                ((properties->optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) == 0)) {
6368dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                std::stringstream ss;
6378dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                ss << "vkCreateImage: VkFormat for TILING_OPTIMAL image (" << string_VkFormat(pCreateInfo->format)
6388dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                   << ") does not support requested Image usage type VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT";
6398dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
6408dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                                     __LINE__, VALIDATION_ERROR_02159, "IMAGE", "%s. %s", ss.str().c_str(),
6418dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                                     validation_error_map[VALIDATION_ERROR_02159]);
6428dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski            }
6438dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski            if ((pCreateInfo->tiling == VK_IMAGE_TILING_LINEAR) &&
644d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski                ((properties->linearTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) == 0)) {
6458dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                std::stringstream ss;
6468dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                ss << "vkCreateImage: VkFormat for TILING_LINEAR image (" << string_VkFormat(pCreateInfo->format)
6478dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                   << ") does not support requested Image usage type VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT";
6488dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
6498dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                                     __LINE__, VALIDATION_ERROR_02154, "IMAGE", "%s. %s", ss.str().c_str(),
6508dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                                     validation_error_map[VALIDATION_ERROR_02154]);
6518dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski            }
6528dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski        }
6538dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    } else {
6548dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski        skip_call |=
6558dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski            log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
6568dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                    VALIDATION_ERROR_00715, "IMAGE", "vkCreateImage: VkFormat for image must not be VK_FORMAT_UNDEFINED. %s",
6578dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                    validation_error_map[VALIDATION_ERROR_00715]);
6588dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    }
6598dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
660d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski    const VkImageFormatProperties *ImageFormatProperties = GetImageFormatProperties(
661d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski        device_data, pCreateInfo->format, pCreateInfo->imageType, pCreateInfo->tiling, pCreateInfo->usage, pCreateInfo->flags);
6628dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
663d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski    VkDeviceSize imageGranularity = GetPhysicalDeviceProperties(device_data)->limits.bufferImageGranularity;
6648dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    imageGranularity = imageGranularity == 1 ? 0 : imageGranularity;
6658dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
666a9991b9f53d0be4fecc63bdbdf3de9950070a3a5Mark Lobodzinski    if ((pCreateInfo->extent.width <= 0) || (pCreateInfo->extent.height <= 0) || (pCreateInfo->extent.depth <= 0)) {
667a9991b9f53d0be4fecc63bdbdf3de9950070a3a5Mark Lobodzinski        skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 0, __LINE__,
668a9991b9f53d0be4fecc63bdbdf3de9950070a3a5Mark Lobodzinski                             VALIDATION_ERROR_00716, "Image",
669a9991b9f53d0be4fecc63bdbdf3de9950070a3a5Mark Lobodzinski                             "CreateImage extent is 0 for at least one required dimension for image: "
670a9991b9f53d0be4fecc63bdbdf3de9950070a3a5Mark Lobodzinski                             "Width = %d Height = %d Depth = %d. %s",
671a9991b9f53d0be4fecc63bdbdf3de9950070a3a5Mark Lobodzinski                             pCreateInfo->extent.width, pCreateInfo->extent.height, pCreateInfo->extent.depth,
672a9991b9f53d0be4fecc63bdbdf3de9950070a3a5Mark Lobodzinski                             validation_error_map[VALIDATION_ERROR_00716]);
6738dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    }
6748dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
6758dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    // TODO: VALIDATION_ERROR_02125 VALIDATION_ERROR_02126 VALIDATION_ERROR_02128 VALIDATION_ERROR_00720
6768dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    // All these extent-related VUs should be checked here
677d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski    if ((pCreateInfo->extent.depth > ImageFormatProperties->maxExtent.depth) ||
678d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski        (pCreateInfo->extent.width > ImageFormatProperties->maxExtent.width) ||
679d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski        (pCreateInfo->extent.height > ImageFormatProperties->maxExtent.height)) {
6808dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski        skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 0, __LINE__,
6818dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                             IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
6828dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                             "CreateImage extents exceed allowable limits for format: "
6838dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                             "Width = %d Height = %d Depth = %d:  Limits for Width = %d Height = %d Depth = %d for format %s.",
6848dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                             pCreateInfo->extent.width, pCreateInfo->extent.height, pCreateInfo->extent.depth,
685d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski                             ImageFormatProperties->maxExtent.width, ImageFormatProperties->maxExtent.height,
686d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski                             ImageFormatProperties->maxExtent.depth, string_VkFormat(pCreateInfo->format));
6878dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    }
6888dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
6898dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    uint64_t totalSize = ((uint64_t)pCreateInfo->extent.width * (uint64_t)pCreateInfo->extent.height *
6908dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                              (uint64_t)pCreateInfo->extent.depth * (uint64_t)pCreateInfo->arrayLayers *
6918dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                              (uint64_t)pCreateInfo->samples * (uint64_t)vk_format_get_size(pCreateInfo->format) +
6928dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                          (uint64_t)imageGranularity) &
6938dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                         ~(uint64_t)imageGranularity;
6948dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
695d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski    if (totalSize > ImageFormatProperties->maxResourceSize) {
6968dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski        skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 0, __LINE__,
6978dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                             IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
6988dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                             "CreateImage resource size exceeds allowable maximum "
6998dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                             "Image resource size = 0x%" PRIxLEAST64 ", maximum resource size = 0x%" PRIxLEAST64 " ",
700d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski                             totalSize, ImageFormatProperties->maxResourceSize);
7018dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    }
7028dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
7038dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    // TODO: VALIDATION_ERROR_02132
704d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski    if (pCreateInfo->mipLevels > ImageFormatProperties->maxMipLevels) {
7058dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski        skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 0, __LINE__,
7068dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                             IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
7078dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                             "CreateImage mipLevels=%d exceeds allowable maximum supported by format of %d", pCreateInfo->mipLevels,
708d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski                             ImageFormatProperties->maxMipLevels);
7098dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    }
7108dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
711d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski    if (pCreateInfo->arrayLayers > ImageFormatProperties->maxArrayLayers) {
7128dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski        skip_call |= log_msg(
7138dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski            report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 0, __LINE__, VALIDATION_ERROR_02133,
7148dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski            "Image", "CreateImage arrayLayers=%d exceeds allowable maximum supported by format of %d. %s", pCreateInfo->arrayLayers,
715d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski            ImageFormatProperties->maxArrayLayers, validation_error_map[VALIDATION_ERROR_02133]);
7168dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    }
7178dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
718d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski    if ((pCreateInfo->samples & ImageFormatProperties->sampleCounts) == 0) {
7198dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski        skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 0, __LINE__,
7208dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                             VALIDATION_ERROR_02138, "Image", "CreateImage samples %s is not supported by format 0x%.8X. %s",
721d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski                             string_VkSampleCountFlagBits(pCreateInfo->samples), ImageFormatProperties->sampleCounts,
7228dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                             validation_error_map[VALIDATION_ERROR_02138]);
7238dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    }
7248dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
7258dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    if (pCreateInfo->initialLayout != VK_IMAGE_LAYOUT_UNDEFINED && pCreateInfo->initialLayout != VK_IMAGE_LAYOUT_PREINITIALIZED) {
7268dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski        skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 0, __LINE__,
7278dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                             VALIDATION_ERROR_00731, "Image",
7288dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                             "vkCreateImage parameter, pCreateInfo->initialLayout, must be VK_IMAGE_LAYOUT_UNDEFINED or "
7298dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                             "VK_IMAGE_LAYOUT_PREINITIALIZED. %s",
7308dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                             validation_error_map[VALIDATION_ERROR_00731]);
7318dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    }
7328dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
73301363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski    if ((pCreateInfo->flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT) && (!GetEnabledFeatures(device_data)->sparseBinding)) {
73401363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski        skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
73501363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski                             VALIDATION_ERROR_02143, "DS",
73601363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski                             "vkCreateImage(): the sparseBinding device feature is disabled: Images cannot be created with the "
73701363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski                             "VK_IMAGE_CREATE_SPARSE_BINDING_BIT set. %s",
73801363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski                             validation_error_map[VALIDATION_ERROR_02143]);
73901363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski    }
74001363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski
7417e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski    if ((pCreateInfo->flags & VK_IMAGE_CREATE_SPARSE_ALIASED_BIT) && (!GetEnabledFeatures(device_data)->sparseResidencyAliased)) {
7427e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski        skip_call |=
7437e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski            log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
7447e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski                    DRAWSTATE_INVALID_FEATURE, "DS",
7457e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski                    "vkCreateImage(): the sparseResidencyAliased device feature is disabled: Images cannot be created with the "
7467e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski                    "VK_IMAGE_CREATE_SPARSE_ALIASED_BIT set.");
7477e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski    }
7487e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski
7498dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    return skip_call;
7508dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski}
7518dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
752e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisvoid PostCallRecordCreateImage(layer_data *device_data, const VkImageCreateInfo *pCreateInfo, VkImage *pImage) {
753c06c9b88f5f5bcc7033ba41d5547b048fa6015a4Mark Lobodzinski    IMAGE_LAYOUT_NODE image_state;
754c06c9b88f5f5bcc7033ba41d5547b048fa6015a4Mark Lobodzinski    image_state.layout = pCreateInfo->initialLayout;
755c06c9b88f5f5bcc7033ba41d5547b048fa6015a4Mark Lobodzinski    image_state.format = pCreateInfo->format;
756920311b6aa5614a545cad59521770d0898a75d65Mark Lobodzinski    GetImageMap(device_data)->insert(std::make_pair(*pImage, std::unique_ptr<IMAGE_STATE>(new IMAGE_STATE(*pImage, pCreateInfo))));
757c06c9b88f5f5bcc7033ba41d5547b048fa6015a4Mark Lobodzinski    ImageSubresourcePair subpair{*pImage, false, VkImageSubresource()};
758920311b6aa5614a545cad59521770d0898a75d65Mark Lobodzinski    (*core_validation::GetImageSubresourceMap(device_data))[*pImage].push_back(subpair);
759920311b6aa5614a545cad59521770d0898a75d65Mark Lobodzinski    (*core_validation::GetImageLayoutMap(device_data))[subpair] = image_state;
760c06c9b88f5f5bcc7033ba41d5547b048fa6015a4Mark Lobodzinski}
7618c59133586421be878d393799b30044497f77727Mark Lobodzinski
762e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisbool PreCallValidateDestroyImage(layer_data *device_data, VkImage image, IMAGE_STATE **image_state, VK_OBJECT *obj_struct) {
7638c59133586421be878d393799b30044497f77727Mark Lobodzinski    const CHECK_DISABLED *disabled = core_validation::GetDisables(device_data);
7649a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    *image_state = core_validation::GetImageState(device_data, image);
7658c59133586421be878d393799b30044497f77727Mark Lobodzinski    *obj_struct = {reinterpret_cast<uint64_t &>(image), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT};
7668c59133586421be878d393799b30044497f77727Mark Lobodzinski    if (disabled->destroy_image) return false;
7678c59133586421be878d393799b30044497f77727Mark Lobodzinski    bool skip = false;
7688c59133586421be878d393799b30044497f77727Mark Lobodzinski    if (*image_state) {
7698c59133586421be878d393799b30044497f77727Mark Lobodzinski        skip |= core_validation::ValidateObjectNotInUse(device_data, *image_state, *obj_struct, VALIDATION_ERROR_00743);
7708c59133586421be878d393799b30044497f77727Mark Lobodzinski    }
7718c59133586421be878d393799b30044497f77727Mark Lobodzinski    return skip;
7728c59133586421be878d393799b30044497f77727Mark Lobodzinski}
7738c59133586421be878d393799b30044497f77727Mark Lobodzinski
774e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisvoid PostCallRecordDestroyImage(layer_data *device_data, VkImage image, IMAGE_STATE *image_state, VK_OBJECT obj_struct) {
7758c59133586421be878d393799b30044497f77727Mark Lobodzinski    core_validation::invalidateCommandBuffers(device_data, image_state->cb_bindings, obj_struct);
7768c59133586421be878d393799b30044497f77727Mark Lobodzinski    // Clean up memory mapping, bindings and range references for image
7778c59133586421be878d393799b30044497f77727Mark Lobodzinski    for (auto mem_binding : image_state->GetBoundMemory()) {
7789a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto mem_info = core_validation::GetMemObjInfo(device_data, mem_binding);
7798c59133586421be878d393799b30044497f77727Mark Lobodzinski        if (mem_info) {
7808c59133586421be878d393799b30044497f77727Mark Lobodzinski            core_validation::RemoveImageMemoryRange(obj_struct.handle, mem_info);
7818c59133586421be878d393799b30044497f77727Mark Lobodzinski        }
7828c59133586421be878d393799b30044497f77727Mark Lobodzinski    }
7838c59133586421be878d393799b30044497f77727Mark Lobodzinski    core_validation::ClearMemoryObjectBindings(device_data, obj_struct.handle, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT);
7848c59133586421be878d393799b30044497f77727Mark Lobodzinski    // Remove image from imageMap
7858c59133586421be878d393799b30044497f77727Mark Lobodzinski    core_validation::GetImageMap(device_data)->erase(image);
7868c59133586421be878d393799b30044497f77727Mark Lobodzinski    std::unordered_map<VkImage, std::vector<ImageSubresourcePair>> *imageSubresourceMap =
7878c59133586421be878d393799b30044497f77727Mark Lobodzinski        core_validation::GetImageSubresourceMap(device_data);
7888c59133586421be878d393799b30044497f77727Mark Lobodzinski
7898c59133586421be878d393799b30044497f77727Mark Lobodzinski    const auto &sub_entry = imageSubresourceMap->find(image);
7908c59133586421be878d393799b30044497f77727Mark Lobodzinski    if (sub_entry != imageSubresourceMap->end()) {
7918c59133586421be878d393799b30044497f77727Mark Lobodzinski        for (const auto &pair : sub_entry->second) {
7928c59133586421be878d393799b30044497f77727Mark Lobodzinski            core_validation::GetImageLayoutMap(device_data)->erase(pair);
7938c59133586421be878d393799b30044497f77727Mark Lobodzinski        }
7948c59133586421be878d393799b30044497f77727Mark Lobodzinski        imageSubresourceMap->erase(sub_entry);
7958c59133586421be878d393799b30044497f77727Mark Lobodzinski    }
7968c59133586421be878d393799b30044497f77727Mark Lobodzinski}
797509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski
798e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisbool ValidateImageAttributes(layer_data *device_data, IMAGE_STATE *image_state, VkImageSubresourceRange range) {
799509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski    bool skip = false;
800509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
801509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski
802509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski    if (range.aspectMask != VK_IMAGE_ASPECT_COLOR_BIT) {
803509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski        char const str[] = "vkCmdClearColorImage aspectMasks for all subresource ranges must be set to VK_IMAGE_ASPECT_COLOR_BIT";
804509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
805509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski                        reinterpret_cast<uint64_t &>(image_state->image), __LINE__, DRAWSTATE_INVALID_IMAGE_ASPECT, "IMAGE", str);
806509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski    }
807509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski
808509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski    if (vk_format_is_depth_or_stencil(image_state->createInfo.format)) {
809509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski        char const str[] = "vkCmdClearColorImage called with depth/stencil image.";
810509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
811509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski                        reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01088, "IMAGE", "%s. %s", str,
812509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski                        validation_error_map[VALIDATION_ERROR_01088]);
813509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski    } else if (vk_format_is_compressed(image_state->createInfo.format)) {
814509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski        char const str[] = "vkCmdClearColorImage called with compressed image.";
815509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
816509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski                        reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01088, "IMAGE", "%s. %s", str,
817509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski                        validation_error_map[VALIDATION_ERROR_01088]);
818509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski    }
819509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski
820509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski    if (!(image_state->createInfo.usage & VK_IMAGE_USAGE_TRANSFER_DST_BIT)) {
821509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski        char const str[] = "vkCmdClearColorImage called with image created without VK_IMAGE_USAGE_TRANSFER_DST_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__, VALIDATION_ERROR_01084, "IMAGE", "%s. %s", str,
824509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski                        validation_error_map[VALIDATION_ERROR_01084]);
825509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski    }
826509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski    return skip;
827509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski}
828623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski
829e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisvoid ResolveRemainingLevelsLayers(layer_data *dev_data, VkImageSubresourceRange *range, IMAGE_STATE *image_state) {
83008c7aae3177092f8567e2b5a946457be61616e9aMark Lobodzinski    // If the caller used the special values VK_REMAINING_MIP_LEVELS and VK_REMAINING_ARRAY_LAYERS, resolve them now in our
83108c7aae3177092f8567e2b5a946457be61616e9aMark Lobodzinski    // internal state to the actual values.
83208c7aae3177092f8567e2b5a946457be61616e9aMark Lobodzinski    if (range->levelCount == VK_REMAINING_MIP_LEVELS) {
83308c7aae3177092f8567e2b5a946457be61616e9aMark Lobodzinski        range->levelCount = image_state->createInfo.mipLevels - range->baseMipLevel;
83408c7aae3177092f8567e2b5a946457be61616e9aMark Lobodzinski    }
835623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski
83608c7aae3177092f8567e2b5a946457be61616e9aMark Lobodzinski    if (range->layerCount == VK_REMAINING_ARRAY_LAYERS) {
83708c7aae3177092f8567e2b5a946457be61616e9aMark Lobodzinski        range->layerCount = image_state->createInfo.arrayLayers - range->baseArrayLayer;
838623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    }
839623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski}
840623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski
841623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski// Return the correct layer/level counts if the caller used the special values VK_REMAINING_MIP_LEVELS or VK_REMAINING_ARRAY_LAYERS.
842e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisvoid ResolveRemainingLevelsLayers(layer_data *dev_data, uint32_t *levels, uint32_t *layers, VkImageSubresourceRange range,
843e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlis                                  IMAGE_STATE *image_state) {
844623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    *levels = range.levelCount;
845623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    *layers = range.layerCount;
84608c7aae3177092f8567e2b5a946457be61616e9aMark Lobodzinski    if (range.levelCount == VK_REMAINING_MIP_LEVELS) {
84708c7aae3177092f8567e2b5a946457be61616e9aMark Lobodzinski        *levels = image_state->createInfo.mipLevels - range.baseMipLevel;
84808c7aae3177092f8567e2b5a946457be61616e9aMark Lobodzinski    }
84908c7aae3177092f8567e2b5a946457be61616e9aMark Lobodzinski    if (range.layerCount == VK_REMAINING_ARRAY_LAYERS) {
85008c7aae3177092f8567e2b5a946457be61616e9aMark Lobodzinski        *layers = image_state->createInfo.arrayLayers - range.baseArrayLayer;
851623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    }
852623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski}
853623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski
854e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisbool VerifyClearImageLayout(layer_data *device_data, GLOBAL_CB_NODE *cb_node, IMAGE_STATE *image_state,
855623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                            VkImageSubresourceRange range, VkImageLayout dest_image_layout, const char *func_name) {
856623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    bool skip = false;
857623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
858623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski
859623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    VkImageSubresourceRange resolved_range = range;
86008c7aae3177092f8567e2b5a946457be61616e9aMark Lobodzinski    ResolveRemainingLevelsLayers(device_data, &resolved_range, image_state);
861623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski
862623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    if (dest_image_layout != VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
863623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        if (dest_image_layout == VK_IMAGE_LAYOUT_GENERAL) {
864623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski            if (image_state->createInfo.tiling != VK_IMAGE_TILING_LINEAR) {
865623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                // LAYOUT_GENERAL is allowed, but may not be performance optimal, flag as perf warning.
866623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0,
867623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                                __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
868623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                                "%s: Layout for cleared image should be TRANSFER_DST_OPTIMAL instead of GENERAL.", func_name);
869623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski            }
870623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        } else {
871623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski            UNIQUE_VALIDATION_ERROR_CODE error_code = VALIDATION_ERROR_01086;
872623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski            if (strcmp(func_name, "vkCmdClearDepthStencilImage()") == 0) {
873623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                error_code = VALIDATION_ERROR_01101;
874623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski            } else {
875623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                assert(strcmp(func_name, "vkCmdClearColorImage()") == 0);
876623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski            }
877623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski            skip |=
878623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, error_code, "DS",
879623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                        "%s: Layout for cleared image is %s but can only be "
880623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                        "TRANSFER_DST_OPTIMAL or GENERAL. %s",
881623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                        func_name, string_VkImageLayout(dest_image_layout), validation_error_map[error_code]);
882623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        }
883623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    }
884623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski
885623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    for (uint32_t level_index = 0; level_index < resolved_range.levelCount; ++level_index) {
886623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        uint32_t level = level_index + resolved_range.baseMipLevel;
887623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        for (uint32_t layer_index = 0; layer_index < resolved_range.layerCount; ++layer_index) {
888623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski            uint32_t layer = layer_index + resolved_range.baseArrayLayer;
889623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski            VkImageSubresource sub = {resolved_range.aspectMask, level, layer};
890623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski            IMAGE_CMD_BUF_LAYOUT_NODE node;
89155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski            if (FindCmdBufLayout(device_data, cb_node, image_state->image, sub, node)) {
892623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                if (node.layout != dest_image_layout) {
893623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                    UNIQUE_VALIDATION_ERROR_CODE error_code = VALIDATION_ERROR_01085;
894623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                    if (strcmp(func_name, "vkCmdClearDepthStencilImage()") == 0) {
895623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                        error_code = VALIDATION_ERROR_01100;
896623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                    } else {
897623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                        assert(strcmp(func_name, "vkCmdClearColorImage()") == 0);
898623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                    }
899623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                    skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0,
900623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                                    __LINE__, error_code, "DS",
901623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                                    "%s: Cannot clear an image whose layout is %s and "
902623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                                    "doesn't match the current layout %s. %s",
903623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                                    func_name, string_VkImageLayout(dest_image_layout), string_VkImageLayout(node.layout),
904623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                                    validation_error_map[error_code]);
905623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                }
906623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski            }
907623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        }
908623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    }
909623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski
910623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    return skip;
911623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski}
912623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski
913e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisvoid RecordClearImageLayout(layer_data *device_data, GLOBAL_CB_NODE *cb_node, VkImage image, VkImageSubresourceRange range,
914e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlis                            VkImageLayout dest_image_layout) {
915623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    VkImageSubresourceRange resolved_range = range;
9169a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    ResolveRemainingLevelsLayers(device_data, &resolved_range, GetImageState(device_data, image));
917623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski
918623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    for (uint32_t level_index = 0; level_index < resolved_range.levelCount; ++level_index) {
919623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        uint32_t level = level_index + resolved_range.baseMipLevel;
920623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        for (uint32_t layer_index = 0; layer_index < resolved_range.layerCount; ++layer_index) {
921623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski            uint32_t layer = layer_index + resolved_range.baseArrayLayer;
922623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski            VkImageSubresource sub = {resolved_range.aspectMask, level, layer};
923623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski            IMAGE_CMD_BUF_LAYOUT_NODE node;
92455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski            if (!FindCmdBufLayout(device_data, cb_node, image, sub, node)) {
92555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                SetLayout(device_data, cb_node, image, sub, IMAGE_CMD_BUF_LAYOUT_NODE(dest_image_layout, dest_image_layout));
926623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski            }
927623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        }
928623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    }
929623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski}
930623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski
931e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisbool PreCallValidateCmdClearColorImage(layer_data *dev_data, VkCommandBuffer commandBuffer, VkImage image,
932623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                                       VkImageLayout imageLayout, uint32_t rangeCount, const VkImageSubresourceRange *pRanges) {
933623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    bool skip = false;
934623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    // TODO : Verify memory is in VK_IMAGE_STATE_CLEAR state
9359a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto cb_node = GetCBNode(dev_data, commandBuffer);
9369a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto image_state = GetImageState(dev_data, image);
937623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    if (cb_node && image_state) {
938623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        skip |= ValidateMemoryIsBoundToImage(dev_data, image_state, "vkCmdClearColorImage()", VALIDATION_ERROR_02527);
939623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        skip |= ValidateCmd(dev_data, cb_node, CMD_CLEARCOLORIMAGE, "vkCmdClearColorImage()");
940623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        skip |= insideRenderPass(dev_data, cb_node, "vkCmdClearColorImage()", VALIDATION_ERROR_01096);
941623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        for (uint32_t i = 0; i < rangeCount; ++i) {
942623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski            skip |= ValidateImageAttributes(dev_data, image_state, pRanges[i]);
94308c7aae3177092f8567e2b5a946457be61616e9aMark Lobodzinski            skip |= VerifyClearImageLayout(dev_data, cb_node, image_state, pRanges[i], imageLayout, "vkCmdClearColorImage()");
944623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        }
945623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    }
946623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    return skip;
947623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski}
948623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski
949623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski// This state recording routine is shared between ClearColorImage and ClearDepthStencilImage
950e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisvoid PreCallRecordCmdClearImage(layer_data *dev_data, VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout,
951e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlis                                uint32_t rangeCount, const VkImageSubresourceRange *pRanges, CMD_TYPE cmd_type) {
9529a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto cb_node = GetCBNode(dev_data, commandBuffer);
9539a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto image_state = GetImageState(dev_data, image);
954623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    if (cb_node && image_state) {
955623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        AddCommandBufferBindingImage(dev_data, cb_node, image_state);
956623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        std::function<bool()> function = [=]() {
957623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski            SetImageMemoryValid(dev_data, image_state, true);
958623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski            return false;
959623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        };
960623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        cb_node->validate_functions.push_back(function);
9619a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        core_validation::UpdateCmdBufferLastCmd(cb_node, cmd_type);
962623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        for (uint32_t i = 0; i < rangeCount; ++i) {
963623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski            RecordClearImageLayout(dev_data, cb_node, image, pRanges[i], imageLayout);
964623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        }
965623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    }
966623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski}
967623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski
968e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisbool PreCallValidateCmdClearDepthStencilImage(layer_data *device_data, VkCommandBuffer commandBuffer, VkImage image,
969e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlis                                              VkImageLayout imageLayout, uint32_t rangeCount,
970623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                                              const VkImageSubresourceRange *pRanges) {
971623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    bool skip = false;
9727244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
9737244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski
974623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    // TODO : Verify memory is in VK_IMAGE_STATE_CLEAR state
9759a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto cb_node = GetCBNode(device_data, commandBuffer);
9769a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto image_state = GetImageState(device_data, image);
977623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    if (cb_node && image_state) {
9787244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski        skip |= ValidateMemoryIsBoundToImage(device_data, image_state, "vkCmdClearDepthStencilImage()", VALIDATION_ERROR_02528);
9797244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski        skip |= ValidateCmd(device_data, cb_node, CMD_CLEARDEPTHSTENCILIMAGE, "vkCmdClearDepthStencilImage()");
9807244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski        skip |= insideRenderPass(device_data, cb_node, "vkCmdClearDepthStencilImage()", VALIDATION_ERROR_01111);
981623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        for (uint32_t i = 0; i < rangeCount; ++i) {
98208c7aae3177092f8567e2b5a946457be61616e9aMark Lobodzinski            skip |=
98308c7aae3177092f8567e2b5a946457be61616e9aMark Lobodzinski                VerifyClearImageLayout(device_data, cb_node, image_state, pRanges[i], imageLayout, "vkCmdClearDepthStencilImage()");
9847244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski            // Image aspect must be depth or stencil or both
9857244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski            if (((pRanges[i].aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) != VK_IMAGE_ASPECT_DEPTH_BIT) &&
9867244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski                ((pRanges[i].aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) != VK_IMAGE_ASPECT_STENCIL_BIT)) {
9877244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski                char const str[] =
9887244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski                    "vkCmdClearDepthStencilImage aspectMasks for all subresource ranges must be "
9897244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski                    "set to VK_IMAGE_ASPECT_DEPTH_BIT and/or VK_IMAGE_ASPECT_STENCIL_BIT";
9907244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
9917244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski                                (uint64_t)commandBuffer, __LINE__, DRAWSTATE_INVALID_IMAGE_ASPECT, "IMAGE", str);
9927244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski            }
9937244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski        }
9947244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski        if (image_state && !vk_format_is_depth_or_stencil(image_state->createInfo.format)) {
9957244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski            char const str[] = "vkCmdClearDepthStencilImage called without a depth/stencil image.";
9967244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
9977244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski                            reinterpret_cast<uint64_t &>(image), __LINE__, VALIDATION_ERROR_01103, "IMAGE", "%s. %s", str,
9987244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski                            validation_error_map[VALIDATION_ERROR_01103]);
999623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        }
1000623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    }
1001623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    return skip;
1002623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski}
1003ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
1004ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski// Returns true if [x, xoffset] and [y, yoffset] overlap
1005ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinskistatic bool RangesIntersect(int32_t start, uint32_t start_offset, int32_t end, uint32_t end_offset) {
1006ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    bool result = false;
1007ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    uint32_t intersection_min = std::max(static_cast<uint32_t>(start), static_cast<uint32_t>(end));
1008ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    uint32_t intersection_max = std::min(static_cast<uint32_t>(start) + start_offset, static_cast<uint32_t>(end) + end_offset);
1009ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
1010ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    if (intersection_max > intersection_min) {
1011ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski        result = true;
1012ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    }
1013ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    return result;
1014ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski}
1015ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
1016ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski// Returns true if two VkImageCopy structures overlap
1017ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinskistatic bool RegionIntersects(const VkImageCopy *src, const VkImageCopy *dst, VkImageType type) {
1018ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    bool result = false;
1019ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    if ((src->srcSubresource.mipLevel == dst->dstSubresource.mipLevel) &&
1020ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski        (RangesIntersect(src->srcSubresource.baseArrayLayer, src->srcSubresource.layerCount, dst->dstSubresource.baseArrayLayer,
1021ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski                         dst->dstSubresource.layerCount))) {
1022ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski        result = true;
1023ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski        switch (type) {
1024ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski            case VK_IMAGE_TYPE_3D:
1025ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski                result &= RangesIntersect(src->srcOffset.z, src->extent.depth, dst->dstOffset.z, dst->extent.depth);
1026ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski            // Intentionally fall through to 2D case
1027ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski            case VK_IMAGE_TYPE_2D:
1028ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski                result &= RangesIntersect(src->srcOffset.y, src->extent.height, dst->dstOffset.y, dst->extent.height);
1029ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski            // Intentionally fall through to 1D case
1030ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski            case VK_IMAGE_TYPE_1D:
1031ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski                result &= RangesIntersect(src->srcOffset.x, src->extent.width, dst->dstOffset.x, dst->extent.width);
1032ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski                break;
1033ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski            default:
1034ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski                // Unrecognized or new IMAGE_TYPE enums will be caught in parameter_validation
1035ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski                assert(false);
1036ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski        }
1037ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    }
1038ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    return result;
1039ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski}
1040ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
1041ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski// Returns true if offset and extent exceed image extents
10425971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houltonstatic bool ExceedsBounds(const VkOffset3D *offset, const VkExtent3D *extent, const VkExtent3D *image_extent) {
1043ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    bool result = false;
1044ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    // Extents/depths cannot be negative but checks left in for clarity
10455971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton    if ((offset->z + extent->depth > image_extent->depth) || (offset->z < 0) ||
10465971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        ((offset->z + static_cast<int32_t>(extent->depth)) < 0)) {
10475971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        result = true;
10485971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton    }
10495971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton    if ((offset->y + extent->height > image_extent->height) || (offset->y < 0) ||
10505971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        ((offset->y + static_cast<int32_t>(extent->height)) < 0)) {
10515971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        result = true;
10525971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton    }
10535971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton    if ((offset->x + extent->width > image_extent->width) || (offset->x < 0) ||
10545971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        ((offset->x + static_cast<int32_t>(extent->width)) < 0)) {
10555971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        result = true;
1056ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    }
1057ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    return result;
1058ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski}
1059ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
10606a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski// Test if two VkExtent3D structs are equivalent
10616a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinskistatic inline bool IsExtentEqual(const VkExtent3D *extent, const VkExtent3D *other_extent) {
10626a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    bool result = true;
10636a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    if ((extent->width != other_extent->width) || (extent->height != other_extent->height) ||
10646a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        (extent->depth != other_extent->depth)) {
10656a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        result = false;
10666a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    }
10676a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    return result;
10686a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski}
10696a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
10706a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski// Returns the image extent of a specific subresource.
10716a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinskistatic inline VkExtent3D GetImageSubresourceExtent(const IMAGE_STATE *img, const VkImageSubresourceLayers *subresource) {
10726a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    const uint32_t mip = subresource->mipLevel;
10736a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    VkExtent3D extent = img->createInfo.extent;
10745971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton    // Don't allow mip adjustment to create 0 dim, but pass along a 0 if that's what subresource specified
10755971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton    extent.width = (0 == extent.width ? 0 : std::max(1U, extent.width >> mip));
10765971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton    extent.height = (0 == extent.height ? 0 : std::max(1U, extent.height >> mip));
10775971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton    extent.depth = (0 == extent.depth ? 0 : std::max(1U, extent.depth >> mip));
10786a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    return extent;
10796a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski}
10806a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
10816a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski// Test if the extent argument has all dimensions set to 0.
10825971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houltonstatic inline bool IsExtentAllZeroes(const VkExtent3D *extent) {
10836a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    return ((extent->width == 0) && (extent->height == 0) && (extent->depth == 0));
10846a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski}
10856a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
10865971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton// Test if the extent argument has any dimensions set to 0.
10875971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houltonstatic inline bool IsExtentSizeZero(const VkExtent3D *extent) {
10885971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton    return ((extent->width == 0) || (extent->height == 0) || (extent->depth == 0));
10895971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton}
10905971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton
10916a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski// Returns the image transfer granularity for a specific image scaled by compressed block size if necessary.
10926a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinskistatic inline VkExtent3D GetScaledItg(layer_data *device_data, const GLOBAL_CB_NODE *cb_node, const IMAGE_STATE *img) {
10936a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    // Default to (0, 0, 0) granularity in case we can't find the real granularity for the physical device.
10946a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    VkExtent3D granularity = {0, 0, 0};
10956a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    auto pPool = GetCommandPoolNode(device_data, cb_node->createInfo.commandPool);
10966a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    if (pPool) {
10976a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        granularity =
10986a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            GetPhysDevProperties(device_data)->queue_family_properties[pPool->queueFamilyIndex].minImageTransferGranularity;
10996a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if (vk_format_is_compressed(img->createInfo.format)) {
1100b82b418c8bea6d408e4c8f25e024a37c5b35508fMark Lobodzinski            auto block_size = vk_format_compressed_texel_block_extents(img->createInfo.format);
11016a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            granularity.width *= block_size.width;
11026a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            granularity.height *= block_size.height;
11036a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
11046a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    }
11056a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    return granularity;
11066a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski}
11076a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
11086a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski// Test elements of a VkExtent3D structure against alignment constraints contained in another VkExtent3D structure
11096a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinskistatic inline bool IsExtentAligned(const VkExtent3D *extent, const VkExtent3D *granularity) {
11106a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    bool valid = true;
11116a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    if ((vk_safe_modulo(extent->depth, granularity->depth) != 0) || (vk_safe_modulo(extent->width, granularity->width) != 0) ||
11126a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        (vk_safe_modulo(extent->height, granularity->height) != 0)) {
11136a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        valid = false;
11146a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    }
11156a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    return valid;
11166a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski}
11176a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
11186a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski// Check elements of a VkOffset3D structure against a queue family's Image Transfer Granularity values
11196a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinskistatic inline bool CheckItgOffset(layer_data *device_data, const GLOBAL_CB_NODE *cb_node, const VkOffset3D *offset,
11206a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                  const VkExtent3D *granularity, const uint32_t i, const char *function, const char *member) {
11216a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
11226a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    bool skip = false;
11236a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    VkExtent3D offset_extent = {};
11246a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    offset_extent.width = static_cast<uint32_t>(abs(offset->x));
11256a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    offset_extent.height = static_cast<uint32_t>(abs(offset->y));
11266a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    offset_extent.depth = static_cast<uint32_t>(abs(offset->z));
11275971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton    if (IsExtentAllZeroes(granularity)) {
11286a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // If the queue family image transfer granularity is (0, 0, 0), then the offset must always be (0, 0, 0)
11295971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        if (IsExtentAllZeroes(&offset_extent) == false) {
11306a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
11316a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            DRAWSTATE_IMAGE_TRANSFER_GRANULARITY, "DS",
11326a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            "%s: pRegion[%d].%s (x=%d, y=%d, z=%d) must be (x=0, y=0, z=0) "
11336a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            "when the command buffer's queue family image transfer granularity is (w=0, h=0, d=0).",
11346a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            function, i, member, offset->x, offset->y, offset->z);
11356a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
11366a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    } else {
11376a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // If the queue family image transfer granularity is not (0, 0, 0), then the offset dimensions must always be even
11386a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // integer multiples of the image transfer granularity.
11396a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if (IsExtentAligned(&offset_extent, granularity) == false) {
11406a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
11416a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            DRAWSTATE_IMAGE_TRANSFER_GRANULARITY, "DS",
11426a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            "%s: pRegion[%d].%s (x=%d, y=%d, z=%d) dimensions must be even integer "
11436a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            "multiples of this command buffer's queue family image transfer granularity (w=%d, h=%d, d=%d).",
11446a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            function, i, member, offset->x, offset->y, offset->z, granularity->width, granularity->height,
11456a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            granularity->depth);
11466a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
11476a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    }
11486a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    return skip;
11496a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski}
11506a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
11516a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski// Check elements of a VkExtent3D structure against a queue family's Image Transfer Granularity values
11526a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinskistatic inline bool CheckItgExtent(layer_data *device_data, const GLOBAL_CB_NODE *cb_node, const VkExtent3D *extent,
11536a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                  const VkOffset3D *offset, const VkExtent3D *granularity, const VkExtent3D *subresource_extent,
11546a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                  const uint32_t i, const char *function, const char *member) {
11556a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
11566a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    bool skip = false;
11575971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton    if (IsExtentAllZeroes(granularity)) {
11586a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // If the queue family image transfer granularity is (0, 0, 0), then the extent must always match the image
11596a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // subresource extent.
11606a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if (IsExtentEqual(extent, subresource_extent) == false) {
11616a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
11626a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            DRAWSTATE_IMAGE_TRANSFER_GRANULARITY, "DS",
11636a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            "%s: pRegion[%d].%s (w=%d, h=%d, d=%d) must match the image subresource extents (w=%d, h=%d, d=%d) "
11646a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            "when the command buffer's queue family image transfer granularity is (w=0, h=0, d=0).",
11656a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            function, i, member, extent->width, extent->height, extent->depth, subresource_extent->width,
11666a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            subresource_extent->height, subresource_extent->depth);
11676a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
11686a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    } else {
11696a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // If the queue family image transfer granularity is not (0, 0, 0), then the extent dimensions must always be even
11706a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // integer multiples of the image transfer granularity or the offset + extent dimensions must always match the image
11716a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // subresource extent dimensions.
11726a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        VkExtent3D offset_extent_sum = {};
11736a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        offset_extent_sum.width = static_cast<uint32_t>(abs(offset->x)) + extent->width;
11746a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        offset_extent_sum.height = static_cast<uint32_t>(abs(offset->y)) + extent->height;
11756a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        offset_extent_sum.depth = static_cast<uint32_t>(abs(offset->z)) + extent->depth;
11766a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if ((IsExtentAligned(extent, granularity) == false) && (IsExtentEqual(&offset_extent_sum, subresource_extent) == false)) {
11776a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            skip |=
11786a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
11796a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                        DRAWSTATE_IMAGE_TRANSFER_GRANULARITY, "DS",
11806a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                        "%s: pRegion[%d].%s (w=%d, h=%d, d=%d) dimensions must be even integer multiples of this command buffer's "
11816a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                        "queue family image transfer granularity (w=%d, h=%d, d=%d) or offset (x=%d, y=%d, z=%d) + "
11826a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                        "extent (w=%d, h=%d, d=%d) must match the image subresource extents (w=%d, h=%d, d=%d).",
11836a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                        function, i, member, extent->width, extent->height, extent->depth, granularity->width, granularity->height,
11846a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                        granularity->depth, offset->x, offset->y, offset->z, extent->width, extent->height, extent->depth,
11856a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                        subresource_extent->width, subresource_extent->height, subresource_extent->depth);
11866a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
11876a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    }
11886a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    return skip;
11896a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski}
11906a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
11916a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski// Check a uint32_t width or stride value against a queue family's Image Transfer Granularity width value
11926a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinskistatic inline bool CheckItgInt(layer_data *device_data, const GLOBAL_CB_NODE *cb_node, const uint32_t value,
11936a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                               const uint32_t granularity, const uint32_t i, const char *function, const char *member) {
11946a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
11956a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
11966a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    bool skip = false;
11976a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    if (vk_safe_modulo(value, granularity) != 0) {
11986a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
11996a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                        DRAWSTATE_IMAGE_TRANSFER_GRANULARITY, "DS",
12006a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                        "%s: pRegion[%d].%s (%d) must be an even integer multiple of this command buffer's queue family image "
12016a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                        "transfer granularity width (%d).",
12026a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                        function, i, member, value, granularity);
12036a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    }
12046a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    return skip;
12056a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski}
12066a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
12076a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski// Check a VkDeviceSize value against a queue family's Image Transfer Granularity width value
12086a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinskistatic inline bool CheckItgSize(layer_data *device_data, const GLOBAL_CB_NODE *cb_node, const VkDeviceSize value,
12096a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                const uint32_t granularity, const uint32_t i, const char *function, const char *member) {
12106a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
12116a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    bool skip = false;
12126a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    if (vk_safe_modulo(value, granularity) != 0) {
12136a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
12146a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                        DRAWSTATE_IMAGE_TRANSFER_GRANULARITY, "DS",
12156a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                        "%s: pRegion[%d].%s (%" PRIdLEAST64
12166a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                        ") must be an even integer multiple of this command buffer's queue family image transfer "
12176a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                        "granularity width (%d).",
12186a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                        function, i, member, value, granularity);
12196a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    }
12206a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    return skip;
12216a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski}
12226a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
12236a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski// Check valid usage Image Tranfer Granularity requirements for elements of a VkBufferImageCopy structure
12246a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinskibool ValidateCopyBufferImageTransferGranularityRequirements(layer_data *device_data, const GLOBAL_CB_NODE *cb_node,
12256a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                                            const IMAGE_STATE *img, const VkBufferImageCopy *region,
12266a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                                            const uint32_t i, const char *function) {
12276a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    bool skip = false;
12286a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    if (vk_format_is_compressed(img->createInfo.format) == true) {
12296a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // TODO: Add granularity checking for compressed formats
12306a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
12316a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // bufferRowLength must be a multiple of the compressed texel block width
12326a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // bufferImageHeight must be a multiple of the compressed texel block height
12336a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // all members of imageOffset must be a multiple of the corresponding dimensions of the compressed texel block
12346a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // bufferOffset must be a multiple of the compressed texel block size in bytes
12356a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // imageExtent.width must be a multiple of the compressed texel block width or (imageExtent.width + imageOffset.x)
12366a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        //     must equal the image subresource width
12376a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // imageExtent.height must be a multiple of the compressed texel block height or (imageExtent.height + imageOffset.y)
12386a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        //     must equal the image subresource height
12396a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // imageExtent.depth must be a multiple of the compressed texel block depth or (imageExtent.depth + imageOffset.z)
12406a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        //     must equal the image subresource depth
12416a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    } else {
12426a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        VkExtent3D granularity = GetScaledItg(device_data, cb_node, img);
12436a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        skip |= CheckItgSize(device_data, cb_node, region->bufferOffset, granularity.width, i, function, "bufferOffset");
12446a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        skip |= CheckItgInt(device_data, cb_node, region->bufferRowLength, granularity.width, i, function, "bufferRowLength");
12456a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        skip |= CheckItgInt(device_data, cb_node, region->bufferImageHeight, granularity.width, i, function, "bufferImageHeight");
12466a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        skip |= CheckItgOffset(device_data, cb_node, &region->imageOffset, &granularity, i, function, "imageOffset");
12476a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        VkExtent3D subresource_extent = GetImageSubresourceExtent(img, &region->imageSubresource);
12486a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        skip |= CheckItgExtent(device_data, cb_node, &region->imageExtent, &region->imageOffset, &granularity, &subresource_extent,
12496a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                               i, function, "imageExtent");
12506a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    }
12516a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    return skip;
12526a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski}
12536a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
12546a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski// Check valid usage Image Tranfer Granularity requirements for elements of a VkImageCopy structure
12556a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinskibool ValidateCopyImageTransferGranularityRequirements(layer_data *device_data, const GLOBAL_CB_NODE *cb_node,
12566a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                                      const IMAGE_STATE *img, const VkImageCopy *region, const uint32_t i,
12576a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                                      const char *function) {
12586a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    bool skip = false;
12596a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    VkExtent3D granularity = GetScaledItg(device_data, cb_node, img);
12606a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    skip |= CheckItgOffset(device_data, cb_node, &region->srcOffset, &granularity, i, function, "srcOffset");
12616a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    skip |= CheckItgOffset(device_data, cb_node, &region->dstOffset, &granularity, i, function, "dstOffset");
12626a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    VkExtent3D subresource_extent = GetImageSubresourceExtent(img, &region->dstSubresource);
12636a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    skip |= CheckItgExtent(device_data, cb_node, &region->extent, &region->dstOffset, &granularity, &subresource_extent, i,
12646a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                           function, "extent");
12656a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    return skip;
12666a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski}
12676a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
1268e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisbool PreCallValidateCmdCopyImage(layer_data *device_data, GLOBAL_CB_NODE *cb_node, IMAGE_STATE *src_image_state,
12696a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                 IMAGE_STATE *dst_image_state, uint32_t region_count, const VkImageCopy *regions,
12706a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                 VkImageLayout src_image_layout, VkImageLayout dst_image_layout) {
1271ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    bool skip = false;
1272ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
1273ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    VkCommandBuffer command_buffer = cb_node->commandBuffer;
1274ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
12756a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    for (uint32_t i = 0; i < region_count; i++) {
12766a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if (regions[i].srcSubresource.layerCount == 0) {
12776a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            std::stringstream ss;
12786a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            ss << "vkCmdCopyImage: number of layers in pRegions[" << i << "] srcSubresource is zero";
12796a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
12806a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            reinterpret_cast<uint64_t &>(command_buffer), __LINE__, DRAWSTATE_INVALID_IMAGE_ASPECT, "IMAGE", "%s",
12816a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            ss.str().c_str());
12826a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
1283ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
12846a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if (regions[i].dstSubresource.layerCount == 0) {
12856a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            std::stringstream ss;
12866a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            ss << "vkCmdCopyImage: number of layers in pRegions[" << i << "] dstSubresource is zero";
12876a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
12886a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            reinterpret_cast<uint64_t &>(command_buffer), __LINE__, DRAWSTATE_INVALID_IMAGE_ASPECT, "IMAGE", "%s",
12896a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            ss.str().c_str());
12906a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
1291ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
12926a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // For each region the layerCount member of srcSubresource and dstSubresource must match
12936a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if (regions[i].srcSubresource.layerCount != regions[i].dstSubresource.layerCount) {
12946a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            std::stringstream ss;
12956a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            ss << "vkCmdCopyImage: number of layers in source and destination subresources for pRegions[" << i << "] do not match";
12966a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
12976a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01198, "IMAGE", "%s. %s",
12986a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            ss.str().c_str(), validation_error_map[VALIDATION_ERROR_01198]);
12996a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
1300ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
13016a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // For each region, the aspectMask member of srcSubresource and dstSubresource must match
13026a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if (regions[i].srcSubresource.aspectMask != regions[i].dstSubresource.aspectMask) {
13036a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            char const str[] = "vkCmdCopyImage: Src and dest aspectMasks for each region must match";
13046a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
13056a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01197, "IMAGE", "%s. %s", str,
13066a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            validation_error_map[VALIDATION_ERROR_01197]);
13076a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
1308ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
13096a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // AspectMask must not contain VK_IMAGE_ASPECT_METADATA_BIT
13106a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if ((regions[i].srcSubresource.aspectMask & VK_IMAGE_ASPECT_METADATA_BIT) ||
13116a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            (regions[i].dstSubresource.aspectMask & VK_IMAGE_ASPECT_METADATA_BIT)) {
13126a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            std::stringstream ss;
13136a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            ss << "vkCmdCopyImage: pRegions[" << i << "] may not specify aspectMask containing VK_IMAGE_ASPECT_METADATA_BIT";
13146a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
13156a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01222, "IMAGE", "%s. %s",
13166a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            ss.str().c_str(), validation_error_map[VALIDATION_ERROR_01222]);
13176a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
1318ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
13196a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // For each region, if aspectMask contains VK_IMAGE_ASPECT_COLOR_BIT, it must not contain either of
13206a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // VK_IMAGE_ASPECT_DEPTH_BIT or VK_IMAGE_ASPECT_STENCIL_BIT
13216a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if ((regions[i].srcSubresource.aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) &&
13226a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            (regions[i].srcSubresource.aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))) {
13236a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            char const str[] = "vkCmdCopyImage aspectMask cannot specify both COLOR and DEPTH/STENCIL aspects";
13246a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
13256a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01221, "IMAGE", "%s. %s", str,
13266a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            validation_error_map[VALIDATION_ERROR_01221]);
13276a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
1328ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
13296a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // If either of the calling command's src_image or dst_image parameters are of VkImageType VK_IMAGE_TYPE_3D,
13306a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // the baseArrayLayer and layerCount members of both srcSubresource and dstSubresource must be 0 and 1, respectively
13316a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if (((src_image_state->createInfo.imageType == VK_IMAGE_TYPE_3D) ||
13326a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski             (dst_image_state->createInfo.imageType == VK_IMAGE_TYPE_3D)) &&
13336a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            ((regions[i].srcSubresource.baseArrayLayer != 0) || (regions[i].srcSubresource.layerCount != 1) ||
13346a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski             (regions[i].dstSubresource.baseArrayLayer != 0) || (regions[i].dstSubresource.layerCount != 1))) {
13356a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            std::stringstream ss;
13366a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            ss << "vkCmdCopyImage: src or dstImage type was IMAGE_TYPE_3D, but in subRegion[" << i
13376a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski               << "] baseArrayLayer was not zero or layerCount was not 1.";
13386a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
13396a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01199, "IMAGE", "%s. %s",
13406a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            ss.str().c_str(), validation_error_map[VALIDATION_ERROR_01199]);
13416a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
1342ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
13436a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // MipLevel must be less than the mipLevels specified in VkImageCreateInfo when the image was created
13446a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if (regions[i].srcSubresource.mipLevel >= src_image_state->createInfo.mipLevels) {
13456a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            std::stringstream ss;
13466a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            ss << "vkCmdCopyImage: pRegions[" << i
13476a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski               << "] specifies a src mipLevel greater than the number specified when the srcImage was created.";
13486a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
13496a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01223, "IMAGE", "%s. %s",
13506a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            ss.str().c_str(), validation_error_map[VALIDATION_ERROR_01223]);
13516a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
13526a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if (regions[i].dstSubresource.mipLevel >= dst_image_state->createInfo.mipLevels) {
13536a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            std::stringstream ss;
13546a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            ss << "vkCmdCopyImage: pRegions[" << i
13556a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski               << "] specifies a dst mipLevel greater than the number specified when the dstImage was created.";
13566a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
13576a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01223, "IMAGE", "%s. %s",
13586a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            ss.str().c_str(), validation_error_map[VALIDATION_ERROR_01223]);
13596a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
1360ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
13616a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // (baseArrayLayer + layerCount) must be less than or equal to the arrayLayers specified in VkImageCreateInfo when the
13626a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // image was created
13636a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if ((regions[i].srcSubresource.baseArrayLayer + regions[i].srcSubresource.layerCount) >
13646a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            src_image_state->createInfo.arrayLayers) {
13656a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            std::stringstream ss;
13666a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            ss << "vkCmdCopyImage: srcImage arrayLayers was " << src_image_state->createInfo.arrayLayers << " but subRegion[" << i
13676a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski               << "] baseArrayLayer + layerCount is "
13686a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski               << (regions[i].srcSubresource.baseArrayLayer + regions[i].srcSubresource.layerCount);
13696a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
13706a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01224, "IMAGE", "%s. %s",
13716a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            ss.str().c_str(), validation_error_map[VALIDATION_ERROR_01224]);
13726a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
13736a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if ((regions[i].dstSubresource.baseArrayLayer + regions[i].dstSubresource.layerCount) >
13746a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            dst_image_state->createInfo.arrayLayers) {
13756a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            std::stringstream ss;
13766a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            ss << "vkCmdCopyImage: dstImage arrayLayers was " << dst_image_state->createInfo.arrayLayers << " but subRegion[" << i
13776a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski               << "] baseArrayLayer + layerCount is "
13786a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski               << (regions[i].dstSubresource.baseArrayLayer + regions[i].dstSubresource.layerCount);
13796a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
13806a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01224, "IMAGE", "%s. %s",
13816a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            ss.str().c_str(), validation_error_map[VALIDATION_ERROR_01224]);
13826a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
1383ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
13846a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // The source region specified by a given element of regions must be a region that is contained within srcImage
13855971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        if (ExceedsBounds(&regions[i].srcOffset, &regions[i].extent, &(src_image_state->createInfo.extent))) {
13866a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            std::stringstream ss;
13876a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            ss << "vkCmdCopyImage: srcSubResource in pRegions[" << i << "] exceeds extents srcImage was created with";
13886a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
13896a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01175, "IMAGE", "%s. %s",
13906a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            ss.str().c_str(), validation_error_map[VALIDATION_ERROR_01175]);
13916a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
1392ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
13936a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // The destination region specified by a given element of regions must be a region that is contained within dst_image
13945971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        if (ExceedsBounds(&regions[i].dstOffset, &regions[i].extent, &(dst_image_state->createInfo.extent))) {
13956a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            std::stringstream ss;
13966a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            ss << "vkCmdCopyImage: dstSubResource in pRegions[" << i << "] exceeds extents dstImage was created with";
13976a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
13986a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01176, "IMAGE", "%s. %s",
13996a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            ss.str().c_str(), validation_error_map[VALIDATION_ERROR_01176]);
14006a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
1401ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
14026a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // The union of all source regions, and the union of all destination regions, specified by the elements of regions,
14036a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // must not overlap in memory
14046a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if (src_image_state->image == dst_image_state->image) {
14056a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            for (uint32_t j = 0; j < region_count; j++) {
14066a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                if (RegionIntersects(&regions[i], &regions[j], src_image_state->createInfo.imageType)) {
14076a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                    std::stringstream ss;
14086a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                    ss << "vkCmdCopyImage: pRegions[" << i << "] src overlaps with pRegions[" << j << "].";
14096a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                    skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
14106a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                    reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01177, "IMAGE",
14116a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                    "%s. %s", ss.str().c_str(), validation_error_map[VALIDATION_ERROR_01177]);
1412ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski                }
1413ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski            }
1414ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski        }
14156a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    }
1416ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
14176a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    // The formats of src_image and dst_image must be compatible. Formats are considered compatible if their texel size in bytes
14186a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    // is the same between both formats. For example, VK_FORMAT_R8G8B8A8_UNORM is compatible with VK_FORMAT_R32_UINT because
14196a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    // because both texels are 4 bytes in size. Depth/stencil formats must match exactly.
14206a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    if (vk_format_is_depth_or_stencil(src_image_state->createInfo.format) ||
14216a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        vk_format_is_depth_or_stencil(dst_image_state->createInfo.format)) {
14226a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if (src_image_state->createInfo.format != dst_image_state->createInfo.format) {
14236a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            char const str[] = "vkCmdCopyImage called with unmatched source and dest image depth/stencil formats.";
14246a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            skip |=
14256a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
14266a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                        reinterpret_cast<uint64_t &>(command_buffer), __LINE__, DRAWSTATE_MISMATCHED_IMAGE_FORMAT, "IMAGE", str);
14276a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
14286a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    } else {
14296a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        size_t srcSize = vk_format_get_size(src_image_state->createInfo.format);
14306a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        size_t destSize = vk_format_get_size(dst_image_state->createInfo.format);
14316a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if (srcSize != destSize) {
14326a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            char const str[] = "vkCmdCopyImage called with unmatched source and dest image format sizes.";
14336a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
14346a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01184, "IMAGE", "%s. %s", str,
14356a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            validation_error_map[VALIDATION_ERROR_01184]);
1436ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski        }
1437ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    }
14386a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
14396a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    skip |= ValidateMemoryIsBoundToImage(device_data, src_image_state, "vkCmdCopyImage()", VALIDATION_ERROR_02533);
14406a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    skip |= ValidateMemoryIsBoundToImage(device_data, dst_image_state, "vkCmdCopyImage()", VALIDATION_ERROR_02534);
14416a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    // Validate that SRC & DST images have correct usage flags set
14426a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    skip |= ValidateImageUsageFlags(device_data, src_image_state, VK_IMAGE_USAGE_TRANSFER_SRC_BIT, true, VALIDATION_ERROR_01178,
14436a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                    "vkCmdCopyImage()", "VK_IMAGE_USAGE_TRANSFER_SRC_BIT");
14446a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    skip |= ValidateImageUsageFlags(device_data, dst_image_state, VK_IMAGE_USAGE_TRANSFER_DST_BIT, true, VALIDATION_ERROR_01181,
14456a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                    "vkCmdCopyImage()", "VK_IMAGE_USAGE_TRANSFER_DST_BIT");
14466a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    skip |= ValidateCmd(device_data, cb_node, CMD_COPYIMAGE, "vkCmdCopyImage()");
14476a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    skip |= insideRenderPass(device_data, cb_node, "vkCmdCopyImage()", VALIDATION_ERROR_01194);
14486a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    for (uint32_t i = 0; i < region_count; ++i) {
14496a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        skip |= VerifySourceImageLayout(device_data, cb_node, src_image_state->image, regions[i].srcSubresource, src_image_layout,
14506a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                        VALIDATION_ERROR_01180);
14516a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        skip |= VerifyDestImageLayout(device_data, cb_node, dst_image_state->image, regions[i].dstSubresource, dst_image_layout,
14526a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                      VALIDATION_ERROR_01183);
14536a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        skip |= ValidateCopyImageTransferGranularityRequirements(device_data, cb_node, dst_image_state, &regions[i], i,
14546a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                                                 "vkCmdCopyImage()");
14556a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    }
14566a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
1457ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    return skip;
1458ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski}
1459a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski
14606a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinskivoid PreCallRecordCmdCopyImage(layer_data *device_data, GLOBAL_CB_NODE *cb_node, IMAGE_STATE *src_image_state,
14616a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                               IMAGE_STATE *dst_image_state) {
14626a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    // Update bindings between images and cmd buffer
14636a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    AddCommandBufferBindingImage(device_data, cb_node, src_image_state);
14646a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    AddCommandBufferBindingImage(device_data, cb_node, dst_image_state);
14653f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton    std::function<bool()> function = [=]() { return ValidateImageMemoryIsValid(device_data, src_image_state, "vkCmdCopyImage()"); };
14666a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    cb_node->validate_functions.push_back(function);
14676a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    function = [=]() {
14686a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        SetImageMemoryValid(device_data, dst_image_state, true);
14696a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        return false;
14706a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    };
14716a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    cb_node->validate_functions.push_back(function);
14726a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    core_validation::UpdateCmdBufferLastCmd(cb_node, CMD_COPYIMAGE);
14736a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski}
14746a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
1475a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski// TODO : Should be tracking lastBound per commandBuffer and when draws occur, report based on that cmd buffer lastBound
1476a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski//   Then need to synchronize the accesses based on cmd buffer so that if I'm reading state on one cmd buffer, updates
1477a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski//   to that same cmd buffer by separate thread are not changing state from underneath us
1478a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski// Track the last cmd buffer touched by this thread
1479a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinskistatic bool hasDrawCmd(GLOBAL_CB_NODE *pCB) {
1480a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski    for (uint32_t i = 0; i < NUM_DRAW_TYPES; i++) {
1481a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski        if (pCB->drawCount[i]) return true;
1482a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski    }
1483a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski    return false;
1484a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski}
1485a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski
1486a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski// Returns true if sub_rect is entirely contained within rect
1487a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinskistatic inline bool ContainsRect(VkRect2D rect, VkRect2D sub_rect) {
1488a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski    if ((sub_rect.offset.x < rect.offset.x) || (sub_rect.offset.x + sub_rect.extent.width > rect.offset.x + rect.extent.width) ||
1489a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski        (sub_rect.offset.y < rect.offset.y) || (sub_rect.offset.y + sub_rect.extent.height > rect.offset.y + rect.extent.height))
1490a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski        return false;
1491a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski    return true;
1492a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski}
1493a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski
1494e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisbool PreCallValidateCmdClearAttachments(layer_data *device_data, VkCommandBuffer commandBuffer, uint32_t attachmentCount,
1495e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlis                                        const VkClearAttachment *pAttachments, uint32_t rectCount, const VkClearRect *pRects) {
14969a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    GLOBAL_CB_NODE *cb_node = GetCBNode(device_data, commandBuffer);
1497a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
1498a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski
1499a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski    bool skip = false;
1500a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski    if (cb_node) {
1501a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski        skip |= ValidateCmd(device_data, cb_node, CMD_CLEARATTACHMENTS, "vkCmdClearAttachments()");
15029a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        core_validation::UpdateCmdBufferLastCmd(cb_node, CMD_CLEARATTACHMENTS);
1503a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski        // Warn if this is issued prior to Draw Cmd and clearing the entire attachment
1504a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski        if (!hasDrawCmd(cb_node) && (cb_node->activeRenderPassBeginInfo.renderArea.extent.width == pRects[0].rect.extent.width) &&
1505a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski            (cb_node->activeRenderPassBeginInfo.renderArea.extent.height == pRects[0].rect.extent.height)) {
1506a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski            // There are times where app needs to use ClearAttachments (generally when reusing a buffer inside of a render pass)
15078e0190bd5904b8a8f044dae2c6ae23a891eb5e11Mark 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
15088e0190bd5904b8a8f044dae2c6ae23a891eb5e11Mark Lobodzinski            // CmdClearAttachments.
150973f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski            skip |=
151073f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                log_msg(report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
151173f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                        reinterpret_cast<uint64_t &>(commandBuffer), 0, DRAWSTATE_CLEAR_CMD_BEFORE_DRAW, "DS",
151273f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                        "vkCmdClearAttachments() issued on command buffer object 0x%p prior to any Draw Cmds."
151373f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                        " It is recommended you use RenderPass LOAD_OP_CLEAR on Attachments prior to any Draw.",
151473f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                        commandBuffer);
1515a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski        }
1516a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski        skip |= outsideRenderPass(device_data, cb_node, "vkCmdClearAttachments()", VALIDATION_ERROR_01122);
1517a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski    }
1518a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski
1519a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski    // Validate that attachment is in reference list of active subpass
1520a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski    if (cb_node->activeRenderPass) {
1521a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski        const VkRenderPassCreateInfo *renderpass_create_info = cb_node->activeRenderPass->createInfo.ptr();
1522a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski        const VkSubpassDescription *subpass_desc = &renderpass_create_info->pSubpasses[cb_node->activeSubpass];
15239a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto framebuffer = GetFramebufferState(device_data, cb_node->activeFramebuffer);
1524a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski
1525a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski        for (uint32_t i = 0; i < attachmentCount; i++) {
1526a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski            auto clear_desc = &pAttachments[i];
1527a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski            VkImageView image_view = VK_NULL_HANDLE;
1528a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski
152973f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski            if (0 == clear_desc->aspectMask) {
153073f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
153173f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                (uint64_t)commandBuffer, __LINE__, VALIDATION_ERROR_01128, "IMAGE", "%s",
153273f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                validation_error_map[VALIDATION_ERROR_01128]);
153373f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski            } else if (clear_desc->aspectMask & VK_IMAGE_ASPECT_METADATA_BIT) {
153473f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
153573f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                (uint64_t)commandBuffer, __LINE__, VALIDATION_ERROR_01126, "IMAGE", "%s",
153673f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                validation_error_map[VALIDATION_ERROR_01126]);
153773f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski            } else if (clear_desc->aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) {
1538a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                if (clear_desc->colorAttachment >= subpass_desc->colorAttachmentCount) {
153973f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                    skip |=
154073f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                        log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
154173f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                (uint64_t)commandBuffer, __LINE__, VALIDATION_ERROR_01114, "DS",
154273f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                "vkCmdClearAttachments() color attachment index %d out of range for active subpass %d. %s",
154373f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                clear_desc->colorAttachment, cb_node->activeSubpass, validation_error_map[VALIDATION_ERROR_01114]);
1544a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                } else if (subpass_desc->pColorAttachments[clear_desc->colorAttachment].attachment == VK_ATTACHMENT_UNUSED) {
1545a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                    skip |= log_msg(report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT,
154673f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                    VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)commandBuffer, __LINE__,
154773f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                    DRAWSTATE_MISSING_ATTACHMENT_REFERENCE, "DS",
154873f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                    "vkCmdClearAttachments() color attachment index %d is VK_ATTACHMENT_UNUSED; ignored.",
154973f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                    clear_desc->colorAttachment);
1550a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                } else {
1551a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                    image_view = framebuffer->createInfo
155273f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                     .pAttachments[subpass_desc->pColorAttachments[clear_desc->colorAttachment].attachment];
1553a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                }
155473f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                if ((clear_desc->aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) ||
155573f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                    (clear_desc->aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT)) {
155673f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                    char const str[] =
155773f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                        "vkCmdClearAttachments aspectMask [%d] must set only VK_IMAGE_ASPECT_COLOR_BIT of a color attachment. %s";
155873f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                    skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
155973f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                    (uint64_t)commandBuffer, __LINE__, VALIDATION_ERROR_01125, "IMAGE", str, i,
156073f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                    validation_error_map[VALIDATION_ERROR_01125]);
156173f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                }
156273f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski            } else {  // Must be depth and/or stencil
156373f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                if (((clear_desc->aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) != VK_IMAGE_ASPECT_DEPTH_BIT) &&
156473f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                    ((clear_desc->aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) != VK_IMAGE_ASPECT_STENCIL_BIT)) {
156573f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                    char const str[] = "vkCmdClearAttachments aspectMask [%d] is not a valid combination of bits. %s";
156673f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                    skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
156773f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                    (uint64_t)commandBuffer, __LINE__, VALIDATION_ERROR_01127, "IMAGE", str, i,
156873f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                    validation_error_map[VALIDATION_ERROR_01127]);
156973f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                }
157073f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                if (!subpass_desc->pDepthStencilAttachment ||
157173f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                    (subpass_desc->pDepthStencilAttachment->attachment == VK_ATTACHMENT_UNUSED)) {
157273f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                    skip |= log_msg(
157373f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                        report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
157473f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                        (uint64_t)commandBuffer, __LINE__, DRAWSTATE_MISSING_ATTACHMENT_REFERENCE, "DS",
157573f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                        "vkCmdClearAttachments() depth/stencil clear with no depth/stencil attachment in subpass; ignored");
1576a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                } else {
1577a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                    image_view = framebuffer->createInfo.pAttachments[subpass_desc->pDepthStencilAttachment->attachment];
1578a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                }
1579a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski            }
1580a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski            if (image_view) {
15819a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis                auto image_view_state = GetImageViewState(device_data, image_view);
1582a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                for (uint32_t j = 0; j < rectCount; j++) {
158373f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                    // The rectangular region specified by a given element of pRects must be contained within the render area of
158473f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                    // the current render pass instance
15858e0190bd5904b8a8f044dae2c6ae23a891eb5e11Mark Lobodzinski                    // TODO: This check should be moved to CmdExecuteCommands or QueueSubmit to cover secondary CB cases
15868e0190bd5904b8a8f044dae2c6ae23a891eb5e11Mark Lobodzinski                    if ((cb_node->createInfo.level == VK_COMMAND_BUFFER_LEVEL_PRIMARY) &&
15878e0190bd5904b8a8f044dae2c6ae23a891eb5e11Mark Lobodzinski                        (false == ContainsRect(cb_node->activeRenderPassBeginInfo.renderArea, pRects[j].rect))) {
158873f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
158973f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                        __LINE__, VALIDATION_ERROR_01115, "DS",
159073f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                        "vkCmdClearAttachments(): The area defined by pRects[%d] is not contained in the area of "
159173f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                        "the current render pass instance. %s",
159273f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                        j, validation_error_map[VALIDATION_ERROR_01115]);
1593a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                    }
1594a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                    // The layers specified by a given element of pRects must be contained within every attachment that
1595a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                    // pAttachments refers to
1596a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                    auto attachment_base_array_layer = image_view_state->create_info.subresourceRange.baseArrayLayer;
1597a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                    auto attachment_layer_count = image_view_state->create_info.subresourceRange.layerCount;
1598a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                    if ((pRects[j].baseArrayLayer < attachment_base_array_layer) || pRects[j].layerCount > attachment_layer_count) {
1599a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                        skip |=
160073f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                            log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
160173f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                    __LINE__, VALIDATION_ERROR_01116, "DS",
160273f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                    "vkCmdClearAttachments(): The layers defined in pRects[%d] are not contained in the layers of "
160373f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                    "pAttachment[%d]. %s",
160473f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                    j, i, validation_error_map[VALIDATION_ERROR_01116]);
1605a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                    }
1606a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                }
1607a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski            }
1608a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski        }
1609a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski    }
1610a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski    return skip;
161160568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski}
161260568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski
1613e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisbool PreCallValidateCmdResolveImage(layer_data *device_data, GLOBAL_CB_NODE *cb_node, IMAGE_STATE *src_image_state,
161454c03b0fa365789b242e680223bd30c940f1abb3Mark Lobodzinski                                    IMAGE_STATE *dst_image_state, uint32_t regionCount, const VkImageResolve *pRegions) {
161525f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
161660568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    bool skip = false;
161760568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    if (cb_node && src_image_state && dst_image_state) {
161860568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        skip |= ValidateMemoryIsBoundToImage(device_data, src_image_state, "vkCmdResolveImage()", VALIDATION_ERROR_02541);
161960568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        skip |= ValidateMemoryIsBoundToImage(device_data, dst_image_state, "vkCmdResolveImage()", VALIDATION_ERROR_02542);
162060568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        skip |= ValidateCmd(device_data, cb_node, CMD_RESOLVEIMAGE, "vkCmdResolveImage()");
162160568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        skip |= insideRenderPass(device_data, cb_node, "vkCmdResolveImage()", VALIDATION_ERROR_01335);
162225f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski
162325f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski        // For each region, the number of layers in the image subresource should not be zero
162425f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski        // For each region, src and dest image aspect must be color only
162525f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski        for (uint32_t i = 0; i < regionCount; i++) {
162625f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski            if (pRegions[i].srcSubresource.layerCount == 0) {
162725f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                char const str[] = "vkCmdResolveImage: number of layers in source subresource is zero";
162854c03b0fa365789b242e680223bd30c940f1abb3Mark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
162925f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                                reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, DRAWSTATE_MISMATCHED_IMAGE_ASPECT,
163025f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                                "IMAGE", str);
163125f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski            }
163225f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski            if (pRegions[i].dstSubresource.layerCount == 0) {
163325f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                char const str[] = "vkCmdResolveImage: number of layers in destination subresource is zero";
163454c03b0fa365789b242e680223bd30c940f1abb3Mark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
163525f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                                reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, DRAWSTATE_MISMATCHED_IMAGE_ASPECT,
163625f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                                "IMAGE", str);
163725f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski            }
163854c03b0fa365789b242e680223bd30c940f1abb3Mark Lobodzinski            if (pRegions[i].srcSubresource.layerCount != pRegions[i].dstSubresource.layerCount) {
163954c03b0fa365789b242e680223bd30c940f1abb3Mark Lobodzinski                skip |= log_msg(
164054c03b0fa365789b242e680223bd30c940f1abb3Mark Lobodzinski                    report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
164154c03b0fa365789b242e680223bd30c940f1abb3Mark Lobodzinski                    reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_01339, "IMAGE",
164254c03b0fa365789b242e680223bd30c940f1abb3Mark Lobodzinski                    "vkCmdResolveImage: layerCount in source and destination subresource of pRegions[%d] does not match. %s", i,
164354c03b0fa365789b242e680223bd30c940f1abb3Mark Lobodzinski                    validation_error_map[VALIDATION_ERROR_01339]);
164454c03b0fa365789b242e680223bd30c940f1abb3Mark Lobodzinski            }
164525f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski            if ((pRegions[i].srcSubresource.aspectMask != VK_IMAGE_ASPECT_COLOR_BIT) ||
164625f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                (pRegions[i].dstSubresource.aspectMask != VK_IMAGE_ASPECT_COLOR_BIT)) {
164725f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                char const str[] =
164825f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                    "vkCmdResolveImage: src and dest aspectMasks for each region must specify only VK_IMAGE_ASPECT_COLOR_BIT";
164925f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
165025f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                                reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_01338, "IMAGE",
165125f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                                "%s. %s", str, validation_error_map[VALIDATION_ERROR_01338]);
165225f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski            }
165325f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski        }
165425f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski
165525f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski        if (src_image_state->createInfo.format != dst_image_state->createInfo.format) {
165625f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski            char const str[] = "vkCmdResolveImage called with unmatched source and dest formats.";
165754c03b0fa365789b242e680223bd30c940f1abb3Mark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
165825f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                            reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, DRAWSTATE_MISMATCHED_IMAGE_FORMAT,
165925f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                            "IMAGE", str);
166025f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski        }
166125f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski        if (src_image_state->createInfo.imageType != dst_image_state->createInfo.imageType) {
166225f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski            char const str[] = "vkCmdResolveImage called with unmatched source and dest image types.";
166354c03b0fa365789b242e680223bd30c940f1abb3Mark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
166425f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                            reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, DRAWSTATE_MISMATCHED_IMAGE_TYPE, "IMAGE",
166525f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                            str);
166625f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski        }
166725f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski        if (src_image_state->createInfo.samples == VK_SAMPLE_COUNT_1_BIT) {
166825f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski            char const str[] = "vkCmdResolveImage called with source sample count less than 2.";
166925f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
167025f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                            reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_01320, "IMAGE", "%s. %s",
167125f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                            str, validation_error_map[VALIDATION_ERROR_01320]);
167225f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski        }
167325f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski        if (dst_image_state->createInfo.samples != VK_SAMPLE_COUNT_1_BIT) {
167425f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski            char const str[] = "vkCmdResolveImage called with dest sample count greater than 1.";
167525f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
167625f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                            reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_01321, "IMAGE", "%s. %s",
167725f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                            str, validation_error_map[VALIDATION_ERROR_01321]);
167825f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski        }
167960568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    } else {
168060568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        assert(0);
168160568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    }
168260568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    return skip;
168360568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski}
168460568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski
1685e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisvoid PreCallRecordCmdResolveImage(layer_data *device_data, GLOBAL_CB_NODE *cb_node, IMAGE_STATE *src_image_state,
1686e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlis                                  IMAGE_STATE *dst_image_state) {
168760568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    // Update bindings between images and cmd buffer
168860568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    AddCommandBufferBindingImage(device_data, cb_node, src_image_state);
168960568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    AddCommandBufferBindingImage(device_data, cb_node, dst_image_state);
169060568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski
169160568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    std::function<bool()> function = [=]() {
169260568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        return ValidateImageMemoryIsValid(device_data, src_image_state, "vkCmdResolveImage()");
169360568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    };
169460568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    cb_node->validate_functions.push_back(function);
169560568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    function = [=]() {
169660568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        SetImageMemoryValid(device_data, dst_image_state, true);
169760568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        return false;
169860568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    };
169960568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    cb_node->validate_functions.push_back(function);
17009a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    core_validation::UpdateCmdBufferLastCmd(cb_node, CMD_RESOLVEIMAGE);
170160568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski}
170260568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski
1703e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisbool PreCallValidateCmdBlitImage(layer_data *device_data, GLOBAL_CB_NODE *cb_node, IMAGE_STATE *src_image_state,
1704055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                                 IMAGE_STATE *dst_image_state, uint32_t regionCount, const VkImageBlit *pRegions, VkFilter filter) {
1705055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
1706055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski
170760568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    bool skip = false;
170860568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    if (cb_node && src_image_state && dst_image_state) {
170960568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        skip |= ValidateImageSampleCount(device_data, src_image_state, VK_SAMPLE_COUNT_1_BIT, "vkCmdBlitImage(): srcImage",
1710055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                                         VALIDATION_ERROR_02194);
171160568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        skip |= ValidateImageSampleCount(device_data, dst_image_state, VK_SAMPLE_COUNT_1_BIT, "vkCmdBlitImage(): dstImage",
1712055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                                         VALIDATION_ERROR_02195);
171360568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        skip |= ValidateMemoryIsBoundToImage(device_data, src_image_state, "vkCmdBlitImage()", VALIDATION_ERROR_02539);
171460568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        skip |= ValidateMemoryIsBoundToImage(device_data, dst_image_state, "vkCmdBlitImage()", VALIDATION_ERROR_02540);
171560568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        skip |= ValidateImageUsageFlags(device_data, src_image_state, VK_IMAGE_USAGE_TRANSFER_SRC_BIT, true, VALIDATION_ERROR_02182,
1716055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                                        "vkCmdBlitImage()", "VK_IMAGE_USAGE_TRANSFER_SRC_BIT");
171760568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        skip |= ValidateImageUsageFlags(device_data, dst_image_state, VK_IMAGE_USAGE_TRANSFER_DST_BIT, true, VALIDATION_ERROR_02186,
1718055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                                        "vkCmdBlitImage()", "VK_IMAGE_USAGE_TRANSFER_DST_BIT");
171960568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        skip |= ValidateCmd(device_data, cb_node, CMD_BLITIMAGE, "vkCmdBlitImage()");
172060568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        skip |= insideRenderPass(device_data, cb_node, "vkCmdBlitImage()", VALIDATION_ERROR_01300);
1721055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski
1722055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski        for (uint32_t i = 0; i < regionCount; i++) {
1723d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski            // Warn for zero-sized regions
1724055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski            if ((pRegions[i].srcOffsets[0].x == pRegions[i].srcOffsets[1].x) ||
1725055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                (pRegions[i].srcOffsets[0].y == pRegions[i].srcOffsets[1].y) ||
1726055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                (pRegions[i].srcOffsets[0].z == pRegions[i].srcOffsets[1].z)) {
1727055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                std::stringstream ss;
1728055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                ss << "vkCmdBlitImage: pRegions[" << i << "].srcOffsets specify a zero-volume area.";
1729055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1730055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                                reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, DRAWSTATE_INVALID_EXTENTS, "IMAGE",
1731055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                                "%s", ss.str().c_str());
1732055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski            }
1733055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski            if ((pRegions[i].dstOffsets[0].x == pRegions[i].dstOffsets[1].x) ||
1734055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                (pRegions[i].dstOffsets[0].y == pRegions[i].dstOffsets[1].y) ||
1735055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                (pRegions[i].dstOffsets[0].z == pRegions[i].dstOffsets[1].z)) {
1736055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                std::stringstream ss;
1737055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                ss << "vkCmdBlitImage: pRegions[" << i << "].dstOffsets specify a zero-volume area.";
1738055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1739055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                                reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, DRAWSTATE_INVALID_EXTENTS, "IMAGE",
1740055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                                "%s", ss.str().c_str());
1741055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski            }
1742d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski            if (pRegions[i].srcSubresource.layerCount == 0) {
1743d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski                char const str[] = "vkCmdBlitImage: number of layers in source subresource is zero";
1744d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
17453f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                                reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, DRAWSTATE_MISMATCHED_IMAGE_ASPECT,
17463f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                                "IMAGE", str);
1747d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski            }
1748d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski            if (pRegions[i].dstSubresource.layerCount == 0) {
1749d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski                char const str[] = "vkCmdBlitImage: number of layers in destination subresource is zero";
1750d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
17513f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                                reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, DRAWSTATE_MISMATCHED_IMAGE_ASPECT,
17523f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                                "IMAGE", str);
1753d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski            }
1754d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski
1755d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski            // Check that src/dst layercounts match
1756d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski            if (pRegions[i].srcSubresource.layerCount != pRegions[i].dstSubresource.layerCount) {
1757d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski                skip |=
1758d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski                    log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1759d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski                            reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_01304, "IMAGE",
1760d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski                            "vkCmdBlitImage: layerCount in source and destination subresource of pRegions[%d] does not match. %s",
1761d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski                            i, validation_error_map[VALIDATION_ERROR_01304]);
1762d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski            }
17638068cb0f90422b6789d0c120f0831f55eb76b71aMark Lobodzinski
17648068cb0f90422b6789d0c120f0831f55eb76b71aMark Lobodzinski            if (pRegions[i].srcSubresource.aspectMask != pRegions[i].dstSubresource.aspectMask) {
17658068cb0f90422b6789d0c120f0831f55eb76b71aMark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
17668068cb0f90422b6789d0c120f0831f55eb76b71aMark Lobodzinski                                reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_01303, "IMAGE",
17678068cb0f90422b6789d0c120f0831f55eb76b71aMark Lobodzinski                                "vkCmdBlitImage: aspectMask members for pRegion[%d] do not match. %s", i,
17688068cb0f90422b6789d0c120f0831f55eb76b71aMark Lobodzinski                                validation_error_map[VALIDATION_ERROR_01303]);
17698068cb0f90422b6789d0c120f0831f55eb76b71aMark Lobodzinski            }
1770055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski        }
1771055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski
1772055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski        VkFormat src_format = src_image_state->createInfo.format;
1773055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski        VkFormat dst_format = dst_image_state->createInfo.format;
1774055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski
1775055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski        // Validate consistency for unsigned formats
1776055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski        if (vk_format_is_uint(src_format) != vk_format_is_uint(dst_format)) {
1777055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski            std::stringstream ss;
1778055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski            ss << "vkCmdBlitImage: If one of srcImage and dstImage images has unsigned integer format, "
1779055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski               << "the other one must also have unsigned integer format.  "
1780055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski               << "Source format is " << string_VkFormat(src_format) << " Destination format is " << string_VkFormat(dst_format);
1781055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1782055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                            reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_02191, "IMAGE", "%s. %s",
1783055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                            ss.str().c_str(), validation_error_map[VALIDATION_ERROR_02191]);
1784055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski        }
1785055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski
1786055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski        // Validate consistency for signed formats
1787055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski        if (vk_format_is_sint(src_format) != vk_format_is_sint(dst_format)) {
1788055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski            std::stringstream ss;
1789055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski            ss << "vkCmdBlitImage: If one of srcImage and dstImage images has signed integer format, "
1790055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski               << "the other one must also have signed integer format.  "
1791055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski               << "Source format is " << string_VkFormat(src_format) << " Destination format is " << string_VkFormat(dst_format);
1792055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1793055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                            reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_02190, "IMAGE", "%s. %s",
1794055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                            ss.str().c_str(), validation_error_map[VALIDATION_ERROR_02190]);
1795055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski        }
1796055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski
1797055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski        // Validate aspect bits and formats for depth/stencil images
1798055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski        if (vk_format_is_depth_or_stencil(src_format) || vk_format_is_depth_or_stencil(dst_format)) {
1799055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski            if (src_format != dst_format) {
1800055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                std::stringstream ss;
1801055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                ss << "vkCmdBlitImage: If one of srcImage and dstImage images has a format of depth, stencil or depth "
1802055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                   << "stencil, the other one must have exactly the same format.  "
1803055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                   << "Source format is " << string_VkFormat(src_format) << " Destination format is "
1804055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                   << string_VkFormat(dst_format);
1805055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1806055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                                reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_02192, "IMAGE",
1807055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                                "%s. %s", ss.str().c_str(), validation_error_map[VALIDATION_ERROR_02192]);
1808055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski            }
1809055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski
1810055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski            for (uint32_t i = 0; i < regionCount; i++) {
1811055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                VkImageAspectFlags srcAspect = pRegions[i].srcSubresource.aspectMask;
1812055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski
1813055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                if (vk_format_is_depth_and_stencil(src_format)) {
1814055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                    if ((srcAspect != VK_IMAGE_ASPECT_DEPTH_BIT) && (srcAspect != VK_IMAGE_ASPECT_STENCIL_BIT)) {
1815055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                        std::stringstream ss;
1816055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                        ss << "vkCmdBlitImage: Combination depth/stencil image formats must have only one of "
1817055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                              "VK_IMAGE_ASPECT_DEPTH_BIT "
1818055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                           << "and VK_IMAGE_ASPECT_STENCIL_BIT set in srcImage and dstImage";
1819055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1820055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                                        reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__,
1821055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                                        DRAWSTATE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
1822055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                    }
1823055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                } else if (vk_format_is_stencil_only(src_format)) {
1824055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                    if (srcAspect != VK_IMAGE_ASPECT_STENCIL_BIT) {
1825055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                        std::stringstream ss;
1826055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                        ss << "vkCmdBlitImage: Stencil-only image formats must have only the VK_IMAGE_ASPECT_STENCIL_BIT "
1827055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                           << "set in both the srcImage and dstImage";
1828055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1829055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                                        reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__,
1830055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                                        DRAWSTATE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
1831055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                    }
1832055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                } else if (vk_format_is_depth_only(src_format)) {
1833055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                    if (srcAspect != VK_IMAGE_ASPECT_DEPTH_BIT) {
1834055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                        std::stringstream ss;
1835055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                        ss << "vkCmdBlitImage: Depth-only image formats must have only the VK_IMAGE_ASPECT_DEPTH "
1836055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                           << "set in both the srcImage and dstImage";
1837055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1838055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                                        reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__,
1839055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                                        DRAWSTATE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
1840055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                    }
1841055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                }
1842055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski            }
1843055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski        }
1844055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski
1845055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski        // Validate filter
1846055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski        if (vk_format_is_depth_or_stencil(src_format) && (filter != VK_FILTER_NEAREST)) {
1847055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski            std::stringstream ss;
1848055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski            ss << "vkCmdBlitImage: If the format of srcImage is a depth, stencil, or depth stencil "
1849055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski               << "then filter must be VK_FILTER_NEAREST.";
1850055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1851055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                            reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_02193, "IMAGE", "%s. %s",
1852055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                            ss.str().c_str(), validation_error_map[VALIDATION_ERROR_02193]);
1853055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski        }
185460568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    } else {
185560568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        assert(0);
185660568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    }
185760568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    return skip;
185860568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski}
185960568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski
1860e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisvoid PreCallRecordCmdBlitImage(layer_data *device_data, GLOBAL_CB_NODE *cb_node, IMAGE_STATE *src_image_state,
1861e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlis                               IMAGE_STATE *dst_image_state) {
186260568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    // Update bindings between images and cmd buffer
186360568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    AddCommandBufferBindingImage(device_data, cb_node, src_image_state);
186460568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    AddCommandBufferBindingImage(device_data, cb_node, dst_image_state);
186560568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski
186660568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    std::function<bool()> function = [=]() { return ValidateImageMemoryIsValid(device_data, src_image_state, "vkCmdBlitImage()"); };
186760568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    cb_node->validate_functions.push_back(function);
186860568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    function = [=]() {
186960568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        SetImageMemoryValid(device_data, dst_image_state, true);
187060568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        return false;
187160568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    };
187260568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    cb_node->validate_functions.push_back(function);
18739a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    core_validation::UpdateCmdBufferLastCmd(cb_node, CMD_BLITIMAGE);
187460568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski}
187560568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski
187651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour// This validates that the initial layout specified in the command buffer for
187751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour// the IMAGE is the same
187851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour// as the global IMAGE layout
1879440bdd357701497c3442e3515f12ac1cfffc180aTony Barbourbool ValidateCmdBufImageLayouts(layer_data *device_data, GLOBAL_CB_NODE *pCB,
1880440bdd357701497c3442e3515f12ac1cfffc180aTony Barbour                                std::unordered_map<ImageSubresourcePair, IMAGE_LAYOUT_NODE> &imageLayoutMap) {
188190e629846621a0d870212dc0cebfbc83431cc5b8Mark Lobodzinski    bool skip = false;
188251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    const debug_report_data *report_data = core_validation::GetReportData(device_data);
1883788ff59d81fc816f451414dcf2a9d6c29456ff63Mark Lobodzinski    for (auto cb_image_data : pCB->imageLayoutMap) {
1884788ff59d81fc816f451414dcf2a9d6c29456ff63Mark Lobodzinski        VkImageLayout imageLayout;
188551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour
1886521b2f3957b3b31aeb2dbcc7529b54e06c9dc9ecJeremy Hayes        if (FindLayout(imageLayoutMap, cb_image_data.first, imageLayout)) {
1887788ff59d81fc816f451414dcf2a9d6c29456ff63Mark Lobodzinski            if (cb_image_data.second.initialLayout == VK_IMAGE_LAYOUT_UNDEFINED) {
1888788ff59d81fc816f451414dcf2a9d6c29456ff63Mark Lobodzinski                // TODO: Set memory invalid which is in mem_tracker currently
1889788ff59d81fc816f451414dcf2a9d6c29456ff63Mark Lobodzinski            } else if (imageLayout != cb_image_data.second.initialLayout) {
1890788ff59d81fc816f451414dcf2a9d6c29456ff63Mark Lobodzinski                if (cb_image_data.first.hasSubresource) {
18913f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                    skip |= log_msg(
18923f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                        report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
18933f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                        reinterpret_cast<uint64_t &>(pCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
18943f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                        "Cannot submit cmd buffer using image (0x%" PRIx64
18953f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                        ") [sub-resource: aspectMask 0x%X array layer %u, mip level %u], "
18963f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                        "with layout %s when first use is %s.",
18973f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                        reinterpret_cast<const uint64_t &>(cb_image_data.first.image), cb_image_data.first.subresource.aspectMask,
18983f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                        cb_image_data.first.subresource.arrayLayer, cb_image_data.first.subresource.mipLevel,
18993f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                        string_VkImageLayout(imageLayout), string_VkImageLayout(cb_image_data.second.initialLayout));
1900788ff59d81fc816f451414dcf2a9d6c29456ff63Mark Lobodzinski                } else {
19013f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                    skip |=
19023f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                        log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
19033f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                                reinterpret_cast<uint64_t &>(pCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
19043f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                                "Cannot submit cmd buffer using image (0x%" PRIx64
19053f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                                ") with layout %s when "
19063f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                                "first use is %s.",
19073f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                                reinterpret_cast<const uint64_t &>(cb_image_data.first.image), string_VkImageLayout(imageLayout),
19083f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                                string_VkImageLayout(cb_image_data.second.initialLayout));
1909788ff59d81fc816f451414dcf2a9d6c29456ff63Mark Lobodzinski                }
1910788ff59d81fc816f451414dcf2a9d6c29456ff63Mark Lobodzinski            }
191151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour            SetLayout(imageLayoutMap, cb_image_data.first, cb_image_data.second.layout);
1912788ff59d81fc816f451414dcf2a9d6c29456ff63Mark Lobodzinski        }
1913788ff59d81fc816f451414dcf2a9d6c29456ff63Mark Lobodzinski    }
191490e629846621a0d870212dc0cebfbc83431cc5b8Mark Lobodzinski    return skip;
1915788ff59d81fc816f451414dcf2a9d6c29456ff63Mark Lobodzinski}
1916940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski
191751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbourvoid UpdateCmdBufImageLayouts(layer_data *device_data, GLOBAL_CB_NODE *pCB) {
191851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    for (auto cb_image_data : pCB->imageLayoutMap) {
191951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour        VkImageLayout imageLayout;
192051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour        FindGlobalLayout(device_data, cb_image_data.first, imageLayout);
192151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour        SetGlobalLayout(device_data, cb_image_data.first, cb_image_data.second.layout);
192251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    }
192351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour}
192451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour
1925940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski// Print readable FlagBits in FlagMask
1926940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinskistatic std::string string_VkAccessFlags(VkAccessFlags accessMask) {
1927940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski    std::string result;
1928940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski    std::string separator;
1929940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski
1930940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski    if (accessMask == 0) {
1931940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski        result = "[None]";
1932940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski    } else {
1933940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski        result = "[";
1934940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski        for (auto i = 0; i < 32; i++) {
1935940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski            if (accessMask & (1 << i)) {
1936940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski                result = result + separator + string_VkAccessFlagBits((VkAccessFlagBits)(1 << i));
1937940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski                separator = " | ";
1938940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski            }
1939940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski        }
1940940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski        result = result + "]";
1941940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski    }
1942940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski    return result;
1943940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski}
1944940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski
19458fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski// AccessFlags MUST have 'required_bit' set, and may have one or more of 'optional_bits' set. If required_bit is zero, accessMask
19468fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski// must have at least one of 'optional_bits' set
1947940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski// TODO: Add tracking to ensure that at least one barrier has been set for these layout transitions
19488fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinskistatic bool ValidateMaskBits(core_validation::layer_data *device_data, VkCommandBuffer cmdBuffer, const VkAccessFlags &accessMask,
19498fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                             const VkImageLayout &layout, VkAccessFlags required_bit, VkAccessFlags optional_bits,
19508fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                             const char *type) {
19518fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
19528fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski    bool skip = false;
1953940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski
1954940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski    if ((accessMask & required_bit) || (!required_bit && (accessMask & optional_bits))) {
1955940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski        if (accessMask & ~(required_bit | optional_bits)) {
1956940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski            // TODO: Verify against Valid Use
19578fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
19588fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                            DRAWSTATE_INVALID_BARRIER, "DS",
19598fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                            "Additional bits in %s accessMask 0x%X %s are specified when layout is %s.", type, accessMask,
19608fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                            string_VkAccessFlags(accessMask).c_str(), string_VkImageLayout(layout));
1961940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski        }
1962940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski    } else {
1963940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski        if (!required_bit) {
19648fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
19658fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                            DRAWSTATE_INVALID_BARRIER, "DS",
19668fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                            "%s AccessMask %d %s must contain at least one of access bits %d "
19678fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                            "%s when layout is %s, unless the app has previously added a "
19688fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                            "barrier for this transition.",
19698fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                            type, accessMask, string_VkAccessFlags(accessMask).c_str(), optional_bits,
19708fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                            string_VkAccessFlags(optional_bits).c_str(), string_VkImageLayout(layout));
1971940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski        } else {
1972940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski            std::string opt_bits;
1973940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski            if (optional_bits != 0) {
1974940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski                std::stringstream ss;
1975940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski                ss << optional_bits;
1976940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski                opt_bits = "and may have optional bits " + ss.str() + ' ' + string_VkAccessFlags(optional_bits);
1977940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski            }
19788fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
19798fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                            DRAWSTATE_INVALID_BARRIER, "DS",
19808fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                            "%s AccessMask %d %s must have required access bit %d %s %s when "
19818fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                            "layout is %s, unless the app has previously added a barrier for "
19828fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                            "this transition.",
19838fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                            type, accessMask, string_VkAccessFlags(accessMask).c_str(), required_bit,
19848fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                            string_VkAccessFlags(required_bit).c_str(), opt_bits.c_str(), string_VkImageLayout(layout));
1985940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski        }
1986940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski    }
19878fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski    return skip;
1988940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski}
1989940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski
19908fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinskibool ValidateMaskBitsFromLayouts(core_validation::layer_data *device_data, VkCommandBuffer cmdBuffer,
19918fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                                 const VkAccessFlags &accessMask, const VkImageLayout &layout, const char *type) {
19928fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
1993940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski
19948fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski    bool skip = false;
1995940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski    switch (layout) {
19968fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski        case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: {
19978fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            skip |= ValidateMaskBits(device_data, cmdBuffer, accessMask, layout, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
19988fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                                     VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, type);
19998fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            break;
2000940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski        }
20018fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski        case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: {
20028fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            skip |= ValidateMaskBits(device_data, cmdBuffer, accessMask, layout, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
20038fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                                     VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, type);
20048fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            break;
20058fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski        }
20068fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski        case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: {
20078fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            skip |= ValidateMaskBits(device_data, cmdBuffer, accessMask, layout, VK_ACCESS_TRANSFER_WRITE_BIT, 0, type);
20088fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            break;
20098fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski        }
20108fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski        case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL: {
20118fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            skip |= ValidateMaskBits(
20128fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                device_data, cmdBuffer, accessMask, layout, 0,
20138fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
20148fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                type);
20158fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            break;
20168fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski        }
20178fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski        case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: {
20188fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            skip |= ValidateMaskBits(device_data, cmdBuffer, accessMask, layout, 0,
20198fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                                     VK_ACCESS_INPUT_ATTACHMENT_READ_BIT | VK_ACCESS_SHADER_READ_BIT, type);
20208fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            break;
20218fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski        }
20228fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski        case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: {
20238fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            skip |= ValidateMaskBits(device_data, cmdBuffer, accessMask, layout, VK_ACCESS_TRANSFER_READ_BIT, 0, type);
20248fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            break;
20258fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski        }
20268fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski        case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR: {
20278fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            skip |= ValidateMaskBits(device_data, cmdBuffer, accessMask, layout, VK_ACCESS_MEMORY_READ_BIT, 0, type);
20288fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            break;
20298fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski        }
20308fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski        case VK_IMAGE_LAYOUT_UNDEFINED: {
20318fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            if (accessMask != 0) {
20328fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                // TODO: Verify against Valid Use section spec
20338fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
20348fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                                DRAWSTATE_INVALID_BARRIER, "DS",
20358fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                                "Additional bits in %s accessMask 0x%X %s are specified when layout is %s.", type, accessMask,
20368fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                                string_VkAccessFlags(accessMask).c_str(), string_VkImageLayout(layout));
20378fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            }
20388fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            break;
20398fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski        }
20408fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski        case VK_IMAGE_LAYOUT_GENERAL:
20418fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski        default: { break; }
2042940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski    }
20438fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski    return skip;
2044940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski}
2045d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski
2046d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski// ValidateLayoutVsAttachmentDescription is a general function where we can validate various state associated with the
2047374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski// VkAttachmentDescription structs that are used by the sub-passes of a renderpass. Initial check is to make sure that READ_ONLY
2048374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski// layout attachments don't have CLEAR as their loadOp.
2049d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinskibool ValidateLayoutVsAttachmentDescription(const debug_report_data *report_data, const VkImageLayout first_layout,
2050374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                           const uint32_t attachment, const VkAttachmentDescription &attachment_description) {
2051374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski    bool skip = false;
2052d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski    // Verify that initial loadOp on READ_ONLY attachments is not CLEAR
2053d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski    if (attachment_description.loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR) {
2054d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski        if ((first_layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL) ||
2055d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            (first_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)) {
2056374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT,
2057374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                            VkDebugReportObjectTypeEXT(0), __LINE__, VALIDATION_ERROR_02351, "DS",
2058374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                            "Cannot clear attachment %d with invalid first layout %s. %s", attachment,
2059374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                            string_VkImageLayout(first_layout), validation_error_map[VALIDATION_ERROR_02351]);
2060d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski        }
2061d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski    }
2062374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski    return skip;
2063d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski}
2064d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski
2065374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinskibool ValidateLayouts(core_validation::layer_data *device_data, VkDevice device, const VkRenderPassCreateInfo *pCreateInfo) {
2066374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
2067d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski    bool skip = false;
2068d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski
2069d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski    // Track when we're observing the first use of an attachment
2070d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski    std::vector<bool> attach_first_use(pCreateInfo->attachmentCount, true);
2071d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski    for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) {
2072d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski        const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i];
2073d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski        for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) {
2074d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            auto attach_index = subpass.pColorAttachments[j].attachment;
2075d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            if (attach_index == VK_ATTACHMENT_UNUSED) continue;
2076d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski
2077d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            switch (subpass.pColorAttachments[j].layout) {
2078374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
2079374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    // This is ideal.
2080374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    break;
2081d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski
2082374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                case VK_IMAGE_LAYOUT_GENERAL:
2083374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    // May not be optimal; TODO: reconsider this warning based on other constraints?
2084374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    skip |= log_msg(report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT,
2085374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                    VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
2086374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                    "Layout for color attachment is GENERAL but should be COLOR_ATTACHMENT_OPTIMAL.");
2087374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    break;
2088374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski
2089374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                default:
2090374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
2091374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                    __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
2092374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                    "Layout for color attachment is %s but can only be COLOR_ATTACHMENT_OPTIMAL or GENERAL.",
2093374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                    string_VkImageLayout(subpass.pColorAttachments[j].layout));
2094d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            }
2095d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski
2096d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            if (attach_first_use[attach_index]) {
2097374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                skip |= ValidateLayoutVsAttachmentDescription(report_data, subpass.pColorAttachments[j].layout, attach_index,
2098374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                                              pCreateInfo->pAttachments[attach_index]);
2099d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            }
2100d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            attach_first_use[attach_index] = false;
2101d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski        }
2102d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski        if (subpass.pDepthStencilAttachment && subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) {
2103d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            switch (subpass.pDepthStencilAttachment->layout) {
2104374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
2105374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
2106374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    // These are ideal.
2107374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    break;
2108374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski
2109374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                case VK_IMAGE_LAYOUT_GENERAL:
2110374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    // May not be optimal; TODO: reconsider this warning based on other constraints? GENERAL can be better than
2111374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    // doing a bunch of transitions.
2112374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    skip |= log_msg(report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT,
2113374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                    VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
2114374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                    "GENERAL layout for depth attachment may not give optimal performance.");
2115374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    break;
2116374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski
2117374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                default:
2118374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    // No other layouts are acceptable
2119374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
2120374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                    __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
2121374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                    "Layout for depth attachment is %s but can only be DEPTH_STENCIL_ATTACHMENT_OPTIMAL, "
2122374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                    "DEPTH_STENCIL_READ_ONLY_OPTIMAL or GENERAL.",
2123374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                    string_VkImageLayout(subpass.pDepthStencilAttachment->layout));
2124d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            }
2125d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski
2126d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            auto attach_index = subpass.pDepthStencilAttachment->attachment;
2127d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            if (attach_first_use[attach_index]) {
2128374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                skip |= ValidateLayoutVsAttachmentDescription(report_data, subpass.pDepthStencilAttachment->layout, attach_index,
2129374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                                              pCreateInfo->pAttachments[attach_index]);
2130d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            }
2131d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            attach_first_use[attach_index] = false;
2132d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski        }
2133d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski        for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) {
2134d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            auto attach_index = subpass.pInputAttachments[j].attachment;
2135d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            if (attach_index == VK_ATTACHMENT_UNUSED) continue;
2136d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski
2137d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            switch (subpass.pInputAttachments[j].layout) {
2138374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
2139374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
2140374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    // These are ideal.
2141374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    break;
2142d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski
2143374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                case VK_IMAGE_LAYOUT_GENERAL:
2144374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    // May not be optimal. TODO: reconsider this warning based on other constraints.
2145374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    skip |= log_msg(report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT,
2146374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                    VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
2147374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                    "Layout for input attachment is GENERAL but should be READ_ONLY_OPTIMAL.");
2148374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    break;
2149374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski
2150374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                default:
2151374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    // No other layouts are acceptable
2152374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
2153374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                    DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
2154374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                    "Layout for input attachment is %s but can only be READ_ONLY_OPTIMAL or GENERAL.",
2155374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                    string_VkImageLayout(subpass.pInputAttachments[j].layout));
2156d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            }
2157d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski
2158d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            if (attach_first_use[attach_index]) {
2159374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                skip |= ValidateLayoutVsAttachmentDescription(report_data, subpass.pInputAttachments[j].layout, attach_index,
2160374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                                              pCreateInfo->pAttachments[attach_index]);
2161d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            }
2162d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            attach_first_use[attach_index] = false;
2163d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski        }
2164d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski    }
2165d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski    return skip;
2166d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski}
2167c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski
2168c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski// For any image objects that overlap mapped memory, verify that their layouts are PREINIT or GENERAL
216909cd2c76808f1485206baeda9864f7ed907d7e05Mark Lobodzinskibool ValidateMapImageLayouts(core_validation::layer_data *device_data, VkDevice device, DEVICE_MEM_INFO const *mem_info,
217009cd2c76808f1485206baeda9864f7ed907d7e05Mark Lobodzinski                             VkDeviceSize offset, VkDeviceSize end_offset) {
217109cd2c76808f1485206baeda9864f7ed907d7e05Mark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
217209cd2c76808f1485206baeda9864f7ed907d7e05Mark Lobodzinski    bool skip = false;
217309cd2c76808f1485206baeda9864f7ed907d7e05Mark Lobodzinski    // Iterate over all bound image ranges and verify that for any that overlap the map ranges, the layouts are
217409cd2c76808f1485206baeda9864f7ed907d7e05Mark Lobodzinski    // VK_IMAGE_LAYOUT_PREINITIALIZED or VK_IMAGE_LAYOUT_GENERAL
2175c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski    // TODO : This can be optimized if we store ranges based on starting address and early exit when we pass our range
2176c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski    for (auto image_handle : mem_info->bound_images) {
2177c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski        auto img_it = mem_info->bound_ranges.find(image_handle);
2178c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski        if (img_it != mem_info->bound_ranges.end()) {
217909cd2c76808f1485206baeda9864f7ed907d7e05Mark Lobodzinski            if (rangesIntersect(device_data, &img_it->second, offset, end_offset)) {
2180c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski                std::vector<VkImageLayout> layouts;
218109cd2c76808f1485206baeda9864f7ed907d7e05Mark Lobodzinski                if (FindLayouts(device_data, VkImage(image_handle), layouts)) {
2182c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski                    for (auto layout : layouts) {
2183c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski                        if (layout != VK_IMAGE_LAYOUT_PREINITIALIZED && layout != VK_IMAGE_LAYOUT_GENERAL) {
21843f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                            skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0,
21853f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                                            __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
2186b4a793e458e946f1218544264f2bf73be5444df5Michael Lentine                                            "Mapping an image with layout %s can result in undefined behavior if this memory is "
2187b4a793e458e946f1218544264f2bf73be5444df5Michael Lentine                                            "used by the device. Only GENERAL or PREINITIALIZED should be used.",
218809cd2c76808f1485206baeda9864f7ed907d7e05Mark Lobodzinski                                            string_VkImageLayout(layout));
2189c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski                        }
2190c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski                    }
2191c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski                }
2192c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski            }
2193c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski        }
2194c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski    }
219509cd2c76808f1485206baeda9864f7ed907d7e05Mark Lobodzinski    return skip;
2196c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski}
21973683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski
21983683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski// Helper function to validate correct usage bits set for buffers or images. Verify that (actual & desired) flags != 0 or, if strict
21993683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski// is true, verify that (actual & desired) flags == desired
2200abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinskistatic bool validate_usage_flags(layer_data *device_data, VkFlags actual, VkFlags desired, VkBool32 strict, uint64_t obj_handle,
22013683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski                                 VkDebugReportObjectTypeEXT obj_type, int32_t const msgCode, char const *ty_str,
22023683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski                                 char const *func_name, char const *usage_str) {
2203abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
22043683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski
22053683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    bool correct_usage = false;
2206abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinski    bool skip = false;
22073683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    if (strict) {
22083683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski        correct_usage = ((actual & desired) == desired);
22093683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    } else {
22103683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski        correct_usage = ((actual & desired) != 0);
22113683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    }
22123683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    if (!correct_usage) {
22133683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski        if (msgCode == -1) {
22143683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski            // TODO: Fix callers with msgCode == -1 to use correct validation checks.
22153f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton            skip = log_msg(
22163f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, obj_type, obj_handle, __LINE__, MEMTRACK_INVALID_USAGE_FLAG, "MEM",
22173f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                "Invalid usage flag for %s 0x%" PRIxLEAST64 " used by %s. In this case, %s should have %s set during creation.",
22183f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                ty_str, obj_handle, func_name, ty_str, usage_str);
22193683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski        } else {
22203683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski            const char *valid_usage = (msgCode == -1) ? "" : validation_error_map[msgCode];
2221abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinski            skip = log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, obj_type, obj_handle, __LINE__, msgCode, "MEM",
2222abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinski                           "Invalid usage flag for %s 0x%" PRIxLEAST64
2223abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinski                           " used by %s. In this case, %s should have %s set during creation. %s",
2224abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinski                           ty_str, obj_handle, func_name, ty_str, usage_str, valid_usage);
22253683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski        }
22263683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    }
2227abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinski    return skip;
22283683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski}
22293683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski
22303683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski// Helper function to validate usage flags for buffers. For given buffer_state send actual vs. desired usage off to helper above
22313683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski// where an error will be flagged if usage is not correct
2232abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinskibool ValidateImageUsageFlags(layer_data *device_data, IMAGE_STATE const *image_state, VkFlags desired, VkBool32 strict,
22333683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski                             int32_t const msgCode, char const *func_name, char const *usage_string) {
2234abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinski    return validate_usage_flags(device_data, image_state->createInfo.usage, desired, strict,
22353683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski                                reinterpret_cast<const uint64_t &>(image_state->image), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
22363683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski                                msgCode, "image", func_name, usage_string);
22373683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski}
22383683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski
22393683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski// Helper function to validate usage flags for buffers. For given buffer_state send actual vs. desired usage off to helper above
22403683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski// where an error will be flagged if usage is not correct
2241abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinskibool ValidateBufferUsageFlags(layer_data *device_data, BUFFER_STATE const *buffer_state, VkFlags desired, VkBool32 strict,
22423683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski                              int32_t const msgCode, char const *func_name, char const *usage_string) {
2243abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinski    return validate_usage_flags(device_data, buffer_state->createInfo.usage, desired, strict,
22443683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski                                reinterpret_cast<const uint64_t &>(buffer_state->buffer), VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT,
22453683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski                                msgCode, "buffer", func_name, usage_string);
22463683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski}
22473683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski
2248abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinskibool PreCallValidateCreateBuffer(layer_data *device_data, const VkBufferCreateInfo *pCreateInfo) {
22493683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    bool skip = false;
225001363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
225101363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski
22523683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    // TODO: Add check for VALIDATION_ERROR_00658
22533683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    // TODO: Add check for VALIDATION_ERROR_00667
22543683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    // TODO: Add check for VALIDATION_ERROR_00668
22553683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    // TODO: Add check for VALIDATION_ERROR_00669
225601363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski
225701363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski    if ((pCreateInfo->flags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT) && (!GetEnabledFeatures(device_data)->sparseBinding)) {
225801363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
225901363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski                        VALIDATION_ERROR_00666, "DS",
226001363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski                        "vkCreateBuffer(): the sparseBinding device feature is disabled: Buffers cannot be created with the "
226101363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski                        "VK_BUFFER_CREATE_SPARSE_BINDING_BIT set. %s",
226201363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski                        validation_error_map[VALIDATION_ERROR_00666]);
226301363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski    }
2264f575247dabffb70e4de1a6f9522db3f09a55492eMark Lobodzinski
2265f575247dabffb70e4de1a6f9522db3f09a55492eMark Lobodzinski    if ((pCreateInfo->flags & VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT) && (!GetEnabledFeatures(device_data)->sparseResidencyBuffer)) {
2266f575247dabffb70e4de1a6f9522db3f09a55492eMark Lobodzinski        skip |=
2267f575247dabffb70e4de1a6f9522db3f09a55492eMark Lobodzinski            log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
2268f575247dabffb70e4de1a6f9522db3f09a55492eMark Lobodzinski                    DRAWSTATE_INVALID_FEATURE, "DS",
2269f575247dabffb70e4de1a6f9522db3f09a55492eMark Lobodzinski                    "vkCreateBuffer(): the sparseResidencyBuffer device feature is disabled: Buffers cannot be created with the "
2270f575247dabffb70e4de1a6f9522db3f09a55492eMark Lobodzinski                    "VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT set.");
2271f575247dabffb70e4de1a6f9522db3f09a55492eMark Lobodzinski    }
22727e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski
22737e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski    if ((pCreateInfo->flags & VK_BUFFER_CREATE_SPARSE_ALIASED_BIT) && (!GetEnabledFeatures(device_data)->sparseResidencyAliased)) {
22747e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski        skip |=
22757e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski            log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
22767e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski                    DRAWSTATE_INVALID_FEATURE, "DS",
22777e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski                    "vkCreateBuffer(): the sparseResidencyAliased device feature is disabled: Buffers cannot be created with the "
22787e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski                    "VK_BUFFER_CREATE_SPARSE_ALIASED_BIT set.");
22797e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski    }
22803683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    return skip;
22813683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski}
22823683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski
22833683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinskivoid PostCallRecordCreateBuffer(layer_data *device_data, const VkBufferCreateInfo *pCreateInfo, VkBuffer *pBuffer) {
22843683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    // TODO : This doesn't create deep copy of pQueueFamilyIndices so need to fix that if/when we want that data to be valid
22853683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    GetBufferMap(device_data)
22863683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski        ->insert(std::make_pair(*pBuffer, std::unique_ptr<BUFFER_STATE>(new BUFFER_STATE(*pBuffer, pCreateInfo))));
22873683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski}
22883683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski
2289abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinskibool PreCallValidateCreateBufferView(layer_data *device_data, const VkBufferViewCreateInfo *pCreateInfo) {
2290abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinski    bool skip = false;
2291abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinski    BUFFER_STATE *buffer_state = GetBufferState(device_data, pCreateInfo->buffer);
22923683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    // If this isn't a sparse buffer, it needs to have memory backing it at CreateBufferView time
22933683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    if (buffer_state) {
2294abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinski        skip |= ValidateMemoryIsBoundToBuffer(device_data, buffer_state, "vkCreateBufferView()", VALIDATION_ERROR_02522);
22953683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski        // In order to create a valid buffer view, the buffer must have been created with at least one of the following flags:
22963683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski        // UNIFORM_TEXEL_BUFFER_BIT or STORAGE_TEXEL_BUFFER_BIT
2297abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinski        skip |= ValidateBufferUsageFlags(
2298abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinski            device_data, buffer_state, VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT, false,
22993683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski            VALIDATION_ERROR_00694, "vkCreateBufferView()", "VK_BUFFER_USAGE_[STORAGE|UNIFORM]_TEXEL_BUFFER_BIT");
23003683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    }
2301abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinski    return skip;
23023683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski}
23033683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski
23043683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinskivoid PostCallRecordCreateBufferView(layer_data *device_data, const VkBufferViewCreateInfo *pCreateInfo, VkBufferView *pView) {
23053683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    (*GetBufferViewMap(device_data))[*pView] = std::unique_ptr<BUFFER_VIEW_STATE>(new BUFFER_VIEW_STATE(*pView, pCreateInfo));
23063683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski}
23071c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski
23081c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski// For the given format verify that the aspect masks make sense
23091c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinskibool ValidateImageAspectMask(layer_data *device_data, VkImage image, VkFormat format, VkImageAspectFlags aspect_mask,
23101c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                             const char *func_name) {
23111c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
23121c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    bool skip = false;
23131c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    if (vk_format_is_color(format)) {
23141c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        if ((aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT) != VK_IMAGE_ASPECT_COLOR_BIT) {
23151c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, (uint64_t)image,
23161c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            __LINE__, VALIDATION_ERROR_00741, "IMAGE",
23171c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            "%s: Color image formats must have the VK_IMAGE_ASPECT_COLOR_BIT set. %s", func_name,
23181c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            validation_error_map[VALIDATION_ERROR_00741]);
23191c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        } else if ((aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT) != aspect_mask) {
23201c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, (uint64_t)image,
23211c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            __LINE__, VALIDATION_ERROR_00741, "IMAGE",
23221c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            "%s: Color image formats must have ONLY the VK_IMAGE_ASPECT_COLOR_BIT set. %s", func_name,
23231c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            validation_error_map[VALIDATION_ERROR_00741]);
23241c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        }
23251c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    } else if (vk_format_is_depth_and_stencil(format)) {
23261c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        if ((aspect_mask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) == 0) {
23271c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, (uint64_t)image,
23281c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            __LINE__, VALIDATION_ERROR_00741, "IMAGE",
23291c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            "%s: Depth/stencil image formats must have "
23301c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            "at least one of VK_IMAGE_ASPECT_DEPTH_BIT "
23311c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            "and VK_IMAGE_ASPECT_STENCIL_BIT set. %s",
23321c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            func_name, validation_error_map[VALIDATION_ERROR_00741]);
23331c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        } else if ((aspect_mask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) != aspect_mask) {
23341c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, (uint64_t)image,
23351c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            __LINE__, VALIDATION_ERROR_00741, "IMAGE",
23361c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            "%s: Combination depth/stencil image formats can have only the VK_IMAGE_ASPECT_DEPTH_BIT and "
23371c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            "VK_IMAGE_ASPECT_STENCIL_BIT set. %s",
23381c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            func_name, validation_error_map[VALIDATION_ERROR_00741]);
23391c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        }
23401c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    } else if (vk_format_is_depth_only(format)) {
23411c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        if ((aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) != VK_IMAGE_ASPECT_DEPTH_BIT) {
23421c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, (uint64_t)image,
23431c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            __LINE__, VALIDATION_ERROR_00741, "IMAGE",
23441c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            "%s: Depth-only image formats must have the VK_IMAGE_ASPECT_DEPTH_BIT set. %s", func_name,
23451c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            validation_error_map[VALIDATION_ERROR_00741]);
23461c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        } else if ((aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) != aspect_mask) {
23471c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, (uint64_t)image,
23481c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            __LINE__, VALIDATION_ERROR_00741, "IMAGE",
23491c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            "%s: Depth-only image formats can have only the VK_IMAGE_ASPECT_DEPTH_BIT set. %s", func_name,
23501c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            validation_error_map[VALIDATION_ERROR_00741]);
23511c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        }
23521c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    } else if (vk_format_is_stencil_only(format)) {
23531c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        if ((aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT) != VK_IMAGE_ASPECT_STENCIL_BIT) {
23541c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, (uint64_t)image,
23551c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            __LINE__, VALIDATION_ERROR_00741, "IMAGE",
23561c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            "%s: Stencil-only image formats must have the VK_IMAGE_ASPECT_STENCIL_BIT set. %s", func_name,
23571c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            validation_error_map[VALIDATION_ERROR_00741]);
23581c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        } else if ((aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT) != aspect_mask) {
23591c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, (uint64_t)image,
23601c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            __LINE__, VALIDATION_ERROR_00741, "IMAGE",
23611c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            "%s: Stencil-only image formats can have only the VK_IMAGE_ASPECT_STENCIL_BIT set. %s", func_name,
23621c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            validation_error_map[VALIDATION_ERROR_00741]);
23631c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        }
23641c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    }
23651c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    return skip;
23661c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski}
23671c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski
23681c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinskibool ValidateImageSubrangeLevelLayerCounts(layer_data *device_data, const VkImageSubresourceRange &subresourceRange,
23691c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                                           const char *func_name) {
23701c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
23711c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    bool skip = false;
23721c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    if (subresourceRange.levelCount == 0) {
23731c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
23741c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                        VALIDATION_ERROR_00768, "IMAGE", "%s called with 0 in subresourceRange.levelCount. %s", func_name,
23751c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                        validation_error_map[VALIDATION_ERROR_00768]);
23761c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    }
23771c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    if (subresourceRange.layerCount == 0) {
23781c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
23791c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                        VALIDATION_ERROR_00769, "IMAGE", "%s called with 0 in subresourceRange.layerCount. %s", func_name,
23801c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                        validation_error_map[VALIDATION_ERROR_00769]);
23811c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    }
23821c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    return skip;
23831c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski}
23841c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski
23851c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinskibool PreCallValidateCreateImageView(layer_data *device_data, const VkImageViewCreateInfo *create_info) {
23861c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
23871c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    bool skip = false;
23881c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    IMAGE_STATE *image_state = GetImageState(device_data, create_info->image);
23891c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    if (image_state) {
23901c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        skip |= ValidateImageUsageFlags(
23911c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            device_data, image_state,
23921c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT |
23931c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
23941c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            false, -1, "vkCreateImageView()",
23951c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            "VK_IMAGE_USAGE_[SAMPLED|STORAGE|COLOR_ATTACHMENT|DEPTH_STENCIL_ATTACHMENT|INPUT_ATTACHMENT]_BIT");
23961c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        // If this isn't a sparse image, it needs to have memory backing it at CreateImageView time
23971c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        skip |= ValidateMemoryIsBoundToImage(device_data, image_state, "vkCreateImageView()", VALIDATION_ERROR_02524);
23981c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        // Checks imported from image layer
23991c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        if (create_info->subresourceRange.baseMipLevel >= image_state->createInfo.mipLevels) {
24001c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            std::stringstream ss;
24011c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            ss << "vkCreateImageView called with baseMipLevel " << create_info->subresourceRange.baseMipLevel << " for image "
24021c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski               << create_info->image << " that only has " << image_state->createInfo.mipLevels << " mip levels.";
24031c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            skip |=
24041c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
24051c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                        VALIDATION_ERROR_00768, "IMAGE", "%s %s", ss.str().c_str(), validation_error_map[VALIDATION_ERROR_00768]);
24061c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        }
24071c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        if (create_info->subresourceRange.baseArrayLayer >= image_state->createInfo.arrayLayers) {
24081c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            std::stringstream ss;
24091c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            ss << "vkCreateImageView called with baseArrayLayer " << create_info->subresourceRange.baseArrayLayer << " for image "
24101c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski               << create_info->image << " that only has " << image_state->createInfo.arrayLayers << " array layers.";
24111c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            skip |=
24121c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
24131c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                        VALIDATION_ERROR_00769, "IMAGE", "%s %s", ss.str().c_str(), validation_error_map[VALIDATION_ERROR_00769]);
24141c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        }
24151c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        // TODO: Need new valid usage language for levelCount == 0 & layerCount == 0
24161c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        skip |= ValidateImageSubrangeLevelLayerCounts(device_data, create_info->subresourceRange, "vkCreateImageView()");
24171c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski
24181c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        VkImageCreateFlags image_flags = image_state->createInfo.flags;
24191c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        VkFormat image_format = image_state->createInfo.format;
24201c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        VkFormat view_format = create_info->format;
24211c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        VkImageAspectFlags aspect_mask = create_info->subresourceRange.aspectMask;
24221c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski
24231c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        // Validate VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT state
24241c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        if (image_flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) {
24251c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            // Format MUST be compatible (in the same format compatibility class) as the format the image was created with
24261c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            if (vk_format_get_compatibility_class(image_format) != vk_format_get_compatibility_class(view_format)) {
24271c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                std::stringstream ss;
24281c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                ss << "vkCreateImageView(): ImageView format " << string_VkFormat(view_format)
24291c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                   << " is not in the same format compatibility class as image (" << (uint64_t)create_info->image << ")  format "
24301c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                   << string_VkFormat(image_format) << ".  Images created with the VK_IMAGE_CREATE_MUTABLE_FORMAT BIT "
24311c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                   << "can support ImageViews with differing formats but they must be in the same compatibility class.";
24321c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
24331c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                                VALIDATION_ERROR_02171, "IMAGE", "%s %s", ss.str().c_str(),
24341c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                                validation_error_map[VALIDATION_ERROR_02171]);
24351c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            }
24361c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        } else {
24371c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            // Format MUST be IDENTICAL to the format the image was created with
24381c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            if (image_format != view_format) {
24391c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                std::stringstream ss;
24401c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                ss << "vkCreateImageView() format " << string_VkFormat(view_format) << " differs from image "
24411c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                   << (uint64_t)create_info->image << " format " << string_VkFormat(image_format)
24421c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                   << ".  Formats MUST be IDENTICAL unless VK_IMAGE_CREATE_MUTABLE_FORMAT BIT was set on image creation.";
24431c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
24441c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                                VALIDATION_ERROR_02172, "IMAGE", "%s %s", ss.str().c_str(),
24451c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                                validation_error_map[VALIDATION_ERROR_02172]);
24461c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            }
24471c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        }
24481c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski
24491c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        // Validate correct image aspect bits for desired formats and format consistency
24501c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        skip |= ValidateImageAspectMask(device_data, image_state->image, image_format, aspect_mask, "vkCreateImageView()");
24511c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    }
24521c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    return skip;
24531c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski}
24541c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski
2455d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinskivoid PostCallRecordCreateImageView(layer_data *device_data, const VkImageViewCreateInfo *create_info, VkImageView view) {
2456d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski    auto image_view_map = GetImageViewMap(device_data);
2457d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski    (*image_view_map)[view] = std::unique_ptr<IMAGE_VIEW_STATE>(new IMAGE_VIEW_STATE(view, create_info));
2458d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski
2459d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski    auto image_state = GetImageState(device_data, create_info->image);
24606677fd2fa2aca17ab772da98cfe69852fb47bdbcPetr Kraus    auto& sub_res_range = (*image_view_map)[view].get()->create_info.subresourceRange;
2461d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski    ResolveRemainingLevelsLayers(device_data, &sub_res_range, image_state);
24621c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski}
24636a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
2464c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinskibool PreCallValidateCmdCopyBuffer(layer_data *device_data, GLOBAL_CB_NODE *cb_node, BUFFER_STATE *src_buffer_state,
2465c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski                                  BUFFER_STATE *dst_buffer_state) {
2466c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    bool skip = false;
2467c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    skip |= ValidateMemoryIsBoundToBuffer(device_data, src_buffer_state, "vkCmdCopyBuffer()", VALIDATION_ERROR_02531);
2468c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    skip |= ValidateMemoryIsBoundToBuffer(device_data, dst_buffer_state, "vkCmdCopyBuffer()", VALIDATION_ERROR_02532);
2469c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    // Validate that SRC & DST buffers have correct usage flags set
2470c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    skip |= ValidateBufferUsageFlags(device_data, src_buffer_state, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, true, VALIDATION_ERROR_01164,
2471c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski                                     "vkCmdCopyBuffer()", "VK_BUFFER_USAGE_TRANSFER_SRC_BIT");
2472c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    skip |= ValidateBufferUsageFlags(device_data, dst_buffer_state, VK_BUFFER_USAGE_TRANSFER_DST_BIT, true, VALIDATION_ERROR_01165,
2473c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski                                     "vkCmdCopyBuffer()", "VK_BUFFER_USAGE_TRANSFER_DST_BIT");
2474c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    skip |= ValidateCmd(device_data, cb_node, CMD_COPYBUFFER, "vkCmdCopyBuffer()");
2475c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    skip |= insideRenderPass(device_data, cb_node, "vkCmdCopyBuffer()", VALIDATION_ERROR_01172);
2476c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    return skip;
2477c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski}
24786a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
2479c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinskivoid PreCallRecordCmdCopyBuffer(layer_data *device_data, GLOBAL_CB_NODE *cb_node, BUFFER_STATE *src_buffer_state,
2480c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski                                BUFFER_STATE *dst_buffer_state) {
2481c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    // Update bindings between buffers and cmd buffer
2482c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    AddCommandBufferBindingBuffer(device_data, cb_node, src_buffer_state);
2483c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    AddCommandBufferBindingBuffer(device_data, cb_node, dst_buffer_state);
2484c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski
2485c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    std::function<bool()> function = [=]() {
2486c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski        return ValidateBufferMemoryIsValid(device_data, src_buffer_state, "vkCmdCopyBuffer()");
2487c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    };
2488c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    cb_node->validate_functions.push_back(function);
2489c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    function = [=]() {
2490c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski        SetBufferMemoryValid(device_data, dst_buffer_state, true);
2491c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski        return false;
2492c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    };
2493c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    cb_node->validate_functions.push_back(function);
2494c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    core_validation::UpdateCmdBufferLastCmd(cb_node, CMD_COPYBUFFER);
2495c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski}
2496842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski
2497842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinskistatic bool validateIdleBuffer(layer_data *device_data, VkBuffer buffer) {
2498842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
2499842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    bool skip = false;
2500842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    auto buffer_state = GetBufferState(device_data, buffer);
2501842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    if (!buffer_state) {
2502842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, (uint64_t)(buffer),
2503842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski                        __LINE__, DRAWSTATE_DOUBLE_DESTROY, "DS",
2504842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski                        "Cannot free buffer 0x%" PRIxLEAST64 " that has not been allocated.", (uint64_t)(buffer));
2505842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    } else {
2506842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski        if (buffer_state->in_use.load()) {
2507842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, (uint64_t)(buffer),
2508842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski                            __LINE__, VALIDATION_ERROR_00676, "DS",
2509842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski                            "Cannot free buffer 0x%" PRIxLEAST64 " that is in use by a command buffer. %s", (uint64_t)(buffer),
2510842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski                            validation_error_map[VALIDATION_ERROR_00676]);
2511842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski        }
2512842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    }
2513842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    return skip;
2514842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski}
2515842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski
2516842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinskibool PreCallValidateDestroyImageView(layer_data *device_data, VkImageView image_view, IMAGE_VIEW_STATE **image_view_state,
2517842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski                                     VK_OBJECT *obj_struct) {
2518842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    *image_view_state = GetImageViewState(device_data, image_view);
2519842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    *obj_struct = {reinterpret_cast<uint64_t &>(image_view), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT};
2520842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    if (GetDisables(device_data)->destroy_image_view) return false;
2521842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    bool skip = false;
2522842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    if (*image_view_state) {
2523842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski        skip |= ValidateObjectNotInUse(device_data, *image_view_state, *obj_struct, VALIDATION_ERROR_00776);
2524842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    }
2525842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    return skip;
2526842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski}
2527842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski
2528842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinskivoid PostCallRecordDestroyImageView(layer_data *device_data, VkImageView image_view, IMAGE_VIEW_STATE *image_view_state,
2529842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski                                    VK_OBJECT obj_struct) {
2530842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    // Any bound cmd buffers are now invalid
2531842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    invalidateCommandBuffers(device_data, image_view_state->cb_bindings, obj_struct);
2532842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    (*GetImageViewMap(device_data)).erase(image_view);
2533842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski}
2534842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski
2535842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinskibool PreCallValidateDestroyBuffer(layer_data *device_data, VkBuffer buffer, BUFFER_STATE **buffer_state, VK_OBJECT *obj_struct) {
2536842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    *buffer_state = GetBufferState(device_data, buffer);
2537842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    *obj_struct = {reinterpret_cast<uint64_t &>(buffer), VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT};
2538842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    if (GetDisables(device_data)->destroy_buffer) return false;
2539842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    bool skip = false;
2540842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    if (*buffer_state) {
2541842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski        skip |= validateIdleBuffer(device_data, buffer);
2542842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    }
2543842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    return skip;
2544842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski}
2545842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski
2546842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinskivoid PostCallRecordDestroyBuffer(layer_data *device_data, VkBuffer buffer, BUFFER_STATE *buffer_state, VK_OBJECT obj_struct) {
2547842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    invalidateCommandBuffers(device_data, buffer_state->cb_bindings, obj_struct);
2548842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    for (auto mem_binding : buffer_state->GetBoundMemory()) {
2549842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski        auto mem_info = GetMemObjInfo(device_data, mem_binding);
2550842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski        if (mem_info) {
2551842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski            core_validation::RemoveBufferMemoryRange(reinterpret_cast<uint64_t &>(buffer), mem_info);
2552842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski        }
2553842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    }
2554842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    ClearMemoryObjectBindings(device_data, reinterpret_cast<uint64_t &>(buffer), VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT);
2555842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    GetBufferMap(device_data)->erase(buffer_state->buffer);
2556842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski}
2557842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski
2558842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinskibool PreCallValidateDestroyBufferView(layer_data *device_data, VkBufferView buffer_view, BUFFER_VIEW_STATE **buffer_view_state,
2559842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski                                      VK_OBJECT *obj_struct) {
2560842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    *buffer_view_state = GetBufferViewState(device_data, buffer_view);
2561842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    *obj_struct = {reinterpret_cast<uint64_t &>(buffer_view), VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT};
2562842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    if (GetDisables(device_data)->destroy_buffer_view) return false;
2563842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    bool skip = false;
2564842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    if (*buffer_view_state) {
2565842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski        skip |= ValidateObjectNotInUse(device_data, *buffer_view_state, *obj_struct, VALIDATION_ERROR_00701);
2566842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    }
2567842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    return skip;
2568842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski}
2569842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski
2570842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinskivoid PostCallRecordDestroyBufferView(layer_data *device_data, VkBufferView buffer_view, BUFFER_VIEW_STATE *buffer_view_state,
2571842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski                                     VK_OBJECT obj_struct) {
2572842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    // Any bound cmd buffers are now invalid
2573842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    invalidateCommandBuffers(device_data, buffer_view_state->cb_bindings, obj_struct);
2574842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    GetBufferViewMap(device_data)->erase(buffer_view);
2575842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski}
257623bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski
257723bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinskibool PreCallValidateCmdFillBuffer(layer_data *device_data, GLOBAL_CB_NODE *cb_node, BUFFER_STATE *buffer_state) {
257823bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski    bool skip = false;
257923bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski    skip |= ValidateMemoryIsBoundToBuffer(device_data, buffer_state, "vkCmdFillBuffer()", VALIDATION_ERROR_02529);
258023bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski    skip |= ValidateCmd(device_data, cb_node, CMD_FILLBUFFER, "vkCmdFillBuffer()");
258123bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski    // Validate that DST buffer has correct usage flags set
258223bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski    skip |= ValidateBufferUsageFlags(device_data, buffer_state, VK_BUFFER_USAGE_TRANSFER_DST_BIT, true, VALIDATION_ERROR_01137,
258323bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski                                     "vkCmdFillBuffer()", "VK_BUFFER_USAGE_TRANSFER_DST_BIT");
258423bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski    skip |= insideRenderPass(device_data, cb_node, "vkCmdFillBuffer()", VALIDATION_ERROR_01142);
258523bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski    return skip;
258623bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski}
258723bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski
258823bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinskivoid PreCallRecordCmdFillBuffer(layer_data *device_data, GLOBAL_CB_NODE *cb_node, BUFFER_STATE *buffer_state) {
258923bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski    std::function<bool()> function = [=]() {
259023bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski        SetBufferMemoryValid(device_data, buffer_state, true);
259123bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski        return false;
259223bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski    };
259323bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski    cb_node->validate_functions.push_back(function);
259423bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski    // Update bindings between buffer and cmd buffer
259523bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski    AddCommandBufferBindingBuffer(device_data, cb_node, buffer_state);
259623bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski    core_validation::UpdateCmdBufferLastCmd(cb_node, CMD_FILLBUFFER);
259723bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski}
2598877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski
259971c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinskibool ValidateBufferImageCopyData(const debug_report_data *report_data, uint32_t regionCount, const VkBufferImageCopy *pRegions,
260071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                                 IMAGE_STATE *image_state, const char *function) {
2601877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski    bool skip = false;
2602877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski
2603877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski    for (uint32_t i = 0; i < regionCount; i++) {
26045971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        if (image_state->createInfo.imageType == VK_IMAGE_TYPE_1D) {
26055971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            if ((pRegions[i].imageOffset.y != 0) || (pRegions[i].imageExtent.height != 1)) {
26065971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
26075971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01746, "IMAGE",
26085971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                "%s(): pRegion[%d] imageOffset.y is %d and imageExtent.height is %d. For 1D images these "
26095971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                "must be 0 and 1, respectively. %s",
26105971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                function, i, pRegions[i].imageOffset.y, pRegions[i].imageExtent.height,
26115971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                validation_error_map[VALIDATION_ERROR_01746]);
2612877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski            }
26135971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        }
2614877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski
26155971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        if ((image_state->createInfo.imageType == VK_IMAGE_TYPE_1D) || (image_state->createInfo.imageType == VK_IMAGE_TYPE_2D)) {
26165971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            if ((pRegions[i].imageOffset.z != 0) || (pRegions[i].imageExtent.depth != 1)) {
2617877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
26185971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01747, "IMAGE",
26195971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                "%s(): pRegion[%d] imageOffset.z is %d and imageExtent.depth is %d. For 1D and 2D images these "
26205971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                "must be 0 and 1, respectively. %s",
26215971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                function, i, pRegions[i].imageOffset.z, pRegions[i].imageExtent.depth,
26225971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                validation_error_map[VALIDATION_ERROR_01747]);
2623877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski            }
26245971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        }
2625877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski
26265971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        if (image_state->createInfo.imageType == VK_IMAGE_TYPE_3D) {
26275971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            if ((0 != pRegions[i].imageSubresource.baseArrayLayer) || (1 != pRegions[i].imageSubresource.layerCount)) {
2628877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
26295971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01281, "IMAGE",
26305971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                "%s(): pRegion[%d] imageSubresource.baseArrayLayer is %d and imageSubresource.layerCount is "
26315971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                "%d. For 3D images these must be 0 and 1, respectively. %s",
26325971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                function, i, pRegions[i].imageSubresource.baseArrayLayer, pRegions[i].imageSubresource.layerCount,
26335971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                validation_error_map[VALIDATION_ERROR_01281]);
2634877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski            }
26355971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        }
2636877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski
26375971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        // If the the calling command's VkImage parameter's format is not a depth/stencil format,
26385971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        // then bufferOffset must be a multiple of the calling command's VkImage parameter's texel size
26395971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        auto texel_size = vk_format_get_size(image_state->createInfo.format);
26405971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        if (!vk_format_is_depth_and_stencil(image_state->createInfo.format) &&
26415971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            vk_safe_modulo(pRegions[i].bufferOffset, texel_size) != 0) {
26425971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
26435971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                            reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01263, "IMAGE",
26445971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                            "%s(): pRegion[%d] bufferOffset 0x%" PRIxLEAST64
26455971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                            " must be a multiple of this format's texel size (" PRINTF_SIZE_T_SPECIFIER "). %s",
26465971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                            function, i, pRegions[i].bufferOffset, texel_size, validation_error_map[VALIDATION_ERROR_01263]);
26475971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        }
26485971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton
26495971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        //  BufferOffset must be a multiple of 4
26505971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        if (vk_safe_modulo(pRegions[i].bufferOffset, 4) != 0) {
26515971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
26525971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                            reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01264, "IMAGE",
26535971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                            "%s(): pRegion[%d] bufferOffset 0x%" PRIxLEAST64 " must be a multiple of 4. %s", function, i,
26545971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                            pRegions[i].bufferOffset, validation_error_map[VALIDATION_ERROR_01264]);
26555971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        }
26565971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton
26575971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        //  BufferRowLength must be 0, or greater than or equal to the width member of imageExtent
26585971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        if ((pRegions[i].bufferRowLength != 0) && (pRegions[i].bufferRowLength < pRegions[i].imageExtent.width)) {
26595971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            skip |= log_msg(
26605971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
26615971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01265, "IMAGE",
26625971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                "%s(): pRegion[%d] bufferRowLength (%d) must be zero or greater-than-or-equal-to imageExtent.width (%d). %s",
26635971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                function, i, pRegions[i].bufferRowLength, pRegions[i].imageExtent.width,
26645971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                validation_error_map[VALIDATION_ERROR_01265]);
26655971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        }
26665971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton
26675971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        //  BufferImageHeight must be 0, or greater than or equal to the height member of imageExtent
26685971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        if ((pRegions[i].bufferImageHeight != 0) && (pRegions[i].bufferImageHeight < pRegions[i].imageExtent.height)) {
26695971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            skip |= log_msg(
26705971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
26715971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01266, "IMAGE",
26725971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                "%s(): pRegion[%d] bufferImageHeight (%d) must be zero or greater-than-or-equal-to imageExtent.height (%d). %s",
26735971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                function, i, pRegions[i].bufferImageHeight, pRegions[i].imageExtent.height,
26745971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                validation_error_map[VALIDATION_ERROR_01266]);
26755971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        }
26765971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton
26775971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        // subresource aspectMask must have exactly 1 bit set
26785971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        const int num_bits = sizeof(VkFlags) * CHAR_BIT;
26795971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        std::bitset<num_bits> aspect_mask_bits(pRegions[i].imageSubresource.aspectMask);
26805971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        if (aspect_mask_bits.count() != 1) {
26815971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
26825971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                            reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01280, "IMAGE",
26835971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                            "%s: aspectMasks for imageSubresource in each region must have only a single bit set. %s", function,
26845971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                            validation_error_map[VALIDATION_ERROR_01280]);
26855971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        }
26865971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton
26875971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        // image subresource aspect bit must match format
26885971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        if (((0 != (pRegions[i].imageSubresource.aspectMask & VK_IMAGE_ASPECT_COLOR_BIT)) &&
26895971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton             (!vk_format_is_color(image_state->createInfo.format))) ||
26905971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            ((0 != (pRegions[i].imageSubresource.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT)) &&
26915971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton             (!vk_format_has_depth(image_state->createInfo.format))) ||
26925971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            ((0 != (pRegions[i].imageSubresource.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT)) &&
26935971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton             (!vk_format_has_stencil(image_state->createInfo.format)))) {
26945971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            skip |= log_msg(
26955971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
26965971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01279, "IMAGE",
26975971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                "%s(): pRegion[%d] subresource aspectMask 0x%x specifies aspects that are not present in image format 0x%x. %s",
26985971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                function, i, pRegions[i].imageSubresource.aspectMask, image_state->createInfo.format,
26995971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                validation_error_map[VALIDATION_ERROR_01279]);
27005971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        }
27015971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton
27025971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        // Checks that apply only to compressed images
27035971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        // TODO: there is a comment in ValidateCopyBufferImageTransferGranularityRequirements() in core_validation.cpp that
27045971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        //       reserves a place for these compressed image checks.  This block of code could move there once the image
27055971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        //       stuff is moved into core validation.
27065971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        if (vk_format_is_compressed(image_state->createInfo.format)) {
27075971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            auto block_size = vk_format_compressed_texel_block_extents(image_state->createInfo.format);
2708877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski
27095971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            //  BufferRowLength must be a multiple of block width
27105971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            if (vk_safe_modulo(pRegions[i].bufferRowLength, block_size.width) != 0) {
2711877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski                skip |= log_msg(
2712877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski                    report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
27135971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                    reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01271, "IMAGE",
27145971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                    "%s(): pRegion[%d] bufferRowLength (%d) must be a multiple of the compressed image's texel width (%d). %s.",
27155971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                    function, i, pRegions[i].bufferRowLength, block_size.width, validation_error_map[VALIDATION_ERROR_01271]);
2716877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski            }
2717877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski
27185971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            //  BufferRowHeight must be a multiple of block height
27195971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            if (vk_safe_modulo(pRegions[i].bufferImageHeight, block_size.height) != 0) {
2720877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
27215971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01272, "IMAGE",
27225971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                "%s(): pRegion[%d] bufferImageHeight (%d) must be a multiple of the compressed image's texel "
27235971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                "height (%d). %s.",
27245971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                function, i, pRegions[i].bufferImageHeight, block_size.height,
27255971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                validation_error_map[VALIDATION_ERROR_01272]);
2726877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski            }
2727877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski
27285971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            //  image offsets must be multiples of block dimensions
27295971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            if ((vk_safe_modulo(pRegions[i].imageOffset.x, block_size.width) != 0) ||
2730045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                (vk_safe_modulo(pRegions[i].imageOffset.y, block_size.height) != 0) ||
2731045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                (vk_safe_modulo(pRegions[i].imageOffset.z, block_size.depth) != 0)) {
27325971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
27335971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01273, "IMAGE",
27345971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                "%s(): pRegion[%d] imageOffset(x,y) (%d, %d) must be multiples of the compressed image's texel "
27355971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                "width & height (%d, %d). %s.",
27365971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                function, i, pRegions[i].imageOffset.x, pRegions[i].imageOffset.y, block_size.width,
27375971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                block_size.height, validation_error_map[VALIDATION_ERROR_01273]);
2738877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski            }
2739877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski
27405971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            // bufferOffset must be a multiple of block size (linear bytes)
27415971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            size_t block_size_in_bytes = vk_format_get_size(image_state->createInfo.format);
27425971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            if (vk_safe_modulo(pRegions[i].bufferOffset, block_size_in_bytes) != 0) {
27435971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
27445971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01274, "IMAGE",
27455971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                "%s(): pRegion[%d] bufferOffset (0x%" PRIxLEAST64
27465971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                ") must be a multiple of the compressed image's texel block "
27475971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                "size (" PRINTF_SIZE_T_SPECIFIER "). %s.",
27485971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                function, i, pRegions[i].bufferOffset, block_size_in_bytes,
27495971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                validation_error_map[VALIDATION_ERROR_01274]);
2750877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski            }
27512cd49094dcd399721f50c123413b8f55693348d7Dave Houlton
27522cd49094dcd399721f50c123413b8f55693348d7Dave Houlton            // imageExtent width must be a multiple of block width, or extent+offset width must equal subresource width
2753045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton            VkExtent3D mip_extent = GetImageSubresourceExtent(image_state, &(pRegions[i].imageSubresource));
27542cd49094dcd399721f50c123413b8f55693348d7Dave Houlton            if ((vk_safe_modulo(pRegions[i].imageExtent.width, block_size.width) != 0) &&
2755045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                (pRegions[i].imageExtent.width + pRegions[i].imageOffset.x != mip_extent.width)) {
2756045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
2757045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                                reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01275, "IMAGE",
2758045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                                "%s(): pRegion[%d] extent width (%d) must be a multiple of the compressed texture block width "
2759045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                                "(%d), or when added to offset.x (%d) must equal the image subresource width (%d). %s.",
2760045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                                function, i, pRegions[i].imageExtent.width, block_size.width, pRegions[i].imageOffset.x,
2761045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                                mip_extent.width, validation_error_map[VALIDATION_ERROR_01275]);
27622cd49094dcd399721f50c123413b8f55693348d7Dave Houlton            }
27632cd49094dcd399721f50c123413b8f55693348d7Dave Houlton
27642cd49094dcd399721f50c123413b8f55693348d7Dave Houlton            // imageExtent height must be a multiple of block height, or extent+offset height must equal subresource height
27652cd49094dcd399721f50c123413b8f55693348d7Dave Houlton            if ((vk_safe_modulo(pRegions[i].imageExtent.height, block_size.height) != 0) &&
2766045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                (pRegions[i].imageExtent.height + pRegions[i].imageOffset.y != mip_extent.height)) {
2767045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
2768045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                                reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01276, "IMAGE",
2769045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                                "%s(): pRegion[%d] extent height (%d) must be a multiple of the compressed texture block height "
2770045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                                "(%d), or when added to offset.y (%d) must equal the image subresource height (%d). %s.",
2771045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                                function, i, pRegions[i].imageExtent.height, block_size.height, pRegions[i].imageOffset.y,
2772045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                                mip_extent.height, validation_error_map[VALIDATION_ERROR_01276]);
27732cd49094dcd399721f50c123413b8f55693348d7Dave Houlton            }
27742cd49094dcd399721f50c123413b8f55693348d7Dave Houlton
27752cd49094dcd399721f50c123413b8f55693348d7Dave Houlton            // imageExtent depth must be a multiple of block depth, or extent+offset depth must equal subresource depth
27762cd49094dcd399721f50c123413b8f55693348d7Dave Houlton            if ((vk_safe_modulo(pRegions[i].imageExtent.depth, block_size.depth) != 0) &&
2777045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                (pRegions[i].imageExtent.depth + pRegions[i].imageOffset.z != mip_extent.depth)) {
2778045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
2779045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                                reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01277, "IMAGE",
2780045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                                "%s(): pRegion[%d] extent width (%d) must be a multiple of the compressed texture block depth "
2781045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                                "(%d), or when added to offset.z (%d) must equal the image subresource depth (%d). %s.",
2782045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                                function, i, pRegions[i].imageExtent.depth, block_size.depth, pRegions[i].imageOffset.z,
2783045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                                mip_extent.depth, validation_error_map[VALIDATION_ERROR_01277]);
27842cd49094dcd399721f50c123413b8f55693348d7Dave Houlton            }
27855971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        }
278671c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    }
278771c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
278871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    return skip;
278971c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski}
279071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
27915971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houltonstatic bool ValidateImageBounds(const debug_report_data *report_data, const IMAGE_STATE *image_state, const uint32_t regionCount,
27925971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                const VkBufferImageCopy *pRegions, const char *func_name, UNIQUE_VALIDATION_ERROR_CODE msg_code) {
279371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    bool skip = false;
27945971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton    const VkImageCreateInfo *image_info = &(image_state->createInfo);
279571c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
279671c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    for (uint32_t i = 0; i < regionCount; i++) {
279771c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        VkExtent3D extent = pRegions[i].imageExtent;
279871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        VkOffset3D offset = pRegions[i].imageOffset;
279971c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
28005971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        if (IsExtentSizeZero(&extent))  // Warn on zero area subresource
28015971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        {
28025971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
28035971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                            (uint64_t)0, __LINE__, IMAGE_ZERO_AREA_SUBREGION, "IMAGE",
28045971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                            "%s: pRegion[%d] imageExtent of {%1d, %1d, %1d} has zero area", func_name, i, extent.width,
28055971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                            extent.height, extent.depth);
280671c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        }
280771c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
28085971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        VkExtent3D image_extent = GetImageSubresourceExtent(image_state, &(pRegions[i].imageSubresource));
28095971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton
28105971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        // If we're using a compressed format, valid extent is rounded up to multiple of block size (per 18.1)
28115971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        if (vk_format_is_compressed(image_info->format)) {
28125971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            auto block_extent = vk_format_compressed_texel_block_extents(image_info->format);
28135971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            if (image_extent.width % block_extent.width) {
28145971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                image_extent.width += (block_extent.width - (image_extent.width % block_extent.width));
28155971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            }
28165971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            if (image_extent.height % block_extent.height) {
28175971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                image_extent.height += (block_extent.height - (image_extent.height % block_extent.height));
28185971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            }
28195971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            if (image_extent.depth % block_extent.depth) {
28205971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                image_extent.depth += (block_extent.depth - (image_extent.depth % block_extent.depth));
28215971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            }
282271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        }
282371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
28245971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        if (ExceedsBounds(&offset, &extent, &image_extent)) {
282571c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)0,
28265971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                            __LINE__, msg_code, "IMAGE", "%s: pRegion[%d] exceeds image bounds. %s.", func_name, i,
282771c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                            validation_error_map[msg_code]);
2828877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski        }
2829877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski    }
2830877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski
2831877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski    return skip;
2832877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski}
2833877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski
283471c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinskistatic inline bool ValidtateBufferBounds(const debug_report_data *report_data, IMAGE_STATE *image_state, BUFFER_STATE *buff_state,
283571c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                                         uint32_t regionCount, const VkBufferImageCopy *pRegions, const char *func_name,
283671c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                                         UNIQUE_VALIDATION_ERROR_CODE msg_code) {
283771c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    bool skip = false;
283871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
283971c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    VkDeviceSize buffer_size = buff_state->createInfo.size;
284071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
284171c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    for (uint32_t i = 0; i < regionCount; i++) {
284271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        VkExtent3D copy_extent = pRegions[i].imageExtent;
284371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
284471c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        VkDeviceSize buffer_width = (0 == pRegions[i].bufferRowLength ? copy_extent.width : pRegions[i].bufferRowLength);
284571c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        VkDeviceSize buffer_height = (0 == pRegions[i].bufferImageHeight ? copy_extent.height : pRegions[i].bufferImageHeight);
284671c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        VkDeviceSize unit_size = vk_format_get_size(image_state->createInfo.format);  // size (bytes) of texel or block
284771c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
28481dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton        // Handle special buffer packing rules for specific depth/stencil formats
28491dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton        if (pRegions[i].imageSubresource.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) {
28501dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton            unit_size = vk_format_get_size(VK_FORMAT_S8_UINT);
28511dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton        } else if (pRegions[i].imageSubresource.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) {
28521dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton            switch (image_state->createInfo.format) {
28531dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton                case VK_FORMAT_D16_UNORM_S8_UINT:
28541dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton                    unit_size = vk_format_get_size(VK_FORMAT_D16_UNORM);
28551dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton                    break;
28561dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton                case VK_FORMAT_D32_SFLOAT_S8_UINT:
28571dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton                    unit_size = vk_format_get_size(VK_FORMAT_D32_SFLOAT);
28581dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton                    break;
28595971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                case VK_FORMAT_X8_D24_UNORM_PACK32:  // Fall through
28601dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton                case VK_FORMAT_D24_UNORM_S8_UINT:
28611dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton                    unit_size = 4;
28621dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton                    break;
28631dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton                default:
28641dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton                    break;
28651dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton            }
28661dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton        }
28671dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton
286871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        if (vk_format_is_compressed(image_state->createInfo.format)) {
28695971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            // Switch to texel block units, rounding up for any partially-used blocks
28705971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            auto block_dim = vk_format_compressed_texel_block_extents(image_state->createInfo.format);
28715971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            buffer_width = (buffer_width + block_dim.width - 1) / block_dim.width;
28725971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            buffer_height = (buffer_height + block_dim.height - 1) / block_dim.height;
287371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
28745971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            copy_extent.width = (copy_extent.width + block_dim.width - 1) / block_dim.width;
28755971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            copy_extent.height = (copy_extent.height + block_dim.height - 1) / block_dim.height;
28765971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            copy_extent.depth = (copy_extent.depth + block_dim.depth - 1) / block_dim.depth;
28775971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        }
287871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
28795971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        // Either depth or layerCount may be greater than 1 (not both). This is the number of 'slices' to copy
28805971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        uint32_t z_copies = std::max(copy_extent.depth, pRegions[i].imageSubresource.layerCount);
28815971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        if (IsExtentSizeZero(&copy_extent) || (0 == z_copies)) {
28825971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            // TODO: Issure warning here? Already warned in ValidateImageBounds()...
28835971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        } else {
28845971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            // Calculate buffer offset of final copied byte, + 1.
28855971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            VkDeviceSize max_buffer_offset = (z_copies - 1) * buffer_height * buffer_width;      // offset to slice
28865971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            max_buffer_offset += ((copy_extent.height - 1) * buffer_width) + copy_extent.width;  // add row,col
28875971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            max_buffer_offset *= unit_size;                                                      // convert to bytes
28885971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            max_buffer_offset += pRegions[i].bufferOffset;                                       // add initial offset (bytes)
288971c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
28905971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            if (buffer_size < max_buffer_offset) {
28915971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                skip |=
28925971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                    log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)0,
28935971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                            __LINE__, msg_code, "IMAGE", "%s: pRegion[%d] exceeds buffer size of %" PRIu64 " bytes. %s.", func_name,
28945971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                            i, buffer_size, validation_error_map[msg_code]);
28955971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            }
289671c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        }
289771c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    }
289871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
289971c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    return skip;
290071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski}
290171c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
290271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinskibool PreCallValidateCmdCopyImageToBuffer(layer_data *device_data, VkImageLayout srcImageLayout, GLOBAL_CB_NODE *cb_node,
2903940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski                                         IMAGE_STATE *src_image_state, BUFFER_STATE *dst_buffer_state, uint32_t regionCount,
2904877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski                                         const VkBufferImageCopy *pRegions, const char *func_name) {
290571c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
290671c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    bool skip = ValidateBufferImageCopyData(report_data, regionCount, pRegions, src_image_state, "vkCmdCopyImageToBuffer");
290771c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
290871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    // Validate command buffer state
290971c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    if (CB_RECORDING != cb_node->state) {
291071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
291171c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                        (uint64_t)cb_node->commandBuffer, __LINE__, VALIDATION_ERROR_01258, "DS",
291271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                        "Cannot call vkCmdCopyImageToBuffer() on command buffer which is not in recording state. %s.",
291371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                        validation_error_map[VALIDATION_ERROR_01258]);
291471c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    } else {
291571c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        skip |= ValidateCmdSubpassState(device_data, cb_node, CMD_COPYIMAGETOBUFFER);
291671c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    }
291771c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
291871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    // Command pool must support graphics, compute, or transfer operations
291971c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    auto pPool = GetCommandPoolNode(device_data, cb_node->createInfo.commandPool);
292071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
292171c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    VkQueueFlags queue_flags = GetPhysDevProperties(device_data)->queue_family_properties[pPool->queueFamilyIndex].queueFlags;
292271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    if (0 == (queue_flags & (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT))) {
292371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
292471c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                        (uint64_t)cb_node->createInfo.commandPool, __LINE__, VALIDATION_ERROR_01259, "DS",
292571c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                        "Cannot call vkCmdCopyImageToBuffer() on a command buffer allocated from a pool without graphics, compute, "
292671c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                        "or transfer capabilities. %s.",
292771c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                        validation_error_map[VALIDATION_ERROR_01259]);
292871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    }
29295971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton    skip |= ValidateImageBounds(report_data, src_image_state, regionCount, pRegions, "vkCmdCopyBufferToImage()",
293071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                                VALIDATION_ERROR_01245);
2931940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    skip |= ValidtateBufferBounds(report_data, src_image_state, dst_buffer_state, regionCount, pRegions, "vkCmdCopyImageToBuffer()",
293271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                                  VALIDATION_ERROR_01246);
293371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
293471c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    skip |= ValidateImageSampleCount(device_data, src_image_state, VK_SAMPLE_COUNT_1_BIT, "vkCmdCopyImageToBuffer(): srcImage",
293571c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                                     VALIDATION_ERROR_01249);
293671c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    skip |= ValidateMemoryIsBoundToImage(device_data, src_image_state, "vkCmdCopyImageToBuffer()", VALIDATION_ERROR_02537);
2937940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    skip |= ValidateMemoryIsBoundToBuffer(device_data, dst_buffer_state, "vkCmdCopyImageToBuffer()", VALIDATION_ERROR_02538);
2938d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski
293971c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    // Validate that SRC image & DST buffer have correct usage flags set
294071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    skip |= ValidateImageUsageFlags(device_data, src_image_state, VK_IMAGE_USAGE_TRANSFER_SRC_BIT, true, VALIDATION_ERROR_01248,
294171c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                                    "vkCmdCopyImageToBuffer()", "VK_IMAGE_USAGE_TRANSFER_SRC_BIT");
2942940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    skip |= ValidateBufferUsageFlags(device_data, dst_buffer_state, VK_BUFFER_USAGE_TRANSFER_DST_BIT, true, VALIDATION_ERROR_01252,
294371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                                     "vkCmdCopyImageToBuffer()", "VK_BUFFER_USAGE_TRANSFER_DST_BIT");
2944d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski    skip |= insideRenderPass(device_data, cb_node, "vkCmdCopyImageToBuffer()", VALIDATION_ERROR_01260);
2945d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski    for (uint32_t i = 0; i < regionCount; ++i) {
2946d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski        skip |= VerifySourceImageLayout(device_data, cb_node, src_image_state->image, pRegions[i].imageSubresource, srcImageLayout,
2947d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski                                        VALIDATION_ERROR_01251);
2948d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski        skip |= ValidateCopyBufferImageTransferGranularityRequirements(device_data, cb_node, src_image_state, &pRegions[i], i,
2949d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski                                                                       "CmdCopyImageToBuffer");
2950d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski    }
2951d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski    return skip;
2952d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski}
2953d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski
2954d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinskivoid PreCallRecordCmdCopyImageToBuffer(layer_data *device_data, GLOBAL_CB_NODE *cb_node, IMAGE_STATE *src_image_state,
2955940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski                                       BUFFER_STATE *dst_buffer_state) {
2956d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski    // Update bindings between buffer/image and cmd buffer
2957d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski    AddCommandBufferBindingImage(device_data, cb_node, src_image_state);
2958940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    AddCommandBufferBindingBuffer(device_data, cb_node, dst_buffer_state);
2959d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski
296071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    std::function<bool()> function = [=]() {
296171c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        return ValidateImageMemoryIsValid(device_data, src_image_state, "vkCmdCopyImageToBuffer()");
296271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    };
296371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    cb_node->validate_functions.push_back(function);
296471c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    function = [=]() {
2965940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski        SetBufferMemoryValid(device_data, dst_buffer_state, true);
296671c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        return false;
296771c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    };
296871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    cb_node->validate_functions.push_back(function);
296971c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
297071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    core_validation::UpdateCmdBufferLastCmd(cb_node, CMD_COPYIMAGETOBUFFER);
2971877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski}
2972877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski
297371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinskibool PreCallValidateCmdCopyBufferToImage(layer_data *device_data, VkImageLayout dstImageLayout, GLOBAL_CB_NODE *cb_node,
2974940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski                                         BUFFER_STATE *src_buffer_state, IMAGE_STATE *dst_image_state, uint32_t regionCount,
2975877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski                                         const VkBufferImageCopy *pRegions, const char *func_name) {
297671c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
297771c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    bool skip = ValidateBufferImageCopyData(report_data, regionCount, pRegions, dst_image_state, "vkCmdCopyBufferToImage");
297871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
297971c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    // Validate command buffer state
298071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    if (CB_RECORDING != cb_node->state) {
298171c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
298271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                        (uint64_t)cb_node->commandBuffer, __LINE__, VALIDATION_ERROR_01240, "DS",
298371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                        "Cannot call vkCmdCopyBufferToImage() on command buffer which is not in recording state. %s.",
298471c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                        validation_error_map[VALIDATION_ERROR_01240]);
298571c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    } else {
298671c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        skip |= ValidateCmdSubpassState(device_data, cb_node, CMD_COPYBUFFERTOIMAGE);
298771c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    }
298871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
298971c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    // Command pool must support graphics, compute, or transfer operations
299071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    auto pPool = GetCommandPoolNode(device_data, cb_node->createInfo.commandPool);
299171c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    VkQueueFlags queue_flags = GetPhysDevProperties(device_data)->queue_family_properties[pPool->queueFamilyIndex].queueFlags;
299271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    if (0 == (queue_flags & (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT))) {
299371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
299471c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                        (uint64_t)cb_node->createInfo.commandPool, __LINE__, VALIDATION_ERROR_01241, "DS",
299571c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                        "Cannot call vkCmdCopyBufferToImage() on a command buffer allocated from a pool without graphics, compute, "
299671c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                        "or transfer capabilities. %s.",
299771c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                        validation_error_map[VALIDATION_ERROR_01241]);
299871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    }
29995971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton    skip |= ValidateImageBounds(report_data, dst_image_state, regionCount, pRegions, "vkCmdCopyBufferToImage()",
300071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                                VALIDATION_ERROR_01228);
3001940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    skip |= ValidtateBufferBounds(report_data, dst_image_state, src_buffer_state, regionCount, pRegions, "vkCmdCopyBufferToImage()",
300271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                                  VALIDATION_ERROR_01227);
300371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    skip |= ValidateImageSampleCount(device_data, dst_image_state, VK_SAMPLE_COUNT_1_BIT, "vkCmdCopyBufferToImage(): dstImage",
300471c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                                     VALIDATION_ERROR_01232);
3005940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    skip |= ValidateMemoryIsBoundToBuffer(device_data, src_buffer_state, "vkCmdCopyBufferToImage()", VALIDATION_ERROR_02535);
300671c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    skip |= ValidateMemoryIsBoundToImage(device_data, dst_image_state, "vkCmdCopyBufferToImage()", VALIDATION_ERROR_02536);
3007940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    skip |= ValidateBufferUsageFlags(device_data, src_buffer_state, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, true, VALIDATION_ERROR_01230,
300871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                                     "vkCmdCopyBufferToImage()", "VK_BUFFER_USAGE_TRANSFER_SRC_BIT");
300971c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    skip |= ValidateImageUsageFlags(device_data, dst_image_state, VK_IMAGE_USAGE_TRANSFER_DST_BIT, true, VALIDATION_ERROR_01231,
301071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                                    "vkCmdCopyBufferToImage()", "VK_IMAGE_USAGE_TRANSFER_DST_BIT");
3011d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski    skip |= insideRenderPass(device_data, cb_node, "vkCmdCopyBufferToImage()", VALIDATION_ERROR_01242);
3012d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski    for (uint32_t i = 0; i < regionCount; ++i) {
3013d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski        skip |= VerifyDestImageLayout(device_data, cb_node, dst_image_state->image, pRegions[i].imageSubresource, dstImageLayout,
3014d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski                                      VALIDATION_ERROR_01234);
3015d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski        skip |= ValidateCopyBufferImageTransferGranularityRequirements(device_data, cb_node, dst_image_state, &pRegions[i], i,
3016d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski                                                                       "vkCmdCopyBufferToImage()");
3017d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski    }
3018d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski    return skip;
3019d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski}
3020d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski
3021940f70f1340803d185c67633b05ef048d277952eMark Lobodzinskivoid PreCallRecordCmdCopyBufferToImage(layer_data *device_data, GLOBAL_CB_NODE *cb_node, BUFFER_STATE *src_buffer_state,
3022d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski                                       IMAGE_STATE *dst_image_state) {
3023940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    AddCommandBufferBindingBuffer(device_data, cb_node, src_buffer_state);
3024d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski    AddCommandBufferBindingImage(device_data, cb_node, dst_image_state);
302571c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    std::function<bool()> function = [=]() {
302671c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        SetImageMemoryValid(device_data, dst_image_state, true);
302771c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        return false;
302871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    };
302971c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    cb_node->validate_functions.push_back(function);
3030940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    function = [=]() { return ValidateBufferMemoryIsValid(device_data, src_buffer_state, "vkCmdCopyBufferToImage()"); };
303171c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    cb_node->validate_functions.push_back(function);
303271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
303371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    core_validation::UpdateCmdBufferLastCmd(cb_node, CMD_COPYBUFFERTOIMAGE);
3034877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski}
3035e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen
3036e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblenbool PreCallValidateGetImageSubresourceLayout(layer_data *device_data, VkImage image, const VkImageSubresource *pSubresource) {
3037e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    const auto report_data = core_validation::GetReportData(device_data);
3038e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    bool skip = false;
3039e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    const VkImageAspectFlags sub_aspect = pSubresource->aspectMask;
3040e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen
3041e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    // VU 00733: The aspectMask member of pSubresource must only have a single bit set
3042e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    const int num_bits = sizeof(sub_aspect) * CHAR_BIT;
3043e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    std::bitset<num_bits> aspect_mask_bits(sub_aspect);
3044e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    if (aspect_mask_bits.count() != 1) {
3045e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
3046e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen                        VALIDATION_ERROR_00733, "IMAGE",
3047e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen                        "vkGetImageSubresourceLayout(): VkImageSubresource.aspectMask must have exactly 1 bit set. %s",
3048e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen                        validation_error_map[VALIDATION_ERROR_00733]);
3049e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    }
3050e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen
3051e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    IMAGE_STATE *image_entry = GetImageState(device_data, image);
3052e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    if (!image_entry) {
3053e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen        return skip;
3054e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    }
3055e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen
3056e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    // VU 00732: image must have been created with tiling equal to VK_IMAGE_TILING_LINEAR
3057e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    if (image_entry->createInfo.tiling != VK_IMAGE_TILING_LINEAR) {
3058e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, (uint64_t)image,
3059e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen                        __LINE__, VALIDATION_ERROR_00732, "IMAGE",
3060e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen                        "vkGetImageSubresourceLayout(): Image must have tiling of VK_IMAGE_TILING_LINEAR. %s",
3061e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen                        validation_error_map[VALIDATION_ERROR_00732]);
3062e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    }
3063e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen
3064e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    // VU 00739: mipLevel must be less than the mipLevels specified in VkImageCreateInfo when the image was created
3065e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    if (pSubresource->mipLevel >= image_entry->createInfo.mipLevels) {
3066e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, (uint64_t)image,
3067e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen                        __LINE__, VALIDATION_ERROR_00739, "IMAGE",
3068e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen                        "vkGetImageSubresourceLayout(): pSubresource.mipLevel (%d) must be less than %d. %s",
3069e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen                        pSubresource->mipLevel, image_entry->createInfo.mipLevels, validation_error_map[VALIDATION_ERROR_00739]);
3070e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    }
3071e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen
3072e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    // VU 00740: arrayLayer must be less than the arrayLayers specified in VkImageCreateInfo when the image was created
3073e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    if (pSubresource->arrayLayer >= image_entry->createInfo.arrayLayers) {
3074e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen        skip |= log_msg(
3075e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen            report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, (uint64_t)image, __LINE__,
3076e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen            VALIDATION_ERROR_00740, "IMAGE", "vkGetImageSubresourceLayout(): pSubresource.arrayLayer (%d) must be less than %d. %s",
3077e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen            pSubresource->arrayLayer, image_entry->createInfo.arrayLayers, validation_error_map[VALIDATION_ERROR_00740]);
3078e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    }
3079e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen
3080e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    // VU 00741: subresource's aspect must be compatible with image's format.
3081e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    const VkFormat img_format = image_entry->createInfo.format;
3082e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    if (vk_format_is_color(img_format)) {
3083e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen        if (sub_aspect != VK_IMAGE_ASPECT_COLOR_BIT) {
3084e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen            skip |= log_msg(
3085e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen                report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, (uint64_t)image, __LINE__,
3086e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen                VALIDATION_ERROR_00741, "IMAGE",
3087e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen                "vkGetImageSubresourceLayout(): For color formats, VkImageSubresource.aspectMask must be VK_IMAGE_ASPECT_COLOR. %s",
3088e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen                validation_error_map[VALIDATION_ERROR_00741]);
3089e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen        }
3090e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    } else if (vk_format_is_depth_or_stencil(img_format)) {
3091e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen        if ((sub_aspect != VK_IMAGE_ASPECT_DEPTH_BIT) && (sub_aspect != VK_IMAGE_ASPECT_STENCIL_BIT)) {
3092e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, (uint64_t)image,
3093e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen                            __LINE__, VALIDATION_ERROR_00741, "IMAGE",
3094e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen                            "vkGetImageSubresourceLayout(): For depth/stencil formats, VkImageSubresource.aspectMask must be "
3095e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen                            "either VK_IMAGE_ASPECT_DEPTH_BIT or VK_IMAGE_ASPECT_STENCIL_BIT. %s",
3096e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen                            validation_error_map[VALIDATION_ERROR_00741]);
3097e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen        }
3098e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    }
3099e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    return skip;
3100e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen}
3101