buffer_validation.cpp revision 92c9c5dfbd0dec1d76ca18faa487fa8c2d302a65
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
5923c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes    if (pCreateInfo->format == VK_FORMAT_UNDEFINED) {
5933c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes        skip_call |=
5943c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes            log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
5953c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes                    VALIDATION_ERROR_00715, "IMAGE", "vkCreateImage: VkFormat for image must not be VK_FORMAT_UNDEFINED. %s",
5963c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes                    validation_error_map[VALIDATION_ERROR_00715]);
5973c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes
5983c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes        return skip_call;
5993c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes    }
6003c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes
6013c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes    const VkFormatProperties *properties = GetFormatProperties(device_data, pCreateInfo->format);
6023c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes
6033c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes    if ((pCreateInfo->tiling == VK_IMAGE_TILING_LINEAR) && (properties->linearTilingFeatures == 0)) {
6043c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes        std::stringstream ss;
6053c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes        ss << "vkCreateImage format parameter (" << string_VkFormat(pCreateInfo->format) << ") is an unsupported format";
6063c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes        skip_call |=
6073c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes            log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
6083c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes                    VALIDATION_ERROR_02150, "IMAGE", "%s. %s", ss.str().c_str(), validation_error_map[VALIDATION_ERROR_02150]);
6093c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes
6103c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes        return skip_call;
6113c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes    }
6123c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes
6133c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes    if ((pCreateInfo->tiling == VK_IMAGE_TILING_OPTIMAL) && (properties->optimalTilingFeatures == 0)) {
6143c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes        std::stringstream ss;
6153c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes        ss << "vkCreateImage format parameter (" << string_VkFormat(pCreateInfo->format) << ") is an unsupported format";
6163c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes        skip_call |=
6173c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes            log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
6183c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes                    VALIDATION_ERROR_02155, "IMAGE", "%s. %s", ss.str().c_str(), validation_error_map[VALIDATION_ERROR_02155]);
6193c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes
6203c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes        return skip_call;
6213c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes    }
6228dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
6233c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes    // Validate that format supports usage as color attachment
6243c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes    if (pCreateInfo->usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {
6253c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes        if ((pCreateInfo->tiling == VK_IMAGE_TILING_OPTIMAL) &&
6263c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes            ((properties->optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) == 0)) {
6278dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski            std::stringstream ss;
6283c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes            ss << "vkCreateImage: VkFormat for TILING_OPTIMAL image (" << string_VkFormat(pCreateInfo->format)
6293c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes               << ") does not support requested Image usage type VK_IMAGE_USAGE_COLOR_ATTACHMENT";
6308dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski            skip_call |=
6318dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
6323c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes                        VALIDATION_ERROR_02158, "IMAGE", "%s. %s", ss.str().c_str(), validation_error_map[VALIDATION_ERROR_02158]);
6338dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski        }
6343c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes        if ((pCreateInfo->tiling == VK_IMAGE_TILING_LINEAR) &&
6353c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes            ((properties->linearTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) == 0)) {
6368dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski            std::stringstream ss;
6373c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes            ss << "vkCreateImage: VkFormat for TILING_LINEAR image (" << string_VkFormat(pCreateInfo->format)
6383c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes               << ") does not support requested Image usage type VK_IMAGE_USAGE_COLOR_ATTACHMENT";
6398dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski            skip_call |=
6408dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
6413c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes                        VALIDATION_ERROR_02153, "IMAGE", "%s. %s", ss.str().c_str(), validation_error_map[VALIDATION_ERROR_02153]);
6428dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski        }
6433c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes    }
6448dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
6453c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes    // Validate that format supports usage as depth/stencil attachment
6463c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes    if (pCreateInfo->usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
6473c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes        if ((pCreateInfo->tiling == VK_IMAGE_TILING_OPTIMAL) &&
6483c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes            ((properties->optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) == 0)) {
6493c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes            std::stringstream ss;
6503c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes            ss << "vkCreateImage: VkFormat for TILING_OPTIMAL image (" << string_VkFormat(pCreateInfo->format)
6513c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes               << ") does not support requested Image usage type VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT";
6523c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes            skip_call |=
6533c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes                log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
6543c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes                        VALIDATION_ERROR_02159, "IMAGE", "%s. %s", ss.str().c_str(), validation_error_map[VALIDATION_ERROR_02159]);
6558dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski        }
6563c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes        if ((pCreateInfo->tiling == VK_IMAGE_TILING_LINEAR) &&
6573c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes            ((properties->linearTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) == 0)) {
6583c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes            std::stringstream ss;
6593c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes            ss << "vkCreateImage: VkFormat for TILING_LINEAR image (" << string_VkFormat(pCreateInfo->format)
6603c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes               << ") does not support requested Image usage type VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT";
6613c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes            skip_call |=
6623c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes                log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
6633c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes                        VALIDATION_ERROR_02154, "IMAGE", "%s. %s", ss.str().c_str(), validation_error_map[VALIDATION_ERROR_02154]);
6648dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski        }
6658dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    }
6668dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
667d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski    const VkImageFormatProperties *ImageFormatProperties = GetImageFormatProperties(
668d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski        device_data, pCreateInfo->format, pCreateInfo->imageType, pCreateInfo->tiling, pCreateInfo->usage, pCreateInfo->flags);
6698dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
670d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski    VkDeviceSize imageGranularity = GetPhysicalDeviceProperties(device_data)->limits.bufferImageGranularity;
6718dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    imageGranularity = imageGranularity == 1 ? 0 : imageGranularity;
6728dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
673a9991b9f53d0be4fecc63bdbdf3de9950070a3a5Mark Lobodzinski    if ((pCreateInfo->extent.width <= 0) || (pCreateInfo->extent.height <= 0) || (pCreateInfo->extent.depth <= 0)) {
674a9991b9f53d0be4fecc63bdbdf3de9950070a3a5Mark Lobodzinski        skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 0, __LINE__,
675a9991b9f53d0be4fecc63bdbdf3de9950070a3a5Mark Lobodzinski                             VALIDATION_ERROR_00716, "Image",
676a9991b9f53d0be4fecc63bdbdf3de9950070a3a5Mark Lobodzinski                             "CreateImage extent is 0 for at least one required dimension for image: "
677a9991b9f53d0be4fecc63bdbdf3de9950070a3a5Mark Lobodzinski                             "Width = %d Height = %d Depth = %d. %s",
678a9991b9f53d0be4fecc63bdbdf3de9950070a3a5Mark Lobodzinski                             pCreateInfo->extent.width, pCreateInfo->extent.height, pCreateInfo->extent.depth,
679a9991b9f53d0be4fecc63bdbdf3de9950070a3a5Mark Lobodzinski                             validation_error_map[VALIDATION_ERROR_00716]);
6808dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    }
6818dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
6828dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    // TODO: VALIDATION_ERROR_02125 VALIDATION_ERROR_02126 VALIDATION_ERROR_02128 VALIDATION_ERROR_00720
6838dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    // All these extent-related VUs should be checked here
684d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski    if ((pCreateInfo->extent.depth > ImageFormatProperties->maxExtent.depth) ||
685d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski        (pCreateInfo->extent.width > ImageFormatProperties->maxExtent.width) ||
686d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski        (pCreateInfo->extent.height > ImageFormatProperties->maxExtent.height)) {
6878dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski        skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 0, __LINE__,
6888dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                             IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
6898dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                             "CreateImage extents exceed allowable limits for format: "
6908dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                             "Width = %d Height = %d Depth = %d:  Limits for Width = %d Height = %d Depth = %d for format %s.",
6918dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                             pCreateInfo->extent.width, pCreateInfo->extent.height, pCreateInfo->extent.depth,
692d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski                             ImageFormatProperties->maxExtent.width, ImageFormatProperties->maxExtent.height,
693d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski                             ImageFormatProperties->maxExtent.depth, string_VkFormat(pCreateInfo->format));
6948dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    }
6958dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
6968dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    uint64_t totalSize = ((uint64_t)pCreateInfo->extent.width * (uint64_t)pCreateInfo->extent.height *
6978dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                              (uint64_t)pCreateInfo->extent.depth * (uint64_t)pCreateInfo->arrayLayers *
6988dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                              (uint64_t)pCreateInfo->samples * (uint64_t)vk_format_get_size(pCreateInfo->format) +
6998dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                          (uint64_t)imageGranularity) &
7008dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                         ~(uint64_t)imageGranularity;
7018dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
702d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski    if (totalSize > ImageFormatProperties->maxResourceSize) {
7038dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski        skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 0, __LINE__,
7048dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                             IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
7058dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                             "CreateImage resource size exceeds allowable maximum "
7068dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                             "Image resource size = 0x%" PRIxLEAST64 ", maximum resource size = 0x%" PRIxLEAST64 " ",
707d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski                             totalSize, ImageFormatProperties->maxResourceSize);
7088dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    }
7098dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
7108dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    // TODO: VALIDATION_ERROR_02132
711d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski    if (pCreateInfo->mipLevels > ImageFormatProperties->maxMipLevels) {
7128dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski        skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 0, __LINE__,
7138dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                             IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
7148dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                             "CreateImage mipLevels=%d exceeds allowable maximum supported by format of %d", pCreateInfo->mipLevels,
715d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski                             ImageFormatProperties->maxMipLevels);
7168dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    }
7178dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
718d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski    if (pCreateInfo->arrayLayers > ImageFormatProperties->maxArrayLayers) {
7198dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski        skip_call |= log_msg(
7208dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski            report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 0, __LINE__, VALIDATION_ERROR_02133,
7218dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski            "Image", "CreateImage arrayLayers=%d exceeds allowable maximum supported by format of %d. %s", pCreateInfo->arrayLayers,
722d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski            ImageFormatProperties->maxArrayLayers, validation_error_map[VALIDATION_ERROR_02133]);
7238dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    }
7248dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
725d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski    if ((pCreateInfo->samples & ImageFormatProperties->sampleCounts) == 0) {
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_02138, "Image", "CreateImage samples %s is not supported by format 0x%.8X. %s",
728d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski                             string_VkSampleCountFlagBits(pCreateInfo->samples), ImageFormatProperties->sampleCounts,
7298dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                             validation_error_map[VALIDATION_ERROR_02138]);
7308dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    }
7318dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
7328dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    if (pCreateInfo->initialLayout != VK_IMAGE_LAYOUT_UNDEFINED && pCreateInfo->initialLayout != VK_IMAGE_LAYOUT_PREINITIALIZED) {
7338dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski        skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 0, __LINE__,
7348dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                             VALIDATION_ERROR_00731, "Image",
7358dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                             "vkCreateImage parameter, pCreateInfo->initialLayout, must be VK_IMAGE_LAYOUT_UNDEFINED or "
7368dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                             "VK_IMAGE_LAYOUT_PREINITIALIZED. %s",
7378dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski                             validation_error_map[VALIDATION_ERROR_00731]);
7388dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    }
7398dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
74001363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski    if ((pCreateInfo->flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT) && (!GetEnabledFeatures(device_data)->sparseBinding)) {
74101363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski        skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
74201363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski                             VALIDATION_ERROR_02143, "DS",
74301363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski                             "vkCreateImage(): the sparseBinding device feature is disabled: Images cannot be created with the "
74401363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski                             "VK_IMAGE_CREATE_SPARSE_BINDING_BIT set. %s",
74501363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski                             validation_error_map[VALIDATION_ERROR_02143]);
74601363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski    }
74701363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski
7487e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski    if ((pCreateInfo->flags & VK_IMAGE_CREATE_SPARSE_ALIASED_BIT) && (!GetEnabledFeatures(device_data)->sparseResidencyAliased)) {
7497e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski        skip_call |=
7507e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski            log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
7517e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski                    DRAWSTATE_INVALID_FEATURE, "DS",
7527e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski                    "vkCreateImage(): the sparseResidencyAliased device feature is disabled: Images cannot be created with the "
7537e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski                    "VK_IMAGE_CREATE_SPARSE_ALIASED_BIT set.");
7547e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski    }
7557e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski
7568dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    return skip_call;
7578dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski}
7588dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
759e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisvoid PostCallRecordCreateImage(layer_data *device_data, const VkImageCreateInfo *pCreateInfo, VkImage *pImage) {
760c06c9b88f5f5bcc7033ba41d5547b048fa6015a4Mark Lobodzinski    IMAGE_LAYOUT_NODE image_state;
761c06c9b88f5f5bcc7033ba41d5547b048fa6015a4Mark Lobodzinski    image_state.layout = pCreateInfo->initialLayout;
762c06c9b88f5f5bcc7033ba41d5547b048fa6015a4Mark Lobodzinski    image_state.format = pCreateInfo->format;
763920311b6aa5614a545cad59521770d0898a75d65Mark Lobodzinski    GetImageMap(device_data)->insert(std::make_pair(*pImage, std::unique_ptr<IMAGE_STATE>(new IMAGE_STATE(*pImage, pCreateInfo))));
764c06c9b88f5f5bcc7033ba41d5547b048fa6015a4Mark Lobodzinski    ImageSubresourcePair subpair{*pImage, false, VkImageSubresource()};
765920311b6aa5614a545cad59521770d0898a75d65Mark Lobodzinski    (*core_validation::GetImageSubresourceMap(device_data))[*pImage].push_back(subpair);
766920311b6aa5614a545cad59521770d0898a75d65Mark Lobodzinski    (*core_validation::GetImageLayoutMap(device_data))[subpair] = image_state;
767c06c9b88f5f5bcc7033ba41d5547b048fa6015a4Mark Lobodzinski}
7688c59133586421be878d393799b30044497f77727Mark Lobodzinski
769e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisbool PreCallValidateDestroyImage(layer_data *device_data, VkImage image, IMAGE_STATE **image_state, VK_OBJECT *obj_struct) {
7708c59133586421be878d393799b30044497f77727Mark Lobodzinski    const CHECK_DISABLED *disabled = core_validation::GetDisables(device_data);
7719a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    *image_state = core_validation::GetImageState(device_data, image);
7728c59133586421be878d393799b30044497f77727Mark Lobodzinski    *obj_struct = {reinterpret_cast<uint64_t &>(image), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT};
7738c59133586421be878d393799b30044497f77727Mark Lobodzinski    if (disabled->destroy_image) return false;
7748c59133586421be878d393799b30044497f77727Mark Lobodzinski    bool skip = false;
7758c59133586421be878d393799b30044497f77727Mark Lobodzinski    if (*image_state) {
7768c59133586421be878d393799b30044497f77727Mark Lobodzinski        skip |= core_validation::ValidateObjectNotInUse(device_data, *image_state, *obj_struct, VALIDATION_ERROR_00743);
7778c59133586421be878d393799b30044497f77727Mark Lobodzinski    }
7788c59133586421be878d393799b30044497f77727Mark Lobodzinski    return skip;
7798c59133586421be878d393799b30044497f77727Mark Lobodzinski}
7808c59133586421be878d393799b30044497f77727Mark Lobodzinski
781e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisvoid PostCallRecordDestroyImage(layer_data *device_data, VkImage image, IMAGE_STATE *image_state, VK_OBJECT obj_struct) {
7828c59133586421be878d393799b30044497f77727Mark Lobodzinski    core_validation::invalidateCommandBuffers(device_data, image_state->cb_bindings, obj_struct);
7838c59133586421be878d393799b30044497f77727Mark Lobodzinski    // Clean up memory mapping, bindings and range references for image
7848c59133586421be878d393799b30044497f77727Mark Lobodzinski    for (auto mem_binding : image_state->GetBoundMemory()) {
7859a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto mem_info = core_validation::GetMemObjInfo(device_data, mem_binding);
7868c59133586421be878d393799b30044497f77727Mark Lobodzinski        if (mem_info) {
7878c59133586421be878d393799b30044497f77727Mark Lobodzinski            core_validation::RemoveImageMemoryRange(obj_struct.handle, mem_info);
7888c59133586421be878d393799b30044497f77727Mark Lobodzinski        }
7898c59133586421be878d393799b30044497f77727Mark Lobodzinski    }
7908c59133586421be878d393799b30044497f77727Mark Lobodzinski    core_validation::ClearMemoryObjectBindings(device_data, obj_struct.handle, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT);
7918c59133586421be878d393799b30044497f77727Mark Lobodzinski    // Remove image from imageMap
7928c59133586421be878d393799b30044497f77727Mark Lobodzinski    core_validation::GetImageMap(device_data)->erase(image);
7938c59133586421be878d393799b30044497f77727Mark Lobodzinski    std::unordered_map<VkImage, std::vector<ImageSubresourcePair>> *imageSubresourceMap =
7948c59133586421be878d393799b30044497f77727Mark Lobodzinski        core_validation::GetImageSubresourceMap(device_data);
7958c59133586421be878d393799b30044497f77727Mark Lobodzinski
7968c59133586421be878d393799b30044497f77727Mark Lobodzinski    const auto &sub_entry = imageSubresourceMap->find(image);
7978c59133586421be878d393799b30044497f77727Mark Lobodzinski    if (sub_entry != imageSubresourceMap->end()) {
7988c59133586421be878d393799b30044497f77727Mark Lobodzinski        for (const auto &pair : sub_entry->second) {
7998c59133586421be878d393799b30044497f77727Mark Lobodzinski            core_validation::GetImageLayoutMap(device_data)->erase(pair);
8008c59133586421be878d393799b30044497f77727Mark Lobodzinski        }
8018c59133586421be878d393799b30044497f77727Mark Lobodzinski        imageSubresourceMap->erase(sub_entry);
8028c59133586421be878d393799b30044497f77727Mark Lobodzinski    }
8038c59133586421be878d393799b30044497f77727Mark Lobodzinski}
804509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski
805e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisbool ValidateImageAttributes(layer_data *device_data, IMAGE_STATE *image_state, VkImageSubresourceRange range) {
806509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski    bool skip = false;
807509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
808509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski
809509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski    if (range.aspectMask != VK_IMAGE_ASPECT_COLOR_BIT) {
810509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski        char const str[] = "vkCmdClearColorImage aspectMasks for all subresource ranges must be set to VK_IMAGE_ASPECT_COLOR_BIT";
811509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
812509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski                        reinterpret_cast<uint64_t &>(image_state->image), __LINE__, DRAWSTATE_INVALID_IMAGE_ASPECT, "IMAGE", str);
813509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski    }
814509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski
815509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski    if (vk_format_is_depth_or_stencil(image_state->createInfo.format)) {
816509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski        char const str[] = "vkCmdClearColorImage called with depth/stencil image.";
817509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
818509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski                        reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01088, "IMAGE", "%s. %s", str,
819509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski                        validation_error_map[VALIDATION_ERROR_01088]);
820509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski    } else if (vk_format_is_compressed(image_state->createInfo.format)) {
821509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski        char const str[] = "vkCmdClearColorImage called with compressed image.";
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_01088, "IMAGE", "%s. %s", str,
824509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski                        validation_error_map[VALIDATION_ERROR_01088]);
825509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski    }
826509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski
827509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski    if (!(image_state->createInfo.usage & VK_IMAGE_USAGE_TRANSFER_DST_BIT)) {
828509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski        char const str[] = "vkCmdClearColorImage called with image created without VK_IMAGE_USAGE_TRANSFER_DST_BIT.";
829509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
830509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski                        reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01084, "IMAGE", "%s. %s", str,
831509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski                        validation_error_map[VALIDATION_ERROR_01084]);
832509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski    }
833509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski    return skip;
834509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski}
835623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski
836e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisvoid ResolveRemainingLevelsLayers(layer_data *dev_data, VkImageSubresourceRange *range, IMAGE_STATE *image_state) {
83708c7aae3177092f8567e2b5a946457be61616e9aMark Lobodzinski    // If the caller used the special values VK_REMAINING_MIP_LEVELS and VK_REMAINING_ARRAY_LAYERS, resolve them now in our
83808c7aae3177092f8567e2b5a946457be61616e9aMark Lobodzinski    // internal state to the actual values.
83908c7aae3177092f8567e2b5a946457be61616e9aMark Lobodzinski    if (range->levelCount == VK_REMAINING_MIP_LEVELS) {
84008c7aae3177092f8567e2b5a946457be61616e9aMark Lobodzinski        range->levelCount = image_state->createInfo.mipLevels - range->baseMipLevel;
84108c7aae3177092f8567e2b5a946457be61616e9aMark Lobodzinski    }
842623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski
84308c7aae3177092f8567e2b5a946457be61616e9aMark Lobodzinski    if (range->layerCount == VK_REMAINING_ARRAY_LAYERS) {
84408c7aae3177092f8567e2b5a946457be61616e9aMark Lobodzinski        range->layerCount = image_state->createInfo.arrayLayers - range->baseArrayLayer;
845623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    }
846623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski}
847623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski
848623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski// Return the correct layer/level counts if the caller used the special values VK_REMAINING_MIP_LEVELS or VK_REMAINING_ARRAY_LAYERS.
849e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisvoid ResolveRemainingLevelsLayers(layer_data *dev_data, uint32_t *levels, uint32_t *layers, VkImageSubresourceRange range,
850e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlis                                  IMAGE_STATE *image_state) {
851623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    *levels = range.levelCount;
852623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    *layers = range.layerCount;
85308c7aae3177092f8567e2b5a946457be61616e9aMark Lobodzinski    if (range.levelCount == VK_REMAINING_MIP_LEVELS) {
85408c7aae3177092f8567e2b5a946457be61616e9aMark Lobodzinski        *levels = image_state->createInfo.mipLevels - range.baseMipLevel;
85508c7aae3177092f8567e2b5a946457be61616e9aMark Lobodzinski    }
85608c7aae3177092f8567e2b5a946457be61616e9aMark Lobodzinski    if (range.layerCount == VK_REMAINING_ARRAY_LAYERS) {
85708c7aae3177092f8567e2b5a946457be61616e9aMark Lobodzinski        *layers = image_state->createInfo.arrayLayers - range.baseArrayLayer;
858623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    }
859623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski}
860623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski
861e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisbool VerifyClearImageLayout(layer_data *device_data, GLOBAL_CB_NODE *cb_node, IMAGE_STATE *image_state,
862623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                            VkImageSubresourceRange range, VkImageLayout dest_image_layout, const char *func_name) {
863623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    bool skip = false;
864623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
865623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski
866623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    VkImageSubresourceRange resolved_range = range;
86708c7aae3177092f8567e2b5a946457be61616e9aMark Lobodzinski    ResolveRemainingLevelsLayers(device_data, &resolved_range, image_state);
868623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski
869623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    if (dest_image_layout != VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
870623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        if (dest_image_layout == VK_IMAGE_LAYOUT_GENERAL) {
871623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski            if (image_state->createInfo.tiling != VK_IMAGE_TILING_LINEAR) {
872623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                // LAYOUT_GENERAL is allowed, but may not be performance optimal, flag as perf warning.
873623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0,
874623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                                __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
875623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                                "%s: Layout for cleared image should be TRANSFER_DST_OPTIMAL instead of GENERAL.", func_name);
876623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski            }
877623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        } else {
878623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski            UNIQUE_VALIDATION_ERROR_CODE error_code = VALIDATION_ERROR_01086;
879623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski            if (strcmp(func_name, "vkCmdClearDepthStencilImage()") == 0) {
880623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                error_code = VALIDATION_ERROR_01101;
881623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski            } else {
882623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                assert(strcmp(func_name, "vkCmdClearColorImage()") == 0);
883623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski            }
884623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski            skip |=
885623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, error_code, "DS",
886623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                        "%s: Layout for cleared image is %s but can only be "
887623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                        "TRANSFER_DST_OPTIMAL or GENERAL. %s",
888623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                        func_name, string_VkImageLayout(dest_image_layout), validation_error_map[error_code]);
889623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        }
890623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    }
891623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski
892623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    for (uint32_t level_index = 0; level_index < resolved_range.levelCount; ++level_index) {
893623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        uint32_t level = level_index + resolved_range.baseMipLevel;
894623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        for (uint32_t layer_index = 0; layer_index < resolved_range.layerCount; ++layer_index) {
895623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski            uint32_t layer = layer_index + resolved_range.baseArrayLayer;
896623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski            VkImageSubresource sub = {resolved_range.aspectMask, level, layer};
897623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski            IMAGE_CMD_BUF_LAYOUT_NODE node;
89855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski            if (FindCmdBufLayout(device_data, cb_node, image_state->image, sub, node)) {
899623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                if (node.layout != dest_image_layout) {
900623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                    UNIQUE_VALIDATION_ERROR_CODE error_code = VALIDATION_ERROR_01085;
901623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                    if (strcmp(func_name, "vkCmdClearDepthStencilImage()") == 0) {
902623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                        error_code = VALIDATION_ERROR_01100;
903623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                    } else {
904623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                        assert(strcmp(func_name, "vkCmdClearColorImage()") == 0);
905623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                    }
906623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                    skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0,
907623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                                    __LINE__, error_code, "DS",
908623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                                    "%s: Cannot clear an image whose layout is %s and "
909623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                                    "doesn't match the current layout %s. %s",
910623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                                    func_name, string_VkImageLayout(dest_image_layout), string_VkImageLayout(node.layout),
911623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                                    validation_error_map[error_code]);
912623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                }
913623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski            }
914623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        }
915623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    }
916623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski
917623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    return skip;
918623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski}
919623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski
920e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisvoid RecordClearImageLayout(layer_data *device_data, GLOBAL_CB_NODE *cb_node, VkImage image, VkImageSubresourceRange range,
921e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlis                            VkImageLayout dest_image_layout) {
922623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    VkImageSubresourceRange resolved_range = range;
9239a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    ResolveRemainingLevelsLayers(device_data, &resolved_range, GetImageState(device_data, image));
924623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski
925623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    for (uint32_t level_index = 0; level_index < resolved_range.levelCount; ++level_index) {
926623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        uint32_t level = level_index + resolved_range.baseMipLevel;
927623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        for (uint32_t layer_index = 0; layer_index < resolved_range.layerCount; ++layer_index) {
928623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski            uint32_t layer = layer_index + resolved_range.baseArrayLayer;
929623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski            VkImageSubresource sub = {resolved_range.aspectMask, level, layer};
930623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski            IMAGE_CMD_BUF_LAYOUT_NODE node;
93155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski            if (!FindCmdBufLayout(device_data, cb_node, image, sub, node)) {
93255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                SetLayout(device_data, cb_node, image, sub, IMAGE_CMD_BUF_LAYOUT_NODE(dest_image_layout, dest_image_layout));
933623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski            }
934623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        }
935623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    }
936623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski}
937623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski
938e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisbool PreCallValidateCmdClearColorImage(layer_data *dev_data, VkCommandBuffer commandBuffer, VkImage image,
939623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                                       VkImageLayout imageLayout, uint32_t rangeCount, const VkImageSubresourceRange *pRanges) {
940623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    bool skip = false;
941623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    // TODO : Verify memory is in VK_IMAGE_STATE_CLEAR state
9429a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto cb_node = GetCBNode(dev_data, commandBuffer);
9439a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto image_state = GetImageState(dev_data, image);
944623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    if (cb_node && image_state) {
945623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        skip |= ValidateMemoryIsBoundToImage(dev_data, image_state, "vkCmdClearColorImage()", VALIDATION_ERROR_02527);
946623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        skip |= ValidateCmd(dev_data, cb_node, CMD_CLEARCOLORIMAGE, "vkCmdClearColorImage()");
947623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        skip |= insideRenderPass(dev_data, cb_node, "vkCmdClearColorImage()", VALIDATION_ERROR_01096);
948623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        for (uint32_t i = 0; i < rangeCount; ++i) {
949623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski            skip |= ValidateImageAttributes(dev_data, image_state, pRanges[i]);
95008c7aae3177092f8567e2b5a946457be61616e9aMark Lobodzinski            skip |= VerifyClearImageLayout(dev_data, cb_node, image_state, pRanges[i], imageLayout, "vkCmdClearColorImage()");
951623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        }
952623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    }
953623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    return skip;
954623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski}
955623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski
956623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski// This state recording routine is shared between ClearColorImage and ClearDepthStencilImage
957e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisvoid PreCallRecordCmdClearImage(layer_data *dev_data, VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout,
958e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlis                                uint32_t rangeCount, const VkImageSubresourceRange *pRanges, CMD_TYPE cmd_type) {
9599a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto cb_node = GetCBNode(dev_data, commandBuffer);
9609a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto image_state = GetImageState(dev_data, image);
961623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    if (cb_node && image_state) {
962623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        AddCommandBufferBindingImage(dev_data, cb_node, image_state);
963623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        std::function<bool()> function = [=]() {
964623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski            SetImageMemoryValid(dev_data, image_state, true);
965623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski            return false;
966623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        };
967623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        cb_node->validate_functions.push_back(function);
9689a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        core_validation::UpdateCmdBufferLastCmd(cb_node, cmd_type);
969623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        for (uint32_t i = 0; i < rangeCount; ++i) {
970623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski            RecordClearImageLayout(dev_data, cb_node, image, pRanges[i], imageLayout);
971623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        }
972623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    }
973623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski}
974623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski
975e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisbool PreCallValidateCmdClearDepthStencilImage(layer_data *device_data, VkCommandBuffer commandBuffer, VkImage image,
976e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlis                                              VkImageLayout imageLayout, uint32_t rangeCount,
977623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski                                              const VkImageSubresourceRange *pRanges) {
978623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    bool skip = false;
9797244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
9807244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski
981623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    // TODO : Verify memory is in VK_IMAGE_STATE_CLEAR state
9829a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto cb_node = GetCBNode(device_data, commandBuffer);
9839a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto image_state = GetImageState(device_data, image);
984623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    if (cb_node && image_state) {
9857244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski        skip |= ValidateMemoryIsBoundToImage(device_data, image_state, "vkCmdClearDepthStencilImage()", VALIDATION_ERROR_02528);
9867244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski        skip |= ValidateCmd(device_data, cb_node, CMD_CLEARDEPTHSTENCILIMAGE, "vkCmdClearDepthStencilImage()");
9877244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski        skip |= insideRenderPass(device_data, cb_node, "vkCmdClearDepthStencilImage()", VALIDATION_ERROR_01111);
988623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        for (uint32_t i = 0; i < rangeCount; ++i) {
98908c7aae3177092f8567e2b5a946457be61616e9aMark Lobodzinski            skip |=
99008c7aae3177092f8567e2b5a946457be61616e9aMark Lobodzinski                VerifyClearImageLayout(device_data, cb_node, image_state, pRanges[i], imageLayout, "vkCmdClearDepthStencilImage()");
9917244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski            // Image aspect must be depth or stencil or both
9927244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski            if (((pRanges[i].aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) != VK_IMAGE_ASPECT_DEPTH_BIT) &&
9937244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski                ((pRanges[i].aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) != VK_IMAGE_ASPECT_STENCIL_BIT)) {
9947244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski                char const str[] =
9957244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski                    "vkCmdClearDepthStencilImage aspectMasks for all subresource ranges must be "
9967244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski                    "set to VK_IMAGE_ASPECT_DEPTH_BIT and/or VK_IMAGE_ASPECT_STENCIL_BIT";
9977244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
9987244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski                                (uint64_t)commandBuffer, __LINE__, DRAWSTATE_INVALID_IMAGE_ASPECT, "IMAGE", str);
9997244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski            }
10007244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski        }
10017244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski        if (image_state && !vk_format_is_depth_or_stencil(image_state->createInfo.format)) {
10027244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski            char const str[] = "vkCmdClearDepthStencilImage called without a depth/stencil image.";
10037244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
10047244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski                            reinterpret_cast<uint64_t &>(image), __LINE__, VALIDATION_ERROR_01103, "IMAGE", "%s. %s", str,
10057244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski                            validation_error_map[VALIDATION_ERROR_01103]);
1006623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski        }
1007623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    }
1008623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski    return skip;
1009623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski}
1010ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
1011ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski// Returns true if [x, xoffset] and [y, yoffset] overlap
1012ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinskistatic bool RangesIntersect(int32_t start, uint32_t start_offset, int32_t end, uint32_t end_offset) {
1013ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    bool result = false;
1014ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    uint32_t intersection_min = std::max(static_cast<uint32_t>(start), static_cast<uint32_t>(end));
1015ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    uint32_t intersection_max = std::min(static_cast<uint32_t>(start) + start_offset, static_cast<uint32_t>(end) + end_offset);
1016ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
1017ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    if (intersection_max > intersection_min) {
1018ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski        result = true;
1019ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    }
1020ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    return result;
1021ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski}
1022ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
1023ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski// Returns true if two VkImageCopy structures overlap
1024ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinskistatic bool RegionIntersects(const VkImageCopy *src, const VkImageCopy *dst, VkImageType type) {
1025ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    bool result = false;
1026ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    if ((src->srcSubresource.mipLevel == dst->dstSubresource.mipLevel) &&
1027ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski        (RangesIntersect(src->srcSubresource.baseArrayLayer, src->srcSubresource.layerCount, dst->dstSubresource.baseArrayLayer,
1028ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski                         dst->dstSubresource.layerCount))) {
1029ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski        result = true;
1030ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski        switch (type) {
1031ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski            case VK_IMAGE_TYPE_3D:
1032ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski                result &= RangesIntersect(src->srcOffset.z, src->extent.depth, dst->dstOffset.z, dst->extent.depth);
1033ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski            // Intentionally fall through to 2D case
1034ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski            case VK_IMAGE_TYPE_2D:
1035ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski                result &= RangesIntersect(src->srcOffset.y, src->extent.height, dst->dstOffset.y, dst->extent.height);
1036ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski            // Intentionally fall through to 1D case
1037ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski            case VK_IMAGE_TYPE_1D:
1038ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski                result &= RangesIntersect(src->srcOffset.x, src->extent.width, dst->dstOffset.x, dst->extent.width);
1039ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski                break;
1040ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski            default:
1041ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski                // Unrecognized or new IMAGE_TYPE enums will be caught in parameter_validation
1042ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski                assert(false);
1043ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski        }
1044ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    }
1045ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    return result;
1046ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski}
1047ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
1048ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski// Returns true if offset and extent exceed image extents
10495971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houltonstatic bool ExceedsBounds(const VkOffset3D *offset, const VkExtent3D *extent, const VkExtent3D *image_extent) {
1050ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    bool result = false;
1051ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    // Extents/depths cannot be negative but checks left in for clarity
10525971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton    if ((offset->z + extent->depth > image_extent->depth) || (offset->z < 0) ||
10535971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        ((offset->z + static_cast<int32_t>(extent->depth)) < 0)) {
10545971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        result = true;
10555971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton    }
10565971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton    if ((offset->y + extent->height > image_extent->height) || (offset->y < 0) ||
10575971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        ((offset->y + static_cast<int32_t>(extent->height)) < 0)) {
10585971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        result = true;
10595971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton    }
10605971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton    if ((offset->x + extent->width > image_extent->width) || (offset->x < 0) ||
10615971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        ((offset->x + static_cast<int32_t>(extent->width)) < 0)) {
10625971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        result = true;
1063ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    }
1064ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    return result;
1065ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski}
1066ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
10676a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski// Test if two VkExtent3D structs are equivalent
10686a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinskistatic inline bool IsExtentEqual(const VkExtent3D *extent, const VkExtent3D *other_extent) {
10696a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    bool result = true;
10706a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    if ((extent->width != other_extent->width) || (extent->height != other_extent->height) ||
10716a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        (extent->depth != other_extent->depth)) {
10726a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        result = false;
10736a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    }
10746a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    return result;
10756a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski}
10766a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
10776a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski// Returns the image extent of a specific subresource.
10786a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinskistatic inline VkExtent3D GetImageSubresourceExtent(const IMAGE_STATE *img, const VkImageSubresourceLayers *subresource) {
10796a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    const uint32_t mip = subresource->mipLevel;
10806a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    VkExtent3D extent = img->createInfo.extent;
10815971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton    // Don't allow mip adjustment to create 0 dim, but pass along a 0 if that's what subresource specified
10825971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton    extent.width = (0 == extent.width ? 0 : std::max(1U, extent.width >> mip));
10835971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton    extent.height = (0 == extent.height ? 0 : std::max(1U, extent.height >> mip));
10845971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton    extent.depth = (0 == extent.depth ? 0 : std::max(1U, extent.depth >> mip));
10856a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    return extent;
10866a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski}
10876a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
10886a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski// Test if the extent argument has all dimensions set to 0.
10895971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houltonstatic inline bool IsExtentAllZeroes(const VkExtent3D *extent) {
10906a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    return ((extent->width == 0) && (extent->height == 0) && (extent->depth == 0));
10916a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski}
10926a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
10935971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton// Test if the extent argument has any dimensions set to 0.
10945971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houltonstatic inline bool IsExtentSizeZero(const VkExtent3D *extent) {
10955971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton    return ((extent->width == 0) || (extent->height == 0) || (extent->depth == 0));
10965971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton}
10975971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton
10986a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski// Returns the image transfer granularity for a specific image scaled by compressed block size if necessary.
10996a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinskistatic inline VkExtent3D GetScaledItg(layer_data *device_data, const GLOBAL_CB_NODE *cb_node, const IMAGE_STATE *img) {
11006a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    // Default to (0, 0, 0) granularity in case we can't find the real granularity for the physical device.
11016a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    VkExtent3D granularity = {0, 0, 0};
11026a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    auto pPool = GetCommandPoolNode(device_data, cb_node->createInfo.commandPool);
11036a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    if (pPool) {
11046a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        granularity =
11056a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            GetPhysDevProperties(device_data)->queue_family_properties[pPool->queueFamilyIndex].minImageTransferGranularity;
11066a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if (vk_format_is_compressed(img->createInfo.format)) {
1107b82b418c8bea6d408e4c8f25e024a37c5b35508fMark Lobodzinski            auto block_size = vk_format_compressed_texel_block_extents(img->createInfo.format);
11086a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            granularity.width *= block_size.width;
11096a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            granularity.height *= block_size.height;
11106a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
11116a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    }
11126a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    return granularity;
11136a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski}
11146a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
11156a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski// Test elements of a VkExtent3D structure against alignment constraints contained in another VkExtent3D structure
11166a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinskistatic inline bool IsExtentAligned(const VkExtent3D *extent, const VkExtent3D *granularity) {
11176a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    bool valid = true;
11186a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    if ((vk_safe_modulo(extent->depth, granularity->depth) != 0) || (vk_safe_modulo(extent->width, granularity->width) != 0) ||
11196a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        (vk_safe_modulo(extent->height, granularity->height) != 0)) {
11206a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        valid = false;
11216a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    }
11226a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    return valid;
11236a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski}
11246a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
11256a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski// Check elements of a VkOffset3D structure against a queue family's Image Transfer Granularity values
11266a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinskistatic inline bool CheckItgOffset(layer_data *device_data, const GLOBAL_CB_NODE *cb_node, const VkOffset3D *offset,
11276a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                  const VkExtent3D *granularity, const uint32_t i, const char *function, const char *member) {
11286a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
11296a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    bool skip = false;
11306a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    VkExtent3D offset_extent = {};
11316a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    offset_extent.width = static_cast<uint32_t>(abs(offset->x));
11326a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    offset_extent.height = static_cast<uint32_t>(abs(offset->y));
11336a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    offset_extent.depth = static_cast<uint32_t>(abs(offset->z));
11345971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton    if (IsExtentAllZeroes(granularity)) {
11356a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // If the queue family image transfer granularity is (0, 0, 0), then the offset must always be (0, 0, 0)
11365971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        if (IsExtentAllZeroes(&offset_extent) == false) {
11376a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
11386a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            DRAWSTATE_IMAGE_TRANSFER_GRANULARITY, "DS",
11396a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            "%s: pRegion[%d].%s (x=%d, y=%d, z=%d) must be (x=0, y=0, z=0) "
11406a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            "when the command buffer's queue family image transfer granularity is (w=0, h=0, d=0).",
11416a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            function, i, member, offset->x, offset->y, offset->z);
11426a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
11436a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    } else {
11446a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // If the queue family image transfer granularity is not (0, 0, 0), then the offset dimensions must always be even
11456a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // integer multiples of the image transfer granularity.
11466a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if (IsExtentAligned(&offset_extent, granularity) == false) {
11476a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
11486a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            DRAWSTATE_IMAGE_TRANSFER_GRANULARITY, "DS",
11496a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            "%s: pRegion[%d].%s (x=%d, y=%d, z=%d) dimensions must be even integer "
11506a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            "multiples of this command buffer's queue family image transfer granularity (w=%d, h=%d, d=%d).",
11516a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            function, i, member, offset->x, offset->y, offset->z, granularity->width, granularity->height,
11526a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            granularity->depth);
11536a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
11546a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    }
11556a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    return skip;
11566a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski}
11576a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
11586a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski// Check elements of a VkExtent3D structure against a queue family's Image Transfer Granularity values
11596a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinskistatic inline bool CheckItgExtent(layer_data *device_data, const GLOBAL_CB_NODE *cb_node, const VkExtent3D *extent,
11606a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                  const VkOffset3D *offset, const VkExtent3D *granularity, const VkExtent3D *subresource_extent,
11616a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                  const uint32_t i, const char *function, const char *member) {
11626a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
11636a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    bool skip = false;
11645971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton    if (IsExtentAllZeroes(granularity)) {
11656a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // If the queue family image transfer granularity is (0, 0, 0), then the extent must always match the image
11666a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // subresource extent.
11676a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if (IsExtentEqual(extent, subresource_extent) == false) {
11686a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
11696a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            DRAWSTATE_IMAGE_TRANSFER_GRANULARITY, "DS",
11706a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            "%s: pRegion[%d].%s (w=%d, h=%d, d=%d) must match the image subresource extents (w=%d, h=%d, d=%d) "
11716a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            "when the command buffer's queue family image transfer granularity is (w=0, h=0, d=0).",
11726a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            function, i, member, extent->width, extent->height, extent->depth, subresource_extent->width,
11736a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            subresource_extent->height, subresource_extent->depth);
11746a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
11756a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    } else {
11766a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // If the queue family image transfer granularity is not (0, 0, 0), then the extent dimensions must always be even
11776a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // integer multiples of the image transfer granularity or the offset + extent dimensions must always match the image
11786a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // subresource extent dimensions.
11796a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        VkExtent3D offset_extent_sum = {};
11806a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        offset_extent_sum.width = static_cast<uint32_t>(abs(offset->x)) + extent->width;
11816a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        offset_extent_sum.height = static_cast<uint32_t>(abs(offset->y)) + extent->height;
11826a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        offset_extent_sum.depth = static_cast<uint32_t>(abs(offset->z)) + extent->depth;
11836a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if ((IsExtentAligned(extent, granularity) == false) && (IsExtentEqual(&offset_extent_sum, subresource_extent) == false)) {
11846a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            skip |=
11856a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
11866a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                        DRAWSTATE_IMAGE_TRANSFER_GRANULARITY, "DS",
11876a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                        "%s: pRegion[%d].%s (w=%d, h=%d, d=%d) dimensions must be even integer multiples of this command buffer's "
11886a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                        "queue family image transfer granularity (w=%d, h=%d, d=%d) or offset (x=%d, y=%d, z=%d) + "
11896a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                        "extent (w=%d, h=%d, d=%d) must match the image subresource extents (w=%d, h=%d, d=%d).",
11906a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                        function, i, member, extent->width, extent->height, extent->depth, granularity->width, granularity->height,
11916a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                        granularity->depth, offset->x, offset->y, offset->z, extent->width, extent->height, extent->depth,
11926a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                        subresource_extent->width, subresource_extent->height, subresource_extent->depth);
11936a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
11946a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    }
11956a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    return skip;
11966a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski}
11976a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
11986a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski// Check a uint32_t width or stride value against a queue family's Image Transfer Granularity width value
11996a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinskistatic inline bool CheckItgInt(layer_data *device_data, const GLOBAL_CB_NODE *cb_node, const uint32_t value,
12006a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                               const uint32_t granularity, const uint32_t i, const char *function, const char *member) {
12016a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
12026a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
12036a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    bool skip = false;
12046a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    if (vk_safe_modulo(value, granularity) != 0) {
12056a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
12066a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                        DRAWSTATE_IMAGE_TRANSFER_GRANULARITY, "DS",
12076a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                        "%s: pRegion[%d].%s (%d) must be an even integer multiple of this command buffer's queue family image "
12086a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                        "transfer granularity width (%d).",
12096a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                        function, i, member, value, granularity);
12106a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    }
12116a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    return skip;
12126a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski}
12136a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
12146a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski// Check a VkDeviceSize value against a queue family's Image Transfer Granularity width value
12156a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinskistatic inline bool CheckItgSize(layer_data *device_data, const GLOBAL_CB_NODE *cb_node, const VkDeviceSize value,
12166a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                const uint32_t granularity, const uint32_t i, const char *function, const char *member) {
12176a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
12186a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    bool skip = false;
12196a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    if (vk_safe_modulo(value, granularity) != 0) {
12206a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
12216a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                        DRAWSTATE_IMAGE_TRANSFER_GRANULARITY, "DS",
12226a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                        "%s: pRegion[%d].%s (%" PRIdLEAST64
12236a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                        ") must be an even integer multiple of this command buffer's queue family image transfer "
12246a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                        "granularity width (%d).",
12256a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                        function, i, member, value, granularity);
12266a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    }
12276a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    return skip;
12286a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski}
12296a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
12306a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski// Check valid usage Image Tranfer Granularity requirements for elements of a VkBufferImageCopy structure
12316a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinskibool ValidateCopyBufferImageTransferGranularityRequirements(layer_data *device_data, const GLOBAL_CB_NODE *cb_node,
12326a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                                            const IMAGE_STATE *img, const VkBufferImageCopy *region,
12336a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                                            const uint32_t i, const char *function) {
12346a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    bool skip = false;
12356a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    if (vk_format_is_compressed(img->createInfo.format) == true) {
12366a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // TODO: Add granularity checking for compressed formats
12376a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
12386a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // bufferRowLength must be a multiple of the compressed texel block width
12396a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // bufferImageHeight must be a multiple of the compressed texel block height
12406a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // all members of imageOffset must be a multiple of the corresponding dimensions of the compressed texel block
12416a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // bufferOffset must be a multiple of the compressed texel block size in bytes
12426a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // imageExtent.width must be a multiple of the compressed texel block width or (imageExtent.width + imageOffset.x)
12436a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        //     must equal the image subresource width
12446a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // imageExtent.height must be a multiple of the compressed texel block height or (imageExtent.height + imageOffset.y)
12456a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        //     must equal the image subresource height
12466a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // imageExtent.depth must be a multiple of the compressed texel block depth or (imageExtent.depth + imageOffset.z)
12476a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        //     must equal the image subresource depth
12486a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    } else {
12496a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        VkExtent3D granularity = GetScaledItg(device_data, cb_node, img);
12506a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        skip |= CheckItgSize(device_data, cb_node, region->bufferOffset, granularity.width, i, function, "bufferOffset");
12516a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        skip |= CheckItgInt(device_data, cb_node, region->bufferRowLength, granularity.width, i, function, "bufferRowLength");
12526a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        skip |= CheckItgInt(device_data, cb_node, region->bufferImageHeight, granularity.width, i, function, "bufferImageHeight");
12536a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        skip |= CheckItgOffset(device_data, cb_node, &region->imageOffset, &granularity, i, function, "imageOffset");
12546a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        VkExtent3D subresource_extent = GetImageSubresourceExtent(img, &region->imageSubresource);
12556a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        skip |= CheckItgExtent(device_data, cb_node, &region->imageExtent, &region->imageOffset, &granularity, &subresource_extent,
12566a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                               i, function, "imageExtent");
12576a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    }
12586a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    return skip;
12596a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski}
12606a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
12616a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski// Check valid usage Image Tranfer Granularity requirements for elements of a VkImageCopy structure
12626a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinskibool ValidateCopyImageTransferGranularityRequirements(layer_data *device_data, const GLOBAL_CB_NODE *cb_node,
12636a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                                      const IMAGE_STATE *img, const VkImageCopy *region, const uint32_t i,
12646a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                                      const char *function) {
12656a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    bool skip = false;
12666a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    VkExtent3D granularity = GetScaledItg(device_data, cb_node, img);
12676a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    skip |= CheckItgOffset(device_data, cb_node, &region->srcOffset, &granularity, i, function, "srcOffset");
12686a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    skip |= CheckItgOffset(device_data, cb_node, &region->dstOffset, &granularity, i, function, "dstOffset");
12696a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    VkExtent3D subresource_extent = GetImageSubresourceExtent(img, &region->dstSubresource);
12706a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    skip |= CheckItgExtent(device_data, cb_node, &region->extent, &region->dstOffset, &granularity, &subresource_extent, i,
12716a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                           function, "extent");
12726a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    return skip;
12736a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski}
12746a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
1275e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisbool PreCallValidateCmdCopyImage(layer_data *device_data, GLOBAL_CB_NODE *cb_node, IMAGE_STATE *src_image_state,
12766a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                 IMAGE_STATE *dst_image_state, uint32_t region_count, const VkImageCopy *regions,
12776a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                 VkImageLayout src_image_layout, VkImageLayout dst_image_layout) {
1278ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    bool skip = false;
1279ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
1280ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    VkCommandBuffer command_buffer = cb_node->commandBuffer;
1281ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
12826a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    for (uint32_t i = 0; i < region_count; i++) {
12836a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if (regions[i].srcSubresource.layerCount == 0) {
12846a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            std::stringstream ss;
12856a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            ss << "vkCmdCopyImage: number of layers in pRegions[" << i << "] srcSubresource is zero";
12866a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
12876a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            reinterpret_cast<uint64_t &>(command_buffer), __LINE__, DRAWSTATE_INVALID_IMAGE_ASPECT, "IMAGE", "%s",
12886a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            ss.str().c_str());
12896a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
1290ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
12916a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if (regions[i].dstSubresource.layerCount == 0) {
12926a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            std::stringstream ss;
12936a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            ss << "vkCmdCopyImage: number of layers in pRegions[" << i << "] dstSubresource is zero";
12946a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
12956a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            reinterpret_cast<uint64_t &>(command_buffer), __LINE__, DRAWSTATE_INVALID_IMAGE_ASPECT, "IMAGE", "%s",
12966a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            ss.str().c_str());
12976a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
1298ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
12996a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // For each region the layerCount member of srcSubresource and dstSubresource must match
13006a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if (regions[i].srcSubresource.layerCount != regions[i].dstSubresource.layerCount) {
13016a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            std::stringstream ss;
13026a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            ss << "vkCmdCopyImage: number of layers in source and destination subresources for pRegions[" << i << "] do not match";
13036a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
13046a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01198, "IMAGE", "%s. %s",
13056a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            ss.str().c_str(), validation_error_map[VALIDATION_ERROR_01198]);
13066a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
1307ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
13086a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // For each region, the aspectMask member of srcSubresource and dstSubresource must match
13096a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if (regions[i].srcSubresource.aspectMask != regions[i].dstSubresource.aspectMask) {
13106a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            char const str[] = "vkCmdCopyImage: Src and dest aspectMasks for each region must match";
13116a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
13126a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01197, "IMAGE", "%s. %s", str,
13136a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            validation_error_map[VALIDATION_ERROR_01197]);
13146a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
1315ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
13166a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // AspectMask must not contain VK_IMAGE_ASPECT_METADATA_BIT
13176a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if ((regions[i].srcSubresource.aspectMask & VK_IMAGE_ASPECT_METADATA_BIT) ||
13186a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            (regions[i].dstSubresource.aspectMask & VK_IMAGE_ASPECT_METADATA_BIT)) {
13196a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            std::stringstream ss;
13206a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            ss << "vkCmdCopyImage: pRegions[" << i << "] may not specify aspectMask containing VK_IMAGE_ASPECT_METADATA_BIT";
13216a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
13226a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01222, "IMAGE", "%s. %s",
13236a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            ss.str().c_str(), validation_error_map[VALIDATION_ERROR_01222]);
13246a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
1325ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
13266a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // For each region, if aspectMask contains VK_IMAGE_ASPECT_COLOR_BIT, it must not contain either of
13276a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // VK_IMAGE_ASPECT_DEPTH_BIT or VK_IMAGE_ASPECT_STENCIL_BIT
13286a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if ((regions[i].srcSubresource.aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) &&
13296a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            (regions[i].srcSubresource.aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))) {
13306a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            char const str[] = "vkCmdCopyImage aspectMask cannot specify both COLOR and DEPTH/STENCIL aspects";
13316a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
13326a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01221, "IMAGE", "%s. %s", str,
13336a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            validation_error_map[VALIDATION_ERROR_01221]);
13346a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
1335ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
13366a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // If either of the calling command's src_image or dst_image parameters are of VkImageType VK_IMAGE_TYPE_3D,
13376a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // the baseArrayLayer and layerCount members of both srcSubresource and dstSubresource must be 0 and 1, respectively
13386a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if (((src_image_state->createInfo.imageType == VK_IMAGE_TYPE_3D) ||
13396a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski             (dst_image_state->createInfo.imageType == VK_IMAGE_TYPE_3D)) &&
13406a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            ((regions[i].srcSubresource.baseArrayLayer != 0) || (regions[i].srcSubresource.layerCount != 1) ||
13416a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski             (regions[i].dstSubresource.baseArrayLayer != 0) || (regions[i].dstSubresource.layerCount != 1))) {
13426a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            std::stringstream ss;
13436a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            ss << "vkCmdCopyImage: src or dstImage type was IMAGE_TYPE_3D, but in subRegion[" << i
13446a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski               << "] baseArrayLayer was not zero or layerCount was not 1.";
13456a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
13466a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01199, "IMAGE", "%s. %s",
13476a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            ss.str().c_str(), validation_error_map[VALIDATION_ERROR_01199]);
13486a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
1349ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
13506a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // MipLevel must be less than the mipLevels specified in VkImageCreateInfo when the image was created
13516a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if (regions[i].srcSubresource.mipLevel >= src_image_state->createInfo.mipLevels) {
13526a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            std::stringstream ss;
13536a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            ss << "vkCmdCopyImage: pRegions[" << i
13546a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski               << "] specifies a src mipLevel greater than the number specified when the srcImage was created.";
13556a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
13566a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01223, "IMAGE", "%s. %s",
13576a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            ss.str().c_str(), validation_error_map[VALIDATION_ERROR_01223]);
13586a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
13596a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if (regions[i].dstSubresource.mipLevel >= dst_image_state->createInfo.mipLevels) {
13606a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            std::stringstream ss;
13616a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            ss << "vkCmdCopyImage: pRegions[" << i
13626a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski               << "] specifies a dst mipLevel greater than the number specified when the dstImage was created.";
13636a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
13646a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01223, "IMAGE", "%s. %s",
13656a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            ss.str().c_str(), validation_error_map[VALIDATION_ERROR_01223]);
13666a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
1367ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
13686a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // (baseArrayLayer + layerCount) must be less than or equal to the arrayLayers specified in VkImageCreateInfo when the
13696a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // image was created
13706a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if ((regions[i].srcSubresource.baseArrayLayer + regions[i].srcSubresource.layerCount) >
13716a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            src_image_state->createInfo.arrayLayers) {
13726a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            std::stringstream ss;
13736a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            ss << "vkCmdCopyImage: srcImage arrayLayers was " << src_image_state->createInfo.arrayLayers << " but subRegion[" << i
13746a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski               << "] baseArrayLayer + layerCount is "
13756a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski               << (regions[i].srcSubresource.baseArrayLayer + regions[i].srcSubresource.layerCount);
13766a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
13776a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01224, "IMAGE", "%s. %s",
13786a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            ss.str().c_str(), validation_error_map[VALIDATION_ERROR_01224]);
13796a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
13806a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if ((regions[i].dstSubresource.baseArrayLayer + regions[i].dstSubresource.layerCount) >
13816a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            dst_image_state->createInfo.arrayLayers) {
13826a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            std::stringstream ss;
13836a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            ss << "vkCmdCopyImage: dstImage arrayLayers was " << dst_image_state->createInfo.arrayLayers << " but subRegion[" << i
13846a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski               << "] baseArrayLayer + layerCount is "
13856a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski               << (regions[i].dstSubresource.baseArrayLayer + regions[i].dstSubresource.layerCount);
13866a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
13876a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01224, "IMAGE", "%s. %s",
13886a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            ss.str().c_str(), validation_error_map[VALIDATION_ERROR_01224]);
13896a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
1390ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
13916a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // The source region specified by a given element of regions must be a region that is contained within srcImage
13925971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        if (ExceedsBounds(&regions[i].srcOffset, &regions[i].extent, &(src_image_state->createInfo.extent))) {
13936a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            std::stringstream ss;
13946a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            ss << "vkCmdCopyImage: srcSubResource in pRegions[" << i << "] exceeds extents srcImage was created with";
13956a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
13966a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01175, "IMAGE", "%s. %s",
13976a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            ss.str().c_str(), validation_error_map[VALIDATION_ERROR_01175]);
13986a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
1399ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
14006a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // The destination region specified by a given element of regions must be a region that is contained within dst_image
14015971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        if (ExceedsBounds(&regions[i].dstOffset, &regions[i].extent, &(dst_image_state->createInfo.extent))) {
14026a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            std::stringstream ss;
14036a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            ss << "vkCmdCopyImage: dstSubResource in pRegions[" << i << "] exceeds extents dstImage was created with";
14046a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
14056a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01176, "IMAGE", "%s. %s",
14066a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            ss.str().c_str(), validation_error_map[VALIDATION_ERROR_01176]);
14076a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
1408ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
14096a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // The union of all source regions, and the union of all destination regions, specified by the elements of regions,
14106a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        // must not overlap in memory
14116a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if (src_image_state->image == dst_image_state->image) {
14126a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            for (uint32_t j = 0; j < region_count; j++) {
14136a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                if (RegionIntersects(&regions[i], &regions[j], src_image_state->createInfo.imageType)) {
14146a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                    std::stringstream ss;
14156a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                    ss << "vkCmdCopyImage: pRegions[" << i << "] src overlaps with pRegions[" << j << "].";
14166a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                    skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
14176a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                    reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01177, "IMAGE",
14186a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                    "%s. %s", ss.str().c_str(), validation_error_map[VALIDATION_ERROR_01177]);
1419ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski                }
1420ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski            }
1421ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski        }
14226a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    }
1423ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski
14246a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    // The formats of src_image and dst_image must be compatible. Formats are considered compatible if their texel size in bytes
14256a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    // is the same between both formats. For example, VK_FORMAT_R8G8B8A8_UNORM is compatible with VK_FORMAT_R32_UINT because
14266a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    // because both texels are 4 bytes in size. Depth/stencil formats must match exactly.
14276a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    if (vk_format_is_depth_or_stencil(src_image_state->createInfo.format) ||
14286a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        vk_format_is_depth_or_stencil(dst_image_state->createInfo.format)) {
14296a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if (src_image_state->createInfo.format != dst_image_state->createInfo.format) {
14306a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            char const str[] = "vkCmdCopyImage called with unmatched source and dest image depth/stencil formats.";
14316a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            skip |=
14326a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
14336a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                        reinterpret_cast<uint64_t &>(command_buffer), __LINE__, DRAWSTATE_MISMATCHED_IMAGE_FORMAT, "IMAGE", str);
14346a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        }
14356a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    } else {
14366a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        size_t srcSize = vk_format_get_size(src_image_state->createInfo.format);
14376a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        size_t destSize = vk_format_get_size(dst_image_state->createInfo.format);
14386a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if (srcSize != destSize) {
14396a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            char const str[] = "vkCmdCopyImage called with unmatched source and dest image format sizes.";
14406a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
14416a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01184, "IMAGE", "%s. %s", str,
14426a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                            validation_error_map[VALIDATION_ERROR_01184]);
1443ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski        }
1444ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    }
14456a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
144692c9c5dfbd0dec1d76ca18faa487fa8c2d302a65Dave Houlton    // Source and dest image sample counts must match
144792c9c5dfbd0dec1d76ca18faa487fa8c2d302a65Dave Houlton    if (src_image_state->createInfo.samples != dst_image_state->createInfo.samples) {
144892c9c5dfbd0dec1d76ca18faa487fa8c2d302a65Dave Houlton        char const str[] = "vkCmdCopyImage() called on image pair with non-identical sample counts.";
144992c9c5dfbd0dec1d76ca18faa487fa8c2d302a65Dave Houlton        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
145092c9c5dfbd0dec1d76ca18faa487fa8c2d302a65Dave Houlton            reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01185, "IMAGE", "%s %s", str,
145192c9c5dfbd0dec1d76ca18faa487fa8c2d302a65Dave Houlton            validation_error_map[VALIDATION_ERROR_01185]);
145292c9c5dfbd0dec1d76ca18faa487fa8c2d302a65Dave Houlton    }
145392c9c5dfbd0dec1d76ca18faa487fa8c2d302a65Dave Houlton
14546a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    skip |= ValidateMemoryIsBoundToImage(device_data, src_image_state, "vkCmdCopyImage()", VALIDATION_ERROR_02533);
14556a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    skip |= ValidateMemoryIsBoundToImage(device_data, dst_image_state, "vkCmdCopyImage()", VALIDATION_ERROR_02534);
14566a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    // Validate that SRC & DST images have correct usage flags set
14576a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    skip |= ValidateImageUsageFlags(device_data, src_image_state, VK_IMAGE_USAGE_TRANSFER_SRC_BIT, true, VALIDATION_ERROR_01178,
14586a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                    "vkCmdCopyImage()", "VK_IMAGE_USAGE_TRANSFER_SRC_BIT");
14596a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    skip |= ValidateImageUsageFlags(device_data, dst_image_state, VK_IMAGE_USAGE_TRANSFER_DST_BIT, true, VALIDATION_ERROR_01181,
14606a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                    "vkCmdCopyImage()", "VK_IMAGE_USAGE_TRANSFER_DST_BIT");
14616a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    skip |= ValidateCmd(device_data, cb_node, CMD_COPYIMAGE, "vkCmdCopyImage()");
14626a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    skip |= insideRenderPass(device_data, cb_node, "vkCmdCopyImage()", VALIDATION_ERROR_01194);
14636a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    for (uint32_t i = 0; i < region_count; ++i) {
14646a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        skip |= VerifySourceImageLayout(device_data, cb_node, src_image_state->image, regions[i].srcSubresource, src_image_layout,
14656a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                        VALIDATION_ERROR_01180);
14666a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        skip |= VerifyDestImageLayout(device_data, cb_node, dst_image_state->image, regions[i].dstSubresource, dst_image_layout,
14676a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                      VALIDATION_ERROR_01183);
14686a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        skip |= ValidateCopyImageTransferGranularityRequirements(device_data, cb_node, dst_image_state, &regions[i], i,
14696a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                                                 "vkCmdCopyImage()");
14706a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    }
14716a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
1472ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski    return skip;
1473ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski}
1474a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski
14756a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinskivoid PreCallRecordCmdCopyImage(layer_data *device_data, GLOBAL_CB_NODE *cb_node, IMAGE_STATE *src_image_state,
14766a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                               IMAGE_STATE *dst_image_state) {
14776a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    // Update bindings between images and cmd buffer
14786a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    AddCommandBufferBindingImage(device_data, cb_node, src_image_state);
14796a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    AddCommandBufferBindingImage(device_data, cb_node, dst_image_state);
14803f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton    std::function<bool()> function = [=]() { return ValidateImageMemoryIsValid(device_data, src_image_state, "vkCmdCopyImage()"); };
14816a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    cb_node->validate_functions.push_back(function);
14826a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    function = [=]() {
14836a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        SetImageMemoryValid(device_data, dst_image_state, true);
14846a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        return false;
14856a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    };
14866a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    cb_node->validate_functions.push_back(function);
14876a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    core_validation::UpdateCmdBufferLastCmd(cb_node, CMD_COPYIMAGE);
14886a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski}
14896a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
1490a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski// TODO : Should be tracking lastBound per commandBuffer and when draws occur, report based on that cmd buffer lastBound
1491a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski//   Then need to synchronize the accesses based on cmd buffer so that if I'm reading state on one cmd buffer, updates
1492a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski//   to that same cmd buffer by separate thread are not changing state from underneath us
1493a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski// Track the last cmd buffer touched by this thread
1494a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinskistatic bool hasDrawCmd(GLOBAL_CB_NODE *pCB) {
1495a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski    for (uint32_t i = 0; i < NUM_DRAW_TYPES; i++) {
1496a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski        if (pCB->drawCount[i]) return true;
1497a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski    }
1498a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski    return false;
1499a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski}
1500a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski
1501a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski// Returns true if sub_rect is entirely contained within rect
1502a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinskistatic inline bool ContainsRect(VkRect2D rect, VkRect2D sub_rect) {
1503a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski    if ((sub_rect.offset.x < rect.offset.x) || (sub_rect.offset.x + sub_rect.extent.width > rect.offset.x + rect.extent.width) ||
1504a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski        (sub_rect.offset.y < rect.offset.y) || (sub_rect.offset.y + sub_rect.extent.height > rect.offset.y + rect.extent.height))
1505a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski        return false;
1506a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski    return true;
1507a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski}
1508a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski
1509e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisbool PreCallValidateCmdClearAttachments(layer_data *device_data, VkCommandBuffer commandBuffer, uint32_t attachmentCount,
1510e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlis                                        const VkClearAttachment *pAttachments, uint32_t rectCount, const VkClearRect *pRects) {
15119a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    GLOBAL_CB_NODE *cb_node = GetCBNode(device_data, commandBuffer);
1512a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
1513a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski
1514a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski    bool skip = false;
1515a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski    if (cb_node) {
1516a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski        skip |= ValidateCmd(device_data, cb_node, CMD_CLEARATTACHMENTS, "vkCmdClearAttachments()");
15179a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        core_validation::UpdateCmdBufferLastCmd(cb_node, CMD_CLEARATTACHMENTS);
1518a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski        // Warn if this is issued prior to Draw Cmd and clearing the entire attachment
1519a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski        if (!hasDrawCmd(cb_node) && (cb_node->activeRenderPassBeginInfo.renderArea.extent.width == pRects[0].rect.extent.width) &&
1520a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski            (cb_node->activeRenderPassBeginInfo.renderArea.extent.height == pRects[0].rect.extent.height)) {
1521a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski            // There are times where app needs to use ClearAttachments (generally when reusing a buffer inside of a render pass)
15228e0190bd5904b8a8f044dae2c6ae23a891eb5e11Mark 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
15238e0190bd5904b8a8f044dae2c6ae23a891eb5e11Mark Lobodzinski            // CmdClearAttachments.
152473f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski            skip |=
152573f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                log_msg(report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
152673f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                        reinterpret_cast<uint64_t &>(commandBuffer), 0, DRAWSTATE_CLEAR_CMD_BEFORE_DRAW, "DS",
152773f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                        "vkCmdClearAttachments() issued on command buffer object 0x%p prior to any Draw Cmds."
152873f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                        " It is recommended you use RenderPass LOAD_OP_CLEAR on Attachments prior to any Draw.",
152973f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                        commandBuffer);
1530a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski        }
1531a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski        skip |= outsideRenderPass(device_data, cb_node, "vkCmdClearAttachments()", VALIDATION_ERROR_01122);
1532a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski    }
1533a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski
1534a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski    // Validate that attachment is in reference list of active subpass
1535a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski    if (cb_node->activeRenderPass) {
1536a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski        const VkRenderPassCreateInfo *renderpass_create_info = cb_node->activeRenderPass->createInfo.ptr();
1537a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski        const VkSubpassDescription *subpass_desc = &renderpass_create_info->pSubpasses[cb_node->activeSubpass];
15389a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto framebuffer = GetFramebufferState(device_data, cb_node->activeFramebuffer);
1539a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski
1540a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski        for (uint32_t i = 0; i < attachmentCount; i++) {
1541a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski            auto clear_desc = &pAttachments[i];
1542a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski            VkImageView image_view = VK_NULL_HANDLE;
1543a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski
154473f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski            if (0 == clear_desc->aspectMask) {
154573f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
154673f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                (uint64_t)commandBuffer, __LINE__, VALIDATION_ERROR_01128, "IMAGE", "%s",
154773f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                validation_error_map[VALIDATION_ERROR_01128]);
154873f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski            } else if (clear_desc->aspectMask & VK_IMAGE_ASPECT_METADATA_BIT) {
154973f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
155073f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                (uint64_t)commandBuffer, __LINE__, VALIDATION_ERROR_01126, "IMAGE", "%s",
155173f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                validation_error_map[VALIDATION_ERROR_01126]);
155273f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski            } else if (clear_desc->aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) {
1553a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                if (clear_desc->colorAttachment >= subpass_desc->colorAttachmentCount) {
155473f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                    skip |=
155573f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                        log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
155673f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                (uint64_t)commandBuffer, __LINE__, VALIDATION_ERROR_01114, "DS",
155773f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                "vkCmdClearAttachments() color attachment index %d out of range for active subpass %d. %s",
155873f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                clear_desc->colorAttachment, cb_node->activeSubpass, validation_error_map[VALIDATION_ERROR_01114]);
1559a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                } else if (subpass_desc->pColorAttachments[clear_desc->colorAttachment].attachment == VK_ATTACHMENT_UNUSED) {
1560a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                    skip |= log_msg(report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT,
156173f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                    VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)commandBuffer, __LINE__,
156273f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                    DRAWSTATE_MISSING_ATTACHMENT_REFERENCE, "DS",
156373f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                    "vkCmdClearAttachments() color attachment index %d is VK_ATTACHMENT_UNUSED; ignored.",
156473f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                    clear_desc->colorAttachment);
1565a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                } else {
1566a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                    image_view = framebuffer->createInfo
156773f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                     .pAttachments[subpass_desc->pColorAttachments[clear_desc->colorAttachment].attachment];
1568a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                }
156973f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                if ((clear_desc->aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) ||
157073f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                    (clear_desc->aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT)) {
157173f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                    char const str[] =
157273f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                        "vkCmdClearAttachments aspectMask [%d] must set only VK_IMAGE_ASPECT_COLOR_BIT of a color attachment. %s";
157373f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                    skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
157473f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                    (uint64_t)commandBuffer, __LINE__, VALIDATION_ERROR_01125, "IMAGE", str, i,
157573f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                    validation_error_map[VALIDATION_ERROR_01125]);
157673f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                }
157773f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski            } else {  // Must be depth and/or stencil
157873f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                if (((clear_desc->aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) != VK_IMAGE_ASPECT_DEPTH_BIT) &&
157973f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                    ((clear_desc->aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) != VK_IMAGE_ASPECT_STENCIL_BIT)) {
158073f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                    char const str[] = "vkCmdClearAttachments aspectMask [%d] is not a valid combination of bits. %s";
158173f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                    skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
158273f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                    (uint64_t)commandBuffer, __LINE__, VALIDATION_ERROR_01127, "IMAGE", str, i,
158373f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                    validation_error_map[VALIDATION_ERROR_01127]);
158473f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                }
158573f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                if (!subpass_desc->pDepthStencilAttachment ||
158673f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                    (subpass_desc->pDepthStencilAttachment->attachment == VK_ATTACHMENT_UNUSED)) {
158773f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                    skip |= log_msg(
158873f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                        report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
158973f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                        (uint64_t)commandBuffer, __LINE__, DRAWSTATE_MISSING_ATTACHMENT_REFERENCE, "DS",
159073f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                        "vkCmdClearAttachments() depth/stencil clear with no depth/stencil attachment in subpass; ignored");
1591a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                } else {
1592a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                    image_view = framebuffer->createInfo.pAttachments[subpass_desc->pDepthStencilAttachment->attachment];
1593a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                }
1594a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski            }
1595a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski            if (image_view) {
15969a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis                auto image_view_state = GetImageViewState(device_data, image_view);
1597a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                for (uint32_t j = 0; j < rectCount; j++) {
159873f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                    // The rectangular region specified by a given element of pRects must be contained within the render area of
159973f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                    // the current render pass instance
16008e0190bd5904b8a8f044dae2c6ae23a891eb5e11Mark Lobodzinski                    // TODO: This check should be moved to CmdExecuteCommands or QueueSubmit to cover secondary CB cases
16018e0190bd5904b8a8f044dae2c6ae23a891eb5e11Mark Lobodzinski                    if ((cb_node->createInfo.level == VK_COMMAND_BUFFER_LEVEL_PRIMARY) &&
16028e0190bd5904b8a8f044dae2c6ae23a891eb5e11Mark Lobodzinski                        (false == ContainsRect(cb_node->activeRenderPassBeginInfo.renderArea, pRects[j].rect))) {
160373f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
160473f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                        __LINE__, VALIDATION_ERROR_01115, "DS",
160573f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                        "vkCmdClearAttachments(): The area defined by pRects[%d] is not contained in the area of "
160673f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                        "the current render pass instance. %s",
160773f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                        j, validation_error_map[VALIDATION_ERROR_01115]);
1608a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                    }
1609a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                    // The layers specified by a given element of pRects must be contained within every attachment that
1610a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                    // pAttachments refers to
1611a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                    auto attachment_base_array_layer = image_view_state->create_info.subresourceRange.baseArrayLayer;
1612a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                    auto attachment_layer_count = image_view_state->create_info.subresourceRange.layerCount;
1613a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                    if ((pRects[j].baseArrayLayer < attachment_base_array_layer) || pRects[j].layerCount > attachment_layer_count) {
1614a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                        skip |=
161573f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                            log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
161673f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                    __LINE__, VALIDATION_ERROR_01116, "DS",
161773f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                    "vkCmdClearAttachments(): The layers defined in pRects[%d] are not contained in the layers of "
161873f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                    "pAttachment[%d]. %s",
161973f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski                                    j, i, validation_error_map[VALIDATION_ERROR_01116]);
1620a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                    }
1621a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski                }
1622a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski            }
1623a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski        }
1624a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski    }
1625a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski    return skip;
162660568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski}
162760568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski
1628e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisbool PreCallValidateCmdResolveImage(layer_data *device_data, GLOBAL_CB_NODE *cb_node, IMAGE_STATE *src_image_state,
162954c03b0fa365789b242e680223bd30c940f1abb3Mark Lobodzinski                                    IMAGE_STATE *dst_image_state, uint32_t regionCount, const VkImageResolve *pRegions) {
163025f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
163160568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    bool skip = false;
163260568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    if (cb_node && src_image_state && dst_image_state) {
163360568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        skip |= ValidateMemoryIsBoundToImage(device_data, src_image_state, "vkCmdResolveImage()", VALIDATION_ERROR_02541);
163460568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        skip |= ValidateMemoryIsBoundToImage(device_data, dst_image_state, "vkCmdResolveImage()", VALIDATION_ERROR_02542);
163560568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        skip |= ValidateCmd(device_data, cb_node, CMD_RESOLVEIMAGE, "vkCmdResolveImage()");
163660568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        skip |= insideRenderPass(device_data, cb_node, "vkCmdResolveImage()", VALIDATION_ERROR_01335);
163725f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski
163825f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski        // For each region, the number of layers in the image subresource should not be zero
163925f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski        // For each region, src and dest image aspect must be color only
164025f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski        for (uint32_t i = 0; i < regionCount; i++) {
164125f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski            if (pRegions[i].srcSubresource.layerCount == 0) {
164225f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                char const str[] = "vkCmdResolveImage: number of layers in source subresource is zero";
164354c03b0fa365789b242e680223bd30c940f1abb3Mark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
164425f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                                reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, DRAWSTATE_MISMATCHED_IMAGE_ASPECT,
164525f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                                "IMAGE", str);
164625f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski            }
164725f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski            if (pRegions[i].dstSubresource.layerCount == 0) {
164825f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                char const str[] = "vkCmdResolveImage: number of layers in destination subresource is zero";
164954c03b0fa365789b242e680223bd30c940f1abb3Mark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
165025f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                                reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, DRAWSTATE_MISMATCHED_IMAGE_ASPECT,
165125f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                                "IMAGE", str);
165225f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski            }
165354c03b0fa365789b242e680223bd30c940f1abb3Mark Lobodzinski            if (pRegions[i].srcSubresource.layerCount != pRegions[i].dstSubresource.layerCount) {
165454c03b0fa365789b242e680223bd30c940f1abb3Mark Lobodzinski                skip |= log_msg(
165554c03b0fa365789b242e680223bd30c940f1abb3Mark Lobodzinski                    report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
165654c03b0fa365789b242e680223bd30c940f1abb3Mark Lobodzinski                    reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_01339, "IMAGE",
165754c03b0fa365789b242e680223bd30c940f1abb3Mark Lobodzinski                    "vkCmdResolveImage: layerCount in source and destination subresource of pRegions[%d] does not match. %s", i,
165854c03b0fa365789b242e680223bd30c940f1abb3Mark Lobodzinski                    validation_error_map[VALIDATION_ERROR_01339]);
165954c03b0fa365789b242e680223bd30c940f1abb3Mark Lobodzinski            }
166025f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski            if ((pRegions[i].srcSubresource.aspectMask != VK_IMAGE_ASPECT_COLOR_BIT) ||
166125f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                (pRegions[i].dstSubresource.aspectMask != VK_IMAGE_ASPECT_COLOR_BIT)) {
166225f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                char const str[] =
166325f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                    "vkCmdResolveImage: src and dest aspectMasks for each region must specify only VK_IMAGE_ASPECT_COLOR_BIT";
166425f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
166525f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                                reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_01338, "IMAGE",
166625f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                                "%s. %s", str, validation_error_map[VALIDATION_ERROR_01338]);
166725f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski            }
166825f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski        }
166925f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski
167025f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski        if (src_image_state->createInfo.format != dst_image_state->createInfo.format) {
167125f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski            char const str[] = "vkCmdResolveImage called with unmatched source and dest formats.";
167254c03b0fa365789b242e680223bd30c940f1abb3Mark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
167325f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                            reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, DRAWSTATE_MISMATCHED_IMAGE_FORMAT,
167425f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                            "IMAGE", str);
167525f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski        }
167625f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski        if (src_image_state->createInfo.imageType != dst_image_state->createInfo.imageType) {
167725f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski            char const str[] = "vkCmdResolveImage called with unmatched source and dest image types.";
167854c03b0fa365789b242e680223bd30c940f1abb3Mark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
167925f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                            reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, DRAWSTATE_MISMATCHED_IMAGE_TYPE, "IMAGE",
168025f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                            str);
168125f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski        }
168225f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski        if (src_image_state->createInfo.samples == VK_SAMPLE_COUNT_1_BIT) {
168325f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski            char const str[] = "vkCmdResolveImage called with source sample count less than 2.";
168425f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
168525f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                            reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_01320, "IMAGE", "%s. %s",
168625f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                            str, validation_error_map[VALIDATION_ERROR_01320]);
168725f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski        }
168825f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski        if (dst_image_state->createInfo.samples != VK_SAMPLE_COUNT_1_BIT) {
168925f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski            char const str[] = "vkCmdResolveImage called with dest sample count greater than 1.";
169025f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
169125f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                            reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_01321, "IMAGE", "%s. %s",
169225f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski                            str, validation_error_map[VALIDATION_ERROR_01321]);
169325f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski        }
169460568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    } else {
169560568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        assert(0);
169660568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    }
169760568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    return skip;
169860568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski}
169960568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski
1700e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisvoid PreCallRecordCmdResolveImage(layer_data *device_data, GLOBAL_CB_NODE *cb_node, IMAGE_STATE *src_image_state,
1701e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlis                                  IMAGE_STATE *dst_image_state) {
170260568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    // Update bindings between images and cmd buffer
170360568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    AddCommandBufferBindingImage(device_data, cb_node, src_image_state);
170460568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    AddCommandBufferBindingImage(device_data, cb_node, dst_image_state);
170560568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski
170660568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    std::function<bool()> function = [=]() {
170760568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        return ValidateImageMemoryIsValid(device_data, src_image_state, "vkCmdResolveImage()");
170860568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    };
170960568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    cb_node->validate_functions.push_back(function);
171060568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    function = [=]() {
171160568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        SetImageMemoryValid(device_data, dst_image_state, true);
171260568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        return false;
171360568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    };
171460568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    cb_node->validate_functions.push_back(function);
17159a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    core_validation::UpdateCmdBufferLastCmd(cb_node, CMD_RESOLVEIMAGE);
171660568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski}
171760568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski
1718e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisbool PreCallValidateCmdBlitImage(layer_data *device_data, GLOBAL_CB_NODE *cb_node, IMAGE_STATE *src_image_state,
1719055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                                 IMAGE_STATE *dst_image_state, uint32_t regionCount, const VkImageBlit *pRegions, VkFilter filter) {
1720055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
1721055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski
172260568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    bool skip = false;
172360568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    if (cb_node && src_image_state && dst_image_state) {
172460568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        skip |= ValidateImageSampleCount(device_data, src_image_state, VK_SAMPLE_COUNT_1_BIT, "vkCmdBlitImage(): srcImage",
1725055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                                         VALIDATION_ERROR_02194);
172660568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        skip |= ValidateImageSampleCount(device_data, dst_image_state, VK_SAMPLE_COUNT_1_BIT, "vkCmdBlitImage(): dstImage",
1727055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                                         VALIDATION_ERROR_02195);
172860568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        skip |= ValidateMemoryIsBoundToImage(device_data, src_image_state, "vkCmdBlitImage()", VALIDATION_ERROR_02539);
172960568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        skip |= ValidateMemoryIsBoundToImage(device_data, dst_image_state, "vkCmdBlitImage()", VALIDATION_ERROR_02540);
173060568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        skip |= ValidateImageUsageFlags(device_data, src_image_state, VK_IMAGE_USAGE_TRANSFER_SRC_BIT, true, VALIDATION_ERROR_02182,
1731055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                                        "vkCmdBlitImage()", "VK_IMAGE_USAGE_TRANSFER_SRC_BIT");
173260568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        skip |= ValidateImageUsageFlags(device_data, dst_image_state, VK_IMAGE_USAGE_TRANSFER_DST_BIT, true, VALIDATION_ERROR_02186,
1733055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                                        "vkCmdBlitImage()", "VK_IMAGE_USAGE_TRANSFER_DST_BIT");
173460568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        skip |= ValidateCmd(device_data, cb_node, CMD_BLITIMAGE, "vkCmdBlitImage()");
173560568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        skip |= insideRenderPass(device_data, cb_node, "vkCmdBlitImage()", VALIDATION_ERROR_01300);
1736055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski
1737055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski        for (uint32_t i = 0; i < regionCount; i++) {
1738d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski            // Warn for zero-sized regions
1739055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski            if ((pRegions[i].srcOffsets[0].x == pRegions[i].srcOffsets[1].x) ||
1740055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                (pRegions[i].srcOffsets[0].y == pRegions[i].srcOffsets[1].y) ||
1741055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                (pRegions[i].srcOffsets[0].z == pRegions[i].srcOffsets[1].z)) {
1742055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                std::stringstream ss;
1743055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                ss << "vkCmdBlitImage: pRegions[" << i << "].srcOffsets specify a zero-volume area.";
1744055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1745055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                                reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, DRAWSTATE_INVALID_EXTENTS, "IMAGE",
1746055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                                "%s", ss.str().c_str());
1747055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski            }
1748055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski            if ((pRegions[i].dstOffsets[0].x == pRegions[i].dstOffsets[1].x) ||
1749055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                (pRegions[i].dstOffsets[0].y == pRegions[i].dstOffsets[1].y) ||
1750055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                (pRegions[i].dstOffsets[0].z == pRegions[i].dstOffsets[1].z)) {
1751055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                std::stringstream ss;
1752055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                ss << "vkCmdBlitImage: pRegions[" << i << "].dstOffsets specify a zero-volume area.";
1753055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1754055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                                reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, DRAWSTATE_INVALID_EXTENTS, "IMAGE",
1755055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                                "%s", ss.str().c_str());
1756055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski            }
1757d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski            if (pRegions[i].srcSubresource.layerCount == 0) {
1758d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski                char const str[] = "vkCmdBlitImage: number of layers in source subresource is zero";
1759d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
17603f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                                reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, DRAWSTATE_MISMATCHED_IMAGE_ASPECT,
17613f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                                "IMAGE", str);
1762d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski            }
1763d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski            if (pRegions[i].dstSubresource.layerCount == 0) {
1764d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski                char const str[] = "vkCmdBlitImage: number of layers in destination subresource is zero";
1765d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
17663f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                                reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, DRAWSTATE_MISMATCHED_IMAGE_ASPECT,
17673f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                                "IMAGE", str);
1768d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski            }
1769d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski
1770d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski            // Check that src/dst layercounts match
1771d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski            if (pRegions[i].srcSubresource.layerCount != pRegions[i].dstSubresource.layerCount) {
1772d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski                skip |=
1773d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski                    log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1774d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski                            reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_01304, "IMAGE",
1775d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski                            "vkCmdBlitImage: layerCount in source and destination subresource of pRegions[%d] does not match. %s",
1776d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski                            i, validation_error_map[VALIDATION_ERROR_01304]);
1777d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski            }
17788068cb0f90422b6789d0c120f0831f55eb76b71aMark Lobodzinski
17798068cb0f90422b6789d0c120f0831f55eb76b71aMark Lobodzinski            if (pRegions[i].srcSubresource.aspectMask != pRegions[i].dstSubresource.aspectMask) {
17808068cb0f90422b6789d0c120f0831f55eb76b71aMark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
17818068cb0f90422b6789d0c120f0831f55eb76b71aMark Lobodzinski                                reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_01303, "IMAGE",
17828068cb0f90422b6789d0c120f0831f55eb76b71aMark Lobodzinski                                "vkCmdBlitImage: aspectMask members for pRegion[%d] do not match. %s", i,
17838068cb0f90422b6789d0c120f0831f55eb76b71aMark Lobodzinski                                validation_error_map[VALIDATION_ERROR_01303]);
17848068cb0f90422b6789d0c120f0831f55eb76b71aMark Lobodzinski            }
1785055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski        }
1786055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski
1787055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski        VkFormat src_format = src_image_state->createInfo.format;
1788055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski        VkFormat dst_format = dst_image_state->createInfo.format;
1789055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski
1790055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski        // Validate consistency for unsigned formats
1791055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski        if (vk_format_is_uint(src_format) != vk_format_is_uint(dst_format)) {
1792055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski            std::stringstream ss;
1793055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski            ss << "vkCmdBlitImage: If one of srcImage and dstImage images has unsigned integer format, "
1794055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski               << "the other one must also have unsigned integer format.  "
1795055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski               << "Source format is " << string_VkFormat(src_format) << " Destination format is " << string_VkFormat(dst_format);
1796055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1797055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                            reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_02191, "IMAGE", "%s. %s",
1798055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                            ss.str().c_str(), validation_error_map[VALIDATION_ERROR_02191]);
1799055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski        }
1800055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski
1801055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski        // Validate consistency for signed formats
1802055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski        if (vk_format_is_sint(src_format) != vk_format_is_sint(dst_format)) {
1803055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski            std::stringstream ss;
1804055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski            ss << "vkCmdBlitImage: If one of srcImage and dstImage images has signed integer format, "
1805055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski               << "the other one must also have signed integer format.  "
1806055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski               << "Source format is " << string_VkFormat(src_format) << " Destination format is " << string_VkFormat(dst_format);
1807055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1808055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                            reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_02190, "IMAGE", "%s. %s",
1809055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                            ss.str().c_str(), validation_error_map[VALIDATION_ERROR_02190]);
1810055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski        }
1811055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski
1812055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski        // Validate aspect bits and formats for depth/stencil images
1813055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski        if (vk_format_is_depth_or_stencil(src_format) || vk_format_is_depth_or_stencil(dst_format)) {
1814055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski            if (src_format != dst_format) {
1815055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                std::stringstream ss;
1816055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                ss << "vkCmdBlitImage: If one of srcImage and dstImage images has a format of depth, stencil or depth "
1817055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                   << "stencil, the other one must have exactly the same format.  "
1818055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                   << "Source format is " << string_VkFormat(src_format) << " Destination format is "
1819055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                   << string_VkFormat(dst_format);
1820055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1821055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                                reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_02192, "IMAGE",
1822055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                                "%s. %s", ss.str().c_str(), validation_error_map[VALIDATION_ERROR_02192]);
1823055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski            }
1824055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski
1825055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski            for (uint32_t i = 0; i < regionCount; i++) {
1826055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                VkImageAspectFlags srcAspect = pRegions[i].srcSubresource.aspectMask;
1827055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski
1828055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                if (vk_format_is_depth_and_stencil(src_format)) {
1829055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                    if ((srcAspect != VK_IMAGE_ASPECT_DEPTH_BIT) && (srcAspect != VK_IMAGE_ASPECT_STENCIL_BIT)) {
1830055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                        std::stringstream ss;
1831055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                        ss << "vkCmdBlitImage: Combination depth/stencil image formats must have only one of "
1832055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                              "VK_IMAGE_ASPECT_DEPTH_BIT "
1833055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                           << "and VK_IMAGE_ASPECT_STENCIL_BIT set in srcImage and dstImage";
1834055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1835055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                                        reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__,
1836055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                                        DRAWSTATE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
1837055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                    }
1838055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                } else if (vk_format_is_stencil_only(src_format)) {
1839055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                    if (srcAspect != VK_IMAGE_ASPECT_STENCIL_BIT) {
1840055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                        std::stringstream ss;
1841055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                        ss << "vkCmdBlitImage: Stencil-only image formats must have only the VK_IMAGE_ASPECT_STENCIL_BIT "
1842055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                           << "set in both the srcImage and dstImage";
1843055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1844055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                                        reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__,
1845055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                                        DRAWSTATE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
1846055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                    }
1847055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                } else if (vk_format_is_depth_only(src_format)) {
1848055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                    if (srcAspect != VK_IMAGE_ASPECT_DEPTH_BIT) {
1849055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                        std::stringstream ss;
1850055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                        ss << "vkCmdBlitImage: Depth-only image formats must have only the VK_IMAGE_ASPECT_DEPTH "
1851055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                           << "set in both the srcImage and dstImage";
1852055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1853055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                                        reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__,
1854055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                                        DRAWSTATE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
1855055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                    }
1856055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                }
1857055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski            }
1858055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski        }
1859055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski
1860055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski        // Validate filter
1861055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski        if (vk_format_is_depth_or_stencil(src_format) && (filter != VK_FILTER_NEAREST)) {
1862055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski            std::stringstream ss;
1863055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski            ss << "vkCmdBlitImage: If the format of srcImage is a depth, stencil, or depth stencil "
1864055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski               << "then filter must be VK_FILTER_NEAREST.";
1865055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1866055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                            reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_02193, "IMAGE", "%s. %s",
1867055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski                            ss.str().c_str(), validation_error_map[VALIDATION_ERROR_02193]);
1868055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski        }
186960568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    } else {
187060568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        assert(0);
187160568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    }
187260568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    return skip;
187360568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski}
187460568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski
1875e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisvoid PreCallRecordCmdBlitImage(layer_data *device_data, GLOBAL_CB_NODE *cb_node, IMAGE_STATE *src_image_state,
1876e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlis                               IMAGE_STATE *dst_image_state) {
187760568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    // Update bindings between images and cmd buffer
187860568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    AddCommandBufferBindingImage(device_data, cb_node, src_image_state);
187960568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    AddCommandBufferBindingImage(device_data, cb_node, dst_image_state);
188060568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski
188160568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    std::function<bool()> function = [=]() { return ValidateImageMemoryIsValid(device_data, src_image_state, "vkCmdBlitImage()"); };
188260568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    cb_node->validate_functions.push_back(function);
188360568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    function = [=]() {
188460568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        SetImageMemoryValid(device_data, dst_image_state, true);
188560568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski        return false;
188660568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    };
188760568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski    cb_node->validate_functions.push_back(function);
18889a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    core_validation::UpdateCmdBufferLastCmd(cb_node, CMD_BLITIMAGE);
188960568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski}
189060568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski
189151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour// This validates that the initial layout specified in the command buffer for
189251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour// the IMAGE is the same
189351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour// as the global IMAGE layout
1894440bdd357701497c3442e3515f12ac1cfffc180aTony Barbourbool ValidateCmdBufImageLayouts(layer_data *device_data, GLOBAL_CB_NODE *pCB,
1895440bdd357701497c3442e3515f12ac1cfffc180aTony Barbour                                std::unordered_map<ImageSubresourcePair, IMAGE_LAYOUT_NODE> &imageLayoutMap) {
189690e629846621a0d870212dc0cebfbc83431cc5b8Mark Lobodzinski    bool skip = false;
189751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    const debug_report_data *report_data = core_validation::GetReportData(device_data);
1898788ff59d81fc816f451414dcf2a9d6c29456ff63Mark Lobodzinski    for (auto cb_image_data : pCB->imageLayoutMap) {
1899788ff59d81fc816f451414dcf2a9d6c29456ff63Mark Lobodzinski        VkImageLayout imageLayout;
190051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour
1901521b2f3957b3b31aeb2dbcc7529b54e06c9dc9ecJeremy Hayes        if (FindLayout(imageLayoutMap, cb_image_data.first, imageLayout)) {
1902788ff59d81fc816f451414dcf2a9d6c29456ff63Mark Lobodzinski            if (cb_image_data.second.initialLayout == VK_IMAGE_LAYOUT_UNDEFINED) {
1903788ff59d81fc816f451414dcf2a9d6c29456ff63Mark Lobodzinski                // TODO: Set memory invalid which is in mem_tracker currently
1904788ff59d81fc816f451414dcf2a9d6c29456ff63Mark Lobodzinski            } else if (imageLayout != cb_image_data.second.initialLayout) {
1905788ff59d81fc816f451414dcf2a9d6c29456ff63Mark Lobodzinski                if (cb_image_data.first.hasSubresource) {
19063f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                    skip |= log_msg(
19073f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                        report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
19083f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                        reinterpret_cast<uint64_t &>(pCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
19093f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                        "Cannot submit cmd buffer using image (0x%" PRIx64
19103f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                        ") [sub-resource: aspectMask 0x%X array layer %u, mip level %u], "
19113f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                        "with layout %s when first use is %s.",
19123f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                        reinterpret_cast<const uint64_t &>(cb_image_data.first.image), cb_image_data.first.subresource.aspectMask,
19133f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                        cb_image_data.first.subresource.arrayLayer, cb_image_data.first.subresource.mipLevel,
19143f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                        string_VkImageLayout(imageLayout), string_VkImageLayout(cb_image_data.second.initialLayout));
1915788ff59d81fc816f451414dcf2a9d6c29456ff63Mark Lobodzinski                } else {
19163f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                    skip |=
19173f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                        log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
19183f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                                reinterpret_cast<uint64_t &>(pCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
19193f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                                "Cannot submit cmd buffer using image (0x%" PRIx64
19203f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                                ") with layout %s when "
19213f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                                "first use is %s.",
19223f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                                reinterpret_cast<const uint64_t &>(cb_image_data.first.image), string_VkImageLayout(imageLayout),
19233f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                                string_VkImageLayout(cb_image_data.second.initialLayout));
1924788ff59d81fc816f451414dcf2a9d6c29456ff63Mark Lobodzinski                }
1925788ff59d81fc816f451414dcf2a9d6c29456ff63Mark Lobodzinski            }
192651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour            SetLayout(imageLayoutMap, cb_image_data.first, cb_image_data.second.layout);
1927788ff59d81fc816f451414dcf2a9d6c29456ff63Mark Lobodzinski        }
1928788ff59d81fc816f451414dcf2a9d6c29456ff63Mark Lobodzinski    }
192990e629846621a0d870212dc0cebfbc83431cc5b8Mark Lobodzinski    return skip;
1930788ff59d81fc816f451414dcf2a9d6c29456ff63Mark Lobodzinski}
1931940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski
193251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbourvoid UpdateCmdBufImageLayouts(layer_data *device_data, GLOBAL_CB_NODE *pCB) {
193351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    for (auto cb_image_data : pCB->imageLayoutMap) {
193451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour        VkImageLayout imageLayout;
193551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour        FindGlobalLayout(device_data, cb_image_data.first, imageLayout);
193651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour        SetGlobalLayout(device_data, cb_image_data.first, cb_image_data.second.layout);
193751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    }
193851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour}
193951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour
1940940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski// Print readable FlagBits in FlagMask
1941940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinskistatic std::string string_VkAccessFlags(VkAccessFlags accessMask) {
1942940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski    std::string result;
1943940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski    std::string separator;
1944940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski
1945940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski    if (accessMask == 0) {
1946940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski        result = "[None]";
1947940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski    } else {
1948940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski        result = "[";
1949940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski        for (auto i = 0; i < 32; i++) {
1950940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski            if (accessMask & (1 << i)) {
1951940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski                result = result + separator + string_VkAccessFlagBits((VkAccessFlagBits)(1 << i));
1952940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski                separator = " | ";
1953940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski            }
1954940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski        }
1955940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski        result = result + "]";
1956940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski    }
1957940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski    return result;
1958940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski}
1959940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski
19608fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski// AccessFlags MUST have 'required_bit' set, and may have one or more of 'optional_bits' set. If required_bit is zero, accessMask
19618fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski// must have at least one of 'optional_bits' set
1962940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski// TODO: Add tracking to ensure that at least one barrier has been set for these layout transitions
19638fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinskistatic bool ValidateMaskBits(core_validation::layer_data *device_data, VkCommandBuffer cmdBuffer, const VkAccessFlags &accessMask,
19648fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                             const VkImageLayout &layout, VkAccessFlags required_bit, VkAccessFlags optional_bits,
19658fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                             const char *type) {
19668fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
19678fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski    bool skip = false;
1968940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski
1969940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski    if ((accessMask & required_bit) || (!required_bit && (accessMask & optional_bits))) {
1970940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski        if (accessMask & ~(required_bit | optional_bits)) {
1971940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski            // TODO: Verify against Valid Use
19728fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
19738fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                            DRAWSTATE_INVALID_BARRIER, "DS",
19748fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                            "Additional bits in %s accessMask 0x%X %s are specified when layout is %s.", type, accessMask,
19758fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                            string_VkAccessFlags(accessMask).c_str(), string_VkImageLayout(layout));
1976940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski        }
1977940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski    } else {
1978940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski        if (!required_bit) {
19798fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
19808fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                            DRAWSTATE_INVALID_BARRIER, "DS",
19818fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                            "%s AccessMask %d %s must contain at least one of access bits %d "
19828fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                            "%s when layout is %s, unless the app has previously added a "
19838fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                            "barrier for this transition.",
19848fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                            type, accessMask, string_VkAccessFlags(accessMask).c_str(), optional_bits,
19858fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                            string_VkAccessFlags(optional_bits).c_str(), string_VkImageLayout(layout));
1986940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski        } else {
1987940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski            std::string opt_bits;
1988940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski            if (optional_bits != 0) {
1989940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski                std::stringstream ss;
1990940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski                ss << optional_bits;
1991940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski                opt_bits = "and may have optional bits " + ss.str() + ' ' + string_VkAccessFlags(optional_bits);
1992940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski            }
19938fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
19948fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                            DRAWSTATE_INVALID_BARRIER, "DS",
19958fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                            "%s AccessMask %d %s must have required access bit %d %s %s when "
19968fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                            "layout is %s, unless the app has previously added a barrier for "
19978fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                            "this transition.",
19988fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                            type, accessMask, string_VkAccessFlags(accessMask).c_str(), required_bit,
19998fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                            string_VkAccessFlags(required_bit).c_str(), opt_bits.c_str(), string_VkImageLayout(layout));
2000940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski        }
2001940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski    }
20028fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski    return skip;
2003940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski}
2004940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski
20058fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinskibool ValidateMaskBitsFromLayouts(core_validation::layer_data *device_data, VkCommandBuffer cmdBuffer,
20068fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                                 const VkAccessFlags &accessMask, const VkImageLayout &layout, const char *type) {
20078fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
2008940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski
20098fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski    bool skip = false;
2010940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski    switch (layout) {
20118fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski        case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: {
20128fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            skip |= ValidateMaskBits(device_data, cmdBuffer, accessMask, layout, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
20138fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                                     VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, type);
20148fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            break;
2015940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski        }
20168fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski        case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: {
20178fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            skip |= ValidateMaskBits(device_data, cmdBuffer, accessMask, layout, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
20188fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                                     VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, type);
20198fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            break;
20208fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski        }
20218fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski        case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: {
20228fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            skip |= ValidateMaskBits(device_data, cmdBuffer, accessMask, layout, VK_ACCESS_TRANSFER_WRITE_BIT, 0, type);
20238fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            break;
20248fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski        }
20258fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski        case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL: {
20268fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            skip |= ValidateMaskBits(
20278fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                device_data, cmdBuffer, accessMask, layout, 0,
20288fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
20298fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                type);
20308fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            break;
20318fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski        }
20328fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski        case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: {
20338fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            skip |= ValidateMaskBits(device_data, cmdBuffer, accessMask, layout, 0,
20348fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                                     VK_ACCESS_INPUT_ATTACHMENT_READ_BIT | VK_ACCESS_SHADER_READ_BIT, type);
20358fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            break;
20368fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski        }
20378fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski        case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: {
20388fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            skip |= ValidateMaskBits(device_data, cmdBuffer, accessMask, layout, VK_ACCESS_TRANSFER_READ_BIT, 0, type);
20398fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            break;
20408fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski        }
20418fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski        case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR: {
20428fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            skip |= ValidateMaskBits(device_data, cmdBuffer, accessMask, layout, VK_ACCESS_MEMORY_READ_BIT, 0, type);
20438fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            break;
20448fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski        }
20458fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski        case VK_IMAGE_LAYOUT_UNDEFINED: {
20468fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            if (accessMask != 0) {
20478fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                // TODO: Verify against Valid Use section spec
20488fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
20498fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                                DRAWSTATE_INVALID_BARRIER, "DS",
20508fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                                "Additional bits in %s accessMask 0x%X %s are specified when layout is %s.", type, accessMask,
20518fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski                                string_VkAccessFlags(accessMask).c_str(), string_VkImageLayout(layout));
20528fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            }
20538fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski            break;
20548fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski        }
20558fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski        case VK_IMAGE_LAYOUT_GENERAL:
20568fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski        default: { break; }
2057940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski    }
20588fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski    return skip;
2059940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski}
2060d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski
2061d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski// ValidateLayoutVsAttachmentDescription is a general function where we can validate various state associated with the
2062374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski// VkAttachmentDescription structs that are used by the sub-passes of a renderpass. Initial check is to make sure that READ_ONLY
2063374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski// layout attachments don't have CLEAR as their loadOp.
2064d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinskibool ValidateLayoutVsAttachmentDescription(const debug_report_data *report_data, const VkImageLayout first_layout,
2065374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                           const uint32_t attachment, const VkAttachmentDescription &attachment_description) {
2066374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski    bool skip = false;
2067d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski    // Verify that initial loadOp on READ_ONLY attachments is not CLEAR
2068d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski    if (attachment_description.loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR) {
2069d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski        if ((first_layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL) ||
2070d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            (first_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)) {
2071374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT,
2072374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                            VkDebugReportObjectTypeEXT(0), __LINE__, VALIDATION_ERROR_02351, "DS",
2073374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                            "Cannot clear attachment %d with invalid first layout %s. %s", attachment,
2074374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                            string_VkImageLayout(first_layout), validation_error_map[VALIDATION_ERROR_02351]);
2075d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski        }
2076d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski    }
2077374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski    return skip;
2078d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski}
2079d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski
2080374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinskibool ValidateLayouts(core_validation::layer_data *device_data, VkDevice device, const VkRenderPassCreateInfo *pCreateInfo) {
2081374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
2082d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski    bool skip = false;
2083d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski
2084d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski    // Track when we're observing the first use of an attachment
2085d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski    std::vector<bool> attach_first_use(pCreateInfo->attachmentCount, true);
2086d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski    for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) {
2087d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski        const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i];
2088d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski        for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) {
2089d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            auto attach_index = subpass.pColorAttachments[j].attachment;
2090d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            if (attach_index == VK_ATTACHMENT_UNUSED) continue;
2091d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski
2092d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            switch (subpass.pColorAttachments[j].layout) {
2093374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
2094374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    // This is ideal.
2095374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    break;
2096d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski
2097374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                case VK_IMAGE_LAYOUT_GENERAL:
2098374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    // May not be optimal; TODO: reconsider this warning based on other constraints?
2099374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    skip |= log_msg(report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT,
2100374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                    VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
2101374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                    "Layout for color attachment is GENERAL but should be COLOR_ATTACHMENT_OPTIMAL.");
2102374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    break;
2103374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski
2104374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                default:
2105374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
2106374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                    __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
2107374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                    "Layout for color attachment is %s but can only be COLOR_ATTACHMENT_OPTIMAL or GENERAL.",
2108374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                    string_VkImageLayout(subpass.pColorAttachments[j].layout));
2109d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            }
2110d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski
2111d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            if (attach_first_use[attach_index]) {
2112374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                skip |= ValidateLayoutVsAttachmentDescription(report_data, subpass.pColorAttachments[j].layout, attach_index,
2113374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                                              pCreateInfo->pAttachments[attach_index]);
2114d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            }
2115d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            attach_first_use[attach_index] = false;
2116d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski        }
2117d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski        if (subpass.pDepthStencilAttachment && subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) {
2118d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            switch (subpass.pDepthStencilAttachment->layout) {
2119374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
2120374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
2121374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    // These are ideal.
2122374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    break;
2123374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski
2124374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                case VK_IMAGE_LAYOUT_GENERAL:
2125374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    // May not be optimal; TODO: reconsider this warning based on other constraints? GENERAL can be better than
2126374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    // doing a bunch of transitions.
2127374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    skip |= log_msg(report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT,
2128374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                    VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
2129374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                    "GENERAL layout for depth attachment may not give optimal performance.");
2130374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    break;
2131374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski
2132374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                default:
2133374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    // No other layouts are acceptable
2134374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
2135374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                    __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
2136374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                    "Layout for depth attachment is %s but can only be DEPTH_STENCIL_ATTACHMENT_OPTIMAL, "
2137374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                    "DEPTH_STENCIL_READ_ONLY_OPTIMAL or GENERAL.",
2138374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                    string_VkImageLayout(subpass.pDepthStencilAttachment->layout));
2139d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            }
2140d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski
2141d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            auto attach_index = subpass.pDepthStencilAttachment->attachment;
2142d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            if (attach_first_use[attach_index]) {
2143374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                skip |= ValidateLayoutVsAttachmentDescription(report_data, subpass.pDepthStencilAttachment->layout, attach_index,
2144374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                                              pCreateInfo->pAttachments[attach_index]);
2145d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            }
2146d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            attach_first_use[attach_index] = false;
2147d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski        }
2148d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski        for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) {
2149d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            auto attach_index = subpass.pInputAttachments[j].attachment;
2150d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            if (attach_index == VK_ATTACHMENT_UNUSED) continue;
2151d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski
2152d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            switch (subpass.pInputAttachments[j].layout) {
2153374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
2154374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
2155374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    // These are ideal.
2156374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    break;
2157d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski
2158374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                case VK_IMAGE_LAYOUT_GENERAL:
2159374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    // May not be optimal. TODO: reconsider this warning based on other constraints.
2160374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    skip |= log_msg(report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT,
2161374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                    VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
2162374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                    "Layout for input attachment is GENERAL but should be READ_ONLY_OPTIMAL.");
2163374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    break;
2164374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski
2165374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                default:
2166374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    // No other layouts are acceptable
2167374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                    skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
2168374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                    DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
2169374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                    "Layout for input attachment is %s but can only be READ_ONLY_OPTIMAL or GENERAL.",
2170374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                    string_VkImageLayout(subpass.pInputAttachments[j].layout));
2171d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            }
2172d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski
2173d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            if (attach_first_use[attach_index]) {
2174374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                skip |= ValidateLayoutVsAttachmentDescription(report_data, subpass.pInputAttachments[j].layout, attach_index,
2175374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski                                                              pCreateInfo->pAttachments[attach_index]);
2176d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            }
2177d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski            attach_first_use[attach_index] = false;
2178d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski        }
2179d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski    }
2180d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski    return skip;
2181d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski}
2182c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski
2183c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski// For any image objects that overlap mapped memory, verify that their layouts are PREINIT or GENERAL
218409cd2c76808f1485206baeda9864f7ed907d7e05Mark Lobodzinskibool ValidateMapImageLayouts(core_validation::layer_data *device_data, VkDevice device, DEVICE_MEM_INFO const *mem_info,
218509cd2c76808f1485206baeda9864f7ed907d7e05Mark Lobodzinski                             VkDeviceSize offset, VkDeviceSize end_offset) {
218609cd2c76808f1485206baeda9864f7ed907d7e05Mark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
218709cd2c76808f1485206baeda9864f7ed907d7e05Mark Lobodzinski    bool skip = false;
218809cd2c76808f1485206baeda9864f7ed907d7e05Mark Lobodzinski    // Iterate over all bound image ranges and verify that for any that overlap the map ranges, the layouts are
218909cd2c76808f1485206baeda9864f7ed907d7e05Mark Lobodzinski    // VK_IMAGE_LAYOUT_PREINITIALIZED or VK_IMAGE_LAYOUT_GENERAL
2190c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski    // TODO : This can be optimized if we store ranges based on starting address and early exit when we pass our range
2191c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski    for (auto image_handle : mem_info->bound_images) {
2192c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski        auto img_it = mem_info->bound_ranges.find(image_handle);
2193c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski        if (img_it != mem_info->bound_ranges.end()) {
219409cd2c76808f1485206baeda9864f7ed907d7e05Mark Lobodzinski            if (rangesIntersect(device_data, &img_it->second, offset, end_offset)) {
2195c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski                std::vector<VkImageLayout> layouts;
219609cd2c76808f1485206baeda9864f7ed907d7e05Mark Lobodzinski                if (FindLayouts(device_data, VkImage(image_handle), layouts)) {
2197c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski                    for (auto layout : layouts) {
2198c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski                        if (layout != VK_IMAGE_LAYOUT_PREINITIALIZED && layout != VK_IMAGE_LAYOUT_GENERAL) {
21993f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                            skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0,
22003f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                                            __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
2201b4a793e458e946f1218544264f2bf73be5444df5Michael Lentine                                            "Mapping an image with layout %s can result in undefined behavior if this memory is "
2202b4a793e458e946f1218544264f2bf73be5444df5Michael Lentine                                            "used by the device. Only GENERAL or PREINITIALIZED should be used.",
220309cd2c76808f1485206baeda9864f7ed907d7e05Mark Lobodzinski                                            string_VkImageLayout(layout));
2204c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski                        }
2205c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski                    }
2206c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski                }
2207c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski            }
2208c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski        }
2209c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski    }
221009cd2c76808f1485206baeda9864f7ed907d7e05Mark Lobodzinski    return skip;
2211c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski}
22123683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski
22133683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski// Helper function to validate correct usage bits set for buffers or images. Verify that (actual & desired) flags != 0 or, if strict
22143683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski// is true, verify that (actual & desired) flags == desired
2215abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinskistatic bool validate_usage_flags(layer_data *device_data, VkFlags actual, VkFlags desired, VkBool32 strict, uint64_t obj_handle,
22163683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski                                 VkDebugReportObjectTypeEXT obj_type, int32_t const msgCode, char const *ty_str,
22173683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski                                 char const *func_name, char const *usage_str) {
2218abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
22193683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski
22203683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    bool correct_usage = false;
2221abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinski    bool skip = false;
22223683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    if (strict) {
22233683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski        correct_usage = ((actual & desired) == desired);
22243683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    } else {
22253683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski        correct_usage = ((actual & desired) != 0);
22263683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    }
22273683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    if (!correct_usage) {
22283683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski        if (msgCode == -1) {
22293683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski            // TODO: Fix callers with msgCode == -1 to use correct validation checks.
22303f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton            skip = log_msg(
22313f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, obj_type, obj_handle, __LINE__, MEMTRACK_INVALID_USAGE_FLAG, "MEM",
22323f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                "Invalid usage flag for %s 0x%" PRIxLEAST64 " used by %s. In this case, %s should have %s set during creation.",
22333f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton                ty_str, obj_handle, func_name, ty_str, usage_str);
22343683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski        } else {
22353683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski            const char *valid_usage = (msgCode == -1) ? "" : validation_error_map[msgCode];
2236abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinski            skip = log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, obj_type, obj_handle, __LINE__, msgCode, "MEM",
2237abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinski                           "Invalid usage flag for %s 0x%" PRIxLEAST64
2238abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinski                           " used by %s. In this case, %s should have %s set during creation. %s",
2239abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinski                           ty_str, obj_handle, func_name, ty_str, usage_str, valid_usage);
22403683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski        }
22413683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    }
2242abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinski    return skip;
22433683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski}
22443683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski
22453683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski// Helper function to validate usage flags for buffers. For given buffer_state send actual vs. desired usage off to helper above
22463683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski// where an error will be flagged if usage is not correct
2247abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinskibool ValidateImageUsageFlags(layer_data *device_data, IMAGE_STATE const *image_state, VkFlags desired, VkBool32 strict,
22483683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski                             int32_t const msgCode, char const *func_name, char const *usage_string) {
2249abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinski    return validate_usage_flags(device_data, image_state->createInfo.usage, desired, strict,
22503683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski                                reinterpret_cast<const uint64_t &>(image_state->image), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
22513683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski                                msgCode, "image", func_name, usage_string);
22523683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski}
22533683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski
22543683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski// Helper function to validate usage flags for buffers. For given buffer_state send actual vs. desired usage off to helper above
22553683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski// where an error will be flagged if usage is not correct
2256abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinskibool ValidateBufferUsageFlags(layer_data *device_data, BUFFER_STATE const *buffer_state, VkFlags desired, VkBool32 strict,
22573683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski                              int32_t const msgCode, char const *func_name, char const *usage_string) {
2258abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinski    return validate_usage_flags(device_data, buffer_state->createInfo.usage, desired, strict,
22593683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski                                reinterpret_cast<const uint64_t &>(buffer_state->buffer), VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT,
22603683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski                                msgCode, "buffer", func_name, usage_string);
22613683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski}
22623683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski
2263abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinskibool PreCallValidateCreateBuffer(layer_data *device_data, const VkBufferCreateInfo *pCreateInfo) {
22643683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    bool skip = false;
226501363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
226601363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski
22673683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    // TODO: Add check for VALIDATION_ERROR_00658
22683683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    // TODO: Add check for VALIDATION_ERROR_00667
22693683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    // TODO: Add check for VALIDATION_ERROR_00668
22703683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    // TODO: Add check for VALIDATION_ERROR_00669
227101363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski
227201363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski    if ((pCreateInfo->flags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT) && (!GetEnabledFeatures(device_data)->sparseBinding)) {
227301363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
227401363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski                        VALIDATION_ERROR_00666, "DS",
227501363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski                        "vkCreateBuffer(): the sparseBinding device feature is disabled: Buffers cannot be created with the "
227601363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski                        "VK_BUFFER_CREATE_SPARSE_BINDING_BIT set. %s",
227701363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski                        validation_error_map[VALIDATION_ERROR_00666]);
227801363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski    }
2279f575247dabffb70e4de1a6f9522db3f09a55492eMark Lobodzinski
2280f575247dabffb70e4de1a6f9522db3f09a55492eMark Lobodzinski    if ((pCreateInfo->flags & VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT) && (!GetEnabledFeatures(device_data)->sparseResidencyBuffer)) {
2281f575247dabffb70e4de1a6f9522db3f09a55492eMark Lobodzinski        skip |=
2282f575247dabffb70e4de1a6f9522db3f09a55492eMark Lobodzinski            log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
2283f575247dabffb70e4de1a6f9522db3f09a55492eMark Lobodzinski                    DRAWSTATE_INVALID_FEATURE, "DS",
2284f575247dabffb70e4de1a6f9522db3f09a55492eMark Lobodzinski                    "vkCreateBuffer(): the sparseResidencyBuffer device feature is disabled: Buffers cannot be created with the "
2285f575247dabffb70e4de1a6f9522db3f09a55492eMark Lobodzinski                    "VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT set.");
2286f575247dabffb70e4de1a6f9522db3f09a55492eMark Lobodzinski    }
22877e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski
22887e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski    if ((pCreateInfo->flags & VK_BUFFER_CREATE_SPARSE_ALIASED_BIT) && (!GetEnabledFeatures(device_data)->sparseResidencyAliased)) {
22897e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski        skip |=
22907e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski            log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
22917e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski                    DRAWSTATE_INVALID_FEATURE, "DS",
22927e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski                    "vkCreateBuffer(): the sparseResidencyAliased device feature is disabled: Buffers cannot be created with the "
22937e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski                    "VK_BUFFER_CREATE_SPARSE_ALIASED_BIT set.");
22947e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski    }
22953683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    return skip;
22963683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski}
22973683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski
22983683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinskivoid PostCallRecordCreateBuffer(layer_data *device_data, const VkBufferCreateInfo *pCreateInfo, VkBuffer *pBuffer) {
22993683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    // TODO : This doesn't create deep copy of pQueueFamilyIndices so need to fix that if/when we want that data to be valid
23003683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    GetBufferMap(device_data)
23013683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski        ->insert(std::make_pair(*pBuffer, std::unique_ptr<BUFFER_STATE>(new BUFFER_STATE(*pBuffer, pCreateInfo))));
23023683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski}
23033683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski
2304abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinskibool PreCallValidateCreateBufferView(layer_data *device_data, const VkBufferViewCreateInfo *pCreateInfo) {
2305abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinski    bool skip = false;
2306abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinski    BUFFER_STATE *buffer_state = GetBufferState(device_data, pCreateInfo->buffer);
23073683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    // If this isn't a sparse buffer, it needs to have memory backing it at CreateBufferView time
23083683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    if (buffer_state) {
2309abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinski        skip |= ValidateMemoryIsBoundToBuffer(device_data, buffer_state, "vkCreateBufferView()", VALIDATION_ERROR_02522);
23103683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski        // In order to create a valid buffer view, the buffer must have been created with at least one of the following flags:
23113683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski        // UNIFORM_TEXEL_BUFFER_BIT or STORAGE_TEXEL_BUFFER_BIT
2312abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinski        skip |= ValidateBufferUsageFlags(
2313abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinski            device_data, buffer_state, VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT, false,
23143683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski            VALIDATION_ERROR_00694, "vkCreateBufferView()", "VK_BUFFER_USAGE_[STORAGE|UNIFORM]_TEXEL_BUFFER_BIT");
23153683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    }
2316abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinski    return skip;
23173683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski}
23183683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski
23193683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinskivoid PostCallRecordCreateBufferView(layer_data *device_data, const VkBufferViewCreateInfo *pCreateInfo, VkBufferView *pView) {
23203683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    (*GetBufferViewMap(device_data))[*pView] = std::unique_ptr<BUFFER_VIEW_STATE>(new BUFFER_VIEW_STATE(*pView, pCreateInfo));
23213683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski}
23221c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski
23231c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski// For the given format verify that the aspect masks make sense
23241c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinskibool ValidateImageAspectMask(layer_data *device_data, VkImage image, VkFormat format, VkImageAspectFlags aspect_mask,
23251c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                             const char *func_name) {
23261c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
23271c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    bool skip = false;
23281c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    if (vk_format_is_color(format)) {
23291c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        if ((aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT) != VK_IMAGE_ASPECT_COLOR_BIT) {
23301c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, (uint64_t)image,
23311c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            __LINE__, VALIDATION_ERROR_00741, "IMAGE",
23321c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            "%s: Color image formats must have the VK_IMAGE_ASPECT_COLOR_BIT set. %s", func_name,
23331c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            validation_error_map[VALIDATION_ERROR_00741]);
23341c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        } else if ((aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT) != aspect_mask) {
23351c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, (uint64_t)image,
23361c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            __LINE__, VALIDATION_ERROR_00741, "IMAGE",
23371c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            "%s: Color image formats must have ONLY the VK_IMAGE_ASPECT_COLOR_BIT set. %s", func_name,
23381c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            validation_error_map[VALIDATION_ERROR_00741]);
23391c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        }
23401c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    } else if (vk_format_is_depth_and_stencil(format)) {
23411c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        if ((aspect_mask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) == 0) {
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/stencil image formats must have "
23451c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            "at least one of VK_IMAGE_ASPECT_DEPTH_BIT "
23461c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            "and VK_IMAGE_ASPECT_STENCIL_BIT set. %s",
23471c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            func_name, validation_error_map[VALIDATION_ERROR_00741]);
23481c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        } else if ((aspect_mask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) != aspect_mask) {
23491c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, (uint64_t)image,
23501c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            __LINE__, VALIDATION_ERROR_00741, "IMAGE",
23511c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            "%s: Combination depth/stencil image formats can have only the VK_IMAGE_ASPECT_DEPTH_BIT and "
23521c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            "VK_IMAGE_ASPECT_STENCIL_BIT set. %s",
23531c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            func_name, validation_error_map[VALIDATION_ERROR_00741]);
23541c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        }
23551c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    } else if (vk_format_is_depth_only(format)) {
23561c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        if ((aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) != VK_IMAGE_ASPECT_DEPTH_BIT) {
23571c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, (uint64_t)image,
23581c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            __LINE__, VALIDATION_ERROR_00741, "IMAGE",
23591c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            "%s: Depth-only image formats must have the VK_IMAGE_ASPECT_DEPTH_BIT set. %s", func_name,
23601c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            validation_error_map[VALIDATION_ERROR_00741]);
23611c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        } else if ((aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) != aspect_mask) {
23621c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, (uint64_t)image,
23631c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            __LINE__, VALIDATION_ERROR_00741, "IMAGE",
23641c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            "%s: Depth-only image formats can have only the VK_IMAGE_ASPECT_DEPTH_BIT set. %s", func_name,
23651c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            validation_error_map[VALIDATION_ERROR_00741]);
23661c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        }
23671c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    } else if (vk_format_is_stencil_only(format)) {
23681c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        if ((aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT) != VK_IMAGE_ASPECT_STENCIL_BIT) {
23691c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, (uint64_t)image,
23701c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            __LINE__, VALIDATION_ERROR_00741, "IMAGE",
23711c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            "%s: Stencil-only image formats must have the VK_IMAGE_ASPECT_STENCIL_BIT set. %s", func_name,
23721c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            validation_error_map[VALIDATION_ERROR_00741]);
23731c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        } else if ((aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT) != aspect_mask) {
23741c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, (uint64_t)image,
23751c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            __LINE__, VALIDATION_ERROR_00741, "IMAGE",
23761c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            "%s: Stencil-only image formats can have only the VK_IMAGE_ASPECT_STENCIL_BIT set. %s", func_name,
23771c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                            validation_error_map[VALIDATION_ERROR_00741]);
23781c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        }
23791c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    }
23801c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    return skip;
23811c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski}
23821c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski
23831c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinskibool ValidateImageSubrangeLevelLayerCounts(layer_data *device_data, const VkImageSubresourceRange &subresourceRange,
23841c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                                           const char *func_name) {
23851c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
23861c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    bool skip = false;
23871c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    if (subresourceRange.levelCount == 0) {
23881c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
23891c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                        VALIDATION_ERROR_00768, "IMAGE", "%s called with 0 in subresourceRange.levelCount. %s", func_name,
23901c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                        validation_error_map[VALIDATION_ERROR_00768]);
23911c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    }
23921c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    if (subresourceRange.layerCount == 0) {
23931c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
23941c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                        VALIDATION_ERROR_00769, "IMAGE", "%s called with 0 in subresourceRange.layerCount. %s", func_name,
23951c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                        validation_error_map[VALIDATION_ERROR_00769]);
23961c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    }
23971c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    return skip;
23981c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski}
23991c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski
24001c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinskibool PreCallValidateCreateImageView(layer_data *device_data, const VkImageViewCreateInfo *create_info) {
24011c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
24021c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    bool skip = false;
24031c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    IMAGE_STATE *image_state = GetImageState(device_data, create_info->image);
24041c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    if (image_state) {
24051c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        skip |= ValidateImageUsageFlags(
24061c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            device_data, image_state,
24071c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT |
24081c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
24091c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            false, -1, "vkCreateImageView()",
24101c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            "VK_IMAGE_USAGE_[SAMPLED|STORAGE|COLOR_ATTACHMENT|DEPTH_STENCIL_ATTACHMENT|INPUT_ATTACHMENT]_BIT");
24111c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        // If this isn't a sparse image, it needs to have memory backing it at CreateImageView time
24121c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        skip |= ValidateMemoryIsBoundToImage(device_data, image_state, "vkCreateImageView()", VALIDATION_ERROR_02524);
24131c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        // Checks imported from image layer
24141c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        if (create_info->subresourceRange.baseMipLevel >= image_state->createInfo.mipLevels) {
24151c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            std::stringstream ss;
24161c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            ss << "vkCreateImageView called with baseMipLevel " << create_info->subresourceRange.baseMipLevel << " for image "
24171c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski               << create_info->image << " that only has " << image_state->createInfo.mipLevels << " mip levels.";
24181c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            skip |=
24191c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
24201c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                        VALIDATION_ERROR_00768, "IMAGE", "%s %s", ss.str().c_str(), validation_error_map[VALIDATION_ERROR_00768]);
24211c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        }
24221c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        if (create_info->subresourceRange.baseArrayLayer >= image_state->createInfo.arrayLayers) {
24231c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            std::stringstream ss;
24241c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            ss << "vkCreateImageView called with baseArrayLayer " << create_info->subresourceRange.baseArrayLayer << " for image "
24251c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski               << create_info->image << " that only has " << image_state->createInfo.arrayLayers << " array layers.";
24261c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            skip |=
24271c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
24281c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                        VALIDATION_ERROR_00769, "IMAGE", "%s %s", ss.str().c_str(), validation_error_map[VALIDATION_ERROR_00769]);
24291c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        }
24301c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        // TODO: Need new valid usage language for levelCount == 0 & layerCount == 0
24311c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        skip |= ValidateImageSubrangeLevelLayerCounts(device_data, create_info->subresourceRange, "vkCreateImageView()");
24321c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski
24331c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        VkImageCreateFlags image_flags = image_state->createInfo.flags;
24341c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        VkFormat image_format = image_state->createInfo.format;
24351c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        VkFormat view_format = create_info->format;
24361c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        VkImageAspectFlags aspect_mask = create_info->subresourceRange.aspectMask;
24371c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski
24381c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        // Validate VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT state
24391c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        if (image_flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) {
24401c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            // Format MUST be compatible (in the same format compatibility class) as the format the image was created with
24411c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            if (vk_format_get_compatibility_class(image_format) != vk_format_get_compatibility_class(view_format)) {
24421c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                std::stringstream ss;
24431c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                ss << "vkCreateImageView(): ImageView format " << string_VkFormat(view_format)
24441c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                   << " is not in the same format compatibility class as image (" << (uint64_t)create_info->image << ")  format "
24451c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                   << string_VkFormat(image_format) << ".  Images created with the VK_IMAGE_CREATE_MUTABLE_FORMAT BIT "
24461c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                   << "can support ImageViews with differing formats but they must be in the same compatibility class.";
24471c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
24481c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                                VALIDATION_ERROR_02171, "IMAGE", "%s %s", ss.str().c_str(),
24491c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                                validation_error_map[VALIDATION_ERROR_02171]);
24501c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            }
24511c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        } else {
24521c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            // Format MUST be IDENTICAL to the format the image was created with
24531c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            if (image_format != view_format) {
24541c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                std::stringstream ss;
24551c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                ss << "vkCreateImageView() format " << string_VkFormat(view_format) << " differs from image "
24561c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                   << (uint64_t)create_info->image << " format " << string_VkFormat(image_format)
24571c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                   << ".  Formats MUST be IDENTICAL unless VK_IMAGE_CREATE_MUTABLE_FORMAT BIT was set on image creation.";
24581c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
24591c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                                VALIDATION_ERROR_02172, "IMAGE", "%s %s", ss.str().c_str(),
24601c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski                                validation_error_map[VALIDATION_ERROR_02172]);
24611c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski            }
24621c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        }
24631c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski
24641c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        // Validate correct image aspect bits for desired formats and format consistency
24651c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski        skip |= ValidateImageAspectMask(device_data, image_state->image, image_format, aspect_mask, "vkCreateImageView()");
24661c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    }
24671c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    return skip;
24681c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski}
24691c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski
2470d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinskivoid PostCallRecordCreateImageView(layer_data *device_data, const VkImageViewCreateInfo *create_info, VkImageView view) {
2471d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski    auto image_view_map = GetImageViewMap(device_data);
2472d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski    (*image_view_map)[view] = std::unique_ptr<IMAGE_VIEW_STATE>(new IMAGE_VIEW_STATE(view, create_info));
2473d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski
2474d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski    auto image_state = GetImageState(device_data, create_info->image);
24756677fd2fa2aca17ab772da98cfe69852fb47bdbcPetr Kraus    auto& sub_res_range = (*image_view_map)[view].get()->create_info.subresourceRange;
2476d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski    ResolveRemainingLevelsLayers(device_data, &sub_res_range, image_state);
24771c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski}
24786a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
2479c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinskibool PreCallValidateCmdCopyBuffer(layer_data *device_data, GLOBAL_CB_NODE *cb_node, BUFFER_STATE *src_buffer_state,
2480c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski                                  BUFFER_STATE *dst_buffer_state) {
2481c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    bool skip = false;
2482c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    skip |= ValidateMemoryIsBoundToBuffer(device_data, src_buffer_state, "vkCmdCopyBuffer()", VALIDATION_ERROR_02531);
2483c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    skip |= ValidateMemoryIsBoundToBuffer(device_data, dst_buffer_state, "vkCmdCopyBuffer()", VALIDATION_ERROR_02532);
2484c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    // Validate that SRC & DST buffers have correct usage flags set
2485c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    skip |= ValidateBufferUsageFlags(device_data, src_buffer_state, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, true, VALIDATION_ERROR_01164,
2486c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski                                     "vkCmdCopyBuffer()", "VK_BUFFER_USAGE_TRANSFER_SRC_BIT");
2487c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    skip |= ValidateBufferUsageFlags(device_data, dst_buffer_state, VK_BUFFER_USAGE_TRANSFER_DST_BIT, true, VALIDATION_ERROR_01165,
2488c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski                                     "vkCmdCopyBuffer()", "VK_BUFFER_USAGE_TRANSFER_DST_BIT");
2489c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    skip |= ValidateCmd(device_data, cb_node, CMD_COPYBUFFER, "vkCmdCopyBuffer()");
2490c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    skip |= insideRenderPass(device_data, cb_node, "vkCmdCopyBuffer()", VALIDATION_ERROR_01172);
2491c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    return skip;
2492c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski}
24936a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
2494c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinskivoid PreCallRecordCmdCopyBuffer(layer_data *device_data, GLOBAL_CB_NODE *cb_node, BUFFER_STATE *src_buffer_state,
2495c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski                                BUFFER_STATE *dst_buffer_state) {
2496c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    // Update bindings between buffers and cmd buffer
2497c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    AddCommandBufferBindingBuffer(device_data, cb_node, src_buffer_state);
2498c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    AddCommandBufferBindingBuffer(device_data, cb_node, dst_buffer_state);
2499c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski
2500c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    std::function<bool()> function = [=]() {
2501c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski        return ValidateBufferMemoryIsValid(device_data, src_buffer_state, "vkCmdCopyBuffer()");
2502c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    };
2503c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    cb_node->validate_functions.push_back(function);
2504c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    function = [=]() {
2505c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski        SetBufferMemoryValid(device_data, dst_buffer_state, true);
2506c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski        return false;
2507c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    };
2508c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    cb_node->validate_functions.push_back(function);
2509c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    core_validation::UpdateCmdBufferLastCmd(cb_node, CMD_COPYBUFFER);
2510c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski}
2511842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski
2512842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinskistatic bool validateIdleBuffer(layer_data *device_data, VkBuffer buffer) {
2513842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
2514842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    bool skip = false;
2515842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    auto buffer_state = GetBufferState(device_data, buffer);
2516842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    if (!buffer_state) {
2517842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, (uint64_t)(buffer),
2518842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski                        __LINE__, DRAWSTATE_DOUBLE_DESTROY, "DS",
2519842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski                        "Cannot free buffer 0x%" PRIxLEAST64 " that has not been allocated.", (uint64_t)(buffer));
2520842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    } else {
2521842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski        if (buffer_state->in_use.load()) {
2522842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, (uint64_t)(buffer),
2523842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski                            __LINE__, VALIDATION_ERROR_00676, "DS",
2524842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski                            "Cannot free buffer 0x%" PRIxLEAST64 " that is in use by a command buffer. %s", (uint64_t)(buffer),
2525842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski                            validation_error_map[VALIDATION_ERROR_00676]);
2526842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski        }
2527842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    }
2528842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    return skip;
2529842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski}
2530842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski
2531842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinskibool PreCallValidateDestroyImageView(layer_data *device_data, VkImageView image_view, IMAGE_VIEW_STATE **image_view_state,
2532842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski                                     VK_OBJECT *obj_struct) {
2533842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    *image_view_state = GetImageViewState(device_data, image_view);
2534842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    *obj_struct = {reinterpret_cast<uint64_t &>(image_view), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT};
2535842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    if (GetDisables(device_data)->destroy_image_view) return false;
2536842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    bool skip = false;
2537842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    if (*image_view_state) {
2538842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski        skip |= ValidateObjectNotInUse(device_data, *image_view_state, *obj_struct, VALIDATION_ERROR_00776);
2539842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    }
2540842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    return skip;
2541842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski}
2542842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski
2543842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinskivoid PostCallRecordDestroyImageView(layer_data *device_data, VkImageView image_view, IMAGE_VIEW_STATE *image_view_state,
2544842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski                                    VK_OBJECT obj_struct) {
2545842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    // Any bound cmd buffers are now invalid
2546842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    invalidateCommandBuffers(device_data, image_view_state->cb_bindings, obj_struct);
2547842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    (*GetImageViewMap(device_data)).erase(image_view);
2548842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski}
2549842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski
2550842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinskibool PreCallValidateDestroyBuffer(layer_data *device_data, VkBuffer buffer, BUFFER_STATE **buffer_state, VK_OBJECT *obj_struct) {
2551842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    *buffer_state = GetBufferState(device_data, buffer);
2552842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    *obj_struct = {reinterpret_cast<uint64_t &>(buffer), VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT};
2553842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    if (GetDisables(device_data)->destroy_buffer) return false;
2554842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    bool skip = false;
2555842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    if (*buffer_state) {
2556842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski        skip |= validateIdleBuffer(device_data, buffer);
2557842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    }
2558842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    return skip;
2559842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski}
2560842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski
2561842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinskivoid PostCallRecordDestroyBuffer(layer_data *device_data, VkBuffer buffer, BUFFER_STATE *buffer_state, VK_OBJECT obj_struct) {
2562842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    invalidateCommandBuffers(device_data, buffer_state->cb_bindings, obj_struct);
2563842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    for (auto mem_binding : buffer_state->GetBoundMemory()) {
2564842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski        auto mem_info = GetMemObjInfo(device_data, mem_binding);
2565842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski        if (mem_info) {
2566842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski            core_validation::RemoveBufferMemoryRange(reinterpret_cast<uint64_t &>(buffer), mem_info);
2567842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski        }
2568842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    }
2569842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    ClearMemoryObjectBindings(device_data, reinterpret_cast<uint64_t &>(buffer), VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT);
2570842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    GetBufferMap(device_data)->erase(buffer_state->buffer);
2571842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski}
2572842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski
2573842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinskibool PreCallValidateDestroyBufferView(layer_data *device_data, VkBufferView buffer_view, BUFFER_VIEW_STATE **buffer_view_state,
2574842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski                                      VK_OBJECT *obj_struct) {
2575842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    *buffer_view_state = GetBufferViewState(device_data, buffer_view);
2576842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    *obj_struct = {reinterpret_cast<uint64_t &>(buffer_view), VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT};
2577842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    if (GetDisables(device_data)->destroy_buffer_view) return false;
2578842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    bool skip = false;
2579842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    if (*buffer_view_state) {
2580842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski        skip |= ValidateObjectNotInUse(device_data, *buffer_view_state, *obj_struct, VALIDATION_ERROR_00701);
2581842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    }
2582842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    return skip;
2583842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski}
2584842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski
2585842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinskivoid PostCallRecordDestroyBufferView(layer_data *device_data, VkBufferView buffer_view, BUFFER_VIEW_STATE *buffer_view_state,
2586842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski                                     VK_OBJECT obj_struct) {
2587842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    // Any bound cmd buffers are now invalid
2588842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    invalidateCommandBuffers(device_data, buffer_view_state->cb_bindings, obj_struct);
2589842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski    GetBufferViewMap(device_data)->erase(buffer_view);
2590842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski}
259123bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski
259223bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinskibool PreCallValidateCmdFillBuffer(layer_data *device_data, GLOBAL_CB_NODE *cb_node, BUFFER_STATE *buffer_state) {
259323bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski    bool skip = false;
259423bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski    skip |= ValidateMemoryIsBoundToBuffer(device_data, buffer_state, "vkCmdFillBuffer()", VALIDATION_ERROR_02529);
259523bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski    skip |= ValidateCmd(device_data, cb_node, CMD_FILLBUFFER, "vkCmdFillBuffer()");
259623bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski    // Validate that DST buffer has correct usage flags set
259723bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski    skip |= ValidateBufferUsageFlags(device_data, buffer_state, VK_BUFFER_USAGE_TRANSFER_DST_BIT, true, VALIDATION_ERROR_01137,
259823bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski                                     "vkCmdFillBuffer()", "VK_BUFFER_USAGE_TRANSFER_DST_BIT");
259923bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski    skip |= insideRenderPass(device_data, cb_node, "vkCmdFillBuffer()", VALIDATION_ERROR_01142);
260023bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski    return skip;
260123bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski}
260223bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski
260323bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinskivoid PreCallRecordCmdFillBuffer(layer_data *device_data, GLOBAL_CB_NODE *cb_node, BUFFER_STATE *buffer_state) {
260423bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski    std::function<bool()> function = [=]() {
260523bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski        SetBufferMemoryValid(device_data, buffer_state, true);
260623bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski        return false;
260723bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski    };
260823bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski    cb_node->validate_functions.push_back(function);
260923bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski    // Update bindings between buffer and cmd buffer
261023bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski    AddCommandBufferBindingBuffer(device_data, cb_node, buffer_state);
261123bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski    core_validation::UpdateCmdBufferLastCmd(cb_node, CMD_FILLBUFFER);
261223bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski}
2613877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski
261471c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinskibool ValidateBufferImageCopyData(const debug_report_data *report_data, uint32_t regionCount, const VkBufferImageCopy *pRegions,
261571c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                                 IMAGE_STATE *image_state, const char *function) {
2616877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski    bool skip = false;
2617877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski
2618877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski    for (uint32_t i = 0; i < regionCount; i++) {
26195971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        if (image_state->createInfo.imageType == VK_IMAGE_TYPE_1D) {
26205971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            if ((pRegions[i].imageOffset.y != 0) || (pRegions[i].imageExtent.height != 1)) {
26215971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
26225971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01746, "IMAGE",
26235971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                "%s(): pRegion[%d] imageOffset.y is %d and imageExtent.height is %d. For 1D images these "
26245971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                "must be 0 and 1, respectively. %s",
26255971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                function, i, pRegions[i].imageOffset.y, pRegions[i].imageExtent.height,
26265971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                validation_error_map[VALIDATION_ERROR_01746]);
2627877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski            }
26285971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        }
2629877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski
26305971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        if ((image_state->createInfo.imageType == VK_IMAGE_TYPE_1D) || (image_state->createInfo.imageType == VK_IMAGE_TYPE_2D)) {
26315971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            if ((pRegions[i].imageOffset.z != 0) || (pRegions[i].imageExtent.depth != 1)) {
2632877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
26335971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01747, "IMAGE",
26345971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                "%s(): pRegion[%d] imageOffset.z is %d and imageExtent.depth is %d. For 1D and 2D images these "
26355971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                "must be 0 and 1, respectively. %s",
26365971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                function, i, pRegions[i].imageOffset.z, pRegions[i].imageExtent.depth,
26375971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                validation_error_map[VALIDATION_ERROR_01747]);
2638877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski            }
26395971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        }
2640877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski
26415971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        if (image_state->createInfo.imageType == VK_IMAGE_TYPE_3D) {
26425971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            if ((0 != pRegions[i].imageSubresource.baseArrayLayer) || (1 != pRegions[i].imageSubresource.layerCount)) {
2643877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
26445971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01281, "IMAGE",
26455971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                "%s(): pRegion[%d] imageSubresource.baseArrayLayer is %d and imageSubresource.layerCount is "
26465971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                "%d. For 3D images these must be 0 and 1, respectively. %s",
26475971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                function, i, pRegions[i].imageSubresource.baseArrayLayer, pRegions[i].imageSubresource.layerCount,
26485971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                validation_error_map[VALIDATION_ERROR_01281]);
2649877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski            }
26505971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        }
2651877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski
26525971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        // If the the calling command's VkImage parameter's format is not a depth/stencil format,
26535971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        // then bufferOffset must be a multiple of the calling command's VkImage parameter's texel size
26545971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        auto texel_size = vk_format_get_size(image_state->createInfo.format);
26555971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        if (!vk_format_is_depth_and_stencil(image_state->createInfo.format) &&
26565971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            vk_safe_modulo(pRegions[i].bufferOffset, texel_size) != 0) {
26575971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
26585971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                            reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01263, "IMAGE",
26595971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                            "%s(): pRegion[%d] bufferOffset 0x%" PRIxLEAST64
26605971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                            " must be a multiple of this format's texel size (" PRINTF_SIZE_T_SPECIFIER "). %s",
26615971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                            function, i, pRegions[i].bufferOffset, texel_size, validation_error_map[VALIDATION_ERROR_01263]);
26625971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        }
26635971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton
26645971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        //  BufferOffset must be a multiple of 4
26655971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        if (vk_safe_modulo(pRegions[i].bufferOffset, 4) != 0) {
26665971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
26675971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                            reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01264, "IMAGE",
26685971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                            "%s(): pRegion[%d] bufferOffset 0x%" PRIxLEAST64 " must be a multiple of 4. %s", function, i,
26695971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                            pRegions[i].bufferOffset, validation_error_map[VALIDATION_ERROR_01264]);
26705971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        }
26715971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton
26725971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        //  BufferRowLength must be 0, or greater than or equal to the width member of imageExtent
26735971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        if ((pRegions[i].bufferRowLength != 0) && (pRegions[i].bufferRowLength < pRegions[i].imageExtent.width)) {
26745971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            skip |= log_msg(
26755971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
26765971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01265, "IMAGE",
26775971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                "%s(): pRegion[%d] bufferRowLength (%d) must be zero or greater-than-or-equal-to imageExtent.width (%d). %s",
26785971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                function, i, pRegions[i].bufferRowLength, pRegions[i].imageExtent.width,
26795971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                validation_error_map[VALIDATION_ERROR_01265]);
26805971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        }
26815971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton
26825971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        //  BufferImageHeight must be 0, or greater than or equal to the height member of imageExtent
26835971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        if ((pRegions[i].bufferImageHeight != 0) && (pRegions[i].bufferImageHeight < pRegions[i].imageExtent.height)) {
26845971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            skip |= log_msg(
26855971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
26865971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01266, "IMAGE",
26875971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                "%s(): pRegion[%d] bufferImageHeight (%d) must be zero or greater-than-or-equal-to imageExtent.height (%d). %s",
26885971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                function, i, pRegions[i].bufferImageHeight, pRegions[i].imageExtent.height,
26895971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                validation_error_map[VALIDATION_ERROR_01266]);
26905971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        }
26915971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton
26925971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        // subresource aspectMask must have exactly 1 bit set
26935971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        const int num_bits = sizeof(VkFlags) * CHAR_BIT;
26945971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        std::bitset<num_bits> aspect_mask_bits(pRegions[i].imageSubresource.aspectMask);
26955971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        if (aspect_mask_bits.count() != 1) {
26965971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
26975971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                            reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01280, "IMAGE",
26985971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                            "%s: aspectMasks for imageSubresource in each region must have only a single bit set. %s", function,
26995971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                            validation_error_map[VALIDATION_ERROR_01280]);
27005971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        }
27015971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton
27025971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        // image subresource aspect bit must match format
27035971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        if (((0 != (pRegions[i].imageSubresource.aspectMask & VK_IMAGE_ASPECT_COLOR_BIT)) &&
27045971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton             (!vk_format_is_color(image_state->createInfo.format))) ||
27055971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            ((0 != (pRegions[i].imageSubresource.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT)) &&
27065971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton             (!vk_format_has_depth(image_state->createInfo.format))) ||
27075971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            ((0 != (pRegions[i].imageSubresource.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT)) &&
27085971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton             (!vk_format_has_stencil(image_state->createInfo.format)))) {
27095971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            skip |= log_msg(
27105971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
27115971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01279, "IMAGE",
27125971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                "%s(): pRegion[%d] subresource aspectMask 0x%x specifies aspects that are not present in image format 0x%x. %s",
27135971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                function, i, pRegions[i].imageSubresource.aspectMask, image_state->createInfo.format,
27145971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                validation_error_map[VALIDATION_ERROR_01279]);
27155971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        }
27165971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton
27175971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        // Checks that apply only to compressed images
27185971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        // TODO: there is a comment in ValidateCopyBufferImageTransferGranularityRequirements() in core_validation.cpp that
27195971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        //       reserves a place for these compressed image checks.  This block of code could move there once the image
27205971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        //       stuff is moved into core validation.
27215971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        if (vk_format_is_compressed(image_state->createInfo.format)) {
27225971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            auto block_size = vk_format_compressed_texel_block_extents(image_state->createInfo.format);
2723877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski
27245971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            //  BufferRowLength must be a multiple of block width
27255971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            if (vk_safe_modulo(pRegions[i].bufferRowLength, block_size.width) != 0) {
2726877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski                skip |= log_msg(
2727877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski                    report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
27285971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                    reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01271, "IMAGE",
27295971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                    "%s(): pRegion[%d] bufferRowLength (%d) must be a multiple of the compressed image's texel width (%d). %s.",
27305971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                    function, i, pRegions[i].bufferRowLength, block_size.width, validation_error_map[VALIDATION_ERROR_01271]);
2731877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski            }
2732877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski
27335971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            //  BufferRowHeight must be a multiple of block height
27345971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            if (vk_safe_modulo(pRegions[i].bufferImageHeight, block_size.height) != 0) {
2735877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
27365971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01272, "IMAGE",
27375971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                "%s(): pRegion[%d] bufferImageHeight (%d) must be a multiple of the compressed image's texel "
27385971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                "height (%d). %s.",
27395971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                function, i, pRegions[i].bufferImageHeight, block_size.height,
27405971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                validation_error_map[VALIDATION_ERROR_01272]);
2741877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski            }
2742877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski
27435971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            //  image offsets must be multiples of block dimensions
27445971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            if ((vk_safe_modulo(pRegions[i].imageOffset.x, block_size.width) != 0) ||
2745045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                (vk_safe_modulo(pRegions[i].imageOffset.y, block_size.height) != 0) ||
2746045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                (vk_safe_modulo(pRegions[i].imageOffset.z, block_size.depth) != 0)) {
27475971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
27485971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01273, "IMAGE",
27495971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                "%s(): pRegion[%d] imageOffset(x,y) (%d, %d) must be multiples of the compressed image's texel "
27505971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                "width & height (%d, %d). %s.",
27515971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                function, i, pRegions[i].imageOffset.x, pRegions[i].imageOffset.y, block_size.width,
27525971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                block_size.height, validation_error_map[VALIDATION_ERROR_01273]);
2753877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski            }
2754877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski
27555971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            // bufferOffset must be a multiple of block size (linear bytes)
27565971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            size_t block_size_in_bytes = vk_format_get_size(image_state->createInfo.format);
27575971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            if (vk_safe_modulo(pRegions[i].bufferOffset, block_size_in_bytes) != 0) {
27585971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
27595971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01274, "IMAGE",
27605971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                "%s(): pRegion[%d] bufferOffset (0x%" PRIxLEAST64
27615971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                ") must be a multiple of the compressed image's texel block "
27625971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                "size (" PRINTF_SIZE_T_SPECIFIER "). %s.",
27635971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                function, i, pRegions[i].bufferOffset, block_size_in_bytes,
27645971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                validation_error_map[VALIDATION_ERROR_01274]);
2765877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski            }
27662cd49094dcd399721f50c123413b8f55693348d7Dave Houlton
27672cd49094dcd399721f50c123413b8f55693348d7Dave Houlton            // imageExtent width must be a multiple of block width, or extent+offset width must equal subresource width
2768045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton            VkExtent3D mip_extent = GetImageSubresourceExtent(image_state, &(pRegions[i].imageSubresource));
27692cd49094dcd399721f50c123413b8f55693348d7Dave Houlton            if ((vk_safe_modulo(pRegions[i].imageExtent.width, block_size.width) != 0) &&
2770045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                (pRegions[i].imageExtent.width + pRegions[i].imageOffset.x != mip_extent.width)) {
2771045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
2772045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                                reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01275, "IMAGE",
2773045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                                "%s(): pRegion[%d] extent width (%d) must be a multiple of the compressed texture block width "
2774045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                                "(%d), or when added to offset.x (%d) must equal the image subresource width (%d). %s.",
2775045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                                function, i, pRegions[i].imageExtent.width, block_size.width, pRegions[i].imageOffset.x,
2776045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                                mip_extent.width, validation_error_map[VALIDATION_ERROR_01275]);
27772cd49094dcd399721f50c123413b8f55693348d7Dave Houlton            }
27782cd49094dcd399721f50c123413b8f55693348d7Dave Houlton
27792cd49094dcd399721f50c123413b8f55693348d7Dave Houlton            // imageExtent height must be a multiple of block height, or extent+offset height must equal subresource height
27802cd49094dcd399721f50c123413b8f55693348d7Dave Houlton            if ((vk_safe_modulo(pRegions[i].imageExtent.height, block_size.height) != 0) &&
2781045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                (pRegions[i].imageExtent.height + pRegions[i].imageOffset.y != mip_extent.height)) {
2782045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
2783045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                                reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01276, "IMAGE",
2784045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                                "%s(): pRegion[%d] extent height (%d) must be a multiple of the compressed texture block height "
2785045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                                "(%d), or when added to offset.y (%d) must equal the image subresource height (%d). %s.",
2786045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                                function, i, pRegions[i].imageExtent.height, block_size.height, pRegions[i].imageOffset.y,
2787045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                                mip_extent.height, validation_error_map[VALIDATION_ERROR_01276]);
27882cd49094dcd399721f50c123413b8f55693348d7Dave Houlton            }
27892cd49094dcd399721f50c123413b8f55693348d7Dave Houlton
27902cd49094dcd399721f50c123413b8f55693348d7Dave Houlton            // imageExtent depth must be a multiple of block depth, or extent+offset depth must equal subresource depth
27912cd49094dcd399721f50c123413b8f55693348d7Dave Houlton            if ((vk_safe_modulo(pRegions[i].imageExtent.depth, block_size.depth) != 0) &&
2792045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                (pRegions[i].imageExtent.depth + pRegions[i].imageOffset.z != mip_extent.depth)) {
2793045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
2794045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                                reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01277, "IMAGE",
2795045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                                "%s(): pRegion[%d] extent width (%d) must be a multiple of the compressed texture block depth "
2796045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                                "(%d), or when added to offset.z (%d) must equal the image subresource depth (%d). %s.",
2797045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                                function, i, pRegions[i].imageExtent.depth, block_size.depth, pRegions[i].imageOffset.z,
2798045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton                                mip_extent.depth, validation_error_map[VALIDATION_ERROR_01277]);
27992cd49094dcd399721f50c123413b8f55693348d7Dave Houlton            }
28005971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        }
280171c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    }
280271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
280371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    return skip;
280471c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski}
280571c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
28065971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houltonstatic bool ValidateImageBounds(const debug_report_data *report_data, const IMAGE_STATE *image_state, const uint32_t regionCount,
28075971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                                const VkBufferImageCopy *pRegions, const char *func_name, UNIQUE_VALIDATION_ERROR_CODE msg_code) {
280871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    bool skip = false;
28095971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton    const VkImageCreateInfo *image_info = &(image_state->createInfo);
281071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
281171c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    for (uint32_t i = 0; i < regionCount; i++) {
281271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        VkExtent3D extent = pRegions[i].imageExtent;
281371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        VkOffset3D offset = pRegions[i].imageOffset;
281471c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
28155971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        if (IsExtentSizeZero(&extent))  // Warn on zero area subresource
28165971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        {
28175971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
28185971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                            (uint64_t)0, __LINE__, IMAGE_ZERO_AREA_SUBREGION, "IMAGE",
28195971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                            "%s: pRegion[%d] imageExtent of {%1d, %1d, %1d} has zero area", func_name, i, extent.width,
28205971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                            extent.height, extent.depth);
282171c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        }
282271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
28235971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        VkExtent3D image_extent = GetImageSubresourceExtent(image_state, &(pRegions[i].imageSubresource));
28245971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton
28255971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        // If we're using a compressed format, valid extent is rounded up to multiple of block size (per 18.1)
28265971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        if (vk_format_is_compressed(image_info->format)) {
28275971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            auto block_extent = vk_format_compressed_texel_block_extents(image_info->format);
28285971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            if (image_extent.width % block_extent.width) {
28295971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                image_extent.width += (block_extent.width - (image_extent.width % block_extent.width));
28305971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            }
28315971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            if (image_extent.height % block_extent.height) {
28325971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                image_extent.height += (block_extent.height - (image_extent.height % block_extent.height));
28335971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            }
28345971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            if (image_extent.depth % block_extent.depth) {
28355971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                image_extent.depth += (block_extent.depth - (image_extent.depth % block_extent.depth));
28365971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            }
283771c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        }
283871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
28395971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        if (ExceedsBounds(&offset, &extent, &image_extent)) {
284071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)0,
28415971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                            __LINE__, msg_code, "IMAGE", "%s: pRegion[%d] exceeds image bounds. %s.", func_name, i,
284271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                            validation_error_map[msg_code]);
2843877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski        }
2844877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski    }
2845877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski
2846877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski    return skip;
2847877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski}
2848877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski
284971c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinskistatic inline bool ValidtateBufferBounds(const debug_report_data *report_data, IMAGE_STATE *image_state, BUFFER_STATE *buff_state,
285071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                                         uint32_t regionCount, const VkBufferImageCopy *pRegions, const char *func_name,
285171c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                                         UNIQUE_VALIDATION_ERROR_CODE msg_code) {
285271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    bool skip = false;
285371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
285471c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    VkDeviceSize buffer_size = buff_state->createInfo.size;
285571c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
285671c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    for (uint32_t i = 0; i < regionCount; i++) {
285771c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        VkExtent3D copy_extent = pRegions[i].imageExtent;
285871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
285971c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        VkDeviceSize buffer_width = (0 == pRegions[i].bufferRowLength ? copy_extent.width : pRegions[i].bufferRowLength);
286071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        VkDeviceSize buffer_height = (0 == pRegions[i].bufferImageHeight ? copy_extent.height : pRegions[i].bufferImageHeight);
286171c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        VkDeviceSize unit_size = vk_format_get_size(image_state->createInfo.format);  // size (bytes) of texel or block
286271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
28631dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton        // Handle special buffer packing rules for specific depth/stencil formats
28641dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton        if (pRegions[i].imageSubresource.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) {
28651dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton            unit_size = vk_format_get_size(VK_FORMAT_S8_UINT);
28661dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton        } else if (pRegions[i].imageSubresource.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) {
28671dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton            switch (image_state->createInfo.format) {
28681dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton                case VK_FORMAT_D16_UNORM_S8_UINT:
28691dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton                    unit_size = vk_format_get_size(VK_FORMAT_D16_UNORM);
28701dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton                    break;
28711dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton                case VK_FORMAT_D32_SFLOAT_S8_UINT:
28721dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton                    unit_size = vk_format_get_size(VK_FORMAT_D32_SFLOAT);
28731dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton                    break;
28745971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                case VK_FORMAT_X8_D24_UNORM_PACK32:  // Fall through
28751dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton                case VK_FORMAT_D24_UNORM_S8_UINT:
28761dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton                    unit_size = 4;
28771dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton                    break;
28781dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton                default:
28791dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton                    break;
28801dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton            }
28811dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton        }
28821dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton
288371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        if (vk_format_is_compressed(image_state->createInfo.format)) {
28845971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            // Switch to texel block units, rounding up for any partially-used blocks
28855971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            auto block_dim = vk_format_compressed_texel_block_extents(image_state->createInfo.format);
28865971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            buffer_width = (buffer_width + block_dim.width - 1) / block_dim.width;
28875971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            buffer_height = (buffer_height + block_dim.height - 1) / block_dim.height;
288871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
28895971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            copy_extent.width = (copy_extent.width + block_dim.width - 1) / block_dim.width;
28905971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            copy_extent.height = (copy_extent.height + block_dim.height - 1) / block_dim.height;
28915971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            copy_extent.depth = (copy_extent.depth + block_dim.depth - 1) / block_dim.depth;
28925971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        }
289371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
28945971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        // Either depth or layerCount may be greater than 1 (not both). This is the number of 'slices' to copy
28955971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        uint32_t z_copies = std::max(copy_extent.depth, pRegions[i].imageSubresource.layerCount);
28965971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        if (IsExtentSizeZero(&copy_extent) || (0 == z_copies)) {
28975971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            // TODO: Issure warning here? Already warned in ValidateImageBounds()...
28985971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton        } else {
28995971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            // Calculate buffer offset of final copied byte, + 1.
29005971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            VkDeviceSize max_buffer_offset = (z_copies - 1) * buffer_height * buffer_width;      // offset to slice
29015971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            max_buffer_offset += ((copy_extent.height - 1) * buffer_width) + copy_extent.width;  // add row,col
29025971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            max_buffer_offset *= unit_size;                                                      // convert to bytes
29035971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            max_buffer_offset += pRegions[i].bufferOffset;                                       // add initial offset (bytes)
290471c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
29055971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            if (buffer_size < max_buffer_offset) {
29065971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                skip |=
29075971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                    log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)0,
29085971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                            __LINE__, msg_code, "IMAGE", "%s: pRegion[%d] exceeds buffer size of %" PRIu64 " bytes. %s.", func_name,
29095971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton                            i, buffer_size, validation_error_map[msg_code]);
29105971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton            }
291171c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        }
291271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    }
291371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
291471c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    return skip;
291571c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski}
291671c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
291771c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinskibool PreCallValidateCmdCopyImageToBuffer(layer_data *device_data, VkImageLayout srcImageLayout, GLOBAL_CB_NODE *cb_node,
2918940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski                                         IMAGE_STATE *src_image_state, BUFFER_STATE *dst_buffer_state, uint32_t regionCount,
2919877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski                                         const VkBufferImageCopy *pRegions, const char *func_name) {
292071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
292171c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    bool skip = ValidateBufferImageCopyData(report_data, regionCount, pRegions, src_image_state, "vkCmdCopyImageToBuffer");
292271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
292371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    // Validate command buffer state
292471c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    if (CB_RECORDING != cb_node->state) {
292571c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
292671c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                        (uint64_t)cb_node->commandBuffer, __LINE__, VALIDATION_ERROR_01258, "DS",
292771c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                        "Cannot call vkCmdCopyImageToBuffer() on command buffer which is not in recording state. %s.",
292871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                        validation_error_map[VALIDATION_ERROR_01258]);
292971c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    } else {
293071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        skip |= ValidateCmdSubpassState(device_data, cb_node, CMD_COPYIMAGETOBUFFER);
293171c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    }
293271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
293371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    // Command pool must support graphics, compute, or transfer operations
293471c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    auto pPool = GetCommandPoolNode(device_data, cb_node->createInfo.commandPool);
293571c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
293671c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    VkQueueFlags queue_flags = GetPhysDevProperties(device_data)->queue_family_properties[pPool->queueFamilyIndex].queueFlags;
293771c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    if (0 == (queue_flags & (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT))) {
293871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
293971c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                        (uint64_t)cb_node->createInfo.commandPool, __LINE__, VALIDATION_ERROR_01259, "DS",
294071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                        "Cannot call vkCmdCopyImageToBuffer() on a command buffer allocated from a pool without graphics, compute, "
294171c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                        "or transfer capabilities. %s.",
294271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                        validation_error_map[VALIDATION_ERROR_01259]);
294371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    }
29445971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton    skip |= ValidateImageBounds(report_data, src_image_state, regionCount, pRegions, "vkCmdCopyBufferToImage()",
294571c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                                VALIDATION_ERROR_01245);
2946940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    skip |= ValidtateBufferBounds(report_data, src_image_state, dst_buffer_state, regionCount, pRegions, "vkCmdCopyImageToBuffer()",
294771c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                                  VALIDATION_ERROR_01246);
294871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
294971c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    skip |= ValidateImageSampleCount(device_data, src_image_state, VK_SAMPLE_COUNT_1_BIT, "vkCmdCopyImageToBuffer(): srcImage",
295071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                                     VALIDATION_ERROR_01249);
295171c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    skip |= ValidateMemoryIsBoundToImage(device_data, src_image_state, "vkCmdCopyImageToBuffer()", VALIDATION_ERROR_02537);
2952940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    skip |= ValidateMemoryIsBoundToBuffer(device_data, dst_buffer_state, "vkCmdCopyImageToBuffer()", VALIDATION_ERROR_02538);
2953d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski
295471c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    // Validate that SRC image & DST buffer have correct usage flags set
295571c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    skip |= ValidateImageUsageFlags(device_data, src_image_state, VK_IMAGE_USAGE_TRANSFER_SRC_BIT, true, VALIDATION_ERROR_01248,
295671c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                                    "vkCmdCopyImageToBuffer()", "VK_IMAGE_USAGE_TRANSFER_SRC_BIT");
2957940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    skip |= ValidateBufferUsageFlags(device_data, dst_buffer_state, VK_BUFFER_USAGE_TRANSFER_DST_BIT, true, VALIDATION_ERROR_01252,
295871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                                     "vkCmdCopyImageToBuffer()", "VK_BUFFER_USAGE_TRANSFER_DST_BIT");
2959d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski    skip |= insideRenderPass(device_data, cb_node, "vkCmdCopyImageToBuffer()", VALIDATION_ERROR_01260);
2960d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski    for (uint32_t i = 0; i < regionCount; ++i) {
2961d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski        skip |= VerifySourceImageLayout(device_data, cb_node, src_image_state->image, pRegions[i].imageSubresource, srcImageLayout,
2962d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski                                        VALIDATION_ERROR_01251);
2963d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski        skip |= ValidateCopyBufferImageTransferGranularityRequirements(device_data, cb_node, src_image_state, &pRegions[i], i,
2964d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski                                                                       "CmdCopyImageToBuffer");
2965d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski    }
2966d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski    return skip;
2967d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski}
2968d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski
2969d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinskivoid PreCallRecordCmdCopyImageToBuffer(layer_data *device_data, GLOBAL_CB_NODE *cb_node, IMAGE_STATE *src_image_state,
2970940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski                                       BUFFER_STATE *dst_buffer_state) {
2971d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski    // Update bindings between buffer/image and cmd buffer
2972d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski    AddCommandBufferBindingImage(device_data, cb_node, src_image_state);
2973940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    AddCommandBufferBindingBuffer(device_data, cb_node, dst_buffer_state);
2974d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski
297571c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    std::function<bool()> function = [=]() {
297671c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        return ValidateImageMemoryIsValid(device_data, src_image_state, "vkCmdCopyImageToBuffer()");
297771c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    };
297871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    cb_node->validate_functions.push_back(function);
297971c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    function = [=]() {
2980940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski        SetBufferMemoryValid(device_data, dst_buffer_state, true);
298171c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        return false;
298271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    };
298371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    cb_node->validate_functions.push_back(function);
298471c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
298571c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    core_validation::UpdateCmdBufferLastCmd(cb_node, CMD_COPYIMAGETOBUFFER);
2986877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski}
2987877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski
298871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinskibool PreCallValidateCmdCopyBufferToImage(layer_data *device_data, VkImageLayout dstImageLayout, GLOBAL_CB_NODE *cb_node,
2989940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski                                         BUFFER_STATE *src_buffer_state, IMAGE_STATE *dst_image_state, uint32_t regionCount,
2990877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski                                         const VkBufferImageCopy *pRegions, const char *func_name) {
299171c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    const debug_report_data *report_data = core_validation::GetReportData(device_data);
299271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    bool skip = ValidateBufferImageCopyData(report_data, regionCount, pRegions, dst_image_state, "vkCmdCopyBufferToImage");
299371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
299471c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    // Validate command buffer state
299571c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    if (CB_RECORDING != cb_node->state) {
299671c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
299771c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                        (uint64_t)cb_node->commandBuffer, __LINE__, VALIDATION_ERROR_01240, "DS",
299871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                        "Cannot call vkCmdCopyBufferToImage() on command buffer which is not in recording state. %s.",
299971c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                        validation_error_map[VALIDATION_ERROR_01240]);
300071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    } else {
300171c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        skip |= ValidateCmdSubpassState(device_data, cb_node, CMD_COPYBUFFERTOIMAGE);
300271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    }
300371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
300471c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    // Command pool must support graphics, compute, or transfer operations
300571c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    auto pPool = GetCommandPoolNode(device_data, cb_node->createInfo.commandPool);
300671c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    VkQueueFlags queue_flags = GetPhysDevProperties(device_data)->queue_family_properties[pPool->queueFamilyIndex].queueFlags;
300771c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    if (0 == (queue_flags & (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT))) {
300871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
300971c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                        (uint64_t)cb_node->createInfo.commandPool, __LINE__, VALIDATION_ERROR_01241, "DS",
301071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                        "Cannot call vkCmdCopyBufferToImage() on a command buffer allocated from a pool without graphics, compute, "
301171c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                        "or transfer capabilities. %s.",
301271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                        validation_error_map[VALIDATION_ERROR_01241]);
301371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    }
30145971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton    skip |= ValidateImageBounds(report_data, dst_image_state, regionCount, pRegions, "vkCmdCopyBufferToImage()",
301571c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                                VALIDATION_ERROR_01228);
3016940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    skip |= ValidtateBufferBounds(report_data, dst_image_state, src_buffer_state, regionCount, pRegions, "vkCmdCopyBufferToImage()",
301771c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                                  VALIDATION_ERROR_01227);
301871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    skip |= ValidateImageSampleCount(device_data, dst_image_state, VK_SAMPLE_COUNT_1_BIT, "vkCmdCopyBufferToImage(): dstImage",
301971c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                                     VALIDATION_ERROR_01232);
3020940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    skip |= ValidateMemoryIsBoundToBuffer(device_data, src_buffer_state, "vkCmdCopyBufferToImage()", VALIDATION_ERROR_02535);
302171c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    skip |= ValidateMemoryIsBoundToImage(device_data, dst_image_state, "vkCmdCopyBufferToImage()", VALIDATION_ERROR_02536);
3022940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    skip |= ValidateBufferUsageFlags(device_data, src_buffer_state, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, true, VALIDATION_ERROR_01230,
302371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                                     "vkCmdCopyBufferToImage()", "VK_BUFFER_USAGE_TRANSFER_SRC_BIT");
302471c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    skip |= ValidateImageUsageFlags(device_data, dst_image_state, VK_IMAGE_USAGE_TRANSFER_DST_BIT, true, VALIDATION_ERROR_01231,
302571c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                                    "vkCmdCopyBufferToImage()", "VK_IMAGE_USAGE_TRANSFER_DST_BIT");
3026d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski    skip |= insideRenderPass(device_data, cb_node, "vkCmdCopyBufferToImage()", VALIDATION_ERROR_01242);
3027d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski    for (uint32_t i = 0; i < regionCount; ++i) {
3028d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski        skip |= VerifyDestImageLayout(device_data, cb_node, dst_image_state->image, pRegions[i].imageSubresource, dstImageLayout,
3029d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski                                      VALIDATION_ERROR_01234);
3030d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski        skip |= ValidateCopyBufferImageTransferGranularityRequirements(device_data, cb_node, dst_image_state, &pRegions[i], i,
3031d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski                                                                       "vkCmdCopyBufferToImage()");
3032d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski    }
3033d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski    return skip;
3034d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski}
3035d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski
3036940f70f1340803d185c67633b05ef048d277952eMark Lobodzinskivoid PreCallRecordCmdCopyBufferToImage(layer_data *device_data, GLOBAL_CB_NODE *cb_node, BUFFER_STATE *src_buffer_state,
3037d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski                                       IMAGE_STATE *dst_image_state) {
3038940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    AddCommandBufferBindingBuffer(device_data, cb_node, src_buffer_state);
3039d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski    AddCommandBufferBindingImage(device_data, cb_node, dst_image_state);
304071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    std::function<bool()> function = [=]() {
304171c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        SetImageMemoryValid(device_data, dst_image_state, true);
304271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski        return false;
304371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    };
304471c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    cb_node->validate_functions.push_back(function);
3045940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    function = [=]() { return ValidateBufferMemoryIsValid(device_data, src_buffer_state, "vkCmdCopyBufferToImage()"); };
304671c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    cb_node->validate_functions.push_back(function);
304771c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski
304871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski    core_validation::UpdateCmdBufferLastCmd(cb_node, CMD_COPYBUFFERTOIMAGE);
3049877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski}
3050e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen
3051e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblenbool PreCallValidateGetImageSubresourceLayout(layer_data *device_data, VkImage image, const VkImageSubresource *pSubresource) {
3052e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    const auto report_data = core_validation::GetReportData(device_data);
3053e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    bool skip = false;
3054e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    const VkImageAspectFlags sub_aspect = pSubresource->aspectMask;
3055e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen
3056e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    // VU 00733: The aspectMask member of pSubresource must only have a single bit set
3057e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    const int num_bits = sizeof(sub_aspect) * CHAR_BIT;
3058e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    std::bitset<num_bits> aspect_mask_bits(sub_aspect);
3059e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    if (aspect_mask_bits.count() != 1) {
3060e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
3061e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen                        VALIDATION_ERROR_00733, "IMAGE",
3062e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen                        "vkGetImageSubresourceLayout(): VkImageSubresource.aspectMask must have exactly 1 bit set. %s",
3063e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen                        validation_error_map[VALIDATION_ERROR_00733]);
3064e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    }
3065e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen
3066e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    IMAGE_STATE *image_entry = GetImageState(device_data, image);
3067e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    if (!image_entry) {
3068e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen        return skip;
3069e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    }
3070e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen
3071e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    // VU 00732: image must have been created with tiling equal to VK_IMAGE_TILING_LINEAR
3072e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    if (image_entry->createInfo.tiling != VK_IMAGE_TILING_LINEAR) {
3073e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, (uint64_t)image,
3074e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen                        __LINE__, VALIDATION_ERROR_00732, "IMAGE",
3075e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen                        "vkGetImageSubresourceLayout(): Image must have tiling of VK_IMAGE_TILING_LINEAR. %s",
3076e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen                        validation_error_map[VALIDATION_ERROR_00732]);
3077e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    }
3078e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen
3079e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    // VU 00739: mipLevel must be less than the mipLevels specified in VkImageCreateInfo when the image was created
3080e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    if (pSubresource->mipLevel >= image_entry->createInfo.mipLevels) {
3081e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, (uint64_t)image,
3082e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen                        __LINE__, VALIDATION_ERROR_00739, "IMAGE",
3083e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen                        "vkGetImageSubresourceLayout(): pSubresource.mipLevel (%d) must be less than %d. %s",
3084e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen                        pSubresource->mipLevel, image_entry->createInfo.mipLevels, validation_error_map[VALIDATION_ERROR_00739]);
3085e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    }
3086e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen
3087e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    // VU 00740: arrayLayer must be less than the arrayLayers specified in VkImageCreateInfo when the image was created
3088e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    if (pSubresource->arrayLayer >= image_entry->createInfo.arrayLayers) {
3089e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen        skip |= log_msg(
3090e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen            report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, (uint64_t)image, __LINE__,
3091e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen            VALIDATION_ERROR_00740, "IMAGE", "vkGetImageSubresourceLayout(): pSubresource.arrayLayer (%d) must be less than %d. %s",
3092e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen            pSubresource->arrayLayer, image_entry->createInfo.arrayLayers, validation_error_map[VALIDATION_ERROR_00740]);
3093e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    }
3094e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen
3095e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    // VU 00741: subresource's aspect must be compatible with image's format.
3096e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    const VkFormat img_format = image_entry->createInfo.format;
3097e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    if (vk_format_is_color(img_format)) {
3098e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen        if (sub_aspect != VK_IMAGE_ASPECT_COLOR_BIT) {
3099e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen            skip |= log_msg(
3100e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen                report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, (uint64_t)image, __LINE__,
3101e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen                VALIDATION_ERROR_00741, "IMAGE",
3102e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen                "vkGetImageSubresourceLayout(): For color formats, VkImageSubresource.aspectMask must be VK_IMAGE_ASPECT_COLOR. %s",
3103e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen                validation_error_map[VALIDATION_ERROR_00741]);
3104e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen        }
3105e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    } else if (vk_format_is_depth_or_stencil(img_format)) {
3106e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen        if ((sub_aspect != VK_IMAGE_ASPECT_DEPTH_BIT) && (sub_aspect != VK_IMAGE_ASPECT_STENCIL_BIT)) {
3107e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, (uint64_t)image,
3108e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen                            __LINE__, VALIDATION_ERROR_00741, "IMAGE",
3109e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen                            "vkGetImageSubresourceLayout(): For depth/stencil formats, VkImageSubresource.aspectMask must be "
3110e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen                            "either VK_IMAGE_ASPECT_DEPTH_BIT or VK_IMAGE_ASPECT_STENCIL_BIT. %s",
3111e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen                            validation_error_map[VALIDATION_ERROR_00741]);
3112e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen        }
3113e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    }
3114e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen    return skip;
3115e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen}
3116