blob: 0f5a45924f30b6abb594adb27271b77cd64710eb [file] [log] [blame]
/*
* Copyright (c) 2015-2025 The Khronos Group Inc.
* Copyright (c) 2015-2025 Valve Corporation
* Copyright (c) 2015-2025 LunarG, Inc.
* Copyright (c) 2015-2025 Google, Inc.
* Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*/
#include "utils/cast_utils.h"
#include "../framework/layer_validation_tests.h"
#ifndef VK_USE_PLATFORM_WIN32_KHR
#include <sys/mman.h>
#endif
class NegativeMemory : public VkLayerTest {};
TEST_F(NegativeMemory, MemoryDecompressionEnabled) {
TEST_DESCRIPTION("Validate memoryDecompression feature is enabled");
AddRequiredExtensions(VK_EXT_MEMORY_DECOMPRESSION_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(Init());
VkPhysicalDeviceMemoryDecompressionPropertiesEXT mem_decomp_props_sao = vku::InitStructHelper();
GetPhysicalDeviceProperties2(mem_decomp_props_sao);
if ((mem_decomp_props_sao.decompressionMethods & VK_MEMORY_DECOMPRESSION_METHOD_GDEFLATE_1_0_BIT_EXT) == 0) {
GTEST_SKIP() << "GDeflate decompression method not supported";
}
VkDeviceSize buffer_size = 1024;
VkDeviceSize decompressed_size = 2048;
vkt::Buffer src_buffer(*m_device, buffer_size, 0, vkt::device_address);
vkt::Buffer dst_buffer(*m_device, decompressed_size, 0, vkt::device_address);
VkDecompressMemoryRegionEXT decompress_region = {};
decompress_region.srcAddress = src_buffer.Address();
decompress_region.dstAddress = dst_buffer.Address();
decompress_region.compressedSize = buffer_size;
decompress_region.decompressedSize = decompressed_size;
VkDecompressMemoryInfoEXT decompress_info = vku::InitStructHelper();
decompress_info.decompressionMethod = VK_MEMORY_DECOMPRESSION_METHOD_GDEFLATE_1_0_BIT_EXT;
decompress_info.regionCount = 1;
decompress_info.pRegions = &decompress_region;
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdDecompressMemoryEXT-memoryDecompression-11761");
vk::CmdDecompressMemoryEXT(m_command_buffer, &decompress_info);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeMemory, MemoryDecompressionIndirectAddressUnaligned) {
AddRequiredExtensions(VK_EXT_MEMORY_DECOMPRESSION_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::memoryDecompression);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(Init());
VkPhysicalDeviceMemoryDecompressionPropertiesEXT props = vku::InitStructHelper();
GetPhysicalDeviceProperties2(props);
if ((props.decompressionMethods & VK_MEMORY_DECOMPRESSION_METHOD_GDEFLATE_1_0_BIT_EXT) == 0) {
GTEST_SKIP() << "GDeflate decompression method not supported";
}
VkDeviceSize sz = 64;
VkBufferUsageFlags2CreateInfo src_usage2 = vku::InitStructHelper();
src_usage2.usage = VK_BUFFER_USAGE_2_MEMORY_DECOMPRESSION_BIT_EXT;
vkt::Buffer src(*m_device, sz, src_usage2, vkt::device_address);
VkBufferUsageFlags2CreateInfo dst_usage2 = vku::InitStructHelper();
dst_usage2.usage = VK_BUFFER_USAGE_2_MEMORY_DECOMPRESSION_BIT_EXT;
vkt::Buffer dst(*m_device, sz, dst_usage2, vkt::device_address);
VkDecompressMemoryRegionEXT region{};
region.srcAddress = src.Address();
region.dstAddress = dst.Address();
region.compressedSize = sz;
region.decompressedSize = sz;
VkDeviceSize ic_size = static_cast<VkDeviceSize>(sizeof(VkDecompressMemoryRegionEXT)) + 16;
vkt::Buffer ic(*m_device, ic_size, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, vkt::device_address);
void* p_ic = ic.Memory().Map();
memcpy(p_ic, &region, sizeof(region));
vkt::Buffer icc(*m_device, sizeof(uint32_t), VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, vkt::device_address);
uint32_t count = 1;
void* p_cnt = icc.Memory().Map();
memcpy(p_cnt, &count, sizeof(count));
const VkMemoryDecompressionMethodFlagsEXT method = VK_MEMORY_DECOMPRESSION_METHOD_GDEFLATE_1_0_BIT_EXT;
const uint32_t max_decompression_count = 1;
const uint32_t stride = static_cast<uint32_t>(sizeof(VkDecompressMemoryRegionEXT));
const VkDeviceAddress start = ic.Address() + 2;
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdDecompressMemoryIndirectCountEXT-indirectCommandsAddress-07695");
vk::CmdDecompressMemoryIndirectCountEXT(m_command_buffer, method, start, icc.Address(), max_decompression_count, stride);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeMemory, MemoryDecompressionIndirectCountAddressUnaligned) {
AddRequiredExtensions(VK_EXT_MEMORY_DECOMPRESSION_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::memoryDecompression);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(Init());
VkPhysicalDeviceMemoryDecompressionPropertiesEXT props = vku::InitStructHelper();
GetPhysicalDeviceProperties2(props);
if ((props.decompressionMethods & VK_MEMORY_DECOMPRESSION_METHOD_GDEFLATE_1_0_BIT_EXT) == 0) {
GTEST_SKIP() << "GDeflate decompression method not supported";
}
VkDeviceSize sz = 64;
VkBufferUsageFlags2CreateInfo src_usage2 = vku::InitStructHelper();
src_usage2.usage = VK_BUFFER_USAGE_2_MEMORY_DECOMPRESSION_BIT_EXT;
vkt::Buffer src(*m_device, sz, src_usage2, vkt::device_address);
VkBufferUsageFlags2CreateInfo dst_usage2 = vku::InitStructHelper();
dst_usage2.usage = VK_BUFFER_USAGE_2_MEMORY_DECOMPRESSION_BIT_EXT;
vkt::Buffer dst(*m_device, sz, dst_usage2, vkt::device_address);
VkDecompressMemoryRegionEXT region{};
region.srcAddress = src.Address();
region.dstAddress = dst.Address();
region.compressedSize = sz;
region.decompressedSize = sz;
vkt::Buffer ic(*m_device, sizeof(VkDecompressMemoryRegionEXT) + 16, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, vkt::device_address);
void* p_ic = ic.Memory().Map();
memcpy(p_ic, &region, sizeof(region));
vkt::Buffer icc(*m_device, sizeof(uint32_t) + 8, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, vkt::device_address);
uint32_t count = 1;
void* p_cnt = icc.Memory().Map();
memcpy(p_cnt, &count, sizeof(count));
const VkMemoryDecompressionMethodFlagsEXT method = VK_MEMORY_DECOMPRESSION_METHOD_GDEFLATE_1_0_BIT_EXT;
const uint32_t max_decompression_count = 1;
const uint32_t stride = static_cast<uint32_t>(sizeof(VkDecompressMemoryRegionEXT));
const VkDeviceAddress count_addr = icc.Address() + 2;
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdDecompressMemoryIndirectCountEXT-indirectCommandsCountAddress-07698");
vk::CmdDecompressMemoryIndirectCountEXT(m_command_buffer, method, ic.Address(), count_addr, max_decompression_count, stride);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeMemory, MemoryDecompressionCompressedSizeZero) {
AddRequiredExtensions(VK_EXT_MEMORY_DECOMPRESSION_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::memoryDecompression);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(Init());
VkPhysicalDeviceMemoryDecompressionPropertiesEXT props = vku::InitStructHelper();
GetPhysicalDeviceProperties2(props);
if ((props.decompressionMethods & VK_MEMORY_DECOMPRESSION_METHOD_GDEFLATE_1_0_BIT_EXT) == 0) {
GTEST_SKIP() << "GDeflate decompression method not supported";
}
VkDeviceSize size = 64;
VkBufferUsageFlags2CreateInfo usage2 = vku::InitStructHelper();
usage2.usage = VK_BUFFER_USAGE_2_MEMORY_DECOMPRESSION_BIT_EXT;
vkt::Buffer src(*m_device, size, usage2, vkt::device_address);
vkt::Buffer dst(*m_device, size, usage2, vkt::device_address);
VkDecompressMemoryRegionEXT region{};
region.srcAddress = src.Address();
region.dstAddress = dst.Address();
region.compressedSize = 0;
region.decompressedSize = 64;
VkDecompressMemoryInfoEXT info = vku::InitStructHelper();
info.decompressionMethod = VK_MEMORY_DECOMPRESSION_METHOD_GDEFLATE_1_0_BIT_EXT;
info.regionCount = 1;
info.pRegions = &region;
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-VkDecompressMemoryRegionEXT-compressedSize-11795");
vk::CmdDecompressMemoryEXT(m_command_buffer, &info);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeMemory, MemoryDecompressionDecompressedSizeZero) {
AddRequiredExtensions(VK_EXT_MEMORY_DECOMPRESSION_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::memoryDecompression);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(Init());
VkPhysicalDeviceMemoryDecompressionPropertiesEXT props = vku::InitStructHelper();
GetPhysicalDeviceProperties2(props);
if ((props.decompressionMethods & VK_MEMORY_DECOMPRESSION_METHOD_GDEFLATE_1_0_BIT_EXT) == 0) {
GTEST_SKIP() << "GDeflate decompression method not supported";
}
VkDeviceSize size = 64;
VkBufferUsageFlags2CreateInfo usage2 = vku::InitStructHelper();
usage2.usage = VK_BUFFER_USAGE_2_MEMORY_DECOMPRESSION_BIT_EXT;
vkt::Buffer src(*m_device, size, usage2, vkt::device_address);
vkt::Buffer dst(*m_device, size, usage2, vkt::device_address);
VkDecompressMemoryRegionEXT region{};
region.srcAddress = src.Address();
region.dstAddress = dst.Address();
region.compressedSize = 16;
region.decompressedSize = 0;
VkDecompressMemoryInfoEXT info = vku::InitStructHelper();
info.decompressionMethod = VK_MEMORY_DECOMPRESSION_METHOD_GDEFLATE_1_0_BIT_EXT;
info.regionCount = 1;
info.pRegions = &region;
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-VkDecompressMemoryRegionEXT-decompressedSize-11796");
vk::CmdDecompressMemoryEXT(m_command_buffer, &info);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeMemory, MemoryDecompressionDstRangeExceedsBuffer) {
AddRequiredExtensions(VK_EXT_MEMORY_DECOMPRESSION_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::memoryDecompression);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(Init());
VkPhysicalDeviceMemoryDecompressionPropertiesEXT props = vku::InitStructHelper();
GetPhysicalDeviceProperties2(props);
if ((props.decompressionMethods & VK_MEMORY_DECOMPRESSION_METHOD_GDEFLATE_1_0_BIT_EXT) == 0) {
GTEST_SKIP() << "GDeflate decompression method not supported";
}
const VkDeviceSize buf_size = 64;
VkBufferUsageFlags2CreateInfo usage2 = vku::InitStructHelper();
usage2.usage = VK_BUFFER_USAGE_2_MEMORY_DECOMPRESSION_BIT_EXT | VK_BUFFER_USAGE_2_SHADER_DEVICE_ADDRESS_BIT;
vkt::Buffer buffer(*m_device, buf_size, usage2, vkt::device_address);
const VkDeviceAddress base = buffer.Address();
VkDecompressMemoryRegionEXT region{};
region.srcAddress = base;
region.compressedSize = 4;
const VkDeviceAddress unaligned_dst = base + (buf_size - 4);
region.dstAddress = unaligned_dst & ~static_cast<VkDeviceAddress>(3);
region.decompressedSize = 8;
VkDecompressMemoryInfoEXT info = vku::InitStructHelper();
info.decompressionMethod = VK_MEMORY_DECOMPRESSION_METHOD_GDEFLATE_1_0_BIT_EXT;
info.regionCount = 1;
info.pRegions = &region;
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-VkDecompressMemoryRegionEXT-dstAddress-07688");
// Possible the src_buffer is allocated next to the dst_buffer in the driver
m_errorMonitor->SetAllowedFailureMsg("VUID-VkDecompressMemoryRegionEXT-srcAddress-07691");
vk::CmdDecompressMemoryEXT(m_command_buffer, &info);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeMemory, MemoryDecompressionIndirectStrideInvalid) {
AddRequiredExtensions(VK_EXT_MEMORY_DECOMPRESSION_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::memoryDecompression);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(Init());
VkPhysicalDeviceMemoryDecompressionPropertiesEXT props = vku::InitStructHelper();
GetPhysicalDeviceProperties2(props);
if ((props.decompressionMethods & VK_MEMORY_DECOMPRESSION_METHOD_GDEFLATE_1_0_BIT_EXT) == 0) {
GTEST_SKIP() << "GDeflate decompression method not supported";
}
VkDeviceSize sz = 64;
VkBufferUsageFlags2CreateInfo usage2 = vku::InitStructHelper();
usage2.usage = VK_BUFFER_USAGE_2_MEMORY_DECOMPRESSION_BIT_EXT;
vkt::Buffer src(*m_device, sz, usage2, vkt::device_address);
vkt::Buffer dst(*m_device, sz, usage2, vkt::device_address);
VkDecompressMemoryRegionEXT region{};
region.srcAddress = src.Address();
region.dstAddress = dst.Address();
region.compressedSize = sz;
region.decompressedSize = sz;
vkt::Buffer ic(*m_device, sizeof(VkDecompressMemoryRegionEXT) + 16, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, vkt::device_address);
void* p_ic = ic.Memory().Map();
memcpy(p_ic, &region, sizeof(region));
vkt::Buffer icc(*m_device, sizeof(uint32_t), VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, vkt::device_address);
uint32_t count = 1;
void* p_cnt = icc.Memory().Map();
memcpy(p_cnt, &count, sizeof(count));
const VkMemoryDecompressionMethodFlagsEXT method = VK_MEMORY_DECOMPRESSION_METHOD_GDEFLATE_1_0_BIT_EXT;
const uint32_t max_decompression_count = 1;
const uint32_t bad_stride = 2;
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdDecompressMemoryIndirectCountEXT-stride-11767");
vk::CmdDecompressMemoryIndirectCountEXT(m_command_buffer, method, ic.Address(), icc.Address(), max_decompression_count,
bad_stride);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeMemory, MemoryDecompressionIndirectEnabled) {
TEST_DESCRIPTION("Validate memoryDecompression feature is enabled");
AddRequiredExtensions(VK_EXT_MEMORY_DECOMPRESSION_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::synchronization2);
AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(Init());
VkPhysicalDeviceMemoryDecompressionPropertiesEXT mem_decomp_props_ie = vku::InitStructHelper();
GetPhysicalDeviceProperties2(mem_decomp_props_ie);
if ((mem_decomp_props_ie.decompressionMethods & VK_MEMORY_DECOMPRESSION_METHOD_GDEFLATE_1_0_BIT_EXT) == 0) {
GTEST_SKIP() << "GDeflate decompression method not supported";
}
static const uint8_t kGdeflate_data[] = {0x47, 0x44, 0x46, 0x4c, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x40, 0x00,
0x00, 0x00, 0xaa, 0xbb, 0xcc, 0xdd, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88};
const std::vector<uint8_t> compressed(std::begin(kGdeflate_data), std::end(kGdeflate_data));
VkDeviceSize buffer_size = static_cast<VkDeviceSize>(compressed.size());
VkDeviceSize decompressed_size = 64;
VkBufferUsageFlags2CreateInfo src_usage2_ind = vku::InitStructHelper();
src_usage2_ind.usage = VK_BUFFER_USAGE_2_MEMORY_DECOMPRESSION_BIT_EXT | VK_BUFFER_USAGE_2_INDIRECT_BUFFER_BIT;
vkt::Buffer src_buffer(*m_device, buffer_size, src_usage2_ind, vkt::device_address);
VkBufferUsageFlags2CreateInfo dst_usage2_ind = vku::InitStructHelper();
dst_usage2_ind.usage = VK_BUFFER_USAGE_2_MEMORY_DECOMPRESSION_BIT_EXT;
vkt::Buffer dst_buffer(*m_device, decompressed_size, dst_usage2_ind, vkt::device_address);
void* p = src_buffer.Memory().Map();
std::memcpy(p, compressed.data(), compressed.size());
VkDecompressMemoryRegionEXT decompress_region = {};
decompress_region.srcAddress = src_buffer.Address();
decompress_region.dstAddress = dst_buffer.Address();
decompress_region.compressedSize = buffer_size;
decompress_region.decompressedSize = decompressed_size;
VkDecompressMemoryRegionEXT cmds[2] = {decompress_region, decompress_region};
vkt::Buffer ic_buffer(*m_device, sizeof(cmds), VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, vkt::device_address);
void* p_ic = ic_buffer.Memory().Map();
memcpy(p_ic, cmds, sizeof(cmds));
vkt::Buffer icc_buffer(*m_device, sizeof(uint32_t), VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, vkt::device_address);
uint32_t count = sizeof(cmds) / sizeof(VkDecompressMemoryRegionEXT);
void* p_cnt = icc_buffer.Memory().Map();
memcpy(p_cnt, &count, sizeof(count));
VkPhysicalDeviceMemoryDecompressionPropertiesEXT memory_decompression_props = vku::InitStructHelper();
GetPhysicalDeviceProperties2(memory_decompression_props);
VkMemoryDecompressionMethodFlagsEXT decompression_method = VK_MEMORY_DECOMPRESSION_METHOD_GDEFLATE_1_0_BIT_EXT;
uint32_t max_decompression_count = count;
uint32_t stride = (uint32_t)sizeof(VkDecompressMemoryRegionEXT);
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdDecompressMemoryIndirectCountEXT-None-07692");
VkMemoryBarrier2 mem_barrier = vku::InitStructHelper();
mem_barrier.srcAccessMask = VK_ACCESS_2_MEMORY_WRITE_BIT;
mem_barrier.srcStageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT;
mem_barrier.dstAccessMask = VK_ACCESS_2_MEMORY_DECOMPRESSION_READ_BIT_EXT | VK_ACCESS_2_MEMORY_DECOMPRESSION_WRITE_BIT_EXT;
mem_barrier.dstStageMask = VK_PIPELINE_STAGE_2_MEMORY_DECOMPRESSION_BIT_EXT;
m_command_buffer.BarrierKHR(mem_barrier);
vk::CmdDecompressMemoryIndirectCountEXT(m_command_buffer, decompression_method, ic_buffer.Address(), icc_buffer.Address(),
max_decompression_count, stride);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeMemory, MemoryDecompressionIndirectCount) {
AddRequiredExtensions(VK_EXT_MEMORY_DECOMPRESSION_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::memoryDecompression);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(Init());
VkPhysicalDeviceMemoryDecompressionPropertiesEXT mem_decomp_props_ic = vku::InitStructHelper();
GetPhysicalDeviceProperties2(mem_decomp_props_ic);
if ((mem_decomp_props_ic.decompressionMethods & VK_MEMORY_DECOMPRESSION_METHOD_GDEFLATE_1_0_BIT_EXT) == 0) {
GTEST_SKIP() << "GDeflate decompression method not supported";
}
VkDeviceSize buffer_size = 1024;
VkDeviceSize decompressed_size = 2048;
vkt::Buffer src_buffer(*m_device, buffer_size, 0, vkt::device_address);
vkt::Buffer dst_buffer(*m_device, decompressed_size, 0, vkt::device_address);
VkDecompressMemoryRegionEXT decompress_region = {};
decompress_region.srcAddress = src_buffer.Address();
decompress_region.dstAddress = dst_buffer.Address();
decompress_region.compressedSize = buffer_size;
decompress_region.decompressedSize = decompressed_size;
VkDecompressMemoryRegionEXT cmds[2] = {decompress_region, decompress_region};
VkBufferUsageFlags2CreateInfo ic_usage2 = vku::InitStructHelper();
ic_usage2.usage = VK_BUFFER_USAGE_2_SHADER_DEVICE_ADDRESS_BIT;
vkt::Buffer ic_buffer(*m_device, sizeof(cmds), ic_usage2, vkt::device_address);
void* ic_buffer_address = ic_buffer.Memory().Map();
memcpy(ic_buffer_address, &cmds, sizeof(cmds));
VkBufferUsageFlags2CreateInfo icc_usage2 = vku::InitStructHelper();
icc_usage2.usage = VK_BUFFER_USAGE_2_SHADER_DEVICE_ADDRESS_BIT;
vkt::Buffer icc_buffer(*m_device, sizeof(uint32_t), icc_usage2, vkt::device_address);
int cmdCount = sizeof(cmds) / sizeof(VkDecompressMemoryRegionEXT);
void* icc_buffer_address = icc_buffer.Memory().Map();
memcpy(icc_buffer_address, &cmdCount, sizeof(cmdCount));
VkPhysicalDeviceMemoryDecompressionPropertiesEXT memory_decompression_props = vku::InitStructHelper();
GetPhysicalDeviceProperties2(memory_decompression_props);
VkMemoryDecompressionMethodFlagsEXT decompression_method = VK_MEMORY_DECOMPRESSION_METHOD_GDEFLATE_1_0_BIT_EXT;
uint32_t max_decompression_count = (uint32_t)memory_decompression_props.maxDecompressionIndirectCount;
uint32_t stride = (uint32_t)sizeof(VkDecompressMemoryRegionEXT);
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdDecompressMemoryIndirectCountEXT-indirectCommandsAddress-07694");
m_errorMonitor->SetDesiredError("VUID-vkCmdDecompressMemoryIndirectCountEXT-indirectCommandsCountAddress-07697");
m_errorMonitor->SetDesiredError("VUID-vkCmdDecompressMemoryIndirectCountEXT-indirectCommandsAddress-11794");
vk::CmdDecompressMemoryIndirectCountEXT(m_command_buffer, decompression_method, ic_buffer.Address(), icc_buffer.Address(),
max_decompression_count, stride);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeMemory, MaxDecompressionCount) {
AddRequiredExtensions(VK_EXT_MEMORY_DECOMPRESSION_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::memoryDecompression);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(Init());
VkPhysicalDeviceMemoryDecompressionPropertiesEXT mem_decomp_props_mdc = vku::InitStructHelper();
GetPhysicalDeviceProperties2(mem_decomp_props_mdc);
if ((mem_decomp_props_mdc.decompressionMethods & VK_MEMORY_DECOMPRESSION_METHOD_GDEFLATE_1_0_BIT_EXT) == 0) {
GTEST_SKIP() << "GDeflate decompression method not supported";
}
VkDeviceSize buffer_size = 1024;
VkDeviceSize decompressed_size = 2048;
vkt::Buffer src_buffer(*m_device, buffer_size, 0, vkt::device_address);
vkt::Buffer dst_buffer(*m_device, decompressed_size, 0, vkt::device_address);
VkDecompressMemoryRegionEXT decompress_region = {};
decompress_region.srcAddress = src_buffer.Address();
decompress_region.dstAddress = dst_buffer.Address();
decompress_region.compressedSize = buffer_size;
decompress_region.decompressedSize = decompressed_size;
VkDecompressMemoryRegionEXT cmds[2] = {decompress_region, decompress_region};
vkt::Buffer ic_buffer(*m_device, sizeof(cmds), VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, vkt::device_address);
void* p_ic = ic_buffer.Memory().Map();
memcpy(p_ic, cmds, sizeof(cmds));
vkt::Buffer icc_buffer(*m_device, sizeof(uint32_t), VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, vkt::device_address);
uint32_t count = sizeof(cmds) / sizeof(VkDecompressMemoryRegionEXT);
void* p_cnt = icc_buffer.Memory().Map();
memcpy(p_cnt, &count, sizeof(count));
VkPhysicalDeviceMemoryDecompressionPropertiesEXT memory_decompression_props = vku::InitStructHelper();
GetPhysicalDeviceProperties2(memory_decompression_props);
VkMemoryDecompressionMethodFlagsEXT decompression_method = VK_MEMORY_DECOMPRESSION_METHOD_GDEFLATE_1_0_BIT_EXT;
uint32_t max_decompression_count = (uint32_t)memory_decompression_props.maxDecompressionIndirectCount;
uint32_t stride = (uint32_t)sizeof(VkDecompressMemoryRegionEXT);
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdDecompressMemoryIndirectCountEXT-maxDecompressionCount-11768");
vk::CmdDecompressMemoryIndirectCountEXT(m_command_buffer, decompression_method, ic_buffer.Address(), icc_buffer.Address(),
max_decompression_count + 1, stride);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeMemory, MemoryDecompressionIndirectAddressRangeSameBuffer) {
AddRequiredExtensions(VK_EXT_MEMORY_DECOMPRESSION_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::memoryDecompression);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(Init());
VkPhysicalDeviceMemoryDecompressionPropertiesEXT mem_decomp_props_arsb = vku::InitStructHelper();
GetPhysicalDeviceProperties2(mem_decomp_props_arsb);
if ((mem_decomp_props_arsb.decompressionMethods & VK_MEMORY_DECOMPRESSION_METHOD_GDEFLATE_1_0_BIT_EXT) == 0) {
GTEST_SKIP() << "GDeflate decompression method not supported";
}
VkDecompressMemoryRegionEXT region = {};
region.srcAddress = 0;
region.dstAddress = 0;
region.compressedSize = 16;
region.decompressedSize = 16;
VkDecompressMemoryRegionEXT cmds[1] = {region};
vkt::Buffer indirect_a(*m_device, sizeof(cmds), VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, vkt::device_address);
vkt::Buffer indirect_b(*m_device, 64, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, vkt::device_address);
void* p_ic = indirect_a.Memory().Map();
memcpy(p_ic, cmds, sizeof(cmds));
vkt::Buffer count_buf(*m_device, sizeof(uint32_t), VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, vkt::device_address);
uint32_t count = 2;
void* p_cnt = count_buf.Memory().Map();
memcpy(p_cnt, &count, sizeof(count));
const VkDeviceAddress end_minus_one = indirect_a.Address() + sizeof(cmds) - 1;
const VkDeviceAddress start = end_minus_one & ~static_cast<VkDeviceAddress>(3);
const uint32_t stride = (uint32_t)sizeof(VkDecompressMemoryRegionEXT);
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdDecompressMemoryIndirectCountEXT-indirectCommandsAddress-11794");
vk::CmdDecompressMemoryIndirectCountEXT(m_command_buffer, VK_MEMORY_DECOMPRESSION_METHOD_GDEFLATE_1_0_BIT_EXT, start,
count_buf.Address(), count, stride);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeMemory, MemoryDecompression) {
AddRequiredExtensions(VK_EXT_MEMORY_DECOMPRESSION_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::memoryDecompression);
RETURN_IF_SKIP(Init());
VkPhysicalDeviceMemoryDecompressionPropertiesEXT mem_decomp_props_md = vku::InitStructHelper();
GetPhysicalDeviceProperties2(mem_decomp_props_md);
if ((mem_decomp_props_md.decompressionMethods & VK_MEMORY_DECOMPRESSION_METHOD_GDEFLATE_1_0_BIT_EXT) == 0) {
GTEST_SKIP() << "GDeflate decompression method not supported";
}
VkDecompressMemoryRegionEXT decompress_region = {};
decompress_region.srcAddress = 1;
decompress_region.dstAddress = 1;
decompress_region.compressedSize = 1024;
decompress_region.decompressedSize = 65537;
VkDecompressMemoryInfoEXT decompress_info = vku::InitStructHelper();
decompress_info.decompressionMethod = VK_MEMORY_DECOMPRESSION_METHOD_GDEFLATE_1_0_BIT_EXT;
decompress_info.regionCount = 1;
decompress_info.pRegions = &decompress_region;
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-VkDecompressMemoryInfoEXT-decompressionMethod-11762");
m_errorMonitor->SetDesiredError("VUID-VkDecompressMemoryRegionEXT-srcAddress-07685");
m_errorMonitor->SetDesiredError("VUID-VkDecompressMemoryRegionEXT-dstAddress-07687");
m_errorMonitor->SetDesiredError("VUID-VkDecompressMemoryRegionEXT-srcAddress-07691");
vk::CmdDecompressMemoryEXT(m_command_buffer, &decompress_info);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeMemory, MemoryDecompressionBufferUsage) {
AddRequiredExtensions(VK_EXT_MEMORY_DECOMPRESSION_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::memoryDecompression);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(Init());
VkPhysicalDeviceMemoryDecompressionPropertiesEXT mem_decomp_props_mdbu = vku::InitStructHelper();
GetPhysicalDeviceProperties2(mem_decomp_props_mdbu);
if ((mem_decomp_props_mdbu.decompressionMethods & VK_MEMORY_DECOMPRESSION_METHOD_GDEFLATE_1_0_BIT_EXT) == 0) {
GTEST_SKIP() << "GDeflate decompression method not supported";
}
VkDeviceSize buffer_size = 64;
VkBufferUsageFlags2CreateInfo src_usage2 = vku::InitStructHelper();
src_usage2.usage = 0;
vkt::Buffer src_buffer(*m_device, buffer_size, src_usage2, vkt::device_address);
VkBufferUsageFlags2CreateInfo dst_usage2 = vku::InitStructHelper();
dst_usage2.usage = 0;
vkt::Buffer dst_buffer(*m_device, buffer_size, dst_usage2, vkt::device_address);
VkDecompressMemoryRegionEXT decompress_region = {};
decompress_region.srcAddress = src_buffer.Address();
decompress_region.dstAddress = dst_buffer.Address();
decompress_region.compressedSize = buffer_size;
decompress_region.decompressedSize = buffer_size;
VkDecompressMemoryInfoEXT decompress_info = vku::InitStructHelper();
decompress_info.decompressionMethod = VK_MEMORY_DECOMPRESSION_METHOD_GDEFLATE_1_0_BIT_EXT;
decompress_info.regionCount = 1;
decompress_info.pRegions = &decompress_region;
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-VkDecompressMemoryRegionEXT-srcAddress-11764");
m_errorMonitor->SetDesiredError("VUID-VkDecompressMemoryRegionEXT-dstAddress-11765");
vk::CmdDecompressMemoryEXT(m_command_buffer, &decompress_info);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeMemory, MemoryDecompressionMethodSingleBit) {
AddRequiredExtensions(VK_EXT_MEMORY_DECOMPRESSION_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::synchronization2);
AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::memoryDecompression);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(Init());
VkPhysicalDeviceMemoryDecompressionPropertiesEXT mem_decomp_props_mmsb = vku::InitStructHelper();
GetPhysicalDeviceProperties2(mem_decomp_props_mmsb);
if ((mem_decomp_props_mmsb.decompressionMethods & VK_MEMORY_DECOMPRESSION_METHOD_GDEFLATE_1_0_BIT_EXT) == 0) {
GTEST_SKIP() << "GDeflate decompression method not supported";
}
VkDeviceSize buffer_size = 64;
VkDeviceSize decompressed_size = 64;
VkBufferUsageFlags2CreateInfo src_usage2 = vku::InitStructHelper();
src_usage2.usage = VK_BUFFER_USAGE_2_MEMORY_DECOMPRESSION_BIT_EXT;
vkt::Buffer src_buffer(*m_device, buffer_size, src_usage2, vkt::device_address);
VkBufferUsageFlags2CreateInfo dst_usage2 = vku::InitStructHelper();
dst_usage2.usage = VK_BUFFER_USAGE_2_MEMORY_DECOMPRESSION_BIT_EXT;
vkt::Buffer dst_buffer(*m_device, decompressed_size, dst_usage2, vkt::device_address);
VkDecompressMemoryRegionEXT region = {};
region.srcAddress = src_buffer.Address();
region.dstAddress = dst_buffer.Address();
region.compressedSize = buffer_size;
region.decompressedSize = decompressed_size;
VkMemoryDecompressionMethodFlagsEXT bad_method =
VK_MEMORY_DECOMPRESSION_METHOD_GDEFLATE_1_0_BIT_EXT | (VkMemoryDecompressionMethodFlagsEXT)0x2;
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-VkDecompressMemoryInfoEXT-decompressionMethod-07690");
// Setting additional unsupported VkMemoryDecompressionMethodFlagBitsEXT bits to trigger error message
m_errorMonitor->SetAllowedFailureMsg("VUID-VkDecompressMemoryInfoEXT-decompressionMethod-parameter");
VkDecompressMemoryInfoEXT info = vku::InitStructHelper();
info.decompressionMethod = bad_method;
info.regionCount = 1;
info.pRegions = &region;
vk::CmdDecompressMemoryEXT(m_command_buffer, &info);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeMemory, MemoryDecompressionSrcAddressOutOfRange) {
AddRequiredExtensions(VK_EXT_MEMORY_DECOMPRESSION_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::memoryDecompression);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
AddRequiredFeature(vkt::Feature::synchronization2);
RETURN_IF_SKIP(Init());
VkPhysicalDeviceMemoryDecompressionPropertiesEXT mem_decomp_props_sao = vku::InitStructHelper();
GetPhysicalDeviceProperties2(mem_decomp_props_sao);
if ((mem_decomp_props_sao.decompressionMethods & VK_MEMORY_DECOMPRESSION_METHOD_GDEFLATE_1_0_BIT_EXT) == 0) {
GTEST_SKIP() << "GDeflate decompression method not supported";
}
const VkDeviceSize buf_size = 128;
VkBufferUsageFlags2CreateInfo src_usage2 = vku::InitStructHelper();
src_usage2.usage = VK_BUFFER_USAGE_2_MEMORY_DECOMPRESSION_BIT_EXT | VK_BUFFER_USAGE_2_SHADER_DEVICE_ADDRESS_BIT;
vkt::Buffer src_buffer(*m_device, buf_size, src_usage2, vkt::device_address);
const VkDeviceAddress base = src_buffer.Address();
const VkDeviceAddress src_near_end = base + buf_size - 8;
const VkDeviceAddress src_addr = src_near_end & ~static_cast<VkDeviceAddress>(3);
VkBufferUsageFlags2CreateInfo dst_usage2 = vku::InitStructHelper();
dst_usage2.usage = VK_BUFFER_USAGE_2_MEMORY_DECOMPRESSION_BIT_EXT | VK_BUFFER_USAGE_2_SHADER_DEVICE_ADDRESS_BIT;
vkt::Buffer dst_buffer(*m_device, buf_size, dst_usage2, vkt::device_address);
const VkDeviceAddress dst_addr = dst_buffer.Address();
VkDecompressMemoryRegionEXT region = {};
region.srcAddress = src_addr;
region.dstAddress = dst_addr;
region.compressedSize = buf_size;
region.decompressedSize = buf_size;
VkDecompressMemoryInfoEXT info = vku::InitStructHelper();
info.decompressionMethod = VK_MEMORY_DECOMPRESSION_METHOD_GDEFLATE_1_0_BIT_EXT;
info.regionCount = 1;
info.pRegions = &region;
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-VkDecompressMemoryRegionEXT-srcAddress-07686");
// Possible the dst_buffer is allocated next to the src_buffer in the driver
m_errorMonitor->SetAllowedFailureMsg("VUID-VkDecompressMemoryRegionEXT-srcAddress-07691");
vk::CmdDecompressMemoryEXT(m_command_buffer, &info);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeMemory, MapMemory) {
RETURN_IF_SKIP(Init());
VkBufferCreateInfo buffer_ci = vku::InitStructHelper();
buffer_ci.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
buffer_ci.size = 256;
vkt::Buffer buffer(*m_device, buffer_ci, vkt::no_mem);
VkMemoryRequirements mem_reqs;
vk::GetBufferMemoryRequirements(device(), buffer, &mem_reqs);
VkMemoryAllocateInfo alloc_info = vku::InitStructHelper();
alloc_info.memoryTypeIndex = 0;
// Ensure memory is big enough for both bindings
// Want to make sure entire allocation is aligned to atom size
const VkDeviceSize atom_size = m_device->Physical().limits_.nonCoherentAtomSize;
static const VkDeviceSize allocation_size = atom_size * 64;
alloc_info.allocationSize = allocation_size;
bool pass = m_device->Physical().SetMemoryType(mem_reqs.memoryTypeBits, &alloc_info, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
if (!pass) {
GTEST_SKIP() << "Failed to set memory type";
}
vkt::DeviceMemory mem(*m_device, alloc_info);
uint8_t *pData;
// Attempt to map memory size 0 is invalid
m_errorMonitor->SetDesiredError("VUID-vkMapMemory-size-00680");
vk::MapMemory(device(), mem, 0, 0, 0, (void **)&pData);
m_errorMonitor->VerifyFound();
// Map memory twice
ASSERT_EQ(VK_SUCCESS, vk::MapMemory(device(), mem, 0, VK_WHOLE_SIZE, 0, (void **)&pData));
m_errorMonitor->SetDesiredError("VUID-vkMapMemory-memory-00678");
vk::MapMemory(device(), mem, 0, VK_WHOLE_SIZE, 0, (void **)&pData);
m_errorMonitor->VerifyFound();
// Unmap the memory to avoid re-map error
vk::UnmapMemory(device(), mem);
// overstep offset with VK_WHOLE_SIZE
m_errorMonitor->SetDesiredError("VUID-vkMapMemory-offset-00679");
vk::MapMemory(device(), mem, allocation_size + 1, VK_WHOLE_SIZE, 0, (void **)&pData);
m_errorMonitor->VerifyFound();
// overstep offset w/o VK_WHOLE_SIZE
m_errorMonitor->SetDesiredError("VUID-vkMapMemory-offset-00679");
vk::MapMemory(device(), mem, allocation_size + 1, VK_WHOLE_SIZE, 0, (void **)&pData);
m_errorMonitor->VerifyFound();
// overstep allocation w/o VK_WHOLE_SIZE
m_errorMonitor->SetDesiredError("VUID-vkMapMemory-size-00681");
vk::MapMemory(device(), mem, 1, allocation_size, 0, (void **)&pData);
m_errorMonitor->VerifyFound();
// Now error due to unmapping memory that's not mapped
m_errorMonitor->SetDesiredError("VUID-vkUnmapMemory-memory-00689");
vk::UnmapMemory(device(), mem);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeMemory, MapMemoryFlush) {
RETURN_IF_SKIP(Init());
VkBufferCreateInfo buffer_ci = vku::InitStructHelper();
buffer_ci.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
buffer_ci.size = 256;
vkt::Buffer buffer(*m_device, buffer_ci, vkt::no_mem);
VkMemoryRequirements mem_reqs;
vk::GetBufferMemoryRequirements(device(), buffer, &mem_reqs);
VkMemoryAllocateInfo alloc_info = vku::InitStructHelper();
alloc_info.memoryTypeIndex = 0;
// Ensure memory is big enough for both bindings
// Want to make sure entire allocation is aligned to atom
const VkDeviceSize atom_size = m_device->Physical().limits_.nonCoherentAtomSize;
static const VkDeviceSize allocation_size = atom_size * 64;
alloc_info.allocationSize = allocation_size;
bool pass = m_device->Physical().SetMemoryType(mem_reqs.memoryTypeBits, &alloc_info, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
if (!pass) {
GTEST_SKIP() << "Failed to set memory type";
}
vkt::DeviceMemory mem(*m_device, alloc_info);
uint8_t *pData;
// Now map memory and cause errors due to flushing invalid ranges
ASSERT_EQ(VK_SUCCESS, vk::MapMemory(device(), mem, 4 * atom_size, VK_WHOLE_SIZE, 0, (void **)&pData));
VkMappedMemoryRange mem_range = vku::InitStructHelper();
mem_range.memory = mem;
mem_range.offset = atom_size; // Error b/c offset less than offset of mapped mem
m_errorMonitor->SetDesiredError("VUID-VkMappedMemoryRange-size-00685");
vk::FlushMappedMemoryRanges(device(), 1, &mem_range);
m_errorMonitor->VerifyFound();
// Now flush range that oversteps mapped range
vk::UnmapMemory(device(), mem);
ASSERT_EQ(VK_SUCCESS, vk::MapMemory(device(), mem, 0, 4 * atom_size, 0, (void **)&pData));
mem_range.offset = atom_size;
mem_range.size = 4 * atom_size; // Flushing bounds exceed mapped bounds
m_errorMonitor->SetDesiredError("VUID-VkMappedMemoryRange-size-00685");
vk::FlushMappedMemoryRanges(device(), 1, &mem_range);
m_errorMonitor->VerifyFound();
// Now flush range with VK_WHOLE_SIZE that oversteps offset
vk::UnmapMemory(device(), mem);
ASSERT_EQ(VK_SUCCESS, vk::MapMemory(device(), mem, 2 * atom_size, 4 * atom_size, 0, (void **)&pData));
mem_range.offset = atom_size;
mem_range.size = VK_WHOLE_SIZE;
m_errorMonitor->SetDesiredError("VUID-VkMappedMemoryRange-size-00686");
vk::FlushMappedMemoryRanges(device(), 1, &mem_range);
m_errorMonitor->VerifyFound();
// Try flushing and invalidating host memory not mapped
vk::UnmapMemory(device(), mem);
mem_range.offset = 0;
mem_range.size = VK_WHOLE_SIZE;
m_errorMonitor->SetDesiredError("VUID-VkMappedMemoryRange-memory-00684");
vk::FlushMappedMemoryRanges(device(), 1, &mem_range);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-VkMappedMemoryRange-memory-00684");
vk::InvalidateMappedMemoryRanges(device(), 1, &mem_range);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeMemory, MapMemoryCoherentAtomSize) {
RETURN_IF_SKIP(Init());
if (IsPlatformMockICD()) {
GTEST_SKIP() << "Test not supported by MockICD, MapMemory will fail ASAN";
}
const VkDeviceSize atom_size = m_device->Physical().limits_.nonCoherentAtomSize;
if (atom_size < 4) {
GTEST_SKIP() << "nonCoherentAtomSize is too small";
}
VkBufferCreateInfo buffer_ci = vku::InitStructHelper();
buffer_ci.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
buffer_ci.size = 256;
vkt::Buffer buffer(*m_device, buffer_ci, vkt::no_mem);
VkMemoryRequirements mem_reqs;
vk::GetBufferMemoryRequirements(device(), buffer, &mem_reqs);
VkMemoryAllocateInfo alloc_info = vku::InitStructHelper();
alloc_info.memoryTypeIndex = 0;
// Ensure memory is big enough for both bindings
// Want to make sure entire allocation is aligned to atom
static const VkDeviceSize allocation_size = atom_size * 64;
alloc_info.allocationSize = allocation_size;
bool pass = m_device->Physical().SetMemoryType(mem_reqs.memoryTypeBits, &alloc_info, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
if (!pass) {
GTEST_SKIP() << "Failed to set memory type";
}
vkt::DeviceMemory mem(*m_device, alloc_info);
uint8_t *pData;
// Now with an offset NOT a multiple of the device limit
ASSERT_EQ(VK_SUCCESS, vk::MapMemory(device(), mem, 0, 4 * atom_size, 0, (void **)&pData));
VkMappedMemoryRange mem_range = vku::InitStructHelper();
mem_range.memory = mem;
mem_range.offset = 3; // Not a multiple of atom_size
mem_range.size = VK_WHOLE_SIZE;
m_errorMonitor->SetDesiredError("VUID-VkMappedMemoryRange-offset-00687");
vk::FlushMappedMemoryRanges(device(), 1, &mem_range);
m_errorMonitor->VerifyFound();
// Now with a size NOT a multiple of the device limit
vk::UnmapMemory(device(), mem);
ASSERT_EQ(VK_SUCCESS, vk::MapMemory(device(), mem, 0, 4 * atom_size, 0, (void **)&pData));
mem_range.offset = atom_size;
mem_range.size = 2 * atom_size + 1; // Not a multiple of atom_size
m_errorMonitor->SetDesiredError("VUID-VkMappedMemoryRange-size-01390");
vk::FlushMappedMemoryRanges(device(), 1, &mem_range);
m_errorMonitor->VerifyFound();
// Now with VK_WHOLE_SIZE and a mapping that does not end at a multiple of atom_size nor at the end of the memory.
vk::UnmapMemory(device(), mem);
ASSERT_EQ(VK_SUCCESS, vk::MapMemory(device(), mem, 0, 4 * atom_size + 1, 0, (void **)&pData));
mem_range.offset = atom_size;
mem_range.size = VK_WHOLE_SIZE;
m_errorMonitor->SetDesiredError("VUID-VkMappedMemoryRange-size-01389");
vk::FlushMappedMemoryRanges(device(), 1, &mem_range);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeMemory, MapMemory2) {
TEST_DESCRIPTION("Attempt to map memory in a number of incorrect ways");
AddRequiredExtensions(VK_KHR_MAP_MEMORY_2_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
/* Vulkan doesn't have any requirements on what allocationSize can be
* other than that it must be non-zero. Pick 64KB because that should
* work out to an even number of pages on basically any GPU.
*/
const VkDeviceSize allocation_size = 64 << 10;
VkMemoryAllocateInfo memory_info = vku::InitStructHelper();
memory_info.allocationSize = allocation_size;
bool pass = m_device->Physical().SetMemoryType(vvl::kU32Max, &memory_info, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
ASSERT_TRUE(pass);
vkt::DeviceMemory memory(*m_device, memory_info);
VkMemoryMapInfo map_info = vku::InitStructHelper();
map_info.memory = memory;
VkMemoryUnmapInfo unmap_info = vku::InitStructHelper();
unmap_info.memory = memory;
uint8_t *pData;
// Attempt to map memory size 0 is invalid
map_info.offset = 0;
map_info.size = 0;
m_errorMonitor->SetDesiredError("VUID-VkMemoryMapInfo-size-07960");
vk::MapMemory2KHR(device(), &map_info, (void **)&pData);
m_errorMonitor->VerifyFound();
// Map memory twice
map_info.offset = 0;
map_info.size = VK_WHOLE_SIZE;
ASSERT_EQ(VK_SUCCESS, vk::MapMemory2KHR(device(), &map_info, (void **)&pData));
m_errorMonitor->SetDesiredError("VUID-VkMemoryMapInfo-memory-07958");
vk::MapMemory2KHR(device(), &map_info, (void **)&pData);
m_errorMonitor->VerifyFound();
// Unmap the memory to avoid re-map error
vk::UnmapMemory2KHR(device(), &unmap_info);
// overstep offset with VK_WHOLE_SIZE
map_info.offset = allocation_size + 1;
map_info.size = VK_WHOLE_SIZE;
m_errorMonitor->SetDesiredError("VUID-VkMemoryMapInfo-offset-07959");
vk::MapMemory2KHR(device(), &map_info, (void **)&pData);
m_errorMonitor->VerifyFound();
// overstep allocation w/o VK_WHOLE_SIZE
map_info.offset = 1,
map_info.size = allocation_size;
m_errorMonitor->SetDesiredError("VUID-VkMemoryMapInfo-size-07961");
vk::MapMemory2KHR(device(), &map_info, (void **)&pData);
m_errorMonitor->VerifyFound();
// Now error due to unmapping memory that's not mapped
m_errorMonitor->SetDesiredError("VUID-VkMemoryUnmapInfo-memory-07964");
vk::UnmapMemory2KHR(device(), &unmap_info);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeMemory, MapMemoryNullppData) {
TEST_DESCRIPTION("vkMapMemory but ppData is null");
RETURN_IF_SKIP(Init());
VkMemoryAllocateInfo memory_info = vku::InitStructHelper();
memory_info.allocationSize = 1024;
ASSERT_TRUE(m_device->Physical().SetMemoryType(vvl::kU32Max, &memory_info, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));
vkt::DeviceMemory memory(*m_device, memory_info);
m_errorMonitor->SetDesiredError("VUID-vkMapMemory-ppData-parameter");
vk::MapMemory(device(), memory, 0, VK_WHOLE_SIZE, 0, nullptr);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeMemory, MapMemWithoutHostVisibleBit) {
TEST_DESCRIPTION("Allocate memory that is not mappable and then attempt to map it.");
RETURN_IF_SKIP(Init());
VkMemoryAllocateInfo mem_alloc = vku::InitStructHelper();
mem_alloc.allocationSize = 1024;
if (!m_device->Physical().SetMemoryType(0xFFFFFFFF, &mem_alloc, 0, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)) {
// If we can't find any unmappable memory this test doesn't make sense
GTEST_SKIP() << "No unmappable memory types found";
}
vkt::DeviceMemory memory(*m_device, mem_alloc);
void *mapped_address = nullptr;
m_errorMonitor->SetDesiredError("VUID-vkMapMemory-memory-00682");
m_errorMonitor->SetUnexpectedError("VUID-vkMapMemory-memory-00683");
vk::MapMemory(device(), memory, 0, VK_WHOLE_SIZE, 0, &mapped_address);
m_errorMonitor->VerifyFound();
// Attempt to flush and invalidate non-host memory
VkMappedMemoryRange memory_range = vku::InitStructHelper();
memory_range.memory = memory;
memory_range.offset = 0;
memory_range.size = VK_WHOLE_SIZE;
m_errorMonitor->SetDesiredError("VUID-VkMappedMemoryRange-memory-00684");
vk::FlushMappedMemoryRanges(device(), 1, &memory_range);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-VkMappedMemoryRange-memory-00684");
vk::InvalidateMappedMemoryRanges(device(), 1, &memory_range);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeMemory, MapMemory2WithoutHostVisibleBit) {
TEST_DESCRIPTION("Allocate memory that is not mappable and then attempt to map it.");
AddRequiredExtensions(VK_KHR_MAP_MEMORY_2_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
VkMemoryAllocateInfo mem_alloc = vku::InitStructHelper();
mem_alloc.allocationSize = 1024;
if (!m_device->Physical().SetMemoryType(
0xFFFFFFFF, &mem_alloc, 0,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)) { // If we can't find any unmappable memory this test doesn't make sense
GTEST_SKIP() << "No unmappable memory types found";
}
vkt::DeviceMemory memory(*m_device, mem_alloc);
VkMemoryMapInfo map_info = vku::InitStructHelper();
map_info.memory = memory;
map_info.offset = 0;
map_info.size = 32;
uint8_t *pData;
m_errorMonitor->SetDesiredError("VUID-VkMemoryMapInfo-memory-07962");
vk::MapMemory2KHR(device(), &map_info, (void **)&pData);
m_errorMonitor->VerifyFound();
}
#ifndef VK_USE_PLATFORM_WIN32_KHR
TEST_F(NegativeMemory, MapMemoryPlaced) {
TEST_DESCRIPTION("Attempt to map placed memory in a number of incorrect ways");
AddRequiredExtensions(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_MAP_MEMORY_2_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_MAP_MEMORY_PLACED_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::memoryMapPlaced);
RETURN_IF_SKIP(Init());
VkPhysicalDeviceMapMemoryPlacedPropertiesEXT map_placed_props = vku::InitStructHelper();
GetPhysicalDeviceProperties2(map_placed_props);
// Vulkan doesn't have any requirements on what allocationSize can be
// other than that it must be non-zero. Pick 64KB because that should
// work out to an even number of pages on basically any GPU.
const VkDeviceSize allocation_size = map_placed_props.minPlacedMemoryMapAlignment * 16;
VkMemoryAllocateInfo memory_info = vku::InitStructHelper();
memory_info.allocationSize = allocation_size;
bool pass = m_device->Physical().SetMemoryType(vvl::kU32Max, &memory_info, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
ASSERT_TRUE(pass);
vkt::DeviceMemory memory(*m_device, memory_info);
VkMemoryMapInfo map_info = vku::InitStructHelper();
map_info.memory = memory;
map_info.flags = VK_MEMORY_MAP_PLACED_BIT_EXT;
map_info.offset = 0;
map_info.size = VK_WHOLE_SIZE;
// No VkMemoryMapPlacedInfoEXT
void *pData;
m_errorMonitor->SetDesiredError("VUID-VkMemoryMapInfo-flags-09570");
vk::MapMemory2KHR(device(), &map_info, &pData);
m_errorMonitor->VerifyFound();
VkMemoryMapPlacedInfoEXT placed_info = vku::InitStructHelper();
map_info.pNext = &placed_info;
// No VkMemoryMapPlacedInfoEXT::pPlacedAddress == NULL
m_errorMonitor->SetDesiredError("VUID-VkMemoryMapInfo-flags-09570");
vk::MapMemory2KHR(device(), &map_info, &pData);
m_errorMonitor->VerifyFound();
// Reserve two more pages in case we need to deal with any alignment weirdness.
size_t reservation_size = allocation_size + map_placed_props.minPlacedMemoryMapAlignment;
void *reservation = mmap(NULL, reservation_size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
ASSERT_TRUE(reservation != MAP_FAILED);
// Align up to minPlacedMemoryMapAlignment
uintptr_t align_1 = map_placed_props.minPlacedMemoryMapAlignment - 1;
void *addr = reinterpret_cast<void *>((reinterpret_cast<uintptr_t>(reservation) + align_1) & ~align_1);
placed_info.pPlacedAddress = ((char *)addr) + (map_placed_props.minPlacedMemoryMapAlignment / 2);
// Unaligned VkMemoryMapPlacedInfoEXT::pPlacedAddress
m_errorMonitor->SetDesiredError("VUID-VkMemoryMapPlacedInfoEXT-pPlacedAddress-09577");
vk::MapMemory2KHR(device(), &map_info, &pData);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeMemory, MemoryMapRangePlacedEnabled) {
TEST_DESCRIPTION("Test when memoryMapRangePlaced is enabled");
AddRequiredExtensions(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_MAP_MEMORY_2_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_MAP_MEMORY_PLACED_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::memoryMapPlaced);
AddRequiredFeature(vkt::Feature::memoryMapRangePlaced);
RETURN_IF_SKIP(Init());
VkPhysicalDeviceMapMemoryPlacedPropertiesEXT map_placed_props = vku::InitStructHelper();
GetPhysicalDeviceProperties2(map_placed_props);
const VkDeviceSize allocation_size = map_placed_props.minPlacedMemoryMapAlignment * 16;
VkMemoryAllocateInfo memory_info = vku::InitStructHelper();
memory_info.allocationSize = allocation_size;
bool pass = m_device->Physical().SetMemoryType(vvl::kU32Max, &memory_info, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
ASSERT_TRUE(pass);
vkt::DeviceMemory memory(*m_device, memory_info);
// Reserve two more pages in case we need to deal with any alignment weirdness.
size_t reservation_size = allocation_size + map_placed_props.minPlacedMemoryMapAlignment;
void *reservation = mmap(NULL, reservation_size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
ASSERT_TRUE(reservation != MAP_FAILED);
uintptr_t align_1 = map_placed_props.minPlacedMemoryMapAlignment - 1;
void *addr = reinterpret_cast<void *>((reinterpret_cast<uintptr_t>(reservation) + align_1) & ~align_1);
VkMemoryMapPlacedInfoEXT placed_info = vku::InitStructHelper();
placed_info.pPlacedAddress = addr;
VkMemoryMapInfo map_info = vku::InitStructHelper(&placed_info);
map_info.memory = memory;
map_info.flags = VK_MEMORY_MAP_PLACED_BIT_EXT;
map_info.size = VK_WHOLE_SIZE;
map_info.offset = map_placed_props.minPlacedMemoryMapAlignment / 2;
void *pData;
// Unaligned offset
m_errorMonitor->SetDesiredError("VUID-VkMemoryMapInfo-flags-09573");
vk::MapMemory2KHR(device(), &map_info, &pData);
m_errorMonitor->VerifyFound();
map_info.offset = 0;
map_info.size = allocation_size - (map_placed_props.minPlacedMemoryMapAlignment / 2);
// Unaligned size
m_errorMonitor->SetDesiredError("VUID-VkMemoryMapInfo-flags-09574");
vk::MapMemory2KHR(device(), &map_info, &pData);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeMemory, MemoryMapRangePlacedDisabled) {
TEST_DESCRIPTION("Test when memoryMapRangePlaced is disabled");
AddRequiredExtensions(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_MAP_MEMORY_2_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_MAP_MEMORY_PLACED_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::memoryMapPlaced);
RETURN_IF_SKIP(Init());
VkPhysicalDeviceMapMemoryPlacedPropertiesEXT map_placed_props = vku::InitStructHelper();
GetPhysicalDeviceProperties2(map_placed_props);
const VkDeviceSize allocation_size = map_placed_props.minPlacedMemoryMapAlignment * 16;
VkMemoryAllocateInfo memory_info = vku::InitStructHelper();
memory_info.allocationSize = allocation_size;
bool pass = m_device->Physical().SetMemoryType(vvl::kU32Max, &memory_info, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
ASSERT_TRUE(pass);
vkt::DeviceMemory memory(*m_device, memory_info);
// Reserve two more pages in case we need to deal with any alignment weirdness.
size_t reservation_size = allocation_size + map_placed_props.minPlacedMemoryMapAlignment;
void *reservation = mmap(NULL, reservation_size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
ASSERT_TRUE(reservation != MAP_FAILED);
uintptr_t align_1 = map_placed_props.minPlacedMemoryMapAlignment - 1;
void *addr = reinterpret_cast<void *>((reinterpret_cast<uintptr_t>(reservation) + align_1) & ~align_1);
VkMemoryMapPlacedInfoEXT placed_info = vku::InitStructHelper();
placed_info.pPlacedAddress = addr;
VkMemoryMapInfo map_info = vku::InitStructHelper(&placed_info);
map_info.memory = memory;
map_info.flags = VK_MEMORY_MAP_PLACED_BIT_EXT;
map_info.size = VK_WHOLE_SIZE;
map_info.offset = map_placed_props.minPlacedMemoryMapAlignment;
void *pData;
// Non-zero offset
m_errorMonitor->SetDesiredError("VUID-VkMemoryMapInfo-flags-09571");
vk::MapMemory2KHR(device(), &map_info, &pData);
m_errorMonitor->VerifyFound();
map_info.offset = 0;
map_info.size = allocation_size - map_placed_props.minPlacedMemoryMapAlignment;
// Not VK_WHOLE_SIZE
m_errorMonitor->SetDesiredError("VUID-VkMemoryMapInfo-flags-09572");
vk::MapMemory2KHR(device(), &map_info, &pData);
m_errorMonitor->VerifyFound();
const VkDeviceSize unaligned_size = allocation_size + map_placed_props.minPlacedMemoryMapAlignment / 2;
memory_info.allocationSize = unaligned_size;
vkt::DeviceMemory unaligned_memory(*m_device, memory_info);
map_info.memory = unaligned_memory;
map_info.offset = 0;
map_info.size = VK_WHOLE_SIZE;
m_errorMonitor->SetDesiredError("VUID-VkMemoryMapInfo-flags-09651");
vk::MapMemory2KHR(device(), &map_info, &pData);
m_errorMonitor->VerifyFound();
map_info.size = unaligned_size;
m_errorMonitor->SetDesiredError("VUID-VkMemoryMapInfo-flags-09574");
vk::MapMemory2KHR(device(), &map_info, &pData);
m_errorMonitor->VerifyFound();
}
#endif
TEST_F(NegativeMemory, RebindMemoryMultiObject) {
RETURN_IF_SKIP(Init());
// Create an image, allocate memory, free it, and then try to bind it
VkImageCreateInfo image_create_info =
vkt::Image::ImageCreateInfo2D(32, 32, 1, 1, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT);
vkt::Image image(*m_device, image_create_info, vkt::no_mem);
VkMemoryRequirements mem_reqs = image.MemoryRequirements();
VkMemoryAllocateInfo mem_alloc = vku::InitStructHelper();
// Introduce failure, do NOT set memProps to
// VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
mem_alloc.memoryTypeIndex = 1;
mem_alloc.allocationSize = mem_reqs.size;
ASSERT_TRUE(m_device->Physical().SetMemoryType(mem_reqs.memoryTypeBits, &mem_alloc, 0));
vkt::DeviceMemory mem1(*m_device, mem_alloc);
vkt::DeviceMemory mem2(*m_device, mem_alloc);
// Bind first memory object to Image object
vk::BindImageMemory(device(), image, mem1, 0);
// Introduce validation failure, try to bind a different memory object to
// the same image object
m_errorMonitor->SetDesiredError("VUID-vkBindImageMemory-image-07460");
vk::BindImageMemory(device(), image, mem2, 0);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeMemory, QueryMemoryCommitmentWithoutLazyProperty) {
TEST_DESCRIPTION("Attempt to query memory commitment on memory without lazy allocation");
RETURN_IF_SKIP(Init());
auto image_ci = vkt::Image::ImageCreateInfo2D(32, 32, 1, 1, VK_FORMAT_B8G8R8A8_UNORM,
VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
vkt::Image image(*m_device, image_ci, vkt::no_mem);
const auto mem_reqs = image.MemoryRequirements();
VkMemoryAllocateInfo image_alloc_info = vku::InitStructHelper();
image_alloc_info.allocationSize = mem_reqs.size;
// the last argument is the "forbid" argument for SetMemoryType, disallowing
// that particular memory type rather than requiring it
if (!m_device->Physical().SetMemoryType(mem_reqs.memoryTypeBits, &image_alloc_info, 0,
VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT)) {
GTEST_SKIP() << "Failed to set memory type";
}
vkt::DeviceMemory mem(*m_device, image_alloc_info);
m_errorMonitor->SetDesiredError("VUID-vkGetDeviceMemoryCommitment-memory-00690");
VkDeviceSize size;
vk::GetDeviceMemoryCommitment(device(), mem, &size);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeMemory, BindImageMemoryType) {
TEST_DESCRIPTION("Create an image, allocate memory, set a bad typeIndex and then try to bind it");
RETURN_IF_SKIP(Init());
VkImageCreateInfo image_create_info =
vkt::Image::ImageCreateInfo2D(32, 32, 1, 1, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT);
vkt::Image image(*m_device, image_create_info, vkt::no_mem);
VkMemoryAllocateInfo mem_alloc = vku::InitStructHelper();
mem_alloc.allocationSize = 0;
mem_alloc.memoryTypeIndex = 0;
VkMemoryRequirements mem_reqs;
vk::GetImageMemoryRequirements(device(), image, &mem_reqs);
mem_alloc.allocationSize = mem_reqs.size;
// Introduce Failure, select invalid TypeIndex
VkPhysicalDeviceMemoryProperties memory_info;
vk::GetPhysicalDeviceMemoryProperties(Gpu(), &memory_info);
uint32_t i = 0;
for (; i < memory_info.memoryTypeCount; i++) {
// Would require deviceCoherentMemory feature
if (memory_info.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD) {
continue;
}
// would require protected feature
if (memory_info.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_PROTECTED_BIT) {
continue;
}
if ((mem_reqs.memoryTypeBits & (1 << i)) == 0) {
mem_alloc.memoryTypeIndex = i;
break;
}
}
if (i >= memory_info.memoryTypeCount) {
GTEST_SKIP() << "No invalid memory type index could be found";
}
m_errorMonitor->SetDesiredError("VUID-vkBindImageMemory-memory-01047");
vkt::DeviceMemory mem(*m_device, mem_alloc);
vk::BindImageMemory(device(), image, mem, 0);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeMemory, BindMemory) {
AddRequiredFeature(vkt::Feature::sparseBinding);
RETURN_IF_SKIP(Init());
VkImageCreateInfo image_create_info =
vkt::Image::ImageCreateInfo2D(256, 256, 1, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT);
auto buffer_create_info = vkt::Buffer::CreateInfo(4 * 1024 * 1024, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
// Create an image/buffer, allocate memory, free it, and then try to bind it
{
vkt::Image image(*m_device, image_create_info, vkt::no_mem);
vkt::Buffer buffer(*m_device, buffer_create_info, vkt::no_mem);
VkMemoryRequirements image_mem_reqs = {}, buffer_mem_reqs = {};
vk::GetImageMemoryRequirements(device(), image, &image_mem_reqs);
vk::GetBufferMemoryRequirements(device(), buffer, &buffer_mem_reqs);
VkMemoryAllocateInfo image_mem_alloc = vku::InitStructHelper();
VkMemoryAllocateInfo buffer_mem_alloc = vku::InitStructHelper();
image_mem_alloc.allocationSize = image_mem_reqs.size;
m_device->Physical().SetMemoryType(image_mem_reqs.memoryTypeBits, &image_mem_alloc, 0);
buffer_mem_alloc.allocationSize = buffer_mem_reqs.size;
m_device->Physical().SetMemoryType(buffer_mem_reqs.memoryTypeBits, &buffer_mem_alloc, 0);
VkDeviceMemory image_mem = VK_NULL_HANDLE, buffer_mem = VK_NULL_HANDLE;
vk::AllocateMemory(device(), &image_mem_alloc, nullptr, &image_mem);
vk::AllocateMemory(device(), &buffer_mem_alloc, nullptr, &buffer_mem);
vk::FreeMemory(device(), image_mem, nullptr);
vk::FreeMemory(device(), buffer_mem, nullptr);
m_errorMonitor->SetDesiredError("VUID-vkBindImageMemory-memory-parameter");
vk::BindImageMemory(device(), image, image_mem, 0);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkBindBufferMemory-memory-parameter");
vk::BindBufferMemory(device(), buffer, buffer_mem, 0);
m_errorMonitor->VerifyFound();
}
// Try to bind memory to an object that already has a memory binding
{
vkt::Image image(*m_device, image_create_info, vkt::no_mem);
vkt::Buffer buffer(*m_device, buffer_create_info, vkt::no_mem);
VkMemoryRequirements image_mem_reqs = {}, buffer_mem_reqs = {};
vk::GetImageMemoryRequirements(device(), image, &image_mem_reqs);
vk::GetBufferMemoryRequirements(device(), buffer, &buffer_mem_reqs);
VkMemoryAllocateInfo image_alloc_info = vku::InitStructHelper();
VkMemoryAllocateInfo buffer_alloc_info = vku::InitStructHelper();
image_alloc_info.allocationSize = image_mem_reqs.size;
buffer_alloc_info.allocationSize = buffer_mem_reqs.size;
m_device->Physical().SetMemoryType(image_mem_reqs.memoryTypeBits, &image_alloc_info, 0);
m_device->Physical().SetMemoryType(buffer_mem_reqs.memoryTypeBits, &buffer_alloc_info, 0);
vkt::DeviceMemory image_mem(*m_device, image_alloc_info);
vkt::DeviceMemory buffer_mem(*m_device, buffer_alloc_info);
vk::BindImageMemory(device(), image, image_mem, 0);
m_errorMonitor->SetDesiredError("VUID-vkBindImageMemory-image-07460");
vk::BindImageMemory(device(), image, image_mem, 0);
m_errorMonitor->VerifyFound();
vk::BindBufferMemory(device(), buffer, buffer_mem, 0);
m_errorMonitor->SetDesiredError("VUID-vkBindBufferMemory-buffer-07459");
vk::BindBufferMemory(device(), buffer, buffer_mem, 0);
m_errorMonitor->VerifyFound();
}
// Try to bind memory to an object with an invalid memoryOffset
{
vkt::Image image(*m_device, image_create_info, vkt::no_mem);
vkt::Buffer buffer(*m_device, buffer_create_info, vkt::no_mem);
VkMemoryRequirements image_mem_reqs = {}, buffer_mem_reqs = {};
vk::GetImageMemoryRequirements(device(), image, &image_mem_reqs);
vk::GetBufferMemoryRequirements(device(), buffer, &buffer_mem_reqs);
VkMemoryAllocateInfo image_alloc_info = vku::InitStructHelper();
VkMemoryAllocateInfo buffer_alloc_info = vku::InitStructHelper();
// Leave some extra space for alignment wiggle room
image_alloc_info.allocationSize = image_mem_reqs.size + image_mem_reqs.alignment;
buffer_alloc_info.allocationSize = buffer_mem_reqs.size + buffer_mem_reqs.alignment;
m_device->Physical().SetMemoryType(image_mem_reqs.memoryTypeBits, &image_alloc_info, 0);
m_device->Physical().SetMemoryType(buffer_mem_reqs.memoryTypeBits, &buffer_alloc_info, 0);
vkt::DeviceMemory image_mem(*m_device, image_alloc_info);
vkt::DeviceMemory buffer_mem(*m_device, buffer_alloc_info);
// Test unaligned memory offset
{
if (image_mem_reqs.alignment > 1) {
VkDeviceSize image_offset = 1;
m_errorMonitor->SetDesiredError("VUID-vkBindImageMemory-None-10735");
vk::BindImageMemory(device(), image, image_mem, image_offset);
m_errorMonitor->VerifyFound();
}
if (buffer_mem_reqs.alignment > 1) {
VkDeviceSize buffer_offset = 1;
m_errorMonitor->SetDesiredError("VUID-vkBindBufferMemory-None-10739");
vk::BindBufferMemory(device(), buffer, buffer_mem, buffer_offset);
m_errorMonitor->VerifyFound();
}
}
// Test memory offsets outside the memory allocation
{
VkDeviceSize image_offset =
(image_alloc_info.allocationSize + image_mem_reqs.alignment) & ~(image_mem_reqs.alignment - 1);
m_errorMonitor->SetDesiredError("VUID-vkBindImageMemory-memoryOffset-01046");
vk::BindImageMemory(device(), image, image_mem, image_offset);
m_errorMonitor->VerifyFound();
VkDeviceSize buffer_offset =
(buffer_alloc_info.allocationSize + buffer_mem_reqs.alignment) & ~(buffer_mem_reqs.alignment - 1);
m_errorMonitor->SetDesiredError("VUID-vkBindBufferMemory-memoryOffset-01031");
vk::BindBufferMemory(device(), buffer, buffer_mem, buffer_offset);
m_errorMonitor->VerifyFound();
}
// Test memory offsets within the memory allocation, but which leave too little memory for
// the resource.
{
VkDeviceSize image_offset = (image_mem_reqs.size - 1) & ~(image_mem_reqs.alignment - 1);
if ((image_offset > 0) && (image_mem_reqs.size < (image_alloc_info.allocationSize - image_mem_reqs.alignment))) {
m_errorMonitor->SetDesiredError("VUID-vkBindImageMemory-None-10737");
vk::BindImageMemory(device(), image, image_mem, image_offset);
m_errorMonitor->VerifyFound();
}
VkDeviceSize buffer_offset = (buffer_mem_reqs.size - 1) & ~(buffer_mem_reqs.alignment - 1);
if (buffer_offset > 0) {
m_errorMonitor->SetDesiredError("VUID-vkBindBufferMemory-None-10741");
vk::BindBufferMemory(device(), buffer, buffer_mem, buffer_offset);
m_errorMonitor->VerifyFound();
}
}
}
// Try to bind memory to an image created with sparse memory flags
{
VkImageCreateInfo sparse_image_create_info = image_create_info;
sparse_image_create_info.flags |= VK_IMAGE_CREATE_SPARSE_BINDING_BIT;
VkImageFormatProperties image_format_properties = {};
VkResult err = GetImageFormatProps(Gpu(), sparse_image_create_info, image_format_properties);
if (!m_device->Physical().Features().sparseResidencyImage2D || err == VK_ERROR_FORMAT_NOT_SUPPORTED) {
// most likely means sparse formats aren't supported here; skip this test.
} else {
if (image_format_properties.maxExtent.width == 0) {
GTEST_SKIP() << "Sparse image format not supported";
} else {
vkt::Image sparse_image(*m_device, sparse_image_create_info, vkt::no_mem);
VkMemoryRequirements sparse_mem_reqs = {};
vk::GetImageMemoryRequirements(device(), sparse_image, &sparse_mem_reqs);
if (sparse_mem_reqs.memoryTypeBits != 0) {
VkMemoryAllocateInfo sparse_mem_alloc = vku::InitStructHelper();
sparse_mem_alloc.allocationSize = sparse_mem_reqs.size;
sparse_mem_alloc.memoryTypeIndex = 0;
m_device->Physical().SetMemoryType(sparse_mem_reqs.memoryTypeBits, &sparse_mem_alloc, 0);
vkt::DeviceMemory memory(*m_device, sparse_mem_alloc);
m_errorMonitor->SetDesiredError("VUID-vkBindImageMemory-image-01045");
vk::BindImageMemory(device(), sparse_image, memory, 0);
m_errorMonitor->VerifyFound();
}
}
}
}
// Try to bind memory to a buffer created with sparse memory flags
{
VkBufferCreateInfo sparse_buffer_create_info = buffer_create_info;
sparse_buffer_create_info.flags |= VK_IMAGE_CREATE_SPARSE_BINDING_BIT;
if (!m_device->Physical().Features().sparseResidencyBuffer) {
// most likely means sparse formats aren't supported here; skip this test.
} else {
vkt::Buffer sparse_buffer(*m_device, sparse_buffer_create_info, vkt::no_mem);
VkMemoryRequirements sparse_mem_reqs = {};
vk::GetBufferMemoryRequirements(device(), sparse_buffer, &sparse_mem_reqs);
if (sparse_mem_reqs.memoryTypeBits != 0) {
VkMemoryAllocateInfo sparse_mem_alloc = vku::InitStructHelper();
sparse_mem_alloc.allocationSize = sparse_mem_reqs.size;
sparse_mem_alloc.memoryTypeIndex = 0;
m_device->Physical().SetMemoryType(sparse_mem_reqs.memoryTypeBits, &sparse_mem_alloc, 0);
vkt::DeviceMemory memory(*m_device, sparse_mem_alloc);
m_errorMonitor->SetDesiredError("VUID-vkBindBufferMemory-buffer-01030");
vk::BindBufferMemory(device(), sparse_buffer, memory, 0);
m_errorMonitor->VerifyFound();
}
}
}
}
TEST_F(NegativeMemory, BindMemoryUnsupported) {
RETURN_IF_SKIP(Init());
VkImageCreateInfo image_create_info =
vkt::Image::ImageCreateInfo2D(256, 256, 1, 1, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT);
vkt::Image image(*m_device, image_create_info, vkt::no_mem);
auto buffer_info = vkt::Buffer::CreateInfo(4 * 1024 * 1024, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
vkt::Buffer buffer(*m_device, buffer_info, vkt::no_mem);
VkMemoryRequirements image_mem_reqs = {}, buffer_mem_reqs = {};
vk::GetImageMemoryRequirements(device(), image, &image_mem_reqs);
vk::GetBufferMemoryRequirements(device(), buffer, &buffer_mem_reqs);
VkMemoryAllocateInfo image_alloc_info = vku::InitStructHelper();
VkMemoryAllocateInfo buffer_alloc_info = vku::InitStructHelper();
image_alloc_info.allocationSize = image_mem_reqs.size;
buffer_alloc_info.allocationSize = buffer_mem_reqs.size;
// Create a mask of available memory types *not* supported by these resources,
// and try to use one of them.
VkPhysicalDeviceMemoryProperties memory_properties = {};
vk::GetPhysicalDeviceMemoryProperties(m_device->Physical(), &memory_properties);
uint32_t image_unsupported_mem_type_bits = ((1 << memory_properties.memoryTypeCount) - 1) & ~image_mem_reqs.memoryTypeBits;
// can't have protected bit because feature bit is not added
bool found_type =
m_device->Physical().SetMemoryType(image_unsupported_mem_type_bits, &image_alloc_info, 0,
VK_MEMORY_PROPERTY_PROTECTED_BIT | VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD);
if (image_unsupported_mem_type_bits != 0 && found_type) {
vkt::DeviceMemory memory(*m_device, image_alloc_info);
m_errorMonitor->SetDesiredError("VUID-vkBindImageMemory-memory-01047");
vk::BindImageMemory(device(), image, memory, 0);
m_errorMonitor->VerifyFound();
}
uint32_t buffer_unsupported_mem_type_bits = ((1 << memory_properties.memoryTypeCount) - 1) & ~buffer_mem_reqs.memoryTypeBits;
found_type = m_device->Physical().SetMemoryType(buffer_unsupported_mem_type_bits, &buffer_alloc_info, 0,
VK_MEMORY_PROPERTY_PROTECTED_BIT | VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD);
if (buffer_unsupported_mem_type_bits != 0 && found_type) {
vkt::DeviceMemory memory(*m_device, buffer_alloc_info);
m_errorMonitor->SetDesiredError("VUID-vkBindBufferMemory-memory-01035");
vk::BindBufferMemory(device(), buffer, memory, 0);
m_errorMonitor->VerifyFound();
}
}
TEST_F(NegativeMemory, BindMemoryNoCheckBuffer) {
TEST_DESCRIPTION("Tests case were no call to memory requirements was made prior to binding");
RETURN_IF_SKIP(Init());
VkBufferCreateInfo buffer_create_info = vku::InitStructHelper();
buffer_create_info.size = 1024;
buffer_create_info.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
// Create 2 buffers, one that is checked and one that isn't by GetBufferMemoryRequirements
vkt::Buffer buffer(*m_device, buffer_create_info, vkt::no_mem);
vkt::Buffer unchecked_buffer(*m_device, buffer_create_info, vkt::no_mem);
VkMemoryRequirements buffer_mem_reqs = {};
vk::GetBufferMemoryRequirements(device(), buffer, &buffer_mem_reqs);
VkMemoryAllocateInfo buffer_alloc_info = vku::InitStructHelper();
// Leave some extra space for alignment wiggle room
buffer_alloc_info.allocationSize = buffer_mem_reqs.size + buffer_mem_reqs.alignment;
ASSERT_TRUE(m_device->Physical().SetMemoryType(buffer_mem_reqs.memoryTypeBits, &buffer_alloc_info, 0));
vkt::DeviceMemory buffer_mem(*m_device, buffer_alloc_info);
vkt::DeviceMemory unchecked_buffer_mem(*m_device, buffer_alloc_info);
if (buffer_mem_reqs.alignment > 1) {
VkDeviceSize buffer_offset = 1;
m_errorMonitor->SetDesiredError("VUID-vkBindBufferMemory-None-10739");
vk::BindBufferMemory(device(), buffer, buffer_mem, buffer_offset);
m_errorMonitor->VerifyFound();
// Should trigger same VUID even when image was never checked
// this makes an assumption that the driver will return the same image requirements for same createImageInfo where even
// being close to running out of heap space
m_errorMonitor->SetDesiredError("VUID-vkBindBufferMemory-None-10739");
vk::BindBufferMemory(device(), unchecked_buffer, unchecked_buffer_mem, buffer_offset);
m_errorMonitor->VerifyFound();
}
}
TEST_F(NegativeMemory, BindMemoryNoCheckImage) {
TEST_DESCRIPTION("Tests case were no call to memory requirements was made prior to binding");
RETURN_IF_SKIP(Init());
VkImageCreateInfo image_create_info =
vkt::Image::ImageCreateInfo2D(256, 256, 1, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT);
// Create 2 images, one that is checked and one that isn't by GetImageMemoryRequirements
vkt::Image image(*m_device, image_create_info, vkt::no_mem);
vkt::Image unchecked_image(*m_device, image_create_info, vkt::no_mem);
VkMemoryRequirements image_mem_reqs = {};
vk::GetImageMemoryRequirements(device(), image, &image_mem_reqs);
VkMemoryAllocateInfo image_alloc_info = vku::InitStructHelper();
// Leave some extra space for alignment wiggle room
image_alloc_info.allocationSize = image_mem_reqs.size + image_mem_reqs.alignment;
ASSERT_TRUE(m_device->Physical().SetMemoryType(image_mem_reqs.memoryTypeBits, &image_alloc_info, 0));
vkt::DeviceMemory image_mem(*m_device, image_alloc_info);
vkt::DeviceMemory unchecked_image_mem(*m_device, image_alloc_info);
// single-plane image
if (image_mem_reqs.alignment > 1) {
VkDeviceSize image_offset = 1;
m_errorMonitor->SetDesiredError("VUID-vkBindImageMemory-None-10735");
vk::BindImageMemory(device(), image, image_mem, image_offset);
m_errorMonitor->VerifyFound();
// Should trigger same VUID even when image was never checked
// this makes an assumption that the driver will return the same image requirements for same createImageInfo where even
// being close to running out of heap space
m_errorMonitor->SetDesiredError("VUID-vkBindImageMemory-None-10735");
vk::BindImageMemory(device(), unchecked_image, unchecked_image_mem, image_offset);
m_errorMonitor->VerifyFound();
}
}
TEST_F(NegativeMemory, BindMemoryNoCheckMultiPlane) {
TEST_DESCRIPTION("Tests case were no call to memory requirements was made prior to binding");
AddRequiredExtensions(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_BIND_MEMORY_2_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
// Check for support of format used by all multi-planar tests
const VkFormat mp_format = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM;
VkFormatProperties mp_format_properties;
vk::GetPhysicalDeviceFormatProperties(m_device->Physical(), mp_format, &mp_format_properties);
if (!((mp_format_properties.optimalTilingFeatures & VK_FORMAT_FEATURE_DISJOINT_BIT) &&
(mp_format_properties.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT))) {
GTEST_SKIP() << "test rely on a supported disjoint format";
}
VkImageCreateInfo mp_image_create_info = vkt::Image::ImageCreateInfo2D(256, 256, 1, 1, mp_format, VK_IMAGE_USAGE_SAMPLED_BIT);
mp_image_create_info.flags = VK_IMAGE_CREATE_DISJOINT_BIT;
// Array represent planes for disjoint images
VkDeviceMemory mp_image_mem[2] = {VK_NULL_HANDLE, VK_NULL_HANDLE};
VkDeviceMemory mp_unchecked_image_mem[2] = {VK_NULL_HANDLE, VK_NULL_HANDLE};
VkMemoryRequirements2 mp_image_mem_reqs2[2];
VkMemoryAllocateInfo mp_image_alloc_info[2];
vkt::Image mp_image(*m_device, mp_image_create_info, vkt::no_mem);
vkt::Image mp_unchecked_image(*m_device, mp_image_create_info, vkt::no_mem);
VkImagePlaneMemoryRequirementsInfo image_plane_req = vku::InitStructHelper();
image_plane_req.planeAspect = VK_IMAGE_ASPECT_PLANE_0_BIT;
VkImageMemoryRequirementsInfo2 mem_req_info2 = vku::InitStructHelper(&image_plane_req);
mem_req_info2.image = mp_image;
mp_image_mem_reqs2[0] = vku::InitStructHelper();
vk::GetImageMemoryRequirements2KHR(device(), &mem_req_info2, &mp_image_mem_reqs2[0]);
image_plane_req.planeAspect = VK_IMAGE_ASPECT_PLANE_1_BIT;
mp_image_mem_reqs2[1] = vku::InitStructHelper();
vk::GetImageMemoryRequirements2KHR(device(), &mem_req_info2, &mp_image_mem_reqs2[1]);
mp_image_alloc_info[0] = vku::InitStructHelper();
mp_image_alloc_info[1] = vku::InitStructHelper();
mp_image_alloc_info[0].allocationSize = mp_image_mem_reqs2[0].memoryRequirements.size;
ASSERT_TRUE(
m_device->Physical().SetMemoryType(mp_image_mem_reqs2[0].memoryRequirements.memoryTypeBits, &mp_image_alloc_info[0], 0));
// Leave some extra space for alignment wiggle room
mp_image_alloc_info[1].allocationSize =
mp_image_mem_reqs2[1].memoryRequirements.size + mp_image_mem_reqs2[1].memoryRequirements.alignment;
ASSERT_TRUE(
m_device->Physical().SetMemoryType(mp_image_mem_reqs2[1].memoryRequirements.memoryTypeBits, &mp_image_alloc_info[1], 0));
ASSERT_EQ(VK_SUCCESS, vk::AllocateMemory(device(), &mp_image_alloc_info[0], NULL, &mp_image_mem[0]));
ASSERT_EQ(VK_SUCCESS, vk::AllocateMemory(device(), &mp_image_alloc_info[1], NULL, &mp_image_mem[1]));
ASSERT_EQ(VK_SUCCESS, vk::AllocateMemory(device(), &mp_image_alloc_info[0], NULL, &mp_unchecked_image_mem[0]));
ASSERT_EQ(VK_SUCCESS, vk::AllocateMemory(device(), &mp_image_alloc_info[1], NULL, &mp_unchecked_image_mem[1]));
// Sets an invalid offset to plane 1
if (mp_image_mem_reqs2[1].memoryRequirements.alignment > 1) {
VkBindImagePlaneMemoryInfo plane_memory_info[2];
plane_memory_info[0] = vku::InitStructHelper();
plane_memory_info[0].planeAspect = VK_IMAGE_ASPECT_PLANE_0_BIT;
plane_memory_info[1] = vku::InitStructHelper();
plane_memory_info[1].planeAspect = VK_IMAGE_ASPECT_PLANE_1_BIT;
VkBindImageMemoryInfo bind_image_info[2];
bind_image_info[0] = vku::InitStructHelper(&plane_memory_info[0]);
bind_image_info[0].image = mp_image;
bind_image_info[0].memory = mp_image_mem[0];
bind_image_info[0].memoryOffset = 0;
bind_image_info[1] = vku::InitStructHelper(&plane_memory_info[1]);
bind_image_info[1].image = mp_image;
bind_image_info[1].memory = mp_image_mem[1];
bind_image_info[1].memoryOffset = 1; // off alignment
m_errorMonitor->SetDesiredError("VUID-VkBindImageMemoryInfo-pNext-01620");
vk::BindImageMemory2KHR(device(), 2, bind_image_info);
m_errorMonitor->VerifyFound();
// Should trigger same VUID even when image was never checked
// this makes an assumption that the driver will return the same image requirements for same createImageInfo where even
// being close to running out of heap space
bind_image_info[0].image = mp_unchecked_image;
bind_image_info[0].memory = mp_unchecked_image_mem[0];
bind_image_info[1].image = mp_unchecked_image;
bind_image_info[1].memory = mp_unchecked_image_mem[1];
m_errorMonitor->SetDesiredError("VUID-VkBindImageMemoryInfo-pNext-01620");
vk::BindImageMemory2KHR(device(), 2, bind_image_info);
m_errorMonitor->VerifyFound();
}
vk::FreeMemory(device(), mp_image_mem[0], NULL);
vk::FreeMemory(device(), mp_image_mem[1], NULL);
vk::FreeMemory(device(), mp_unchecked_image_mem[0], NULL);
vk::FreeMemory(device(), mp_unchecked_image_mem[1], NULL);
}
TEST_F(NegativeMemory, BindMemory2BindInfos) {
TEST_DESCRIPTION("These tests deal with VK_KHR_bind_memory_2 and invalid VkBindImageMemoryInfo* pBindInfos");
AddRequiredExtensions(VK_KHR_BIND_MEMORY_2_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
VkImageCreateInfo image_create_info =
vkt::Image::ImageCreateInfo2D(256, 256, 1, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT);
// Create 2 image with 2 memory objects
vkt::Image image_a(*m_device, image_create_info, vkt::no_mem);
vkt::Image image_b(*m_device, image_create_info, vkt::no_mem);
VkMemoryRequirements image_mem_reqs = {};
vk::GetImageMemoryRequirements(device(), image_a, &image_mem_reqs);
VkMemoryAllocateInfo image_alloc_info = vku::InitStructHelper();
image_alloc_info.allocationSize = image_mem_reqs.size;
ASSERT_TRUE(m_device->Physical().SetMemoryType(image_mem_reqs.memoryTypeBits, &image_alloc_info, 0));
vkt::DeviceMemory image_a_mem(*m_device, image_alloc_info);
vk::GetImageMemoryRequirements(device(), image_b, &image_mem_reqs);
image_alloc_info.allocationSize = image_mem_reqs.size;
ASSERT_TRUE(m_device->Physical().SetMemoryType(image_mem_reqs.memoryTypeBits, &image_alloc_info, 0));
vkt::DeviceMemory image_b_mem(*m_device, image_alloc_info);
// Try binding same image twice in array
VkBindImageMemoryInfo bind_image_info[3];
bind_image_info[0] = vku::InitStructHelper();
bind_image_info[0].image = image_a;
bind_image_info[0].memory = image_a_mem;
bind_image_info[0].memoryOffset = 0;
bind_image_info[1] = vku::InitStructHelper();
bind_image_info[1].image = image_b;
bind_image_info[1].memory = image_b_mem;
bind_image_info[1].memoryOffset = 0;
bind_image_info[2] = bind_image_info[0]; // duplicate bind
m_errorMonitor->SetDesiredError("VUID-vkBindImageMemory2-pBindInfos-04006");
vk::BindImageMemory2KHR(device(), 3, bind_image_info);
m_errorMonitor->VerifyFound();
// Bind same image to 2 different memory in same array
bind_image_info[1].image = image_a;
m_errorMonitor->SetDesiredError("VUID-vkBindImageMemory2-pBindInfos-04006");
vk::BindImageMemory2KHR(device(), 2, bind_image_info);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeMemory, BindMemory2BindInfosMultiPlane) {
TEST_DESCRIPTION("These tests deal with VK_KHR_bind_memory_2 and invalid VkBindImageMemoryInfo* pBindInfos");
AddRequiredExtensions(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_BIND_MEMORY_2_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
VkImageCreateInfo image_create_info =
vkt::Image::ImageCreateInfo2D(256, 256, 1, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT);
const VkFormat mp_format = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM;
// Check for support of format used by all multi-planar tests
VkFormatProperties mp_format_properties;
vk::GetPhysicalDeviceFormatProperties(m_device->Physical(), mp_format, &mp_format_properties);
if (!((mp_format_properties.optimalTilingFeatures & VK_FORMAT_FEATURE_DISJOINT_BIT) &&
(mp_format_properties.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT))) {
GTEST_SKIP() << "test rely on a supported disjoint format";
}
// Creat 1 normal, not disjoint image
vkt::Image normal_image(*m_device, image_create_info, vkt::no_mem);
VkMemoryRequirements image_mem_reqs = {};
vk::GetImageMemoryRequirements(device(), normal_image, &image_mem_reqs);
VkMemoryAllocateInfo image_alloc_info = vku::InitStructHelper();
image_alloc_info.allocationSize = image_mem_reqs.size;
ASSERT_TRUE(m_device->Physical().SetMemoryType(image_mem_reqs.memoryTypeBits, &image_alloc_info, 0));
vkt::DeviceMemory normal_image_mem(*m_device, image_alloc_info);
// Create 2 disjoint images with memory backing each plane
VkImageCreateInfo mp_image_create_info = image_create_info;
mp_image_create_info.format = mp_format;
mp_image_create_info.flags = VK_IMAGE_CREATE_DISJOINT_BIT;
VkDeviceMemory mp_image_a_mem[2] = {VK_NULL_HANDLE, VK_NULL_HANDLE};
VkDeviceMemory mp_image_b_mem[2] = {VK_NULL_HANDLE, VK_NULL_HANDLE};
vkt::Image mp_image_a(*m_device, mp_image_create_info, vkt::no_mem);
vkt::Image mp_image_b(*m_device, mp_image_create_info, vkt::no_mem);
auto allocate = [this](VkImage mp_image, VkDeviceMemory *mp_image_mem, VkImageAspectFlagBits plane) {
VkImagePlaneMemoryRequirementsInfo image_plane_req = vku::InitStructHelper();
image_plane_req.planeAspect = plane;
VkImageMemoryRequirementsInfo2 mem_req_info2 = vku::InitStructHelper(&image_plane_req);
mem_req_info2.image = mp_image;
VkMemoryRequirements2 mp_image_mem_reqs2 = vku::InitStructHelper();
vk::GetImageMemoryRequirements2KHR(device(), &mem_req_info2, &mp_image_mem_reqs2);
VkMemoryAllocateInfo mp_image_alloc_info = vku::InitStructHelper();
mp_image_alloc_info.allocationSize = mp_image_mem_reqs2.memoryRequirements.size;
ASSERT_TRUE(
m_device->Physical().SetMemoryType(mp_image_mem_reqs2.memoryRequirements.memoryTypeBits, &mp_image_alloc_info, 0));
vk::AllocateMemory(device(), &mp_image_alloc_info, NULL, mp_image_mem);
};
allocate(mp_image_a, &mp_image_a_mem[0], VK_IMAGE_ASPECT_PLANE_0_BIT);
allocate(mp_image_a, &mp_image_a_mem[1], VK_IMAGE_ASPECT_PLANE_1_BIT);
allocate(mp_image_b, &mp_image_b_mem[0], VK_IMAGE_ASPECT_PLANE_0_BIT);
allocate(mp_image_b, &mp_image_b_mem[1], VK_IMAGE_ASPECT_PLANE_1_BIT);
VkBindImagePlaneMemoryInfo plane_memory_info[2];
plane_memory_info[0] = vku::InitStructHelper();
plane_memory_info[0].planeAspect = VK_IMAGE_ASPECT_PLANE_0_BIT;
plane_memory_info[1] = vku::InitStructHelper();
plane_memory_info[1].planeAspect = VK_IMAGE_ASPECT_PLANE_1_BIT;
// set all sType and memoryOffset as they are the same
VkBindImageMemoryInfo bind_image_info[6];
for (int i = 0; i < 6; i++) {
bind_image_info[i] = vku::InitStructHelper();
bind_image_info[i].memoryOffset = 0;
}
// Try only binding part of image_b
bind_image_info[0].pNext = (void *)&plane_memory_info[0];
bind_image_info[0].image = mp_image_a;
bind_image_info[0].memory = mp_image_a_mem[0];
bind_image_info[1].pNext = (void *)&plane_memory_info[1];
bind_image_info[1].image = mp_image_a;
bind_image_info[1].memory = mp_image_a_mem[1];
bind_image_info[2].pNext = (void *)&plane_memory_info[0];
bind_image_info[2].image = mp_image_b;
bind_image_info[2].memory = mp_image_b_mem[0];
m_errorMonitor->SetDesiredError("VUID-vkBindImageMemory2-pBindInfos-02858");
vk::BindImageMemory2KHR(device(), 3, bind_image_info);
m_errorMonitor->VerifyFound();
// Same thing, but mix in a non-disjoint image
bind_image_info[3].pNext = nullptr;
bind_image_info[3].image = normal_image;
bind_image_info[3].memory = normal_image_mem;
m_errorMonitor->SetDesiredError("VUID-vkBindImageMemory2-pBindInfos-02858");
vk::BindImageMemory2KHR(device(), 4, bind_image_info);
m_errorMonitor->VerifyFound();
// Try binding image_b plane 1 twice
// Valid case where binding disjoint and non-disjoint
bind_image_info[4].pNext = (void *)&plane_memory_info[1];
bind_image_info[4].image = mp_image_b;
bind_image_info[4].memory = mp_image_b_mem[1];
bind_image_info[5].pNext = (void *)&plane_memory_info[1];
bind_image_info[5].image = mp_image_b;
bind_image_info[5].memory = mp_image_b_mem[1];
m_errorMonitor->SetDesiredError("VUID-vkBindImageMemory2-pBindInfos-04006");
vk::BindImageMemory2KHR(device(), 6, bind_image_info);
m_errorMonitor->VerifyFound();
// Try binding image_a with no plane specified
bind_image_info[0].pNext = nullptr;
m_errorMonitor->SetDesiredError("VUID-VkBindImageMemoryInfo-image-07736");
vk::BindImageMemory2KHR(device(), 1, bind_image_info);
m_errorMonitor->VerifyFound();
bind_image_info[0].pNext = (void *)&plane_memory_info[0];
// Valid case of binding 2 disjoint image and normal image by removing duplicate
vk::BindImageMemory2KHR(device(), 5, bind_image_info);
vk::FreeMemory(device(), mp_image_a_mem[0], nullptr);
vk::FreeMemory(device(), mp_image_a_mem[1], nullptr);
vk::FreeMemory(device(), mp_image_b_mem[0], nullptr);
vk::FreeMemory(device(), mp_image_b_mem[1], nullptr);
}
TEST_F(NegativeMemory, BindMemoryToDestroyedObject) {
RETURN_IF_SKIP(Init());
// Create an image object, allocate memory, destroy the object and then try
// to bind it
VkImage image;
VkMemoryRequirements mem_reqs;
VkImageCreateInfo image_create_info =
vkt::Image::ImageCreateInfo2D(32, 32, 1, 1, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT);
vk::CreateImage(device(), &image_create_info, nullptr, &image);
VkMemoryAllocateInfo mem_alloc = vku::InitStructHelper();
mem_alloc.allocationSize = 0;
mem_alloc.memoryTypeIndex = 0;
vk::GetImageMemoryRequirements(device(), image, &mem_reqs);
mem_alloc.allocationSize = mem_reqs.size;
bool pass = m_device->Physical().SetMemoryType(mem_reqs.memoryTypeBits, &mem_alloc, 0);
ASSERT_TRUE(pass);
vkt::DeviceMemory mem(*m_device, mem_alloc);
// Introduce validation failure, destroy Image object before binding
vk::DestroyImage(device(), image, nullptr);
// Now Try to bind memory to this destroyed object
m_errorMonitor->SetDesiredError("VUID-vkBindImageMemory-image-parameter");
vk::BindImageMemory(device(), image, mem, 0);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeMemory, AllocationCount) {
VkResult err = VK_SUCCESS;
const int max_mems = 32;
VkDeviceMemory mems[max_mems + 1];
RETURN_IF_SKIP(InitFramework());
PFN_vkSetPhysicalDeviceLimitsEXT fpvkSetPhysicalDeviceLimitsEXT = nullptr;
PFN_vkGetOriginalPhysicalDeviceLimitsEXT fpvkGetOriginalPhysicalDeviceLimitsEXT = nullptr;
if (!LoadDeviceProfileLayer(fpvkSetPhysicalDeviceLimitsEXT, fpvkGetOriginalPhysicalDeviceLimitsEXT)) {
GTEST_SKIP() << "Failed to load device profile layer.";
}
VkPhysicalDeviceProperties props;
fpvkGetOriginalPhysicalDeviceLimitsEXT(Gpu(), &props.limits);
if (props.limits.maxMemoryAllocationCount > max_mems) {
props.limits.maxMemoryAllocationCount = max_mems;
fpvkSetPhysicalDeviceLimitsEXT(Gpu(), &props.limits);
}
RETURN_IF_SKIP(InitState());
m_errorMonitor->SetDesiredError("VUID-vkAllocateMemory-maxMemoryAllocationCount-04101");
VkMemoryAllocateInfo mem_alloc = vku::InitStructHelper();
mem_alloc.memoryTypeIndex = 0;
mem_alloc.allocationSize = 4;
int i;
for (i = 0; i <= max_mems; i++) {
err = vk::AllocateMemory(device(), &mem_alloc, NULL, &mems[i]);
if (err != VK_SUCCESS) {
break;
}
}
m_errorMonitor->VerifyFound();
for (int j = 0; j < i; j++) {
vk::FreeMemory(device(), mems[j], NULL);
}
}
TEST_F(NegativeMemory, ImageMemoryNotBound) {
TEST_DESCRIPTION("Attempt to draw with an image which has not had memory bound to it.");
RETURN_IF_SKIP(Init());
const VkFormat tex_format = VK_FORMAT_B8G8R8A8_UNORM;
VkImageCreateInfo image_create_info = vkt::Image::ImageCreateInfo2D(
32, 32, 1, 1, tex_format, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
vkt::Image image(*m_device, image_create_info, vkt::no_mem);
// Have to bind memory to image before recording cmd in cmd buffer using it
VkMemoryRequirements mem_reqs;
bool pass;
VkMemoryAllocateInfo mem_alloc = vku::InitStructHelper();
mem_alloc.memoryTypeIndex = 0;
vk::GetImageMemoryRequirements(device(), image, &mem_reqs);
mem_alloc.allocationSize = mem_reqs.size;
pass = m_device->Physical().SetMemoryType(mem_reqs.memoryTypeBits, &mem_alloc, 0);
ASSERT_TRUE(pass);
vkt::DeviceMemory image_mem(*m_device, mem_alloc);
// Introduce error, do not call vk::BindImageMemory(device(), image, image_mem, 0);
m_errorMonitor->SetDesiredError("VUID-vkCmdClearColorImage-image-00003");
m_command_buffer.Begin();
VkClearColorValue ccv;
ccv.float32[0] = 1.0f;
ccv.float32[1] = 1.0f;
ccv.float32[2] = 1.0f;
ccv.float32[3] = 1.0f;
VkImageSubresourceRange isr = {};
isr.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
isr.baseArrayLayer = 0;
isr.baseMipLevel = 0;
isr.layerCount = 1;
isr.levelCount = 1;
vk::CmdClearColorImage(m_command_buffer, image, VK_IMAGE_LAYOUT_GENERAL, &ccv, 1, &isr);
m_command_buffer.End();
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeMemory, BufferMemoryNotBound) {
TEST_DESCRIPTION("Attempt to copy from a buffer which has not had memory bound to it.");
RETURN_IF_SKIP(Init());
vkt::Image image(*m_device, 128, 128, VK_FORMAT_B8G8R8A8_UNORM,
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
VkBufferCreateInfo buf_info = vku::InitStructHelper();
buf_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
buf_info.size = 1024;
vkt::Buffer buffer(*m_device, buf_info, vkt::no_mem);
VkMemoryAllocateInfo alloc_info = vku::InitStructHelper();
alloc_info.allocationSize = 1024;
VkMemoryRequirements mem_reqs;
vk::GetBufferMemoryRequirements(device(), buffer, &mem_reqs);
if (!m_device->Physical().SetMemoryType(mem_reqs.memoryTypeBits, &alloc_info, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)) {
GTEST_SKIP() << "Failed to set memory type";
}
VkBufferImageCopy region = {};
region.bufferRowLength = 16;
region.bufferImageHeight = 16;
region.imageSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1};
region.imageExtent = {4, 4, 1};
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdCopyBufferToImage-srcBuffer-00176");
vk::CmdCopyBufferToImage(m_command_buffer, buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeMemory, DedicatedAllocationBinding) {
AddRequiredExtensions(VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
VkMemoryPropertyFlags mem_flags = 0;
const VkDeviceSize resource_size = 1024;
auto buffer_info = vkt::Buffer::CreateInfo(resource_size, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
vkt::Buffer buffer(*m_device, buffer_info, vkt::no_mem);
auto buffer_alloc_info = vkt::DeviceMemory::GetResourceAllocInfo(*m_device, buffer.MemoryRequirements(), mem_flags);
VkMemoryDedicatedAllocateInfo buffer_dedicated_info = vku::InitStructHelper();
buffer_dedicated_info.buffer = buffer;
buffer_alloc_info.pNext = &buffer_dedicated_info;
vkt::DeviceMemory dedicated_buffer_memory(*m_device, buffer_alloc_info);
vkt::Buffer wrong_buffer(*m_device, buffer_info, vkt::no_mem);
// Bind with wrong buffer
m_errorMonitor->SetDesiredError("VUID-vkBindBufferMemory-memory-01508");
vk::BindBufferMemory(*m_device, wrong_buffer, dedicated_buffer_memory, 0);
m_errorMonitor->VerifyFound();
// Bind with non-zero offset (same VUID)
m_errorMonitor->SetDesiredError("VUID-vkBindBufferMemory-memory-01508"); // offset must be zero
m_errorMonitor->SetDesiredError("VUID-vkBindBufferMemory-None-10741"); // offset pushes us past size
auto offset = buffer.MemoryRequirements().alignment;
vk::BindBufferMemory(*m_device, buffer, dedicated_buffer_memory, offset);
m_errorMonitor->VerifyFound();
// Bind correctly (depends on the "skip" above)
vk::BindBufferMemory(*m_device, buffer, dedicated_buffer_memory, 0);
// And for images...
auto image_info =
vkt::Image::ImageCreateInfo2D(resource_size, 1, 1, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_TRANSFER_DST_BIT);
vkt::Image image(*m_device, image_info, vkt::no_mem);
vkt::Image wrong_image(*m_device, image_info, vkt::no_mem);
VkMemoryDedicatedAllocateInfo image_dedicated_info = vku::InitStructHelper();
image_dedicated_info.image = image;
auto image_alloc_info = vkt::DeviceMemory::GetResourceAllocInfo(*m_device, image.MemoryRequirements(), mem_flags);
image_alloc_info.pNext = &image_dedicated_info;
vkt::DeviceMemory dedicated_image_memory(*m_device, image_alloc_info);
// Bind with wrong image
m_errorMonitor->SetDesiredError("VUID-vkBindImageMemory-memory-02628");
vk::BindImageMemory(*m_device, wrong_image, dedicated_image_memory, 0);
m_errorMonitor->VerifyFound();
// Bind with non-zero offset (same VUID)
m_errorMonitor->SetDesiredError("VUID-vkBindImageMemory-memory-02628"); // offset must be zero
m_errorMonitor->SetDesiredError("VUID-vkBindImageMemory-None-10737"); // offset pushes us past size
auto image_offset = image.MemoryRequirements().alignment;
vk::BindImageMemory(*m_device, image, dedicated_image_memory, image_offset);
m_errorMonitor->VerifyFound();
// Bind correctly (depends on the "skip" above)
vk::BindImageMemory(*m_device, image, dedicated_image_memory, 0);
}
TEST_F(NegativeMemory, DedicatedAllocationImageAliasing) {
AddRequiredExtensions(VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME);
AddRequiredExtensions(VK_NV_DEDICATED_ALLOCATION_IMAGE_ALIASING_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::dedicatedAllocationImageAliasing);
RETURN_IF_SKIP(Init());
VkMemoryPropertyFlags mem_flags = 0;
const VkDeviceSize resource_size = 1024;
auto image_info =
vkt::Image::ImageCreateInfo2D(resource_size, 1, 1, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_TRANSFER_DST_BIT);
vkt::Image image(*m_device, image_info, vkt::no_mem);
vkt::Image identical_image(*m_device, image_info, vkt::no_mem);
vkt::Image post_delete_image(*m_device, image_info, vkt::no_mem);
VkMemoryDedicatedAllocateInfo image_dedicated_info = vku::InitStructHelper();
image_dedicated_info.image = image;
auto image_alloc_info = vkt::DeviceMemory::GetResourceAllocInfo(*m_device, image.MemoryRequirements(), mem_flags);
image_alloc_info.pNext = &image_dedicated_info;
vkt::DeviceMemory dedicated_image_memory(*m_device, image_alloc_info);
// Bind with different but identical image
vk::BindImageMemory(*m_device, identical_image, dedicated_image_memory, 0);
image_info =
vkt::Image::ImageCreateInfo2D(resource_size - 1, 1, 1, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_TRANSFER_DST_BIT);
vkt::Image smaller_image(*m_device, image_info, vkt::no_mem);
// Bind with a smaller image
vk::BindImageMemory(*m_device, smaller_image, dedicated_image_memory, 0);
image_info =
vkt::Image::ImageCreateInfo2D(resource_size + 1, 1, 1, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_TRANSFER_DST_BIT);
vkt::Image larger_image(*m_device, image_info, vkt::no_mem);
// Bind with a larger image (not supported, and not enough memory)
m_errorMonitor->SetDesiredError("VUID-vkBindImageMemory-memory-02629");
if (larger_image.MemoryRequirements().size > image.MemoryRequirements().size) {
m_errorMonitor->SetDesiredError("VUID-vkBindImageMemory-None-10737");
}
vk::BindImageMemory(*m_device, larger_image, dedicated_image_memory, 0);
m_errorMonitor->VerifyFound();
// Bind with non-zero offset
m_errorMonitor->SetDesiredError("VUID-vkBindImageMemory-memory-02629"); // offset must be zero
m_errorMonitor->SetDesiredError("VUID-vkBindImageMemory-None-10737"); // offset pushes us past size
auto image_offset = image.MemoryRequirements().alignment;
vk::BindImageMemory(*m_device, image, dedicated_image_memory, image_offset);
m_errorMonitor->VerifyFound();
// Bind correctly (depends on the "skip" above)
vk::BindImageMemory(*m_device, image, dedicated_image_memory, 0);
image.Destroy(); // destroy the original image
vk::BindImageMemory(*m_device, post_delete_image, dedicated_image_memory, 0);
}
TEST_F(NegativeMemory, BufferDeviceAddressEXT) {
TEST_DESCRIPTION("Test VK_EXT_buffer_device_address.");
AddRequiredExtensions(VK_EXT_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
RETURN_IF_SKIP(InitFramework());
VkPhysicalDeviceBufferAddressFeaturesEXT buffer_device_address_features = vku::InitStructHelper();
GetPhysicalDeviceFeatures2(buffer_device_address_features);
buffer_device_address_features.bufferDeviceAddressCaptureReplay = VK_FALSE;
RETURN_IF_SKIP(InitState(nullptr, &buffer_device_address_features));
InitRenderTarget();
VkBufferCreateInfo buffer_create_info = vku::InitStructHelper();
buffer_create_info.size = sizeof(uint32_t);
buffer_create_info.usage = VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
buffer_create_info.flags = VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT;
CreateBufferTest(buffer_create_info, "VUID-VkBufferCreateInfo-flags-03338");
buffer_create_info.flags = 0;
VkBufferDeviceAddressCreateInfoEXT addr_ci = vku::InitStructHelper();
addr_ci.deviceAddress = 1;
buffer_create_info.pNext = &addr_ci;
CreateBufferTest(buffer_create_info, "VUID-VkBufferCreateInfo-deviceAddress-02604");
buffer_create_info.pNext = nullptr;
vkt::Buffer buffer(*m_device, buffer_create_info, vkt::no_mem);
VkBufferDeviceAddressInfo info = vku::InitStructHelper();
info.buffer = buffer;
m_errorMonitor->SetDesiredError("VUID-vkGetBufferDeviceAddress-bufferDeviceAddress-03324");
vk::GetBufferDeviceAddressEXT(device(), &info);
m_errorMonitor->VerifyFound();
VkMemoryRequirements buffer_mem_reqs = {};
vk::GetBufferMemoryRequirements(device(), buffer, &buffer_mem_reqs);
VkMemoryAllocateInfo buffer_alloc_info = vku::InitStructHelper();
buffer_alloc_info.allocationSize = buffer_mem_reqs.size;
m_device->Physical().SetMemoryType(buffer_mem_reqs.memoryTypeBits, &buffer_alloc_info, 0);
vkt::DeviceMemory buffer_mem(*m_device, buffer_alloc_info);
vk::BindBufferMemory(device(), buffer, buffer_mem, 0);
}
TEST_F(NegativeMemory, BufferDeviceAddressEXTDisabled) {
TEST_DESCRIPTION("Test VK_EXT_buffer_device_address.");
AddRequiredExtensions(VK_EXT_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
RETURN_IF_SKIP(InitFramework());
VkPhysicalDeviceBufferAddressFeaturesEXT buffer_device_address_features = vku::InitStructHelper();
buffer_device_address_features.bufferDeviceAddress = VK_FALSE;
buffer_device_address_features.bufferDeviceAddressCaptureReplay = VK_FALSE;
RETURN_IF_SKIP(InitState(nullptr, &buffer_device_address_features));
InitRenderTarget();
VkBufferCreateInfo buffer_create_info = vku::InitStructHelper();
buffer_create_info.size = sizeof(uint32_t);
buffer_create_info.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
vkt::Buffer buffer(*m_device, buffer_create_info, vkt::no_mem);
VkBufferDeviceAddressInfo info = vku::InitStructHelper();
info.buffer = buffer;
m_errorMonitor->SetDesiredError("VUID-vkGetBufferDeviceAddress-bufferDeviceAddress-03324");
m_errorMonitor->SetDesiredError("VUID-VkBufferDeviceAddressInfo-buffer-02601");
m_errorMonitor->SetDesiredError("VUID-vkGetBufferDeviceAddress-bufferDeviceAddress-03324");
vk::GetBufferDeviceAddressEXT(device(), &info);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeMemory, BufferDeviceAddressKHRCaptureReplayFeature) {
SetTargetApiVersion(VK_API_VERSION_1_2);
AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkBufferCreateInfo buffer_create_info = vku::InitStructHelper();
buffer_create_info.size = sizeof(uint32_t);
buffer_create_info.usage = VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
buffer_create_info.flags = VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT;
CreateBufferTest(buffer_create_info, "VUID-VkBufferCreateInfo-flags-03338");
}
TEST_F(NegativeMemory, BufferDeviceAddressKHR) {
TEST_DESCRIPTION("Test VK_KHR_buffer_device_address.");
SetTargetApiVersion(VK_API_VERSION_1_2);
AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
AddRequiredFeature(vkt::Feature::bufferDeviceAddressCaptureReplay);
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkBufferCreateInfo buffer_create_info = vku::InitStructHelper();
buffer_create_info.size = sizeof(uint32_t);
buffer_create_info.usage = VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
buffer_create_info.flags = 0;
VkBufferOpaqueCaptureAddressCreateInfo addr_ci = vku::InitStructHelper();
addr_ci.opaqueCaptureAddress = 1;
buffer_create_info.pNext = &addr_ci;
CreateBufferTest(buffer_create_info, "VUID-VkBufferCreateInfo-opaqueCaptureAddress-03337");
buffer_create_info.pNext = nullptr;
vkt::Buffer buffer(*m_device, buffer_create_info, vkt::no_mem);
VkBufferDeviceAddressInfo info = vku::InitStructHelper();
info.buffer = buffer;
m_errorMonitor->SetDesiredError("VUID-vkGetBufferDeviceAddress-bufferDeviceAddress-03324");
vk::GetBufferDeviceAddressKHR(device(), &info);
m_errorMonitor->VerifyFound();
VkMemoryRequirements buffer_mem_reqs = {};
vk::GetBufferMemoryRequirements(device(), buffer, &buffer_mem_reqs);
VkMemoryAllocateInfo buffer_alloc_info = vku::InitStructHelper();
buffer_alloc_info.allocationSize = buffer_mem_reqs.size;
m_device->Physical().SetMemoryType(buffer_mem_reqs.memoryTypeBits, &buffer_alloc_info, 0);
vkt::DeviceMemory buffer_mem(*m_device, buffer_alloc_info);
m_errorMonitor->SetDesiredError("VUID-vkBindBufferMemory-bufferDeviceAddress-03339");
vk::BindBufferMemory(device(), buffer, buffer_mem, 0);
m_errorMonitor->VerifyFound();
VkDeviceMemoryOpaqueCaptureAddressInfo mem_opaque_addr_info = vku::InitStructHelper();
mem_opaque_addr_info.memory = buffer_mem;
m_errorMonitor->SetDesiredError("VUID-VkDeviceMemoryOpaqueCaptureAddressInfo-memory-03336");
vk::GetDeviceMemoryOpaqueCaptureAddressKHR(device(), &mem_opaque_addr_info);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-VkDeviceMemoryOpaqueCaptureAddressInfo-memory-03336");
vk::GetDeviceMemoryOpaqueCaptureAddressKHR(device(), &mem_opaque_addr_info);
m_errorMonitor->VerifyFound();
VkMemoryAllocateFlagsInfo alloc_flags = vku::InitStructHelper();
alloc_flags.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT;
buffer_alloc_info.pNext = &alloc_flags;
vkt::DeviceMemory buffer_mem2(*m_device, buffer_alloc_info);
mem_opaque_addr_info.memory = buffer_mem2;
m_errorMonitor->SetDesiredError("VUID-vkGetDeviceMemoryOpaqueCaptureAddress-pInfo-10727");
vk::GetDeviceMemoryOpaqueCaptureAddressKHR(device(), &mem_opaque_addr_info);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeMemory, BufferDeviceAddressKHRDisabled) {
TEST_DESCRIPTION("Test VK_KHR_buffer_device_address.");
SetTargetApiVersion(VK_API_VERSION_1_2);
AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkBufferCreateInfo buffer_create_info = vku::InitStructHelper();
buffer_create_info.size = sizeof(uint32_t);
buffer_create_info.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
vkt::Buffer buffer(*m_device, buffer_create_info, vkt::no_mem);
VkBufferDeviceAddressInfo info = vku::InitStructHelper();
info.buffer = buffer;
m_errorMonitor->SetDesiredError("VUID-vkGetBufferDeviceAddress-bufferDeviceAddress-03324");
m_errorMonitor->SetDesiredError("VUID-VkBufferDeviceAddressInfo-buffer-02601");
m_errorMonitor->SetDesiredError("VUID-vkGetBufferDeviceAddress-bufferDeviceAddress-03324");
vk::GetBufferDeviceAddressKHR(device(), &info);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkGetBufferOpaqueCaptureAddress-pInfo-10725");
m_errorMonitor->SetDesiredError("VUID-VkBufferDeviceAddressInfo-buffer-02601");
m_errorMonitor->SetDesiredError("VUID-vkGetBufferOpaqueCaptureAddress-None-03326");
vk::GetBufferOpaqueCaptureAddressKHR(device(), &info);
m_errorMonitor->VerifyFound();
VkMemoryRequirements buffer_mem_reqs = {};
vk::GetBufferMemoryRequirements(device(), buffer, &buffer_mem_reqs);
VkMemoryAllocateInfo buffer_alloc_info = vku::InitStructHelper();
buffer_alloc_info.allocationSize = buffer_mem_reqs.size;
m_device->Physical().SetMemoryType(buffer_mem_reqs.memoryTypeBits, &buffer_alloc_info, 0);
VkDeviceMemory buffer_mem;
vk::AllocateMemory(device(), &buffer_alloc_info, NULL, &buffer_mem);
VkDeviceMemoryOpaqueCaptureAddressInfo mem_opaque_addr_info = vku::InitStructHelper();
mem_opaque_addr_info.memory = buffer_mem;
m_errorMonitor->SetDesiredError("VUID-vkGetDeviceMemoryOpaqueCaptureAddress-None-03334");
m_errorMonitor->SetDesiredError("VUID-VkDeviceMemoryOpaqueCaptureAddressInfo-memory-03336");
vk::GetDeviceMemoryOpaqueCaptureAddressKHR(device(), &mem_opaque_addr_info);
m_errorMonitor->VerifyFound();
vk::FreeMemory(device(), buffer_mem, NULL);
VkMemoryAllocateFlagsInfo alloc_flags = vku::InitStructHelper();
alloc_flags.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT | VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT;
buffer_alloc_info.pNext = &alloc_flags;
m_errorMonitor->SetDesiredError("VUID-VkMemoryAllocateInfo-flags-03330");
m_errorMonitor->SetDesiredError("VUID-VkMemoryAllocateInfo-flags-03331");
vk::AllocateMemory(device(), &buffer_alloc_info, NULL, &buffer_mem);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeMemory, MemoryType) {
// Attempts to allocate from a memory type that doesn't exist
RETURN_IF_SKIP(Init());
VkPhysicalDeviceMemoryProperties memory_info;
vk::GetPhysicalDeviceMemoryProperties(Gpu(), &memory_info);
m_errorMonitor->SetDesiredError("VUID-vkAllocateMemory-pAllocateInfo-01714");
VkMemoryAllocateInfo mem_alloc = vku::InitStructHelper();
mem_alloc.memoryTypeIndex = memory_info.memoryTypeCount;
mem_alloc.allocationSize = 4;
VkDeviceMemory mem;
vk::AllocateMemory(device(), &mem_alloc, NULL, &mem);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeMemory, AllocationBeyondHeapSize) {
// Attempts to allocate a single piece of memory that's larger than the heap size
RETURN_IF_SKIP(Init());
VkPhysicalDeviceMemoryProperties memory_info;
vk::GetPhysicalDeviceMemoryProperties(Gpu(), &memory_info);
// This can be triggered due to the extremely large allocation
m_errorMonitor->SetAllowedFailureMsg("UNASSIGNED-vkAllocateMemory-maxMemoryAllocationSize");
m_errorMonitor->SetDesiredError("VUID-vkAllocateMemory-pAllocateInfo-01713");
VkMemoryAllocateInfo mem_alloc = vku::InitStructHelper();
mem_alloc.memoryTypeIndex = 0;
mem_alloc.allocationSize = memory_info.memoryHeaps[memory_info.memoryTypes[0].heapIndex].size + 1;
VkDeviceMemory mem;
vk::AllocateMemory(device(), &mem_alloc, NULL, &mem);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeMemory, DeviceCoherentMemoryDisabledAMD) {
// Attempts to allocate device coherent memory without enabling the extension/feature
AddRequiredExtensions(VK_AMD_DEVICE_COHERENT_MEMORY_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
if (IsPlatformMockICD()) {
GTEST_SKIP() << "Test not supported by MockICD, does not support the necessary memory type";
}
// Find a memory type that includes the device coherent memory property
VkPhysicalDeviceMemoryProperties memory_info;
vk::GetPhysicalDeviceMemoryProperties(Gpu(), &memory_info);
uint32_t deviceCoherentMemoryTypeIndex = memory_info.memoryTypeCount; // Set to an invalid value just in case
for (uint32_t i = 0; i < memory_info.memoryTypeCount; ++i) {
if ((memory_info.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD) != 0) {
deviceCoherentMemoryTypeIndex = i;
break;
}
}
if (deviceCoherentMemoryTypeIndex == memory_info.memoryTypeCount) {
GTEST_SKIP() << "Valid memory type index not found";
}
m_errorMonitor->SetDesiredError("VUID-vkAllocateMemory-deviceCoherentMemory-02790");
VkMemoryAllocateInfo mem_alloc = vku::InitStructHelper();
mem_alloc.memoryTypeIndex = deviceCoherentMemoryTypeIndex;
mem_alloc.allocationSize = 4;
VkDeviceMemory mem;
vk::AllocateMemory(device(), &mem_alloc, NULL, &mem);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeMemory, DedicatedAllocation) {
TEST_DESCRIPTION("Create invalid requests to dedicated allocation of memory");
// Both VK_KHR_dedicated_allocation and VK_KHR_sampler_ycbcr_conversion supported in 1.1
// Quicke to set 1.1 then check all extensions in 1.0
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredFeature(vkt::Feature::sparseBinding);
RETURN_IF_SKIP(Init());
const VkFormat disjoint_format = VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM;
const VkFormat normal_format = VK_FORMAT_R8G8B8A8_UNORM;
VkFormatProperties format_properties;
vk::GetPhysicalDeviceFormatProperties(m_device->Physical(), disjoint_format, &format_properties);
bool sparse_support = (m_device->Physical().Features().sparseBinding == VK_TRUE);
bool disjoint_support = ((format_properties.optimalTilingFeatures & VK_FORMAT_FEATURE_DISJOINT_BIT) != 0);
VkBufferCreateInfo buffer_create_info = vku::InitStructHelper();
buffer_create_info.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
buffer_create_info.size = 2048;
VkImageCreateInfo image_create_info =
vkt::Image::ImageCreateInfo2D(64, 64, 1, 1, normal_format, VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
// Create Images and Buffers without any memory backing
VkImage normal_image = VK_NULL_HANDLE;
vk::CreateImage(device(), &image_create_info, nullptr, &normal_image);
VkBuffer normal_buffer = VK_NULL_HANDLE;
vk::CreateBuffer(device(), &buffer_create_info, nullptr, &normal_buffer);
VkImage sparse_image = VK_NULL_HANDLE;
VkBuffer sparse_buffer = VK_NULL_HANDLE;
if (sparse_support == true) {
image_create_info.flags = VK_IMAGE_CREATE_SPARSE_BINDING_BIT;
vk::CreateImage(device(), &image_create_info, nullptr, &sparse_image);
buffer_create_info.flags = VK_BUFFER_CREATE_SPARSE_BINDING_BIT;
vk::CreateBuffer(device(), &buffer_create_info, nullptr, &sparse_buffer);
}
VkImage disjoint_image = VK_NULL_HANDLE;
if (disjoint_support == true) {
image_create_info.format = disjoint_format;
image_create_info.flags = VK_IMAGE_CREATE_DISJOINT_BIT;
vk::CreateImage(device(), &image_create_info, nullptr, &disjoint_image);
}
VkDeviceMemory device_memory;
VkMemoryDedicatedAllocateInfo dedicated_allocate_info = vku::InitStructHelper();
VkMemoryAllocateInfo memory_allocate_info = vku::InitStructHelper(&dedicated_allocate_info);
memory_allocate_info.memoryTypeIndex = 0;
memory_allocate_info.allocationSize = 64;
// Both image and buffer set in dedicated allocation
dedicated_allocate_info.image = normal_image;
dedicated_allocate_info.buffer = normal_buffer;
m_errorMonitor->SetDesiredError("VUID-VkMemoryDedicatedAllocateInfo-image-01432");
vk::AllocateMemory(device(), &memory_allocate_info, NULL, &device_memory);
m_errorMonitor->VerifyFound();
if (sparse_support == true) {
VkMemoryRequirements sparse_image_memory_req;
vk::GetImageMemoryRequirements(device(), sparse_image, &sparse_image_memory_req);
VkMemoryRequirements sparse_buffer_memory_req;
vk::GetBufferMemoryRequirements(device(), sparse_buffer, &sparse_buffer_memory_req);
dedicated_allocate_info.image = sparse_image;
dedicated_allocate_info.buffer = VK_NULL_HANDLE;
memory_allocate_info.allocationSize = sparse_image_memory_req.size;
m_errorMonitor->SetDesiredError("VUID-VkMemoryDedicatedAllocateInfo-image-01434");
vk::AllocateMemory(device(), &memory_allocate_info, NULL, &device_memory);
m_errorMonitor->VerifyFound();
dedicated_allocate_info.image = VK_NULL_HANDLE;
dedicated_allocate_info.buffer = sparse_buffer;
memory_allocate_info.allocationSize = sparse_buffer_memory_req.size;
m_errorMonitor->SetDesiredError("VUID-VkMemoryDedicatedAllocateInfo-buffer-01436");
vk::AllocateMemory(device(), &memory_allocate_info, NULL, &device_memory);
m_errorMonitor->VerifyFound();
}
if (disjoint_support == true) {
VkImagePlaneMemoryRequirementsInfo image_plane_req = vku::InitStructHelper();
image_plane_req.planeAspect = VK_IMAGE_ASPECT_PLANE_2_BIT;
VkImageMemoryRequirementsInfo2 mem_req_info2 = vku::InitStructHelper(&image_plane_req);
mem_req_info2.image = disjoint_image;
VkMemoryRequirements2 mem_req2 = vku::InitStructHelper();
vk::GetImageMemoryRequirements2(device(), &mem_req_info2, &mem_req2);
dedicated_allocate_info.image = disjoint_image;
dedicated_allocate_info.buffer = VK_NULL_HANDLE;
memory_allocate_info.allocationSize = mem_req2.memoryRequirements.size;
m_errorMonitor->SetDesiredError("VUID-VkMemoryDedicatedAllocateInfo-image-01797");
vk::AllocateMemory(device(), &memory_allocate_info, NULL, &device_memory);
m_errorMonitor->VerifyFound();
}
VkMemoryRequirements normal_image_memory_req;
vk::GetImageMemoryRequirements(device(), normal_image, &normal_image_memory_req);
VkMemoryRequirements normal_buffer_memory_req;
vk::GetBufferMemoryRequirements(device(), normal_buffer, &normal_buffer_memory_req);
// Set allocation size to be not equal to memory requirement
memory_allocate_info.allocationSize = normal_image_memory_req.size - 1;
dedicated_allocate_info.image = normal_image;
dedicated_allocate_info.buffer = VK_NULL_HANDLE;
m_errorMonitor->SetDesiredError("VUID-VkMemoryDedicatedAllocateInfo-image-02964");
vk::AllocateMemory(device(), &memory_allocate_info, NULL, &device_memory);
m_errorMonitor->VerifyFound();
memory_allocate_info.allocationSize = normal_buffer_memory_req.size - 1;
dedicated_allocate_info.image = VK_NULL_HANDLE;
dedicated_allocate_info.buffer = normal_buffer;
m_errorMonitor->SetDesiredError("VUID-VkMemoryDedicatedAllocateInfo-buffer-02965");
vk::AllocateMemory(device(), &memory_allocate_info, NULL, &device_memory);
m_errorMonitor->VerifyFound();
vk::DestroyImage(device(), normal_image, nullptr);
vk::DestroyBuffer(device(), normal_buffer, nullptr);
if (sparse_support == true) {
vk::DestroyImage(device(), sparse_image, nullptr);
vk::DestroyBuffer(device(), sparse_buffer, nullptr);
}
if (disjoint_support == true) {
vk::DestroyImage(device(), disjoint_image, nullptr);
}
}
TEST_F(NegativeMemory, MemoryRequirements) {
TEST_DESCRIPTION("Create invalid requests to image and buffer memory requirements.");
AddRequiredExtensions(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_BIND_MEMORY_2_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
// Need to make sure disjoint is supported for format
// Also need to support an arbitrary image usage feature
VkFormatProperties format_properties;
vk::GetPhysicalDeviceFormatProperties(m_device->Physical(), VK_FORMAT_G8_B8R8_2PLANE_420_UNORM, &format_properties);
if (!((format_properties.optimalTilingFeatures & VK_FORMAT_FEATURE_DISJOINT_BIT) &&
(format_properties.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT))) {
GTEST_SKIP() << "test requires disjoint/sampled feature bit on format";
}
VkImageCreateInfo image_create_info = vku::InitStructHelper();
image_create_info.imageType = VK_IMAGE_TYPE_2D;
image_create_info.format = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM;
image_create_info.extent = {64, 64, 1};
image_create_info.mipLevels = 1;
image_create_info.arrayLayers = 1;
image_create_info.samples = VK_SAMPLE_COUNT_1_BIT;
image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL;
image_create_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
image_create_info.flags = VK_IMAGE_CREATE_DISJOINT_BIT;
VkImage image;
VkResult err = vk::CreateImage(device(), &image_create_info, NULL, &image);
ASSERT_EQ(VK_SUCCESS, err);
m_errorMonitor->SetDesiredError("VUID-vkGetImageMemoryRequirements-image-01588");
VkMemoryRequirements memory_requirements;
vk::GetImageMemoryRequirements(device(), image, &memory_requirements);
m_errorMonitor->VerifyFound();
VkImageMemoryRequirementsInfo2 mem_req_info2 = vku::InitStructHelper();
mem_req_info2.image = image;
VkMemoryRequirements2 mem_req2 = vku::InitStructHelper();
m_errorMonitor->SetDesiredError("VUID-VkImageMemoryRequirementsInfo2-image-01589");
vk::GetImageMemoryRequirements2KHR(device(), &mem_req_info2, &mem_req2);
m_errorMonitor->VerifyFound();
// Point to a 3rd plane for a 2-plane format
VkImagePlaneMemoryRequirementsInfo image_plane_req = vku::InitStructHelper();
image_plane_req.planeAspect = VK_IMAGE_ASPECT_PLANE_2_BIT;
mem_req_info2.pNext = &image_plane_req;
mem_req_info2.image = image;
m_errorMonitor->SetDesiredError("VUID-VkImagePlaneMemoryRequirementsInfo-planeAspect-02281");
vk::GetImageMemoryRequirements2KHR(device(), &mem_req_info2, &mem_req2);
m_errorMonitor->VerifyFound();
// Test with a non planar image aspect also
image_plane_req.planeAspect = VK_IMAGE_ASPECT_COLOR_BIT;
mem_req_info2.pNext = &image_plane_req;
mem_req_info2.image = image;
m_errorMonitor->SetDesiredError("VUID-VkImagePlaneMemoryRequirementsInfo-planeAspect-02281");
vk::GetImageMemoryRequirements2KHR(device(), &mem_req_info2, &mem_req2);
m_errorMonitor->VerifyFound();
vk::DestroyImage(device(), image, nullptr);
// Recreate image without Disjoint bit
image_create_info.flags = 0;
err = vk::CreateImage(device(), &image_create_info, NULL, &image);
ASSERT_EQ(VK_SUCCESS, err);
image_plane_req.planeAspect = VK_IMAGE_ASPECT_PLANE_0_BIT;
mem_req_info2.pNext = &image_plane_req;
mem_req_info2.image = image;
m_errorMonitor->SetDesiredError("VUID-VkImageMemoryRequirementsInfo2-image-01590");
vk::GetImageMemoryRequirements2KHR(device(), &mem_req_info2, &mem_req2);
m_errorMonitor->VerifyFound();
vk::DestroyImage(device(), image, nullptr);
// Recreate image with single plane format and with Disjoint bit
image_create_info.flags = 0;
image_create_info.format = VK_FORMAT_R8G8B8A8_UNORM;
err = vk::CreateImage(device(), &image_create_info, NULL, &image);
ASSERT_EQ(VK_SUCCESS, err);
image_plane_req.planeAspect = VK_IMAGE_ASPECT_PLANE_0_BIT;
mem_req_info2.pNext = &image_plane_req;
mem_req_info2.image = image;
// Disjoint bit isn't set as likely not even supported by non-planar format
m_errorMonitor->SetUnexpectedError("VUID-VkImageMemoryRequirementsInfo2-image-01590");
m_errorMonitor->SetDesiredError("VUID-VkImageMemoryRequirementsInfo2-image-02280");
vk::GetImageMemoryRequirements2KHR(device(), &mem_req_info2, &mem_req2);
m_errorMonitor->VerifyFound();
vk::DestroyImage(device(), image, nullptr);
}
TEST_F(NegativeMemory, MemoryAllocatepNextChain) {
AddRequiredExtensions(VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME);
AddRequiredExtensions(VK_NV_EXTERNAL_MEMORY_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
VkDeviceMemory mem;
VkMemoryAllocateInfo mem_alloc = vku::InitStructHelper();
mem_alloc.memoryTypeIndex = 0;
mem_alloc.allocationSize = 4;
// pNext chain includes both VkExportMemoryAllocateInfo and VkExportMemoryAllocateInfoNV
VkExportMemoryAllocateInfoNV export_memory_info_nv = vku::InitStructHelper();
export_memory_info_nv.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_NV;
VkExportMemoryAllocateInfo export_memory_info = vku::InitStructHelper(&export_memory_info_nv);
export_memory_info.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
m_errorMonitor->SetDesiredError("VUID-VkMemoryAllocateInfo-pNext-00640");
mem_alloc.pNext = &export_memory_info;
vk::AllocateMemory(device(), &mem_alloc, NULL, &mem);
m_errorMonitor->VerifyFound();
}
#ifdef VK_USE_PLATFORM_WIN32_KHR
TEST_F(NegativeMemory, MemoryAllocatepNextChainWin32) {
AddRequiredExtensions(VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME);
AddRequiredExtensions(VK_NV_EXTERNAL_MEMORY_EXTENSION_NAME);
AddRequiredExtensions(VK_NV_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
VkDeviceMemory mem;
VkMemoryAllocateInfo mem_alloc = vku::InitStructHelper();
mem_alloc.memoryTypeIndex = 0;
mem_alloc.allocationSize = 4;
// pNext chain includes both VkExportMemoryAllocateInfo and VkExportMemoryWin32HandleInfoNV
{
VkExportMemoryWin32HandleInfoNV export_memory_info_win32_nv = vku::InitStructHelper();
export_memory_info_win32_nv.pAttributes = nullptr;
export_memory_info_win32_nv.dwAccess = 0;
VkExportMemoryAllocateInfo export_memory_info = vku::InitStructHelper(&export_memory_info_win32_nv);
export_memory_info.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
m_errorMonitor->SetDesiredError("VUID-VkMemoryAllocateInfo-pNext-00640");
mem_alloc.pNext = &export_memory_info;
vk::AllocateMemory(device(), &mem_alloc, NULL, &mem);
m_errorMonitor->VerifyFound();
}
// pNext chain includes both VkImportMemoryWin32HandleInfoKHR and VkImportMemoryWin32HandleInfoNV
{
VkImportMemoryWin32HandleInfoKHR import_memory_info_win32_khr = vku::InitStructHelper();
import_memory_info_win32_khr.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT;
VkImportMemoryWin32HandleInfoNV import_memory_info_win32_nv = vku::InitStructHelper(&import_memory_info_win32_khr);
import_memory_info_win32_nv.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_NV;
m_errorMonitor->SetUnexpectedError("VUID-VkMemoryAllocateInfo-None-06657");
m_errorMonitor->SetDesiredError("VUID-VkMemoryAllocateInfo-pNext-00641");
mem_alloc.pNext = &import_memory_info_win32_nv;
vk::AllocateMemory(device(), &mem_alloc, NULL, &mem);
m_errorMonitor->VerifyFound();
}
}
#endif // VK_USE_PLATFORM_WIN32_KHR
TEST_F(NegativeMemory, DeviceImageMemoryRequirementsSwapchain) {
TEST_DESCRIPTION("Validate usage of VkDeviceImageMemoryRequirementsKHR.");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_KHR_MAINTENANCE_4_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
VkImageSwapchainCreateInfoKHR image_swapchain_create_info = vku::InitStructHelper();
image_swapchain_create_info.swapchain = m_swapchain;
VkImageCreateInfo image_create_info = vku::InitStructHelper(&image_swapchain_create_info);
image_create_info.imageType = VK_IMAGE_TYPE_2D;
image_create_info.format = VK_FORMAT_R8G8B8A8_UNORM;
image_create_info.extent = {32, 32, 1};
image_create_info.mipLevels = 1;
image_create_info.samples = VK_SAMPLE_COUNT_1_BIT;
image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL;
image_create_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
image_create_info.arrayLayers = 1;
VkDeviceImageMemoryRequirementsKHR device_image_memory_requirements = vku::InitStructHelper();
device_image_memory_requirements.pCreateInfo = &image_create_info;
device_image_memory_requirements.planeAspect = VK_IMAGE_ASPECT_COLOR_BIT;
VkMemoryRequirements2 memory_requirements = vku::InitStructHelper();
m_errorMonitor->SetDesiredError("VUID-VkDeviceImageMemoryRequirements-pCreateInfo-06416");
vk::GetDeviceImageMemoryRequirementsKHR(device(), &device_image_memory_requirements, &memory_requirements);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeMemory, DeviceImageMemoryRequirementsDisjoint) {
TEST_DESCRIPTION("Validate usage of VkDeviceImageMemoryRequirementsKHR.");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_KHR_MAINTENANCE_4_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
const VkFormat format = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM;
VkFormatProperties format_properties;
vk::GetPhysicalDeviceFormatProperties(m_device->Physical(), format, &format_properties);
if ((format_properties.optimalTilingFeatures & VK_FORMAT_FEATURE_DISJOINT_BIT) == 0) {
GTEST_SKIP() << "Test requires disjoint support extensions";
}
VkImageCreateInfo image_create_info = vku::InitStructHelper();
image_create_info.imageType = VK_IMAGE_TYPE_2D;
image_create_info.format = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM;
image_create_info.flags = VK_IMAGE_CREATE_DISJOINT_BIT;
image_create_info.extent = {32, 32, 1};
image_create_info.mipLevels = 1;
image_create_info.samples = VK_SAMPLE_COUNT_1_BIT;
image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL;
image_create_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
image_create_info.arrayLayers = 1;
VkDeviceImageMemoryRequirementsKHR device_image_memory_requirements = vku::InitStructHelper();
device_image_memory_requirements.pCreateInfo = &image_create_info;
device_image_memory_requirements.planeAspect = VK_IMAGE_ASPECT_NONE;
VkMemoryRequirements2 memory_requirements = vku::InitStructHelper();
m_errorMonitor->SetDesiredError("VUID-VkDeviceImageMemoryRequirements-pCreateInfo-06417");
vk::GetDeviceImageMemoryRequirementsKHR(device(), &device_image_memory_requirements, &memory_requirements);
m_errorMonitor->VerifyFound();
device_image_memory_requirements.planeAspect = VK_IMAGE_ASPECT_PLANE_2_BIT;
m_errorMonitor->SetDesiredError("VUID-VkDeviceImageMemoryRequirements-pCreateInfo-06419");
vk::GetDeviceImageMemoryRequirementsKHR(device(), &device_image_memory_requirements, &memory_requirements);
m_errorMonitor->VerifyFound();
// valid
device_image_memory_requirements.planeAspect = VK_IMAGE_ASPECT_PLANE_1_BIT;
vk::GetDeviceImageMemoryRequirementsKHR(device(), &device_image_memory_requirements, &memory_requirements);
}
TEST_F(NegativeMemory, BindBufferMemoryDeviceGroup) {
TEST_DESCRIPTION("Test VkBindBufferMemoryDeviceGroupInfo.");
SetTargetApiVersion(VK_API_VERSION_1_1);
RETURN_IF_SKIP(InitFramework());
uint32_t physical_device_group_count = 0;
vk::EnumeratePhysicalDeviceGroups(instance(), &physical_device_group_count, nullptr);
if (physical_device_group_count == 0) {
GTEST_SKIP() << "physical_device_group_count is 0";
}
std::vector<VkPhysicalDeviceGroupProperties> physical_device_group(physical_device_group_count,
{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES});
vk::EnumeratePhysicalDeviceGroups(instance(), &physical_device_group_count, physical_device_group.data());
VkDeviceGroupDeviceCreateInfo create_device_pnext = vku::InitStructHelper();
create_device_pnext.physicalDeviceCount = 0;
create_device_pnext.pPhysicalDevices = nullptr;
for (const auto &dg : physical_device_group) {
if (dg.physicalDeviceCount > 1) {
create_device_pnext.physicalDeviceCount = dg.physicalDeviceCount;
create_device_pnext.pPhysicalDevices = dg.physicalDevices;
break;
}
}
if (create_device_pnext.pPhysicalDevices) {
RETURN_IF_SKIP(InitState(nullptr, &create_device_pnext));
} else {
GTEST_SKIP() << "Test requires a physical device group with more than 1 device";
}
auto buffer_info = vkt::Buffer::CreateInfo(4096, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
vkt::Buffer buffer(*m_device, buffer_info, vkt::no_mem);
VkMemoryRequirements buffer_mem_reqs;
vk::GetBufferMemoryRequirements(device(), buffer, &buffer_mem_reqs);
VkMemoryAllocateInfo buffer_alloc_info = vku::InitStructHelper();
buffer_alloc_info.memoryTypeIndex = 0;
buffer_alloc_info.allocationSize = buffer_mem_reqs.size;
vkt::DeviceMemory buffer_memory(*m_device, buffer_alloc_info);
std::vector<uint32_t> device_indices(create_device_pnext.physicalDeviceCount);
VkBindBufferMemoryDeviceGroupInfo bind_buffer_memory_device_group = vku::InitStructHelper();
bind_buffer_memory_device_group.deviceIndexCount = 1;
bind_buffer_memory_device_group.pDeviceIndices = device_indices.data();
VkBindBufferMemoryInfo bind_buffer_info = vku::InitStructHelper(&bind_buffer_memory_device_group);
bind_buffer_info.buffer = buffer;
bind_buffer_info.memory = buffer_memory;
bind_buffer_info.memoryOffset = 0;
m_errorMonitor->SetDesiredError("VUID-VkBindBufferMemoryDeviceGroupInfo-deviceIndexCount-01606");
vk::BindBufferMemory2(device(), 1, &bind_buffer_info);
m_errorMonitor->VerifyFound();
bind_buffer_memory_device_group.deviceIndexCount = create_device_pnext.physicalDeviceCount;
device_indices[0] = create_device_pnext.physicalDeviceCount;
m_errorMonitor->SetDesiredError("VUID-VkBindBufferMemoryDeviceGroupInfo-pDeviceIndices-01607");
vk::BindBufferMemory2(device(), 1, &bind_buffer_info);
m_errorMonitor->VerifyFound();
device_indices[0] = 0;
VkImageCreateInfo image_create_info =
vkt::Image::ImageCreateInfo2D(32, 32, 1, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
vkt::Image image(*m_device, image_create_info, vkt::no_mem);
VkMemoryRequirements image_mem_reqs;
vk::GetBufferMemoryRequirements(device(), buffer, &image_mem_reqs);
VkMemoryAllocateInfo image_alloc_info = vku::InitStructHelper();
image_alloc_info.memoryTypeIndex = 0;
image_alloc_info.allocationSize = image_mem_reqs.size;
vkt::DeviceMemory image_memory(*m_device, image_alloc_info);
VkBindImageMemoryDeviceGroupInfo bind_image_memory_device_group = vku::InitStructHelper();
bind_image_memory_device_group.deviceIndexCount = 1;
bind_image_memory_device_group.pDeviceIndices = device_indices.data();
VkBindImageMemoryInfo bind_image_info = vku::InitStructHelper(&bind_image_memory_device_group);
bind_image_info.image = image;
bind_image_info.memory = image_memory;
bind_image_info.memoryOffset = 0;
m_errorMonitor->SetDesiredError("VUID-VkBindImageMemoryDeviceGroupInfo-deviceIndexCount-01634");
vk::BindImageMemory2(device(), 1, &bind_image_info);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeMemory, MemoryPriorityOutOfRange) {
TEST_DESCRIPTION("Allocate memory with invalid priority.");
AddRequiredExtensions(VK_EXT_MEMORY_PRIORITY_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
VkMemoryPriorityAllocateInfoEXT priority = vku::InitStructHelper();
priority.priority = 2.0f;
VkMemoryAllocateInfo memory_ai = vku::InitStructHelper(&priority);
memory_ai.allocationSize = 0x100000;
memory_ai.memoryTypeIndex = 0;
VkDeviceMemory memory;
m_errorMonitor->SetDesiredError("VUID-VkMemoryPriorityAllocateInfoEXT-priority-02602");
vk::AllocateMemory(*m_device, &memory_ai, nullptr, &memory);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeMemory, SetDeviceMemoryPriority) {
AddRequiredExtensions(VK_EXT_PAGEABLE_DEVICE_LOCAL_MEMORY_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
vkt::Buffer buffer(*m_device, vkt::Buffer::CreateInfo(1024, VK_BUFFER_USAGE_TRANSFER_DST_BIT), vkt::no_mem);
vkt::DeviceMemory buffer_memory(*m_device, vkt::DeviceMemory::GetResourceAllocInfo(*m_device, buffer.MemoryRequirements(), 0));
m_errorMonitor->SetDesiredError("VUID-vkSetDeviceMemoryPriorityEXT-priority-06258");
vk::SetDeviceMemoryPriorityEXT(*m_device, buffer_memory, -0.01f);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkSetDeviceMemoryPriorityEXT-priority-06258");
vk::SetDeviceMemoryPriorityEXT(*m_device, buffer_memory, 1.01f);
m_errorMonitor->VerifyFound();
vk::SetDeviceMemoryPriorityEXT(*m_device, buffer_memory, 1.0f);
}
TEST_F(NegativeMemory, BadMemoryBindMemory2) {
TEST_DESCRIPTION("Bind bogus memory for VkBindImageMemoryInfo::memory ");
AddRequiredExtensions(VK_KHR_BIND_MEMORY_2_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
auto image_ci = vkt::Image::ImageCreateInfo2D(32, 32, 1, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_TRANSFER_DST_BIT);
vkt::Image image(*m_device, image_ci, vkt::no_mem);
VkDeviceMemory bad_memory = CastToHandle<VkDeviceMemory, uintptr_t>(0xbaadbeef);
VkBindImageMemoryInfo image_bind_info = vku::InitStructHelper();
image_bind_info.image = image;
image_bind_info.memory = bad_memory;
image_bind_info.memoryOffset = 0;
m_errorMonitor->SetDesiredError("VUID-VkBindImageMemoryInfo-pNext-01632");
vk::BindImageMemory2KHR(device(), 1, &image_bind_info);
m_errorMonitor->VerifyFound();
}
// TODO - Need a way to trigger Test ICD to fail call
TEST_F(NegativeMemory, DISABLED_PartialBoundBuffer) {
TEST_DESCRIPTION("https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/5527");
AddRequiredExtensions(VK_KHR_BIND_MEMORY_2_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
if (!IsPlatformMockICD()) {
GTEST_SKIP() << "Test needs to force a failure";
}
VkBufferCreateInfo buffer_create_info = vku::InitStructHelper();
buffer_create_info.size = 1024;
buffer_create_info.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
vkt::Buffer buffer_0(*m_device, buffer_create_info, vkt::no_mem);
vkt::Buffer buffer_1(*m_device, buffer_create_info, vkt::no_mem);
VkMemoryAllocateInfo alloc_info = vkt::DeviceMemory::GetResourceAllocInfo(*m_device, buffer_0.MemoryRequirements(), 0);
vkt::DeviceMemory buffer_memory(*m_device, alloc_info);
VkBindBufferMemoryInfo bind_buffer_infos[2];
bind_buffer_infos[0] = vku::InitStructHelper();
bind_buffer_infos[0].buffer = buffer_0;
bind_buffer_infos[0].memory = buffer_memory;
bind_buffer_infos[1] = vku::InitStructHelper();
bind_buffer_infos[1].buffer = buffer_1;
bind_buffer_infos[1].memory = buffer_memory;
VkResult result = vk::BindBufferMemory2KHR(device(), 2, bind_buffer_infos);
if (result == VK_SUCCESS) {
GTEST_SKIP() << "Test needs a to fail call";
}
m_errorMonitor->SetDesiredError("VUID-vkBindBufferMemory-buffer-07459");
vk::BindBufferMemory(device(), buffer_0, buffer_memory, 0);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeMemory, MaxMemoryAllocationSize) {
SetTargetApiVersion(VK_API_VERSION_1_2);
RETURN_IF_SKIP(Init());
if (!IsPlatformMockICD()) {
GTEST_SKIP() << "Can't test well on real hardware";
}
VkPhysicalDeviceVulkan11Properties props11 = vku::InitStructHelper();
GetPhysicalDeviceProperties2(props11);
VkMemoryAllocateInfo alloc_info = vku::InitStructHelper();
alloc_info.allocationSize = props11.maxMemoryAllocationSize + 64;
m_errorMonitor->SetAllowedFailureMsg("VUID-vkAllocateMemory-pAllocateInfo-01713"); // need to bypass stateless
m_errorMonitor->SetDesiredError("UNASSIGNED-vkAllocateMemory-maxMemoryAllocationSize");
vkt::DeviceMemory memory(*m_device, alloc_info);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeMemory, RequiredDedicatedAllocationBuffer) {
SetTargetApiVersion(VK_API_VERSION_1_1);
RETURN_IF_SKIP(Init());
auto buffer_info = vkt::Buffer::CreateInfo(4096, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
vkt::Buffer buffer(*m_device, buffer_info, vkt::no_mem);
vkt::Buffer buffer2(*m_device, buffer_info, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
VkBufferMemoryRequirementsInfo2 buffer_memory_requirements_info = vku::InitStructHelper();
buffer_memory_requirements_info.buffer = buffer;
VkMemoryDedicatedRequirements memory_dedicated_requirements = vku::InitStructHelper();
VkMemoryRequirements2 memory_requirements = vku::InitStructHelper(&memory_dedicated_requirements);
vk::GetBufferMemoryRequirements2(device(), &buffer_memory_requirements_info, &memory_requirements);
// TODO - hard to get this required for buffer, would be good to have way for TestICD to force it on for this test
if (!memory_dedicated_requirements.requiresDedicatedAllocation) {
GTEST_SKIP() << "requiresDedicatedAllocation is false";
}
{
VkMemoryAllocateInfo memory_info = vku::InitStructHelper();
memory_info.allocationSize = memory_requirements.memoryRequirements.size;
bool pass = m_device->Physical().SetMemoryType(memory_requirements.memoryRequirements.memoryTypeBits, &memory_info,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
ASSERT_TRUE(pass);
vkt::DeviceMemory device_memory(*m_device, memory_info);
VkBindBufferMemoryInfo bind_buffer_memory_info = vku::InitStructHelper();
bind_buffer_memory_info.buffer = buffer;
bind_buffer_memory_info.memory = device_memory;
bind_buffer_memory_info.memoryOffset = 0u;
m_errorMonitor->SetDesiredError("VUID-VkBindBufferMemoryInfo-buffer-01444");
vk::BindBufferMemory2(device(), 1u, &bind_buffer_memory_info);
m_errorMonitor->VerifyFound();
}
{
VkMemoryDedicatedAllocateInfo memory_dedicated_allocate_info = vku::InitStructHelper();
memory_dedicated_allocate_info.buffer = buffer2;
VkMemoryAllocateInfo memory_info = vku::InitStructHelper(&memory_dedicated_allocate_info);
memory_info.allocationSize = memory_requirements.memoryRequirements.size;
bool pass = m_device->Physical().SetMemoryType(memory_requirements.memoryRequirements.memoryTypeBits, &memory_info,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
ASSERT_TRUE(pass);
vkt::DeviceMemory device_memory(*m_device, memory_info);
m_errorMonitor->SetDesiredError("VUID-vkBindBufferMemory-memory-01508");
m_errorMonitor->SetDesiredError("VUID-vkBindBufferMemory-buffer-01444");
vk::BindBufferMemory(device(), buffer, device_memory, 0u);
m_errorMonitor->VerifyFound();
}
}
TEST_F(NegativeMemory, MapMemoryWithMapPlacedFlag) {
TEST_DESCRIPTION("Test vkCmdUpdateBuffer");
AddRequiredExtensions(VK_EXT_MAP_MEMORY_PLACED_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
const VkDeviceSize allocation_size = 8192u;
VkMemoryAllocateInfo memory_info = vku::InitStructHelper();
memory_info.allocationSize = allocation_size;
bool pass = m_device->Physical().SetMemoryType(vvl::kU32Max, &memory_info, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
ASSERT_TRUE(pass);
vkt::DeviceMemory memory(*m_device, memory_info);
void *data;
m_errorMonitor->SetDesiredError("VUID-vkMapMemory-flags-09568");
vk::MapMemory(device(), memory, 0u, 4u, VK_MEMORY_MAP_PLACED_BIT_EXT, &data);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeMemory, RequiredDedicatedAllocationImage) {
SetTargetApiVersion(VK_API_VERSION_1_1);
RETURN_IF_SKIP(Init());
VkImageCreateInfo image_create_info =
vkt::Image::ImageCreateInfo2D(32u, 32u, 1u, 1u, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT);
vkt::Image image(*m_device, image_create_info, vkt::no_mem);
vkt::Image image2(*m_device, image_create_info, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
VkImageMemoryRequirementsInfo2 image_memory_requirements_info = vku::InitStructHelper();
image_memory_requirements_info.image = image;
VkMemoryDedicatedRequirements memory_dedicated_requirements = vku::InitStructHelper();
VkMemoryRequirements2 memory_requirements = vku::InitStructHelper(&memory_dedicated_requirements);
vk::GetImageMemoryRequirements2(device(), &image_memory_requirements_info, &memory_requirements);
if (!memory_dedicated_requirements.requiresDedicatedAllocation) {
GTEST_SKIP() << "requiresDedicatedAllocation is false";
}
{
VkMemoryAllocateInfo memory_info = vku::InitStructHelper();
memory_info.allocationSize = memory_requirements.memoryRequirements.size;
bool pass = m_device->Physical().SetMemoryType(memory_requirements.memoryRequirements.memoryTypeBits, &memory_info,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
ASSERT_TRUE(pass);
vkt::DeviceMemory device_memory(*m_device, memory_info);
VkBindImageMemoryInfo bind_image_memory_info = vku::InitStructHelper();
bind_image_memory_info.image = image;
bind_image_memory_info.memory = device_memory;
bind_image_memory_info.memoryOffset = 0u;
m_errorMonitor->SetDesiredError("VUID-VkBindImageMemoryInfo-image-01445");
vk::BindImageMemory2(device(), 1u, &bind_image_memory_info);
m_errorMonitor->VerifyFound();
}
{
VkMemoryDedicatedAllocateInfo memory_dedicated_allocate_info = vku::InitStructHelper();
memory_dedicated_allocate_info.image = image2;
VkMemoryAllocateInfo memory_info = vku::InitStructHelper(&memory_dedicated_allocate_info);
memory_info.allocationSize = memory_requirements.memoryRequirements.size;
bool pass = m_device->Physical().SetMemoryType(memory_requirements.memoryRequirements.memoryTypeBits, &memory_info,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
ASSERT_TRUE(pass);
vkt::DeviceMemory device_memory(*m_device, memory_info);
m_errorMonitor->SetDesiredError("VUID-vkBindImageMemory-memory-02628");
m_errorMonitor->SetDesiredError("VUID-vkBindImageMemory-image-01445");
vk::BindImageMemory(device(), image, device_memory, 0u);
m_errorMonitor->VerifyFound();
}
}
TEST_F(NegativeMemory, DedicatedAllocationWrongObject) {
SetTargetApiVersion(VK_API_VERSION_1_1);
RETURN_IF_SKIP(Init());
auto buffer_info = vkt::Buffer::CreateInfo(4096u, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
vkt::Buffer buffer(*m_device, buffer_info, vkt::no_mem);
auto image_info = vkt::Image::ImageCreateInfo2D(32u, 32u, 1u, 1u, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT);
vkt::Image image(*m_device, image_info, vkt::no_mem);
VkBufferMemoryRequirementsInfo2 buffer_memory_requirements_info = vku::InitStructHelper();
buffer_memory_requirements_info.buffer = buffer;
VkMemoryDedicatedRequirements buffer_memory_dedicated_requirements = vku::InitStructHelper();
VkMemoryRequirements2 buffer_memory_requirements = vku::InitStructHelper(&buffer_memory_dedicated_requirements);
vk::GetBufferMemoryRequirements2(device(), &buffer_memory_requirements_info, &buffer_memory_requirements);
VkImageMemoryRequirementsInfo2 image_memory_requirements_info = vku::InitStructHelper();
image_memory_requirements_info.image = image;
VkMemoryDedicatedRequirements image_memory_dedicated_requirements = vku::InitStructHelper();
VkMemoryRequirements2 image_memory_requirements = vku::InitStructHelper(&image_memory_dedicated_requirements);
vk::GetImageMemoryRequirements2(device(), &image_memory_requirements_info, &image_memory_requirements);
VkDeviceSize memory_size =
std::max(buffer_memory_requirements.memoryRequirements.size, image_memory_requirements.memoryRequirements.size);
{
VkMemoryDedicatedAllocateInfo memory_dedicated_allocate_info = vku::InitStructHelper();
memory_dedicated_allocate_info.image = VK_NULL_HANDLE;
memory_dedicated_allocate_info.buffer = buffer;
VkMemoryAllocateInfo memory_info = vku::InitStructHelper(&memory_dedicated_allocate_info);
memory_info.allocationSize = memory_size;
bool pass = m_device->Physical().SetMemoryType(image_memory_requirements.memoryRequirements.memoryTypeBits, &memory_info,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
ASSERT_TRUE(pass);
vkt::DeviceMemory device_memory(*m_device, memory_info);
m_errorMonitor->SetDesiredError("VUID-vkBindImageMemory-memory-10926");
vk::BindImageMemory(device(), image, device_memory, 0u);
m_errorMonitor->VerifyFound();
}
{
VkMemoryDedicatedAllocateInfo memory_dedicated_allocate_info = vku::InitStructHelper();
memory_dedicated_allocate_info.image = image;
memory_dedicated_allocate_info.buffer = VK_NULL_HANDLE;
VkMemoryAllocateInfo memory_info = vku::InitStructHelper(&memory_dedicated_allocate_info);
memory_info.allocationSize = memory_size;
bool pass = m_device->Physical().SetMemoryType(buffer_memory_requirements.memoryRequirements.memoryTypeBits, &memory_info,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
ASSERT_TRUE(pass);
vkt::DeviceMemory device_memory(*m_device, memory_info);
m_errorMonitor->SetDesiredError("VUID-vkBindBufferMemory-memory-10925");
vk::BindBufferMemory(device(), buffer, device_memory, 0u);
m_errorMonitor->VerifyFound();
}
}