blob: 8a9a7f892a831914ac975e8e01da947358b4f302 [file]
/*
* Copyright (c) 2023-2026 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"
#include "../framework/render_pass_helper.h"
#include "utils/math_utils.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;
m_errorMonitor->SetDesiredError("VUID-VkBufferCreateInfo-flags-09641");
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-vkAllocateMemory-tileMemoryHeap-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());
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);
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());
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());
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);
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());
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);
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();
}
TEST_F(NegativeTileMemoryHeap, BindNonTileMemoryCommandBuffer) {
TEST_DESCRIPTION("Bind non Tile Memory with vkCmdBindTileMemoryQCOM in Primary/Secondary Command Buffer.");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_QCOM_TILE_MEMORY_HEAP_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::tileMemoryHeap);
RETURN_IF_SKIP(Init());
VkMemoryAllocateInfo mem_alloc = vku::InitStructHelper();
mem_alloc.allocationSize = 256;
mem_alloc.memoryTypeIndex = 0;
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 (!(memory_info.memoryHeaps[memory_info.memoryTypes[i].heapIndex].flags & VK_MEMORY_HEAP_TILE_MEMORY_BIT_QCOM)) {
mem_alloc.memoryTypeIndex = i;
break;
}
}
if (i >= memory_info.memoryTypeCount) {
GTEST_SKIP() << "No invalid memory type index could be found";
}
vkt::DeviceMemory non_tile_memory(*m_device, mem_alloc);
VkTileMemoryBindInfoQCOM tile_mem_bind_info = vku::InitStructHelper();
tile_mem_bind_info.memory = non_tile_memory;
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-VkTileMemoryBindInfoQCOM-memory-10726");
vk::CmdBindTileMemoryQCOM(m_command_buffer, &tile_mem_bind_info);
m_errorMonitor->VerifyFound();
const VkCommandBufferInheritanceInfo cmdbuff_ii = vku::InitStructHelper(&tile_mem_bind_info);
VkCommandBufferBeginInfo cmdbuff_bi = vku::InitStructHelper();
cmdbuff_bi.pInheritanceInfo = &cmdbuff_ii;
vkt::CommandBuffer secondary(*m_device, m_command_pool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
m_errorMonitor->SetDesiredError("VUID-VkTileMemoryBindInfoQCOM-memory-10726");
vk::BeginCommandBuffer(secondary, &cmdbuff_bi);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeTileMemoryHeap, TileMemoryMismatchResourceCommandBuffer) {
TEST_DESCRIPTION("Mismatch VkDeviceMemory between underlying Resource and Command Buffer");
SetTargetApiVersion(VK_API_VERSION_1_2);
AddRequiredExtensions(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME);
AddRequiredExtensions(VK_QCOM_TILE_MEMORY_HEAP_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::tileMemoryHeap);
AddRequiredFeature(vkt::Feature::dynamicRendering);
RETURN_IF_SKIP(Init());
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);
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 alloc_info = vku::InitStructHelper();
alloc_info.memoryTypeIndex = 0;
alloc_info.allocationSize = tile_mem_reqs.size;
bool pass = m_device->Physical().SetMemoryType(image_reqs.memoryRequirements.memoryTypeBits, &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, alloc_info);
vk::BindImageMemory(device(), image, image_memory, 0);
vkt::ImageView image_view = image.CreateView();
VkFormat color_formats = VK_FORMAT_R8G8B8A8_UNORM;
VkPipelineRenderingCreateInfo pipeline_rendering_info = vku::InitStructHelper();
pipeline_rendering_info.colorAttachmentCount = 1;
pipeline_rendering_info.pColorAttachmentFormats = &color_formats;
CreatePipelineHelper pipe(*this, &pipeline_rendering_info);
pipe.CreateGraphicsPipeline();
VkRenderingAttachmentInfo color_attachment = vku::InitStructHelper();
color_attachment.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
color_attachment.imageView = image_view;
VkRenderingInfo begin_rendering_info = vku::InitStructHelper();
begin_rendering_info.colorAttachmentCount = 1;
begin_rendering_info.pColorAttachments = &color_attachment;
begin_rendering_info.layerCount = 1;
begin_rendering_info.renderArea = {{0, 0}, {32, 32}};
m_command_buffer.Begin();
m_command_buffer.BeginRendering(begin_rendering_info);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-commandBuffer-10746");
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRendering();
VkAttachmentReference2 attachment_ref = vku::InitStructHelper();
attachment_ref.layout = VK_IMAGE_LAYOUT_GENERAL;
attachment_ref.attachment = 0;
VkSubpassDescription2 subpass[2] = {};
subpass[0] = vku::InitStructHelper();
subpass[0].colorAttachmentCount = 1;
subpass[0].pColorAttachments = &attachment_ref;
subpass[1] = vku::InitStructHelper();
subpass[1].colorAttachmentCount = 1;
subpass[1].pColorAttachments = &attachment_ref;
VkAttachmentDescription2 attach_desc = vku::InitStructHelper();
attach_desc.format = VK_FORMAT_R8G8B8A8_UNORM;
attach_desc.samples = VK_SAMPLE_COUNT_1_BIT;
attach_desc.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attach_desc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
attach_desc.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
VkRenderPassCreateInfo2 rp = vku::InitStructHelper();
rp.subpassCount = 2;
rp.pSubpasses = &subpass[0];
rp.attachmentCount = 1;
rp.pAttachments = &attach_desc;
vkt::RenderPass test_rp(*m_device, rp);
VkImageView fb_image_view = image_view;
auto frame_buffer_create_info =
vku::InitStruct<VkFramebufferCreateInfo>(nullptr, 0u, test_rp.handle(), 1u, &fb_image_view, 32u, 32u, 1u);
vkt::Framebuffer fb(*m_device, frame_buffer_create_info);
CreatePipelineHelper render_pass_pipe(*this);
render_pass_pipe.gp_ci_.renderPass = test_rp;
render_pass_pipe.gp_ci_.subpass = 0;
render_pass_pipe.CreateGraphicsPipeline();
m_command_buffer.BeginRenderPass(test_rp, fb, 32u, 32u, 0, nullptr);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, render_pass_pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-commandBuffer-10746");
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeTileMemoryHeap, SecondaryCommandBufferTileMemory) {
SetTargetApiVersion(VK_API_VERSION_1_2);
AddRequiredExtensions(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME);
AddRequiredExtensions(VK_QCOM_TILE_MEMORY_HEAP_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::tileMemoryHeap);
AddRequiredFeature(vkt::Feature::dynamicRendering);
RETURN_IF_SKIP(Init());
auto image_create_info =
vkt::Image::ImageCreateInfo2D(32u, 32u, 1u, 1u, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
vkt::Image image(*m_device, image_create_info);
VkCommandBufferAllocateInfo secondary_cmd_buffer_alloc_info = vku::InitStructHelper();
secondary_cmd_buffer_alloc_info.commandPool = m_command_pool;
secondary_cmd_buffer_alloc_info.level = VK_COMMAND_BUFFER_LEVEL_SECONDARY;
secondary_cmd_buffer_alloc_info.commandBufferCount = 1;
vkt::CommandBuffer secondary_cmd_buffer(*m_device, secondary_cmd_buffer_alloc_info);
VkPhysicalDeviceMemoryProperties memory_info;
int mem_type_index = -1;
vk::GetPhysicalDeviceMemoryProperties(Gpu(), &memory_info);
for (uint32_t i = 0; i < memory_info.memoryTypeCount; i++) {
int heap_index = memory_info.memoryTypes[i].heapIndex;
if (memory_info.memoryHeaps[heap_index].flags & VK_MEMORY_HEAP_TILE_MEMORY_BIT_QCOM) {
mem_type_index = i;
break;
}
}
if (mem_type_index == -1) {
GTEST_SKIP() << "Could not find an eligible Tile Memory Type.";
}
VkMemoryAllocateInfo tile_mem_alloc_info = vku::InitStructHelper();
tile_mem_alloc_info.memoryTypeIndex = mem_type_index;
tile_mem_alloc_info.allocationSize = 1024;
vkt::DeviceMemory tile_mem1(*m_device, tile_mem_alloc_info);
tile_mem_alloc_info.allocationSize = 512;
vkt::DeviceMemory tile_mem2(*m_device, tile_mem_alloc_info);
VkTileMemoryBindInfoQCOM bind_info = vku::InitStructHelper();
bind_info.memory = tile_mem1;
VkTileMemoryBindInfoQCOM tile_memory_bind_info = vku::InitStructHelper();
tile_memory_bind_info.memory = tile_mem2;
VkFormat color_formats = VK_FORMAT_R8G8B8A8_UNORM;
VkCommandBufferInheritanceRenderingInfo inheritance_rendering_info = vku::InitStructHelper(&tile_memory_bind_info);
inheritance_rendering_info.colorAttachmentCount = 1;
inheritance_rendering_info.pColorAttachmentFormats = &color_formats;
inheritance_rendering_info.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
inheritance_rendering_info.flags = VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT;
VkCommandBufferInheritanceInfo cmd_buffer_inheritance_info = vku::InitStructHelper(&inheritance_rendering_info);
VkCommandBufferBeginInfo secondary_cmd_buffer_begin_info = vku::InitStructHelper{};
secondary_cmd_buffer_begin_info.flags = VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
secondary_cmd_buffer_begin_info.pInheritanceInfo = &cmd_buffer_inheritance_info;
secondary_cmd_buffer.Begin(&secondary_cmd_buffer_begin_info);
secondary_cmd_buffer.End();
vkt::ImageView image_view = image.CreateView();
VkRenderingAttachmentInfo color_attachment = vku::InitStructHelper();
color_attachment.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
color_attachment.imageView = image_view;
VkRenderingInfo begin_rendering_info = vku::InitStructHelper();
begin_rendering_info.flags = VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT;
begin_rendering_info.colorAttachmentCount = 1;
begin_rendering_info.pColorAttachments = &color_attachment;
begin_rendering_info.layerCount = 1;
begin_rendering_info.renderArea = {{0, 0}, {32, 32}};
m_command_buffer.Begin();
vk::CmdBindTileMemoryQCOM(m_command_buffer, &bind_info);
m_command_buffer.BeginRendering(begin_rendering_info);
m_errorMonitor->SetDesiredError("VUID-vkCmdExecuteCommands-memory-10724");
vk::CmdExecuteCommands(m_command_buffer, 1, &secondary_cmd_buffer.handle());
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeTileMemoryHeap, TileProperties) {
TEST_DESCRIPTION("Provide a Tile Memory size that is greater than the largest Tile Memory heap.");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_QCOM_TILE_MEMORY_HEAP_EXTENSION_NAME);
AddRequiredExtensions(VK_QCOM_TILE_PROPERTIES_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::tileMemoryHeap);
AddRequiredFeature(vkt::Feature::tileProperties);
RETURN_IF_SKIP(Init());
VkPhysicalDeviceMemoryProperties memory_info;
vk::GetPhysicalDeviceMemoryProperties(Gpu(), &memory_info);
uint64_t max_tile_memory_heap_size = 0;
uint32_t i = 0;
for (; i < memory_info.memoryHeapCount; i++) {
if (memory_info.memoryHeaps[i].flags & VK_MEMORY_HEAP_TILE_MEMORY_BIT_QCOM) {
max_tile_memory_heap_size = std::max(memory_info.memoryHeaps[i].size, max_tile_memory_heap_size);
}
}
if (max_tile_memory_heap_size == 0xFFFFFFFFFFFFFFFF) {
GTEST_SKIP() << "Tile Memory heap exposes max 64 bit value.";
}
VkTilePropertiesQCOM tile_properties = vku::InitStructHelper();
VkTileMemorySizeInfoQCOM tile_memory_size_info = vku::InitStructHelper();
VkRenderingAttachmentInfo color_attachment = vku::InitStructHelper();
color_attachment.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
tile_memory_size_info.size = max_tile_memory_heap_size + 1;
VkRenderingInfo begin_rendering_info = vku::InitStructHelper(&tile_memory_size_info);
begin_rendering_info.colorAttachmentCount = 1;
begin_rendering_info.pColorAttachments = &color_attachment;
begin_rendering_info.layerCount = 1;
begin_rendering_info.renderArea = {{0, 0}, {1, 1}};
m_errorMonitor->SetDesiredError("VUID-VkTileMemorySizeInfoQCOM-size-10729");
vk::GetDynamicRenderingTilePropertiesQCOM(device(), &begin_rendering_info, &tile_properties);
m_errorMonitor->VerifyFound();
RenderPass2SingleSubpass rp2(*this);
rp2.AddAttachmentDescription(VK_FORMAT_R8_UINT);
m_errorMonitor->SetDesiredError("VUID-VkTileMemorySizeInfoQCOM-size-10729");
rp2.CreateRenderPass(&tile_memory_size_info);
m_errorMonitor->VerifyFound();
RenderPassSingleSubpass rp(*this);
rp.AddAttachmentDescription(VK_FORMAT_R8_UINT);
m_errorMonitor->SetDesiredError("VUID-VkTileMemorySizeInfoQCOM-size-10729");
rp.CreateRenderPass(&tile_memory_size_info);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeTileMemoryHeap, ResolveAttachment) {
TEST_DESCRIPTION("Resolve to a Tile Memory Attachment.");
SetTargetApiVersion(VK_API_VERSION_1_2);
AddRequiredExtensions(VK_QCOM_TILE_MEMORY_HEAP_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::tileMemoryHeap);
AddRequiredFeature(vkt::Feature::dynamicRendering);
AddRequiredFeature(vkt::Feature::imagelessFramebuffer);
RETURN_IF_SKIP(Init());
VkImageCreateInfo image_create_info = vku::InitStructHelper();
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.arrayLayers = 1;
image_create_info.samples = VK_SAMPLE_COUNT_4_BIT;
image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL;
image_create_info.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
vkt::Image msaa_image(*m_device, image_create_info, vkt::set_layout);
vkt::ImageView msaa_image_view = msaa_image.CreateView();
auto tile_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 tile_memory_image(*m_device, tile_image_create_info, vkt::no_mem);
VkImageMemoryRequirementsInfo2 image_info = vku::InitStructHelper();
VkTileMemoryRequirementsQCOM tile_mem_reqs = vku::InitStructHelper();
VkMemoryRequirements2 image_reqs = vku::InitStructHelper(&tile_mem_reqs);
image_info.image = tile_memory_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 alloc_info = vku::InitStructHelper();
alloc_info.memoryTypeIndex = 0;
alloc_info.allocationSize = tile_mem_reqs.size;
bool pass = m_device->Physical().SetMemoryType(image_reqs.memoryRequirements.memoryTypeBits, &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, alloc_info);
vk::BindImageMemory(device(), tile_memory_image, image_memory, 0);
vkt::ImageView resolve_image_view = tile_memory_image.CreateView();
VkRenderingAttachmentInfo color_attachment = vku::InitStructHelper();
color_attachment.imageView = msaa_image_view;
color_attachment.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
color_attachment.resolveMode = VK_RESOLVE_MODE_AVERAGE_BIT;
color_attachment.resolveImageLayout = VK_IMAGE_LAYOUT_GENERAL;
color_attachment.resolveImageView = resolve_image_view;
VkRenderingInfo begin_rendering_info = vku::InitStructHelper();
begin_rendering_info.colorAttachmentCount = 1;
begin_rendering_info.pColorAttachments = &color_attachment;
begin_rendering_info.layerCount = 1;
begin_rendering_info.renderArea = {{0, 0}, {1, 1}};
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-VkRenderingAttachmentInfo-resolveImageView-10728");
m_command_buffer.BeginRendering(begin_rendering_info);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
m_command_buffer.Reset();
VkAttachmentReference2 msaa_attachment_ref = vku::InitStructHelper();
msaa_attachment_ref.layout = VK_IMAGE_LAYOUT_GENERAL;
msaa_attachment_ref.attachment = 0;
VkAttachmentReference2 resolve_attachment_ref = vku::InitStructHelper();
resolve_attachment_ref.layout = VK_IMAGE_LAYOUT_GENERAL;
resolve_attachment_ref.attachment = 1;
VkSubpassDescription2 subpass = vku::InitStructHelper();
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &msaa_attachment_ref;
subpass.pResolveAttachments = &resolve_attachment_ref;
VkAttachmentDescription2 attach_desc[2] = {};
attach_desc[0] = vku::InitStructHelper();
attach_desc[0].format = VK_FORMAT_R8G8B8A8_UNORM;
attach_desc[0].samples = VK_SAMPLE_COUNT_4_BIT;
attach_desc[0].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attach_desc[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
attach_desc[0].finalLayout = VK_IMAGE_LAYOUT_GENERAL;
attach_desc[1] = vku::InitStructHelper();
attach_desc[1].format = VK_FORMAT_R8G8B8A8_UNORM;
attach_desc[1].samples = VK_SAMPLE_COUNT_1_BIT;
attach_desc[1].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attach_desc[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
attach_desc[1].finalLayout = VK_IMAGE_LAYOUT_GENERAL;
VkRenderPassCreateInfo2 rp = vku::InitStructHelper();
rp.subpassCount = 1;
rp.pSubpasses = &subpass;
rp.attachmentCount = 2;
rp.pAttachments = &attach_desc[0];
vkt::RenderPass test_rp(*m_device, rp);
VkImageView views[2] = {};
views[0] = msaa_image_view;
views[1] = resolve_image_view;
auto frame_buffer_create_info =
vku::InitStruct<VkFramebufferCreateInfo>(nullptr, 0u, test_rp.handle(), 2u, &views[0], 32u, 32u, 1u);
VkFramebuffer fb;
m_errorMonitor->SetDesiredError("VUID-VkFramebufferCreateInfo-pAttachments-12327");
vk::CreateFramebuffer(device(), &frame_buffer_create_info, nullptr, &fb);
m_errorMonitor->VerifyFound();
// Imageless FBO
VkFormat framebuffer_attachment_formats = VK_FORMAT_R8G8B8A8_UNORM;
VkFramebufferAttachmentImageInfo framebuffer_attachment_image_info[2] = {};
framebuffer_attachment_image_info[0] = vku::InitStructHelper();
framebuffer_attachment_image_info[0].usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
framebuffer_attachment_image_info[0].width = 32;
framebuffer_attachment_image_info[0].height = 32;
framebuffer_attachment_image_info[0].layerCount = 1;
framebuffer_attachment_image_info[0].viewFormatCount = 1;
framebuffer_attachment_image_info[0].pViewFormats = &framebuffer_attachment_formats;
framebuffer_attachment_image_info[1] = vku::InitStructHelper();
framebuffer_attachment_image_info[1].usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TILE_MEMORY_BIT_QCOM;
framebuffer_attachment_image_info[1].width = 32;
framebuffer_attachment_image_info[1].height = 32;
framebuffer_attachment_image_info[1].layerCount = 1;
framebuffer_attachment_image_info[1].viewFormatCount = 1;
framebuffer_attachment_image_info[1].pViewFormats = &framebuffer_attachment_formats;
VkFramebufferAttachmentsCreateInfo framebuffer_attachment_ci = vku::InitStructHelper();
framebuffer_attachment_ci.attachmentImageInfoCount = 2;
framebuffer_attachment_ci.pAttachmentImageInfos = &framebuffer_attachment_image_info[0];
auto imageless_fbci = vku::InitStruct<VkFramebufferCreateInfo>(nullptr, 0u, test_rp.handle(), 2u, nullptr, 32u, 32u, 1u);
imageless_fbci.pNext = &framebuffer_attachment_ci;
imageless_fbci.flags = VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT;
vkt::Framebuffer imageless_fb(*m_device, imageless_fbci);
VkImageView image_views[2] = {msaa_image_view, resolve_image_view};
VkRenderPassAttachmentBeginInfo rp_attachment_begin_info = vku::InitStructHelper();
rp_attachment_begin_info.attachmentCount = 2;
rp_attachment_begin_info.pAttachments = &image_views[0];
VkRenderPassBeginInfo rp_begin_info = vku::InitStructHelper(&rp_attachment_begin_info);
rp_begin_info.renderPass = test_rp.handle();
rp_begin_info.renderArea.extent = {32, 32};
rp_begin_info.framebuffer = imageless_fb;
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-VkRenderPassBeginInfo-framebuffer-12328");
m_command_buffer.BeginRenderPass(rp_begin_info);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeTileMemoryHeap, BufferDescriptorMismatchTileMemory) {
TEST_DESCRIPTION("Create tile memory storage buffer and use it within a dispatch.");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_QCOM_TILE_MEMORY_HEAP_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::tileMemoryHeap);
RETURN_IF_SKIP(Init());
// 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);
// Tile Memory Texel Buffer
vkt::Buffer texel_buffer(
*m_device,
vkt::Buffer::CreateInfo(4096, VK_BUFFER_USAGE_2_TILE_MEMORY_BIT_QCOM | VK_BUFFER_USAGE_2_STORAGE_TEXEL_BUFFER_BIT),
vkt::no_mem);
// Query Tile Memory Buffer Requirements
VkDeviceSize buffer_size = 0;
VkDeviceSize texel_buffer_size = 0;
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.";
}
buffer_size = tile_mem_reqs.size;
buffer_info.buffer = texel_buffer;
vk::GetBufferMemoryRequirements2(device(), &buffer_info, &buffer_reqs);
if (tile_mem_reqs.size == 0) {
GTEST_SKIP() << "Texel Buffer not eligible to be bound with Tile Memory.";
}
buffer_size = AlignToMultiple(buffer_size, tile_mem_reqs.alignment);
texel_buffer_size = tile_mem_reqs.size;
// Find a memory configuration for the Tile Memory Resources, otherwise exit
VkMemoryAllocateInfo alloc_info = vku::InitStructHelper();
alloc_info.memoryTypeIndex = 0;
alloc_info.allocationSize = buffer_size + texel_buffer_size;
bool pass = m_device->Physical().SetMemoryType(buffer_reqs.memoryRequirements.memoryTypeBits, &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.";
}
// Bind Tile Memory to Buffer
vkt::DeviceMemory buffer_memory(*m_device, alloc_info);
vk::BindBufferMemory(device(), buffer, buffer_memory, 0);
// Bind Tile Memory to Texel Buffer with offset
vk::BindBufferMemory(device(), texel_buffer, buffer_memory, buffer_size);
VkBufferUsageFlags2CreateInfo buffer_usage_flags = vku::InitStructHelper();
buffer_usage_flags.usage = VK_BUFFER_USAGE_2_STORAGE_TEXEL_BUFFER_BIT;
VkBufferViewCreateInfo bvci = vku::InitStructHelper(&buffer_usage_flags);
bvci.buffer = texel_buffer;
bvci.format = VK_FORMAT_R32_SFLOAT;
bvci.range = VK_WHOLE_SIZE;
vkt::BufferView texel_buffer_view(*m_device, bvci);
// Create Compute Shader to write to Tile Memory Buffer
const char* cs_source = R"glsl(
#version 450
layout(set = 0, binding = 0) buffer ssbo { float tileMemBuffer; };
layout(set = 0, binding = 1, r32f) uniform imageBuffer s_buffer;
void main() {
tileMemBuffer = 1.0f;
imageStore(s_buffer, 0, vec4(0.5f));
}
)glsl";
CreateComputePipelineHelper pipe(*this);
pipe.dsl_bindings_ = {{0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr},
{1, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}};
pipe.cs_ = VkShaderObj(*m_device, cs_source, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_1);
pipe.CreateComputePipeline();
pipe.descriptor_set_.WriteDescriptorBufferInfo(0, buffer, 0, 4096, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
pipe.descriptor_set_.WriteDescriptorBufferView(1, texel_buffer_view, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER);
pipe.descriptor_set_.UpdateDescriptorSets();
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdDispatch-commandBuffer-10746", 2);
vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe.pipeline_layout_, 0, 1,
&pipe.descriptor_set_.set_, 0, nullptr);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe);
vk::CmdDispatch(m_command_buffer, 1, 1, 1);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeTileMemoryHeap, ImageDescriptorMismatchTileMemory) {
TEST_DESCRIPTION("Create tile memory storage buffer and use it within a dispatch.");
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_STORAGE_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 alloc_info = vku::InitStructHelper();
alloc_info.memoryTypeIndex = 0;
alloc_info.allocationSize = tile_mem_reqs.size;
bool pass = m_device->Physical().SetMemoryType(image_reqs.memoryRequirements.memoryTypeBits, &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, alloc_info);
vk::BindImageMemory(device(), image, image_memory, 0);
vkt::ImageView image_view = image.CreateView();
OneOffDescriptorSet descriptor_set(m_device, {
{0, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_ALL, nullptr},
});
descriptor_set.WriteDescriptorImageInfo(0, image_view, VK_NULL_HANDLE, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
VK_IMAGE_LAYOUT_GENERAL);
descriptor_set.UpdateDescriptorSets();
const char* cs_source = R"glsl(
#version 450
layout(set=0, binding=0, rgba8) uniform readonly image2D storage_image;
void main(){
vec4 data = imageLoad(storage_image, ivec2(0));
}
)glsl";
CreateComputePipelineHelper pipe(*this);
pipe.cs_ = VkShaderObj(*m_device, cs_source, VK_SHADER_STAGE_COMPUTE_BIT);
pipe.pipeline_layout_ = vkt::PipelineLayout(*m_device, {&descriptor_set.layout_});
pipe.CreateComputePipeline();
m_command_buffer.Begin();
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe);
vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe.pipeline_layout_, 0, 1, &descriptor_set.set_,
0, nullptr);
m_errorMonitor->SetDesiredError("VUID-vkCmdDispatch-commandBuffer-10746");
vk::CmdDispatch(m_command_buffer, 1, 1, 1);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}