buffer_validation.cpp revision dab32891b91206a5bef7a3929b781e44fc1b7268
1584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski/* Copyright (c) 2015-2017 The Khronos Group Inc. 2584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski * Copyright (c) 2015-2017 Valve Corporation 3584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski * Copyright (c) 2015-2017 LunarG, Inc. 4584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski * Copyright (C) 2015-2017 Google Inc. 5584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski * 6584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski * Licensed under the Apache License, Version 2.0 (the "License"); 7584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski * you may not use this file except in compliance with the License. 8584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski * You may obtain a copy of the License at 9584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski * 10584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski * http://www.apache.org/licenses/LICENSE-2.0 11584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski * 12584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski * Unless required by applicable law or agreed to in writing, software 13584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski * distributed under the License is distributed on an "AS IS" BASIS, 14584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski * See the License for the specific language governing permissions and 16584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski * limitations under the License. 17584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski * 18584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski * Author: Mark Lobodzinski <mark@lunarg.com> 19e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton * Author: Dave Houlton <daveh@lunarg.com> 20584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski */ 21584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski 22584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski// Allow use of STL min and max functions in Windows 23584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski#define NOMINMAX 24584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski 2523c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus#include <inttypes.h> 268dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski#include <sstream> 2723c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus#include <string> 288dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski 298dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski#include "vk_enum_string_helper.h" 308dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski#include "vk_layer_data.h" 318dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski#include "vk_layer_utils.h" 328dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski#include "vk_layer_logging.h" 338dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski 34584b2b6a66e3069a66727639e5a0b7ef9ebf13b6Mark Lobodzinski#include "buffer_validation.h" 35c06c9b88f5f5bcc7033ba41d5547b048fa6015a4Mark Lobodzinski 3623c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus// TODO: remove on NDK update (r15 will probably have proper STL impl) 3723c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus#ifdef __ANDROID__ 3823c5a2092f724fef497a5c87a489f32c8fa51e58Petr Krausnamespace std { 3923c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus 4023c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraustemplate <typename T> 4123c5a2092f724fef497a5c87a489f32c8fa51e58Petr Krausstd::string to_string(T var) { 4223c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus std::ostringstream ss; 4323c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus ss << var; 4423c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus return ss.str(); 4523c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus} 4623c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus} 4723c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus#endif 4823c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus 49e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisvoid SetLayout(layer_data *device_data, GLOBAL_CB_NODE *pCB, ImageSubresourcePair imgpair, const VkImageLayout &layout) { 500d2fd381af11d2202d3856cb2da2c7122a0294efChris Forbes if (pCB->imageLayoutMap.find(imgpair) != pCB->imageLayoutMap.end()) { 5155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski pCB->imageLayoutMap[imgpair].layout = layout; 5255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski } else { 5355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski assert(imgpair.hasSubresource); 5455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski IMAGE_CMD_BUF_LAYOUT_NODE node; 5555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski if (!FindCmdBufLayout(device_data, pCB, imgpair.image, imgpair.subresource, node)) { 5655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski node.initialLayout = layout; 5755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski } 5855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski SetLayout(device_data, pCB, imgpair, {node.initialLayout, layout}); 5955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski } 6055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski} 6155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinskitemplate <class OBJECT, class LAYOUT> 62e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisvoid SetLayout(layer_data *device_data, OBJECT *pObject, VkImage image, VkImageSubresource range, const LAYOUT &layout) { 6355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski ImageSubresourcePair imgpair = {image, true, range}; 6455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski SetLayout(device_data, pObject, imgpair, layout, VK_IMAGE_ASPECT_COLOR_BIT); 6555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski SetLayout(device_data, pObject, imgpair, layout, VK_IMAGE_ASPECT_DEPTH_BIT); 6655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski SetLayout(device_data, pObject, imgpair, layout, VK_IMAGE_ASPECT_STENCIL_BIT); 6755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski SetLayout(device_data, pObject, imgpair, layout, VK_IMAGE_ASPECT_METADATA_BIT); 6855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski} 6955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski 7055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinskitemplate <class OBJECT, class LAYOUT> 71e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisvoid SetLayout(layer_data *device_data, OBJECT *pObject, ImageSubresourcePair imgpair, const LAYOUT &layout, 7255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski VkImageAspectFlags aspectMask) { 7355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski if (imgpair.subresource.aspectMask & aspectMask) { 7455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski imgpair.subresource.aspectMask = aspectMask; 7555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski SetLayout(device_data, pObject, imgpair, layout); 7655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski } 7755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski} 7855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski 7951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour// Set the layout in supplied map 80440bdd357701497c3442e3515f12ac1cfffc180aTony Barbourvoid SetLayout(std::unordered_map<ImageSubresourcePair, IMAGE_LAYOUT_NODE> &imageLayoutMap, ImageSubresourcePair imgpair, 81440bdd357701497c3442e3515f12ac1cfffc180aTony Barbour VkImageLayout layout) { 8251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour imageLayoutMap[imgpair].layout = layout; 8351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour} 8451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 850db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlisbool FindLayoutVerifyNode(layer_data const *device_data, GLOBAL_CB_NODE const *pCB, ImageSubresourcePair imgpair, 8655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski IMAGE_CMD_BUF_LAYOUT_NODE &node, const VkImageAspectFlags aspectMask) { 8755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski const debug_report_data *report_data = core_validation::GetReportData(device_data); 8855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski 8955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski if (!(imgpair.subresource.aspectMask & aspectMask)) { 9055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski return false; 9155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski } 9255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski VkImageAspectFlags oldAspectMask = imgpair.subresource.aspectMask; 9355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski imgpair.subresource.aspectMask = aspectMask; 9455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski auto imgsubIt = pCB->imageLayoutMap.find(imgpair); 9555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski if (imgsubIt == pCB->imageLayoutMap.end()) { 9655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski return false; 9755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski } 9855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski if (node.layout != VK_IMAGE_LAYOUT_MAX_ENUM && node.layout != imgsubIt->second.layout) { 999b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, HandleToUint64(imgpair.image), 1009b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus __LINE__, DRAWSTATE_INVALID_LAYOUT, "DS", 10155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski "Cannot query for VkImage 0x%" PRIx64 " layout when combined aspect mask %d has multiple layout types: %s and %s", 1029b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(imgpair.image), oldAspectMask, string_VkImageLayout(node.layout), 10355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski string_VkImageLayout(imgsubIt->second.layout)); 10455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski } 10555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski if (node.initialLayout != VK_IMAGE_LAYOUT_MAX_ENUM && node.initialLayout != imgsubIt->second.initialLayout) { 1069b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, HandleToUint64(imgpair.image), 1079b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus __LINE__, DRAWSTATE_INVALID_LAYOUT, "DS", 10855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski "Cannot query for VkImage 0x%" PRIx64 10955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski " layout when combined aspect mask %d has multiple initial layout types: %s and %s", 1109b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(imgpair.image), oldAspectMask, string_VkImageLayout(node.initialLayout), 11155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski string_VkImageLayout(imgsubIt->second.initialLayout)); 11255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski } 11355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski node = imgsubIt->second; 11455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski return true; 11555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski} 11655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski 1170db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlisbool FindLayoutVerifyLayout(layer_data const *device_data, ImageSubresourcePair imgpair, VkImageLayout &layout, 11855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski const VkImageAspectFlags aspectMask) { 11955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski if (!(imgpair.subresource.aspectMask & aspectMask)) { 12055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski return false; 12155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski } 12255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski const debug_report_data *report_data = core_validation::GetReportData(device_data); 12355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski VkImageAspectFlags oldAspectMask = imgpair.subresource.aspectMask; 12455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski imgpair.subresource.aspectMask = aspectMask; 12555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski auto imgsubIt = (*core_validation::GetImageLayoutMap(device_data)).find(imgpair); 12655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski if (imgsubIt == (*core_validation::GetImageLayoutMap(device_data)).end()) { 12755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski return false; 12855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski } 12955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski if (layout != VK_IMAGE_LAYOUT_MAX_ENUM && layout != imgsubIt->second.layout) { 1309b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, HandleToUint64(imgpair.image), 1319b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus __LINE__, DRAWSTATE_INVALID_LAYOUT, "DS", 13255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski "Cannot query for VkImage 0x%" PRIx64 " layout when combined aspect mask %d has multiple layout types: %s and %s", 1339b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(imgpair.image), oldAspectMask, string_VkImageLayout(layout), 13455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski string_VkImageLayout(imgsubIt->second.layout)); 13555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski } 13655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski layout = imgsubIt->second.layout; 13755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski return true; 13855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski} 13955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski 14055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski// Find layout(s) on the command buffer level 1410db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlisbool FindCmdBufLayout(layer_data const *device_data, GLOBAL_CB_NODE const *pCB, VkImage image, VkImageSubresource range, 14255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski IMAGE_CMD_BUF_LAYOUT_NODE &node) { 14355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski ImageSubresourcePair imgpair = {image, true, range}; 14455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski node = IMAGE_CMD_BUF_LAYOUT_NODE(VK_IMAGE_LAYOUT_MAX_ENUM, VK_IMAGE_LAYOUT_MAX_ENUM); 14555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski FindLayoutVerifyNode(device_data, pCB, imgpair, node, VK_IMAGE_ASPECT_COLOR_BIT); 14655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski FindLayoutVerifyNode(device_data, pCB, imgpair, node, VK_IMAGE_ASPECT_DEPTH_BIT); 14755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski FindLayoutVerifyNode(device_data, pCB, imgpair, node, VK_IMAGE_ASPECT_STENCIL_BIT); 14855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski FindLayoutVerifyNode(device_data, pCB, imgpair, node, VK_IMAGE_ASPECT_METADATA_BIT); 14955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski if (node.layout == VK_IMAGE_LAYOUT_MAX_ENUM) { 15055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski imgpair = {image, false, VkImageSubresource()}; 15155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski auto imgsubIt = pCB->imageLayoutMap.find(imgpair); 15255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski if (imgsubIt == pCB->imageLayoutMap.end()) return false; 15355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski // TODO: This is ostensibly a find function but it changes state here 15455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski node = imgsubIt->second; 15555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski } 15655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski return true; 15755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski} 15855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski 15955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski// Find layout(s) on the global level 160e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisbool FindGlobalLayout(layer_data *device_data, ImageSubresourcePair imgpair, VkImageLayout &layout) { 16155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski layout = VK_IMAGE_LAYOUT_MAX_ENUM; 16255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski FindLayoutVerifyLayout(device_data, imgpair, layout, VK_IMAGE_ASPECT_COLOR_BIT); 16355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski FindLayoutVerifyLayout(device_data, imgpair, layout, VK_IMAGE_ASPECT_DEPTH_BIT); 16455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski FindLayoutVerifyLayout(device_data, imgpair, layout, VK_IMAGE_ASPECT_STENCIL_BIT); 16555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski FindLayoutVerifyLayout(device_data, imgpair, layout, VK_IMAGE_ASPECT_METADATA_BIT); 16655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski if (layout == VK_IMAGE_LAYOUT_MAX_ENUM) { 16755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski imgpair = {imgpair.image, false, VkImageSubresource()}; 16855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski auto imgsubIt = (*core_validation::GetImageLayoutMap(device_data)).find(imgpair); 16955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski if (imgsubIt == (*core_validation::GetImageLayoutMap(device_data)).end()) return false; 17055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski layout = imgsubIt->second.layout; 17155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski } 17255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski return true; 17355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski} 17455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski 175e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisbool FindLayouts(layer_data *device_data, VkImage image, std::vector<VkImageLayout> &layouts) { 17655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski auto sub_data = (*core_validation::GetImageSubresourceMap(device_data)).find(image); 17755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski if (sub_data == (*core_validation::GetImageSubresourceMap(device_data)).end()) return false; 1789a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_state = GetImageState(device_data, image); 17955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski if (!image_state) return false; 18055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski bool ignoreGlobal = false; 18155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski // TODO: Make this robust for >1 aspect mask. Now it will just say ignore potential errors in this case. 18255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski if (sub_data->second.size() >= (image_state->createInfo.arrayLayers * image_state->createInfo.mipLevels + 1)) { 18355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski ignoreGlobal = true; 18455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski } 18555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski for (auto imgsubpair : sub_data->second) { 18655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski if (ignoreGlobal && !imgsubpair.hasSubresource) continue; 18755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski auto img_data = (*core_validation::GetImageLayoutMap(device_data)).find(imgsubpair); 18855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski if (img_data != (*core_validation::GetImageLayoutMap(device_data)).end()) { 18955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski layouts.push_back(img_data->second.layout); 19055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski } 19155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski } 19255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski return true; 19355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski} 194440bdd357701497c3442e3515f12ac1cfffc180aTony Barbourbool FindLayout(const std::unordered_map<ImageSubresourcePair, IMAGE_LAYOUT_NODE> &imageLayoutMap, ImageSubresourcePair imgpair, 195440bdd357701497c3442e3515f12ac1cfffc180aTony Barbour VkImageLayout &layout, const VkImageAspectFlags aspectMask) { 19651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (!(imgpair.subresource.aspectMask & aspectMask)) { 19751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour return false; 19851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 19951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour imgpair.subresource.aspectMask = aspectMask; 20051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour auto imgsubIt = imageLayoutMap.find(imgpair); 20151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (imgsubIt == imageLayoutMap.end()) { 20251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour return false; 20351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 20451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour layout = imgsubIt->second.layout; 20551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour return true; 206440bdd357701497c3442e3515f12ac1cfffc180aTony Barbour} 20751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 20851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour// find layout in supplied map 209440bdd357701497c3442e3515f12ac1cfffc180aTony Barbourbool FindLayout(const std::unordered_map<ImageSubresourcePair, IMAGE_LAYOUT_NODE> &imageLayoutMap, ImageSubresourcePair imgpair, 210440bdd357701497c3442e3515f12ac1cfffc180aTony Barbour VkImageLayout &layout) { 21151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour layout = VK_IMAGE_LAYOUT_MAX_ENUM; 21251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour FindLayout(imageLayoutMap, imgpair, layout, VK_IMAGE_ASPECT_COLOR_BIT); 21351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour FindLayout(imageLayoutMap, imgpair, layout, VK_IMAGE_ASPECT_DEPTH_BIT); 21451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour FindLayout(imageLayoutMap, imgpair, layout, VK_IMAGE_ASPECT_STENCIL_BIT); 21551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour FindLayout(imageLayoutMap, imgpair, layout, VK_IMAGE_ASPECT_METADATA_BIT); 21651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (layout == VK_IMAGE_LAYOUT_MAX_ENUM) { 21751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour imgpair = {imgpair.image, false, VkImageSubresource()}; 21851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour auto imgsubIt = imageLayoutMap.find(imgpair); 21951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (imgsubIt == imageLayoutMap.end()) return false; 22051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour layout = imgsubIt->second.layout; 22151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 22251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour return true; 22351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour} 22455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski 22555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski// Set the layout on the global level 226e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisvoid SetGlobalLayout(layer_data *device_data, ImageSubresourcePair imgpair, const VkImageLayout &layout) { 22755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski VkImage &image = imgpair.image; 22855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski (*core_validation::GetImageLayoutMap(device_data))[imgpair].layout = layout; 22955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski auto &image_subresources = (*core_validation::GetImageSubresourceMap(device_data))[image]; 23055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski auto subresource = std::find(image_subresources.begin(), image_subresources.end(), imgpair); 23155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski if (subresource == image_subresources.end()) { 23255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski image_subresources.push_back(imgpair); 23355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski } 23455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski} 23555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski 23655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski// Set the layout on the cmdbuf level 237e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisvoid SetLayout(layer_data *device_data, GLOBAL_CB_NODE *pCB, ImageSubresourcePair imgpair, const IMAGE_CMD_BUF_LAYOUT_NODE &node) { 23855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski pCB->imageLayoutMap[imgpair] = node; 23955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski} 240a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis// Set image layout for given VkImageSubresourceRange struct 241a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlisvoid SetImageLayout(layer_data *device_data, GLOBAL_CB_NODE *cb_node, const IMAGE_STATE *image_state, 242a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis VkImageSubresourceRange image_subresource_range, const VkImageLayout &layout) { 243a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis assert(image_state); 244a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis for (uint32_t level_index = 0; level_index < image_subresource_range.levelCount; ++level_index) { 245a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis uint32_t level = image_subresource_range.baseMipLevel + level_index; 246a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis for (uint32_t layer_index = 0; layer_index < image_subresource_range.layerCount; layer_index++) { 247a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis uint32_t layer = image_subresource_range.baseArrayLayer + layer_index; 248a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis VkImageSubresource sub = {image_subresource_range.aspectMask, level, layer}; 24955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski // TODO: If ImageView was created with depth or stencil, transition both layouts as the aspectMask is ignored and both 25055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski // are used. Verify that the extra implicit layout is OK for descriptor set layout validation 251a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis if (image_subresource_range.aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { 25216769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton if (FormatIsDepthAndStencil(image_state->createInfo.format)) { 25355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski sub.aspectMask |= (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT); 25455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski } 25555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski } 256a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis SetLayout(device_data, cb_node, image_state->image, sub, layout); 25755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski } 25855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski } 25955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski} 260a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis// Set image layout for given VkImageSubresourceLayers struct 261a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlisvoid SetImageLayout(layer_data *device_data, GLOBAL_CB_NODE *cb_node, const IMAGE_STATE *image_state, 262a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis VkImageSubresourceLayers image_subresource_layers, const VkImageLayout &layout) { 263a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis // Transfer VkImageSubresourceLayers into VkImageSubresourceRange struct 264a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis VkImageSubresourceRange image_subresource_range; 265a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis image_subresource_range.aspectMask = image_subresource_layers.aspectMask; 266a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis image_subresource_range.baseArrayLayer = image_subresource_layers.baseArrayLayer; 267a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis image_subresource_range.layerCount = image_subresource_layers.layerCount; 268a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis image_subresource_range.baseMipLevel = image_subresource_layers.mipLevel; 269a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis image_subresource_range.levelCount = 1; 270a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis SetImageLayout(device_data, cb_node, image_state, image_subresource_range, layout); 271a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis} 272a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis// Set image layout for all slices of an image view 273a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlisvoid SetImageViewLayout(layer_data *device_data, GLOBAL_CB_NODE *cb_node, VkImageView imageView, const VkImageLayout &layout) { 274a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis auto view_state = GetImageViewState(device_data, imageView); 275a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis assert(view_state); 276a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis 277a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis SetImageLayout(device_data, cb_node, GetImageState(device_data, view_state->create_info.image), 278a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis view_state->create_info.subresourceRange, layout); 279a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis} 28055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski 281e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisbool VerifyFramebufferAndRenderPassLayouts(layer_data *device_data, GLOBAL_CB_NODE *pCB, 28255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski const VkRenderPassBeginInfo *pRenderPassBegin, 28355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski const FRAMEBUFFER_STATE *framebuffer_state) { 2843251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 2859a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto const pRenderPassInfo = GetRenderPassState(device_data, pRenderPassBegin->renderPass)->createInfo.ptr(); 28655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski auto const &framebufferInfo = framebuffer_state->createInfo; 28755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski const auto report_data = core_validation::GetReportData(device_data); 28855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski if (pRenderPassInfo->attachmentCount != framebufferInfo.attachmentCount) { 2893251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 2909b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS", 2913251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "You cannot start a render pass using a framebuffer " 2923251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "with a different number of attachments."); 29355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski } 29455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski for (uint32_t i = 0; i < pRenderPassInfo->attachmentCount; ++i) { 29555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski const VkImageView &image_view = framebufferInfo.pAttachments[i]; 2969a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto view_state = GetImageViewState(device_data, image_view); 29755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski assert(view_state); 29855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski const VkImage &image = view_state->create_info.image; 29955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski const VkImageSubresourceRange &subRange = view_state->create_info.subresourceRange; 3005f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlis auto initial_layout = pRenderPassInfo->pAttachments[i].initialLayout; 30155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski // TODO: Do not iterate over every possibility - consolidate where possible 30255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski for (uint32_t j = 0; j < subRange.levelCount; j++) { 30355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski uint32_t level = subRange.baseMipLevel + j; 30455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski for (uint32_t k = 0; k < subRange.layerCount; k++) { 30555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski uint32_t layer = subRange.baseArrayLayer + k; 30655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski VkImageSubresource sub = {subRange.aspectMask, level, layer}; 30755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski IMAGE_CMD_BUF_LAYOUT_NODE node; 30855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski if (!FindCmdBufLayout(device_data, pCB, image, sub, node)) { 3095f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlis // Missing layouts will be added during state update 31055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski continue; 31155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski } 3125f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlis if (initial_layout != VK_IMAGE_LAYOUT_UNDEFINED && initial_layout != node.layout) { 3133251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 3143251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS", 3153251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "You cannot start a render pass using attachment %u " 3163251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "where the render pass initial layout is %s and the previous " 3173251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "known layout of the attachment is %s. The layouts must match, or " 3183251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "the render pass initial layout for the attachment must be " 3193251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "VK_IMAGE_LAYOUT_UNDEFINED", 3203251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski i, string_VkImageLayout(initial_layout), string_VkImageLayout(node.layout)); 32155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski } 32255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski } 32355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski } 32455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski } 3253251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 32655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski} 32755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski 328e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisvoid TransitionAttachmentRefLayout(layer_data *device_data, GLOBAL_CB_NODE *pCB, FRAMEBUFFER_STATE *pFramebuffer, 32955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski VkAttachmentReference ref) { 33055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski if (ref.attachment != VK_ATTACHMENT_UNUSED) { 33155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski auto image_view = pFramebuffer->createInfo.pAttachments[ref.attachment]; 33255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski SetImageViewLayout(device_data, pCB, image_view, ref.layout); 33355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski } 33455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski} 33555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski 3365f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlisvoid TransitionSubpassLayouts(layer_data *device_data, GLOBAL_CB_NODE *pCB, const RENDER_PASS_STATE *render_pass_state, 337e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlis const int subpass_index, FRAMEBUFFER_STATE *framebuffer_state) { 3385f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlis assert(render_pass_state); 33955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski 34055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski if (framebuffer_state) { 3415f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlis auto const &subpass = render_pass_state->createInfo.pSubpasses[subpass_index]; 34255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) { 34355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski TransitionAttachmentRefLayout(device_data, pCB, framebuffer_state, subpass.pInputAttachments[j]); 34455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski } 34555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) { 34655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski TransitionAttachmentRefLayout(device_data, pCB, framebuffer_state, subpass.pColorAttachments[j]); 34755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski } 34855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski if (subpass.pDepthStencilAttachment) { 34955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski TransitionAttachmentRefLayout(device_data, pCB, framebuffer_state, *subpass.pDepthStencilAttachment); 35055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski } 35155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski } 35255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski} 35355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski 354e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinskibool ValidateImageAspectLayout(layer_data *device_data, GLOBAL_CB_NODE *pCB, const VkImageMemoryBarrier *mem_barrier, 355e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski uint32_t level, uint32_t layer, VkImageAspectFlags aspect) { 35655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski if (!(mem_barrier->subresourceRange.aspectMask & aspect)) { 35755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski return false; 35855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski } 35955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski VkImageSubresource sub = {aspect, level, layer}; 36055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski IMAGE_CMD_BUF_LAYOUT_NODE node; 36155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski if (!FindCmdBufLayout(device_data, pCB, mem_barrier->image, sub, node)) { 36255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski return false; 36355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski } 36455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski bool skip = false; 36555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski if (mem_barrier->oldLayout == VK_IMAGE_LAYOUT_UNDEFINED) { 36655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski // TODO: Set memory invalid which is in mem_tracker currently 36755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski } else if (node.layout != mem_barrier->oldLayout) { 3680620f54d857b76b4866f3835bc1aea96e525699cMark Lobodzinski skip |= 3690620f54d857b76b4866f3835bc1aea96e525699cMark Lobodzinski log_msg(core_validation::GetReportData(device_data), VK_DEBUG_REPORT_ERROR_BIT_EXT, 3709b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, HandleToUint64(pCB->commandBuffer), __LINE__, 3710620f54d857b76b4866f3835bc1aea96e525699cMark Lobodzinski DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS", 3720620f54d857b76b4866f3835bc1aea96e525699cMark Lobodzinski "For image 0x%" PRIxLEAST64 " you cannot transition the layout of aspect %d from %s when current layout is %s.", 3739b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(mem_barrier->image), aspect, string_VkImageLayout(mem_barrier->oldLayout), 3740620f54d857b76b4866f3835bc1aea96e525699cMark Lobodzinski string_VkImageLayout(node.layout)); 37555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski } 37655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski return skip; 37755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski} 37855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski 3795f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlis// Transition the layout state for renderpass attachments based on the BeginRenderPass() call. This includes: 3805f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlis// 1. Transition into initialLayout state 3815f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlis// 2. Transition from initialLayout to layout used in subpass 0 3825f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlisvoid TransitionBeginRenderPassLayouts(layer_data *device_data, GLOBAL_CB_NODE *cb_state, const RENDER_PASS_STATE *render_pass_state, 3835f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlis FRAMEBUFFER_STATE *framebuffer_state) { 3845f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlis // First transition into initialLayout 3855f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlis auto const rpci = render_pass_state->createInfo.ptr(); 3865f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlis for (uint32_t i = 0; i < rpci->attachmentCount; ++i) { 3875f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlis VkImageView image_view = framebuffer_state->createInfo.pAttachments[i]; 3885f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlis SetImageViewLayout(device_data, cb_state, image_view, rpci->pAttachments[i].initialLayout); 3895f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlis } 3905f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlis // Now transition for first subpass (index 0) 3915f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlis TransitionSubpassLayouts(device_data, cb_state, render_pass_state, 0, framebuffer_state); 3925f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlis} 3935f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlis 394e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinskivoid TransitionImageAspectLayout(layer_data *device_data, GLOBAL_CB_NODE *pCB, const VkImageMemoryBarrier *mem_barrier, 395e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski uint32_t level, uint32_t layer, VkImageAspectFlags aspect) { 396e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski if (!(mem_barrier->subresourceRange.aspectMask & aspect)) { 397e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski return; 398e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski } 399e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski VkImageSubresource sub = {aspect, level, layer}; 400e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski IMAGE_CMD_BUF_LAYOUT_NODE node; 401e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski if (!FindCmdBufLayout(device_data, pCB, mem_barrier->image, sub, node)) { 402e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski SetLayout(device_data, pCB, mem_barrier->image, sub, 403e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski IMAGE_CMD_BUF_LAYOUT_NODE(mem_barrier->oldLayout, mem_barrier->newLayout)); 404e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski return; 405e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski } 406e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski if (mem_barrier->oldLayout == VK_IMAGE_LAYOUT_UNDEFINED) { 407e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski // TODO: Set memory invalid 408e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski } 409e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski SetLayout(device_data, pCB, mem_barrier->image, sub, mem_barrier->newLayout); 410e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski} 411e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski 41265b2f2c31703462c8ad1fcf4543c459df8a028ccDave Houltonbool VerifyAspectsPresent(VkImageAspectFlags aspect_mask, VkFormat format) { 413e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton if ((aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT) != 0) { 41416769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton if (!FormatIsColor(format)) return false; 415e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton } 416e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton if ((aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) != 0) { 41716769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton if (!FormatHasDepth(format)) return false; 418e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton } 419e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton if ((aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT) != 0) { 42016769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton if (!FormatHasStencil(format)) return false; 421e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton } 422e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton return true; 423e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton} 424e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton 425a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen// Verify an ImageMemoryBarrier's old/new ImageLayouts are compatible with the Image's ImageUsageFlags. 426a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblenbool ValidateBarrierLayoutToImageUsage(layer_data *device_data, const VkImageMemoryBarrier *img_barrier, bool new_not_old, 427a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen VkImageUsageFlags usage_flags, const char *func_name) { 428a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen const auto report_data = core_validation::GetReportData(device_data); 429a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen bool skip = false; 430a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen const VkImageLayout layout = (new_not_old) ? img_barrier->newLayout : img_barrier->oldLayout; 431a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen UNIQUE_VALIDATION_ERROR_CODE msg_code = VALIDATION_ERROR_UNDEFINED; // sentinel value meaning "no error" 432a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen 433a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen switch (layout) { 434a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: 435a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen if ((usage_flags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) == 0) { 436315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis msg_code = VALIDATION_ERROR_0a000970; 437a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen } 438a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen break; 439a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: 440a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen if ((usage_flags & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) == 0) { 441315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis msg_code = VALIDATION_ERROR_0a000972; 442a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen } 443a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen break; 444a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL: 445a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen if ((usage_flags & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) == 0) { 446315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis msg_code = VALIDATION_ERROR_0a000974; 447a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen } 448a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen break; 449a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: 450a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen if ((usage_flags & (VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) == 0) { 451315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis msg_code = VALIDATION_ERROR_0a000976; 452a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen } 453a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen break; 454a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: 455a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen if ((usage_flags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) == 0) { 456315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis msg_code = VALIDATION_ERROR_0a000978; 457a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen } 458a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen break; 459a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: 460a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen if ((usage_flags & VK_IMAGE_USAGE_TRANSFER_DST_BIT) == 0) { 461315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis msg_code = VALIDATION_ERROR_0a00097a; 462a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen } 463a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen break; 464a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen default: 465a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen // Other VkImageLayout values do not have VUs defined in this context. 466a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen break; 467a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen } 468a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen 469a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen if (msg_code != VALIDATION_ERROR_UNDEFINED) { 470fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski skip |= 471fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 4729b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(img_barrier->image), __LINE__, msg_code, "DS", 473fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski "%s: Image barrier 0x%p %sLayout=%s is not compatible with image 0x%" PRIx64 " usage flags 0x%" PRIx32 ". %s", 474fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski func_name, img_barrier, ((new_not_old) ? "new" : "old"), string_VkImageLayout(layout), 4759b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(img_barrier->image), usage_flags, validation_error_map[msg_code]); 476a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen } 477a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen return skip; 478a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen} 479a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen 480a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen// Verify image barriers are compatible with the images they reference. 481a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblenbool ValidateBarriersToImages(layer_data *device_data, VkCommandBuffer cmdBuffer, uint32_t imageMemoryBarrierCount, 482a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen const VkImageMemoryBarrier *pImageMemoryBarriers, const char *func_name) { 4839a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(device_data, cmdBuffer); 48455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski bool skip = false; 485a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen 486a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen for (uint32_t i = 0; i < imageMemoryBarrierCount; ++i) { 487a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen auto img_barrier = &pImageMemoryBarriers[i]; 488a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen if (!img_barrier) continue; 48955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski 49087a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis auto image_state = GetImageState(device_data, img_barrier->image); 49187a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis if (image_state) { 49287a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis VkImageUsageFlags usage_flags = image_state->createInfo.usage; 49387a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis skip |= ValidateBarrierLayoutToImageUsage(device_data, img_barrier, false, usage_flags, func_name); 49487a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis skip |= ValidateBarrierLayoutToImageUsage(device_data, img_barrier, true, usage_flags, func_name); 49587a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis 49687a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis // Make sure layout is able to be transitioned, currently only presented shared presentable images are locked 49787a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis if (image_state->layout_locked) { 49887a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis // TODO: Add unique id for error when available 49987a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis skip |= log_msg(core_validation::GetReportData(device_data), VK_DEBUG_REPORT_ERROR_BIT_EXT, 50087a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 0, "DS", 50187a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis "Attempting to transition shared presentable image 0x%" PRIxLEAST64 50287a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis " from layout %s to layout %s, but image has already been presented and cannot have its layout transitioned.", 50387a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis reinterpret_cast<const uint64_t &>(img_barrier->image), string_VkImageLayout(img_barrier->oldLayout), 50487a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis string_VkImageLayout(img_barrier->newLayout)); 50587a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis } 50687a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis } 50787a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis 50895b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski VkImageCreateInfo *image_create_info = &(GetImageState(device_data, img_barrier->image)->createInfo); 509c7455116cef9c14f8405aae43bc0247f2c256f96Tobin Ehlis // For a Depth/Stencil image both aspects MUST be set 510c7455116cef9c14f8405aae43bc0247f2c256f96Tobin Ehlis if (FormatIsDepthAndStencil(image_create_info->format)) { 511c7455116cef9c14f8405aae43bc0247f2c256f96Tobin Ehlis auto const aspect_mask = img_barrier->subresourceRange.aspectMask; 512c7455116cef9c14f8405aae43bc0247f2c256f96Tobin Ehlis auto const ds_mask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; 513c7455116cef9c14f8405aae43bc0247f2c256f96Tobin Ehlis if ((aspect_mask & ds_mask) != (ds_mask)) { 514c7455116cef9c14f8405aae43bc0247f2c256f96Tobin Ehlis skip |= 515c7455116cef9c14f8405aae43bc0247f2c256f96Tobin Ehlis log_msg(core_validation::GetReportData(device_data), VK_DEBUG_REPORT_ERROR_BIT_EXT, 5169b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, HandleToUint64(img_barrier->image), __LINE__, 517315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_0a00096e, "DS", 518315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis "%s: Image barrier 0x%p references image 0x%" PRIx64 519315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis " of format %s that must have the depth and stencil aspects set, but its " 520315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis "aspectMask is 0x%" PRIx32 ". %s", 5219b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus func_name, img_barrier, HandleToUint64(img_barrier->image), string_VkFormat(image_create_info->format), 522315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis aspect_mask, validation_error_map[VALIDATION_ERROR_0a00096e]); 523c7455116cef9c14f8405aae43bc0247f2c256f96Tobin Ehlis } 524c7455116cef9c14f8405aae43bc0247f2c256f96Tobin Ehlis } 52595b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski uint32_t level_count = ResolveRemainingLevels(&img_barrier->subresourceRange, image_create_info->mipLevels); 52695b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski uint32_t layer_count = ResolveRemainingLayers(&img_barrier->subresourceRange, image_create_info->arrayLayers); 527a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen 528a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen for (uint32_t j = 0; j < level_count; j++) { 529a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen uint32_t level = img_barrier->subresourceRange.baseMipLevel + j; 530a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen for (uint32_t k = 0; k < layer_count; k++) { 531a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen uint32_t layer = img_barrier->subresourceRange.baseArrayLayer + k; 532a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen skip |= ValidateImageAspectLayout(device_data, pCB, img_barrier, level, layer, VK_IMAGE_ASPECT_COLOR_BIT); 533a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen skip |= ValidateImageAspectLayout(device_data, pCB, img_barrier, level, layer, VK_IMAGE_ASPECT_DEPTH_BIT); 534a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen skip |= ValidateImageAspectLayout(device_data, pCB, img_barrier, level, layer, VK_IMAGE_ASPECT_STENCIL_BIT); 535a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen skip |= ValidateImageAspectLayout(device_data, pCB, img_barrier, level, layer, VK_IMAGE_ASPECT_METADATA_BIT); 53655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski } 53755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski } 53855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski } 53955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski return skip; 54055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski} 54155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski 542e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinskivoid TransitionImageLayouts(layer_data *device_data, VkCommandBuffer cmdBuffer, uint32_t memBarrierCount, 543e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski const VkImageMemoryBarrier *pImgMemBarriers) { 544e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski GLOBAL_CB_NODE *pCB = GetCBNode(device_data, cmdBuffer); 545e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski 546e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski for (uint32_t i = 0; i < memBarrierCount; ++i) { 547e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski auto mem_barrier = &pImgMemBarriers[i]; 548e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski if (!mem_barrier) continue; 549e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski 55095b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski VkImageCreateInfo *image_create_info = &(GetImageState(device_data, mem_barrier->image)->createInfo); 55195b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski uint32_t level_count = ResolveRemainingLevels(&mem_barrier->subresourceRange, image_create_info->mipLevels); 55295b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski uint32_t layer_count = ResolveRemainingLayers(&mem_barrier->subresourceRange, image_create_info->arrayLayers); 55395b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski 55495b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski for (uint32_t j = 0; j < level_count; j++) { 555e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski uint32_t level = mem_barrier->subresourceRange.baseMipLevel + j; 55695b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski for (uint32_t k = 0; k < layer_count; k++) { 557e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski uint32_t layer = mem_barrier->subresourceRange.baseArrayLayer + k; 558e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski TransitionImageAspectLayout(device_data, pCB, mem_barrier, level, layer, VK_IMAGE_ASPECT_COLOR_BIT); 559e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski TransitionImageAspectLayout(device_data, pCB, mem_barrier, level, layer, VK_IMAGE_ASPECT_DEPTH_BIT); 560e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski TransitionImageAspectLayout(device_data, pCB, mem_barrier, level, layer, VK_IMAGE_ASPECT_STENCIL_BIT); 561e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski TransitionImageAspectLayout(device_data, pCB, mem_barrier, level, layer, VK_IMAGE_ASPECT_METADATA_BIT); 562e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski } 563e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski } 564e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski } 565e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski} 566e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski 5670db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlisbool VerifyImageLayout(layer_data const *device_data, GLOBAL_CB_NODE const *cb_node, IMAGE_STATE *image_state, 568fab4fd84d0d187bc73b5bc6709d8ed6370bb7cc3Tobin Ehlis VkImageSubresourceLayers subLayers, VkImageLayout explicit_layout, VkImageLayout optimal_layout, 5690db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlis const char *caller, UNIQUE_VALIDATION_ERROR_CODE msg_code, bool *error) { 57055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski const auto report_data = core_validation::GetReportData(device_data); 571fab4fd84d0d187bc73b5bc6709d8ed6370bb7cc3Tobin Ehlis const auto image = image_state->image; 5723251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 57355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski 57455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski for (uint32_t i = 0; i < subLayers.layerCount; ++i) { 57555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski uint32_t layer = i + subLayers.baseArrayLayer; 57655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski VkImageSubresource sub = {subLayers.aspectMask, subLayers.mipLevel, layer}; 57755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski IMAGE_CMD_BUF_LAYOUT_NODE node; 578a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis if (FindCmdBufLayout(device_data, cb_node, image, sub, node)) { 579a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis if (node.layout != explicit_layout) { 5800db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlis *error = true; 581a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis // TODO: Improve log message in the next pass 5823251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 5839b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(cb_node->commandBuffer), __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS", 5843251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "%s: Cannot use image 0x%" PRIxLEAST64 5853251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski " with specific layout %s that doesn't match the actual current layout %s.", 5869b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus caller, HandleToUint64(image), string_VkImageLayout(explicit_layout), 5873251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski string_VkImageLayout(node.layout)); 588a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis } 58955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski } 59055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski } 591fab4fd84d0d187bc73b5bc6709d8ed6370bb7cc3Tobin Ehlis // If optimal_layout is not UNDEFINED, check that layout matches optimal for this case 592fab4fd84d0d187bc73b5bc6709d8ed6370bb7cc3Tobin Ehlis if ((VK_IMAGE_LAYOUT_UNDEFINED != optimal_layout) && (explicit_layout != optimal_layout)) { 593fab4fd84d0d187bc73b5bc6709d8ed6370bb7cc3Tobin Ehlis if (VK_IMAGE_LAYOUT_GENERAL == explicit_layout) { 59455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski if (image_state->createInfo.tiling != VK_IMAGE_TILING_LINEAR) { 59555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski // LAYOUT_GENERAL is allowed, but may not be performance optimal, flag as perf warning. 5963251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, 5979b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, HandleToUint64(cb_node->commandBuffer), __LINE__, 5989b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS", 5993251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "%s: For optimal performance image 0x%" PRIxLEAST64 " layout should be %s instead of GENERAL.", 6009b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus caller, HandleToUint64(image), string_VkImageLayout(optimal_layout)); 60155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski } 602d4eaca34eca7f4b4e34190c441a579347bb2016aMark Lobodzinski } else if (GetDeviceExtensions(device_data)->vk_khr_shared_presentable_image) { 6036084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski if (image_state->shared_presentable) { 6046084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski if (VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR != explicit_layout) { 6056084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski // TODO: Add unique error id when available. 6066084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 6076084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski __LINE__, msg_code, "DS", 6086084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski "Layout for shared presentable image is %s but must be VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR.", 6096084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski string_VkImageLayout(optimal_layout)); 6106084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski } 61187a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis } 61255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski } else { 6130db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlis *error = true; 6143251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 6159b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(cb_node->commandBuffer), __LINE__, msg_code, "DS", 6163251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "%s: Layout for image 0x%" PRIxLEAST64 " is %s but can only be %s or VK_IMAGE_LAYOUT_GENERAL. %s", 6179b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus caller, HandleToUint64(image), string_VkImageLayout(explicit_layout), 6183251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski string_VkImageLayout(optimal_layout), validation_error_map[msg_code]); 61955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski } 62055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski } 6213251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 62255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski} 62355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski 624e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisvoid TransitionFinalSubpassLayouts(layer_data *device_data, GLOBAL_CB_NODE *pCB, const VkRenderPassBeginInfo *pRenderPassBegin, 625e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlis FRAMEBUFFER_STATE *framebuffer_state) { 6269a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto renderPass = GetRenderPassState(device_data, pRenderPassBegin->renderPass); 62755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski if (!renderPass) return; 62855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski 62955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski const VkRenderPassCreateInfo *pRenderPassInfo = renderPass->createInfo.ptr(); 63055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski if (framebuffer_state) { 63155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski for (uint32_t i = 0; i < pRenderPassInfo->attachmentCount; ++i) { 63255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski auto image_view = framebuffer_state->createInfo.pAttachments[i]; 63355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski SetImageViewLayout(device_data, pCB, image_view, pRenderPassInfo->pAttachments[i].finalLayout); 63455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski } 63555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski } 63655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski} 63755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski 638e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisbool PreCallValidateCreateImage(layer_data *device_data, const VkImageCreateInfo *pCreateInfo, 6398dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski const VkAllocationCallbacks *pAllocator, VkImage *pImage) { 6403251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 6418dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski const debug_report_data *report_data = core_validation::GetReportData(device_data); 6428dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski 6433c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes if (pCreateInfo->format == VK_FORMAT_UNDEFINED) { 6443251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 645315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_09e0075e, "IMAGE", "vkCreateImage: VkFormat for image must not be VK_FORMAT_UNDEFINED. %s", 646315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_09e0075e]); 6473c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes 6483251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 6493c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes } 6503c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes 6513c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes const VkFormatProperties *properties = GetFormatProperties(device_data, pCreateInfo->format); 6523c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes 6533c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes if ((pCreateInfo->tiling == VK_IMAGE_TILING_LINEAR) && (properties->linearTilingFeatures == 0)) { 6543c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes std::stringstream ss; 6553c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes ss << "vkCreateImage format parameter (" << string_VkFormat(pCreateInfo->format) << ") is an unsupported format"; 6563251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 657315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_09e007a2, "IMAGE", "%s. %s", ss.str().c_str(), 658315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_09e007a2]); 6593c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes 6603251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 6613c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes } 6623c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes 6633c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes if ((pCreateInfo->tiling == VK_IMAGE_TILING_OPTIMAL) && (properties->optimalTilingFeatures == 0)) { 6643c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes std::stringstream ss; 6653c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes ss << "vkCreateImage format parameter (" << string_VkFormat(pCreateInfo->format) << ") is an unsupported format"; 6663251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 667315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_09e007ac, "IMAGE", "%s. %s", ss.str().c_str(), 668315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_09e007ac]); 6693c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes 6703251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 6713c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes } 6728dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski 6733c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes // Validate that format supports usage as color attachment 6743c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes if (pCreateInfo->usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) { 6753c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes if ((pCreateInfo->tiling == VK_IMAGE_TILING_OPTIMAL) && 6763c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes ((properties->optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) == 0)) { 6778dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski std::stringstream ss; 6783c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes ss << "vkCreateImage: VkFormat for TILING_OPTIMAL image (" << string_VkFormat(pCreateInfo->format) 6793c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes << ") does not support requested Image usage type VK_IMAGE_USAGE_COLOR_ATTACHMENT"; 680315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 681315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_09e007b2, "IMAGE", "%s. %s", ss.str().c_str(), 682315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_09e007b2]); 6838dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski } 6843c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes if ((pCreateInfo->tiling == VK_IMAGE_TILING_LINEAR) && 6853c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes ((properties->linearTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) == 0)) { 6868dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski std::stringstream ss; 6873c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes ss << "vkCreateImage: VkFormat for TILING_LINEAR image (" << string_VkFormat(pCreateInfo->format) 6883c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes << ") does not support requested Image usage type VK_IMAGE_USAGE_COLOR_ATTACHMENT"; 689315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 690315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_09e007a8, "IMAGE", "%s. %s", ss.str().c_str(), 691315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_09e007a8]); 6928dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski } 6933c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes } 6948dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski 6953c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes // Validate that format supports usage as depth/stencil attachment 6963c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes if (pCreateInfo->usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { 6973c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes if ((pCreateInfo->tiling == VK_IMAGE_TILING_OPTIMAL) && 6983c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes ((properties->optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) == 0)) { 6993c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes std::stringstream ss; 7003c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes ss << "vkCreateImage: VkFormat for TILING_OPTIMAL image (" << string_VkFormat(pCreateInfo->format) 7013c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes << ") does not support requested Image usage type VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT"; 702315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 703315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_09e007b4, "IMAGE", "%s. %s", ss.str().c_str(), 704315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_09e007b4]); 7058dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski } 7063c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes if ((pCreateInfo->tiling == VK_IMAGE_TILING_LINEAR) && 7073c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes ((properties->linearTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) == 0)) { 7083c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes std::stringstream ss; 7093c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes ss << "vkCreateImage: VkFormat for TILING_LINEAR image (" << string_VkFormat(pCreateInfo->format) 7103c4d73267a033429a5b49318cdfd743432518761Jeremy Hayes << ") does not support requested Image usage type VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT"; 711315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 712315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_09e007aa, "IMAGE", "%s. %s", ss.str().c_str(), 713315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_09e007aa]); 7148dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski } 7158dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski } 7168dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski 717d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski const VkImageFormatProperties *ImageFormatProperties = GetImageFormatProperties( 718d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski device_data, pCreateInfo->format, pCreateInfo->imageType, pCreateInfo->tiling, pCreateInfo->usage, pCreateInfo->flags); 7198dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski 720d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski VkDeviceSize imageGranularity = GetPhysicalDeviceProperties(device_data)->limits.bufferImageGranularity; 7218dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski imageGranularity = imageGranularity == 1 ? 0 : imageGranularity; 72260f59be7ded9ccf2d57c36b2e0974cc2798cf844Tobin Ehlis // TODO : This is also covering 2918 & 2919. Break out into separate checks 723a9991b9f53d0be4fecc63bdbdf3de9950070a3a5Mark Lobodzinski if ((pCreateInfo->extent.width <= 0) || (pCreateInfo->extent.height <= 0) || (pCreateInfo->extent.depth <= 0)) { 7243251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 0, __LINE__, 725315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_09e007b8, "Image", 7263251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "CreateImage extent is 0 for at least one required dimension for image: " 7273251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Width = %d Height = %d Depth = %d. %s", 7283251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski pCreateInfo->extent.width, pCreateInfo->extent.height, pCreateInfo->extent.depth, 729315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_09e007b8]); 7308dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski } 7318dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski 732315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis // TODO: VALIDATION_ERROR_09e00770 VALIDATION_ERROR_09e00772 VALIDATION_ERROR_09e00776 VALIDATION_ERROR_09e0076e 7338dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski // All these extent-related VUs should be checked here 734d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski if ((pCreateInfo->extent.depth > ImageFormatProperties->maxExtent.depth) || 735d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski (pCreateInfo->extent.width > ImageFormatProperties->maxExtent.width) || 736d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski (pCreateInfo->extent.height > ImageFormatProperties->maxExtent.height)) { 7373251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 0, __LINE__, 7383251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image", 7393251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "CreateImage extents exceed allowable limits for format: " 7403251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Width = %d Height = %d Depth = %d: Limits for Width = %d Height = %d Depth = %d for format %s.", 7413251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski pCreateInfo->extent.width, pCreateInfo->extent.height, pCreateInfo->extent.depth, 7423251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski ImageFormatProperties->maxExtent.width, ImageFormatProperties->maxExtent.height, 7433251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski ImageFormatProperties->maxExtent.depth, string_VkFormat(pCreateInfo->format)); 7448dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski } 7458dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski 746cf2ce8673669ca1111e333bdea272c4dd57cb5c2Dave Houlton uint64_t totalSize = 747cf2ce8673669ca1111e333bdea272c4dd57cb5c2Dave Houlton ((uint64_t)pCreateInfo->extent.width * (uint64_t)pCreateInfo->extent.height * (uint64_t)pCreateInfo->extent.depth * 748cf2ce8673669ca1111e333bdea272c4dd57cb5c2Dave Houlton (uint64_t)pCreateInfo->arrayLayers * (uint64_t)pCreateInfo->samples * (uint64_t)FormatSize(pCreateInfo->format) + 749cf2ce8673669ca1111e333bdea272c4dd57cb5c2Dave Houlton (uint64_t)imageGranularity) & 750cf2ce8673669ca1111e333bdea272c4dd57cb5c2Dave Houlton ~(uint64_t)imageGranularity; 7518dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski 752d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski if (totalSize > ImageFormatProperties->maxResourceSize) { 7533251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 0, __LINE__, 7543251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image", 7553251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "CreateImage resource size exceeds allowable maximum " 7563251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Image resource size = 0x%" PRIxLEAST64 ", maximum resource size = 0x%" PRIxLEAST64 " ", 7573251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski totalSize, ImageFormatProperties->maxResourceSize); 7588dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski } 7598dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski 760315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis // TODO: VALIDATION_ERROR_09e0077e 761d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski if (pCreateInfo->mipLevels > ImageFormatProperties->maxMipLevels) { 7623251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 0, __LINE__, 7633251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image", 7643251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "CreateImage mipLevels=%d exceeds allowable maximum supported by format of %d", pCreateInfo->mipLevels, 7653251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski ImageFormatProperties->maxMipLevels); 7668dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski } 7678dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski 768d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski if (pCreateInfo->arrayLayers > ImageFormatProperties->maxArrayLayers) { 769315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= 770315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 0, __LINE__, 771315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_09e00780, "Image", 772315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis "CreateImage arrayLayers=%d exceeds allowable maximum supported by format of %d. %s", pCreateInfo->arrayLayers, 773315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis ImageFormatProperties->maxArrayLayers, validation_error_map[VALIDATION_ERROR_09e00780]); 7748dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski } 7758dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski 776d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski if ((pCreateInfo->samples & ImageFormatProperties->sampleCounts) == 0) { 7773251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 0, __LINE__, 778315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_09e0078e, "Image", "CreateImage samples %s is not supported by format 0x%.8X. %s", 7793251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski string_VkSampleCountFlagBits(pCreateInfo->samples), ImageFormatProperties->sampleCounts, 780315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_09e0078e]); 7818dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski } 7828dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski 7838dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski if (pCreateInfo->initialLayout != VK_IMAGE_LAYOUT_UNDEFINED && pCreateInfo->initialLayout != VK_IMAGE_LAYOUT_PREINITIALIZED) { 7843251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 0, __LINE__, 785315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_09e0b801, "Image", 7863251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkCreateImage parameter, pCreateInfo->initialLayout, must be VK_IMAGE_LAYOUT_UNDEFINED or " 7873251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "VK_IMAGE_LAYOUT_PREINITIALIZED. %s", 788315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_09e0b801]); 7898dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski } 7908dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski 79101363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski if ((pCreateInfo->flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT) && (!GetEnabledFeatures(device_data)->sparseBinding)) { 7923251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 793315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_09e00792, "DS", 7943251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkCreateImage(): the sparseBinding device feature is disabled: Images cannot be created with the " 7953251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "VK_IMAGE_CREATE_SPARSE_BINDING_BIT set. %s", 796315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_09e00792]); 79701363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski } 79801363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski 7997e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski if ((pCreateInfo->flags & VK_IMAGE_CREATE_SPARSE_ALIASED_BIT) && (!GetEnabledFeatures(device_data)->sparseResidencyAliased)) { 8003251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 8013251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski DRAWSTATE_INVALID_FEATURE, "DS", 8023251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkCreateImage(): the sparseResidencyAliased device feature is disabled: Images cannot be created with the " 8033251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "VK_IMAGE_CREATE_SPARSE_ALIASED_BIT set."); 8047e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski } 8057e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski 8063251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 8078dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski} 8088dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski 809e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisvoid PostCallRecordCreateImage(layer_data *device_data, const VkImageCreateInfo *pCreateInfo, VkImage *pImage) { 810c06c9b88f5f5bcc7033ba41d5547b048fa6015a4Mark Lobodzinski IMAGE_LAYOUT_NODE image_state; 811c06c9b88f5f5bcc7033ba41d5547b048fa6015a4Mark Lobodzinski image_state.layout = pCreateInfo->initialLayout; 812c06c9b88f5f5bcc7033ba41d5547b048fa6015a4Mark Lobodzinski image_state.format = pCreateInfo->format; 813920311b6aa5614a545cad59521770d0898a75d65Mark Lobodzinski GetImageMap(device_data)->insert(std::make_pair(*pImage, std::unique_ptr<IMAGE_STATE>(new IMAGE_STATE(*pImage, pCreateInfo)))); 814c06c9b88f5f5bcc7033ba41d5547b048fa6015a4Mark Lobodzinski ImageSubresourcePair subpair{*pImage, false, VkImageSubresource()}; 815920311b6aa5614a545cad59521770d0898a75d65Mark Lobodzinski (*core_validation::GetImageSubresourceMap(device_data))[*pImage].push_back(subpair); 816920311b6aa5614a545cad59521770d0898a75d65Mark Lobodzinski (*core_validation::GetImageLayoutMap(device_data))[subpair] = image_state; 817c06c9b88f5f5bcc7033ba41d5547b048fa6015a4Mark Lobodzinski} 8188c59133586421be878d393799b30044497f77727Mark Lobodzinski 819e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisbool PreCallValidateDestroyImage(layer_data *device_data, VkImage image, IMAGE_STATE **image_state, VK_OBJECT *obj_struct) { 8208c59133586421be878d393799b30044497f77727Mark Lobodzinski const CHECK_DISABLED *disabled = core_validation::GetDisables(device_data); 8219a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *image_state = core_validation::GetImageState(device_data, image); 8229b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus *obj_struct = {HandleToUint64(image), kVulkanObjectTypeImage}; 8238c59133586421be878d393799b30044497f77727Mark Lobodzinski if (disabled->destroy_image) return false; 8248c59133586421be878d393799b30044497f77727Mark Lobodzinski bool skip = false; 8258c59133586421be878d393799b30044497f77727Mark Lobodzinski if (*image_state) { 826315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= core_validation::ValidateObjectNotInUse(device_data, *image_state, *obj_struct, VALIDATION_ERROR_252007d0); 8278c59133586421be878d393799b30044497f77727Mark Lobodzinski } 8288c59133586421be878d393799b30044497f77727Mark Lobodzinski return skip; 8298c59133586421be878d393799b30044497f77727Mark Lobodzinski} 8308c59133586421be878d393799b30044497f77727Mark Lobodzinski 831e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisvoid PostCallRecordDestroyImage(layer_data *device_data, VkImage image, IMAGE_STATE *image_state, VK_OBJECT obj_struct) { 8328c59133586421be878d393799b30044497f77727Mark Lobodzinski core_validation::invalidateCommandBuffers(device_data, image_state->cb_bindings, obj_struct); 8338c59133586421be878d393799b30044497f77727Mark Lobodzinski // Clean up memory mapping, bindings and range references for image 8348c59133586421be878d393799b30044497f77727Mark Lobodzinski for (auto mem_binding : image_state->GetBoundMemory()) { 8359a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto mem_info = core_validation::GetMemObjInfo(device_data, mem_binding); 8368c59133586421be878d393799b30044497f77727Mark Lobodzinski if (mem_info) { 8378c59133586421be878d393799b30044497f77727Mark Lobodzinski core_validation::RemoveImageMemoryRange(obj_struct.handle, mem_info); 8388c59133586421be878d393799b30044497f77727Mark Lobodzinski } 8398c59133586421be878d393799b30044497f77727Mark Lobodzinski } 8407a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski core_validation::ClearMemoryObjectBindings(device_data, obj_struct.handle, kVulkanObjectTypeImage); 8418c59133586421be878d393799b30044497f77727Mark Lobodzinski // Remove image from imageMap 8428c59133586421be878d393799b30044497f77727Mark Lobodzinski core_validation::GetImageMap(device_data)->erase(image); 8438c59133586421be878d393799b30044497f77727Mark Lobodzinski std::unordered_map<VkImage, std::vector<ImageSubresourcePair>> *imageSubresourceMap = 8448c59133586421be878d393799b30044497f77727Mark Lobodzinski core_validation::GetImageSubresourceMap(device_data); 8458c59133586421be878d393799b30044497f77727Mark Lobodzinski 8468c59133586421be878d393799b30044497f77727Mark Lobodzinski const auto &sub_entry = imageSubresourceMap->find(image); 8478c59133586421be878d393799b30044497f77727Mark Lobodzinski if (sub_entry != imageSubresourceMap->end()) { 8488c59133586421be878d393799b30044497f77727Mark Lobodzinski for (const auto &pair : sub_entry->second) { 8498c59133586421be878d393799b30044497f77727Mark Lobodzinski core_validation::GetImageLayoutMap(device_data)->erase(pair); 8508c59133586421be878d393799b30044497f77727Mark Lobodzinski } 8518c59133586421be878d393799b30044497f77727Mark Lobodzinski imageSubresourceMap->erase(sub_entry); 8528c59133586421be878d393799b30044497f77727Mark Lobodzinski } 8538c59133586421be878d393799b30044497f77727Mark Lobodzinski} 854509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski 855e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisbool ValidateImageAttributes(layer_data *device_data, IMAGE_STATE *image_state, VkImageSubresourceRange range) { 856509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski bool skip = false; 857509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski const debug_report_data *report_data = core_validation::GetReportData(device_data); 858509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski 859509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski if (range.aspectMask != VK_IMAGE_ASPECT_COLOR_BIT) { 860509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski char const str[] = "vkCmdClearColorImage aspectMasks for all subresource ranges must be set to VK_IMAGE_ASPECT_COLOR_BIT"; 861509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 8629b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(image_state->image), __LINE__, DRAWSTATE_INVALID_IMAGE_ASPECT, "IMAGE", str); 863509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski } 864509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski 86516769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton if (FormatIsDepthOrStencil(image_state->createInfo.format)) { 866509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski char const str[] = "vkCmdClearColorImage called with depth/stencil image."; 867509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 868315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(image_state->image), __LINE__, VALIDATION_ERROR_1880000e, "IMAGE", "%s. %s", str, 869315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_1880000e]); 87016769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton } else if (FormatIsCompressed(image_state->createInfo.format)) { 871509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski char const str[] = "vkCmdClearColorImage called with compressed image."; 872509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 873315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(image_state->image), __LINE__, VALIDATION_ERROR_1880000e, "IMAGE", "%s. %s", str, 874315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_1880000e]); 875509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski } 876509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski 877509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski if (!(image_state->createInfo.usage & VK_IMAGE_USAGE_TRANSFER_DST_BIT)) { 878509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski char const str[] = "vkCmdClearColorImage called with image created without VK_IMAGE_USAGE_TRANSFER_DST_BIT."; 879509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 880315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(image_state->image), __LINE__, VALIDATION_ERROR_18800004, "IMAGE", "%s. %s", str, 881315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_18800004]); 882509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski } 883509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski return skip; 884509e427aa732fc714b9aa01a175ca5f57b2d7a07Mark Lobodzinski} 885623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski 88695b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinskiuint32_t ResolveRemainingLevels(const VkImageSubresourceRange *range, uint32_t mip_levels) { 88795b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski // Return correct number of mip levels taking into account VK_REMAINING_MIP_LEVELS 88895b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski uint32_t mip_level_count = range->levelCount; 88908c7aae3177092f8567e2b5a946457be61616e9aMark Lobodzinski if (range->levelCount == VK_REMAINING_MIP_LEVELS) { 89095b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski mip_level_count = mip_levels - range->baseMipLevel; 891623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski } 89295b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski return mip_level_count; 893623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski} 894623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski 89595b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinskiuint32_t ResolveRemainingLayers(const VkImageSubresourceRange *range, uint32_t layers) { 89695b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski // Return correct number of layers taking into account VK_REMAINING_ARRAY_LAYERS 89795b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski uint32_t array_layer_count = range->layerCount; 89895b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski if (range->layerCount == VK_REMAINING_ARRAY_LAYERS) { 89995b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski array_layer_count = layers - range->baseArrayLayer; 900623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski } 90195b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski return array_layer_count; 902623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski} 903623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski 904e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisbool VerifyClearImageLayout(layer_data *device_data, GLOBAL_CB_NODE *cb_node, IMAGE_STATE *image_state, 905623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski VkImageSubresourceRange range, VkImageLayout dest_image_layout, const char *func_name) { 906623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski bool skip = false; 907623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski const debug_report_data *report_data = core_validation::GetReportData(device_data); 908623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski 90995b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski uint32_t level_count = ResolveRemainingLevels(&range, image_state->createInfo.mipLevels); 91095b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski uint32_t layer_count = ResolveRemainingLayers(&range, image_state->createInfo.arrayLayers); 911623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski 912623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski if (dest_image_layout != VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) { 913623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski if (dest_image_layout == VK_IMAGE_LAYOUT_GENERAL) { 914623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski if (image_state->createInfo.tiling != VK_IMAGE_TILING_LINEAR) { 915623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski // LAYOUT_GENERAL is allowed, but may not be performance optimal, flag as perf warning. 916fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 9179b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(image_state->image), __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS", 918623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski "%s: Layout for cleared image should be TRANSFER_DST_OPTIMAL instead of GENERAL.", func_name); 919623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski } 9206084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski } else if (VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR == dest_image_layout) { 921d4eaca34eca7f4b4e34190c441a579347bb2016aMark Lobodzinski if (!GetDeviceExtensions(device_data)->vk_khr_shared_presentable_image) { 922480a11822ef9a45f577f13644759c0895a49db19Tobin Ehlis // TODO: Add unique error id when available. 9236084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 924480a11822ef9a45f577f13644759c0895a49db19Tobin Ehlis HandleToUint64(image_state->image), __LINE__, 0, "DS", 9256084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski "Must enable VK_KHR_shared_presentable_image extension before creating images with a layout type " 9266084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski "of VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR."); 9276084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski 9286084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski } else { 9296084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski if (image_state->shared_presentable) { 9306084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski skip |= log_msg( 9316084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 932480a11822ef9a45f577f13644759c0895a49db19Tobin Ehlis HandleToUint64(image_state->image), __LINE__, 0, "DS", 9336084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski "Layout for shared presentable cleared image is %s but can only be VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR.", 9346084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski string_VkImageLayout(dest_image_layout)); 9356084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski } 93687a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis } 937623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski } else { 938315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis UNIQUE_VALIDATION_ERROR_CODE error_code = VALIDATION_ERROR_1880000a; 939623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski if (strcmp(func_name, "vkCmdClearDepthStencilImage()") == 0) { 940315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis error_code = VALIDATION_ERROR_18a00018; 941623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski } else { 942623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski assert(strcmp(func_name, "vkCmdClearColorImage()") == 0); 943623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski } 944fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 9459b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(image_state->image), __LINE__, error_code, "DS", 946fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski "%s: Layout for cleared image is %s but can only be " 947fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski "TRANSFER_DST_OPTIMAL or GENERAL. %s", 948fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski func_name, string_VkImageLayout(dest_image_layout), validation_error_map[error_code]); 949623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski } 950623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski } 951623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski 95295b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski for (uint32_t level_index = 0; level_index < level_count; ++level_index) { 95395b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski uint32_t level = level_index + range.baseMipLevel; 95495b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski for (uint32_t layer_index = 0; layer_index < layer_count; ++layer_index) { 95595b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski uint32_t layer = layer_index + range.baseArrayLayer; 95695b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski VkImageSubresource sub = {range.aspectMask, level, layer}; 957623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski IMAGE_CMD_BUF_LAYOUT_NODE node; 95855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski if (FindCmdBufLayout(device_data, cb_node, image_state->image, sub, node)) { 959623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski if (node.layout != dest_image_layout) { 960315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis UNIQUE_VALIDATION_ERROR_CODE error_code = VALIDATION_ERROR_18800008; 961623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski if (strcmp(func_name, "vkCmdClearDepthStencilImage()") == 0) { 962315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis error_code = VALIDATION_ERROR_18a00016; 963623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski } else { 964623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski assert(strcmp(func_name, "vkCmdClearColorImage()") == 0); 965623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski } 966623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, 967623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski __LINE__, error_code, "DS", 968623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski "%s: Cannot clear an image whose layout is %s and " 969623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski "doesn't match the current layout %s. %s", 970623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski func_name, string_VkImageLayout(dest_image_layout), string_VkImageLayout(node.layout), 971623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski validation_error_map[error_code]); 972623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski } 973623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski } 974623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski } 975623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski } 976623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski 977623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski return skip; 978623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski} 979623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski 980e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisvoid RecordClearImageLayout(layer_data *device_data, GLOBAL_CB_NODE *cb_node, VkImage image, VkImageSubresourceRange range, 981e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlis VkImageLayout dest_image_layout) { 98295b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski VkImageCreateInfo *image_create_info = &(GetImageState(device_data, image)->createInfo); 98395b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski uint32_t level_count = ResolveRemainingLevels(&range, image_create_info->mipLevels); 98495b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski uint32_t layer_count = ResolveRemainingLayers(&range, image_create_info->arrayLayers); 98595b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski 98695b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski for (uint32_t level_index = 0; level_index < level_count; ++level_index) { 98795b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski uint32_t level = level_index + range.baseMipLevel; 98895b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski for (uint32_t layer_index = 0; layer_index < layer_count; ++layer_index) { 98995b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski uint32_t layer = layer_index + range.baseArrayLayer; 99095b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski VkImageSubresource sub = {range.aspectMask, level, layer}; 991623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski IMAGE_CMD_BUF_LAYOUT_NODE node; 99255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski if (!FindCmdBufLayout(device_data, cb_node, image, sub, node)) { 99355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski SetLayout(device_data, cb_node, image, sub, IMAGE_CMD_BUF_LAYOUT_NODE(dest_image_layout, dest_image_layout)); 994623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski } 995623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski } 996623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski } 997623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski} 998623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski 999e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisbool PreCallValidateCmdClearColorImage(layer_data *dev_data, VkCommandBuffer commandBuffer, VkImage image, 1000623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski VkImageLayout imageLayout, uint32_t rangeCount, const VkImageSubresourceRange *pRanges) { 1001623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski bool skip = false; 1002623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski // TODO : Verify memory is in VK_IMAGE_STATE_CLEAR state 10039a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, commandBuffer); 10049a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_state = GetImageState(dev_data, image); 1005623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski if (cb_node && image_state) { 1006315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateMemoryIsBoundToImage(dev_data, image_state, "vkCmdClearColorImage()", VALIDATION_ERROR_18800006); 1007baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip |= ValidateCmdQueueFlags(dev_data, cb_node, "vkCmdClearColorImage()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, 1008315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_18802415); 1009623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski skip |= ValidateCmd(dev_data, cb_node, CMD_CLEARCOLORIMAGE, "vkCmdClearColorImage()"); 1010315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= insideRenderPass(dev_data, cb_node, "vkCmdClearColorImage()", VALIDATION_ERROR_18800017); 1011623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski for (uint32_t i = 0; i < rangeCount; ++i) { 101223c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus std::string param_name = "pRanges[" + std::to_string(i) + "]"; 1013dab32891b91206a5bef7a3929b781e44fc1b7268Petr Kraus skip |= 1014dab32891b91206a5bef7a3929b781e44fc1b7268Petr Kraus ValidateImageSubresourceRange(dev_data, image_state, false, pRanges[i], "vkCmdClearColorImage", param_name.c_str()); 1015623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski skip |= ValidateImageAttributes(dev_data, image_state, pRanges[i]); 101608c7aae3177092f8567e2b5a946457be61616e9aMark Lobodzinski skip |= VerifyClearImageLayout(dev_data, cb_node, image_state, pRanges[i], imageLayout, "vkCmdClearColorImage()"); 1017623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski } 1018623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski } 1019623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski return skip; 1020623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski} 1021623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski 1022623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski// This state recording routine is shared between ClearColorImage and ClearDepthStencilImage 1023e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisvoid PreCallRecordCmdClearImage(layer_data *dev_data, VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, 1024e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlis uint32_t rangeCount, const VkImageSubresourceRange *pRanges, CMD_TYPE cmd_type) { 10259a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, commandBuffer); 10269a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_state = GetImageState(dev_data, image); 1027623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski if (cb_node && image_state) { 1028623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski AddCommandBufferBindingImage(dev_data, cb_node, image_state); 1029623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski std::function<bool()> function = [=]() { 1030623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski SetImageMemoryValid(dev_data, image_state, true); 1031623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski return false; 1032623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski }; 1033623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski cb_node->validate_functions.push_back(function); 10349a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis core_validation::UpdateCmdBufferLastCmd(cb_node, cmd_type); 1035623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski for (uint32_t i = 0; i < rangeCount; ++i) { 1036623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski RecordClearImageLayout(dev_data, cb_node, image, pRanges[i], imageLayout); 1037623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski } 1038623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski } 1039623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski} 1040623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski 1041e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisbool PreCallValidateCmdClearDepthStencilImage(layer_data *device_data, VkCommandBuffer commandBuffer, VkImage image, 1042e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlis VkImageLayout imageLayout, uint32_t rangeCount, 1043623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski const VkImageSubresourceRange *pRanges) { 1044623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski bool skip = false; 10457244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski const debug_report_data *report_data = core_validation::GetReportData(device_data); 10467244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski 1047623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski // TODO : Verify memory is in VK_IMAGE_STATE_CLEAR state 10489a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(device_data, commandBuffer); 10499a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_state = GetImageState(device_data, image); 1050623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski if (cb_node && image_state) { 1051315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateMemoryIsBoundToImage(device_data, image_state, "vkCmdClearDepthStencilImage()", VALIDATION_ERROR_18a00014); 1052baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip |= ValidateCmdQueueFlags(device_data, cb_node, "vkCmdClearDepthStencilImage()", VK_QUEUE_GRAPHICS_BIT, 1053315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_18a02415); 10547244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski skip |= ValidateCmd(device_data, cb_node, CMD_CLEARDEPTHSTENCILIMAGE, "vkCmdClearDepthStencilImage()"); 1055315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= insideRenderPass(device_data, cb_node, "vkCmdClearDepthStencilImage()", VALIDATION_ERROR_18a00017); 1056623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski for (uint32_t i = 0; i < rangeCount; ++i) { 105723c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus std::string param_name = "pRanges[" + std::to_string(i) + "]"; 1058dab32891b91206a5bef7a3929b781e44fc1b7268Petr Kraus skip |= ValidateImageSubresourceRange(device_data, image_state, false, pRanges[i], "vkCmdClearDepthStencilImage", 105923c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus param_name.c_str()); 106008c7aae3177092f8567e2b5a946457be61616e9aMark Lobodzinski skip |= 106108c7aae3177092f8567e2b5a946457be61616e9aMark Lobodzinski VerifyClearImageLayout(device_data, cb_node, image_state, pRanges[i], imageLayout, "vkCmdClearDepthStencilImage()"); 10627244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski // Image aspect must be depth or stencil or both 10637244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski if (((pRanges[i].aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) != VK_IMAGE_ASPECT_DEPTH_BIT) && 10647244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski ((pRanges[i].aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) != VK_IMAGE_ASPECT_STENCIL_BIT)) { 10657244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski char const str[] = 10667244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski "vkCmdClearDepthStencilImage aspectMasks for all subresource ranges must be " 10677244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski "set to VK_IMAGE_ASPECT_DEPTH_BIT and/or VK_IMAGE_ASPECT_STENCIL_BIT"; 10687244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 10699b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(commandBuffer), __LINE__, DRAWSTATE_INVALID_IMAGE_ASPECT, "IMAGE", str); 10707244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski } 10717244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski } 107216769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton if (image_state && !FormatIsDepthOrStencil(image_state->createInfo.format)) { 10737244435437260842ba43b67bb7d008e161736c31Mark Lobodzinski char const str[] = "vkCmdClearDepthStencilImage called without a depth/stencil image."; 1074315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 1075315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(image), __LINE__, VALIDATION_ERROR_18a0001c, "IMAGE", "%s. %s", str, 1076315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_18a0001c]); 1077623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski } 1078623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski } 1079623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski return skip; 1080623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski} 1081ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski 1082ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski// Returns true if [x, xoffset] and [y, yoffset] overlap 1083ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinskistatic bool RangesIntersect(int32_t start, uint32_t start_offset, int32_t end, uint32_t end_offset) { 1084ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski bool result = false; 1085ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski uint32_t intersection_min = std::max(static_cast<uint32_t>(start), static_cast<uint32_t>(end)); 1086ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski uint32_t intersection_max = std::min(static_cast<uint32_t>(start) + start_offset, static_cast<uint32_t>(end) + end_offset); 1087ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski 1088ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski if (intersection_max > intersection_min) { 1089ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski result = true; 1090ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski } 1091ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski return result; 1092ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski} 1093ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski 1094ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski// Returns true if two VkImageCopy structures overlap 1095ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinskistatic bool RegionIntersects(const VkImageCopy *src, const VkImageCopy *dst, VkImageType type) { 1096ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski bool result = false; 1097ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski if ((src->srcSubresource.mipLevel == dst->dstSubresource.mipLevel) && 1098ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski (RangesIntersect(src->srcSubresource.baseArrayLayer, src->srcSubresource.layerCount, dst->dstSubresource.baseArrayLayer, 1099ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski dst->dstSubresource.layerCount))) { 1100ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski result = true; 1101ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski switch (type) { 1102ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski case VK_IMAGE_TYPE_3D: 1103ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski result &= RangesIntersect(src->srcOffset.z, src->extent.depth, dst->dstOffset.z, dst->extent.depth); 1104ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski // Intentionally fall through to 2D case 1105ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski case VK_IMAGE_TYPE_2D: 1106ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski result &= RangesIntersect(src->srcOffset.y, src->extent.height, dst->dstOffset.y, dst->extent.height); 1107ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski // Intentionally fall through to 1D case 1108ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski case VK_IMAGE_TYPE_1D: 1109ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski result &= RangesIntersect(src->srcOffset.x, src->extent.width, dst->dstOffset.x, dst->extent.width); 1110ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski break; 1111ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski default: 1112ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski // Unrecognized or new IMAGE_TYPE enums will be caught in parameter_validation 1113ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski assert(false); 1114ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski } 1115ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski } 1116ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski return result; 1117ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski} 1118ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski 11193fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton// Returns non-zero if offset and extent exceed image extents 11203fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houltonstatic const uint32_t x_bit = 1; 11213fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houltonstatic const uint32_t y_bit = 2; 11223fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houltonstatic const uint32_t z_bit = 4; 1123cf2ce8673669ca1111e333bdea272c4dd57cb5c2Dave Houltonstatic uint32_t ExceedsBounds(const VkOffset3D *offset, const VkExtent3D *extent, const VkExtent3D *image_extent) { 11243fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton uint32_t result = 0; 1125ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski // Extents/depths cannot be negative but checks left in for clarity 11265971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton if ((offset->z + extent->depth > image_extent->depth) || (offset->z < 0) || 11275971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton ((offset->z + static_cast<int32_t>(extent->depth)) < 0)) { 11283fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton result |= z_bit; 11295971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton } 11305971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton if ((offset->y + extent->height > image_extent->height) || (offset->y < 0) || 11315971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton ((offset->y + static_cast<int32_t>(extent->height)) < 0)) { 11323fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton result |= y_bit; 11335971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton } 11345971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton if ((offset->x + extent->width > image_extent->width) || (offset->x < 0) || 11355971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton ((offset->x + static_cast<int32_t>(extent->width)) < 0)) { 11363fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton result |= x_bit; 1137ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski } 1138ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski return result; 1139ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski} 1140ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski 11416a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski// Test if two VkExtent3D structs are equivalent 11426a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinskistatic inline bool IsExtentEqual(const VkExtent3D *extent, const VkExtent3D *other_extent) { 11436a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski bool result = true; 11446a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski if ((extent->width != other_extent->width) || (extent->height != other_extent->height) || 11456a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski (extent->depth != other_extent->depth)) { 11466a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski result = false; 11476a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski } 11486a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski return result; 11496a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski} 11506a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski 115178ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton// Returns the effective extent of an image subresource, adjusted for mip level and array depth. 11526a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinskistatic inline VkExtent3D GetImageSubresourceExtent(const IMAGE_STATE *img, const VkImageSubresourceLayers *subresource) { 11536a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski const uint32_t mip = subresource->mipLevel; 11543fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton 11553fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton // Return zero extent if mip level doesn't exist 1156cf2ce8673669ca1111e333bdea272c4dd57cb5c2Dave Houlton if (mip >= img->createInfo.mipLevels) { 1157cf2ce8673669ca1111e333bdea272c4dd57cb5c2Dave Houlton return VkExtent3D{0, 0, 0}; 11583fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton } 1159cf2ce8673669ca1111e333bdea272c4dd57cb5c2Dave Houlton 11605971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton // Don't allow mip adjustment to create 0 dim, but pass along a 0 if that's what subresource specified 11613fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton VkExtent3D extent = img->createInfo.extent; 11625971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton extent.width = (0 == extent.width ? 0 : std::max(1U, extent.width >> mip)); 11635971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton extent.height = (0 == extent.height ? 0 : std::max(1U, extent.height >> mip)); 11645971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton extent.depth = (0 == extent.depth ? 0 : std::max(1U, extent.depth >> mip)); 11653fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton 116678ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton // Image arrays have an effective z extent that isn't diminished by mip level 116778ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton if (VK_IMAGE_TYPE_3D != img->createInfo.imageType) { 11683fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton extent.depth = img->createInfo.arrayLayers; 11693fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton } 11703fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton 11716a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski return extent; 11726a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski} 11736a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski 11746a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski// Test if the extent argument has all dimensions set to 0. 11755971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houltonstatic inline bool IsExtentAllZeroes(const VkExtent3D *extent) { 11766a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski return ((extent->width == 0) && (extent->height == 0) && (extent->depth == 0)); 11776a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski} 11786a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski 11795971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton// Test if the extent argument has any dimensions set to 0. 11805971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houltonstatic inline bool IsExtentSizeZero(const VkExtent3D *extent) { 11815971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton return ((extent->width == 0) || (extent->height == 0) || (extent->depth == 0)); 11825971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton} 11835971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton 11846a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski// Returns the image transfer granularity for a specific image scaled by compressed block size if necessary. 11856a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinskistatic inline VkExtent3D GetScaledItg(layer_data *device_data, const GLOBAL_CB_NODE *cb_node, const IMAGE_STATE *img) { 11866a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski // Default to (0, 0, 0) granularity in case we can't find the real granularity for the physical device. 11876a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski VkExtent3D granularity = {0, 0, 0}; 11886a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski auto pPool = GetCommandPoolNode(device_data, cb_node->createInfo.commandPool); 11896a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski if (pPool) { 11906a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski granularity = 11916a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski GetPhysDevProperties(device_data)->queue_family_properties[pPool->queueFamilyIndex].minImageTransferGranularity; 119216769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton if (FormatIsCompressed(img->createInfo.format)) { 119316769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton auto block_size = FormatCompressedTexelBlockExtent(img->createInfo.format); 11946a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski granularity.width *= block_size.width; 11956a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski granularity.height *= block_size.height; 11966a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski } 11976a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski } 11986a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski return granularity; 11996a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski} 12006a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski 12016a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski// Test elements of a VkExtent3D structure against alignment constraints contained in another VkExtent3D structure 12026a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinskistatic inline bool IsExtentAligned(const VkExtent3D *extent, const VkExtent3D *granularity) { 12036a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski bool valid = true; 120416769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton if ((SafeModulo(extent->depth, granularity->depth) != 0) || (SafeModulo(extent->width, granularity->width) != 0) || 120516769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton (SafeModulo(extent->height, granularity->height) != 0)) { 12066a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski valid = false; 12076a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski } 12086a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski return valid; 12096a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski} 12106a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski 12116a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski// Check elements of a VkOffset3D structure against a queue family's Image Transfer Granularity values 12126a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinskistatic inline bool CheckItgOffset(layer_data *device_data, const GLOBAL_CB_NODE *cb_node, const VkOffset3D *offset, 12136a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski const VkExtent3D *granularity, const uint32_t i, const char *function, const char *member) { 12146a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski const debug_report_data *report_data = core_validation::GetReportData(device_data); 12156a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski bool skip = false; 12166a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski VkExtent3D offset_extent = {}; 12176a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski offset_extent.width = static_cast<uint32_t>(abs(offset->x)); 12186a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski offset_extent.height = static_cast<uint32_t>(abs(offset->y)); 12196a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski offset_extent.depth = static_cast<uint32_t>(abs(offset->z)); 12205971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton if (IsExtentAllZeroes(granularity)) { 12216a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski // If the queue family image transfer granularity is (0, 0, 0), then the offset must always be (0, 0, 0) 12225971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton if (IsExtentAllZeroes(&offset_extent) == false) { 12239b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 12249b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(cb_node->commandBuffer), __LINE__, DRAWSTATE_IMAGE_TRANSFER_GRANULARITY, "DS", 12259b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "%s: pRegion[%d].%s (x=%d, y=%d, z=%d) must be (x=0, y=0, z=0) " 12269b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "when the command buffer's queue family image transfer granularity is (w=0, h=0, d=0).", 12279b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus function, i, member, offset->x, offset->y, offset->z); 12286a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski } 12296a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski } else { 12306a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski // If the queue family image transfer granularity is not (0, 0, 0), then the offset dimensions must always be even 12316a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski // integer multiples of the image transfer granularity. 12326a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski if (IsExtentAligned(&offset_extent, granularity) == false) { 12339b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 12349b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(cb_node->commandBuffer), __LINE__, DRAWSTATE_IMAGE_TRANSFER_GRANULARITY, "DS", 12359b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "%s: pRegion[%d].%s (x=%d, y=%d, z=%d) dimensions must be even integer " 12369b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "multiples of this command buffer's queue family image transfer granularity (w=%d, h=%d, d=%d).", 12379b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus function, i, member, offset->x, offset->y, offset->z, granularity->width, granularity->height, 12389b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus granularity->depth); 12396a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski } 12406a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski } 12416a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski return skip; 12426a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski} 12436a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski 12446a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski// Check elements of a VkExtent3D structure against a queue family's Image Transfer Granularity values 12456a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinskistatic inline bool CheckItgExtent(layer_data *device_data, const GLOBAL_CB_NODE *cb_node, const VkExtent3D *extent, 12466a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski const VkOffset3D *offset, const VkExtent3D *granularity, const VkExtent3D *subresource_extent, 12476a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski const uint32_t i, const char *function, const char *member) { 12486a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski const debug_report_data *report_data = core_validation::GetReportData(device_data); 12496a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski bool skip = false; 12505971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton if (IsExtentAllZeroes(granularity)) { 12516a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski // If the queue family image transfer granularity is (0, 0, 0), then the extent must always match the image 12526a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski // subresource extent. 12536a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski if (IsExtentEqual(extent, subresource_extent) == false) { 12549b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 12559b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(cb_node->commandBuffer), __LINE__, DRAWSTATE_IMAGE_TRANSFER_GRANULARITY, "DS", 12569b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "%s: pRegion[%d].%s (w=%d, h=%d, d=%d) must match the image subresource extents (w=%d, h=%d, d=%d) " 12579b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "when the command buffer's queue family image transfer granularity is (w=0, h=0, d=0).", 12589b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus function, i, member, extent->width, extent->height, extent->depth, subresource_extent->width, 12599b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus subresource_extent->height, subresource_extent->depth); 12606a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski } 12616a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski } else { 12626a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski // If the queue family image transfer granularity is not (0, 0, 0), then the extent dimensions must always be even 12636a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski // integer multiples of the image transfer granularity or the offset + extent dimensions must always match the image 12646a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski // subresource extent dimensions. 12656a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski VkExtent3D offset_extent_sum = {}; 12666a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski offset_extent_sum.width = static_cast<uint32_t>(abs(offset->x)) + extent->width; 12676a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski offset_extent_sum.height = static_cast<uint32_t>(abs(offset->y)) + extent->height; 12686a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski offset_extent_sum.depth = static_cast<uint32_t>(abs(offset->z)) + extent->depth; 126978ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton 127078ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton bool x_ok = 127178ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton ((0 == SafeModulo(extent->width, granularity->width)) || (subresource_extent->width == offset_extent_sum.width)); 127278ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton bool y_ok = 127378ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton ((0 == SafeModulo(extent->height, granularity->height)) || (subresource_extent->height == offset_extent_sum.height)); 127478ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton bool z_ok = 127578ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton ((0 == SafeModulo(extent->depth, granularity->depth)) || (subresource_extent->depth == offset_extent_sum.depth)); 127678ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton 127778ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton if (!(x_ok && y_ok && z_ok)) { 12786a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski skip |= 1279fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 12809b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(cb_node->commandBuffer), __LINE__, DRAWSTATE_IMAGE_TRANSFER_GRANULARITY, "DS", 12816a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski "%s: pRegion[%d].%s (w=%d, h=%d, d=%d) dimensions must be even integer multiples of this command buffer's " 12826a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski "queue family image transfer granularity (w=%d, h=%d, d=%d) or offset (x=%d, y=%d, z=%d) + " 12836a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski "extent (w=%d, h=%d, d=%d) must match the image subresource extents (w=%d, h=%d, d=%d).", 12846a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski function, i, member, extent->width, extent->height, extent->depth, granularity->width, granularity->height, 12856a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski granularity->depth, offset->x, offset->y, offset->z, extent->width, extent->height, extent->depth, 12866a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski subresource_extent->width, subresource_extent->height, subresource_extent->depth); 12876a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski } 12886a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski } 12896a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski return skip; 12906a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski} 12916a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski 12926a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski// Check a uint32_t width or stride value against a queue family's Image Transfer Granularity width value 12936a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinskistatic inline bool CheckItgInt(layer_data *device_data, const GLOBAL_CB_NODE *cb_node, const uint32_t value, 12946a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski const uint32_t granularity, const uint32_t i, const char *function, const char *member) { 12956a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski const debug_report_data *report_data = core_validation::GetReportData(device_data); 12966a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski 12976a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski bool skip = false; 129816769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton if (SafeModulo(value, granularity) != 0) { 1299fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 13009b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(cb_node->commandBuffer), __LINE__, DRAWSTATE_IMAGE_TRANSFER_GRANULARITY, "DS", 13016a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski "%s: pRegion[%d].%s (%d) must be an even integer multiple of this command buffer's queue family image " 13026a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski "transfer granularity width (%d).", 13036a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski function, i, member, value, granularity); 13046a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski } 13056a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski return skip; 13066a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski} 13076a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski 13086a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski// Check a VkDeviceSize value against a queue family's Image Transfer Granularity width value 13096a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinskistatic inline bool CheckItgSize(layer_data *device_data, const GLOBAL_CB_NODE *cb_node, const VkDeviceSize value, 13106a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski const uint32_t granularity, const uint32_t i, const char *function, const char *member) { 13116a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski const debug_report_data *report_data = core_validation::GetReportData(device_data); 13126a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski bool skip = false; 131316769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton if (SafeModulo(value, granularity) != 0) { 1314fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 13159b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(cb_node->commandBuffer), __LINE__, DRAWSTATE_IMAGE_TRANSFER_GRANULARITY, "DS", 13166a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski "%s: pRegion[%d].%s (%" PRIdLEAST64 13176a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski ") must be an even integer multiple of this command buffer's queue family image transfer " 13186a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski "granularity width (%d).", 13196a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski function, i, member, value, granularity); 13206a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski } 13216a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski return skip; 13226a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski} 13236a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski 13246a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski// Check valid usage Image Tranfer Granularity requirements for elements of a VkBufferImageCopy structure 13256a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinskibool ValidateCopyBufferImageTransferGranularityRequirements(layer_data *device_data, const GLOBAL_CB_NODE *cb_node, 13266a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski const IMAGE_STATE *img, const VkBufferImageCopy *region, 13276a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski const uint32_t i, const char *function) { 13286a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski bool skip = false; 132916769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton if (FormatIsCompressed(img->createInfo.format) == true) { 13306a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski // TODO: Add granularity checking for compressed formats 13316a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski 13326a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski // bufferRowLength must be a multiple of the compressed texel block width 13336a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski // bufferImageHeight must be a multiple of the compressed texel block height 13346a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski // all members of imageOffset must be a multiple of the corresponding dimensions of the compressed texel block 13356a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski // bufferOffset must be a multiple of the compressed texel block size in bytes 13366a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski // imageExtent.width must be a multiple of the compressed texel block width or (imageExtent.width + imageOffset.x) 13376a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski // must equal the image subresource width 13386a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski // imageExtent.height must be a multiple of the compressed texel block height or (imageExtent.height + imageOffset.y) 13396a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski // must equal the image subresource height 13406a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski // imageExtent.depth must be a multiple of the compressed texel block depth or (imageExtent.depth + imageOffset.z) 13416a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski // must equal the image subresource depth 13426a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski } else { 13436a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski VkExtent3D granularity = GetScaledItg(device_data, cb_node, img); 13446a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski skip |= CheckItgSize(device_data, cb_node, region->bufferOffset, granularity.width, i, function, "bufferOffset"); 13456a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski skip |= CheckItgInt(device_data, cb_node, region->bufferRowLength, granularity.width, i, function, "bufferRowLength"); 13466a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski skip |= CheckItgInt(device_data, cb_node, region->bufferImageHeight, granularity.width, i, function, "bufferImageHeight"); 13476a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski skip |= CheckItgOffset(device_data, cb_node, ®ion->imageOffset, &granularity, i, function, "imageOffset"); 13486a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski VkExtent3D subresource_extent = GetImageSubresourceExtent(img, ®ion->imageSubresource); 13496a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski skip |= CheckItgExtent(device_data, cb_node, ®ion->imageExtent, ®ion->imageOffset, &granularity, &subresource_extent, 13506a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski i, function, "imageExtent"); 13516a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski } 13526a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski return skip; 13536a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski} 13546a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski 13556a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski// Check valid usage Image Tranfer Granularity requirements for elements of a VkImageCopy structure 13566a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinskibool ValidateCopyImageTransferGranularityRequirements(layer_data *device_data, const GLOBAL_CB_NODE *cb_node, 135778ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton const IMAGE_STATE *src_img, const IMAGE_STATE *dst_img, 135878ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton const VkImageCopy *region, const uint32_t i, const char *function) { 13596a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski bool skip = false; 136078ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton VkExtent3D granularity = GetScaledItg(device_data, cb_node, src_img); 13616a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski skip |= CheckItgOffset(device_data, cb_node, ®ion->srcOffset, &granularity, i, function, "srcOffset"); 136278ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton VkExtent3D subresource_extent = GetImageSubresourceExtent(src_img, ®ion->srcSubresource); 136378ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton skip |= CheckItgExtent(device_data, cb_node, ®ion->extent, ®ion->srcOffset, &granularity, &subresource_extent, i, 136478ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton function, "extent"); 136578ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton 136678ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton granularity = GetScaledItg(device_data, cb_node, dst_img); 13676a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski skip |= CheckItgOffset(device_data, cb_node, ®ion->dstOffset, &granularity, i, function, "dstOffset"); 136878ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton subresource_extent = GetImageSubresourceExtent(dst_img, ®ion->dstSubresource); 13696a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski skip |= CheckItgExtent(device_data, cb_node, ®ion->extent, ®ion->dstOffset, &granularity, &subresource_extent, i, 13706a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski function, "extent"); 13716a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski return skip; 13726a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski} 13736a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski 137478ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton// Validate contents of a VkImageCopy struct 137578ab91073f6d67b85f667f7f409390a93c2239e7Dave Houltonbool ValidateImageCopyData(const layer_data *device_data, const debug_report_data *report_data, const uint32_t regionCount, 137678ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton const VkImageCopy *ic_regions, const IMAGE_STATE *src_state, const IMAGE_STATE *dst_state) { 137778ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton bool skip = false; 137878ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton 137978ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton for (uint32_t i = 0; i < regionCount; i++) { 138078ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton VkImageCopy image_copy = ic_regions[i]; 138178ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton bool slice_override = false; 138278ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton uint32_t depth_slices = 0; 138378ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton 138478ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton // Special case for copying between a 1D/2D array and a 3D image 138578ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton // TBD: This seems like the only way to reconcile 3 mutually-exclusive VU checks for 2D/3D copies. Heads up. 138678ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton if ((VK_IMAGE_TYPE_3D == src_state->createInfo.imageType) && (VK_IMAGE_TYPE_3D != dst_state->createInfo.imageType)) { 138778ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton depth_slices = image_copy.dstSubresource.layerCount; // Slice count from 2D subresource 138878ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton slice_override = (depth_slices != 1); 138978ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton } else if ((VK_IMAGE_TYPE_3D == dst_state->createInfo.imageType) && (VK_IMAGE_TYPE_3D != src_state->createInfo.imageType)) { 139078ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton depth_slices = image_copy.srcSubresource.layerCount; // Slice count from 2D subresource 139178ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton slice_override = (depth_slices != 1); 139278ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton } 139378ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton 139478ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton // Do all checks on source image 139578ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton // 139678ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton if (src_state->createInfo.imageType == VK_IMAGE_TYPE_1D) { 139778ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton if ((0 != image_copy.srcOffset.y) || (1 != image_copy.extent.height)) { 1398315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= 1399315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 1400315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis reinterpret_cast<const uint64_t &>(src_state->image), __LINE__, VALIDATION_ERROR_09c00124, "IMAGE", 1401315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis "vkCmdCopyImage(): pRegion[%d] srcOffset.y is %d and extent.height is %d. For 1D images these must " 1402315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis "be 0 and 1, respectively. %s", 1403315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis i, image_copy.srcOffset.y, image_copy.extent.height, validation_error_map[VALIDATION_ERROR_09c00124]); 140478ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton } 140578ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton } 140678ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton 140778ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton if ((src_state->createInfo.imageType == VK_IMAGE_TYPE_1D) || (src_state->createInfo.imageType == VK_IMAGE_TYPE_2D)) { 140878ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton if ((0 != image_copy.srcOffset.z) || (1 != image_copy.extent.depth)) { 1409315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= 1410315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 1411315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis reinterpret_cast<const uint64_t &>(src_state->image), __LINE__, VALIDATION_ERROR_09c00128, "IMAGE", 1412315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis "vkCmdCopyImage(): pRegion[%d] srcOffset.z is %d and extent.depth is %d. For 1D and 2D images " 1413315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis "these must be 0 and 1, respectively. %s", 1414315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis i, image_copy.srcOffset.z, image_copy.extent.depth, validation_error_map[VALIDATION_ERROR_09c00128]); 141578ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton } 141678ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton } 141778ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton 141878ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton // VU01199 changed with mnt1 1419d4eaca34eca7f4b4e34190c441a579347bb2016aMark Lobodzinski if (GetDeviceExtensions(device_data)->vk_khr_maintenance1) { 142078ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton if (src_state->createInfo.imageType == VK_IMAGE_TYPE_3D) { 142178ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton if ((0 != image_copy.srcSubresource.baseArrayLayer) || (1 != image_copy.srcSubresource.layerCount)) { 142278ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton skip |= 142378ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 1424315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis reinterpret_cast<const uint64_t &>(src_state->image), __LINE__, VALIDATION_ERROR_09c0011a, "IMAGE", 142578ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton "vkCmdCopyImage(): pRegion[%d] srcSubresource.baseArrayLayer is %d and srcSubresource.layerCount " 142678ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton "is %d. For VK_IMAGE_TYPE_3D images these must be 0 and 1, respectively. %s", 142778ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton i, image_copy.srcSubresource.baseArrayLayer, image_copy.srcSubresource.layerCount, 1428315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_09c0011a]); 142978ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton } 143078ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton } 143178ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton } else { // Pre maint 1 143278ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton if (src_state->createInfo.imageType == VK_IMAGE_TYPE_3D || dst_state->createInfo.imageType == VK_IMAGE_TYPE_3D) { 143378ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton if ((0 != image_copy.srcSubresource.baseArrayLayer) || (1 != image_copy.srcSubresource.layerCount)) { 1434315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= 1435315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 1436315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis reinterpret_cast<const uint64_t &>(src_state->image), __LINE__, VALIDATION_ERROR_09c0011a, "IMAGE", 1437315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis "vkCmdCopyImage(): pRegion[%d] srcSubresource.baseArrayLayer is %d and " 1438315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis "srcSubresource.layerCount is %d. For copies with either source or dest of type " 1439315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis "VK_IMAGE_TYPE_3D, these must be 0 and 1, respectively. %s", 1440315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis i, image_copy.srcSubresource.baseArrayLayer, image_copy.srcSubresource.layerCount, 1441315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_09c0011a]); 144278ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton } 144378ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton } 144478ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton } 144578ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton 144678ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton // TODO: this VU is redundant with VU01224. Gitlab issue 812 submitted to get it removed from the spec. 144778ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton if ((image_copy.srcSubresource.baseArrayLayer >= src_state->createInfo.arrayLayers) || 144878ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton (image_copy.srcSubresource.baseArrayLayer + image_copy.srcSubresource.layerCount > src_state->createInfo.arrayLayers)) { 144978ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 1450315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis reinterpret_cast<const uint64_t &>(src_state->image), __LINE__, VALIDATION_ERROR_09c0012a, "IMAGE", 145178ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton "vkCmdCopyImage(): pRegion[%d] srcSubresource.baseArrayLayer (%d) must be less than the source image's " 145278ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton "arrayLayers (%d), and the sum of baseArrayLayer and srcSubresource.layerCount (%d) must be less than " 145378ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton "or equal to the source image's arrayLayers. %s", 145478ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton i, image_copy.srcSubresource.baseArrayLayer, src_state->createInfo.arrayLayers, 1455315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis image_copy.srcSubresource.layerCount, validation_error_map[VALIDATION_ERROR_09c0012a]); 145678ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton } 145778ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton 145878ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton // Checks that apply only to compressed images 145978ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton if (FormatIsCompressed(src_state->createInfo.format)) { 146078ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton VkExtent3D block_size = FormatCompressedTexelBlockExtent(src_state->createInfo.format); 146178ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton 146278ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton // image offsets must be multiples of block dimensions 146378ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton if ((SafeModulo(image_copy.srcOffset.x, block_size.width) != 0) || 146478ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton (SafeModulo(image_copy.srcOffset.y, block_size.height) != 0) || 146578ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton (SafeModulo(image_copy.srcOffset.z, block_size.depth) != 0)) { 146678ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 1467315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis reinterpret_cast<const uint64_t &>(src_state->image), __LINE__, VALIDATION_ERROR_09c0013a, "IMAGE", 146878ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton "vkCmdCopyImage(): pRegion[%d] srcOffset (%d, %d) must be multiples of the compressed image's " 146978ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton "texel width & height (%d, %d). %s.", 147078ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton i, image_copy.srcOffset.x, image_copy.srcOffset.y, block_size.width, block_size.height, 1471315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_09c0013a]); 147278ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton } 147378ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton 147478ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton // extent width must be a multiple of block width, or extent+offset width must equal subresource width 147578ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton VkExtent3D mip_extent = GetImageSubresourceExtent(src_state, &(image_copy.srcSubresource)); 147678ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton if ((SafeModulo(image_copy.extent.width, block_size.width) != 0) && 147778ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton (image_copy.extent.width + image_copy.srcOffset.x != mip_extent.width)) { 147878ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton skip |= 147978ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 1480315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis reinterpret_cast<const uint64_t &>(src_state->image), __LINE__, VALIDATION_ERROR_09c0013c, "IMAGE", 148178ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton "vkCmdCopyImage(): pRegion[%d] extent width (%d) must be a multiple of the compressed texture block " 148278ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton "width (%d), or when added to srcOffset.x (%d) must equal the image subresource width (%d). %s.", 148378ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton i, image_copy.extent.width, block_size.width, image_copy.srcOffset.x, mip_extent.width, 1484315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_09c0013c]); 148578ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton } 148678ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton 148778ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton // extent height must be a multiple of block height, or extent+offset height must equal subresource height 148878ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton if ((SafeModulo(image_copy.extent.height, block_size.height) != 0) && 148978ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton (image_copy.extent.height + image_copy.srcOffset.y != mip_extent.height)) { 149078ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton skip |= 149178ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 1492315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis reinterpret_cast<const uint64_t &>(src_state->image), __LINE__, VALIDATION_ERROR_09c0013e, "IMAGE", 149378ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton "vkCmdCopyImage(): pRegion[%d] extent height (%d) must be a multiple of the compressed texture block " 149478ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton "height (%d), or when added to srcOffset.y (%d) must equal the image subresource height (%d). %s.", 149578ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton i, image_copy.extent.height, block_size.height, image_copy.srcOffset.y, mip_extent.height, 1496315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_09c0013e]); 149778ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton } 149878ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton 149978ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton // extent depth must be a multiple of block depth, or extent+offset depth must equal subresource depth 150078ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton uint32_t copy_depth = (slice_override ? depth_slices : image_copy.extent.depth); 150178ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton if ((SafeModulo(copy_depth, block_size.depth) != 0) && (copy_depth + image_copy.srcOffset.z != mip_extent.depth)) { 150278ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton skip |= 150378ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 1504315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis reinterpret_cast<const uint64_t &>(src_state->image), __LINE__, VALIDATION_ERROR_09c00140, "IMAGE", 150578ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton "vkCmdCopyImage(): pRegion[%d] extent width (%d) must be a multiple of the compressed texture block " 150678ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton "depth (%d), or when added to srcOffset.z (%d) must equal the image subresource depth (%d). %s.", 150778ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton i, image_copy.extent.depth, block_size.depth, image_copy.srcOffset.z, mip_extent.depth, 1508315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_09c00140]); 150978ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton } 151078ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton } // Compressed 151178ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton 151278ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton // Do all checks on dest image 151378ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton // 151478ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton if (dst_state->createInfo.imageType == VK_IMAGE_TYPE_1D) { 151578ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton if ((0 != image_copy.dstOffset.y) || (1 != image_copy.extent.height)) { 1516315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= 1517315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 1518315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis reinterpret_cast<const uint64_t &>(dst_state->image), __LINE__, VALIDATION_ERROR_09c00130, "IMAGE", 1519315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis "vkCmdCopyImage(): pRegion[%d] dstOffset.y is %d and extent.height is %d. For 1D images these must " 1520315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis "be 0 and 1, respectively. %s", 1521315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis i, image_copy.dstOffset.y, image_copy.extent.height, validation_error_map[VALIDATION_ERROR_09c00130]); 152278ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton } 152378ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton } 152478ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton 152578ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton if ((dst_state->createInfo.imageType == VK_IMAGE_TYPE_1D) || (dst_state->createInfo.imageType == VK_IMAGE_TYPE_2D)) { 152678ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton if ((0 != image_copy.dstOffset.z) || (1 != image_copy.extent.depth)) { 1527315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= 1528315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 1529315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis reinterpret_cast<const uint64_t &>(dst_state->image), __LINE__, VALIDATION_ERROR_09c00134, "IMAGE", 1530315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis "vkCmdCopyImage(): pRegion[%d] dstOffset.z is %d and extent.depth is %d. For 1D and 2D images " 1531315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis "these must be 0 and 1, respectively. %s", 1532315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis i, image_copy.dstOffset.z, image_copy.extent.depth, validation_error_map[VALIDATION_ERROR_09c00134]); 153378ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton } 153478ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton } 153578ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton 153678ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton if (dst_state->createInfo.imageType == VK_IMAGE_TYPE_3D) { 153778ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton if ((0 != image_copy.dstSubresource.baseArrayLayer) || (1 != image_copy.dstSubresource.layerCount)) { 153878ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 1539315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis reinterpret_cast<const uint64_t &>(dst_state->image), __LINE__, VALIDATION_ERROR_09c0011a, "IMAGE", 154078ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton "vkCmdCopyImage(): pRegion[%d] dstSubresource.baseArrayLayer is %d and dstSubresource.layerCount " 154178ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton "is %d. For VK_IMAGE_TYPE_3D images these must be 0 and 1, respectively. %s", 154278ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton i, image_copy.dstSubresource.baseArrayLayer, image_copy.dstSubresource.layerCount, 1543315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_09c0011a]); 154478ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton } 154578ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton } 154678ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton // VU01199 changed with mnt1 1547d4eaca34eca7f4b4e34190c441a579347bb2016aMark Lobodzinski if (GetDeviceExtensions(device_data)->vk_khr_maintenance1) { 154878ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton if (dst_state->createInfo.imageType == VK_IMAGE_TYPE_3D) { 154978ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton if ((0 != image_copy.dstSubresource.baseArrayLayer) || (1 != image_copy.dstSubresource.layerCount)) { 155078ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton skip |= 155178ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 1552315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis reinterpret_cast<const uint64_t &>(dst_state->image), __LINE__, VALIDATION_ERROR_09c0011a, "IMAGE", 155378ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton "vkCmdCopyImage(): pRegion[%d] dstSubresource.baseArrayLayer is %d and dstSubresource.layerCount " 155478ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton "is %d. For VK_IMAGE_TYPE_3D images these must be 0 and 1, respectively. %s", 155578ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton i, image_copy.dstSubresource.baseArrayLayer, image_copy.dstSubresource.layerCount, 1556315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_09c0011a]); 155778ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton } 155878ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton } 155978ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton } else { // Pre maint 1 156078ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton if (src_state->createInfo.imageType == VK_IMAGE_TYPE_3D || dst_state->createInfo.imageType == VK_IMAGE_TYPE_3D) { 156178ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton if ((0 != image_copy.dstSubresource.baseArrayLayer) || (1 != image_copy.dstSubresource.layerCount)) { 1562315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= 1563315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 1564315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis reinterpret_cast<const uint64_t &>(dst_state->image), __LINE__, VALIDATION_ERROR_09c0011a, "IMAGE", 1565315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis "vkCmdCopyImage(): pRegion[%d] dstSubresource.baseArrayLayer is %d and " 1566315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis "dstSubresource.layerCount is %d. For copies with either source or dest of type " 1567315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis "VK_IMAGE_TYPE_3D, these must be 0 and 1, respectively. %s", 1568315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis i, image_copy.dstSubresource.baseArrayLayer, image_copy.dstSubresource.layerCount, 1569315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_09c0011a]); 157078ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton } 157178ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton } 157278ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton } 157378ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton 157478ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton // TODO: this VU is redundant with VU01224. Gitlab issue 812 submitted to get it removed from the spec. 157578ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton if ((image_copy.dstSubresource.baseArrayLayer >= dst_state->createInfo.arrayLayers) || 157678ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton (image_copy.dstSubresource.baseArrayLayer + image_copy.dstSubresource.layerCount > dst_state->createInfo.arrayLayers)) { 157778ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 1578315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis reinterpret_cast<const uint64_t &>(dst_state->image), __LINE__, VALIDATION_ERROR_09c00136, "IMAGE", 157978ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton "vkCmdCopyImage(): pRegion[%d] dstSubresource.baseArrayLayer (%d) must be less than the dest image's " 158078ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton "arrayLayers (%d), and the sum of baseArrayLayer and dstSubresource.layerCount (%d) must be less than " 158178ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton "or equal to the dest image's arrayLayers. %s", 158278ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton i, image_copy.dstSubresource.baseArrayLayer, dst_state->createInfo.arrayLayers, 1583315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis image_copy.dstSubresource.layerCount, validation_error_map[VALIDATION_ERROR_09c00136]); 158478ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton } 158578ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton 158678ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton // Checks that apply only to compressed images 158778ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton if (FormatIsCompressed(dst_state->createInfo.format)) { 158878ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton VkExtent3D block_size = FormatCompressedTexelBlockExtent(dst_state->createInfo.format); 158978ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton 159078ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton // image offsets must be multiples of block dimensions 159178ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton if ((SafeModulo(image_copy.dstOffset.x, block_size.width) != 0) || 159278ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton (SafeModulo(image_copy.dstOffset.y, block_size.height) != 0) || 159378ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton (SafeModulo(image_copy.dstOffset.z, block_size.depth) != 0)) { 159478ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 1595315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis reinterpret_cast<const uint64_t &>(dst_state->image), __LINE__, VALIDATION_ERROR_09c00144, "IMAGE", 159678ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton "vkCmdCopyImage(): pRegion[%d] dstOffset (%d, %d) must be multiples of the compressed image's " 159778ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton "texel width & height (%d, %d). %s.", 159878ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton i, image_copy.dstOffset.x, image_copy.dstOffset.y, block_size.width, block_size.height, 1599315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_09c00144]); 160078ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton } 160178ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton 160278ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton // extent width must be a multiple of block width, or extent+offset width must equal subresource width 160378ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton VkExtent3D mip_extent = GetImageSubresourceExtent(dst_state, &(image_copy.dstSubresource)); 160478ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton if ((SafeModulo(image_copy.extent.width, block_size.width) != 0) && 160578ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton (image_copy.extent.width + image_copy.dstOffset.x != mip_extent.width)) { 160678ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton skip |= 160778ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 1608315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis reinterpret_cast<const uint64_t &>(dst_state->image), __LINE__, VALIDATION_ERROR_09c00146, "IMAGE", 160978ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton "vkCmdCopyImage(): pRegion[%d] extent width (%d) must be a multiple of the compressed texture block " 161078ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton "width (%d), or when added to dstOffset.x (%d) must equal the image subresource width (%d). %s.", 161178ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton i, image_copy.extent.width, block_size.width, image_copy.dstOffset.x, mip_extent.width, 1612315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_09c00146]); 161378ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton } 161478ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton 161578ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton // extent height must be a multiple of block height, or extent+offset height must equal subresource height 161678ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton if ((SafeModulo(image_copy.extent.height, block_size.height) != 0) && 161778ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton (image_copy.extent.height + image_copy.dstOffset.y != mip_extent.height)) { 161878ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton skip |= 161978ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 1620315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis reinterpret_cast<const uint64_t &>(dst_state->image), __LINE__, VALIDATION_ERROR_09c00148, "IMAGE", 162178ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton "vkCmdCopyImage(): pRegion[%d] extent height (%d) must be a multiple of the compressed texture block " 162278ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton "height (%d), or when added to dstOffset.y (%d) must equal the image subresource height (%d). %s.", 162378ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton i, image_copy.extent.height, block_size.height, image_copy.dstOffset.y, mip_extent.height, 1624315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_09c00148]); 162578ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton } 162678ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton 162778ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton // extent depth must be a multiple of block depth, or extent+offset depth must equal subresource depth 162878ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton uint32_t copy_depth = (slice_override ? depth_slices : image_copy.extent.depth); 162978ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton if ((SafeModulo(copy_depth, block_size.depth) != 0) && (copy_depth + image_copy.dstOffset.z != mip_extent.depth)) { 163078ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton skip |= 163178ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 1632315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis reinterpret_cast<const uint64_t &>(dst_state->image), __LINE__, VALIDATION_ERROR_09c0014a, "IMAGE", 163378ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton "vkCmdCopyImage(): pRegion[%d] extent width (%d) must be a multiple of the compressed texture block " 163478ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton "depth (%d), or when added to dstOffset.z (%d) must equal the image subresource depth (%d). %s.", 163578ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton i, image_copy.extent.depth, block_size.depth, image_copy.dstOffset.z, mip_extent.depth, 1636315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_09c0014a]); 163778ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton } 163878ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton } // Compressed 163978ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton } 164078ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton return skip; 164178ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton} 164278ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton 1643e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisbool PreCallValidateCmdCopyImage(layer_data *device_data, GLOBAL_CB_NODE *cb_node, IMAGE_STATE *src_image_state, 16446a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski IMAGE_STATE *dst_image_state, uint32_t region_count, const VkImageCopy *regions, 16456a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski VkImageLayout src_image_layout, VkImageLayout dst_image_layout) { 1646ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski bool skip = false; 1647ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski const debug_report_data *report_data = core_validation::GetReportData(device_data); 164878ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton skip = ValidateImageCopyData(device_data, report_data, region_count, regions, src_image_state, dst_image_state); 164978ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton 1650ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski VkCommandBuffer command_buffer = cb_node->commandBuffer; 1651ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski 16526a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski for (uint32_t i = 0; i < region_count; i++) { 165378ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton bool slice_override = false; 165478ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton uint32_t depth_slices = 0; 165578ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton 165678ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton // Special case for copying between a 1D/2D array and a 3D image 165778ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton // TBD: This seems like the only way to reconcile 3 mutually-exclusive VU checks for 2D/3D copies. Heads up. 165878ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton if ((VK_IMAGE_TYPE_3D == src_image_state->createInfo.imageType) && 165978ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton (VK_IMAGE_TYPE_3D != dst_image_state->createInfo.imageType)) { 166078ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton depth_slices = regions[i].dstSubresource.layerCount; // Slice count from 2D subresource 166178ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton slice_override = (depth_slices != 1); 166278ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton } else if ((VK_IMAGE_TYPE_3D == dst_image_state->createInfo.imageType) && 166378ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton (VK_IMAGE_TYPE_3D != src_image_state->createInfo.imageType)) { 166478ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton depth_slices = regions[i].srcSubresource.layerCount; // Slice count from 2D subresource 166578ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton slice_override = (depth_slices != 1); 166678ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton } 166778ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton 16686a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski if (regions[i].srcSubresource.layerCount == 0) { 16696a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski std::stringstream ss; 16706a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski ss << "vkCmdCopyImage: number of layers in pRegions[" << i << "] srcSubresource is zero"; 16719b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus skip |= 16729b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 16739b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(command_buffer), __LINE__, DRAWSTATE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str()); 16746a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski } 1675ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski 16766a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski if (regions[i].dstSubresource.layerCount == 0) { 16776a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski std::stringstream ss; 16786a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski ss << "vkCmdCopyImage: number of layers in pRegions[" << i << "] dstSubresource is zero"; 16799b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus skip |= 16809b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 16819b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(command_buffer), __LINE__, DRAWSTATE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str()); 16826a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski } 1683ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski 1684d4eaca34eca7f4b4e34190c441a579347bb2016aMark Lobodzinski if (GetDeviceExtensions(device_data)->vk_khr_maintenance1) { 168578ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton // No chance of mismatch if we're overriding depth slice count 168678ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton if (!slice_override) { 168778ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton // The number of depth slices in srcSubresource and dstSubresource must match 168878ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton // Depth comes from layerCount for 1D,2D resources, from extent.depth for 3D 168978ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton uint32_t src_slices = 169078ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton (VK_IMAGE_TYPE_3D == src_image_state->createInfo.imageType ? regions[i].extent.depth 169178ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton : regions[i].srcSubresource.layerCount); 169278ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton uint32_t dst_slices = 169378ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton (VK_IMAGE_TYPE_3D == dst_image_state->createInfo.imageType ? regions[i].extent.depth 169478ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton : regions[i].dstSubresource.layerCount); 169578ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton if (src_slices != dst_slices) { 169678ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton std::stringstream ss; 169778ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton ss << "vkCmdCopyImage: number of depth slices in source and destination subresources for pRegions[" << i 169878ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton << "] do not match"; 169978ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 1700315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_09c00118, "IMAGE", 1701315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis "%s. %s", ss.str().c_str(), validation_error_map[VALIDATION_ERROR_09c00118]); 170278ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton } 170378ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton } 170478ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton } else { 170557eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt // For each region the layerCount member of srcSubresource and dstSubresource must match 170657eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt if (regions[i].srcSubresource.layerCount != regions[i].dstSubresource.layerCount) { 170757eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt std::stringstream ss; 170857eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt ss << "vkCmdCopyImage: number of layers in source and destination subresources for pRegions[" << i 170957eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt << "] do not match"; 171057eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 1711315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(command_buffer), __LINE__, VALIDATION_ERROR_09c00118, "IMAGE", "%s. %s", 1712315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis ss.str().c_str(), validation_error_map[VALIDATION_ERROR_09c00118]); 171357eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt } 17146a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski } 1715ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski 17166a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski // For each region, the aspectMask member of srcSubresource and dstSubresource must match 17176a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski if (regions[i].srcSubresource.aspectMask != regions[i].dstSubresource.aspectMask) { 17186a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski char const str[] = "vkCmdCopyImage: Src and dest aspectMasks for each region must match"; 17196a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 1720315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(command_buffer), __LINE__, VALIDATION_ERROR_09c00112, "IMAGE", "%s. %s", str, 1721315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_09c00112]); 17226a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski } 1723ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski 1724e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton // For each region, the aspectMask member of srcSubresource must be present in the source image 1725e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton if (!VerifyAspectsPresent(regions[i].srcSubresource.aspectMask, src_image_state->createInfo.format)) { 1726e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton std::stringstream ss; 1727e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton ss << "vkCmdCopyImage: pRegion[" << i 1728e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton << "] srcSubresource.aspectMask cannot specify aspects not present in source image"; 1729e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 1730315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(command_buffer), __LINE__, VALIDATION_ERROR_09c0011c, "IMAGE", "%s. %s", 1731315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis ss.str().c_str(), validation_error_map[VALIDATION_ERROR_09c0011c]); 1732e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton } 1733e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton 1734e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton // For each region, the aspectMask member of dstSubresource must be present in the destination image 1735e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton if (!VerifyAspectsPresent(regions[i].dstSubresource.aspectMask, dst_image_state->createInfo.format)) { 1736e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton std::stringstream ss; 1737e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton ss << "vkCmdCopyImage: pRegion[" << i << "] dstSubresource.aspectMask cannot specify aspects not present in dest image"; 1738e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 1739315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(command_buffer), __LINE__, VALIDATION_ERROR_09c0011e, "IMAGE", "%s. %s", 1740315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis ss.str().c_str(), validation_error_map[VALIDATION_ERROR_09c0011e]); 1741e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton } 1742e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton 17436a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski // AspectMask must not contain VK_IMAGE_ASPECT_METADATA_BIT 17446a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski if ((regions[i].srcSubresource.aspectMask & VK_IMAGE_ASPECT_METADATA_BIT) || 17456a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski (regions[i].dstSubresource.aspectMask & VK_IMAGE_ASPECT_METADATA_BIT)) { 17466a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski std::stringstream ss; 17476a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski ss << "vkCmdCopyImage: pRegions[" << i << "] may not specify aspectMask containing VK_IMAGE_ASPECT_METADATA_BIT"; 17486a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 1749315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(command_buffer), __LINE__, VALIDATION_ERROR_0a600150, "IMAGE", "%s. %s", 1750315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis ss.str().c_str(), validation_error_map[VALIDATION_ERROR_0a600150]); 17516a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski } 1752ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski 17536a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski // For each region, if aspectMask contains VK_IMAGE_ASPECT_COLOR_BIT, it must not contain either of 17546a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski // VK_IMAGE_ASPECT_DEPTH_BIT or VK_IMAGE_ASPECT_STENCIL_BIT 17556a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski if ((regions[i].srcSubresource.aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) && 17566a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski (regions[i].srcSubresource.aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))) { 17576a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski char const str[] = "vkCmdCopyImage aspectMask cannot specify both COLOR and DEPTH/STENCIL aspects"; 17586a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 1759315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(command_buffer), __LINE__, VALIDATION_ERROR_0a60014e, "IMAGE", "%s. %s", str, 1760315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_0a60014e]); 17616a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski } 1762ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski 17636a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski // MipLevel must be less than the mipLevels specified in VkImageCreateInfo when the image was created 17646a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski if (regions[i].srcSubresource.mipLevel >= src_image_state->createInfo.mipLevels) { 17656a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski std::stringstream ss; 17666a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski ss << "vkCmdCopyImage: pRegions[" << i 17676a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski << "] specifies a src mipLevel greater than the number specified when the srcImage was created."; 17686a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 1769315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(command_buffer), __LINE__, VALIDATION_ERROR_0a600152, "IMAGE", "%s. %s", 1770315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis ss.str().c_str(), validation_error_map[VALIDATION_ERROR_0a600152]); 17716a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski } 17726a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski if (regions[i].dstSubresource.mipLevel >= dst_image_state->createInfo.mipLevels) { 17736a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski std::stringstream ss; 17746a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski ss << "vkCmdCopyImage: pRegions[" << i 17756a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski << "] specifies a dst mipLevel greater than the number specified when the dstImage was created."; 17766a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 1777315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(command_buffer), __LINE__, VALIDATION_ERROR_0a600152, "IMAGE", "%s. %s", 1778315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis ss.str().c_str(), validation_error_map[VALIDATION_ERROR_0a600152]); 17796a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski } 1780ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski 17816a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski // (baseArrayLayer + layerCount) must be less than or equal to the arrayLayers specified in VkImageCreateInfo when the 17826a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski // image was created 17836a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski if ((regions[i].srcSubresource.baseArrayLayer + regions[i].srcSubresource.layerCount) > 17846a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski src_image_state->createInfo.arrayLayers) { 17856a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski std::stringstream ss; 17866a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski ss << "vkCmdCopyImage: srcImage arrayLayers was " << src_image_state->createInfo.arrayLayers << " but subRegion[" << i 17876a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski << "] baseArrayLayer + layerCount is " 17886a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski << (regions[i].srcSubresource.baseArrayLayer + regions[i].srcSubresource.layerCount); 17896a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 1790315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(command_buffer), __LINE__, VALIDATION_ERROR_0a600154, "IMAGE", "%s. %s", 1791315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis ss.str().c_str(), validation_error_map[VALIDATION_ERROR_0a600154]); 17926a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski } 17936a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski if ((regions[i].dstSubresource.baseArrayLayer + regions[i].dstSubresource.layerCount) > 17946a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski dst_image_state->createInfo.arrayLayers) { 17956a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski std::stringstream ss; 17966a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski ss << "vkCmdCopyImage: dstImage arrayLayers was " << dst_image_state->createInfo.arrayLayers << " but subRegion[" << i 17976a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski << "] baseArrayLayer + layerCount is " 17986a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski << (regions[i].dstSubresource.baseArrayLayer + regions[i].dstSubresource.layerCount); 17996a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 1800315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(command_buffer), __LINE__, VALIDATION_ERROR_0a600154, "IMAGE", "%s. %s", 1801315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis ss.str().c_str(), validation_error_map[VALIDATION_ERROR_0a600154]); 18026a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski } 1803ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski 180457eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt // Check region extents for 1D-1D, 2D-2D, and 3D-3D copies 180557eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt if (src_image_state->createInfo.imageType == dst_image_state->createInfo.imageType) { 180657eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt // The source region specified by a given element of regions must be a region that is contained within srcImage 18073fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton VkExtent3D img_extent = GetImageSubresourceExtent(src_image_state, &(regions[i].srcSubresource)); 18083fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton if (0 != ExceedsBounds(®ions[i].srcOffset, ®ions[i].extent, &img_extent)) { 180957eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt std::stringstream ss; 18103fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton ss << "vkCmdCopyImage: Source pRegion[" << i << "] with mipLevel [ " << regions[i].srcSubresource.mipLevel 18113fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton << " ], offset [ " << regions[i].srcOffset.x << ", " << regions[i].srcOffset.y << ", " << regions[i].srcOffset.z 18123fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton << " ], extent [ " << regions[i].extent.width << ", " << regions[i].extent.height << ", " 18133fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton << regions[i].extent.depth << " ] exceeds the source image dimensions"; 181457eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 1815315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(command_buffer), __LINE__, VALIDATION_ERROR_190000f4, "IMAGE", "%s. %s", 1816315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis ss.str().c_str(), validation_error_map[VALIDATION_ERROR_190000f4]); 181757eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt } 1818ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski 181957eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt // The destination region specified by a given element of regions must be a region that is contained within dst_image 18203fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton img_extent = GetImageSubresourceExtent(dst_image_state, &(regions[i].dstSubresource)); 18213fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton if (0 != ExceedsBounds(®ions[i].dstOffset, ®ions[i].extent, &img_extent)) { 182257eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt std::stringstream ss; 18233fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton ss << "vkCmdCopyImage: Dest pRegion[" << i << "] with mipLevel [ " << regions[i].dstSubresource.mipLevel 18243fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton << " ], offset [ " << regions[i].dstOffset.x << ", " << regions[i].dstOffset.y << ", " << regions[i].dstOffset.z 18253fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton << " ], extent [ " << regions[i].extent.width << ", " << regions[i].extent.height << ", " 18263fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton << regions[i].extent.depth << " ] exceeds the destination image dimensions"; 182757eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 1828315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(command_buffer), __LINE__, VALIDATION_ERROR_190000f6, "IMAGE", "%s. %s", 1829315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis ss.str().c_str(), validation_error_map[VALIDATION_ERROR_190000f6]); 183057eda737eea95dd728f6dce5c78d6b00fb126076Mike Schuchardt } 18316a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski } 1832ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski 18333fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton // Each dimension offset + extent limits must fall with image subresource extent 18343fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton VkExtent3D subresource_extent = GetImageSubresourceExtent(src_image_state, &(regions[i].srcSubresource)); 183578ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton VkExtent3D copy_extent = regions[i].extent; 183678ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton if (slice_override) copy_extent.depth = depth_slices; 183778ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton uint32_t extent_check = ExceedsBounds(&(regions[i].srcOffset), ©_extent, &subresource_extent); 18383fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton if (extent_check & x_bit) { 18393fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 1840315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(command_buffer), __LINE__, VALIDATION_ERROR_09c00120, "IMAGE", 18413fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton "vkCmdCopyImage: Source image pRegion %1d x-dimension offset [%1d] + extent [%1d] exceeds subResource " 18423fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton "width [%1d]. %s", 18433fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton i, regions[i].srcOffset.x, regions[i].extent.width, subresource_extent.width, 1844315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_09c00120]); 18453fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton } 18463fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton 18473fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton if (extent_check & y_bit) { 18483fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 1849315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(command_buffer), __LINE__, VALIDATION_ERROR_09c00122, "IMAGE", 18503fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton "vkCmdCopyImage: Source image pRegion %1d y-dimension offset [%1d] + extent [%1d] exceeds subResource " 18513fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton "height [%1d]. %s", 18523fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton i, regions[i].srcOffset.y, regions[i].extent.height, subresource_extent.height, 1853315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_09c00122]); 18543fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton } 18553fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton if (extent_check & z_bit) { 18563fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 1857315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(command_buffer), __LINE__, VALIDATION_ERROR_09c00126, "IMAGE", 18583fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton "vkCmdCopyImage: Source image pRegion %1d z-dimension offset [%1d] + extent [%1d] exceeds subResource " 18593fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton "depth [%1d]. %s", 186078ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton i, regions[i].srcOffset.z, copy_extent.depth, subresource_extent.depth, 1861315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_09c00126]); 18623fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton } 18633fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton 18643fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton subresource_extent = GetImageSubresourceExtent(dst_image_state, &(regions[i].dstSubresource)); 186578ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton copy_extent = regions[i].extent; 186678ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton if (slice_override) copy_extent.depth = depth_slices; 186778ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton extent_check = ExceedsBounds(&(regions[i].dstOffset), ©_extent, &subresource_extent); 18683fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton if (extent_check & x_bit) { 18693fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 1870315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(command_buffer), __LINE__, VALIDATION_ERROR_09c0012c, "IMAGE", 18713fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton "vkCmdCopyImage: Dest image pRegion %1d x-dimension offset [%1d] + extent [%1d] exceeds subResource " 18723fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton "width [%1d]. %s", 18733fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton i, regions[i].dstOffset.x, regions[i].extent.width, subresource_extent.width, 1874315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_09c0012c]); 18753fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton } 18763fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton if (extent_check & y_bit) { 18773fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 1878315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(command_buffer), __LINE__, VALIDATION_ERROR_09c0012e, "IMAGE", 18793fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton "vkCmdCopyImage: Dest image pRegion %1d y-dimension offset [%1d] + extent [%1d] exceeds subResource " 18803fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton "height [%1d]. %s", 18813fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton i, regions[i].dstOffset.y, regions[i].extent.height, subresource_extent.height, 1882315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_09c0012e]); 18833fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton } 18843fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton if (extent_check & z_bit) { 18853fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 1886315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(command_buffer), __LINE__, VALIDATION_ERROR_09c00132, "IMAGE", 18873fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton "vkCmdCopyImage: Dest image pRegion %1d z-dimension offset [%1d] + extent [%1d] exceeds subResource " 18883fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton "depth [%1d]. %s", 188978ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton i, regions[i].dstOffset.z, copy_extent.depth, subresource_extent.depth, 1890315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_09c00132]); 18913fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton } 18923fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton 18936a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski // The union of all source regions, and the union of all destination regions, specified by the elements of regions, 18946a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski // must not overlap in memory 18956a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski if (src_image_state->image == dst_image_state->image) { 18966a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski for (uint32_t j = 0; j < region_count; j++) { 18976a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski if (RegionIntersects(®ions[i], ®ions[j], src_image_state->createInfo.imageType)) { 18986a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski std::stringstream ss; 18996a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski ss << "vkCmdCopyImage: pRegions[" << i << "] src overlaps with pRegions[" << j << "]."; 19006a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 1901315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(command_buffer), __LINE__, VALIDATION_ERROR_190000f8, "IMAGE", "%s. %s", 1902315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis ss.str().c_str(), validation_error_map[VALIDATION_ERROR_190000f8]); 1903ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski } 1904ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski } 1905ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski } 19066a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski } 1907ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski 19086a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski // The formats of src_image and dst_image must be compatible. Formats are considered compatible if their texel size in bytes 19096a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski // is the same between both formats. For example, VK_FORMAT_R8G8B8A8_UNORM is compatible with VK_FORMAT_R32_UINT because 19106a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski // because both texels are 4 bytes in size. Depth/stencil formats must match exactly. 1911cf2ce8673669ca1111e333bdea272c4dd57cb5c2Dave Houlton if (FormatIsDepthOrStencil(src_image_state->createInfo.format) || FormatIsDepthOrStencil(dst_image_state->createInfo.format)) { 19126a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski if (src_image_state->createInfo.format != dst_image_state->createInfo.format) { 19136a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski char const str[] = "vkCmdCopyImage called with unmatched source and dest image depth/stencil formats."; 19149b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 19159b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(command_buffer), __LINE__, DRAWSTATE_MISMATCHED_IMAGE_FORMAT, "IMAGE", str); 19166a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski } 19176a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski } else { 191816769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton size_t srcSize = FormatSize(src_image_state->createInfo.format); 191916769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton size_t destSize = FormatSize(dst_image_state->createInfo.format); 19206a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski if (srcSize != destSize) { 19216a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski char const str[] = "vkCmdCopyImage called with unmatched source and dest image format sizes."; 19226a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 1923315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(command_buffer), __LINE__, VALIDATION_ERROR_1900010e, "IMAGE", "%s. %s", str, 1924315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_1900010e]); 1925ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski } 1926ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski } 19276a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski 192892c9c5dfbd0dec1d76ca18faa487fa8c2d302a65Dave Houlton // Source and dest image sample counts must match 192992c9c5dfbd0dec1d76ca18faa487fa8c2d302a65Dave Houlton if (src_image_state->createInfo.samples != dst_image_state->createInfo.samples) { 193092c9c5dfbd0dec1d76ca18faa487fa8c2d302a65Dave Houlton char const str[] = "vkCmdCopyImage() called on image pair with non-identical sample counts."; 193192c9c5dfbd0dec1d76ca18faa487fa8c2d302a65Dave Houlton skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 1932315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(command_buffer), __LINE__, VALIDATION_ERROR_19000110, "IMAGE", "%s %s", str, 1933315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_19000110]); 193492c9c5dfbd0dec1d76ca18faa487fa8c2d302a65Dave Houlton } 193592c9c5dfbd0dec1d76ca18faa487fa8c2d302a65Dave Houlton 1936315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateMemoryIsBoundToImage(device_data, src_image_state, "vkCmdCopyImage()", VALIDATION_ERROR_190000fe); 1937315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateMemoryIsBoundToImage(device_data, dst_image_state, "vkCmdCopyImage()", VALIDATION_ERROR_19000108); 19386a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski // Validate that SRC & DST images have correct usage flags set 1939315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateImageUsageFlags(device_data, src_image_state, VK_IMAGE_USAGE_TRANSFER_SRC_BIT, true, VALIDATION_ERROR_190000fc, 19406a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski "vkCmdCopyImage()", "VK_IMAGE_USAGE_TRANSFER_SRC_BIT"); 1941315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateImageUsageFlags(device_data, dst_image_state, VK_IMAGE_USAGE_TRANSFER_DST_BIT, true, VALIDATION_ERROR_19000106, 19426a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski "vkCmdCopyImage()", "VK_IMAGE_USAGE_TRANSFER_DST_BIT"); 1943baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip |= ValidateCmdQueueFlags(device_data, cb_node, "vkCmdCopyImage()", 1944315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VK_QUEUE_TRANSFER_BIT | VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, VALIDATION_ERROR_19002415); 19456a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski skip |= ValidateCmd(device_data, cb_node, CMD_COPYIMAGE, "vkCmdCopyImage()"); 1946315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= insideRenderPass(device_data, cb_node, "vkCmdCopyImage()", VALIDATION_ERROR_19000017); 19470db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlis bool hit_error = false; 19486a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski for (uint32_t i = 0; i < region_count; ++i) { 1949fab4fd84d0d187bc73b5bc6709d8ed6370bb7cc3Tobin Ehlis skip |= VerifyImageLayout(device_data, cb_node, src_image_state, regions[i].srcSubresource, src_image_layout, 1950315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, "vkCmdCopyImage()", VALIDATION_ERROR_19000102, &hit_error); 1951fab4fd84d0d187bc73b5bc6709d8ed6370bb7cc3Tobin Ehlis skip |= VerifyImageLayout(device_data, cb_node, dst_image_state, regions[i].dstSubresource, dst_image_layout, 1952315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, "vkCmdCopyImage()", VALIDATION_ERROR_1900010c, &hit_error); 195378ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton skip |= ValidateCopyImageTransferGranularityRequirements(device_data, cb_node, src_image_state, dst_image_state, 195478ab91073f6d67b85f667f7f409390a93c2239e7Dave Houlton ®ions[i], i, "vkCmdCopyImage()"); 19556a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski } 19566a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski 1957ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski return skip; 1958ff309c48cf48eec4599c9bf83f5b5cd802fa2db0Mark Lobodzinski} 1959a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski 19606a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinskivoid PreCallRecordCmdCopyImage(layer_data *device_data, GLOBAL_CB_NODE *cb_node, IMAGE_STATE *src_image_state, 1961a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis IMAGE_STATE *dst_image_state, uint32_t region_count, const VkImageCopy *regions, 1962a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis VkImageLayout src_image_layout, VkImageLayout dst_image_layout) { 1963a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis // Make sure that all image slices are updated to correct layout 1964a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis for (uint32_t i = 0; i < region_count; ++i) { 1965a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis SetImageLayout(device_data, cb_node, src_image_state, regions[i].srcSubresource, src_image_layout); 1966a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis SetImageLayout(device_data, cb_node, dst_image_state, regions[i].dstSubresource, dst_image_layout); 1967a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis } 19686a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski // Update bindings between images and cmd buffer 19696a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski AddCommandBufferBindingImage(device_data, cb_node, src_image_state); 19706a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski AddCommandBufferBindingImage(device_data, cb_node, dst_image_state); 19713f97578f1f51ffcb797a9feef4e5c8a600711a94Dave Houlton std::function<bool()> function = [=]() { return ValidateImageMemoryIsValid(device_data, src_image_state, "vkCmdCopyImage()"); }; 19726a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski cb_node->validate_functions.push_back(function); 19736a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski function = [=]() { 19746a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski SetImageMemoryValid(device_data, dst_image_state, true); 19756a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski return false; 19766a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski }; 19776a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski cb_node->validate_functions.push_back(function); 19786a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski core_validation::UpdateCmdBufferLastCmd(cb_node, CMD_COPYIMAGE); 19796a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski} 19806a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski 1981a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski// Returns true if sub_rect is entirely contained within rect 1982a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinskistatic inline bool ContainsRect(VkRect2D rect, VkRect2D sub_rect) { 1983a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski if ((sub_rect.offset.x < rect.offset.x) || (sub_rect.offset.x + sub_rect.extent.width > rect.offset.x + rect.extent.width) || 1984a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski (sub_rect.offset.y < rect.offset.y) || (sub_rect.offset.y + sub_rect.extent.height > rect.offset.y + rect.extent.height)) 1985a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski return false; 1986a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski return true; 1987a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski} 1988a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski 1989e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisbool PreCallValidateCmdClearAttachments(layer_data *device_data, VkCommandBuffer commandBuffer, uint32_t attachmentCount, 1990e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlis const VkClearAttachment *pAttachments, uint32_t rectCount, const VkClearRect *pRects) { 19919a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *cb_node = GetCBNode(device_data, commandBuffer); 1992a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski const debug_report_data *report_data = core_validation::GetReportData(device_data); 1993a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski 1994a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski bool skip = false; 1995a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski if (cb_node) { 1996315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateCmdQueueFlags(device_data, cb_node, "vkCmdClearAttachments()", VK_QUEUE_GRAPHICS_BIT, 1997315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_18602415); 1998a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski skip |= ValidateCmd(device_data, cb_node, CMD_CLEARATTACHMENTS, "vkCmdClearAttachments()"); 19999a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis core_validation::UpdateCmdBufferLastCmd(cb_node, CMD_CLEARATTACHMENTS); 2000a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski // Warn if this is issued prior to Draw Cmd and clearing the entire attachment 2001b68b13ed4952bce61f6ebb0023542660c26b0562Chris Forbes if (!cb_node->hasDrawCmd && (cb_node->activeRenderPassBeginInfo.renderArea.extent.width == pRects[0].rect.extent.width) && 2002a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski (cb_node->activeRenderPassBeginInfo.renderArea.extent.height == pRects[0].rect.extent.height)) { 2003a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski // There are times where app needs to use ClearAttachments (generally when reusing a buffer inside of a render pass) 20048e0190bd5904b8a8f044dae2c6ae23a891eb5e11Mark 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 20058e0190bd5904b8a8f044dae2c6ae23a891eb5e11Mark Lobodzinski // CmdClearAttachments. 200673f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski skip |= 200773f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski log_msg(report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 20089b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(commandBuffer), 0, DRAWSTATE_CLEAR_CMD_BEFORE_DRAW, "DS", 200973f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski "vkCmdClearAttachments() issued on command buffer object 0x%p prior to any Draw Cmds." 201073f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski " It is recommended you use RenderPass LOAD_OP_CLEAR on Attachments prior to any Draw.", 201173f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski commandBuffer); 2012a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski } 2013315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= outsideRenderPass(device_data, cb_node, "vkCmdClearAttachments()", VALIDATION_ERROR_18600017); 2014a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski } 2015a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski 2016a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski // Validate that attachment is in reference list of active subpass 2017a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski if (cb_node->activeRenderPass) { 2018a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski const VkRenderPassCreateInfo *renderpass_create_info = cb_node->activeRenderPass->createInfo.ptr(); 2019a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski const VkSubpassDescription *subpass_desc = &renderpass_create_info->pSubpasses[cb_node->activeSubpass]; 20209a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto framebuffer = GetFramebufferState(device_data, cb_node->activeFramebuffer); 2021a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski 2022a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski for (uint32_t i = 0; i < attachmentCount; i++) { 2023a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski auto clear_desc = &pAttachments[i]; 2024a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski VkImageView image_view = VK_NULL_HANDLE; 2025a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski 202673f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski if (0 == clear_desc->aspectMask) { 202773f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 2028315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_01c00c03, "IMAGE", "%s", 2029315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_01c00c03]); 203073f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski } else if (clear_desc->aspectMask & VK_IMAGE_ASPECT_METADATA_BIT) { 203173f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 2032315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_01c00028, "IMAGE", "%s", 2033315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_01c00028]); 203473f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski } else if (clear_desc->aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) { 2035a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski if (clear_desc->colorAttachment >= subpass_desc->colorAttachmentCount) { 2036315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 2037315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_1860001e, "DS", 2038315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis "vkCmdClearAttachments() color attachment index %d out of range for active subpass %d. %s", 2039315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis clear_desc->colorAttachment, cb_node->activeSubpass, 2040315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_1860001e]); 2041a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski } else if (subpass_desc->pColorAttachments[clear_desc->colorAttachment].attachment == VK_ATTACHMENT_UNUSED) { 2042a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, 20439b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, HandleToUint64(commandBuffer), __LINE__, 20449b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus DRAWSTATE_MISSING_ATTACHMENT_REFERENCE, "DS", 204573f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski "vkCmdClearAttachments() color attachment index %d is VK_ATTACHMENT_UNUSED; ignored.", 204673f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski clear_desc->colorAttachment); 2047a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski } else { 2048a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski image_view = framebuffer->createInfo 204973f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski .pAttachments[subpass_desc->pColorAttachments[clear_desc->colorAttachment].attachment]; 2050a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski } 205173f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski if ((clear_desc->aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) || 205273f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski (clear_desc->aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT)) { 205373f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski char const str[] = 205473f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski "vkCmdClearAttachments aspectMask [%d] must set only VK_IMAGE_ASPECT_COLOR_BIT of a color attachment. %s"; 205573f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 2056315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_01c00026, "IMAGE", str, i, 2057315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_01c00026]); 205873f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski } 205973f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski } else { // Must be depth and/or stencil 206073f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski if (((clear_desc->aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) != VK_IMAGE_ASPECT_DEPTH_BIT) && 206173f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski ((clear_desc->aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) != VK_IMAGE_ASPECT_STENCIL_BIT)) { 206273f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski char const str[] = "vkCmdClearAttachments aspectMask [%d] is not a valid combination of bits. %s"; 206373f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 2064315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_01c00c01, "IMAGE", str, i, 2065315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_01c00c01]); 206673f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski } 206773f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski if (!subpass_desc->pDepthStencilAttachment || 206873f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski (subpass_desc->pDepthStencilAttachment->attachment == VK_ATTACHMENT_UNUSED)) { 206973f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski skip |= log_msg( 207073f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 20719b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(commandBuffer), __LINE__, DRAWSTATE_MISSING_ATTACHMENT_REFERENCE, "DS", 207273f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski "vkCmdClearAttachments() depth/stencil clear with no depth/stencil attachment in subpass; ignored"); 2073a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski } else { 2074a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski image_view = framebuffer->createInfo.pAttachments[subpass_desc->pDepthStencilAttachment->attachment]; 2075a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski } 2076a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski } 2077a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski if (image_view) { 20789a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_view_state = GetImageViewState(device_data, image_view); 2079a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski for (uint32_t j = 0; j < rectCount; j++) { 208073f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski // The rectangular region specified by a given element of pRects must be contained within the render area of 208173f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski // the current render pass instance 20828e0190bd5904b8a8f044dae2c6ae23a891eb5e11Mark Lobodzinski // TODO: This check should be moved to CmdExecuteCommands or QueueSubmit to cover secondary CB cases 20838e0190bd5904b8a8f044dae2c6ae23a891eb5e11Mark Lobodzinski if ((cb_node->createInfo.level == VK_COMMAND_BUFFER_LEVEL_PRIMARY) && 20848e0190bd5904b8a8f044dae2c6ae23a891eb5e11Mark Lobodzinski (false == ContainsRect(cb_node->activeRenderPassBeginInfo.renderArea, pRects[j].rect))) { 2085fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 2086315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_18600020, "DS", 208773f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski "vkCmdClearAttachments(): The area defined by pRects[%d] is not contained in the area of " 208873f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski "the current render pass instance. %s", 2089315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis j, validation_error_map[VALIDATION_ERROR_18600020]); 2090a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski } 2091a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski // The layers specified by a given element of pRects must be contained within every attachment that 2092a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski // pAttachments refers to 2093a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski auto attachment_layer_count = image_view_state->create_info.subresourceRange.layerCount; 20940025f5cb69a4e6457254db9b93da4f30b86413f2Dave Houlton if ((pRects[j].baseArrayLayer >= attachment_layer_count) || 20950025f5cb69a4e6457254db9b93da4f30b86413f2Dave Houlton (pRects[j].baseArrayLayer + pRects[j].layerCount > attachment_layer_count)) { 2096a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski skip |= 2097fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 2098315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_18600022, "DS", 209973f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski "vkCmdClearAttachments(): The layers defined in pRects[%d] are not contained in the layers of " 210073f044278acc4f663257c463f9032b603a5f1be7Mark Lobodzinski "pAttachment[%d]. %s", 2101315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis j, i, validation_error_map[VALIDATION_ERROR_18600022]); 2102a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski } 2103a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski } 2104a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski } 2105a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski } 2106a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski } 2107a6b0aebe9298e0dfc98174423f78bb7d06f1da97Mark Lobodzinski return skip; 210860568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski} 210960568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski 2110e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisbool PreCallValidateCmdResolveImage(layer_data *device_data, GLOBAL_CB_NODE *cb_node, IMAGE_STATE *src_image_state, 211154c03b0fa365789b242e680223bd30c940f1abb3Mark Lobodzinski IMAGE_STATE *dst_image_state, uint32_t regionCount, const VkImageResolve *pRegions) { 211225f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski const debug_report_data *report_data = core_validation::GetReportData(device_data); 211360568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski bool skip = false; 211460568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski if (cb_node && src_image_state && dst_image_state) { 2115315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateMemoryIsBoundToImage(device_data, src_image_state, "vkCmdResolveImage()", VALIDATION_ERROR_1c800200); 2116315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateMemoryIsBoundToImage(device_data, dst_image_state, "vkCmdResolveImage()", VALIDATION_ERROR_1c800204); 2117315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= 2118315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis ValidateCmdQueueFlags(device_data, cb_node, "vkCmdResolveImage()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_1c802415); 211960568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski skip |= ValidateCmd(device_data, cb_node, CMD_RESOLVEIMAGE, "vkCmdResolveImage()"); 2120315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= insideRenderPass(device_data, cb_node, "vkCmdResolveImage()", VALIDATION_ERROR_1c800017); 212125f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski 212225f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski // For each region, the number of layers in the image subresource should not be zero 212325f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski // For each region, src and dest image aspect must be color only 212425f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski for (uint32_t i = 0; i < regionCount; i++) { 212525f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski if (pRegions[i].srcSubresource.layerCount == 0) { 212625f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski char const str[] = "vkCmdResolveImage: number of layers in source subresource is zero"; 212754c03b0fa365789b242e680223bd30c940f1abb3Mark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 21289b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(cb_node->commandBuffer), __LINE__, DRAWSTATE_MISMATCHED_IMAGE_ASPECT, "IMAGE", str); 212925f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski } 213025f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski if (pRegions[i].dstSubresource.layerCount == 0) { 213125f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski char const str[] = "vkCmdResolveImage: number of layers in destination subresource is zero"; 213254c03b0fa365789b242e680223bd30c940f1abb3Mark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 21339b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(cb_node->commandBuffer), __LINE__, DRAWSTATE_MISMATCHED_IMAGE_ASPECT, "IMAGE", str); 213425f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski } 213554c03b0fa365789b242e680223bd30c940f1abb3Mark Lobodzinski if (pRegions[i].srcSubresource.layerCount != pRegions[i].dstSubresource.layerCount) { 213654c03b0fa365789b242e680223bd30c940f1abb3Mark Lobodzinski skip |= log_msg( 213754c03b0fa365789b242e680223bd30c940f1abb3Mark Lobodzinski report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 2138315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_0a200216, "IMAGE", 213954c03b0fa365789b242e680223bd30c940f1abb3Mark Lobodzinski "vkCmdResolveImage: layerCount in source and destination subresource of pRegions[%d] does not match. %s", i, 2140315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_0a200216]); 214154c03b0fa365789b242e680223bd30c940f1abb3Mark Lobodzinski } 214225f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski if ((pRegions[i].srcSubresource.aspectMask != VK_IMAGE_ASPECT_COLOR_BIT) || 214325f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski (pRegions[i].dstSubresource.aspectMask != VK_IMAGE_ASPECT_COLOR_BIT)) { 214425f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski char const str[] = 214525f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski "vkCmdResolveImage: src and dest aspectMasks for each region must specify only VK_IMAGE_ASPECT_COLOR_BIT"; 214625f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 2147315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_0a200214, "IMAGE", "%s. %s", str, 2148315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_0a200214]); 214925f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski } 215025f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski } 215125f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski 215225f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski if (src_image_state->createInfo.format != dst_image_state->createInfo.format) { 215325f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski char const str[] = "vkCmdResolveImage called with unmatched source and dest formats."; 215454c03b0fa365789b242e680223bd30c940f1abb3Mark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 21559b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(cb_node->commandBuffer), __LINE__, DRAWSTATE_MISMATCHED_IMAGE_FORMAT, "IMAGE", str); 215625f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski } 215725f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski if (src_image_state->createInfo.imageType != dst_image_state->createInfo.imageType) { 215825f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski char const str[] = "vkCmdResolveImage called with unmatched source and dest image types."; 215954c03b0fa365789b242e680223bd30c940f1abb3Mark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 21609b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(cb_node->commandBuffer), __LINE__, DRAWSTATE_MISMATCHED_IMAGE_TYPE, "IMAGE", str); 216125f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski } 216225f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski if (src_image_state->createInfo.samples == VK_SAMPLE_COUNT_1_BIT) { 216325f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski char const str[] = "vkCmdResolveImage called with source sample count less than 2."; 216425f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 2165315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_1c800202, "IMAGE", "%s. %s", str, 2166315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_1c800202]); 216725f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski } 216825f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski if (dst_image_state->createInfo.samples != VK_SAMPLE_COUNT_1_BIT) { 216925f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski char const str[] = "vkCmdResolveImage called with dest sample count greater than 1."; 217025f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 2171315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_1c800206, "IMAGE", "%s. %s", str, 2172315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_1c800206]); 217325f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski } 217487a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis // TODO: Need to validate image layouts, which will include layout validation for shared presentable images 217560568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski } else { 217660568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski assert(0); 217760568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski } 217860568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski return skip; 217960568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski} 218060568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski 2181e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisvoid PreCallRecordCmdResolveImage(layer_data *device_data, GLOBAL_CB_NODE *cb_node, IMAGE_STATE *src_image_state, 2182e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlis IMAGE_STATE *dst_image_state) { 218360568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski // Update bindings between images and cmd buffer 218460568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski AddCommandBufferBindingImage(device_data, cb_node, src_image_state); 218560568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski AddCommandBufferBindingImage(device_data, cb_node, dst_image_state); 218660568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski 218760568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski std::function<bool()> function = [=]() { 218860568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski return ValidateImageMemoryIsValid(device_data, src_image_state, "vkCmdResolveImage()"); 218960568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski }; 219060568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski cb_node->validate_functions.push_back(function); 219160568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski function = [=]() { 219260568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski SetImageMemoryValid(device_data, dst_image_state, true); 219360568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski return false; 219460568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski }; 219560568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski cb_node->validate_functions.push_back(function); 21969a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis core_validation::UpdateCmdBufferLastCmd(cb_node, CMD_RESOLVEIMAGE); 219760568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski} 219860568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski 2199e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisbool PreCallValidateCmdBlitImage(layer_data *device_data, GLOBAL_CB_NODE *cb_node, IMAGE_STATE *src_image_state, 2200055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski IMAGE_STATE *dst_image_state, uint32_t regionCount, const VkImageBlit *pRegions, VkFilter filter) { 2201055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski const debug_report_data *report_data = core_validation::GetReportData(device_data); 2202055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski 220360568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski bool skip = false; 220460568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski if (cb_node && src_image_state && dst_image_state) { 220560568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski skip |= ValidateImageSampleCount(device_data, src_image_state, VK_SAMPLE_COUNT_1_BIT, "vkCmdBlitImage(): srcImage", 2206315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_184001d2); 220760568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski skip |= ValidateImageSampleCount(device_data, dst_image_state, VK_SAMPLE_COUNT_1_BIT, "vkCmdBlitImage(): dstImage", 2208315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_184001d4); 2209315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateMemoryIsBoundToImage(device_data, src_image_state, "vkCmdBlitImage()", VALIDATION_ERROR_184001b8); 2210315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateMemoryIsBoundToImage(device_data, dst_image_state, "vkCmdBlitImage()", VALIDATION_ERROR_184001c2); 2211315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateImageUsageFlags(device_data, src_image_state, VK_IMAGE_USAGE_TRANSFER_SRC_BIT, true, 2212315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_184001b6, "vkCmdBlitImage()", "VK_IMAGE_USAGE_TRANSFER_SRC_BIT"); 2213315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateImageUsageFlags(device_data, dst_image_state, VK_IMAGE_USAGE_TRANSFER_DST_BIT, true, 2214315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_184001c0, "vkCmdBlitImage()", "VK_IMAGE_USAGE_TRANSFER_DST_BIT"); 2215315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateCmdQueueFlags(device_data, cb_node, "vkCmdBlitImage()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_18402415); 221660568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski skip |= ValidateCmd(device_data, cb_node, CMD_BLITIMAGE, "vkCmdBlitImage()"); 2217315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= insideRenderPass(device_data, cb_node, "vkCmdBlitImage()", VALIDATION_ERROR_18400017); 221887a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis // TODO: Need to validate image layouts, which will include layout validation for shared presentable images 2219055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski 2220055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski for (uint32_t i = 0; i < regionCount; i++) { 222143a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton VkImageBlit rgn = pRegions[i]; 222243a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton 2223d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski // Warn for zero-sized regions 222443a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton if ((rgn.srcOffsets[0].x == rgn.srcOffsets[1].x) || (rgn.srcOffsets[0].y == rgn.srcOffsets[1].y) || 222543a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton (rgn.srcOffsets[0].z == rgn.srcOffsets[1].z)) { 2226055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski std::stringstream ss; 2227055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski ss << "vkCmdBlitImage: pRegions[" << i << "].srcOffsets specify a zero-volume area."; 2228055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 22299b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(cb_node->commandBuffer), __LINE__, DRAWSTATE_INVALID_EXTENTS, "IMAGE", "%s", 22309b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus ss.str().c_str()); 2231055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski } 223243a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton if ((rgn.dstOffsets[0].x == rgn.dstOffsets[1].x) || (rgn.dstOffsets[0].y == rgn.dstOffsets[1].y) || 223343a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton (rgn.dstOffsets[0].z == rgn.dstOffsets[1].z)) { 2234055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski std::stringstream ss; 2235055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski ss << "vkCmdBlitImage: pRegions[" << i << "].dstOffsets specify a zero-volume area."; 2236055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 22379b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(cb_node->commandBuffer), __LINE__, DRAWSTATE_INVALID_EXTENTS, "IMAGE", "%s", 22389b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus ss.str().c_str()); 2239055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski } 224043a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton if (rgn.srcSubresource.layerCount == 0) { 2241d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski char const str[] = "vkCmdBlitImage: number of layers in source subresource is zero"; 2242d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 22439b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(cb_node->commandBuffer), __LINE__, DRAWSTATE_MISMATCHED_IMAGE_ASPECT, "IMAGE", str); 2244d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski } 224543a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton if (rgn.dstSubresource.layerCount == 0) { 2246d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski char const str[] = "vkCmdBlitImage: number of layers in destination subresource is zero"; 2247d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 22489b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(cb_node->commandBuffer), __LINE__, DRAWSTATE_MISMATCHED_IMAGE_ASPECT, "IMAGE", str); 2249d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski } 2250d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski 2251d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski // Check that src/dst layercounts match 225243a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton if (rgn.srcSubresource.layerCount != rgn.dstSubresource.layerCount) { 2253d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski skip |= 2254d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 2255315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_09a001de, "IMAGE", 2256d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski "vkCmdBlitImage: layerCount in source and destination subresource of pRegions[%d] does not match. %s", 2257315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis i, validation_error_map[VALIDATION_ERROR_09a001de]); 2258d81f107590290d41d3e39fcbf3f077658be0f5a6Mark Lobodzinski } 22598068cb0f90422b6789d0c120f0831f55eb76b71aMark Lobodzinski 226043a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton if (rgn.srcSubresource.aspectMask != rgn.dstSubresource.aspectMask) { 22618068cb0f90422b6789d0c120f0831f55eb76b71aMark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 2262315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_09a001dc, "IMAGE", 22638068cb0f90422b6789d0c120f0831f55eb76b71aMark Lobodzinski "vkCmdBlitImage: aspectMask members for pRegion[%d] do not match. %s", i, 2264315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_09a001dc]); 22658068cb0f90422b6789d0c120f0831f55eb76b71aMark Lobodzinski } 226643a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton 226743a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton // Validate source image offsets 226843a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton VkExtent3D src_extent = GetImageSubresourceExtent(src_image_state, &(rgn.srcSubresource)); 226943a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton if (VK_IMAGE_TYPE_1D == src_image_state->createInfo.imageType) { 227043a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton if ((0 != rgn.srcOffsets[0].y) || (1 != rgn.srcOffsets[1].y)) { 227143a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 227243a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_09a001ea, "IMAGE", 227343a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton "vkCmdBlitImage: region [%d], source image of type VK_IMAGE_TYPE_1D with srcOffset[].y values " 227443a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton "of (%1d, %1d). These must be (0, 1). %s", 227543a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton i, rgn.srcOffsets[0].y, rgn.srcOffsets[1].y, validation_error_map[VALIDATION_ERROR_09a001ea]); 227643a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton } 227743a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton } 227843a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton 227943a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton if ((VK_IMAGE_TYPE_1D == src_image_state->createInfo.imageType) || 228043a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton (VK_IMAGE_TYPE_2D == src_image_state->createInfo.imageType)) { 228143a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton if ((0 != rgn.srcOffsets[0].z) || (1 != rgn.srcOffsets[1].z)) { 228243a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 228343a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_09a001ee, "IMAGE", 228443a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton "vkCmdBlitImage: region [%d], source image of type VK_IMAGE_TYPE_1D or VK_IMAGE_TYPE_2D with " 228543a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton "srcOffset[].z values of (%1d, %1d). These must be (0, 1). %s", 228643a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton i, rgn.srcOffsets[0].z, rgn.srcOffsets[1].z, validation_error_map[VALIDATION_ERROR_09a001ee]); 228743a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton } 228843a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton } 228943a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton 229043a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton if ((rgn.srcOffsets[0].x < 0) || (rgn.srcOffsets[0].x > static_cast<int32_t>(src_extent.width)) || 229143a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton (rgn.srcOffsets[1].x < 0) || (rgn.srcOffsets[1].x > static_cast<int32_t>(src_extent.width))) { 229243a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton skip |= log_msg( 229343a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 229443a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_09a001e6, "IMAGE", 229543a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton "vkCmdBlitImage: region [%d] srcOffset[].x values (%1d, %1d) exceed srcSubresource width extent (%1d). %s", i, 229643a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton rgn.srcOffsets[0].x, rgn.srcOffsets[1].x, src_extent.width, validation_error_map[VALIDATION_ERROR_09a001e6]); 229743a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton } 229843a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton if ((rgn.srcOffsets[0].y < 0) || (rgn.srcOffsets[0].y > static_cast<int32_t>(src_extent.height)) || 229943a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton (rgn.srcOffsets[1].y < 0) || (rgn.srcOffsets[1].y > static_cast<int32_t>(src_extent.height))) { 230043a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton skip |= log_msg( 230143a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 230243a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_09a001e8, "IMAGE", 230343a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton "vkCmdBlitImage: region [%d] srcOffset[].y values (%1d, %1d) exceed srcSubresource height extent (%1d). %s", i, 230443a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton rgn.srcOffsets[0].y, rgn.srcOffsets[1].y, src_extent.height, validation_error_map[VALIDATION_ERROR_09a001e8]); 230543a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton } 230643a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton if ((rgn.srcOffsets[0].z < 0) || (rgn.srcOffsets[0].z > static_cast<int32_t>(src_extent.depth)) || 230743a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton (rgn.srcOffsets[1].z < 0) || (rgn.srcOffsets[1].z > static_cast<int32_t>(src_extent.depth))) { 230843a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton skip |= log_msg( 230943a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 231043a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_09a001ec, "IMAGE", 231143a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton "vkCmdBlitImage: region [%d] srcOffset[].z values (%1d, %1d) exceed srcSubresource depth extent (%1d). %s", i, 231243a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton rgn.srcOffsets[0].z, rgn.srcOffsets[1].z, src_extent.depth, validation_error_map[VALIDATION_ERROR_09a001ec]); 231343a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton } 231443a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton 231543a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton // Validate dest image offsets 231643a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton VkExtent3D dst_extent = GetImageSubresourceExtent(dst_image_state, &(rgn.dstSubresource)); 231743a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton if (VK_IMAGE_TYPE_1D == dst_image_state->createInfo.imageType) { 231843a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton if ((0 != rgn.dstOffsets[0].y) || (1 != rgn.dstOffsets[1].y)) { 231943a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 232043a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_09a001f4, "IMAGE", 232143a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton "vkCmdBlitImage: region [%d], dest image of type VK_IMAGE_TYPE_1D with dstOffset[].y values of " 232243a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton "(%1d, %1d). These must be (0, 1). %s", 232343a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton i, rgn.dstOffsets[0].y, rgn.dstOffsets[1].y, validation_error_map[VALIDATION_ERROR_09a001f4]); 232443a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton } 232543a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton } 232643a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton 232743a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton if ((VK_IMAGE_TYPE_1D == dst_image_state->createInfo.imageType) || 232843a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton (VK_IMAGE_TYPE_2D == dst_image_state->createInfo.imageType)) { 232943a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton if ((0 != rgn.dstOffsets[0].z) || (1 != rgn.dstOffsets[1].z)) { 233043a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 233143a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_09a001f8, "IMAGE", 233243a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton "vkCmdBlitImage: region [%d], dest image of type VK_IMAGE_TYPE_1D or VK_IMAGE_TYPE_2D with " 233343a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton "dstOffset[].z values of (%1d, %1d). These must be (0, 1). %s", 233443a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton i, rgn.dstOffsets[0].z, rgn.dstOffsets[1].z, validation_error_map[VALIDATION_ERROR_09a001f8]); 233543a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton } 233643a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton } 233743a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton 233843a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton if ((rgn.dstOffsets[0].x < 0) || (rgn.dstOffsets[0].x > static_cast<int32_t>(dst_extent.width)) || 233943a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton (rgn.dstOffsets[1].x < 0) || (rgn.dstOffsets[1].x > static_cast<int32_t>(dst_extent.width))) { 234043a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton skip |= log_msg( 234143a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 234243a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_09a001f0, "IMAGE", 234343a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton "vkCmdBlitImage: region [%d] dstOffset[].x values (%1d, %1d) exceed dstSubresource width extent (%1d). %s", i, 234443a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton rgn.dstOffsets[0].x, rgn.dstOffsets[1].x, dst_extent.width, validation_error_map[VALIDATION_ERROR_09a001f0]); 234543a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton } 234643a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton if ((rgn.dstOffsets[0].y < 0) || (rgn.dstOffsets[0].y > static_cast<int32_t>(dst_extent.height)) || 234743a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton (rgn.dstOffsets[1].y < 0) || (rgn.dstOffsets[1].y > static_cast<int32_t>(dst_extent.height))) { 234843a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton skip |= log_msg( 234943a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 235043a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_09a001f2, "IMAGE", 235143a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton "vkCmdBlitImage: region [%d] dstOffset[].y values (%1d, %1d) exceed dstSubresource height extent (%1d). %s", i, 235243a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton rgn.dstOffsets[0].y, rgn.dstOffsets[1].y, dst_extent.height, validation_error_map[VALIDATION_ERROR_09a001f2]); 235343a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton } 235443a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton if ((rgn.dstOffsets[0].z < 0) || (rgn.dstOffsets[0].z > static_cast<int32_t>(dst_extent.depth)) || 235543a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton (rgn.dstOffsets[1].z < 0) || (rgn.dstOffsets[1].z > static_cast<int32_t>(dst_extent.depth))) { 235643a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton skip |= log_msg( 235743a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 235843a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_09a001f6, "IMAGE", 235943a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton "vkCmdBlitImage: region [%d] dstOffset[].z values (%1d, %1d) exceed dstSubresource depth extent (%1d). %s", i, 236043a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton rgn.dstOffsets[0].z, rgn.dstOffsets[1].z, dst_extent.depth, validation_error_map[VALIDATION_ERROR_09a001f6]); 236143a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton } 2362055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski } 2363055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski 2364055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski VkFormat src_format = src_image_state->createInfo.format; 2365055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski VkFormat dst_format = dst_image_state->createInfo.format; 2366055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski 2367055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski // Validate consistency for unsigned formats 236816769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton if (FormatIsUInt(src_format) != FormatIsUInt(dst_format)) { 2369055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski std::stringstream ss; 2370055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski ss << "vkCmdBlitImage: If one of srcImage and dstImage images has unsigned integer format, " 2371055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski << "the other one must also have unsigned integer format. " 2372055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski << "Source format is " << string_VkFormat(src_format) << " Destination format is " << string_VkFormat(dst_format); 2373055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 2374315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_184001cc, "IMAGE", "%s. %s", 2375315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis ss.str().c_str(), validation_error_map[VALIDATION_ERROR_184001cc]); 2376055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski } 2377055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski 2378055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski // Validate consistency for signed formats 237916769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton if (FormatIsSInt(src_format) != FormatIsSInt(dst_format)) { 2380055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski std::stringstream ss; 2381055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski ss << "vkCmdBlitImage: If one of srcImage and dstImage images has signed integer format, " 2382055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski << "the other one must also have signed integer format. " 2383055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski << "Source format is " << string_VkFormat(src_format) << " Destination format is " << string_VkFormat(dst_format); 2384055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 2385315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_184001ca, "IMAGE", "%s. %s", 2386315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis ss.str().c_str(), validation_error_map[VALIDATION_ERROR_184001ca]); 2387055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski } 2388055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski 2389055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski // Validate aspect bits and formats for depth/stencil images 239016769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton if (FormatIsDepthOrStencil(src_format) || FormatIsDepthOrStencil(dst_format)) { 2391055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski if (src_format != dst_format) { 2392055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski std::stringstream ss; 2393055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski ss << "vkCmdBlitImage: If one of srcImage and dstImage images has a format of depth, stencil or depth " 2394055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski << "stencil, the other one must have exactly the same format. " 2395055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski << "Source format is " << string_VkFormat(src_format) << " Destination format is " 2396055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski << string_VkFormat(dst_format); 2397055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 2398315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_184001ce, "IMAGE", "%s. %s", 2399315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis ss.str().c_str(), validation_error_map[VALIDATION_ERROR_184001ce]); 2400055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski } 2401055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski 240243a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton#if 0 // TODO: Cannot find VU statements or spec language for these in CmdBlitImage. Verify or remove. 2403055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski for (uint32_t i = 0; i < regionCount; i++) { 2404055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski VkImageAspectFlags srcAspect = pRegions[i].srcSubresource.aspectMask; 2405055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski 240616769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton if (FormatIsDepthAndStencil(src_format)) { 2407055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski if ((srcAspect != VK_IMAGE_ASPECT_DEPTH_BIT) && (srcAspect != VK_IMAGE_ASPECT_STENCIL_BIT)) { 2408055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski std::stringstream ss; 2409055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski ss << "vkCmdBlitImage: Combination depth/stencil image formats must have only one of " 2410055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski "VK_IMAGE_ASPECT_DEPTH_BIT " 2411055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski << "and VK_IMAGE_ASPECT_STENCIL_BIT set in srcImage and dstImage"; 2412055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 24139b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(cb_node->commandBuffer), __LINE__, DRAWSTATE_INVALID_IMAGE_ASPECT, "IMAGE", 24149b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "%s", ss.str().c_str()); 2415055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski } 241616769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton } else if (FormatIsStencilOnly(src_format)) { 2417055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski if (srcAspect != VK_IMAGE_ASPECT_STENCIL_BIT) { 2418055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski std::stringstream ss; 2419055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski ss << "vkCmdBlitImage: Stencil-only image formats must have only the VK_IMAGE_ASPECT_STENCIL_BIT " 2420055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski << "set in both the srcImage and dstImage"; 2421055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 24229b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(cb_node->commandBuffer), __LINE__, DRAWSTATE_INVALID_IMAGE_ASPECT, "IMAGE", 24239b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "%s", ss.str().c_str()); 2424055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski } 242516769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton } else if (FormatIsDepthOnly(src_format)) { 2426055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski if (srcAspect != VK_IMAGE_ASPECT_DEPTH_BIT) { 2427055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski std::stringstream ss; 2428055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski ss << "vkCmdBlitImage: Depth-only image formats must have only the VK_IMAGE_ASPECT_DEPTH " 2429055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski << "set in both the srcImage and dstImage"; 2430055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 24319b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(cb_node->commandBuffer), __LINE__, DRAWSTATE_INVALID_IMAGE_ASPECT, "IMAGE", 24329b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "%s", ss.str().c_str()); 2433055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski } 2434055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski } 2435055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski } 243643a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton#endif 243743a02ff3ea4bf0a6d308abc05dd5f4346bc13311Dave Houlton } // Depth/Stencil 2438055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski 2439055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski // Validate filter 244016769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton if (FormatIsDepthOrStencil(src_format) && (filter != VK_FILTER_NEAREST)) { 2441055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski std::stringstream ss; 2442055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski ss << "vkCmdBlitImage: If the format of srcImage is a depth, stencil, or depth stencil " 2443055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski << "then filter must be VK_FILTER_NEAREST."; 2444055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 2445315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_184001d0, "IMAGE", "%s. %s", 2446315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis ss.str().c_str(), validation_error_map[VALIDATION_ERROR_184001d0]); 2447055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski } 244860568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski } else { 244960568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski assert(0); 245060568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski } 245160568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski return skip; 245260568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski} 245360568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski 2454e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlisvoid PreCallRecordCmdBlitImage(layer_data *device_data, GLOBAL_CB_NODE *cb_node, IMAGE_STATE *src_image_state, 2455e40189d4deab674240cd9baf4c063bab4567c212Tobin Ehlis IMAGE_STATE *dst_image_state) { 245660568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski // Update bindings between images and cmd buffer 245760568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski AddCommandBufferBindingImage(device_data, cb_node, src_image_state); 245860568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski AddCommandBufferBindingImage(device_data, cb_node, dst_image_state); 245960568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski 246060568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski std::function<bool()> function = [=]() { return ValidateImageMemoryIsValid(device_data, src_image_state, "vkCmdBlitImage()"); }; 246160568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski cb_node->validate_functions.push_back(function); 246260568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski function = [=]() { 246360568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski SetImageMemoryValid(device_data, dst_image_state, true); 246460568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski return false; 246560568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski }; 246660568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski cb_node->validate_functions.push_back(function); 24679a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis core_validation::UpdateCmdBufferLastCmd(cb_node, CMD_BLITIMAGE); 246860568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski} 246960568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski 247051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour// This validates that the initial layout specified in the command buffer for 247151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour// the IMAGE is the same 247251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour// as the global IMAGE layout 2473440bdd357701497c3442e3515f12ac1cfffc180aTony Barbourbool ValidateCmdBufImageLayouts(layer_data *device_data, GLOBAL_CB_NODE *pCB, 2474440bdd357701497c3442e3515f12ac1cfffc180aTony Barbour std::unordered_map<ImageSubresourcePair, IMAGE_LAYOUT_NODE> &imageLayoutMap) { 247590e629846621a0d870212dc0cebfbc83431cc5b8Mark Lobodzinski bool skip = false; 247651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour const debug_report_data *report_data = core_validation::GetReportData(device_data); 2477788ff59d81fc816f451414dcf2a9d6c29456ff63Mark Lobodzinski for (auto cb_image_data : pCB->imageLayoutMap) { 2478788ff59d81fc816f451414dcf2a9d6c29456ff63Mark Lobodzinski VkImageLayout imageLayout; 247951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 2480521b2f3957b3b31aeb2dbcc7529b54e06c9dc9ecJeremy Hayes if (FindLayout(imageLayoutMap, cb_image_data.first, imageLayout)) { 2481788ff59d81fc816f451414dcf2a9d6c29456ff63Mark Lobodzinski if (cb_image_data.second.initialLayout == VK_IMAGE_LAYOUT_UNDEFINED) { 2482788ff59d81fc816f451414dcf2a9d6c29456ff63Mark Lobodzinski // TODO: Set memory invalid which is in mem_tracker currently 2483788ff59d81fc816f451414dcf2a9d6c29456ff63Mark Lobodzinski } else if (imageLayout != cb_image_data.second.initialLayout) { 2484788ff59d81fc816f451414dcf2a9d6c29456ff63Mark Lobodzinski if (cb_image_data.first.hasSubresource) { 24859b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 24869b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS", 24879b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "Cannot submit cmd buffer using image (0x%" PRIx64 24889b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus ") [sub-resource: aspectMask 0x%X array layer %u, mip level %u], " 24899b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "with layout %s when first use is %s.", 24909b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(cb_image_data.first.image), cb_image_data.first.subresource.aspectMask, 24919b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus cb_image_data.first.subresource.arrayLayer, cb_image_data.first.subresource.mipLevel, 24929b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus string_VkImageLayout(imageLayout), string_VkImageLayout(cb_image_data.second.initialLayout)); 2493788ff59d81fc816f451414dcf2a9d6c29456ff63Mark Lobodzinski } else { 24949b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 24959b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS", 24969b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "Cannot submit cmd buffer using image (0x%" PRIx64 24979b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus ") with layout %s when " 24989b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "first use is %s.", 24999b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(cb_image_data.first.image), string_VkImageLayout(imageLayout), 25009b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus string_VkImageLayout(cb_image_data.second.initialLayout)); 2501788ff59d81fc816f451414dcf2a9d6c29456ff63Mark Lobodzinski } 2502788ff59d81fc816f451414dcf2a9d6c29456ff63Mark Lobodzinski } 250351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour SetLayout(imageLayoutMap, cb_image_data.first, cb_image_data.second.layout); 2504788ff59d81fc816f451414dcf2a9d6c29456ff63Mark Lobodzinski } 2505788ff59d81fc816f451414dcf2a9d6c29456ff63Mark Lobodzinski } 250690e629846621a0d870212dc0cebfbc83431cc5b8Mark Lobodzinski return skip; 2507788ff59d81fc816f451414dcf2a9d6c29456ff63Mark Lobodzinski} 2508940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski 250951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbourvoid UpdateCmdBufImageLayouts(layer_data *device_data, GLOBAL_CB_NODE *pCB) { 251051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour for (auto cb_image_data : pCB->imageLayoutMap) { 251151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour VkImageLayout imageLayout; 251251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour FindGlobalLayout(device_data, cb_image_data.first, imageLayout); 251351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour SetGlobalLayout(device_data, cb_image_data.first, cb_image_data.second.layout); 251451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 251551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour} 251651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 2517940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski// Print readable FlagBits in FlagMask 2518940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinskistatic std::string string_VkAccessFlags(VkAccessFlags accessMask) { 2519940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski std::string result; 2520940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski std::string separator; 2521940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski 2522940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski if (accessMask == 0) { 2523940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski result = "[None]"; 2524940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski } else { 2525940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski result = "["; 2526940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski for (auto i = 0; i < 32; i++) { 2527940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski if (accessMask & (1 << i)) { 2528940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski result = result + separator + string_VkAccessFlagBits((VkAccessFlagBits)(1 << i)); 2529940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski separator = " | "; 2530940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski } 2531940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski } 2532940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski result = result + "]"; 2533940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski } 2534940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski return result; 2535940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski} 2536940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski 25378fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski// AccessFlags MUST have 'required_bit' set, and may have one or more of 'optional_bits' set. If required_bit is zero, accessMask 25388fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski// must have at least one of 'optional_bits' set 2539940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski// TODO: Add tracking to ensure that at least one barrier has been set for these layout transitions 25408fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinskistatic bool ValidateMaskBits(core_validation::layer_data *device_data, VkCommandBuffer cmdBuffer, const VkAccessFlags &accessMask, 25418fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski const VkImageLayout &layout, VkAccessFlags required_bit, VkAccessFlags optional_bits, 25428fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski const char *type) { 25438fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski const debug_report_data *report_data = core_validation::GetReportData(device_data); 25448fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski bool skip = false; 2545940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski 2546940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski if ((accessMask & required_bit) || (!required_bit && (accessMask & optional_bits))) { 2547940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski if (accessMask & ~(required_bit | optional_bits)) { 2548940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski // TODO: Verify against Valid Use 2549fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 25509b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(cmdBuffer), __LINE__, DRAWSTATE_INVALID_BARRIER, "DS", 25518fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski "Additional bits in %s accessMask 0x%X %s are specified when layout is %s.", type, accessMask, 25528fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski string_VkAccessFlags(accessMask).c_str(), string_VkImageLayout(layout)); 2553940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski } 2554940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski } else { 2555940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski if (!required_bit) { 2556fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 25579b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(cmdBuffer), __LINE__, DRAWSTATE_INVALID_BARRIER, "DS", 25588fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski "%s AccessMask %d %s must contain at least one of access bits %d " 25598fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski "%s when layout is %s, unless the app has previously added a " 25608fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski "barrier for this transition.", 25618fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski type, accessMask, string_VkAccessFlags(accessMask).c_str(), optional_bits, 25628fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski string_VkAccessFlags(optional_bits).c_str(), string_VkImageLayout(layout)); 2563940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski } else { 2564940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski std::string opt_bits; 2565940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski if (optional_bits != 0) { 2566940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski std::stringstream ss; 2567940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski ss << optional_bits; 2568940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski opt_bits = "and may have optional bits " + ss.str() + ' ' + string_VkAccessFlags(optional_bits); 2569940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski } 2570fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 25719b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(cmdBuffer), __LINE__, DRAWSTATE_INVALID_BARRIER, "DS", 25728fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski "%s AccessMask %d %s must have required access bit %d %s %s when " 25738fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski "layout is %s, unless the app has previously added a barrier for " 25748fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski "this transition.", 25758fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski type, accessMask, string_VkAccessFlags(accessMask).c_str(), required_bit, 25768fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski string_VkAccessFlags(required_bit).c_str(), opt_bits.c_str(), string_VkImageLayout(layout)); 2577940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski } 2578940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski } 25798fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski return skip; 2580940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski} 2581940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski 25828fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinskibool ValidateMaskBitsFromLayouts(core_validation::layer_data *device_data, VkCommandBuffer cmdBuffer, 25838fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski const VkAccessFlags &accessMask, const VkImageLayout &layout, const char *type) { 25848fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski const debug_report_data *report_data = core_validation::GetReportData(device_data); 2585940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski 25868fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski bool skip = false; 2587940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski switch (layout) { 25888fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: { 25898fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski skip |= ValidateMaskBits(device_data, cmdBuffer, accessMask, layout, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, 25908fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, type); 25918fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski break; 2592940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski } 25938fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: { 25948fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski skip |= ValidateMaskBits(device_data, cmdBuffer, accessMask, layout, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, 25958fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, type); 25968fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski break; 25978fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski } 25988fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: { 25998fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski skip |= ValidateMaskBits(device_data, cmdBuffer, accessMask, layout, VK_ACCESS_TRANSFER_WRITE_BIT, 0, type); 26008fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski break; 26018fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski } 26028fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL: { 26038fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski skip |= ValidateMaskBits( 26048fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski device_data, cmdBuffer, accessMask, layout, 0, 26058fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, 26068fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski type); 26078fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski break; 26088fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski } 26098fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: { 26108fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski skip |= ValidateMaskBits(device_data, cmdBuffer, accessMask, layout, 0, 26118fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski VK_ACCESS_INPUT_ATTACHMENT_READ_BIT | VK_ACCESS_SHADER_READ_BIT, type); 26128fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski break; 26138fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski } 26148fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: { 26158fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski skip |= ValidateMaskBits(device_data, cmdBuffer, accessMask, layout, VK_ACCESS_TRANSFER_READ_BIT, 0, type); 26168fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski break; 26178fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski } 26188fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski case VK_IMAGE_LAYOUT_UNDEFINED: { 26198fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski if (accessMask != 0) { 26208fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski // TODO: Verify against Valid Use section spec 2621fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 26229b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(cmdBuffer), __LINE__, DRAWSTATE_INVALID_BARRIER, "DS", 26238fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski "Additional bits in %s accessMask 0x%X %s are specified when layout is %s.", type, accessMask, 26248fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski string_VkAccessFlags(accessMask).c_str(), string_VkImageLayout(layout)); 26258fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski } 26268fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski break; 26278fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski } 26286e3442c40be4c735b830775a753bb449c331e15dChris Forbes case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR: 2629cf2ce8673669ca1111e333bdea272c4dd57cb5c2Dave Houlton // Notes: QueuePresentKHR performs automatic visibility operations, 2630cf2ce8673669ca1111e333bdea272c4dd57cb5c2Dave Houlton // so the app is /NOT/ required to include VK_ACCESS_MEMORY_READ_BIT 2631cf2ce8673669ca1111e333bdea272c4dd57cb5c2Dave Houlton // when transitioning to this layout. 2632cf2ce8673669ca1111e333bdea272c4dd57cb5c2Dave Houlton // 2633cf2ce8673669ca1111e333bdea272c4dd57cb5c2Dave Houlton // When transitioning /from/ this layout, the application needs to 2634cf2ce8673669ca1111e333bdea272c4dd57cb5c2Dave Houlton // avoid only a WAR hazard -- any writes need to be ordered after 2635cf2ce8673669ca1111e333bdea272c4dd57cb5c2Dave Houlton // the PE's reads. There is no need for a memory dependency for this 2636cf2ce8673669ca1111e333bdea272c4dd57cb5c2Dave Houlton // case. 26376084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski // Intentionally fall through 26386084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski 26396084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski case VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR: 26406084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski // Todo -- shouldn't be valid unless extension is enabled 26416084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski // Intentionally fall through 26426e3442c40be4c735b830775a753bb449c331e15dChris Forbes 26438fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski case VK_IMAGE_LAYOUT_GENERAL: 26448fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski default: { break; } 2645940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski } 26468fefffdd7f4b8a91b65b50dedb70ad4be159e998Mark Lobodzinski return skip; 2647940eb407cf288675f9bc7552dca723cd7028edacMark Lobodzinski} 2648d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski 2649d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski// ValidateLayoutVsAttachmentDescription is a general function where we can validate various state associated with the 2650374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski// VkAttachmentDescription structs that are used by the sub-passes of a renderpass. Initial check is to make sure that READ_ONLY 2651374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski// layout attachments don't have CLEAR as their loadOp. 2652d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinskibool ValidateLayoutVsAttachmentDescription(const debug_report_data *report_data, const VkImageLayout first_layout, 2653374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski const uint32_t attachment, const VkAttachmentDescription &attachment_description) { 2654374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski bool skip = false; 2655d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski // Verify that initial loadOp on READ_ONLY attachments is not CLEAR 2656d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski if (attachment_description.loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR) { 2657d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski if ((first_layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL) || 2658d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski (first_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)) { 26595b9ab1fb8720c30edfbe8dd974e2364425471ad5Mark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 2660315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_12200688, "DS", "Cannot clear attachment %d with invalid first layout %s. %s", 2661315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis attachment, string_VkImageLayout(first_layout), validation_error_map[VALIDATION_ERROR_12200688]); 2662d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski } 2663d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski } 2664374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski return skip; 2665d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski} 2666d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski 2667374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinskibool ValidateLayouts(core_validation::layer_data *device_data, VkDevice device, const VkRenderPassCreateInfo *pCreateInfo) { 2668374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski const debug_report_data *report_data = core_validation::GetReportData(device_data); 2669d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski bool skip = false; 2670d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski 2671d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski // Track when we're observing the first use of an attachment 2672d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski std::vector<bool> attach_first_use(pCreateInfo->attachmentCount, true); 2673d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) { 2674d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i]; 2675ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton 2676ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton // Check input attachments first, so we can detect first-use-as-input for VU #00349 2677ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) { 2678ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton auto attach_index = subpass.pInputAttachments[j].attachment; 2679ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton if (attach_index == VK_ATTACHMENT_UNUSED) continue; 2680ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton 2681ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton switch (subpass.pInputAttachments[j].layout) { 2682ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL: 2683ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: 2684ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton // These are ideal. 2685ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton break; 2686ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton 2687ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton case VK_IMAGE_LAYOUT_GENERAL: 2688ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton // May not be optimal. TODO: reconsider this warning based on other constraints. 2689ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton skip |= log_msg(report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, 2690ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS", 2691ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton "Layout for input attachment is GENERAL but should be READ_ONLY_OPTIMAL."); 2692ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton break; 2693ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton 2694ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton default: 2695ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton // No other layouts are acceptable 2696ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 2697ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS", 2698ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton "Layout for input attachment is %s but can only be READ_ONLY_OPTIMAL or GENERAL.", 2699ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton string_VkImageLayout(subpass.pInputAttachments[j].layout)); 2700ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton } 2701ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton 2702ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton VkImageLayout layout = subpass.pInputAttachments[j].layout; 2703ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton bool found_layout_mismatch = subpass.pDepthStencilAttachment && 2704ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton subpass.pDepthStencilAttachment->attachment == attach_index && 2705ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton subpass.pDepthStencilAttachment->layout != layout; 2706ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton for (uint32_t c = 0; !found_layout_mismatch && c < subpass.colorAttachmentCount; ++c) { 2707ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton found_layout_mismatch = 2708ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton (subpass.pColorAttachments[c].attachment == attach_index && subpass.pColorAttachments[c].layout != layout); 2709ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton } 2710ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton if (found_layout_mismatch) { 2711ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton skip |= log_msg( 2712ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 2713315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_140006ae, "DS", 2714ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton "CreateRenderPass: Subpass %u pInputAttachments[%u] (%u) has layout %u, but is also used as a depth/color " 2715ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton "attachment with a different layout. %s", 2716315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis i, j, attach_index, layout, validation_error_map[VALIDATION_ERROR_140006ae]); 2717ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton } 2718ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton 2719ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton if (attach_first_use[attach_index]) { 2720ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton skip |= ValidateLayoutVsAttachmentDescription(report_data, subpass.pInputAttachments[j].layout, attach_index, 2721ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton pCreateInfo->pAttachments[attach_index]); 2722ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton 2723ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton bool used_as_depth = 2724ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton (subpass.pDepthStencilAttachment != NULL && subpass.pDepthStencilAttachment->attachment == attach_index); 2725ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton bool used_as_color = false; 2726ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton for (uint32_t k = 0; !used_as_depth && !used_as_color && k < subpass.colorAttachmentCount; ++k) { 2727ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton used_as_color = (subpass.pColorAttachments[k].attachment == attach_index); 2728ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton } 2729ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton if (!used_as_depth && !used_as_color && 2730ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton pCreateInfo->pAttachments[attach_index].loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR) { 2731ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton skip |= log_msg( 2732ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 2733315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_1400069c, "DS", 2734ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton "CreateRenderPass: attachment %u is first used as an input attachment in subpass %u with loadOp=CLEAR. %s", 2735315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis attach_index, attach_index, validation_error_map[VALIDATION_ERROR_1400069c]); 2736ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton } 2737ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton } 2738ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton attach_first_use[attach_index] = false; 2739ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton } 2740d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) { 2741d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski auto attach_index = subpass.pColorAttachments[j].attachment; 2742d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski if (attach_index == VK_ATTACHMENT_UNUSED) continue; 2743d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski 274487a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis // TODO: Need a way to validate shared presentable images here, currently just allowing 274587a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis // VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR 274687a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis // as an acceptable layout, but need to make sure shared presentable images ONLY use that layout 2747d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski switch (subpass.pColorAttachments[j].layout) { 2748374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: 2749374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski // This is ideal. 275087a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis case VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR: 275187a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis // TODO: See note above, just assuming that attachment is shared presentable and allowing this for now. 2752374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski break; 2753d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski 2754374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski case VK_IMAGE_LAYOUT_GENERAL: 2755374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski // May not be optimal; TODO: reconsider this warning based on other constraints? 2756374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, 2757374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS", 2758374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski "Layout for color attachment is GENERAL but should be COLOR_ATTACHMENT_OPTIMAL."); 2759374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski break; 2760374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski 2761374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski default: 2762374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 2763374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS", 2764374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski "Layout for color attachment is %s but can only be COLOR_ATTACHMENT_OPTIMAL or GENERAL.", 2765374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski string_VkImageLayout(subpass.pColorAttachments[j].layout)); 2766d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski } 2767d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski 2768d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski if (attach_first_use[attach_index]) { 2769374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski skip |= ValidateLayoutVsAttachmentDescription(report_data, subpass.pColorAttachments[j].layout, attach_index, 2770374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski pCreateInfo->pAttachments[attach_index]); 2771d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski } 2772d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski attach_first_use[attach_index] = false; 2773d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski } 2774d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski if (subpass.pDepthStencilAttachment && subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) { 2775d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski switch (subpass.pDepthStencilAttachment->layout) { 2776374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: 2777374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL: 2778374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski // These are ideal. 2779374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski break; 2780374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski 2781374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski case VK_IMAGE_LAYOUT_GENERAL: 2782374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski // May not be optimal; TODO: reconsider this warning based on other constraints? GENERAL can be better than 2783374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski // doing a bunch of transitions. 2784374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, 2785374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS", 2786374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski "GENERAL layout for depth attachment may not give optimal performance."); 2787374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski break; 2788374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski 2789374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski default: 2790374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski // No other layouts are acceptable 2791374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 2792374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS", 2793374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski "Layout for depth attachment is %s but can only be DEPTH_STENCIL_ATTACHMENT_OPTIMAL, " 2794374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski "DEPTH_STENCIL_READ_ONLY_OPTIMAL or GENERAL.", 2795374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski string_VkImageLayout(subpass.pDepthStencilAttachment->layout)); 2796d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski } 2797d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski 2798d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski auto attach_index = subpass.pDepthStencilAttachment->attachment; 2799d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski if (attach_first_use[attach_index]) { 2800374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski skip |= ValidateLayoutVsAttachmentDescription(report_data, subpass.pDepthStencilAttachment->layout, attach_index, 2801374d6151f9db5d62891ffdbe833bcbb51848db6bMark Lobodzinski pCreateInfo->pAttachments[attach_index]); 2802d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski } 2803d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski attach_first_use[attach_index] = false; 2804d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski } 2805d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski } 2806d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski return skip; 2807d76960c655c53f47aaf2e16538ea0c40e6d527ecMark Lobodzinski} 2808c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski 2809c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski// For any image objects that overlap mapped memory, verify that their layouts are PREINIT or GENERAL 281009cd2c76808f1485206baeda9864f7ed907d7e05Mark Lobodzinskibool ValidateMapImageLayouts(core_validation::layer_data *device_data, VkDevice device, DEVICE_MEM_INFO const *mem_info, 281109cd2c76808f1485206baeda9864f7ed907d7e05Mark Lobodzinski VkDeviceSize offset, VkDeviceSize end_offset) { 281209cd2c76808f1485206baeda9864f7ed907d7e05Mark Lobodzinski const debug_report_data *report_data = core_validation::GetReportData(device_data); 281309cd2c76808f1485206baeda9864f7ed907d7e05Mark Lobodzinski bool skip = false; 281409cd2c76808f1485206baeda9864f7ed907d7e05Mark Lobodzinski // Iterate over all bound image ranges and verify that for any that overlap the map ranges, the layouts are 281509cd2c76808f1485206baeda9864f7ed907d7e05Mark Lobodzinski // VK_IMAGE_LAYOUT_PREINITIALIZED or VK_IMAGE_LAYOUT_GENERAL 2816c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski // TODO : This can be optimized if we store ranges based on starting address and early exit when we pass our range 2817c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski for (auto image_handle : mem_info->bound_images) { 2818c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski auto img_it = mem_info->bound_ranges.find(image_handle); 2819c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski if (img_it != mem_info->bound_ranges.end()) { 282009cd2c76808f1485206baeda9864f7ed907d7e05Mark Lobodzinski if (rangesIntersect(device_data, &img_it->second, offset, end_offset)) { 2821c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski std::vector<VkImageLayout> layouts; 282209cd2c76808f1485206baeda9864f7ed907d7e05Mark Lobodzinski if (FindLayouts(device_data, VkImage(image_handle), layouts)) { 2823c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski for (auto layout : layouts) { 2824c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski if (layout != VK_IMAGE_LAYOUT_PREINITIALIZED && layout != VK_IMAGE_LAYOUT_GENERAL) { 28259b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus skip |= 28269b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 28279b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(mem_info->mem), __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS", 28289b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "Mapping an image with layout %s can result in undefined behavior if this memory is " 28299b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "used by the device. Only GENERAL or PREINITIALIZED should be used.", 28309b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus string_VkImageLayout(layout)); 2831c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski } 2832c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski } 2833c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski } 2834c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski } 2835c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski } 2836c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski } 283709cd2c76808f1485206baeda9864f7ed907d7e05Mark Lobodzinski return skip; 2838c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski} 28393683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski 28403683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski// Helper function to validate correct usage bits set for buffers or images. Verify that (actual & desired) flags != 0 or, if strict 28413683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski// is true, verify that (actual & desired) flags == desired 2842abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinskistatic bool validate_usage_flags(layer_data *device_data, VkFlags actual, VkFlags desired, VkBool32 strict, uint64_t obj_handle, 28437a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski VulkanObjectType obj_type, int32_t const msgCode, char const *func_name, char const *usage_str) { 2844abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinski const debug_report_data *report_data = core_validation::GetReportData(device_data); 28453683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski 28463683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski bool correct_usage = false; 2847abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinski bool skip = false; 28487a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski const char *type_str = object_string[obj_type]; 28493683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski if (strict) { 28503683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski correct_usage = ((actual & desired) == desired); 28513683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski } else { 28523683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski correct_usage = ((actual & desired) != 0); 28533683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski } 28543683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski if (!correct_usage) { 28553683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski if (msgCode == -1) { 28563683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski // TODO: Fix callers with msgCode == -1 to use correct validation checks. 285702a510945ff39f3d9e486e456aca5bfa6ea0c43aMark Lobodzinski skip = log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, get_debug_report_enum[obj_type], obj_handle, __LINE__, 28587a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski MEMTRACK_INVALID_USAGE_FLAG, "MEM", 28597a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski "Invalid usage flag for %s 0x%" PRIxLEAST64 28607a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski " used by %s. In this case, %s should have %s set during creation.", 28617a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski type_str, obj_handle, func_name, type_str, usage_str); 28623683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski } else { 28633683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski const char *valid_usage = (msgCode == -1) ? "" : validation_error_map[msgCode]; 28647a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski skip = log_msg( 286502a510945ff39f3d9e486e456aca5bfa6ea0c43aMark Lobodzinski report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, get_debug_report_enum[obj_type], obj_handle, __LINE__, msgCode, "MEM", 28667a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski "Invalid usage flag for %s 0x%" PRIxLEAST64 " used by %s. In this case, %s should have %s set during creation. %s", 28677a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski type_str, obj_handle, func_name, type_str, usage_str, valid_usage); 28683683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski } 28693683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski } 2870abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinski return skip; 28713683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski} 28723683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski 28733683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski// Helper function to validate usage flags for buffers. For given buffer_state send actual vs. desired usage off to helper above 28743683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski// where an error will be flagged if usage is not correct 28750bcfcca3af64ac0214112949aa68496914b8d7a9Chris Forbesbool ValidateImageUsageFlags(layer_data *device_data, IMAGE_STATE const *image_state, VkFlags desired, bool strict, 28763683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski int32_t const msgCode, char const *func_name, char const *usage_string) { 28779b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus return validate_usage_flags(device_data, image_state->createInfo.usage, desired, strict, HandleToUint64(image_state->image), 28789b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus kVulkanObjectTypeImage, msgCode, func_name, usage_string); 28793683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski} 28803683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski 28813683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski// Helper function to validate usage flags for buffers. For given buffer_state send actual vs. desired usage off to helper above 28823683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski// where an error will be flagged if usage is not correct 28830bcfcca3af64ac0214112949aa68496914b8d7a9Chris Forbesbool ValidateBufferUsageFlags(layer_data *device_data, BUFFER_STATE const *buffer_state, VkFlags desired, bool strict, 28843683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski int32_t const msgCode, char const *func_name, char const *usage_string) { 28859b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus return validate_usage_flags(device_data, buffer_state->createInfo.usage, desired, strict, HandleToUint64(buffer_state->buffer), 28869b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus kVulkanObjectTypeBuffer, msgCode, func_name, usage_string); 28873683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski} 28883683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski 2889abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinskibool PreCallValidateCreateBuffer(layer_data *device_data, const VkBufferCreateInfo *pCreateInfo) { 28903683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski bool skip = false; 289101363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski const debug_report_data *report_data = core_validation::GetReportData(device_data); 289201363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski 2893315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis // TODO: Add check for VALIDATION_ERROR_1ec0071e 2894315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis // TODO: Add check for VALIDATION_ERROR_01400728 2895315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis // TODO: Add check for VALIDATION_ERROR_0140072a 2896315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis // TODO: Add check for VALIDATION_ERROR_0140072c 289701363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski 289801363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski if ((pCreateInfo->flags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT) && (!GetEnabledFeatures(device_data)->sparseBinding)) { 289901363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 2900315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_01400726, "DS", 290101363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski "vkCreateBuffer(): the sparseBinding device feature is disabled: Buffers cannot be created with the " 290201363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski "VK_BUFFER_CREATE_SPARSE_BINDING_BIT set. %s", 2903315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_01400726]); 290401363bf3d84ba5841a6870b40c041c2f53d76583Mark Lobodzinski } 2905f575247dabffb70e4de1a6f9522db3f09a55492eMark Lobodzinski 2906f575247dabffb70e4de1a6f9522db3f09a55492eMark Lobodzinski if ((pCreateInfo->flags & VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT) && (!GetEnabledFeatures(device_data)->sparseResidencyBuffer)) { 2907f575247dabffb70e4de1a6f9522db3f09a55492eMark Lobodzinski skip |= 2908f575247dabffb70e4de1a6f9522db3f09a55492eMark Lobodzinski log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 2909f575247dabffb70e4de1a6f9522db3f09a55492eMark Lobodzinski DRAWSTATE_INVALID_FEATURE, "DS", 2910f575247dabffb70e4de1a6f9522db3f09a55492eMark Lobodzinski "vkCreateBuffer(): the sparseResidencyBuffer device feature is disabled: Buffers cannot be created with the " 2911f575247dabffb70e4de1a6f9522db3f09a55492eMark Lobodzinski "VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT set."); 2912f575247dabffb70e4de1a6f9522db3f09a55492eMark Lobodzinski } 29137e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski 29147e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski if ((pCreateInfo->flags & VK_BUFFER_CREATE_SPARSE_ALIASED_BIT) && (!GetEnabledFeatures(device_data)->sparseResidencyAliased)) { 29157e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski skip |= 29167e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 29177e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski DRAWSTATE_INVALID_FEATURE, "DS", 29187e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski "vkCreateBuffer(): the sparseResidencyAliased device feature is disabled: Buffers cannot be created with the " 29197e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski "VK_BUFFER_CREATE_SPARSE_ALIASED_BIT set."); 29207e105b26dcb40aff4f9776b8f5b5f1326aa1e36cMark Lobodzinski } 29213683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski return skip; 29223683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski} 29233683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski 29243683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinskivoid PostCallRecordCreateBuffer(layer_data *device_data, const VkBufferCreateInfo *pCreateInfo, VkBuffer *pBuffer) { 29253683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski // TODO : This doesn't create deep copy of pQueueFamilyIndices so need to fix that if/when we want that data to be valid 29263683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski GetBufferMap(device_data) 29273683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski ->insert(std::make_pair(*pBuffer, std::unique_ptr<BUFFER_STATE>(new BUFFER_STATE(*pBuffer, pCreateInfo)))); 29283683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski} 29293683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski 2930abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinskibool PreCallValidateCreateBufferView(layer_data *device_data, const VkBufferViewCreateInfo *pCreateInfo) { 2931abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinski bool skip = false; 2932abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinski BUFFER_STATE *buffer_state = GetBufferState(device_data, pCreateInfo->buffer); 29333683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski // If this isn't a sparse buffer, it needs to have memory backing it at CreateBufferView time 29343683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski if (buffer_state) { 2935315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateMemoryIsBoundToBuffer(device_data, buffer_state, "vkCreateBufferView()", VALIDATION_ERROR_01a0074e); 29363683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski // In order to create a valid buffer view, the buffer must have been created with at least one of the following flags: 29373683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski // UNIFORM_TEXEL_BUFFER_BIT or STORAGE_TEXEL_BUFFER_BIT 2938abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinski skip |= ValidateBufferUsageFlags( 2939abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinski device_data, buffer_state, VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT, false, 2940315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_01a00748, "vkCreateBufferView()", "VK_BUFFER_USAGE_[STORAGE|UNIFORM]_TEXEL_BUFFER_BIT"); 29413683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski } 2942abfd2f0c07bb8ff00d48dbe6127819eaf839c9aeMark Lobodzinski return skip; 29433683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski} 29443683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski 29453683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinskivoid PostCallRecordCreateBufferView(layer_data *device_data, const VkBufferViewCreateInfo *pCreateInfo, VkBufferView *pView) { 29463683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski (*GetBufferViewMap(device_data))[*pView] = std::unique_ptr<BUFFER_VIEW_STATE>(new BUFFER_VIEW_STATE(*pView, pCreateInfo)); 29473683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski} 29481c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski 29491c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski// For the given format verify that the aspect masks make sense 29501c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinskibool ValidateImageAspectMask(layer_data *device_data, VkImage image, VkFormat format, VkImageAspectFlags aspect_mask, 29511c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski const char *func_name) { 29521c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski const debug_report_data *report_data = core_validation::GetReportData(device_data); 29531c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski bool skip = false; 295416769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton if (FormatIsColor(format)) { 29551c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski if ((aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT) != VK_IMAGE_ASPECT_COLOR_BIT) { 29569b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 2957315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(image), __LINE__, VALIDATION_ERROR_0a400c01, "IMAGE", 29581c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski "%s: Color image formats must have the VK_IMAGE_ASPECT_COLOR_BIT set. %s", func_name, 2959315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_0a400c01]); 29601c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski } else if ((aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT) != aspect_mask) { 29619b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 2962315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(image), __LINE__, VALIDATION_ERROR_0a400c01, "IMAGE", 29631c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski "%s: Color image formats must have ONLY the VK_IMAGE_ASPECT_COLOR_BIT set. %s", func_name, 2964315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_0a400c01]); 29651c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski } 296616769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton } else if (FormatIsDepthAndStencil(format)) { 29671c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski if ((aspect_mask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) == 0) { 29689b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 2969315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(image), __LINE__, VALIDATION_ERROR_0a400c01, "IMAGE", 29701c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski "%s: Depth/stencil image formats must have " 29711c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski "at least one of VK_IMAGE_ASPECT_DEPTH_BIT " 29721c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski "and VK_IMAGE_ASPECT_STENCIL_BIT set. %s", 2973315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis func_name, validation_error_map[VALIDATION_ERROR_0a400c01]); 29741c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski } else if ((aspect_mask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) != aspect_mask) { 29759b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 2976315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(image), __LINE__, VALIDATION_ERROR_0a400c01, "IMAGE", 29771c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski "%s: Combination depth/stencil image formats can have only the VK_IMAGE_ASPECT_DEPTH_BIT and " 29781c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski "VK_IMAGE_ASPECT_STENCIL_BIT set. %s", 2979315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis func_name, validation_error_map[VALIDATION_ERROR_0a400c01]); 29801c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski } 298116769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton } else if (FormatIsDepthOnly(format)) { 29821c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski if ((aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) != VK_IMAGE_ASPECT_DEPTH_BIT) { 29839b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 2984315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(image), __LINE__, VALIDATION_ERROR_0a400c01, "IMAGE", 29851c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski "%s: Depth-only image formats must have the VK_IMAGE_ASPECT_DEPTH_BIT set. %s", func_name, 2986315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_0a400c01]); 29871c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski } else if ((aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) != aspect_mask) { 29889b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 2989315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(image), __LINE__, VALIDATION_ERROR_0a400c01, "IMAGE", 29901c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski "%s: Depth-only image formats can have only the VK_IMAGE_ASPECT_DEPTH_BIT set. %s", func_name, 2991315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_0a400c01]); 29921c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski } 299316769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton } else if (FormatIsStencilOnly(format)) { 29941c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski if ((aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT) != VK_IMAGE_ASPECT_STENCIL_BIT) { 29959b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 2996315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(image), __LINE__, VALIDATION_ERROR_0a400c01, "IMAGE", 29971c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski "%s: Stencil-only image formats must have the VK_IMAGE_ASPECT_STENCIL_BIT set. %s", func_name, 2998315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_0a400c01]); 29991c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski } else if ((aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT) != aspect_mask) { 30009b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 3001315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(image), __LINE__, VALIDATION_ERROR_0a400c01, "IMAGE", 30021c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski "%s: Stencil-only image formats can have only the VK_IMAGE_ASPECT_STENCIL_BIT set. %s", func_name, 3003315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_0a400c01]); 30041c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski } 30051c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski } 30061c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski return skip; 30071c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski} 30081c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski 3009dab32891b91206a5bef7a3929b781e44fc1b7268Petr Krausbool ValidateImageSubresourceRange(const layer_data *device_data, const IMAGE_STATE *image_state, const bool is_imageview_2d_array, 301023c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus const VkImageSubresourceRange &subresourceRange, const char *cmd_name, const char *param_name) { 30111c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski const debug_report_data *report_data = core_validation::GetReportData(device_data); 30121c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski bool skip = false; 301323c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus 301423c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus // Validate mip levels 301523c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus const auto image_mip_count = image_state->createInfo.mipLevels; 301623c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus 30171c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski if (subresourceRange.levelCount == 0) { 301823c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 3019315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(image_state->image), __LINE__, VALIDATION_ERROR_0a8007fc, "IMAGE", 3020315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis "%s: %s.levelCount is 0. %s", cmd_name, param_name, validation_error_map[VALIDATION_ERROR_0a8007fc]); 302123c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus } else if (subresourceRange.levelCount == VK_REMAINING_MIP_LEVELS) { 302223c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus // TODO: Not in the spec VUs. Probably missing -- KhronosGroup/Vulkan-Docs#416 302323c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus if (subresourceRange.baseMipLevel >= image_mip_count) { 302423c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 302523c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus HandleToUint64(image_state->image), __LINE__, DRAWSTATE_INVALID_IMAGE_SUBRANGE, "IMAGE", 302623c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus "%s: %s.baseMipLevel (= %" PRIu32 ") is greater or equal to the mip level count of the image (i.e. " 302723c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus "greater or equal to %" PRIu32 ").", 302823c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus cmd_name, param_name, subresourceRange.baseMipLevel, image_mip_count); 302923c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus } 303023c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus } else { 303123c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus const uint64_t necessary_mip_count = uint64_t{subresourceRange.baseMipLevel} + uint64_t{subresourceRange.levelCount}; 303223c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus 303323c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus if (necessary_mip_count > image_mip_count) { 303423c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 3035315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(image_state->image), __LINE__, VALIDATION_ERROR_0a8007fc, "IMAGE", 3036315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis "%s: %s.baseMipLevel + .levelCount (= %" PRIu32 " + %" PRIu32 " = %" PRIu64 3037315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis ") is greater than the " 303823c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus "mip level count of the image (i.e. greater than %" PRIu32 "). %s", 303923c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus cmd_name, param_name, subresourceRange.baseMipLevel, subresourceRange.levelCount, necessary_mip_count, 3040315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis image_mip_count, validation_error_map[VALIDATION_ERROR_0a8007fc]); 304123c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus } 30421c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski } 304323c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus 304423c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus // Validate array layers 3045dab32891b91206a5bef7a3929b781e44fc1b7268Petr Kraus bool is_khr_maintenance1 = GetDeviceExtensions(device_data)->vk_khr_maintenance1; 3046dab32891b91206a5bef7a3929b781e44fc1b7268Petr Kraus bool is_3D_to_2D_map = is_khr_maintenance1 && image_state->createInfo.imageType == VK_IMAGE_TYPE_3D && is_imageview_2d_array; 304723c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus 304823c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus const auto image_layer_count = is_3D_to_2D_map ? image_state->createInfo.extent.depth : image_state->createInfo.arrayLayers; 304923c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus const auto image_layer_count_var_name = is_3D_to_2D_map ? "extent.depth" : "arrayLayers"; 3050dab32891b91206a5bef7a3929b781e44fc1b7268Petr Kraus 3051dab32891b91206a5bef7a3929b781e44fc1b7268Petr Kraus const auto invalid_layer_code = 3052dab32891b91206a5bef7a3929b781e44fc1b7268Petr Kraus is_khr_maintenance1 ? (is_3D_to_2D_map ? VALIDATION_ERROR_0a800800 : VALIDATION_ERROR_0a800802) : VALIDATION_ERROR_0a8007fe; 305323c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus 30541c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski if (subresourceRange.layerCount == 0) { 305523c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 305623c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus HandleToUint64(image_state->image), __LINE__, invalid_layer_code, "IMAGE", "%s: %s.layerCount is 0. %s", 305723c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus cmd_name, param_name, validation_error_map[invalid_layer_code]); 305823c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus } else if (subresourceRange.layerCount == VK_REMAINING_ARRAY_LAYERS) { 305923c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus // TODO: Not in the spec VUs. Probably missing -- KhronosGroup/Vulkan-Docs#416 306023c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus if (subresourceRange.baseArrayLayer >= image_layer_count) { 306123c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 306223c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus HandleToUint64(image_state->image), __LINE__, DRAWSTATE_INVALID_IMAGE_SUBRANGE, "IMAGE", 306323c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus "%s: %s.baseArrayLayer (= %" PRIu32 ") is greater or equal to the %s of the image when it was created " 306423c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus "(i.e. greater or equal to %" PRIu32 ").", 306523c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus cmd_name, param_name, subresourceRange.baseArrayLayer, image_layer_count_var_name, image_layer_count); 306623c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus } 306723c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus } else { 306823c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus const uint64_t necessary_layer_count = uint64_t{subresourceRange.baseArrayLayer} + uint64_t{subresourceRange.layerCount}; 306923c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus 307023c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus if (necessary_layer_count > image_layer_count) { 307123c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus skip |= 307223c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 307323c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus HandleToUint64(image_state->image), __LINE__, invalid_layer_code, "IMAGE", 307423c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus "%s: %s.baseArrayLayer + .layerCount (= %" PRIu32 " + %" PRIu32 " = %" PRIu64 ") is greater than the " 307523c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus "%s of the image when it was created (i.e. greater than %" PRIu32 "). %s", 307623c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus cmd_name, param_name, subresourceRange.baseArrayLayer, subresourceRange.layerCount, necessary_layer_count, 307723c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus image_layer_count_var_name, image_layer_count, validation_error_map[invalid_layer_code]); 307823c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus } 30791c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski } 308023c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus 30811c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski return skip; 30821c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski} 30831c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski 30841c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinskibool PreCallValidateCreateImageView(layer_data *device_data, const VkImageViewCreateInfo *create_info) { 30851c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski const debug_report_data *report_data = core_validation::GetReportData(device_data); 30861c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski bool skip = false; 30871c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski IMAGE_STATE *image_state = GetImageState(device_data, create_info->image); 30881c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski if (image_state) { 30891c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski skip |= ValidateImageUsageFlags( 30901c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski device_data, image_state, 30911c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | 30921c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, 30931c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski false, -1, "vkCreateImageView()", 30941c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski "VK_IMAGE_USAGE_[SAMPLED|STORAGE|COLOR_ATTACHMENT|DEPTH_STENCIL_ATTACHMENT|INPUT_ATTACHMENT]_BIT"); 30951c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski // If this isn't a sparse image, it needs to have memory backing it at CreateImageView time 3096315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateMemoryIsBoundToImage(device_data, image_state, "vkCreateImageView()", VALIDATION_ERROR_0ac007f8); 30971c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski // Checks imported from image layer 3098dab32891b91206a5bef7a3929b781e44fc1b7268Petr Kraus skip |= ValidateImageSubresourceRange(device_data, image_state, create_info->viewType == VK_IMAGE_VIEW_TYPE_2D_ARRAY, 3099dab32891b91206a5bef7a3929b781e44fc1b7268Petr Kraus create_info->subresourceRange, "vkCreateImageView", "pCreateInfo->subresourceRange"); 31001c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski 31011c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski VkImageCreateFlags image_flags = image_state->createInfo.flags; 31021c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski VkFormat image_format = image_state->createInfo.format; 31031c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski VkFormat view_format = create_info->format; 31041c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski VkImageAspectFlags aspect_mask = create_info->subresourceRange.aspectMask; 31051c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski 31061c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski // Validate VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT state 31071c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski if (image_flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) { 31081c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski // Format MUST be compatible (in the same format compatibility class) as the format the image was created with 310916769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton if (FormatCompatibilityClass(image_format) != FormatCompatibilityClass(view_format)) { 31101c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski std::stringstream ss; 31111c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski ss << "vkCreateImageView(): ImageView format " << string_VkFormat(view_format) 31129b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus << " is not in the same format compatibility class as image (" << HandleToUint64(create_info->image) 31139b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus << ") format " << string_VkFormat(image_format) 31149b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus << ". Images created with the VK_IMAGE_CREATE_MUTABLE_FORMAT BIT " 31151c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski << "can support ImageViews with differing formats but they must be in the same compatibility class."; 3116fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 3117315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_0ac007f4, "IMAGE", "%s %s", ss.str().c_str(), 3118315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_0ac007f4]); 31191c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski } 31201c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski } else { 31211c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski // Format MUST be IDENTICAL to the format the image was created with 31221c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski if (image_format != view_format) { 31231c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski std::stringstream ss; 31241c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski ss << "vkCreateImageView() format " << string_VkFormat(view_format) << " differs from image " 31259b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus << HandleToUint64(create_info->image) << " format " << string_VkFormat(image_format) 31261c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski << ". Formats MUST be IDENTICAL unless VK_IMAGE_CREATE_MUTABLE_FORMAT BIT was set on image creation."; 3127fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 3128315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_0ac007f6, "IMAGE", "%s %s", ss.str().c_str(), 3129315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_0ac007f6]); 31301c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski } 31311c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski } 31321c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski 31331c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski // Validate correct image aspect bits for desired formats and format consistency 31341c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski skip |= ValidateImageAspectMask(device_data, image_state->image, image_format, aspect_mask, "vkCreateImageView()"); 31351c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski } 31361c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski return skip; 31371c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski} 31381c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski 3139d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinskivoid PostCallRecordCreateImageView(layer_data *device_data, const VkImageViewCreateInfo *create_info, VkImageView view) { 3140d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski auto image_view_map = GetImageViewMap(device_data); 3141d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski (*image_view_map)[view] = std::unique_ptr<IMAGE_VIEW_STATE>(new IMAGE_VIEW_STATE(view, create_info)); 3142d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski 3143d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski auto image_state = GetImageState(device_data, create_info->image); 3144e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton auto &sub_res_range = (*image_view_map)[view].get()->create_info.subresourceRange; 314595b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski sub_res_range.levelCount = ResolveRemainingLevels(&sub_res_range, image_state->createInfo.mipLevels); 314695b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski sub_res_range.layerCount = ResolveRemainingLayers(&sub_res_range, image_state->createInfo.arrayLayers); 31471c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski} 31486a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski 3149c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinskibool PreCallValidateCmdCopyBuffer(layer_data *device_data, GLOBAL_CB_NODE *cb_node, BUFFER_STATE *src_buffer_state, 3150c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski BUFFER_STATE *dst_buffer_state) { 3151c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski bool skip = false; 3152315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateMemoryIsBoundToBuffer(device_data, src_buffer_state, "vkCmdCopyBuffer()", VALIDATION_ERROR_18c000ee); 3153315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateMemoryIsBoundToBuffer(device_data, dst_buffer_state, "vkCmdCopyBuffer()", VALIDATION_ERROR_18c000f2); 3154c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski // Validate that SRC & DST buffers have correct usage flags set 3155315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateBufferUsageFlags(device_data, src_buffer_state, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, true, 3156315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_18c000ec, "vkCmdCopyBuffer()", "VK_BUFFER_USAGE_TRANSFER_SRC_BIT"); 3157315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateBufferUsageFlags(device_data, dst_buffer_state, VK_BUFFER_USAGE_TRANSFER_DST_BIT, true, 3158315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_18c000f0, "vkCmdCopyBuffer()", "VK_BUFFER_USAGE_TRANSFER_DST_BIT"); 3159baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip |= ValidateCmdQueueFlags(device_data, cb_node, "vkCmdCopyBuffer()", 3160315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VK_QUEUE_TRANSFER_BIT | VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, VALIDATION_ERROR_18c02415); 3161c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski skip |= ValidateCmd(device_data, cb_node, CMD_COPYBUFFER, "vkCmdCopyBuffer()"); 3162315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= insideRenderPass(device_data, cb_node, "vkCmdCopyBuffer()", VALIDATION_ERROR_18c00017); 3163c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski return skip; 3164c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski} 31656a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski 3166c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinskivoid PreCallRecordCmdCopyBuffer(layer_data *device_data, GLOBAL_CB_NODE *cb_node, BUFFER_STATE *src_buffer_state, 3167c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski BUFFER_STATE *dst_buffer_state) { 3168c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski // Update bindings between buffers and cmd buffer 3169c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski AddCommandBufferBindingBuffer(device_data, cb_node, src_buffer_state); 3170c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski AddCommandBufferBindingBuffer(device_data, cb_node, dst_buffer_state); 3171c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski 3172c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski std::function<bool()> function = [=]() { 3173c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski return ValidateBufferMemoryIsValid(device_data, src_buffer_state, "vkCmdCopyBuffer()"); 3174c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski }; 3175c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski cb_node->validate_functions.push_back(function); 3176c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski function = [=]() { 3177c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski SetBufferMemoryValid(device_data, dst_buffer_state, true); 3178c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski return false; 3179c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski }; 3180c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski cb_node->validate_functions.push_back(function); 3181c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski core_validation::UpdateCmdBufferLastCmd(cb_node, CMD_COPYBUFFER); 3182c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski} 3183842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski 3184842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinskistatic bool validateIdleBuffer(layer_data *device_data, VkBuffer buffer) { 3185842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski const debug_report_data *report_data = core_validation::GetReportData(device_data); 3186842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski bool skip = false; 3187842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski auto buffer_state = GetBufferState(device_data, buffer); 3188842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski if (!buffer_state) { 31899b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, HandleToUint64(buffer), 3190842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski __LINE__, DRAWSTATE_DOUBLE_DESTROY, "DS", 31919b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "Cannot free buffer 0x%" PRIxLEAST64 " that has not been allocated.", HandleToUint64(buffer)); 3192842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski } else { 3193842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski if (buffer_state->in_use.load()) { 31949b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, 3195315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(buffer), __LINE__, VALIDATION_ERROR_23c00734, "DS", 31969b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "Cannot free buffer 0x%" PRIxLEAST64 " that is in use by a command buffer. %s", HandleToUint64(buffer), 3197315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_23c00734]); 3198842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski } 3199842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski } 3200842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski return skip; 3201842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski} 3202842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski 3203842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinskibool PreCallValidateDestroyImageView(layer_data *device_data, VkImageView image_view, IMAGE_VIEW_STATE **image_view_state, 3204842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski VK_OBJECT *obj_struct) { 3205842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski *image_view_state = GetImageViewState(device_data, image_view); 32069b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus *obj_struct = {HandleToUint64(image_view), kVulkanObjectTypeImageView}; 3207842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski if (GetDisables(device_data)->destroy_image_view) return false; 3208842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski bool skip = false; 3209842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski if (*image_view_state) { 3210315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateObjectNotInUse(device_data, *image_view_state, *obj_struct, VALIDATION_ERROR_25400804); 3211842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski } 3212842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski return skip; 3213842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski} 3214842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski 3215842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinskivoid PostCallRecordDestroyImageView(layer_data *device_data, VkImageView image_view, IMAGE_VIEW_STATE *image_view_state, 3216842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski VK_OBJECT obj_struct) { 3217842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski // Any bound cmd buffers are now invalid 3218842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski invalidateCommandBuffers(device_data, image_view_state->cb_bindings, obj_struct); 3219842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski (*GetImageViewMap(device_data)).erase(image_view); 3220842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski} 3221842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski 3222842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinskibool PreCallValidateDestroyBuffer(layer_data *device_data, VkBuffer buffer, BUFFER_STATE **buffer_state, VK_OBJECT *obj_struct) { 3223842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski *buffer_state = GetBufferState(device_data, buffer); 32249b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus *obj_struct = {HandleToUint64(buffer), kVulkanObjectTypeBuffer}; 3225842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski if (GetDisables(device_data)->destroy_buffer) return false; 3226842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski bool skip = false; 3227842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski if (*buffer_state) { 3228842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski skip |= validateIdleBuffer(device_data, buffer); 3229842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski } 3230842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski return skip; 3231842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski} 3232842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski 3233842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinskivoid PostCallRecordDestroyBuffer(layer_data *device_data, VkBuffer buffer, BUFFER_STATE *buffer_state, VK_OBJECT obj_struct) { 3234842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski invalidateCommandBuffers(device_data, buffer_state->cb_bindings, obj_struct); 3235842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski for (auto mem_binding : buffer_state->GetBoundMemory()) { 3236842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski auto mem_info = GetMemObjInfo(device_data, mem_binding); 3237842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski if (mem_info) { 32389b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus core_validation::RemoveBufferMemoryRange(HandleToUint64(buffer), mem_info); 3239842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski } 3240842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski } 32419b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus ClearMemoryObjectBindings(device_data, HandleToUint64(buffer), kVulkanObjectTypeBuffer); 3242842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski GetBufferMap(device_data)->erase(buffer_state->buffer); 3243842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski} 3244842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski 3245842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinskibool PreCallValidateDestroyBufferView(layer_data *device_data, VkBufferView buffer_view, BUFFER_VIEW_STATE **buffer_view_state, 3246842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski VK_OBJECT *obj_struct) { 3247842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski *buffer_view_state = GetBufferViewState(device_data, buffer_view); 32489b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus *obj_struct = {HandleToUint64(buffer_view), kVulkanObjectTypeBufferView}; 3249842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski if (GetDisables(device_data)->destroy_buffer_view) return false; 3250842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski bool skip = false; 3251842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski if (*buffer_view_state) { 3252315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateObjectNotInUse(device_data, *buffer_view_state, *obj_struct, VALIDATION_ERROR_23e00750); 3253842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski } 3254842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski return skip; 3255842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski} 3256842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski 3257842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinskivoid PostCallRecordDestroyBufferView(layer_data *device_data, VkBufferView buffer_view, BUFFER_VIEW_STATE *buffer_view_state, 3258842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski VK_OBJECT obj_struct) { 3259842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski // Any bound cmd buffers are now invalid 3260842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski invalidateCommandBuffers(device_data, buffer_view_state->cb_bindings, obj_struct); 3261842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski GetBufferViewMap(device_data)->erase(buffer_view); 3262842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinski} 326323bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski 326423bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinskibool PreCallValidateCmdFillBuffer(layer_data *device_data, GLOBAL_CB_NODE *cb_node, BUFFER_STATE *buffer_state) { 326523bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski bool skip = false; 3266315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateMemoryIsBoundToBuffer(device_data, buffer_state, "vkCmdFillBuffer()", VALIDATION_ERROR_1b40003e); 3267baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip |= ValidateCmdQueueFlags(device_data, cb_node, "vkCmdFillBuffer()", 3268315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VK_QUEUE_TRANSFER_BIT | VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, VALIDATION_ERROR_1b402415); 326923bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski skip |= ValidateCmd(device_data, cb_node, CMD_FILLBUFFER, "vkCmdFillBuffer()"); 327023bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski // Validate that DST buffer has correct usage flags set 3271315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateBufferUsageFlags(device_data, buffer_state, VK_BUFFER_USAGE_TRANSFER_DST_BIT, true, VALIDATION_ERROR_1b40003a, 327223bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski "vkCmdFillBuffer()", "VK_BUFFER_USAGE_TRANSFER_DST_BIT"); 3273315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= insideRenderPass(device_data, cb_node, "vkCmdFillBuffer()", VALIDATION_ERROR_1b400017); 327423bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski return skip; 327523bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski} 327623bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski 327723bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinskivoid PreCallRecordCmdFillBuffer(layer_data *device_data, GLOBAL_CB_NODE *cb_node, BUFFER_STATE *buffer_state) { 327823bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski std::function<bool()> function = [=]() { 327923bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski SetBufferMemoryValid(device_data, buffer_state, true); 328023bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski return false; 328123bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski }; 328223bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski cb_node->validate_functions.push_back(function); 328323bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski // Update bindings between buffer and cmd buffer 328423bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski AddCommandBufferBindingBuffer(device_data, cb_node, buffer_state); 328523bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski core_validation::UpdateCmdBufferLastCmd(cb_node, CMD_FILLBUFFER); 328623bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski} 3287877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski 328871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinskibool ValidateBufferImageCopyData(const debug_report_data *report_data, uint32_t regionCount, const VkBufferImageCopy *pRegions, 328971c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski IMAGE_STATE *image_state, const char *function) { 3290877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski bool skip = false; 3291877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski 3292877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski for (uint32_t i = 0; i < regionCount; i++) { 32935971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton if (image_state->createInfo.imageType == VK_IMAGE_TYPE_1D) { 32945971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton if ((pRegions[i].imageOffset.y != 0) || (pRegions[i].imageExtent.height != 1)) { 32955971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 3296315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(image_state->image), __LINE__, VALIDATION_ERROR_0160018e, "IMAGE", 32975971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton "%s(): pRegion[%d] imageOffset.y is %d and imageExtent.height is %d. For 1D images these " 32985971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton "must be 0 and 1, respectively. %s", 32995971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton function, i, pRegions[i].imageOffset.y, pRegions[i].imageExtent.height, 3300315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_0160018e]); 3301877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski } 33025971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton } 3303877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski 33045971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton if ((image_state->createInfo.imageType == VK_IMAGE_TYPE_1D) || (image_state->createInfo.imageType == VK_IMAGE_TYPE_2D)) { 33055971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton if ((pRegions[i].imageOffset.z != 0) || (pRegions[i].imageExtent.depth != 1)) { 3306877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 3307315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(image_state->image), __LINE__, VALIDATION_ERROR_01600192, "IMAGE", 33085971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton "%s(): pRegion[%d] imageOffset.z is %d and imageExtent.depth is %d. For 1D and 2D images these " 33095971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton "must be 0 and 1, respectively. %s", 33105971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton function, i, pRegions[i].imageOffset.z, pRegions[i].imageExtent.depth, 3311315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_01600192]); 3312877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski } 33135971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton } 3314877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski 33155971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton if (image_state->createInfo.imageType == VK_IMAGE_TYPE_3D) { 33165971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton if ((0 != pRegions[i].imageSubresource.baseArrayLayer) || (1 != pRegions[i].imageSubresource.layerCount)) { 3317877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 3318315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(image_state->image), __LINE__, VALIDATION_ERROR_016001aa, "IMAGE", 33195971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton "%s(): pRegion[%d] imageSubresource.baseArrayLayer is %d and imageSubresource.layerCount is " 33205971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton "%d. For 3D images these must be 0 and 1, respectively. %s", 33215971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton function, i, pRegions[i].imageSubresource.baseArrayLayer, pRegions[i].imageSubresource.layerCount, 3322315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_016001aa]); 3323877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski } 33245971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton } 3325877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski 33265971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton // If the the calling command's VkImage parameter's format is not a depth/stencil format, 33275971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton // then bufferOffset must be a multiple of the calling command's VkImage parameter's texel size 332816769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton auto texel_size = FormatSize(image_state->createInfo.format); 3329cf2ce8673669ca1111e333bdea272c4dd57cb5c2Dave Houlton if (!FormatIsDepthAndStencil(image_state->createInfo.format) && SafeModulo(pRegions[i].bufferOffset, texel_size) != 0) { 33305971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 3331315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(image_state->image), __LINE__, VALIDATION_ERROR_01600182, "IMAGE", 33325971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton "%s(): pRegion[%d] bufferOffset 0x%" PRIxLEAST64 33335971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton " must be a multiple of this format's texel size (" PRINTF_SIZE_T_SPECIFIER "). %s", 3334315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis function, i, pRegions[i].bufferOffset, texel_size, validation_error_map[VALIDATION_ERROR_01600182]); 33355971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton } 33365971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton 33375971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton // BufferOffset must be a multiple of 4 333816769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton if (SafeModulo(pRegions[i].bufferOffset, 4) != 0) { 33395971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 3340315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(image_state->image), __LINE__, VALIDATION_ERROR_01600184, "IMAGE", 33415971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton "%s(): pRegion[%d] bufferOffset 0x%" PRIxLEAST64 " must be a multiple of 4. %s", function, i, 3342315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis pRegions[i].bufferOffset, validation_error_map[VALIDATION_ERROR_01600184]); 33435971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton } 33445971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton 33455971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton // BufferRowLength must be 0, or greater than or equal to the width member of imageExtent 33465971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton if ((pRegions[i].bufferRowLength != 0) && (pRegions[i].bufferRowLength < pRegions[i].imageExtent.width)) { 33475971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton skip |= log_msg( 33485971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 3349315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(image_state->image), __LINE__, VALIDATION_ERROR_01600186, "IMAGE", 33505971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton "%s(): pRegion[%d] bufferRowLength (%d) must be zero or greater-than-or-equal-to imageExtent.width (%d). %s", 33515971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton function, i, pRegions[i].bufferRowLength, pRegions[i].imageExtent.width, 3352315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_01600186]); 33535971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton } 33545971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton 33555971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton // BufferImageHeight must be 0, or greater than or equal to the height member of imageExtent 33565971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton if ((pRegions[i].bufferImageHeight != 0) && (pRegions[i].bufferImageHeight < pRegions[i].imageExtent.height)) { 33575971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton skip |= log_msg( 33585971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 3359315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(image_state->image), __LINE__, VALIDATION_ERROR_01600188, "IMAGE", 33605971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton "%s(): pRegion[%d] bufferImageHeight (%d) must be zero or greater-than-or-equal-to imageExtent.height (%d). %s", 33615971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton function, i, pRegions[i].bufferImageHeight, pRegions[i].imageExtent.height, 3362315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_01600188]); 33635971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton } 33645971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton 33655971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton // subresource aspectMask must have exactly 1 bit set 33665971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton const int num_bits = sizeof(VkFlags) * CHAR_BIT; 33675971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton std::bitset<num_bits> aspect_mask_bits(pRegions[i].imageSubresource.aspectMask); 33685971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton if (aspect_mask_bits.count() != 1) { 33695971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 3370315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(image_state->image), __LINE__, VALIDATION_ERROR_016001a8, "IMAGE", 33715971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton "%s: aspectMasks for imageSubresource in each region must have only a single bit set. %s", function, 3372315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_016001a8]); 33735971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton } 33745971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton 33755971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton // image subresource aspect bit must match format 3376e9d74ac8e13687c1be3ee147efce42e8215a049eDave Houlton if (!VerifyAspectsPresent(pRegions[i].imageSubresource.aspectMask, image_state->createInfo.format)) { 33775971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton skip |= log_msg( 33785971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 3379315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(image_state->image), __LINE__, VALIDATION_ERROR_016001a6, "IMAGE", 33805971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton "%s(): pRegion[%d] subresource aspectMask 0x%x specifies aspects that are not present in image format 0x%x. %s", 33815971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton function, i, pRegions[i].imageSubresource.aspectMask, image_state->createInfo.format, 3382315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_016001a6]); 33835971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton } 33845971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton 33855971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton // Checks that apply only to compressed images 33865971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton // TODO: there is a comment in ValidateCopyBufferImageTransferGranularityRequirements() in core_validation.cpp that 33875971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton // reserves a place for these compressed image checks. This block of code could move there once the image 33885971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton // stuff is moved into core validation. 338916769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton if (FormatIsCompressed(image_state->createInfo.format)) { 339016769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton auto block_size = FormatCompressedTexelBlockExtent(image_state->createInfo.format); 3391877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski 33925971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton // BufferRowLength must be a multiple of block width 339316769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton if (SafeModulo(pRegions[i].bufferRowLength, block_size.width) != 0) { 3394877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski skip |= log_msg( 3395877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 3396315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(image_state->image), __LINE__, VALIDATION_ERROR_01600196, "IMAGE", 33975971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton "%s(): pRegion[%d] bufferRowLength (%d) must be a multiple of the compressed image's texel width (%d). %s.", 3398315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis function, i, pRegions[i].bufferRowLength, block_size.width, validation_error_map[VALIDATION_ERROR_01600196]); 3399877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski } 3400877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski 34015971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton // BufferRowHeight must be a multiple of block height 340216769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton if (SafeModulo(pRegions[i].bufferImageHeight, block_size.height) != 0) { 3403877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 3404315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(image_state->image), __LINE__, VALIDATION_ERROR_01600198, "IMAGE", 34055971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton "%s(): pRegion[%d] bufferImageHeight (%d) must be a multiple of the compressed image's texel " 34065971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton "height (%d). %s.", 34075971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton function, i, pRegions[i].bufferImageHeight, block_size.height, 3408315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_01600198]); 3409877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski } 3410877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski 34115971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton // image offsets must be multiples of block dimensions 341216769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton if ((SafeModulo(pRegions[i].imageOffset.x, block_size.width) != 0) || 341316769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton (SafeModulo(pRegions[i].imageOffset.y, block_size.height) != 0) || 341416769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton (SafeModulo(pRegions[i].imageOffset.z, block_size.depth) != 0)) { 34155971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 3416315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(image_state->image), __LINE__, VALIDATION_ERROR_0160019a, "IMAGE", 34175971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton "%s(): pRegion[%d] imageOffset(x,y) (%d, %d) must be multiples of the compressed image's texel " 34185971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton "width & height (%d, %d). %s.", 34195971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton function, i, pRegions[i].imageOffset.x, pRegions[i].imageOffset.y, block_size.width, 3420315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis block_size.height, validation_error_map[VALIDATION_ERROR_0160019a]); 3421877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski } 3422877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski 34235971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton // bufferOffset must be a multiple of block size (linear bytes) 342416769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton size_t block_size_in_bytes = FormatSize(image_state->createInfo.format); 342516769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton if (SafeModulo(pRegions[i].bufferOffset, block_size_in_bytes) != 0) { 34265971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 3427315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(image_state->image), __LINE__, VALIDATION_ERROR_0160019c, "IMAGE", 34285971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton "%s(): pRegion[%d] bufferOffset (0x%" PRIxLEAST64 34295971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton ") must be a multiple of the compressed image's texel block " 34305971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton "size (" PRINTF_SIZE_T_SPECIFIER "). %s.", 34315971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton function, i, pRegions[i].bufferOffset, block_size_in_bytes, 3432315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_0160019c]); 3433877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski } 34342cd49094dcd399721f50c123413b8f55693348d7Dave Houlton 34352cd49094dcd399721f50c123413b8f55693348d7Dave Houlton // imageExtent width must be a multiple of block width, or extent+offset width must equal subresource width 3436045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton VkExtent3D mip_extent = GetImageSubresourceExtent(image_state, &(pRegions[i].imageSubresource)); 343716769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton if ((SafeModulo(pRegions[i].imageExtent.width, block_size.width) != 0) && 3438045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton (pRegions[i].imageExtent.width + pRegions[i].imageOffset.x != mip_extent.width)) { 3439045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 3440315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(image_state->image), __LINE__, VALIDATION_ERROR_0160019e, "IMAGE", 3441045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton "%s(): pRegion[%d] extent width (%d) must be a multiple of the compressed texture block width " 3442045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton "(%d), or when added to offset.x (%d) must equal the image subresource width (%d). %s.", 3443045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton function, i, pRegions[i].imageExtent.width, block_size.width, pRegions[i].imageOffset.x, 3444315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis mip_extent.width, validation_error_map[VALIDATION_ERROR_0160019e]); 34452cd49094dcd399721f50c123413b8f55693348d7Dave Houlton } 34462cd49094dcd399721f50c123413b8f55693348d7Dave Houlton 34472cd49094dcd399721f50c123413b8f55693348d7Dave Houlton // imageExtent height must be a multiple of block height, or extent+offset height must equal subresource height 344816769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton if ((SafeModulo(pRegions[i].imageExtent.height, block_size.height) != 0) && 3449045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton (pRegions[i].imageExtent.height + pRegions[i].imageOffset.y != mip_extent.height)) { 3450045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 3451315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(image_state->image), __LINE__, VALIDATION_ERROR_016001a0, "IMAGE", 3452045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton "%s(): pRegion[%d] extent height (%d) must be a multiple of the compressed texture block height " 3453045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton "(%d), or when added to offset.y (%d) must equal the image subresource height (%d). %s.", 3454045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton function, i, pRegions[i].imageExtent.height, block_size.height, pRegions[i].imageOffset.y, 3455315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis mip_extent.height, validation_error_map[VALIDATION_ERROR_016001a0]); 34562cd49094dcd399721f50c123413b8f55693348d7Dave Houlton } 34572cd49094dcd399721f50c123413b8f55693348d7Dave Houlton 34582cd49094dcd399721f50c123413b8f55693348d7Dave Houlton // imageExtent depth must be a multiple of block depth, or extent+offset depth must equal subresource depth 345916769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton if ((SafeModulo(pRegions[i].imageExtent.depth, block_size.depth) != 0) && 3460045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton (pRegions[i].imageExtent.depth + pRegions[i].imageOffset.z != mip_extent.depth)) { 3461045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 3462315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(image_state->image), __LINE__, VALIDATION_ERROR_016001a2, "IMAGE", 3463045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton "%s(): pRegion[%d] extent width (%d) must be a multiple of the compressed texture block depth " 3464045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton "(%d), or when added to offset.z (%d) must equal the image subresource depth (%d). %s.", 3465045a77f666b6efc8a229481b2a7a351f725e3725Dave Houlton function, i, pRegions[i].imageExtent.depth, block_size.depth, pRegions[i].imageOffset.z, 3466315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis mip_extent.depth, validation_error_map[VALIDATION_ERROR_016001a2]); 34672cd49094dcd399721f50c123413b8f55693348d7Dave Houlton } 34685971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton } 346971c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski } 347071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski 347171c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski return skip; 347271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski} 347371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski 34745971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houltonstatic bool ValidateImageBounds(const debug_report_data *report_data, const IMAGE_STATE *image_state, const uint32_t regionCount, 34755971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton const VkBufferImageCopy *pRegions, const char *func_name, UNIQUE_VALIDATION_ERROR_CODE msg_code) { 347671c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski bool skip = false; 34775971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton const VkImageCreateInfo *image_info = &(image_state->createInfo); 347871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski 347971c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski for (uint32_t i = 0; i < regionCount; i++) { 348071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski VkExtent3D extent = pRegions[i].imageExtent; 348171c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski VkOffset3D offset = pRegions[i].imageOffset; 348271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski 34835971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton if (IsExtentSizeZero(&extent)) // Warn on zero area subresource 34845971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton { 34855971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 34865971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton (uint64_t)0, __LINE__, IMAGE_ZERO_AREA_SUBREGION, "IMAGE", 34875971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton "%s: pRegion[%d] imageExtent of {%1d, %1d, %1d} has zero area", func_name, i, extent.width, 34885971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton extent.height, extent.depth); 348971c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski } 349071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski 34915971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton VkExtent3D image_extent = GetImageSubresourceExtent(image_state, &(pRegions[i].imageSubresource)); 34925971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton 34935971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton // If we're using a compressed format, valid extent is rounded up to multiple of block size (per 18.1) 349416769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton if (FormatIsCompressed(image_info->format)) { 349516769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton auto block_extent = FormatCompressedTexelBlockExtent(image_info->format); 34965971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton if (image_extent.width % block_extent.width) { 34975971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton image_extent.width += (block_extent.width - (image_extent.width % block_extent.width)); 34985971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton } 34995971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton if (image_extent.height % block_extent.height) { 35005971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton image_extent.height += (block_extent.height - (image_extent.height % block_extent.height)); 35015971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton } 35025971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton if (image_extent.depth % block_extent.depth) { 35035971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton image_extent.depth += (block_extent.depth - (image_extent.depth % block_extent.depth)); 35045971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton } 350571c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski } 350671c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski 35073fb79e4c87829ef090622d69a117f33ec7d4ded5Dave Houlton if (0 != ExceedsBounds(&offset, &extent, &image_extent)) { 350871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)0, 35095971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton __LINE__, msg_code, "IMAGE", "%s: pRegion[%d] exceeds image bounds. %s.", func_name, i, 351071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski validation_error_map[msg_code]); 3511877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski } 3512877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski } 3513877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski 3514877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski return skip; 3515877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski} 3516877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski 3517a72d7c6cce872aacc993f014dfd7963ca14675f4Chris Forbesstatic inline bool ValidateBufferBounds(const debug_report_data *report_data, IMAGE_STATE *image_state, BUFFER_STATE *buff_state, 351871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski uint32_t regionCount, const VkBufferImageCopy *pRegions, const char *func_name, 351971c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski UNIQUE_VALIDATION_ERROR_CODE msg_code) { 352071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski bool skip = false; 352171c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski 352271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski VkDeviceSize buffer_size = buff_state->createInfo.size; 352371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski 352471c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski for (uint32_t i = 0; i < regionCount; i++) { 352571c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski VkExtent3D copy_extent = pRegions[i].imageExtent; 352671c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski 352771c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski VkDeviceSize buffer_width = (0 == pRegions[i].bufferRowLength ? copy_extent.width : pRegions[i].bufferRowLength); 352871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski VkDeviceSize buffer_height = (0 == pRegions[i].bufferImageHeight ? copy_extent.height : pRegions[i].bufferImageHeight); 352916769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton VkDeviceSize unit_size = FormatSize(image_state->createInfo.format); // size (bytes) of texel or block 353071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski 35311dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton // Handle special buffer packing rules for specific depth/stencil formats 35321dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton if (pRegions[i].imageSubresource.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) { 353316769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton unit_size = FormatSize(VK_FORMAT_S8_UINT); 35341dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton } else if (pRegions[i].imageSubresource.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) { 35351dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton switch (image_state->createInfo.format) { 35361dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton case VK_FORMAT_D16_UNORM_S8_UINT: 353716769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton unit_size = FormatSize(VK_FORMAT_D16_UNORM); 35381dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton break; 35391dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton case VK_FORMAT_D32_SFLOAT_S8_UINT: 354016769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton unit_size = FormatSize(VK_FORMAT_D32_SFLOAT); 35411dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton break; 35425971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton case VK_FORMAT_X8_D24_UNORM_PACK32: // Fall through 35431dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton case VK_FORMAT_D24_UNORM_S8_UINT: 35441dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton unit_size = 4; 35451dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton break; 35461dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton default: 35471dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton break; 35481dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton } 35491dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton } 35501dc764a1d9155b6fb137006f21e7f6a354aad310Dave Houlton 355116769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton if (FormatIsCompressed(image_state->createInfo.format)) { 35525971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton // Switch to texel block units, rounding up for any partially-used blocks 355316769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton auto block_dim = FormatCompressedTexelBlockExtent(image_state->createInfo.format); 35545971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton buffer_width = (buffer_width + block_dim.width - 1) / block_dim.width; 35555971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton buffer_height = (buffer_height + block_dim.height - 1) / block_dim.height; 355671c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski 35575971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton copy_extent.width = (copy_extent.width + block_dim.width - 1) / block_dim.width; 35585971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton copy_extent.height = (copy_extent.height + block_dim.height - 1) / block_dim.height; 35595971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton copy_extent.depth = (copy_extent.depth + block_dim.depth - 1) / block_dim.depth; 35605971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton } 356171c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski 35625971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton // Either depth or layerCount may be greater than 1 (not both). This is the number of 'slices' to copy 35635971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton uint32_t z_copies = std::max(copy_extent.depth, pRegions[i].imageSubresource.layerCount); 35645971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton if (IsExtentSizeZero(©_extent) || (0 == z_copies)) { 3565a72d7c6cce872aacc993f014dfd7963ca14675f4Chris Forbes // TODO: Issue warning here? Already warned in ValidateImageBounds()... 35665971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton } else { 35675971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton // Calculate buffer offset of final copied byte, + 1. 35685971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton VkDeviceSize max_buffer_offset = (z_copies - 1) * buffer_height * buffer_width; // offset to slice 35695971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton max_buffer_offset += ((copy_extent.height - 1) * buffer_width) + copy_extent.width; // add row,col 35705971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton max_buffer_offset *= unit_size; // convert to bytes 35715971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton max_buffer_offset += pRegions[i].bufferOffset; // add initial offset (bytes) 357271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski 35735971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton if (buffer_size < max_buffer_offset) { 35745971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton skip |= 35755971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)0, 35765971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton __LINE__, msg_code, "IMAGE", "%s: pRegion[%d] exceeds buffer size of %" PRIu64 " bytes. %s.", func_name, 35775971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton i, buffer_size, validation_error_map[msg_code]); 35785971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton } 357971c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski } 358071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski } 358171c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski 358271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski return skip; 358371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski} 358471c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski 358571c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinskibool PreCallValidateCmdCopyImageToBuffer(layer_data *device_data, VkImageLayout srcImageLayout, GLOBAL_CB_NODE *cb_node, 3586940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski IMAGE_STATE *src_image_state, BUFFER_STATE *dst_buffer_state, uint32_t regionCount, 3587877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski const VkBufferImageCopy *pRegions, const char *func_name) { 358871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski const debug_report_data *report_data = core_validation::GetReportData(device_data); 358971c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski bool skip = ValidateBufferImageCopyData(report_data, regionCount, pRegions, src_image_state, "vkCmdCopyImageToBuffer"); 359071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski 359171c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski // Validate command buffer state 359271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski if (CB_RECORDING != cb_node->state) { 359371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 3594315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_19202413, "DS", 359571c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski "Cannot call vkCmdCopyImageToBuffer() on command buffer which is not in recording state. %s.", 3596315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_19202413]); 359771c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski } else { 359871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski skip |= ValidateCmdSubpassState(device_data, cb_node, CMD_COPYIMAGETOBUFFER); 359971c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski } 360071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski 360171c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski // Command pool must support graphics, compute, or transfer operations 360271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski auto pPool = GetCommandPoolNode(device_data, cb_node->createInfo.commandPool); 360371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski 360471c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski VkQueueFlags queue_flags = GetPhysDevProperties(device_data)->queue_family_properties[pPool->queueFamilyIndex].queueFlags; 360571c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski if (0 == (queue_flags & (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT))) { 360671c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 3607315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(cb_node->createInfo.commandPool), __LINE__, VALIDATION_ERROR_19202415, "DS", 360871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski "Cannot call vkCmdCopyImageToBuffer() on a command buffer allocated from a pool without graphics, compute, " 360971c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski "or transfer capabilities. %s.", 3610315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_19202415]); 361171c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski } 36125971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton skip |= ValidateImageBounds(report_data, src_image_state, regionCount, pRegions, "vkCmdCopyBufferToImage()", 3613315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_1920016c); 3614a72d7c6cce872aacc993f014dfd7963ca14675f4Chris Forbes skip |= ValidateBufferBounds(report_data, src_image_state, dst_buffer_state, regionCount, pRegions, "vkCmdCopyImageToBuffer()", 3615315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_1920016e); 361671c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski 361771c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski skip |= ValidateImageSampleCount(device_data, src_image_state, VK_SAMPLE_COUNT_1_BIT, "vkCmdCopyImageToBuffer(): srcImage", 3618315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_19200178); 3619315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateMemoryIsBoundToImage(device_data, src_image_state, "vkCmdCopyImageToBuffer()", VALIDATION_ERROR_19200176); 3620315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateMemoryIsBoundToBuffer(device_data, dst_buffer_state, "vkCmdCopyImageToBuffer()", VALIDATION_ERROR_19200180); 3621d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski 362271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski // Validate that SRC image & DST buffer have correct usage flags set 3623315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateImageUsageFlags(device_data, src_image_state, VK_IMAGE_USAGE_TRANSFER_SRC_BIT, true, VALIDATION_ERROR_19200174, 362471c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski "vkCmdCopyImageToBuffer()", "VK_IMAGE_USAGE_TRANSFER_SRC_BIT"); 3625315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateBufferUsageFlags(device_data, dst_buffer_state, VK_BUFFER_USAGE_TRANSFER_DST_BIT, true, 3626315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_1920017e, "vkCmdCopyImageToBuffer()", "VK_BUFFER_USAGE_TRANSFER_DST_BIT"); 3627315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= insideRenderPass(device_data, cb_node, "vkCmdCopyImageToBuffer()", VALIDATION_ERROR_19200017); 36280db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlis bool hit_error = false; 3629d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski for (uint32_t i = 0; i < regionCount; ++i) { 3630315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= VerifyImageLayout(device_data, cb_node, src_image_state, pRegions[i].imageSubresource, srcImageLayout, 3631315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, "vkCmdCopyImageToBuffer()", VALIDATION_ERROR_1920017c, 3632315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis &hit_error); 3633d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski skip |= ValidateCopyBufferImageTransferGranularityRequirements(device_data, cb_node, src_image_state, &pRegions[i], i, 3634fab4fd84d0d187bc73b5bc6709d8ed6370bb7cc3Tobin Ehlis "vkCmdCopyImageToBuffer()"); 3635d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski } 3636d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski return skip; 3637d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski} 3638d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski 3639d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinskivoid PreCallRecordCmdCopyImageToBuffer(layer_data *device_data, GLOBAL_CB_NODE *cb_node, IMAGE_STATE *src_image_state, 3640a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis BUFFER_STATE *dst_buffer_state, uint32_t region_count, const VkBufferImageCopy *regions, 3641a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis VkImageLayout src_image_layout) { 3642a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis // Make sure that all image slices are updated to correct layout 3643a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis for (uint32_t i = 0; i < region_count; ++i) { 3644a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis SetImageLayout(device_data, cb_node, src_image_state, regions[i].imageSubresource, src_image_layout); 3645a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis } 3646d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski // Update bindings between buffer/image and cmd buffer 3647d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski AddCommandBufferBindingImage(device_data, cb_node, src_image_state); 3648940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski AddCommandBufferBindingBuffer(device_data, cb_node, dst_buffer_state); 3649d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski 365071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski std::function<bool()> function = [=]() { 365171c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski return ValidateImageMemoryIsValid(device_data, src_image_state, "vkCmdCopyImageToBuffer()"); 365271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski }; 365371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski cb_node->validate_functions.push_back(function); 365471c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski function = [=]() { 3655940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski SetBufferMemoryValid(device_data, dst_buffer_state, true); 365671c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski return false; 365771c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski }; 365871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski cb_node->validate_functions.push_back(function); 365971c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski 366071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski core_validation::UpdateCmdBufferLastCmd(cb_node, CMD_COPYIMAGETOBUFFER); 3661877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski} 3662877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski 366371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinskibool PreCallValidateCmdCopyBufferToImage(layer_data *device_data, VkImageLayout dstImageLayout, GLOBAL_CB_NODE *cb_node, 3664940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski BUFFER_STATE *src_buffer_state, IMAGE_STATE *dst_image_state, uint32_t regionCount, 3665877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski const VkBufferImageCopy *pRegions, const char *func_name) { 366671c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski const debug_report_data *report_data = core_validation::GetReportData(device_data); 366771c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski bool skip = ValidateBufferImageCopyData(report_data, regionCount, pRegions, dst_image_state, "vkCmdCopyBufferToImage"); 366871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski 366971c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski // Validate command buffer state 367071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski if (CB_RECORDING != cb_node->state) { 367171c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 3672315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(cb_node->commandBuffer), __LINE__, VALIDATION_ERROR_18e02413, "DS", 367371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski "Cannot call vkCmdCopyBufferToImage() on command buffer which is not in recording state. %s.", 3674315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_18e02413]); 367571c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski } else { 367671c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski skip |= ValidateCmdSubpassState(device_data, cb_node, CMD_COPYBUFFERTOIMAGE); 367771c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski } 367871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski 367971c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski // Command pool must support graphics, compute, or transfer operations 368071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski auto pPool = GetCommandPoolNode(device_data, cb_node->createInfo.commandPool); 368171c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski VkQueueFlags queue_flags = GetPhysDevProperties(device_data)->queue_family_properties[pPool->queueFamilyIndex].queueFlags; 368271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski if (0 == (queue_flags & (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT))) { 368371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 3684315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(cb_node->createInfo.commandPool), __LINE__, VALIDATION_ERROR_18e02415, "DS", 368571c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski "Cannot call vkCmdCopyBufferToImage() on a command buffer allocated from a pool without graphics, compute, " 368671c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski "or transfer capabilities. %s.", 3687315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_18e02415]); 368871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski } 36895971c8e986a756c19a66a86d5faf5bd48a2c22c2Dave Houlton skip |= ValidateImageBounds(report_data, dst_image_state, regionCount, pRegions, "vkCmdCopyBufferToImage()", 3690315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_18e00158); 3691a72d7c6cce872aacc993f014dfd7963ca14675f4Chris Forbes skip |= ValidateBufferBounds(report_data, dst_image_state, src_buffer_state, regionCount, pRegions, "vkCmdCopyBufferToImage()", 3692315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_18e00156); 369371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski skip |= ValidateImageSampleCount(device_data, dst_image_state, VK_SAMPLE_COUNT_1_BIT, "vkCmdCopyBufferToImage(): dstImage", 3694315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_18e00166); 3695315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateMemoryIsBoundToBuffer(device_data, src_buffer_state, "vkCmdCopyBufferToImage()", VALIDATION_ERROR_18e00160); 3696315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateMemoryIsBoundToImage(device_data, dst_image_state, "vkCmdCopyBufferToImage()", VALIDATION_ERROR_18e00164); 3697315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateBufferUsageFlags(device_data, src_buffer_state, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, true, 3698315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_18e0015c, "vkCmdCopyBufferToImage()", "VK_BUFFER_USAGE_TRANSFER_SRC_BIT"); 3699315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateImageUsageFlags(device_data, dst_image_state, VK_IMAGE_USAGE_TRANSFER_DST_BIT, true, VALIDATION_ERROR_18e00162, 370071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski "vkCmdCopyBufferToImage()", "VK_IMAGE_USAGE_TRANSFER_DST_BIT"); 3701315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= insideRenderPass(device_data, cb_node, "vkCmdCopyBufferToImage()", VALIDATION_ERROR_18e00017); 37020db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlis bool hit_error = false; 3703d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski for (uint32_t i = 0; i < regionCount; ++i) { 3704315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= VerifyImageLayout(device_data, cb_node, dst_image_state, pRegions[i].imageSubresource, dstImageLayout, 3705315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, "vkCmdCopyBufferToImage()", VALIDATION_ERROR_18e0016a, 3706315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis &hit_error); 3707d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski skip |= ValidateCopyBufferImageTransferGranularityRequirements(device_data, cb_node, dst_image_state, &pRegions[i], i, 3708d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski "vkCmdCopyBufferToImage()"); 3709d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski } 3710d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski return skip; 3711d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski} 3712d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski 3713940f70f1340803d185c67633b05ef048d277952eMark Lobodzinskivoid PreCallRecordCmdCopyBufferToImage(layer_data *device_data, GLOBAL_CB_NODE *cb_node, BUFFER_STATE *src_buffer_state, 3714a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis IMAGE_STATE *dst_image_state, uint32_t region_count, const VkBufferImageCopy *regions, 3715a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis VkImageLayout dst_image_layout) { 3716a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis // Make sure that all image slices are updated to correct layout 3717a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis for (uint32_t i = 0; i < region_count; ++i) { 3718a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis SetImageLayout(device_data, cb_node, dst_image_state, regions[i].imageSubresource, dst_image_layout); 3719a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis } 3720940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski AddCommandBufferBindingBuffer(device_data, cb_node, src_buffer_state); 3721d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski AddCommandBufferBindingImage(device_data, cb_node, dst_image_state); 372271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski std::function<bool()> function = [=]() { 372371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski SetImageMemoryValid(device_data, dst_image_state, true); 372471c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski return false; 372571c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski }; 372671c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski cb_node->validate_functions.push_back(function); 3727940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski function = [=]() { return ValidateBufferMemoryIsValid(device_data, src_buffer_state, "vkCmdCopyBufferToImage()"); }; 372871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski cb_node->validate_functions.push_back(function); 372971c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski 373071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski core_validation::UpdateCmdBufferLastCmd(cb_node, CMD_COPYBUFFERTOIMAGE); 3731877577537c1f97bf8d50e32aecd7d3ca09a230a2Mark Lobodzinski} 3732e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen 3733e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblenbool PreCallValidateGetImageSubresourceLayout(layer_data *device_data, VkImage image, const VkImageSubresource *pSubresource) { 3734e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen const auto report_data = core_validation::GetReportData(device_data); 3735e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen bool skip = false; 3736e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen const VkImageAspectFlags sub_aspect = pSubresource->aspectMask; 3737e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen 3738e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen // VU 00733: The aspectMask member of pSubresource must only have a single bit set 3739e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen const int num_bits = sizeof(sub_aspect) * CHAR_BIT; 3740e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen std::bitset<num_bits> aspect_mask_bits(sub_aspect); 3741e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen if (aspect_mask_bits.count() != 1) { 37429b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, HandleToUint64(image), 3743315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis __LINE__, VALIDATION_ERROR_2a6007ca, "IMAGE", 3744e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen "vkGetImageSubresourceLayout(): VkImageSubresource.aspectMask must have exactly 1 bit set. %s", 3745315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_2a6007ca]); 3746e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen } 3747e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen 3748e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen IMAGE_STATE *image_entry = GetImageState(device_data, image); 3749e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen if (!image_entry) { 3750e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen return skip; 3751e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen } 3752e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen 3753e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen // VU 00732: image must have been created with tiling equal to VK_IMAGE_TILING_LINEAR 3754e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen if (image_entry->createInfo.tiling != VK_IMAGE_TILING_LINEAR) { 37559b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, HandleToUint64(image), 3756315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis __LINE__, VALIDATION_ERROR_2a6007c8, "IMAGE", 3757e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen "vkGetImageSubresourceLayout(): Image must have tiling of VK_IMAGE_TILING_LINEAR. %s", 3758315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_2a6007c8]); 3759e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen } 3760e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen 3761e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen // VU 00739: mipLevel must be less than the mipLevels specified in VkImageCreateInfo when the image was created 3762e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen if (pSubresource->mipLevel >= image_entry->createInfo.mipLevels) { 37639b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, HandleToUint64(image), 3764315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis __LINE__, VALIDATION_ERROR_0a4007cc, "IMAGE", 3765e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen "vkGetImageSubresourceLayout(): pSubresource.mipLevel (%d) must be less than %d. %s", 3766315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis pSubresource->mipLevel, image_entry->createInfo.mipLevels, validation_error_map[VALIDATION_ERROR_0a4007cc]); 3767e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen } 3768e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen 3769e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen // VU 00740: arrayLayer must be less than the arrayLayers specified in VkImageCreateInfo when the image was created 3770e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen if (pSubresource->arrayLayer >= image_entry->createInfo.arrayLayers) { 3771315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= 3772315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, HandleToUint64(image), 3773315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis __LINE__, VALIDATION_ERROR_0a4007ce, "IMAGE", 3774315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis "vkGetImageSubresourceLayout(): pSubresource.arrayLayer (%d) must be less than %d. %s", 3775315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis pSubresource->arrayLayer, image_entry->createInfo.arrayLayers, validation_error_map[VALIDATION_ERROR_0a4007ce]); 3776e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen } 3777e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen 3778e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen // VU 00741: subresource's aspect must be compatible with image's format. 3779e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen const VkFormat img_format = image_entry->createInfo.format; 378016769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton if (FormatIsColor(img_format)) { 3781e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen if (sub_aspect != VK_IMAGE_ASPECT_COLOR_BIT) { 3782e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen skip |= log_msg( 37839b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, HandleToUint64(image), __LINE__, 3784315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_0a400c01, "IMAGE", 3785e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen "vkGetImageSubresourceLayout(): For color formats, VkImageSubresource.aspectMask must be VK_IMAGE_ASPECT_COLOR. %s", 3786315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_0a400c01]); 3787e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen } 378816769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton } else if (FormatIsDepthOrStencil(img_format)) { 3789e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen if ((sub_aspect != VK_IMAGE_ASPECT_DEPTH_BIT) && (sub_aspect != VK_IMAGE_ASPECT_STENCIL_BIT)) { 3790fdc75c21ced997fbbc180734bef87bf6d5811d4bMark Lobodzinski skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 3791315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(image), __LINE__, VALIDATION_ERROR_0a400c01, "IMAGE", 3792e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen "vkGetImageSubresourceLayout(): For depth/stencil formats, VkImageSubresource.aspectMask must be " 3793e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen "either VK_IMAGE_ASPECT_DEPTH_BIT or VK_IMAGE_ASPECT_STENCIL_BIT. %s", 3794315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_0a400c01]); 3795e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen } 3796e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen } 3797e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen return skip; 3798e6e50fcd129baea00fd5eb908cad29b252abaaa7Mike Weiblen} 3799