blob: 51af6ec8811ef063d97eb1eae27e8079e90aa4ae [file] [log] [blame]
/*
* Copyright (c) 2023-2025 LunarG, Inc.
*
* 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 "../framework/layer_validation_tests.h"
#include "../framework/pipeline_helper.h"
class NegativeTileMemoryHeap : public TileMemoryHeapTest {};
TEST_F(NegativeTileMemoryHeap, CreateBufferTest) {
TEST_DESCRIPTION("Use VK_BUFFER_USAGE_TILE_MEMORY_BIT_QCOM without enabling the tileMemoryHeap feature");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_QCOM_TILE_MEMORY_HEAP_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
VkBufferCreateInfo buffer_ci = vku::InitStructHelper();
buffer_ci.size = 4096;
buffer_ci.usage = VK_BUFFER_USAGE_TILE_MEMORY_BIT_QCOM;
CreateBufferTest(buffer_ci, "VUID-VkBufferCreateInfo-tileMemoryHeap-10762");
}
TEST_F(NegativeTileMemoryHeap, CreateBufferProtectedMemoryFlag) {
TEST_DESCRIPTION("Test Protected flag in CreateBuffer with tileMemoryHeap feature");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_QCOM_TILE_MEMORY_HEAP_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::tileMemoryHeap);
AddRequiredFeature(vkt::Feature::protectedMemory);
RETURN_IF_SKIP(Init());
VkBufferCreateInfo buffer_ci = vku::InitStructHelper();
buffer_ci.size = 4096;
buffer_ci.usage = VK_BUFFER_USAGE_TILE_MEMORY_BIT_QCOM;
buffer_ci.flags = VK_BUFFER_CREATE_PROTECTED_BIT;
CreateBufferTest(buffer_ci, "VUID-VkBufferCreateInfo-usage-10763");
}
TEST_F(NegativeTileMemoryHeap, CreateBufferTestIndexUsageFlags) {
TEST_DESCRIPTION("Test Index Usage Flag in CreateBuffer with tileMemoryHeap feature");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_QCOM_TILE_MEMORY_HEAP_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::tileMemoryHeap);
RETURN_IF_SKIP(Init());
VkBufferCreateInfo buffer_ci = vku::InitStructHelper();
buffer_ci.size = 4096;
buffer_ci.usage = VK_BUFFER_USAGE_TILE_MEMORY_BIT_QCOM | VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
CreateBufferTest(buffer_ci, "VUID-VkBufferCreateInfo-usage-10764");
}
TEST_F(NegativeTileMemoryHeap, AllocateMemory) {
TEST_DESCRIPTION("Allocate Tile Memory without the Tile Memory feature enabled.");
AddRequiredExtensions(VK_QCOM_TILE_MEMORY_HEAP_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
VkMemoryAllocateInfo alloc_info = vku::InitStructHelper();
alloc_info.allocationSize = 256;
bool pass = m_device->Physical().SetMemoryType(0xFFFFFFFF, &alloc_info, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 0,
VK_MEMORY_HEAP_TILE_MEMORY_BIT_QCOM);
if (!pass) {
GTEST_SKIP() << "Could not find an eligible Tile Memory Type.";
}
m_errorMonitor->SetDesiredError("VUID-VkTileMemoryBindInfoQCOM-memoryTypeIndex-10976");
vkt::DeviceMemory buffer_memory(*m_device, alloc_info);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeTileMemoryHeap, BindBufferMemorySize) {
TEST_DESCRIPTION("Bind Tile Memory to a Buffer with too small of size");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_QCOM_TILE_MEMORY_HEAP_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::tileMemoryHeap);
RETURN_IF_SKIP(Init());
// Create a Tile Memory Buffer
vkt::Buffer buffer(*m_device,
vkt::Buffer::CreateInfo(4096, VK_BUFFER_USAGE_2_TILE_MEMORY_BIT_QCOM | VK_BUFFER_USAGE_2_STORAGE_BUFFER_BIT),
vkt::no_mem);
// Query Tile Memory Buffer Requirements
VkBufferMemoryRequirementsInfo2 buffer_info = vku::InitStructHelper();
VkTileMemoryRequirementsQCOM tile_mem_reqs = vku::InitStructHelper();
VkMemoryRequirements2 buffer_reqs = vku::InitStructHelper(&tile_mem_reqs);
buffer_info.buffer = buffer;
vk::GetBufferMemoryRequirements2(device(), &buffer_info, &buffer_reqs);
if (tile_mem_reqs.size == 0) {
GTEST_SKIP() << "Buffer not eligible to be bound with Tile Memory.";
}
// Find a memory configuration for the Tile Memory Buffer, otherwise exit
VkMemoryAllocateInfo bad_alloc_info = vku::InitStructHelper();
bad_alloc_info.memoryTypeIndex = 0;
// Purposely subtract 1 from size
bad_alloc_info.allocationSize = tile_mem_reqs.size - 1;
bool pass = m_device->Physical().SetMemoryType(buffer_reqs.memoryRequirements.memoryTypeBits, &bad_alloc_info,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 0, VK_MEMORY_HEAP_TILE_MEMORY_BIT_QCOM);
if (!pass) {
GTEST_SKIP() << "Could not find an eligible Tile Memory Type.";
}
vkt::DeviceMemory buffer_memory(*m_device, bad_alloc_info);
m_errorMonitor->SetDesiredError("VUID-vkBindBufferMemory-memory-10742");
vk::BindBufferMemory(device(), buffer, buffer_memory, 0);
m_errorMonitor->VerifyFound();
VkBindBufferMemoryInfo bind_buffer_info = vku::InitStructHelper();
bind_buffer_info.buffer = buffer;
bind_buffer_info.memory = buffer_memory;
bind_buffer_info.memoryOffset = 0;
m_errorMonitor->SetDesiredError("VUID-VkBindBufferMemoryInfo-memory-10742");
vk::BindBufferMemory2(device(), 1, &bind_buffer_info);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeTileMemoryHeap, BindBufferMemoryAlignment) {
TEST_DESCRIPTION("Bind Tile Memory to a Buffer with an offset that is not a multiple of alignment");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_QCOM_TILE_MEMORY_HEAP_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::tileMemoryHeap);
RETURN_IF_SKIP(Init());
// Create a Tile Memory Buffer
vkt::Buffer buffer(*m_device,
vkt::Buffer::CreateInfo(4096, VK_BUFFER_USAGE_2_TILE_MEMORY_BIT_QCOM | VK_BUFFER_USAGE_2_STORAGE_BUFFER_BIT),
vkt::no_mem);
// Query Tile Memory Buffer Requirements
VkBufferMemoryRequirementsInfo2 buffer_info = vku::InitStructHelper();
VkTileMemoryRequirementsQCOM tile_mem_reqs = vku::InitStructHelper();
VkMemoryRequirements2 buffer_reqs = vku::InitStructHelper(&tile_mem_reqs);
buffer_info.buffer = buffer;
vk::GetBufferMemoryRequirements2(device(), &buffer_info, &buffer_reqs);
if (tile_mem_reqs.size == 0) {
GTEST_SKIP() << "Buffer not eligible to be bound with Tile Memory.";
}
// Find a memory configuration for the Tile Memory Buffer, otherwise exit
const uint32_t badOffset = 1;
VkMemoryAllocateInfo bad_alloc_info = vku::InitStructHelper();
bad_alloc_info.memoryTypeIndex = 0;
// Purposely add 1 to size for offset
bad_alloc_info.allocationSize = tile_mem_reqs.size + badOffset;
bool pass = m_device->Physical().SetMemoryType(buffer_reqs.memoryRequirements.memoryTypeBits, &bad_alloc_info,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 0, VK_MEMORY_HEAP_TILE_MEMORY_BIT_QCOM);
if (!pass) {
GTEST_SKIP() << "Could not find an eligible Tile Memory Type.";
}
vkt::DeviceMemory buffer_memory(*m_device, bad_alloc_info);
m_errorMonitor->SetDesiredError("VUID-vkBindBufferMemory-memory-10740");
vk::BindBufferMemory(device(), buffer, buffer_memory, badOffset);
m_errorMonitor->VerifyFound();
VkBindBufferMemoryInfo bind_buffer_info = vku::InitStructHelper();
bind_buffer_info.buffer = buffer;
bind_buffer_info.memory = buffer_memory;
bind_buffer_info.memoryOffset = badOffset;
m_errorMonitor->SetDesiredError("VUID-VkBindBufferMemoryInfo-memory-10740");
vk::BindBufferMemory2(device(), 1, &bind_buffer_info);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeTileMemoryHeap, CreateImageTest) {
TEST_DESCRIPTION("Use VK_IMAGE_USAGE_TILE_MEMORY_BIT_QCOM in CreateImage without enabling the tileMemoryHeap feature");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_QCOM_TILE_MEMORY_HEAP_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
CreateImageTest(vkt::Image::ImageCreateInfo2D(256, 256, 1, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_TILE_MEMORY_BIT_QCOM),
"VUID-VkImageCreateInfo-tileMemoryHeap-10766");
}
TEST_F(NegativeTileMemoryHeap, BindImageMemorySize) {
TEST_DESCRIPTION("Bind Tile Memory to an Image with too small of size");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_QCOM_TILE_MEMORY_HEAP_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::tileMemoryHeap);
RETURN_IF_SKIP(Init());
// Create a Tile Memory Image
auto image_create_info = vkt::Image::ImageCreateInfo2D(
32u, 32u, 1u, 1u, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TILE_MEMORY_BIT_QCOM);
vkt::Image image(*m_device, image_create_info, vkt::no_mem);
// Query Tile Memory Image Requirements
VkImageMemoryRequirementsInfo2 image_info = vku::InitStructHelper();
VkTileMemoryRequirementsQCOM tile_mem_reqs = vku::InitStructHelper();
VkMemoryRequirements2 image_reqs = vku::InitStructHelper(&tile_mem_reqs);
image_info.image = image;
vk::GetImageMemoryRequirements2(device(), &image_info, &image_reqs);
if (tile_mem_reqs.size == 0) {
GTEST_SKIP() << "Image not eligible to be bound with Tile Memory.";
}
// Find a memory configuration for the Tile Memory Image, otherwise exit
VkMemoryAllocateInfo bad_alloc_info = vku::InitStructHelper();
bad_alloc_info.memoryTypeIndex = 0;
// Purposely subtract 1 from size
bad_alloc_info.allocationSize = tile_mem_reqs.size - 1;
bool pass = m_device->Physical().SetMemoryType(image_reqs.memoryRequirements.memoryTypeBits, &bad_alloc_info,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 0, VK_MEMORY_HEAP_TILE_MEMORY_BIT_QCOM);
if (!pass) {
GTEST_SKIP() << "Could not find an eligible Tile Memory Type.";
}
vkt::DeviceMemory image_memory(*m_device, bad_alloc_info);
m_errorMonitor->SetDesiredError("VUID-vkBindImageMemory-memory-10738");
vk::BindImageMemory(device(), image, image_memory, 0);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeTileMemoryHeap, BindImageMemoryAlignment) {
TEST_DESCRIPTION("Bind Tile Memory to an Image with an offset that is not a multiple of alignment");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_QCOM_TILE_MEMORY_HEAP_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::tileMemoryHeap);
RETURN_IF_SKIP(Init());
// Create a Tile Memory Image
auto image_create_info = vkt::Image::ImageCreateInfo2D(
32u, 32u, 1u, 1u, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TILE_MEMORY_BIT_QCOM);
vkt::Image image(*m_device, image_create_info, vkt::no_mem);
// Query Tile Memory Image Requirements
VkImageMemoryRequirementsInfo2 image_info = vku::InitStructHelper();
VkTileMemoryRequirementsQCOM tile_mem_reqs = vku::InitStructHelper();
VkMemoryRequirements2 image_reqs = vku::InitStructHelper(&tile_mem_reqs);
image_info.image = image;
vk::GetImageMemoryRequirements2(device(), &image_info, &image_reqs);
if (tile_mem_reqs.size == 0) {
GTEST_SKIP() << "Image not eligible to be bound with Tile Memory.";
}
// Find a memory configuration for the Tile Memory Image, otherwise exit
const uint32_t badOffset = 1;
VkMemoryAllocateInfo bad_alloc_info = vku::InitStructHelper();
bad_alloc_info.memoryTypeIndex = 0;
// Purposely add 1 to size for offset
bad_alloc_info.allocationSize = tile_mem_reqs.size + badOffset;
bool pass = m_device->Physical().SetMemoryType(image_reqs.memoryRequirements.memoryTypeBits, &bad_alloc_info,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 0, VK_MEMORY_HEAP_TILE_MEMORY_BIT_QCOM);
if (!pass) {
GTEST_SKIP() << "Could not find an eligible Tile Memory Type.";
}
vkt::DeviceMemory image_memory(*m_device, bad_alloc_info);
m_errorMonitor->SetDesiredError("VUID-vkBindImageMemory-memory-10736");
vk::BindImageMemory(device(), image, image_memory, badOffset);
m_errorMonitor->VerifyFound();
}