blob: 1b26ed7c3774046e59dd325c78fde82fe6afb2ba [file]
/*
* Copyright (C) 2025-2026 Advanced Micro Devices, Inc. All rights reserved.
* Copyright (c) 2025-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 "utils/math_utils.h"
#include "../framework/layer_validation_tests.h"
#include "../framework/pipeline_helper.h"
#include "../framework/shader_object_helper.h"
#include <cstdint>
#include <vulkan/utility/vk_struct_helper.hpp>
void DescriptorHeapTest::InitBasicDescriptorHeap() {
SetTargetApiVersion(VK_API_VERSION_1_3);
AddRequiredExtensions(VK_EXT_DESCRIPTOR_HEAP_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::descriptorHeap);
RETURN_IF_SKIP(Init());
heap_props.pNext = &tensor_heap_props;
GetPhysicalDeviceProperties2(heap_props);
}
void DescriptorHeapTest::CreateResourceHeap(VkDeviceSize app_size) {
const VkDeviceSize heap_size = AlignResource(app_size + heap_props.minResourceHeapReservedRange);
VkBufferUsageFlags2CreateInfo buffer_usage = vku::InitStructHelper();
buffer_usage.usage = VK_BUFFER_USAGE_2_DESCRIPTOR_HEAP_BIT_EXT | VK_BUFFER_USAGE_2_SHADER_DEVICE_ADDRESS_BIT;
VkMemoryAllocateFlagsInfo allocate_flag_info = vku::InitStructHelper();
allocate_flag_info.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT;
resource_heap_.Init(*m_device, vkt::Buffer::CreateInfo(heap_size, 0, {}, &buffer_usage),
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &allocate_flag_info);
resource_heap_data_ = static_cast<uint8_t*>(resource_heap_.Memory().Map());
}
void DescriptorHeapTest::CreateSamplerHeap(VkDeviceSize app_size, bool use_embedded_samplers) {
embedded_samplers = use_embedded_samplers;
const VkDeviceSize reserved_range =
(embedded_samplers ? heap_props.minSamplerHeapReservedRangeWithEmbedded : heap_props.minSamplerHeapReservedRange);
const VkDeviceSize heap_size = AlignSampler(app_size + reserved_range);
VkBufferUsageFlags2CreateInfo buffer_usage = vku::InitStructHelper();
buffer_usage.usage = VK_BUFFER_USAGE_2_DESCRIPTOR_HEAP_BIT_EXT | VK_BUFFER_USAGE_2_SHADER_DEVICE_ADDRESS_BIT;
VkMemoryAllocateFlagsInfo allocate_flag_info = vku::InitStructHelper();
allocate_flag_info.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT;
sampler_heap_.Init(*m_device, vkt::Buffer::CreateInfo(heap_size, 0, {}, &buffer_usage),
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &allocate_flag_info);
sampler_heap_data_ = static_cast<uint8_t*>(sampler_heap_.Memory().Map());
}
void DescriptorHeapTest::BindResourceHeap() {
VkBindHeapInfoEXT bind_resource_info = vku::InitStructHelper();
bind_resource_info.heapRange = resource_heap_.AddressRange();
bind_resource_info.reservedRangeOffset = resource_heap_.CreateInfo().size - heap_props.minResourceHeapReservedRange;
bind_resource_info.reservedRangeSize = heap_props.minResourceHeapReservedRange;
vk::CmdBindResourceHeapEXT(m_command_buffer, &bind_resource_info);
}
void DescriptorHeapTest::BindSamplerHeap() {
const VkDeviceSize min_reserved_range =
embedded_samplers ? heap_props.minSamplerHeapReservedRangeWithEmbedded : heap_props.minSamplerHeapReservedRange;
VkBindHeapInfoEXT bind_resource_info = vku::InitStructHelper();
bind_resource_info.heapRange = sampler_heap_.AddressRange();
bind_resource_info.reservedRangeOffset = sampler_heap_.CreateInfo().size - min_reserved_range;
bind_resource_info.reservedRangeSize = min_reserved_range;
vk::CmdBindSamplerHeapEXT(m_command_buffer, &bind_resource_info);
}
// Aligns end according to type alignment and sets the value to return as the begin of the type
// Then increments end by size * count and sets it as the new end
VkDeviceSize DescriptorHeapTest::AlignedAppend(VkDeviceSize& end, VkDescriptorType type, uint32_t count) {
VkDeviceSize size = 0;
VkDeviceSize align = 0;
switch (type) {
case VK_DESCRIPTOR_TYPE_SAMPLER:
size = heap_props.samplerDescriptorSize;
align = heap_props.samplerDescriptorAlignment;
break;
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR:
case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV:
size = heap_props.bufferDescriptorSize;
align = heap_props.bufferDescriptorAlignment;
break;
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
case VK_DESCRIPTOR_TYPE_SAMPLE_WEIGHT_IMAGE_QCOM:
case VK_DESCRIPTOR_TYPE_BLOCK_MATCH_IMAGE_QCOM:
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
size = heap_props.imageDescriptorSize;
align = heap_props.imageDescriptorAlignment;
break;
case VK_DESCRIPTOR_TYPE_TENSOR_ARM: {
size = tensor_heap_props.tensorDescriptorSize;
align = tensor_heap_props.tensorDescriptorAlignment;
break;
}
default:
assert(0);
}
end = Align(end, align);
const VkDeviceSize start = end;
end += count * size;
return start;
}
VkDeviceSize DescriptorHeapTest::AlignResource(VkDeviceSize offset) {
return Align(Align(offset, heap_props.bufferDescriptorAlignment), heap_props.imageDescriptorAlignment);
}
VkDeviceSize DescriptorHeapTest::AlignSampler(VkDeviceSize offset) { return Align(offset, heap_props.samplerDescriptorAlignment); }
class NegativeDescriptorHeap : public DescriptorHeapTest {};
TEST_F(NegativeDescriptorHeap, NotEnabled) {
TEST_DESCRIPTION("Tests for descriptor heap when feature is not enabled");
SetTargetApiVersion(VK_API_VERSION_1_2);
AddRequiredExtensions(VK_EXT_DESCRIPTOR_HEAP_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(Init());
GetPhysicalDeviceProperties2(heap_props);
{
VkSamplerCreateInfo sampler_ci = vku::InitStructHelper();
VkHostAddressRangeEXT descriptors = {&sampler_ci, static_cast<size_t>(heap_props.samplerDescriptorSize)};
m_errorMonitor->SetDesiredError("VUID-vkWriteSamplerDescriptorsEXT-descriptorHeap-11202");
vk::WriteSamplerDescriptorsEXT(device(), 1u, &sampler_ci, &descriptors);
m_errorMonitor->VerifyFound();
}
{
const VkDeviceSize buffer_size = heap_props.bufferDescriptorSize;
vkt::Buffer buffer(*m_device, buffer_size, VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, vkt::device_address);
VkTexelBufferDescriptorInfoEXT texel_buffer_info = vku::InitStructHelper();
texel_buffer_info.format = VK_FORMAT_R8G8B8A8_UNORM;
texel_buffer_info.addressRange.address = buffer.Address();
texel_buffer_info.addressRange.size = buffer_size;
VkResourceDescriptorInfoEXT desc_info = vku::InitStructHelper();
desc_info.type = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
desc_info.data.pTexelBuffer = &texel_buffer_info;
VkHostAddressRangeEXT descriptors = {&desc_info, static_cast<size_t>(heap_props.imageDescriptorSize)};
m_errorMonitor->SetDesiredError("VUID-vkWriteResourceDescriptorsEXT-descriptorHeap-11206");
vk::WriteResourceDescriptorsEXT(device(), 1u, &desc_info, &descriptors);
m_errorMonitor->VerifyFound();
}
{
std::vector<uint8_t> data(heap_props.imageCaptureReplayOpaqueDataSize);
VkImageCreateInfo image_create_info = vku::InitStructHelper();
image_create_info.imageType = VK_IMAGE_TYPE_2D;
image_create_info.extent.width = 128;
image_create_info.extent.height = 128;
image_create_info.extent.depth = 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.format = VK_FORMAT_D32_SFLOAT;
image_create_info.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
vkt::Image image(*m_device, image_create_info, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
VkHostAddressRangeEXT data2 = {data.data(), data.size()};
m_errorMonitor->SetDesiredError("VUID-vkGetImageOpaqueCaptureDataEXT-descriptorHeapCaptureReplay-11282");
m_errorMonitor->SetDesiredError("VUID-vkGetImageOpaqueCaptureDataEXT-pImages-11285");
vk::GetImageOpaqueCaptureDataEXT(device(), 1, &image.handle(), &data2);
m_errorMonitor->VerifyFound();
}
}
TEST_F(NegativeDescriptorHeap, SamplerParameterSize) {
TEST_DESCRIPTION("Validate vkWriteSamplerDescriptorsEXT size parameter");
RETURN_IF_SKIP(InitBasicDescriptorHeap());
const VkDeviceSize sampler_size = vk::GetPhysicalDeviceDescriptorSizeEXT(Gpu(), VK_DESCRIPTOR_TYPE_SAMPLER);
std::vector<uint8_t> data(static_cast<size_t>(sampler_size));
VkSamplerCreateInfo sampler_ci = vku::InitStructHelper();
VkHostAddressRangeEXT descriptors = {data.data(), static_cast<size_t>(sampler_size) - 1};
{
m_errorMonitor->SetDesiredError("VUID-vkWriteSamplerDescriptorsEXT-size-11203");
vk::WriteSamplerDescriptorsEXT(device(), 1u, &sampler_ci, &descriptors);
m_errorMonitor->VerifyFound();
}
{
descriptors.size = 0;
m_errorMonitor->SetDesiredError("VUID-VkHostAddressRangeEXT-size-arraylength");
vk::WriteSamplerDescriptorsEXT(device(), 1u, &sampler_ci, &descriptors);
m_errorMonitor->VerifyFound();
}
}
TEST_F(NegativeDescriptorHeap, SamplerParameterYCbCr) {
TEST_DESCRIPTION("Validate vkWriteSamplerDescriptorsEXT with YCbCr conversion");
AddRequiredFeature(vkt::Feature::samplerYcbcrConversion);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
const VkDeviceSize sampler_size = vk::GetPhysicalDeviceDescriptorSizeEXT(Gpu(), VK_DESCRIPTOR_TYPE_SAMPLER);
std::vector<uint8_t> data(static_cast<size_t>(sampler_size));
vkt::SamplerYcbcrConversion conversion(*m_device, VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM);
VkSamplerYcbcrConversionInfoKHR ycbcr_conversion_info = vku::InitStructHelper();
ycbcr_conversion_info.conversion = conversion;
VkSamplerCreateInfo sampler_ci = vku::InitStructHelper(&ycbcr_conversion_info);
sampler_ci.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
sampler_ci.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
sampler_ci.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
VkHostAddressRangeEXT descriptors = {data.data(), static_cast<size_t>(sampler_size)};
m_errorMonitor->SetDesiredError("VUID-vkWriteSamplerDescriptorsEXT-pSamplers-11204");
vk::WriteSamplerDescriptorsEXT(device(), 1u, &sampler_ci, &descriptors);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDescriptorHeap, SamplerParameterDebugUtilsObjectName) {
TEST_DESCRIPTION("Validate vkWriteSamplerDescriptorsEXT with DebugUilsObjectName");
RETURN_IF_SKIP(InitBasicDescriptorHeap());
const VkDeviceSize sampler_size = vk::GetPhysicalDeviceDescriptorSizeEXT(Gpu(), VK_DESCRIPTOR_TYPE_SAMPLER);
std::vector<uint8_t> data(static_cast<size_t>(sampler_size));
VkDebugUtilsObjectNameInfoEXT object_name_info = vku::InitStructHelper();
object_name_info.objectType = VK_OBJECT_TYPE_DEVICE;
VkSamplerCreateInfo sampler_ci = vku::InitStructHelper(&object_name_info);
VkHostAddressRangeEXT descriptors = {data.data(), static_cast<size_t>(sampler_size)};
m_errorMonitor->SetDesiredError("VUID-vkWriteSamplerDescriptorsEXT-pNext-11400");
vk::WriteSamplerDescriptorsEXT(device(), 1u, &sampler_ci, &descriptors);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDescriptorHeap, SamplerParameterCustomBorderColor) {
TEST_DESCRIPTION("Validate vkWriteSamplerDescriptorsEXT with custom border color");
AddRequiredExtensions(VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::customBorderColors);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
const VkDeviceSize sampler_size = vk::GetPhysicalDeviceDescriptorSizeEXT(Gpu(), VK_DESCRIPTOR_TYPE_SAMPLER);
std::vector<uint8_t> data(static_cast<size_t>(sampler_size));
VkPhysicalDeviceCustomBorderColorPropertiesEXT border_color_props = vku::InitStructHelper();
GetPhysicalDeviceProperties2(border_color_props);
VkSamplerCustomBorderColorCreateInfoEXT custom_border_color_ci = vku::InitStructHelper();
custom_border_color_ci.format = VK_FORMAT_R8G8B8A8_UNORM;
VkSamplerCustomBorderColorIndexCreateInfoEXT border_color_info = vku::InitStructHelper(&custom_border_color_ci);
border_color_info.index = border_color_props.maxCustomBorderColorSamplers;
VkSamplerCreateInfo sampler_ci = vku::InitStructHelper(&border_color_info);
sampler_ci.borderColor = VK_BORDER_COLOR_FLOAT_CUSTOM_EXT;
VkHostAddressRangeEXT descriptors = {data.data(), static_cast<size_t>(sampler_size)};
{
m_errorMonitor->SetDesiredError("VUID-vkWriteSamplerDescriptorsEXT-borderColor-11205");
// Do not use SetDesiredError in next line, due to it ends validation after the error
m_errorMonitor->SetAllowedFailureMsg("VUID-VkSamplerCustomBorderColorIndexCreateInfoEXT-index-11289");
vk::WriteSamplerDescriptorsEXT(device(), 1u, &sampler_ci, &descriptors);
m_errorMonitor->VerifyFound();
}
{
sampler_ci.pNext = &custom_border_color_ci;
m_errorMonitor->SetDesiredError("VUID-vkWriteSamplerDescriptorsEXT-borderColor-11444");
vk::WriteSamplerDescriptorsEXT(device(), 1u, &sampler_ci, &descriptors);
m_errorMonitor->VerifyFound();
}
}
TEST_F(NegativeDescriptorHeap, SamplerParameterPSamplersStateless) {
TEST_DESCRIPTION("Validate vkWriteSamplerDescriptorsEXT check stateless path");
RETURN_IF_SKIP(InitBasicDescriptorHeap());
const VkDeviceSize sampler_size = vk::GetPhysicalDeviceDescriptorSizeEXT(Gpu(), VK_DESCRIPTOR_TYPE_SAMPLER);
std::vector<uint8_t> data(static_cast<size_t>(sampler_size));
VkSamplerCreateInfo sampler_ci = vku::InitStructHelper();
VkHostAddressRangeEXT descriptors = {data.data(), static_cast<size_t>(sampler_size)};
sampler_ci.minLod = 1.0f;
sampler_ci.maxLod = 0.0f;
m_errorMonitor->SetDesiredError("VUID-VkSamplerCreateInfo-maxLod-01973");
vk::WriteSamplerDescriptorsEXT(device(), 1u, &sampler_ci, &descriptors);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDescriptorHeap, SamplerParameterPSamplersCore) {
TEST_DESCRIPTION("Validate vkWriteSamplerDescriptorsEXT check core validation path");
AddRequiredFeature(vkt::Feature::samplerYcbcrConversion);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
const VkDeviceSize sampler_size = vk::GetPhysicalDeviceDescriptorSizeEXT(Gpu(), VK_DESCRIPTOR_TYPE_SAMPLER);
std::vector<uint8_t> data(static_cast<size_t>(sampler_size));
VkHostAddressRangeEXT descriptors = {data.data(), static_cast<size_t>(sampler_size)};
PFN_vkSetPhysicalDeviceFormatPropertiesEXT fpvkSetPhysicalDeviceFormatPropertiesEXT = nullptr;
PFN_vkGetOriginalPhysicalDeviceFormatPropertiesEXT fpvkGetOriginalPhysicalDeviceFormatPropertiesEXT = nullptr;
if (!LoadDeviceProfileLayer(fpvkSetPhysicalDeviceFormatPropertiesEXT, fpvkGetOriginalPhysicalDeviceFormatPropertiesEXT)) {
GTEST_SKIP() << "Failed to load device profile layer.";
}
VkSamplerYcbcrConversion ycbcr_conv = VK_NULL_HANDLE;
VkSamplerYcbcrConversionCreateInfo sycci = vku::InitStructHelper();
sycci.format = VK_FORMAT_UNDEFINED;
sycci.ycbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY;
sycci.ycbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_FULL;
sycci.forceExplicitReconstruction = VK_FALSE;
sycci.chromaFilter = VK_FILTER_NEAREST;
sycci.xChromaOffset = VK_CHROMA_LOCATION_COSITED_EVEN;
sycci.yChromaOffset = VK_CHROMA_LOCATION_COSITED_EVEN;
// test non external conversion with a VK_FORMAT_UNDEFINED
m_errorMonitor->SetDesiredError("VUID-VkSamplerYcbcrConversionCreateInfo-format-04061");
vk::CreateSamplerYcbcrConversion(device(), &sycci, nullptr, &ycbcr_conv);
m_errorMonitor->VerifyFound();
// test for non unorm
sycci.format = VK_FORMAT_R8G8B8A8_SNORM;
m_errorMonitor->SetDesiredError("VUID-VkSamplerYcbcrConversionCreateInfo-format-04061");
m_errorMonitor->SetUnexpectedError("VUID-VkSamplerYcbcrConversionCreateInfo-format-01650");
vk::CreateSamplerYcbcrConversion(device(), &sycci, nullptr, &ycbcr_conv);
m_errorMonitor->VerifyFound();
// Force the multi-planar format support desired format features
VkFormat mp_format = VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM;
VkFormatProperties formatProps;
fpvkGetOriginalPhysicalDeviceFormatPropertiesEXT(Gpu(), mp_format, &formatProps);
formatProps.linearTilingFeatures = 0;
formatProps.optimalTilingFeatures = 0;
fpvkSetPhysicalDeviceFormatPropertiesEXT(Gpu(), mp_format, formatProps);
// Check that errors are caught when format feature don't exist
sycci.format = mp_format;
// No Chroma Sampler Bit set
m_errorMonitor->SetDesiredError("VUID-VkSamplerYcbcrConversionCreateInfo-format-01650");
// 01651 set off twice for both xChromaOffset and yChromaOffset
m_errorMonitor->SetDesiredError("VUID-VkSamplerYcbcrConversionCreateInfo-xChromaOffset-01651");
m_errorMonitor->SetDesiredError("VUID-VkSamplerYcbcrConversionCreateInfo-xChromaOffset-01651");
vk::CreateSamplerYcbcrConversion(device(), &sycci, nullptr, &ycbcr_conv);
m_errorMonitor->VerifyFound();
// Cosited feature supported, but midpoint samples set
formatProps.linearTilingFeatures = 0;
formatProps.optimalTilingFeatures = VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT;
fpvkSetPhysicalDeviceFormatPropertiesEXT(Gpu(), mp_format, formatProps);
sycci.xChromaOffset = VK_CHROMA_LOCATION_MIDPOINT;
sycci.yChromaOffset = VK_CHROMA_LOCATION_COSITED_EVEN;
m_errorMonitor->SetDesiredError("VUID-VkSamplerYcbcrConversionCreateInfo-xChromaOffset-01652");
vk::CreateSamplerYcbcrConversion(device(), &sycci, nullptr, &ycbcr_conv);
m_errorMonitor->VerifyFound();
// Moving support to Linear to test that it checks either linear or optimal
formatProps.linearTilingFeatures = VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT;
formatProps.optimalTilingFeatures = 0;
fpvkSetPhysicalDeviceFormatPropertiesEXT(Gpu(), mp_format, formatProps);
sycci.xChromaOffset = VK_CHROMA_LOCATION_MIDPOINT;
sycci.yChromaOffset = VK_CHROMA_LOCATION_COSITED_EVEN;
m_errorMonitor->SetDesiredError("VUID-VkSamplerYcbcrConversionCreateInfo-xChromaOffset-01652");
vk::CreateSamplerYcbcrConversion(device(), &sycci, nullptr, &ycbcr_conv);
m_errorMonitor->VerifyFound();
// Using forceExplicitReconstruction without feature bit
sycci.forceExplicitReconstruction = VK_TRUE;
sycci.xChromaOffset = VK_CHROMA_LOCATION_COSITED_EVEN;
sycci.yChromaOffset = VK_CHROMA_LOCATION_COSITED_EVEN;
m_errorMonitor->SetDesiredError("VUID-VkSamplerYcbcrConversionCreateInfo-forceExplicitReconstruction-01656");
vk::CreateSamplerYcbcrConversion(device(), &sycci, nullptr, &ycbcr_conv);
m_errorMonitor->VerifyFound();
// Linear chroma filtering without feature bit
sycci.forceExplicitReconstruction = VK_FALSE;
sycci.chromaFilter = VK_FILTER_LINEAR;
m_errorMonitor->SetDesiredError("VUID-VkSamplerYcbcrConversionCreateInfo-chromaFilter-01657");
vk::CreateSamplerYcbcrConversion(device(), &sycci, nullptr, &ycbcr_conv);
m_errorMonitor->VerifyFound();
// Add linear feature bit so can create valid SamplerYcbcrConversion
formatProps.linearTilingFeatures = VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT;
formatProps.optimalTilingFeatures = VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT;
fpvkSetPhysicalDeviceFormatPropertiesEXT(Gpu(), mp_format, formatProps);
vkt::SamplerYcbcrConversion conversion(*m_device, sycci);
// Try to create a Sampler with non-matching filters without feature bit set
VkSamplerYcbcrConversionInfo sampler_ycbcr_info = vku::InitStructHelper();
sampler_ycbcr_info.conversion = conversion;
VkSamplerCreateInfo sampler_ci = SafeSaneSamplerCreateInfo();
sampler_ci.minFilter = VK_FILTER_NEAREST; // Different than chromaFilter
sampler_ci.magFilter = VK_FILTER_LINEAR;
sampler_ci.pNext = (void*)&sampler_ycbcr_info;
m_errorMonitor->SetDesiredError("VUID-vkWriteSamplerDescriptorsEXT-pSamplers-11204");
vk::WriteSamplerDescriptorsEXT(device(), 1u, &sampler_ci, &descriptors);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDescriptorHeap, ResourceParameterTypeInvalid) {
TEST_DESCRIPTION("Validate vkWriteResourceDescriptorsEXT with unacceptable type");
RETURN_IF_SKIP(InitBasicDescriptorHeap());
const VkDeviceSize size = 1024;
std::vector<uint8_t> data(size);
VkResourceDescriptorInfoEXT resource_desc_info = vku::InitStructHelper();
resource_desc_info.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
VkHostAddressRangeEXT descriptors = {&data[0], data.size()};
m_errorMonitor->SetDesiredError("VUID-VkResourceDescriptorInfoEXT-type-11210");
vk::WriteResourceDescriptorsEXT(device(), 1u, &resource_desc_info, &descriptors);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDescriptorHeap, ResourceParameterSize) {
TEST_DESCRIPTION("Validate vkWriteResourceDescriptorsEXT size parameter");
AddRequiredFeature(vkt::Feature::nullDescriptor);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
const VkDescriptorType types[] = {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE};
for (auto t : types) {
const VkDeviceSize size = vk::GetPhysicalDeviceDescriptorSizeEXT(Gpu(), t);
if (size > 0) {
std::vector<uint8_t> data(static_cast<size_t>(size));
VkResourceDescriptorInfoEXT resource_desc_info = vku::InitStructHelper();
resource_desc_info.type = t;
VkHostAddressRangeEXT descriptors = {data.data(), static_cast<size_t>(size - 1)};
{
m_errorMonitor->SetDesiredError("VUID-vkWriteResourceDescriptorsEXT-size-11207");
vk::WriteResourceDescriptorsEXT(device(), 1u, &resource_desc_info, &descriptors);
m_errorMonitor->VerifyFound();
}
{
descriptors.size = 0;
m_errorMonitor->SetDesiredError("VUID-VkHostAddressRangeEXT-size-arraylength");
vk::WriteResourceDescriptorsEXT(device(), 1u, &resource_desc_info, &descriptors);
m_errorMonitor->VerifyFound();
}
}
}
}
TEST_F(NegativeDescriptorHeap, ResourceParameterDataNull) {
TEST_DESCRIPTION("Validate vkWriteResourceDescriptorsEXT null pointer");
RETURN_IF_SKIP(InitBasicDescriptorHeap());
const struct {
const char* vuid;
std::vector<VkDescriptorType> types;
} subtests[] = {
{
"VUID-VkResourceDescriptorInfoEXT-None-11211",
std::vector<VkDescriptorType>{
VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
},
},
{"VUID-VkResourceDescriptorInfoEXT-None-11212",
std::vector<VkDescriptorType>{VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER}},
{"VUID-VkResourceDescriptorInfoEXT-None-11213",
std::vector<VkDescriptorType>{// checked in separate test VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR,
// VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV,
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER}},
};
for (const auto& s : subtests) {
for (auto type : s.types) {
const VkDeviceSize size = vk::GetPhysicalDeviceDescriptorSizeEXT(Gpu(), type);
std::vector<uint8_t> data(static_cast<size_t>(size));
VkResourceDescriptorInfoEXT resource_desc_info = vku::InitStructHelper();
resource_desc_info.type = type;
VkHostAddressRangeEXT descriptors = {data.data(), static_cast<size_t>(size)};
m_errorMonitor->SetDesiredError(s.vuid);
vk::WriteResourceDescriptorsEXT(device(), 1u, &resource_desc_info, &descriptors);
m_errorMonitor->VerifyFound();
}
}
}
TEST_F(NegativeDescriptorHeap, ResourceParameterDataNullAS) {
TEST_DESCRIPTION("Validate vkWriteResourceDescriptorsEXT nullDescriptor for acceleration structure");
AddRequiredExtensions(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::accelerationStructure);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
const VkDeviceSize size = vk::GetPhysicalDeviceDescriptorSizeEXT(Gpu(), VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR);
std::vector<uint8_t> data(static_cast<size_t>(size));
VkResourceDescriptorInfoEXT resource_desc_info = vku::InitStructHelper();
resource_desc_info.type = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR;
VkHostAddressRangeEXT descriptors = {data.data(), static_cast<size_t>(size)};
m_errorMonitor->SetDesiredError("VUID-VkResourceDescriptorInfoEXT-None-11213");
vk::WriteResourceDescriptorsEXT(device(), 1u, &resource_desc_info, &descriptors);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDescriptorHeap, ResourceParameterDataNullTensor) {
AddRequiredExtensions(VK_ARM_TENSORS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::tensors);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
const VkDeviceSize size = vk::GetPhysicalDeviceDescriptorSizeEXT(Gpu(), VK_DESCRIPTOR_TYPE_TENSOR_ARM);
std::vector<uint8_t> data(static_cast<size_t>(size));
VkResourceDescriptorInfoEXT resource_desc_info = vku::InitStructHelper();
resource_desc_info.type = VK_DESCRIPTOR_TYPE_TENSOR_ARM;
VkHostAddressRangeEXT descriptors = {data.data(), static_cast<size_t>(size)};
m_errorMonitor->SetDesiredError("VUID-VkResourceDescriptorInfoEXT-None-11457");
vk::WriteResourceDescriptorsEXT(device(), 1u, &resource_desc_info, &descriptors);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDescriptorHeap, ResourceParameterDebugUtilsObjectName) {
TEST_DESCRIPTION("Validate vkWriteResourceDescriptorsEXT with DebugUilsObjectName");
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
const VkDeviceSize resource_size = vk::GetPhysicalDeviceDescriptorSizeEXT(Gpu(), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
std::vector<uint8_t> data(static_cast<size_t>(resource_size));
const uint32_t buffer_size = 16;
vkt::Buffer dummy_buffer(*m_device, buffer_size, VK_BUFFER_USAGE_2_STORAGE_BUFFER_BIT, vkt::device_address);
VkDeviceAddressRangeEXT device_address_range = {dummy_buffer.Address(), buffer_size};
VkDebugUtilsObjectNameInfoEXT object_name_info = vku::InitStructHelper();
object_name_info.objectType = VK_OBJECT_TYPE_DEVICE;
VkResourceDescriptorInfoEXT resource_desc_info = vku::InitStructHelper();
resource_desc_info.pNext = &object_name_info;
resource_desc_info.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
resource_desc_info.data.pAddressRange = &device_address_range;
VkHostAddressRangeEXT descriptors = {data.data(), static_cast<size_t>(resource_size)};
m_errorMonitor->SetDesiredError("VUID-VkResourceDescriptorInfoEXT-pNext-11401");
vk::WriteResourceDescriptorsEXT(device(), 1u, &resource_desc_info, &descriptors);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDescriptorHeap, ResourceParameterDataAddressZero) {
TEST_DESCRIPTION("Validate vkWriteResourceDescriptorsEXT case when address is 0, but size is not");
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
{
const VkDeviceSize size = vk::GetPhysicalDeviceDescriptorSizeEXT(Gpu(), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
std::vector<uint8_t> data(static_cast<size_t>(size));
VkDeviceAddressRangeEXT invalid_device_address_range = {0, 16};
VkResourceDescriptorInfoEXT resource_desc_info = vku::InitStructHelper();
resource_desc_info.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
resource_desc_info.data.pAddressRange = &invalid_device_address_range;
VkHostAddressRangeEXT descriptors = {data.data(), static_cast<size_t>(size)};
m_errorMonitor->SetDesiredError("VUID-VkDeviceAddressRangeKHR-size-11411");
vk::WriteResourceDescriptorsEXT(device(), 1u, &resource_desc_info, &descriptors);
m_errorMonitor->VerifyFound();
}
{
const VkDeviceSize size = vk::GetPhysicalDeviceDescriptorSizeEXT(Gpu(), VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER);
std::vector<uint8_t> data(static_cast<size_t>(size));
VkTexelBufferDescriptorInfoEXT texel_buffer_info = vku::InitStructHelper();
texel_buffer_info.format = VK_FORMAT_R8G8B8A8_UNORM;
texel_buffer_info.addressRange.address = 0;
texel_buffer_info.addressRange.size = size;
VkResourceDescriptorInfoEXT resource_desc_info = vku::InitStructHelper();
resource_desc_info.type = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
resource_desc_info.data.pTexelBuffer = &texel_buffer_info;
VkHostAddressRangeEXT descriptors = {data.data(), static_cast<size_t>(size)};
m_errorMonitor->SetDesiredError("VUID-VkDeviceAddressRangeKHR-size-11411");
vk::WriteResourceDescriptorsEXT(device(), 1u, &resource_desc_info, &descriptors);
m_errorMonitor->VerifyFound();
}
}
TEST_F(NegativeDescriptorHeap, ResourceParameterDataSizeZero) {
TEST_DESCRIPTION("Validate vkWriteResourceDescriptorsEXT case when size is 0");
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
auto types = {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER};
const VkDeviceSize buffer_size = heap_props.bufferDescriptorSize;
vkt::Buffer buffer(*m_device, buffer_size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
vkt::device_address);
for (auto type : types) {
const VkDeviceSize size = vk::GetPhysicalDeviceDescriptorSizeEXT(Gpu(), type);
std::vector<uint8_t> data(static_cast<size_t>(size));
VkDeviceAddressRangeEXT invalid_device_address_range = {buffer.Address(), 0};
VkResourceDescriptorInfoEXT resource_desc_info = vku::InitStructHelper();
resource_desc_info.type = type;
resource_desc_info.data.pAddressRange = &invalid_device_address_range;
VkHostAddressRangeEXT descriptors = {data.data(), static_cast<size_t>(size)};
m_errorMonitor->SetDesiredError("VUID-VkResourceDescriptorInfoEXT-type-11433");
vk::WriteResourceDescriptorsEXT(device(), 1u, &resource_desc_info, &descriptors);
m_errorMonitor->VerifyFound();
}
}
TEST_F(NegativeDescriptorHeap, ResourceParameterUniformAlign) {
TEST_DESCRIPTION("Validate vkWriteResourceDescriptorsEXT for VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER");
AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
const VkDeviceSize align = m_device->Physical().limits_.minUniformBufferOffsetAlignment;
const VkDeviceSize bdsize = heap_props.bufferDescriptorSize;
const auto type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
EXPECT_GT(align, 0u);
if (align == 1) {
GTEST_SKIP() << "Cannot be unaligned with align equal 1";
}
vkt::Buffer buffer(*m_device, 2 * std::max(align, bdsize), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, vkt::device_address);
const VkDeviceSize size = vk::GetPhysicalDeviceDescriptorSizeEXT(Gpu(), type);
std::vector<uint8_t> data(static_cast<size_t>(size));
VkDeviceAddressRangeEXT invalid_device_address_range = {0, 0};
VkResourceDescriptorInfoEXT desc_info = vku::InitStructHelper();
desc_info.type = type;
desc_info.data.pAddressRange = &invalid_device_address_range;
VkHostAddressRangeEXT descriptors = {data.data(), static_cast<size_t>(size)};
invalid_device_address_range.address = buffer.Address() + 1;
invalid_device_address_range.size = align;
m_errorMonitor->SetDesiredError("VUID-VkResourceDescriptorInfoEXT-type-12350");
vk::WriteResourceDescriptorsEXT(device(), 1u, &desc_info, &descriptors);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDescriptorHeap, ResourceParameterStorageAlign) {
TEST_DESCRIPTION("Validate vkWriteResourceDescriptorsEXT for VK_DESCRIPTOR_TYPE_STORAGE_BUFFER");
AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
const VkDeviceSize align = m_device->Physical().limits_.minStorageBufferOffsetAlignment;
const VkDeviceSize bdsize = heap_props.bufferDescriptorSize;
EXPECT_GT(align, 0u);
if (align == 1) {
GTEST_SKIP() << "Cannot be unaligned with align equal 1";
}
vkt::Buffer buffer(*m_device, 2 * std::max(align, bdsize), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, vkt::device_address);
const VkDeviceSize size = vk::GetPhysicalDeviceDescriptorSizeEXT(Gpu(), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
std::vector<uint8_t> data(static_cast<size_t>(size));
VkDeviceAddressRangeEXT invalid_device_address_range = {0, 0};
VkResourceDescriptorInfoEXT desc_info = vku::InitStructHelper();
desc_info.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
desc_info.data.pAddressRange = &invalid_device_address_range;
VkHostAddressRangeEXT descriptors = {data.data(), static_cast<size_t>(size)};
invalid_device_address_range.address = buffer.Address() + 1;
invalid_device_address_range.size = align;
m_errorMonitor->SetDesiredError("VUID-VkResourceDescriptorInfoEXT-type-12351");
vk::WriteResourceDescriptorsEXT(device(), 1u, &desc_info, &descriptors);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDescriptorHeap, ResourceParameterAccelerationStructureAlign) {
TEST_DESCRIPTION("Validate vkWriteResourceDescriptorsEXT for VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR");
AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
AddRequiredExtensions(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::accelerationStructure);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
const VkDeviceSize align = 256;
const VkDeviceSize bdsize = heap_props.bufferDescriptorSize;
vkt::Buffer buffer(*m_device, 2 * std::max(align, bdsize), VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR,
vkt::device_address);
const VkDeviceSize size = vk::GetPhysicalDeviceDescriptorSizeEXT(Gpu(), VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR);
std::vector<uint8_t> data(static_cast<size_t>(size));
VkDeviceAddressRangeEXT invalid_device_address_range = {0, 0};
VkResourceDescriptorInfoEXT desc_info = vku::InitStructHelper();
desc_info.type = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR;
desc_info.data.pAddressRange = &invalid_device_address_range;
VkHostAddressRangeEXT descriptors = {data.data(), static_cast<size_t>(size)};
invalid_device_address_range.address = buffer.Address() + 1;
invalid_device_address_range.size = align;
m_errorMonitor->SetDesiredError("VUID-VkResourceDescriptorInfoEXT-type-11454");
vk::WriteResourceDescriptorsEXT(device(), 1u, &desc_info, &descriptors);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDescriptorHeap, UniformTexelBufferOffsetSingleTexelAlignmentFalse) {
TEST_DESCRIPTION("Validate vkWriteResourceDescriptorsEXT with uniformTexelBufferOffsetSingleTexelAlignment == VK_FALSE");
AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT align_props = vku::InitStructHelper();
GetPhysicalDeviceProperties2(align_props);
if (align_props.uniformTexelBufferOffsetSingleTexelAlignment != VK_FALSE) {
GTEST_SKIP() << "uniformTexelBufferOffsetSingleTexelAlignment required to be VK_FALSE";
}
const VkDeviceSize align = align_props.uniformTexelBufferOffsetAlignmentBytes;
const VkDeviceSize bdsize = heap_props.bufferDescriptorSize;
EXPECT_GT(align, 0u);
if (align == 1) {
GTEST_SKIP() << "Cannot be unaligned with align equal 1";
}
vkt::Buffer buffer(*m_device, 2 * std::max(align, bdsize), VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, vkt::device_address);
VkTexelBufferDescriptorInfoEXT texel_buffer_info = vku::InitStructHelper();
texel_buffer_info.format = VK_FORMAT_R8G8B8A8_UNORM;
VkResourceDescriptorInfoEXT desc_info = vku::InitStructHelper();
desc_info.type = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
desc_info.data.pTexelBuffer = &texel_buffer_info;
auto data = std::vector<uint8_t>(static_cast<size_t>(bdsize));
VkHostAddressRangeEXT descriptors = {&data[0], data.size()};
texel_buffer_info.addressRange.address = buffer.Address() + 1;
texel_buffer_info.addressRange.size = align;
m_errorMonitor->SetDesiredError("VUID-VkResourceDescriptorInfoEXT-type-12349");
vk::WriteResourceDescriptorsEXT(device(), 1u, &desc_info, &descriptors);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDescriptorHeap, UniformTexelBufferOffsetSingleTexelAlignmentTrue) {
TEST_DESCRIPTION("Validate vkWriteResourceDescriptorsEXT with uniformTexelBufferOffsetSingleTexelAlignment == VK_TRUE");
AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT align_props = vku::InitStructHelper();
GetPhysicalDeviceProperties2(align_props);
if (align_props.uniformTexelBufferOffsetSingleTexelAlignment != VK_TRUE) {
GTEST_SKIP() << "uniformTexelBufferOffsetSingleTexelAlignment required to be VK_TRUE";
}
const VkFormat format = VK_FORMAT_R8G8B8A8_UNORM;
const VkDeviceSize format_size = GetSmallestGreaterOrEquallPowerOfTwo(vkuFormatTexelBlockSize(format));
const VkDeviceSize align = std::min(align_props.uniformTexelBufferOffsetAlignmentBytes, format_size);
const VkDeviceSize bdsize = heap_props.bufferDescriptorSize;
EXPECT_GT(align, 0u);
if (align == 1) {
GTEST_SKIP() << "Cannot be unaligned with align equal 1";
}
vkt::Buffer buffer(*m_device, 2 * std::max(align, bdsize), VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, vkt::device_address);
VkTexelBufferDescriptorInfoEXT texel_buffer_info = vku::InitStructHelper();
texel_buffer_info.format = format;
VkResourceDescriptorInfoEXT desc_info = vku::InitStructHelper();
desc_info.type = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
desc_info.data.pTexelBuffer = &texel_buffer_info;
auto data = std::vector<uint8_t>(static_cast<size_t>(bdsize));
VkHostAddressRangeEXT descriptors = {&data[0], data.size()};
texel_buffer_info.addressRange.address = buffer.Address() + 1;
texel_buffer_info.addressRange.size = align;
m_errorMonitor->SetDesiredError("VUID-VkResourceDescriptorInfoEXT-type-12349");
vk::WriteResourceDescriptorsEXT(device(), 1u, &desc_info, &descriptors);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDescriptorHeap, StorageTexelBufferOffsetSingleTexelAlignmentFalse) {
TEST_DESCRIPTION("Validate vkWriteResourceDescriptorsEXT with storageTexelBufferOffsetSingleTexelAlignment == VK_FALSE");
AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT align_props = vku::InitStructHelper();
GetPhysicalDeviceProperties2(align_props);
if (align_props.storageTexelBufferOffsetSingleTexelAlignment != VK_FALSE) {
GTEST_SKIP() << "storageTexelBufferOffsetSingleTexelAlignment required to be VK_FALSE";
}
const VkDeviceSize align = align_props.storageTexelBufferOffsetAlignmentBytes;
const VkDeviceSize bdsize = heap_props.bufferDescriptorSize;
EXPECT_GT(align, 0u);
if (align == 1) {
GTEST_SKIP() << "Cannot be unaligned with align equal 1";
}
vkt::Buffer buffer(*m_device, 2 * std::max(align, bdsize), VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT, vkt::device_address);
VkTexelBufferDescriptorInfoEXT texel_buffer_info = vku::InitStructHelper();
texel_buffer_info.format = VK_FORMAT_R8G8B8A8_UNORM;
VkResourceDescriptorInfoEXT desc_info = vku::InitStructHelper();
desc_info.type = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
desc_info.data.pTexelBuffer = &texel_buffer_info;
auto data = std::vector<uint8_t>(static_cast<size_t>(bdsize));
VkHostAddressRangeEXT descriptors = {&data[0], data.size()};
texel_buffer_info.addressRange.address = buffer.Address() + 1;
texel_buffer_info.addressRange.size = align;
m_errorMonitor->SetDesiredError("VUID-VkResourceDescriptorInfoEXT-type-12349");
vk::WriteResourceDescriptorsEXT(device(), 1u, &desc_info, &descriptors);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDescriptorHeap, StorageTexelBufferOffsetSingleTexelAlignmentTrue) {
TEST_DESCRIPTION("Validate vkWriteResourceDescriptorsEXT with storageTexelBufferOffsetSingleTexelAlignment == VK_TRUE");
AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT align_props = vku::InitStructHelper();
GetPhysicalDeviceProperties2(align_props);
if (align_props.storageTexelBufferOffsetSingleTexelAlignment != VK_TRUE) {
GTEST_SKIP() << "storageTexelBufferOffsetSingleTexelAlignment required to be VK_TRUE";
}
const VkFormat format = VK_FORMAT_R8G8B8A8_UNORM;
const VkDeviceSize format_size = GetSmallestGreaterOrEquallPowerOfTwo(vkuFormatTexelBlockSize(format));
const VkDeviceSize align = std::min(align_props.storageTexelBufferOffsetAlignmentBytes, format_size);
const VkDeviceSize bdsize = heap_props.bufferDescriptorSize;
EXPECT_GT(align, 0u);
if (align == 1) {
GTEST_SKIP() << "Cannot be unaligned with align equal 1";
}
vkt::Buffer buffer(*m_device, 2 * std::max(align, bdsize), VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT, vkt::device_address);
VkTexelBufferDescriptorInfoEXT texel_buffer_info = vku::InitStructHelper();
texel_buffer_info.format = format;
VkResourceDescriptorInfoEXT desc_info = vku::InitStructHelper();
desc_info.type = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
desc_info.data.pTexelBuffer = &texel_buffer_info;
auto data = std::vector<uint8_t>(static_cast<size_t>(bdsize));
VkHostAddressRangeEXT descriptors = {&data[0], data.size()};
texel_buffer_info.addressRange.address = buffer.Address() + 1;
texel_buffer_info.addressRange.size = align;
m_errorMonitor->SetDesiredError("VUID-VkResourceDescriptorInfoEXT-type-12349");
vk::WriteResourceDescriptorsEXT(device(), 1u, &desc_info, &descriptors);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDescriptorHeap, MinTexelBufferOffsetAlignment) {
TEST_DESCRIPTION("Validate vkWriteResourceDescriptorsEXT with minTexelBufferOffsetAlignment");
AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
SetTargetApiVersion(VK_API_VERSION_1_2);
AddRequiredExtensions(VK_EXT_DESCRIPTOR_HEAP_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::descriptorHeap);
RETURN_IF_SKIP(Init());
GetPhysicalDeviceProperties2(heap_props);
const VkDeviceSize align = m_device->Physical().limits_.minTexelBufferOffsetAlignment;
const VkDeviceSize bdsize = heap_props.bufferDescriptorSize;
EXPECT_GT(align, 0u);
if (align == 1) {
GTEST_SKIP() << "Cannot be unaligned with align equal 1";
}
vkt::Buffer buffer(*m_device, 2 * std::max(align, bdsize), VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, vkt::device_address);
VkTexelBufferDescriptorInfoEXT texel_buffer_info = vku::InitStructHelper();
texel_buffer_info.format = VK_FORMAT_R8G8B8A8_UNORM;
VkResourceDescriptorInfoEXT desc_info = vku::InitStructHelper();
desc_info.type = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
desc_info.data.pTexelBuffer = &texel_buffer_info;
auto data = std::vector<uint8_t>(static_cast<size_t>(bdsize));
VkHostAddressRangeEXT descriptors = {&data[0], data.size()};
texel_buffer_info.addressRange.address = buffer.Address() + 1;
texel_buffer_info.addressRange.size = align;
m_errorMonitor->SetDesiredError("VUID-VkResourceDescriptorInfoEXT-type-12349");
vk::WriteResourceDescriptorsEXT(device(), 1u, &desc_info, &descriptors);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDescriptorHeap, ResourceParameterYCbCr) {
TEST_DESCRIPTION("Validate vkWriteResourceDescriptorsEXT with YCbCr conversion");
AddRequiredFeature(vkt::Feature::samplerYcbcrConversion);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
const VkDescriptorType types[] = {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT};
for (auto type : types) {
const VkDeviceSize size = vk::GetPhysicalDeviceDescriptorSizeEXT(Gpu(), type);
if (size == 0) {
continue;
}
// Check if the device can make the image required for this test case.
VkSamplerYcbcrConversionImageFormatProperties ycbcr_conversion_image_format_props = vku::InitStructHelper();
VkImageFormatProperties2 format_props = vku::InitStructHelper(&ycbcr_conversion_image_format_props);
VkPhysicalDeviceImageFormatInfo2 form_info = vku::InitStructHelper();
form_info.format = VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM;
form_info.type = VK_IMAGE_TYPE_2D;
form_info.tiling = VK_IMAGE_TILING_OPTIMAL;
form_info.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
VkResult res = vk::GetPhysicalDeviceImageFormatProperties2(Gpu(), &form_info, &format_props);
// If not, skip this part of the test.
if (res || ycbcr_conversion_image_format_props.combinedImageSamplerDescriptorCount == 0) {
continue;
}
vkt::Image image(*m_device, 32, 32, form_info.format, form_info.usage);
auto size2 = size * ycbcr_conversion_image_format_props.combinedImageSamplerDescriptorCount;
std::vector<uint8_t> data(static_cast<size_t>(size2));
VkResourceDescriptorInfoEXT resource_desc_info = vku::InitStructHelper();
resource_desc_info.type = type;
vkt::SamplerYcbcrConversion conversion(*m_device, VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM);
VkSamplerYcbcrConversionInfoKHR ycbcr_conversion_info = vku::InitStructHelper();
ycbcr_conversion_info.conversion = conversion;
VkImageViewCreateInfo image_view_ci = vku::InitStructHelper(&ycbcr_conversion_info);
image_view_ci.viewType = VK_IMAGE_VIEW_TYPE_2D;
image_view_ci.format = form_info.format;
image_view_ci.image = image;
image_view_ci.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
image_view_ci.components = {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A};
VkImageDescriptorInfoEXT image_info = vku::InitStructHelper();
image_info.pView = &image_view_ci;
image_info.layout = VK_IMAGE_LAYOUT_GENERAL;
resource_desc_info.data.pImage = &image_info;
VkHostAddressRangeEXT descriptors = {data.data(), static_cast<size_t>(size - 1)};
m_errorMonitor->SetDesiredError("VUID-vkWriteResourceDescriptorsEXT-pResources-11208");
if (ycbcr_conversion_image_format_props.combinedImageSamplerDescriptorCount == 1) {
m_errorMonitor->SetDesiredError("VUID-vkWriteResourceDescriptorsEXT-size-11207");
}
vk::WriteResourceDescriptorsEXT(device(), 1u, &resource_desc_info, &descriptors);
m_errorMonitor->VerifyFound();
}
}
TEST_F(NegativeDescriptorHeap, ResourceParameterSubsampledImage) {
TEST_DESCRIPTION("Validate vkWriteResourceDescriptorsEXT with subsampled image");
AddRequiredExtensions(VK_EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::fragmentDensityMap);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
const VkDescriptorType types[] = {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT};
for (auto type : types) {
const VkDeviceSize size = vk::GetPhysicalDeviceDescriptorSizeEXT(Gpu(), type);
if (size == 0) {
continue;
}
// Check if the device can make the image required for this test case.
VkSubsampledImageFormatPropertiesEXT subsampled_image_format_props = vku::InitStructHelper();
VkImageFormatProperties2 format_props = vku::InitStructHelper(&subsampled_image_format_props);
VkPhysicalDeviceImageFormatInfo2 form_info = vku::InitStructHelper();
form_info.format = VK_FORMAT_R8G8B8A8_UNORM;
form_info.type = VK_IMAGE_TYPE_2D;
form_info.tiling = VK_IMAGE_TILING_OPTIMAL;
form_info.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
form_info.flags = VK_IMAGE_CREATE_SUBSAMPLED_BIT_EXT;
VkResult res = vk::GetPhysicalDeviceImageFormatProperties2(Gpu(), &form_info, &format_props);
// If not, skip this part of the test.
if (res || subsampled_image_format_props.subsampledImageDescriptorCount == 0) {
continue;
}
VkImageCreateInfo image_create_info = vku::InitStructHelper();
image_create_info.imageType = form_info.type;
image_create_info.format = form_info.format;
image_create_info.extent = {32, 32, 1};
image_create_info.mipLevels = 1;
image_create_info.arrayLayers = 1;
image_create_info.samples = VK_SAMPLE_COUNT_1_BIT;
image_create_info.tiling = form_info.tiling;
image_create_info.usage = form_info.usage;
image_create_info.flags = form_info.flags;
vkt::Image image(*m_device, image_create_info);
auto size2 = size * subsampled_image_format_props.subsampledImageDescriptorCount;
std::vector<uint8_t> data(static_cast<size_t>(size2));
VkResourceDescriptorInfoEXT resource_desc_info = vku::InitStructHelper();
resource_desc_info.type = type;
VkSamplerYcbcrConversionInfoKHR ycbcr_conversion_info = vku::InitStructHelper();
VkImageViewCreateInfo image_view_ci = vku::InitStructHelper(&ycbcr_conversion_info);
image_view_ci.viewType = VK_IMAGE_VIEW_TYPE_2D;
image_view_ci.format = form_info.format;
image_view_ci.image = image;
image_view_ci.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
image_view_ci.components = {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A};
VkImageDescriptorInfoEXT image_info = vku::InitStructHelper();
image_info.pView = &image_view_ci;
image_info.layout = VK_IMAGE_LAYOUT_GENERAL;
resource_desc_info.data.pImage = &image_info;
VkHostAddressRangeEXT descriptors = {data.data(), static_cast<size_t>(size2 - 1)};
m_errorMonitor->SetDesiredError("VUID-vkWriteResourceDescriptorsEXT-pResources-11209");
if (subsampled_image_format_props.subsampledImageDescriptorCount == 1) {
m_errorMonitor->SetDesiredError("VUID-vkWriteResourceDescriptorsEXT-size-11207");
}
vk::WriteResourceDescriptorsEXT(device(), 1u, &resource_desc_info, &descriptors);
m_errorMonitor->VerifyFound();
}
}
TEST_F(NegativeDescriptorHeap, ResourceParameterPViewNull) {
TEST_DESCRIPTION("Validate vkWriteResourceDescriptorsEXT with pView nullptr");
RETURN_IF_SKIP(InitBasicDescriptorHeap());
const VkDescriptorType types[] = {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT};
for (auto type : types) {
const VkDeviceSize size = vk::GetPhysicalDeviceDescriptorSizeEXT(Gpu(), type);
ASSERT_TRUE(size != 0);
std::vector<uint8_t> data(static_cast<size_t>(size));
vkt::Image image(*m_device, 32, 32, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
VkResourceDescriptorInfoEXT resource_desc_info = vku::InitStructHelper();
resource_desc_info.type = type;
VkImageDescriptorInfoEXT image_info = vku::InitStructHelper();
image_info.pView = nullptr;
image_info.layout = VK_IMAGE_LAYOUT_GENERAL;
resource_desc_info.data.pImage = &image_info;
VkHostAddressRangeEXT descriptors = {data.data(), static_cast<size_t>(size)};
m_errorMonitor->SetDesiredError("VUID-VkImageDescriptorInfoEXT-pView-parameter");
vk::WriteResourceDescriptorsEXT(device(), 1u, &resource_desc_info, &descriptors);
m_errorMonitor->VerifyFound();
}
}
TEST_F(NegativeDescriptorHeap, ResourceParameterPView) {
TEST_DESCRIPTION("Validate vkWriteResourceDescriptorsEXT triggers all validation paths for pView");
RETURN_IF_SKIP(InitBasicDescriptorHeap());
std::vector<uint8_t> data(static_cast<size_t>(heap_props.imageDescriptorSize));
vkt::Image image(*m_device, 32, 32, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_STORAGE_BIT);
VkResourceDescriptorInfoEXT resource_desc_info = vku::InitStructHelper();
resource_desc_info.type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
VkImageViewCreateInfo image_view_ci = vku::InitStructHelper();
image_view_ci.format = image.CreateInfo().format;
image_view_ci.image = image;
image_view_ci.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
image_view_ci.components = {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A};
VkImageDescriptorInfoEXT image_info = vku::InitStructHelper();
image_info.pView = &image_view_ci;
image_info.layout = VK_IMAGE_LAYOUT_GENERAL;
resource_desc_info.data.pImage = &image_info;
VkHostAddressRangeEXT descriptors = {data.data(), data.size()};
{
// Validate stateless path
image_view_ci.viewType = VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
image_view_ci.image = image;
image_view_ci.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
m_errorMonitor->SetDesiredError("VUID-VkImageViewCreateInfo-viewType-01004");
vk::WriteResourceDescriptorsEXT(device(), 1u, &resource_desc_info, &descriptors);
m_errorMonitor->VerifyFound();
}
{
// Validate object tracker path
image_view_ci.viewType = VK_IMAGE_VIEW_TYPE_2D;
image_view_ci.image = (VkImage)(((uint64_t)image.handle()) + 1); // Make invalid handle to trigger error
m_errorMonitor->SetDesiredError("VUID-VkImageViewCreateInfo-image-parameter");
vk::WriteResourceDescriptorsEXT(device(), 1u, &resource_desc_info, &descriptors);
m_errorMonitor->VerifyFound();
}
{
// Validate core validation path
image_view_ci.image = image;
image.Memory().Destroy();
m_errorMonitor->SetDesiredError("VUID-VkImageViewCreateInfo-image-01020");
vk::WriteResourceDescriptorsEXT(device(), 1u, &resource_desc_info, &descriptors);
m_errorMonitor->VerifyFound();
}
}
TEST_F(NegativeDescriptorHeap, CmdBindSamplerHeap) {
TEST_DESCRIPTION("Validate vkCmdBindSamplerHeapEXT");
AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
const VkDeviceSize descriptor_size = AlignSampler(2 * heap_props.samplerDescriptorSize);
const VkDeviceSize heap_size = descriptor_size + heap_props.minSamplerHeapReservedRange;
vkt::Buffer heap(*m_device, heap_size, VK_BUFFER_USAGE_DESCRIPTOR_HEAP_BIT_EXT, vkt::device_address);
if (heap_props.samplerDescriptorSize + 1 != 0) {
// reservedRangeOffset check
VkBindHeapInfoEXT bind_info = vku::InitStructHelper();
bind_info.heapRange = {heap.Address(), descriptor_size + heap_props.minSamplerHeapReservedRange};
bind_info.reservedRangeOffset = descriptor_size * 2;
bind_info.reservedRangeSize = heap_props.minSamplerHeapReservedRange;
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdBindSamplerHeapEXT-pBindInfo-11223");
if (bind_info.heapRange.size > heap_props.maxSamplerHeapSize) {
m_errorMonitor->SetDesiredError("VUID-vkCmdBindSamplerHeapEXT-pBindInfo-11225");
}
vk::CmdBindSamplerHeapEXT(m_command_buffer, &bind_info);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
const bool overflow = heap_props.maxSamplerHeapSize + heap_props.samplerDescriptorSize <
(heap_props.maxSamplerHeapSize | heap_props.samplerDescriptorSize);
const VkDeviceSize max_buffer_size = descriptor_size + heap_props.maxSamplerHeapSize;
VkPhysicalDeviceVulkan11Properties props11 = vku::InitStructHelper();
GetPhysicalDeviceProperties2(props11);
if (!overflow && max_buffer_size <= props11.maxMemoryAllocationSize) {
VkBufferCreateInfo buffer_ci = vku::InitStructHelper();
buffer_ci.usage = VK_BUFFER_USAGE_DESCRIPTOR_HEAP_BIT_EXT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
buffer_ci.size = max_buffer_size;
vkt::Buffer max_buffer(*m_device, buffer_ci, vkt::no_mem);
VkMemoryRequirements mem_reqs;
vk::GetBufferMemoryRequirements(device(), max_buffer, &mem_reqs);
VkMemoryAllocateFlagsInfo alloc_flags = vku::InitStructHelper();
alloc_flags.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT;
auto mem_alloc_info =
vkt::DeviceMemory::GetResourceAllocInfo(*m_device, mem_reqs, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &alloc_flags);
vkt::DeviceMemory mem(*m_device, mem_alloc_info);
if (!mem.initialized()) {
GTEST_SKIP() << "Can't allocte memory over maxResourceHeapSize";
}
vk::BindBufferMemory(device(), max_buffer, mem, 0);
// reservedRangeOffset check
VkBindHeapInfoEXT bind_info = vku::InitStructHelper();
bind_info.heapRange = {max_buffer.Address(), max_buffer_size};
bind_info.reservedRangeOffset = 0;
bind_info.reservedRangeSize = heap_props.minSamplerHeapReservedRange;
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdBindSamplerHeapEXT-pBindInfo-11225");
vk::CmdBindSamplerHeapEXT(m_command_buffer, &bind_info);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
}
TEST_F(NegativeDescriptorHeap, CmdBindSamplerHeapReservedRangeSize) {
TEST_DESCRIPTION("Validate vkCmdBindSamplerHeapEXT ReservedRangeSize is greater or equal minSamplerHeapReservedRange");
AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
if (heap_props.minSamplerHeapReservedRange == 0) {
GTEST_SKIP() << "Cannot run when minSamplerHeapReservedRange is zero";
}
const VkDeviceSize heap_size = 2 * heap_props.samplerDescriptorSize + heap_props.minSamplerHeapReservedRange;
vkt::Buffer heap(*m_device, heap_size, VK_BUFFER_USAGE_DESCRIPTOR_HEAP_BIT_EXT, vkt::device_address);
VkBindHeapInfoEXT bind_info = vku::InitStructHelper();
bind_info.heapRange = heap.AddressRange();
bind_info.reservedRangeSize = heap_props.minSamplerHeapReservedRange - 1;
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdBindSamplerHeapEXT-pBindInfo-11224");
vk::CmdBindSamplerHeapEXT(m_command_buffer, &bind_info);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeDescriptorHeap, CmdBindSamplerHeapAlign) {
TEST_DESCRIPTION("Validate vkCmdBindSamplerHeapEXT addr alignement");
AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
const VkDeviceSize heap_size = 2 * heap_props.samplerDescriptorSize + heap_props.minSamplerHeapReservedRange;
EXPECT_GT(heap_props.samplerHeapAlignment, 0u);
if (heap_props.samplerHeapAlignment == 1) {
GTEST_SKIP() << "Cannot be unaligned with align equal 1";
}
vkt::Buffer heap(*m_device, heap_size, VK_BUFFER_USAGE_DESCRIPTOR_HEAP_BIT_EXT, vkt::device_address);
VkBindHeapInfoEXT bind_info = vku::InitStructHelper();
bind_info.heapRange = {heap.Address() + 1, heap_size - 1};
bind_info.reservedRangeOffset = 0;
bind_info.reservedRangeSize = heap_props.minSamplerHeapReservedRange;
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdBindSamplerHeapEXT-pBindInfo-11226");
vk::CmdBindSamplerHeapEXT(m_command_buffer, &bind_info);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeDescriptorHeap, CmdBindSamplerHeapReservedRangeAlign) {
TEST_DESCRIPTION("Validate vkCmdBindSamplerHeapEXT reservedRange alignement");
AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
const VkDeviceSize heap_size = 2 * std::max(heap_props.samplerDescriptorSize, heap_props.minSamplerHeapReservedRange);
vkt::Buffer heap(*m_device, heap_size, VK_BUFFER_USAGE_DESCRIPTOR_HEAP_BIT_EXT, vkt::device_address);
VkBindHeapInfoEXT bind_info = vku::InitStructHelper();
bind_info.heapRange = heap.AddressRange();
bind_info.reservedRangeOffset = 1;
bind_info.reservedRangeSize = heap_size / 2;
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdBindSamplerHeapEXT-pBindInfo-11434");
vk::CmdBindSamplerHeapEXT(m_command_buffer, &bind_info);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeDescriptorHeap, CmdBindSamplerHeapSecondaryBuffer) {
TEST_DESCRIPTION("Validate vkCmdBindSamplerHeapEXT command written to secondary buffer");
AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
const VkDeviceSize heap_size = heap_props.samplerDescriptorSize + heap_props.minSamplerHeapReservedRange;
vkt::Buffer heap(*m_device, heap_size, VK_BUFFER_USAGE_DESCRIPTOR_HEAP_BIT_EXT, vkt::device_address);
vkt::CommandBuffer secondary(*m_device, m_command_pool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
VkCommandBufferInheritanceDescriptorHeapInfoEXT inh_desc_heap_info = vku::InitStructHelper();
VkBindHeapInfoEXT samplerHeapBindInfo = vku::InitStructHelper();
inh_desc_heap_info.pSamplerHeapBindInfo = &samplerHeapBindInfo;
VkCommandBufferInheritanceInfo inh = vku::InitStructHelper(&inh_desc_heap_info);
VkCommandBufferBeginInfo cbbi = vku::InitStructHelper();
cbbi.pInheritanceInfo = &inh;
secondary.Begin(&cbbi);
VkBindHeapInfoEXT bind_info = vku::InitStructHelper();
bind_info.heapRange = heap.AddressRange();
bind_info.reservedRangeOffset = heap_props.samplerDescriptorSize;
bind_info.reservedRangeSize = heap_props.minSamplerHeapReservedRange;
if (bind_info.reservedRangeOffset % heap_props.samplerDescriptorSize != 0) {
m_errorMonitor->SetDesiredError("VUID-vkCmdBindSamplerHeapEXT-pBindInfo-11434");
}
m_errorMonitor->SetDesiredError("VUID-vkCmdBindSamplerHeapEXT-commandBuffer-11231");
vk::CmdBindSamplerHeapEXT(secondary, &bind_info);
m_errorMonitor->VerifyFound();
secondary.End();
}
TEST_F(NegativeDescriptorHeap, CmdBindResourceHeap) {
AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
const VkDeviceSize app_size = AlignResource(heap_props.bufferDescriptorSize);
const VkDeviceSize heap_size = app_size + heap_props.minResourceHeapReservedRange;
vkt::Buffer heap(*m_device, heap_size, VK_BUFFER_USAGE_DESCRIPTOR_HEAP_BIT_EXT, vkt::device_address);
{
// reservedRangeOffset check
VkBindHeapInfoEXT bind_info = vku::InitStructHelper();
bind_info.heapRange = heap.AddressRange();
bind_info.reservedRangeOffset = app_size;
bind_info.reservedRangeSize = heap_size;
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdBindResourceHeapEXT-pBindInfo-11232");
vk::CmdBindResourceHeapEXT(m_command_buffer, &bind_info);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
if (heap_props.minResourceHeapReservedRange > 0) {
// size check
VkBindHeapInfoEXT bind_info = vku::InitStructHelper();
bind_info.heapRange = heap.AddressRange();
bind_info.reservedRangeSize = heap_props.minResourceHeapReservedRange - 1;
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdBindResourceHeapEXT-pBindInfo-11233");
vk::CmdBindResourceHeapEXT(m_command_buffer, &bind_info);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
const bool overflow = heap_props.maxResourceHeapSize + heap_props.bufferDescriptorSize <
(heap_props.maxResourceHeapSize | heap_props.bufferDescriptorSize);
const auto max_buffer_size = heap_props.maxResourceHeapSize + heap_props.bufferDescriptorSize;
VkPhysicalDeviceVulkan11Properties props11 = vku::InitStructHelper();
GetPhysicalDeviceProperties2(props11);
if (!overflow && max_buffer_size <= props11.maxMemoryAllocationSize) {
VkBufferCreateInfo buffer_ci = vku::InitStructHelper();
buffer_ci.usage = VK_BUFFER_USAGE_DESCRIPTOR_HEAP_BIT_EXT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
buffer_ci.size = max_buffer_size;
vkt::Buffer max_buffer(*m_device, buffer_ci, vkt::no_mem);
VkMemoryRequirements mem_reqs;
vk::GetBufferMemoryRequirements(device(), max_buffer, &mem_reqs);
VkMemoryAllocateFlagsInfo alloc_flags = vku::InitStructHelper();
alloc_flags.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT;
auto mem_alloc_info =
vkt::DeviceMemory::GetResourceAllocInfo(*m_device, mem_reqs, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &alloc_flags);
vkt::DeviceMemory mem(*m_device, mem_alloc_info);
if (!mem.initialized()) {
GTEST_SKIP() << "Can't allocte memory over maxResourceHeapSize";
}
vk::BindBufferMemory(device(), max_buffer, mem, 0);
// reservedRangeOffset check
VkBindHeapInfoEXT bind_info = vku::InitStructHelper();
bind_info.heapRange = {max_buffer.Address(), heap_props.maxResourceHeapSize + heap_props.bufferDescriptorSize};
bind_info.reservedRangeOffset = 0;
bind_info.reservedRangeSize = heap_props.minResourceHeapReservedRange;
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdBindResourceHeapEXT-pBindInfo-11234");
vk::CmdBindResourceHeapEXT(m_command_buffer, &bind_info);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
}
TEST_F(NegativeDescriptorHeap, SamplerInheritance) {
TEST_DESCRIPTION("Validate that inherited ranges match primary buffer");
AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
const VkDeviceSize heap_size = heap_props.minSamplerHeapReservedRange + 2 * heap_props.samplerDescriptorSize;
vkt::Buffer heap(*m_device, heap_size, VK_BUFFER_USAGE_DESCRIPTOR_HEAP_BIT_EXT, vkt::device_address);
vkt::CommandBuffer secondary(*m_device, m_command_pool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
{
VkCommandBufferInheritanceDescriptorHeapInfoEXT inh_desc_heap_info = vku::InitStructHelper();
VkBindHeapInfoEXT bind_info = vku::InitStructHelper();
bind_info.heapRange = {heap.Address(), heap_size / 2};
bind_info.reservedRangeOffset = 0;
bind_info.reservedRangeSize = heap_props.minSamplerHeapReservedRange;
inh_desc_heap_info.pSamplerHeapBindInfo = &bind_info;
VkCommandBufferInheritanceInfo inh = vku::InitStructHelper(&inh_desc_heap_info);
VkCommandBufferBeginInfo cbbi = vku::InitStructHelper();
cbbi.pInheritanceInfo = &inh;
secondary.Begin(&cbbi);
secondary.End();
}
{
m_command_buffer.Begin();
VkBindHeapInfoEXT bind_info = vku::InitStructHelper();
bind_info.heapRange = heap.AddressRange();
bind_info.reservedRangeOffset = 0;
bind_info.reservedRangeSize = heap_props.minSamplerHeapReservedRange;
vk::CmdBindSamplerHeapEXT(m_command_buffer, &bind_info);
m_errorMonitor->SetDesiredError("VUID-vkCmdExecuteCommands-commandBuffer-11351");
vk::CmdExecuteCommands(m_command_buffer, 1, &secondary.handle());
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
}
TEST_F(NegativeDescriptorHeap, ResourceInheritance) {
TEST_DESCRIPTION("Validate that inherited ranges match primary buffer");
AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
const VkDeviceSize heap_size = heap_props.minResourceHeapReservedRange + 2 * heap_props.bufferDescriptorSize;
vkt::Buffer heap(*m_device, heap_size, VK_BUFFER_USAGE_DESCRIPTOR_HEAP_BIT_EXT, vkt::device_address);
vkt::CommandBuffer secondary(*m_device, m_command_pool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
{
VkCommandBufferInheritanceDescriptorHeapInfoEXT inh_desc_heap_info = vku::InitStructHelper();
VkBindHeapInfoEXT bind_info = vku::InitStructHelper();
bind_info.heapRange = {heap.Address(), heap_size / 2};
bind_info.reservedRangeOffset = 0;
bind_info.reservedRangeSize = heap_props.minResourceHeapReservedRange;
inh_desc_heap_info.pResourceHeapBindInfo = &bind_info;
VkCommandBufferInheritanceInfo inh = vku::InitStructHelper(&inh_desc_heap_info);
VkCommandBufferBeginInfo cbbi = vku::InitStructHelper();
cbbi.pInheritanceInfo = &inh;
secondary.Begin(&cbbi);
secondary.End();
}
{
m_command_buffer.Begin();
VkBindHeapInfoEXT bind_info = vku::InitStructHelper();
bind_info.heapRange = heap.AddressRange();
bind_info.reservedRangeOffset = 0;
bind_info.reservedRangeSize = heap_props.minResourceHeapReservedRange;
vk::CmdBindResourceHeapEXT(m_command_buffer, &bind_info);
m_errorMonitor->SetDesiredError("VUID-vkCmdExecuteCommands-commandBuffer-11352");
vk::CmdExecuteCommands(m_command_buffer, 1, &secondary.handle());
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
}
TEST_F(NegativeDescriptorHeap, CmdBindResourceHeapAlign) {
AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
EXPECT_GT(heap_props.resourceHeapAlignment, 0u);
if (heap_props.resourceHeapAlignment == 1) {
GTEST_SKIP() << "Cannot be unaligned with align equal 1";
}
if (heap_props.minResourceHeapReservedRange == 0) {
GTEST_SKIP() << "Test requires minResourceHeapReservedRange to not be 0";
}
const VkDeviceSize heap_size = heap_props.minResourceHeapReservedRange * 2;
vkt::Buffer heap(*m_device, heap_size, VK_BUFFER_USAGE_DESCRIPTOR_HEAP_BIT_EXT, vkt::device_address);
VkBindHeapInfoEXT bind_info = vku::InitStructHelper();
bind_info.heapRange = {heap.Address() + 1, heap_size - 1};
bind_info.reservedRangeOffset = 0;
bind_info.reservedRangeSize = heap_props.minResourceHeapReservedRange;
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdBindResourceHeapEXT-pBindInfo-11235");
vk::CmdBindResourceHeapEXT(m_command_buffer, &bind_info);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeDescriptorHeap, CmdBindResourceHeapReservedRangeAlign) {
TEST_DESCRIPTION("Validate vkCmdBindResourceHeapEXT reservedRangeOffset alignment");
AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
const VkDeviceSize buf_img_size = std::max(heap_props.bufferDescriptorAlignment, heap_props.imageDescriptorAlignment);
const VkDeviceSize heap_size = 2 * std::max(buf_img_size, heap_props.minResourceHeapReservedRange);
vkt::Buffer heap(*m_device, heap_size, VK_BUFFER_USAGE_DESCRIPTOR_HEAP_BIT_EXT, vkt::device_address);
// reservedRangeOffset alignment check
VkBindHeapInfoEXT bind_info = vku::InitStructHelper();
bind_info.heapRange = heap.AddressRange();
bind_info.reservedRangeOffset = 1;
bind_info.reservedRangeSize = heap_size / 2;
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdBindResourceHeapEXT-pBindInfo-11435");
m_errorMonitor->SetDesiredError("VUID-vkCmdBindResourceHeapEXT-pBindInfo-11436");
vk::CmdBindResourceHeapEXT(m_command_buffer, &bind_info);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeDescriptorHeap, CmdBindResourceHeapSecondaryBuffer) {
TEST_DESCRIPTION("Validate vkCmdBindResourceHeapEXT command written to secondary buffer");
AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
const VkDeviceSize descriptor_size = AlignResource(heap_props.bufferDescriptorSize);
const VkDeviceSize heap_size = descriptor_size + heap_props.minResourceHeapReservedRange;
vkt::Buffer heap(*m_device, heap_size, VK_BUFFER_USAGE_DESCRIPTOR_HEAP_BIT_EXT, vkt::device_address);
vkt::CommandBuffer secondary(*m_device, m_command_pool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
VkCommandBufferInheritanceDescriptorHeapInfoEXT inh_desc_heap_info = vku::InitStructHelper();
VkBindHeapInfoEXT resourceHeapBindInfo = vku::InitStructHelper();
inh_desc_heap_info.pResourceHeapBindInfo = &resourceHeapBindInfo;
VkCommandBufferInheritanceInfo inh = vku::InitStructHelper(&inh_desc_heap_info);
VkCommandBufferBeginInfo cbbi = vku::InitStructHelper();
cbbi.pInheritanceInfo = &inh;
secondary.Begin(&cbbi);
VkBindHeapInfoEXT bind_info = vku::InitStructHelper();
bind_info.heapRange = heap.AddressRange();
bind_info.reservedRangeOffset = descriptor_size;
bind_info.reservedRangeSize = heap_props.minResourceHeapReservedRange;
m_errorMonitor->SetDesiredError("VUID-vkCmdBindResourceHeapEXT-commandBuffer-11238");
vk::CmdBindResourceHeapEXT(secondary, &bind_info);
m_errorMonitor->VerifyFound();
secondary.End();
}
TEST_F(NegativeDescriptorHeap, CmdBindResourceHeapSecondaryBufferMemoryTests) {
TEST_DESCRIPTION("Validate memory overflow corruption and binding written to secondary buffer");
AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
vkt::CommandBuffer secondary(*m_device, m_command_pool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
VkCommandBufferInheritanceDescriptorHeapInfoEXT inh_desc_heap_info = vku::InitStructHelper();
VkCommandBufferInheritanceInfo inh = vku::InitStructHelper(&inh_desc_heap_info);
VkCommandBufferBeginInfo cbbi = vku::InitStructHelper();
cbbi.pInheritanceInfo = &inh;
{
secondary.Begin(&cbbi);
const VkDeviceSize heap_size = AlignSampler(heap_props.samplerDescriptorSize) + heap_props.minSamplerHeapReservedRange;
vkt::Buffer heap(*m_device, heap_size, VK_BUFFER_USAGE_DESCRIPTOR_HEAP_BIT_EXT, vkt::device_address);
VkBindHeapInfoEXT bind_info = vku::InitStructHelper();
bind_info.heapRange = {heap.Address(), heap_size + heap_props.samplerDescriptorAlignment};
bind_info.reservedRangeOffset = heap_props.samplerDescriptorAlignment;
bind_info.reservedRangeSize = heap_props.minSamplerHeapReservedRange;
m_errorMonitor->SetDesiredError("VUID-VkDeviceAddressRangeKHR-address-11365");
vk::CmdBindSamplerHeapEXT(secondary, &bind_info);
m_errorMonitor->VerifyFound();
secondary.End();
}
{
secondary.Begin(&cbbi);
const VkDeviceSize heap_size = AlignSampler(heap_props.samplerDescriptorSize) + heap_props.minSamplerHeapReservedRange;
vkt::Buffer heap(*m_device, heap_size, VK_BUFFER_USAGE_DESCRIPTOR_HEAP_BIT_EXT, vkt::device_address);
VkBindHeapInfoEXT bind_info = vku::InitStructHelper();
bind_info.heapRange = heap.AddressRange();
bind_info.reservedRangeOffset = heap_props.samplerDescriptorAlignment;
bind_info.reservedRangeSize = heap_props.minSamplerHeapReservedRange;
heap.Memory().Destroy();
m_errorMonitor->SetDesiredError("VUID-VkDeviceAddress-None-10894");
vk::CmdBindSamplerHeapEXT(secondary, &bind_info);
m_errorMonitor->VerifyFound();
secondary.End();
}
{
secondary.Begin(&cbbi);
const VkDeviceSize heap_size = heap_props.bufferDescriptorSize + heap_props.minResourceHeapReservedRange;
vkt::Buffer heap(*m_device, heap_size, VK_BUFFER_USAGE_DESCRIPTOR_HEAP_BIT_EXT, vkt::device_address);
VkBindHeapInfoEXT bind_info = vku::InitStructHelper();
bind_info.heapRange = {heap.Address(), heap_size + heap_props.resourceHeapAlignment};
bind_info.reservedRangeOffset = 0;
bind_info.reservedRangeSize = heap_props.minResourceHeapReservedRange;
m_errorMonitor->SetDesiredError("VUID-VkDeviceAddressRangeKHR-address-11365");
vk::CmdBindResourceHeapEXT(secondary, &bind_info);
m_errorMonitor->VerifyFound();
secondary.End();
}
{
secondary.Begin(&cbbi);
const VkDeviceSize heap_size = heap_props.bufferDescriptorSize + heap_props.minResourceHeapReservedRange;
vkt::Buffer heap(*m_device, heap_size, VK_BUFFER_USAGE_DESCRIPTOR_HEAP_BIT_EXT, vkt::device_address);
VkBindHeapInfoEXT bind_info = vku::InitStructHelper();
bind_info.heapRange = heap.AddressRange();
bind_info.reservedRangeOffset = 0;
bind_info.reservedRangeSize = heap_props.minResourceHeapReservedRange;
heap.Memory().Destroy();
m_errorMonitor->SetDesiredError("VUID-VkDeviceAddress-None-10894");
vk::CmdBindResourceHeapEXT(secondary, &bind_info);
m_errorMonitor->VerifyFound();
secondary.End();
}
}
TEST_F(NegativeDescriptorHeap, CmdPushData) {
AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
std::vector<uint8_t> payload(static_cast<size_t>(4 * heap_props.maxPushDataSize));
VkPushDataInfoEXT push_data_info = vku::InitStructHelper();
push_data_info.data.address = payload.data();
m_command_buffer.Begin();
{
push_data_info.data.size = payload.size();
push_data_info.offset = (uint32_t)heap_props.maxPushDataSize;
m_errorMonitor->SetDesiredError("VUID-VkPushDataInfoEXT-offset-11243");
vk::CmdPushDataEXT(m_command_buffer, &push_data_info);
m_errorMonitor->VerifyFound();
}
{
push_data_info.data.size = 0;
push_data_info.offset = 0;
m_errorMonitor->SetDesiredError("VUID-VkHostAddressRangeConstEXT-size-arraylength");
vk::CmdPushDataEXT(m_command_buffer, &push_data_info);
m_errorMonitor->VerifyFound();
}
{
push_data_info.data.size = (uint32_t)heap_props.maxPushDataSize / 2;
push_data_info.offset = 1;
m_errorMonitor->SetDesiredError("VUID-VkPushDataInfoEXT-offset-11418");
vk::CmdPushDataEXT(m_command_buffer, &push_data_info);
m_errorMonitor->VerifyFound();
}
{
push_data_info.data.size = 1 + (uint32_t)heap_props.maxPushDataSize / 2;
push_data_info.offset = 0;
m_errorMonitor->SetDesiredError("VUID-VkPushDataInfoEXT-data-11419");
vk::CmdPushDataEXT(m_command_buffer, &push_data_info);
m_errorMonitor->VerifyFound();
}
}
TEST_F(NegativeDescriptorHeap, ShaderDescriptorSetAndBindingMapping) {
RETURN_IF_SKIP(InitBasicDescriptorHeap());
InitRenderTarget();
VkShaderDescriptorSetAndBindingMappingInfoEXT mapping_info = vku::InitStructHelper();
VkDescriptorSetAndBindingMappingEXT mapping[2];
mapping_info.mappingCount = 2;
mapping_info.pMappings = mapping;
{
// Same range
mapping[0] = MakeSetAndBindingMapping(0, 0, 1, VK_SPIRV_RESOURCE_TYPE_UNIFORM_BUFFER_BIT_EXT);
mapping[0].source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT;
mapping[1] = mapping[0];
CreatePipelineHelper pipe(*this);
pipe.shader_stages_[0].pNext = &mapping_info;
m_errorMonitor->SetDesiredError("VUID-VkShaderDescriptorSetAndBindingMappingInfoEXT-pMappings-11244");
pipe.CreateGraphicsPipeline();
m_errorMonitor->VerifyFound();
}
{
// Overlapping subrange
mapping[0] = MakeSetAndBindingMapping(0, 1, 10, VK_SPIRV_RESOURCE_TYPE_SAMPLER_BIT_EXT);
mapping[0].source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT;
mapping[1] = MakeSetAndBindingMapping(0, 2, 5, VK_SPIRV_RESOURCE_TYPE_SAMPLER_BIT_EXT);
mapping[1].source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT;
CreatePipelineHelper pipe(*this);
pipe.shader_stages_[0].pNext = &mapping_info;
m_errorMonitor->SetDesiredError("VUID-VkShaderDescriptorSetAndBindingMappingInfoEXT-pMappings-11244");
pipe.CreateGraphicsPipeline();
m_errorMonitor->VerifyFound();
}
{
// Overlapping range
mapping[0] = MakeSetAndBindingMapping(1, 0, 10, VK_SPIRV_RESOURCE_TYPE_SAMPLER_BIT_EXT);
mapping[0].source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT;
mapping[1] = MakeSetAndBindingMapping(1, 2, 10, VK_SPIRV_RESOURCE_TYPE_SAMPLER_BIT_EXT);
mapping[1].source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT;
CreatePipelineHelper pipe(*this);
pipe.shader_stages_[0].pNext = &mapping_info;
m_errorMonitor->SetDesiredError("VUID-VkShaderDescriptorSetAndBindingMappingInfoEXT-pMappings-11244");
pipe.CreateGraphicsPipeline();
m_errorMonitor->VerifyFound();
}
{
// Overlapping range with UINT32_MAX bindingCount
mapping[0] = MakeSetAndBindingMapping(2, 20, UINT32_MAX, VK_SPIRV_RESOURCE_TYPE_SAMPLER_BIT_EXT);
mapping[0].source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT;
mapping[1] = MakeSetAndBindingMapping(2, 30, 10, VK_SPIRV_RESOURCE_TYPE_SAMPLER_BIT_EXT);
mapping[1].source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT;
CreatePipelineHelper pipe(*this);
pipe.shader_stages_[0].pNext = &mapping_info;
m_errorMonitor->SetDesiredError("VUID-VkShaderDescriptorSetAndBindingMappingInfoEXT-pMappings-11244");
pipe.CreateGraphicsPipeline();
m_errorMonitor->VerifyFound();
}
{
// No overlapping
mapping[0] = MakeSetAndBindingMapping(1, 0, 1, VK_SPIRV_RESOURCE_TYPE_SAMPLER_BIT_EXT);
mapping[0].source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT;
mapping[1] = MakeSetAndBindingMapping(1, 1, 1, VK_SPIRV_RESOURCE_TYPE_SAMPLER_BIT_EXT);
mapping[1].source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT;
CreateComputePipelineHelper pipe(*this);
pipe.LateBindPipelineInfo();
pipe.cp_ci_.stage.pNext = &mapping_info;
m_errorMonitor->Reset();
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
}
TEST_F(NegativeDescriptorHeap, DescriptorSetAndBindingMappingPipeline) {
TEST_DESCRIPTION("Validate VkDescriptorSetAndBindingMappingEXT structure using pipeline");
RETURN_IF_SKIP(InitBasicDescriptorHeap());
VkDescriptorSetAndBindingMappingEXT mapping = {};
VkShaderDescriptorSetAndBindingMappingInfoEXT mapping_info = vku::InitStructHelper();
mapping_info.mappingCount = 1;
mapping_info.pMappings = &mapping;
for (auto source : {VK_DESCRIPTOR_MAPPING_SOURCE_PUSH_DATA_EXT, VK_DESCRIPTOR_MAPPING_SOURCE_PUSH_ADDRESS_EXT,
VK_DESCRIPTOR_MAPPING_SOURCE_INDIRECT_ADDRESS_EXT, VK_DESCRIPTOR_MAPPING_SOURCE_RESOURCE_HEAP_DATA_EXT}) {
mapping = MakeSetAndBindingMapping(0, 0, 2, VK_SPIRV_RESOURCE_TYPE_UNIFORM_BUFFER_BIT_EXT);
mapping.source = source;
CreateComputePipelineHelper pipe(*this);
pipe.LateBindPipelineInfo();
pipe.cp_ci_.stage.pNext = &mapping_info;
m_errorMonitor->SetDesiredError("VUID-VkDescriptorSetAndBindingMappingEXT-source-11245");
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
for (auto source : {VK_DESCRIPTOR_MAPPING_SOURCE_PUSH_DATA_EXT, VK_DESCRIPTOR_MAPPING_SOURCE_PUSH_ADDRESS_EXT}) {
bool data = source == VK_DESCRIPTOR_MAPPING_SOURCE_PUSH_DATA_EXT;
mapping = MakeSetAndBindingMapping(0, 0, 1, VK_SPIRV_RESOURCE_TYPE_UNIFORM_BUFFER_BIT_EXT);
mapping.source = source;
if (data) {
mapping.sourceData.pushDataOffset = 3;
} else {
mapping.sourceData.pushAddressOffset = 7;
}
CreateComputePipelineHelper pipe(*this);
pipe.LateBindPipelineInfo();
pipe.cp_ci_.stage.pNext = &mapping_info;
m_errorMonitor->SetDesiredError(data ? "VUID-VkDescriptorSetAndBindingMappingEXT-source-11246"
: "VUID-VkDescriptorSetAndBindingMappingEXT-source-11247");
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
for (auto source :
{VK_DESCRIPTOR_MAPPING_SOURCE_SHADER_RECORD_DATA_EXT, VK_DESCRIPTOR_MAPPING_SOURCE_SHADER_RECORD_ADDRESS_EXT}) {
mapping = MakeSetAndBindingMapping(0, 0, 2, VK_SPIRV_RESOURCE_TYPE_UNIFORM_BUFFER_BIT_EXT);
mapping.source = source;
mapping.sourceData.shaderRecordAddressOffset = 8;
CreateComputePipelineHelper pipe(*this);
pipe.LateBindPipelineInfo();
pipe.cp_ci_.stage.pNext = &mapping_info;
m_errorMonitor->SetDesiredError("VUID-VkDescriptorSetAndBindingMappingEXT-source-11248");
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
for (auto source :
{VK_DESCRIPTOR_MAPPING_SOURCE_SHADER_RECORD_DATA_EXT, VK_DESCRIPTOR_MAPPING_SOURCE_SHADER_RECORD_ADDRESS_EXT}) {
mapping = MakeSetAndBindingMapping(0, 0, 1, VK_SPIRV_RESOURCE_TYPE_UNIFORM_BUFFER_BIT_EXT);
bool data = source == VK_DESCRIPTOR_MAPPING_SOURCE_SHADER_RECORD_DATA_EXT;
mapping.source = source;
if (data) {
mapping.sourceData.shaderRecordDataOffset = 3;
} else {
mapping.sourceData.shaderRecordAddressOffset = 7;
}
CreateComputePipelineHelper pipe(*this);
pipe.LateBindPipelineInfo();
pipe.cp_ci_.stage.pNext = &mapping_info;
m_errorMonitor->SetDesiredError(data ? "VUID-VkDescriptorSetAndBindingMappingEXT-source-11249"
: "VUID-VkDescriptorSetAndBindingMappingEXT-source-11250");
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
for (auto source : {VK_DESCRIPTOR_MAPPING_SOURCE_RESOURCE_HEAP_DATA_EXT, VK_DESCRIPTOR_MAPPING_SOURCE_SHADER_RECORD_DATA_EXT,
VK_DESCRIPTOR_MAPPING_SOURCE_PUSH_DATA_EXT}) {
mapping = MakeSetAndBindingMapping(0, 0, 1, VK_SPIRV_RESOURCE_TYPE_COMBINED_SAMPLED_IMAGE_BIT_EXT);
mapping.source = source;
mapping.sourceData.shaderRecordDataOffset = 0;
CreateComputePipelineHelper pipe(*this);
pipe.LateBindPipelineInfo();
pipe.cp_ci_.stage.pNext = &mapping_info;
m_errorMonitor->SetDesiredError("VUID-VkDescriptorSetAndBindingMappingEXT-source-11356");
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
for (auto source : {VK_DESCRIPTOR_MAPPING_SOURCE_SHADER_RECORD_ADDRESS_EXT, VK_DESCRIPTOR_MAPPING_SOURCE_PUSH_ADDRESS_EXT}) {
mapping = MakeSetAndBindingMapping(0, 0, 1, VK_SPIRV_RESOURCE_TYPE_COMBINED_SAMPLED_IMAGE_BIT_EXT);
mapping.source = source;
mapping.sourceData.shaderRecordDataOffset = 0;
CreateComputePipelineHelper pipe(*this);
pipe.LateBindPipelineInfo();
pipe.cp_ci_.stage.pNext = &mapping_info;
m_errorMonitor->SetDesiredError("VUID-VkDescriptorSetAndBindingMappingEXT-source-11357");
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
for (auto source :
{VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_SHADER_RECORD_INDEX_EXT, VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_PUSH_INDEX_EXT,
VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_INDIRECT_INDEX_EXT,
VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_INDIRECT_INDEX_ARRAY_EXT}) {
mapping = MakeSetAndBindingMapping(0, 0, 1, VK_SPIRV_RESOURCE_TYPE_READ_ONLY_IMAGE_BIT_EXT);
mapping.source = source;
switch (source) {
case VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_SHADER_RECORD_INDEX_EXT:
mapping.sourceData.shaderRecordIndex.useCombinedImageSamplerIndex = VK_TRUE;
break;
case VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_PUSH_INDEX_EXT:
mapping.sourceData.pushIndex.useCombinedImageSamplerIndex = VK_TRUE;
break;
case VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_INDIRECT_INDEX_EXT:
mapping.sourceData.indirectIndex.useCombinedImageSamplerIndex = VK_TRUE;
break;
case VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_INDIRECT_INDEX_ARRAY_EXT:
mapping.sourceData.indirectIndexArray.useCombinedImageSamplerIndex = VK_TRUE;
break;
default:
assert(0);
}
CreateComputePipelineHelper pipe(*this);
pipe.LateBindPipelineInfo();
pipe.cp_ci_.stage.pNext = &mapping_info;
m_errorMonitor->SetDesiredError("VUID-VkDescriptorSetAndBindingMappingEXT-source-11358");
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
for (auto source :
{VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT, VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_PUSH_INDEX_EXT,
VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_SHADER_RECORD_INDEX_EXT, VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_INDIRECT_INDEX_EXT,
VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_INDIRECT_INDEX_ARRAY_EXT}) {
mapping = MakeSetAndBindingMapping(0, 0, 2, VK_SPIRV_RESOURCE_TYPE_READ_ONLY_IMAGE_BIT_EXT);
mapping.source = source;
VkSamplerCreateInfo embedded_sampler = vku::InitStructHelper();
switch (source) {
case VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT:
mapping.sourceData.constantOffset.pEmbeddedSampler = &embedded_sampler;
break;
case VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_SHADER_RECORD_INDEX_EXT:
mapping.sourceData.shaderRecordIndex.pEmbeddedSampler = &embedded_sampler;
break;
case VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_PUSH_INDEX_EXT:
mapping.sourceData.pushIndex.pEmbeddedSampler = &embedded_sampler;
break;
case VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_INDIRECT_INDEX_EXT:
mapping.sourceData.indirectIndex.pEmbeddedSampler = &embedded_sampler;
break;
case VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_INDIRECT_INDEX_ARRAY_EXT:
mapping.sourceData.indirectIndexArray.pEmbeddedSampler = &embedded_sampler;
break;
default:
assert(0);
}
CreateComputePipelineHelper pipe(*this);
pipe.LateBindPipelineInfo();
pipe.cp_ci_.stage.pNext = &mapping_info;
m_errorMonitor->SetDesiredError("VUID-VkDescriptorSetAndBindingMappingEXT-source-11389");
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
for (auto source :
{VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT, VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_PUSH_INDEX_EXT,
VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_SHADER_RECORD_INDEX_EXT, VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_INDIRECT_INDEX_EXT,
VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_INDIRECT_INDEX_ARRAY_EXT}) {
mapping = MakeSetAndBindingMapping(0, 0, 1, VK_SPIRV_RESOURCE_TYPE_READ_ONLY_IMAGE_BIT_EXT);
mapping.source = source;
VkDebugUtilsObjectNameInfoEXT object_name_info = vku::InitStructHelper();
object_name_info.objectType = VK_OBJECT_TYPE_DEVICE;
VkSamplerCreateInfo embedded_sampler = vku::InitStructHelper(&object_name_info);
const char* vuid = nullptr;
switch (source) {
case VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT:
mapping.sourceData.constantOffset.pEmbeddedSampler = &embedded_sampler;
vuid = "VUID-VkDescriptorMappingSourceConstantOffsetEXT-pEmbeddedSampler-11415";
break;
case VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_SHADER_RECORD_INDEX_EXT:
mapping.sourceData.shaderRecordIndex.pEmbeddedSampler = &embedded_sampler;
vuid = "VUID-VkDescriptorMappingSourceShaderRecordIndexEXT-pEmbeddedSampler-11405";
break;
case VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_PUSH_INDEX_EXT:
mapping.sourceData.pushIndex.pEmbeddedSampler = &embedded_sampler;
vuid = "VUID-VkDescriptorMappingSourcePushIndexEXT-pEmbeddedSampler-11402";
break;
case VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_INDIRECT_INDEX_EXT:
mapping.sourceData.indirectIndex.pEmbeddedSampler = &embedded_sampler;
vuid = "VUID-VkDescriptorMappingSourceIndirectIndexEXT-pEmbeddedSampler-11403";
break;
case VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_INDIRECT_INDEX_ARRAY_EXT:
mapping.sourceData.indirectIndexArray.pEmbeddedSampler = &embedded_sampler;
vuid = "VUID-VkDescriptorMappingSourceIndirectIndexArrayEXT-pEmbeddedSampler-11404";
break;
default:
assert(0);
}
CreateComputePipelineHelper pipe(*this);
pipe.LateBindPipelineInfo();
pipe.cp_ci_.stage.pNext = &mapping_info;
m_errorMonitor->SetDesiredError(vuid);
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
for (auto source :
{VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT, VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_PUSH_INDEX_EXT,
VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_SHADER_RECORD_INDEX_EXT, VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_INDIRECT_INDEX_EXT,
VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_INDIRECT_INDEX_ARRAY_EXT}) {
mapping = MakeSetAndBindingMapping(0, 0, 1, VK_SPIRV_RESOURCE_TYPE_READ_ONLY_IMAGE_BIT_EXT);
mapping.source = source;
for (const auto borderColor : {VK_BORDER_COLOR_FLOAT_CUSTOM_EXT, VK_BORDER_COLOR_INT_CUSTOM_EXT}) {
VkSamplerCreateInfo embedded_sampler = vku::InitStructHelper();
embedded_sampler.borderColor = borderColor;
const char* vuid = nullptr;
switch (source) {
case VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT:
mapping.sourceData.constantOffset.pEmbeddedSampler = &embedded_sampler;
vuid = "VUID-VkDescriptorMappingSourceConstantOffsetEXT-pEmbeddedSampler-11445";
break;
case VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_SHADER_RECORD_INDEX_EXT:
mapping.sourceData.shaderRecordIndex.pEmbeddedSampler = &embedded_sampler;
vuid = "VUID-VkDescriptorMappingSourceShaderRecordIndexEXT-pEmbeddedSampler-11449";
break;
case VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_PUSH_INDEX_EXT:
mapping.sourceData.pushIndex.pEmbeddedSampler = &embedded_sampler;
vuid = "VUID-VkDescriptorMappingSourcePushIndexEXT-pEmbeddedSampler-11446";
break;
case VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_INDIRECT_INDEX_EXT:
mapping.sourceData.indirectIndex.pEmbeddedSampler = &embedded_sampler;
vuid = "VUID-VkDescriptorMappingSourceIndirectIndexEXT-pEmbeddedSampler-11447";
break;
case VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_INDIRECT_INDEX_ARRAY_EXT:
mapping.sourceData.indirectIndexArray.pEmbeddedSampler = &embedded_sampler;
vuid = "VUID-VkDescriptorMappingSourceIndirectIndexArrayEXT-pEmbeddedSampler-11448";
break;
default:
assert(0);
}
CreateComputePipelineHelper pipe(*this);
pipe.LateBindPipelineInfo();
pipe.cp_ci_.stage.pNext = &mapping_info;
m_errorMonitor->SetDesiredError(vuid);
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
}
}
TEST_F(NegativeDescriptorHeap, DescriptorSetAndBindingMappingShaderObject) {
TEST_DESCRIPTION("Validate VkDescriptorSetAndBindingMappingEXT structure using shader object");
AddRequiredExtensions(VK_EXT_SHADER_OBJECT_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::shaderObject);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
VkDescriptorSetAndBindingMappingEXT mapping = {};
VkShaderDescriptorSetAndBindingMappingInfoEXT mapping_info = vku::InitStructHelper();
mapping_info.mappingCount = 1;
mapping_info.pMappings = &mapping;
for (auto source :
{VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT, VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_PUSH_INDEX_EXT,
VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_SHADER_RECORD_INDEX_EXT, VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_INDIRECT_INDEX_EXT,
VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_INDIRECT_INDEX_ARRAY_EXT}) {
mapping = MakeSetAndBindingMapping(0, 0, 2, VK_SPIRV_RESOURCE_TYPE_READ_ONLY_IMAGE_BIT_EXT);
mapping.source = source;
VkSamplerCreateInfo embedded_sampler = vku::InitStructHelper();
switch (source) {
case VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT:
mapping.sourceData.constantOffset.pEmbeddedSampler = &embedded_sampler;
break;
case VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_SHADER_RECORD_INDEX_EXT:
mapping.sourceData.shaderRecordIndex.pEmbeddedSampler = &embedded_sampler;
break;
case VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_PUSH_INDEX_EXT:
mapping.sourceData.pushIndex.pEmbeddedSampler = &embedded_sampler;
break;
case VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_INDIRECT_INDEX_EXT:
mapping.sourceData.indirectIndex.pEmbeddedSampler = &embedded_sampler;
break;
case VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_INDIRECT_INDEX_ARRAY_EXT:
mapping.sourceData.indirectIndexArray.pEmbeddedSampler = &embedded_sampler;
break;
default:
assert(0);
}
const auto vert_spv = GLSLToSPV(VK_SHADER_STAGE_VERTEX_BIT, kVertexMinimalGlsl);
const VkShaderCreateFlagsEXT flags = VK_SHADER_CREATE_DESCRIPTOR_HEAP_BIT_EXT;
VkShaderCreateInfoEXT vert_ci = ShaderCreateInfoFlag(vert_spv, VK_SHADER_STAGE_VERTEX_BIT, flags);
vert_ci.pNext = &mapping_info;
m_errorMonitor->SetDesiredError("VUID-VkDescriptorSetAndBindingMappingEXT-source-11389");
const vkt::Shader vertShader(*m_device, vert_ci);
m_errorMonitor->VerifyFound();
}
}
TEST_F(NegativeDescriptorHeap, DescriptorMappingSourcePushIndex) {
RETURN_IF_SKIP(InitBasicDescriptorHeap());
VkDescriptorSetAndBindingMappingEXT mapping =
MakeSetAndBindingMapping(0, 0, 1, VK_SPIRV_RESOURCE_TYPE_READ_ONLY_STORAGE_BUFFER_BIT_EXT);
VkShaderDescriptorSetAndBindingMappingInfoEXT mapping_info = vku::InitStructHelper();
mapping_info.mappingCount = 1;
mapping_info.pMappings = &mapping;
{
mapping.source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_PUSH_INDEX_EXT;
mapping.sourceData.pushIndex.pushOffset = 3;
CreateComputePipelineHelper pipe(*this);
pipe.LateBindPipelineInfo();
pipe.cp_ci_.stage.pNext = &mapping_info;
m_errorMonitor->SetDesiredError("VUID-VkDescriptorMappingSourcePushIndexEXT-pushOffset-11258");
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
{
mapping.source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_PUSH_INDEX_EXT;
mapping.sourceData.pushIndex.pushOffset = (uint32_t)heap_props.maxPushDataSize;
CreateComputePipelineHelper pipe(*this);
pipe.LateBindPipelineInfo();
pipe.cp_ci_.stage.pNext = &mapping_info;
m_errorMonitor->SetDesiredError("VUID-VkDescriptorMappingSourcePushIndexEXT-pushOffset-11259");
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
}
TEST_F(NegativeDescriptorHeap, DescriptorMappingSourceIndirectIndex) {
RETURN_IF_SKIP(InitBasicDescriptorHeap());
VkDescriptorSetAndBindingMappingEXT mapping = {};
VkShaderDescriptorSetAndBindingMappingInfoEXT mapping_info = vku::InitStructHelper();
mapping_info.mappingCount = 1;
mapping_info.pMappings = &mapping;
{
mapping = MakeSetAndBindingMapping(0, 0, 1, VK_SPIRV_RESOURCE_TYPE_READ_ONLY_STORAGE_BUFFER_BIT_EXT);
mapping.source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_INDIRECT_INDEX_EXT;
mapping.sourceData.indirectIndex.pushOffset = 4;
CreateComputePipelineHelper pipe(*this);
pipe.LateBindPipelineInfo();
pipe.cp_ci_.stage.pNext = &mapping_info;
m_errorMonitor->SetDesiredError("VUID-VkDescriptorMappingSourceIndirectIndexEXT-pushOffset-11260");
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
{
mapping = MakeSetAndBindingMapping(0, 0, 1, VK_SPIRV_RESOURCE_TYPE_READ_ONLY_STORAGE_BUFFER_BIT_EXT);
mapping.source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_INDIRECT_INDEX_EXT;
mapping.sourceData.indirectIndex.pushOffset = (uint32_t)heap_props.maxPushDataSize;
CreateComputePipelineHelper pipe(*this);
pipe.LateBindPipelineInfo();
pipe.cp_ci_.stage.pNext = &mapping_info;
m_errorMonitor->SetDesiredError("VUID-VkDescriptorMappingSourceIndirectIndexEXT-pushOffset-11261");
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
{
mapping = MakeSetAndBindingMapping(0, 0, 1, VK_SPIRV_RESOURCE_TYPE_READ_ONLY_STORAGE_BUFFER_BIT_EXT);
mapping.source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_INDIRECT_INDEX_EXT;
mapping.sourceData.indirectIndex.addressOffset = 3;
CreateComputePipelineHelper pipe(*this);
pipe.LateBindPipelineInfo();
pipe.cp_ci_.stage.pNext = &mapping_info;
m_errorMonitor->SetDesiredError("VUID-VkDescriptorMappingSourceIndirectIndexEXT-addressOffset-11262");
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
}
TEST_F(NegativeDescriptorHeap, DescriptorMappingSourceHeapData) {
RETURN_IF_SKIP(InitBasicDescriptorHeap());
VkDescriptorSetAndBindingMappingEXT mapping = {};
VkShaderDescriptorSetAndBindingMappingInfoEXT mapping_info = vku::InitStructHelper();
mapping_info.mappingCount = 1;
mapping_info.pMappings = &mapping;
if (m_device->Physical().limits_.minUniformBufferOffsetAlignment > 0) {
mapping = MakeSetAndBindingMapping(0, 0, 1, VK_SPIRV_RESOURCE_TYPE_UNIFORM_BUFFER_BIT_EXT);
mapping.source = VK_DESCRIPTOR_MAPPING_SOURCE_RESOURCE_HEAP_DATA_EXT;
mapping.sourceData.heapData.heapOffset = (uint32_t)m_device->Physical().limits_.minUniformBufferOffsetAlignment + 1;
CreateComputePipelineHelper pipe(*this);
pipe.LateBindPipelineInfo();
pipe.cp_ci_.stage.pNext = &mapping_info;
m_errorMonitor->SetDesiredError("VUID-VkDescriptorMappingSourceHeapDataEXT-heapOffset-11263");
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
{
mapping = MakeSetAndBindingMapping(0, 0, 1, VK_SPIRV_RESOURCE_TYPE_UNIFORM_BUFFER_BIT_EXT);
mapping.source = VK_DESCRIPTOR_MAPPING_SOURCE_RESOURCE_HEAP_DATA_EXT;
mapping.sourceData.heapData.pushOffset = 3u;
CreateComputePipelineHelper pipe(*this);
pipe.LateBindPipelineInfo();
pipe.cp_ci_.stage.pNext = &mapping_info;
m_errorMonitor->SetDesiredError("VUID-VkDescriptorMappingSourceHeapDataEXT-pushOffset-11264");
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
{
mapping = MakeSetAndBindingMapping(0, 0, 1, VK_SPIRV_RESOURCE_TYPE_UNIFORM_BUFFER_BIT_EXT);
mapping.source = VK_DESCRIPTOR_MAPPING_SOURCE_RESOURCE_HEAP_DATA_EXT;
mapping.sourceData.heapData.pushOffset = (uint32_t)heap_props.maxPushDataSize;
CreateComputePipelineHelper pipe(*this);
pipe.LateBindPipelineInfo();
pipe.cp_ci_.stage.pNext = &mapping_info;
m_errorMonitor->SetDesiredError("VUID-VkDescriptorMappingSourceHeapDataEXT-pushOffset-11265");
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
}
TEST_F(NegativeDescriptorHeap, DescriptorMappingSourceIndirectAddress) {
RETURN_IF_SKIP(InitBasicDescriptorHeap());
VkDescriptorSetAndBindingMappingEXT mapping = {};
VkShaderDescriptorSetAndBindingMappingInfoEXT mapping_info = vku::InitStructHelper();
mapping_info.mappingCount = 1;
mapping_info.pMappings = &mapping;
{
mapping = MakeSetAndBindingMapping(0, 0, 1, VK_SPIRV_RESOURCE_TYPE_READ_ONLY_STORAGE_BUFFER_BIT_EXT);
mapping.source = VK_DESCRIPTOR_MAPPING_SOURCE_INDIRECT_ADDRESS_EXT;
mapping.sourceData.indirectAddress.pushOffset = 4;
CreateComputePipelineHelper pipe(*this);
pipe.LateBindPipelineInfo();
pipe.cp_ci_.stage.pNext = &mapping_info;
m_errorMonitor->SetDesiredError("VUID-VkDescriptorMappingSourceIndirectAddressEXT-pushOffset-11266");
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
{
mapping = MakeSetAndBindingMapping(0, 0, 1, VK_SPIRV_RESOURCE_TYPE_READ_ONLY_STORAGE_BUFFER_BIT_EXT);
mapping.source = VK_DESCRIPTOR_MAPPING_SOURCE_INDIRECT_ADDRESS_EXT;
mapping.sourceData.indirectAddress.pushOffset = (uint32_t)heap_props.maxPushDataSize;
CreateComputePipelineHelper pipe(*this);
pipe.LateBindPipelineInfo();
pipe.cp_ci_.stage.pNext = &mapping_info;
m_errorMonitor->SetDesiredError("VUID-VkDescriptorMappingSourceIndirectAddressEXT-pushOffset-11267");
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
{
mapping = MakeSetAndBindingMapping(0, 0, 1, VK_SPIRV_RESOURCE_TYPE_READ_ONLY_STORAGE_BUFFER_BIT_EXT);
mapping.source = VK_DESCRIPTOR_MAPPING_SOURCE_INDIRECT_ADDRESS_EXT;
mapping.sourceData.indirectAddress.addressOffset = 7;
CreateComputePipelineHelper pipe(*this);
pipe.LateBindPipelineInfo();
pipe.cp_ci_.stage.pNext = &mapping_info;
m_errorMonitor->SetDesiredError("VUID-VkDescriptorMappingSourceIndirectAddressEXT-addressOffset-11268");
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
}
TEST_F(NegativeDescriptorHeap, DescriptorMappingSourceShaderRecordIndexAlign) {
RETURN_IF_SKIP(InitBasicDescriptorHeap());
VkDescriptorSetAndBindingMappingEXT mapping =
MakeSetAndBindingMapping(0, 0, 1, VK_SPIRV_RESOURCE_TYPE_READ_ONLY_STORAGE_BUFFER_BIT_EXT);
mapping.source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_SHADER_RECORD_INDEX_EXT;
mapping.sourceData.shaderRecordIndex.shaderRecordOffset = 3;
VkShaderDescriptorSetAndBindingMappingInfoEXT mapping_info = vku::InitStructHelper();
mapping_info.mappingCount = 1;
mapping_info.pMappings = &mapping;
CreateComputePipelineHelper pipe(*this);
pipe.LateBindPipelineInfo();
pipe.cp_ci_.stage.pNext = &mapping_info;
m_errorMonitor->SetDesiredError("VUID-VkDescriptorMappingSourceShaderRecordIndexEXT-shaderRecordOffset-11269");
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDescriptorHeap, DescriptorMappingSourceShaderRecordIndexSize) {
AddRequiredExtensions(VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::rayTracingPipeline);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
VkPhysicalDeviceRayTracingPipelinePropertiesKHR ray_tracing_properties = vku::InitStructHelper();
GetPhysicalDeviceProperties2(ray_tracing_properties);
VkDescriptorSetAndBindingMappingEXT mapping =
MakeSetAndBindingMapping(0, 0, 1, VK_SPIRV_RESOURCE_TYPE_READ_ONLY_STORAGE_BUFFER_BIT_EXT);
mapping.source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_SHADER_RECORD_INDEX_EXT;
mapping.sourceData.shaderRecordIndex.shaderRecordOffset = Align(ray_tracing_properties.maxShaderGroupStride, 4u);
VkShaderDescriptorSetAndBindingMappingInfoEXT mapping_info = vku::InitStructHelper();
mapping_info.mappingCount = 1;
mapping_info.pMappings = &mapping;
CreateComputePipelineHelper pipe(*this);
pipe.LateBindPipelineInfo();
pipe.cp_ci_.stage.pNext = &mapping_info;
m_errorMonitor->SetDesiredError("VUID-VkDescriptorMappingSourceShaderRecordIndexEXT-shaderRecordOffset-11270");
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDescriptorHeap, DescriptorMappingSourceIndirectIndexArray) {
RETURN_IF_SKIP(InitBasicDescriptorHeap());
VkDescriptorSetAndBindingMappingEXT mapping = {};
VkShaderDescriptorSetAndBindingMappingInfoEXT mapping_info = vku::InitStructHelper();
mapping_info.mappingCount = 1;
mapping_info.pMappings = &mapping;
{
mapping = MakeSetAndBindingMapping(0, 0, 1, VK_SPIRV_RESOURCE_TYPE_READ_ONLY_STORAGE_BUFFER_BIT_EXT);
mapping.source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_INDIRECT_INDEX_ARRAY_EXT;
mapping.sourceData.indirectIndexArray.pushOffset = 4;
CreateComputePipelineHelper pipe(*this);
pipe.LateBindPipelineInfo();
pipe.cp_ci_.stage.pNext = &mapping_info;
m_errorMonitor->SetDesiredError("VUID-VkDescriptorMappingSourceIndirectIndexArrayEXT-pushOffset-11359");
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
{
mapping = MakeSetAndBindingMapping(0, 0, 1, VK_SPIRV_RESOURCE_TYPE_READ_ONLY_STORAGE_BUFFER_BIT_EXT);
mapping.source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_INDIRECT_INDEX_ARRAY_EXT;
mapping.sourceData.indirectIndexArray.pushOffset = (uint32_t)heap_props.maxPushDataSize;
CreateComputePipelineHelper pipe(*this);
pipe.LateBindPipelineInfo();
pipe.cp_ci_.stage.pNext = &mapping_info;
m_errorMonitor->SetDesiredError("VUID-VkDescriptorMappingSourceIndirectIndexArrayEXT-pushOffset-11360");
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
{
mapping = MakeSetAndBindingMapping(0, 0, 1, VK_SPIRV_RESOURCE_TYPE_READ_ONLY_STORAGE_BUFFER_BIT_EXT);
mapping.source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_INDIRECT_INDEX_ARRAY_EXT;
mapping.sourceData.indirectIndexArray.addressOffset = 7;
CreateComputePipelineHelper pipe(*this);
pipe.LateBindPipelineInfo();
pipe.cp_ci_.stage.pNext = &mapping_info;
m_errorMonitor->SetDesiredError("VUID-VkDescriptorMappingSourceIndirectIndexArrayEXT-addressOffset-11361");
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
}
TEST_F(NegativeDescriptorHeap, OpaqueCaptureDataCreateInfo) {
RETURN_IF_SKIP(InitBasicDescriptorHeap());
std::vector<uint8_t> data(heap_props.imageCaptureReplayOpaqueDataSize + 1);
VkOpaqueCaptureDataCreateInfoEXT capture_data_create_info = vku::InitStructHelper();
VkHostAddressRangeConstEXT data_range = {data.data(), data.size()};
capture_data_create_info.pData = &data_range;
for (int i = 0; i < 2; i++) {
VkImageCreateInfo image_create_info = vku::InitStructHelper(&capture_data_create_info);
image_create_info.imageType = VK_IMAGE_TYPE_2D;
image_create_info.flags = (i == 0) ? 0u : (VkImageCreateFlags)VK_IMAGE_CREATE_DESCRIPTOR_HEAP_CAPTURE_REPLAY_BIT_EXT;
image_create_info.extent.width = 128;
image_create_info.extent.height = 128;
image_create_info.extent.depth = 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.format = VK_FORMAT_D32_SFLOAT;
image_create_info.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
if (i == 0) {
m_errorMonitor->SetDesiredError("VUID-VkImageCreateInfo-flags-11281");
} else {
m_errorMonitor->SetDesiredError("VUID-VkImageCreateInfo-flags-08104");
}
vkt::Image image(*m_device, image_create_info, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
m_errorMonitor->VerifyFound();
}
}
TEST_F(NegativeDescriptorHeap, OpaqueCaptureDataCreateInfoSize) {
AddRequiredFeature(vkt::Feature::descriptorHeapCaptureReplay);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
std::vector<uint8_t> data(heap_props.imageCaptureReplayOpaqueDataSize + 1);
VkOpaqueCaptureDataCreateInfoEXT capture_data_create_info = vku::InitStructHelper();
VkHostAddressRangeConstEXT data_range = {data.data(), data.size()};
capture_data_create_info.pData = &data_range;
VkImageCreateInfo image_create_info = vku::InitStructHelper(&capture_data_create_info);
image_create_info.imageType = VK_IMAGE_TYPE_2D;
image_create_info.flags = VK_IMAGE_CREATE_DESCRIPTOR_HEAP_CAPTURE_REPLAY_BIT_EXT;
image_create_info.extent.width = 128;
image_create_info.extent.height = 128;
image_create_info.extent.depth = 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.format = VK_FORMAT_D32_SFLOAT;
image_create_info.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
m_errorMonitor->SetDesiredError("VUID-VkImageCreateInfo-pData-11286");
vkt::Image image(*m_device, image_create_info, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDescriptorHeap, GetImageOpaqueCaptureData) {
SetTargetApiVersion(VK_API_VERSION_1_2);
AddRequiredFeature(vkt::Feature::descriptorHeapCaptureReplay);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
AddRequiredFeature(vkt::Feature::bufferDeviceAddressCaptureReplay);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
std::vector<uint8_t> payload(heap_props.imageCaptureReplayOpaqueDataSize + 1);
VkOpaqueCaptureDataCreateInfoEXT capture_data_create_info = vku::InitStructHelper();
VkHostAddressRangeConstEXT range1 = {payload.data(), heap_props.imageCaptureReplayOpaqueDataSize};
capture_data_create_info.pData = &range1;
VkImageCreateInfo image_create_info = vku::InitStructHelper(&capture_data_create_info);
image_create_info.flags = VK_IMAGE_CREATE_DESCRIPTOR_HEAP_CAPTURE_REPLAY_BIT_EXT;
image_create_info.imageType = VK_IMAGE_TYPE_2D;
image_create_info.extent.width = 128;
image_create_info.extent.height = 128;
image_create_info.extent.depth = 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.format = VK_FORMAT_D32_SFLOAT;
image_create_info.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
VkMemoryAllocateFlagsInfo alloc_info = vku::InitStructHelper();
alloc_info.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT | VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT;
vkt::Image image(*m_device, image_create_info, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &alloc_info);
VkHostAddressRangeEXT range2 = {payload.data(), payload.size()};
m_errorMonitor->SetDesiredError("VUID-vkGetImageOpaqueCaptureDataEXT-size-11283");
vk::GetImageOpaqueCaptureDataEXT(device(), 1, &image.handle(), &range2);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDescriptorHeap, GetImageOpaqueCaptureDataMissingFlag) {
SetTargetApiVersion(VK_API_VERSION_1_2);
AddRequiredFeature(vkt::Feature::descriptorHeapCaptureReplay);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
AddRequiredFeature(vkt::Feature::bufferDeviceAddressCaptureReplay);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
VkOpaqueCaptureDataCreateInfoEXT capture_data_create_info = vku::InitStructHelper();
capture_data_create_info.pData = nullptr;
VkImageCreateInfo image_create_info = vku::InitStructHelper(&capture_data_create_info);
image_create_info.imageType = VK_IMAGE_TYPE_2D;
image_create_info.extent.width = 128;
image_create_info.extent.height = 128;
image_create_info.extent.depth = 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.format = VK_FORMAT_D32_SFLOAT;
image_create_info.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
VkMemoryAllocateFlagsInfo alloc_info = vku::InitStructHelper();
alloc_info.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT | VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT;
vkt::Image image(*m_device, image_create_info, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &alloc_info);
std::vector<uint8_t> payload(heap_props.imageCaptureReplayOpaqueDataSize);
VkHostAddressRangeEXT range2 = {payload.data(), payload.size()};
{
m_errorMonitor->SetDesiredError("VUID-vkGetImageOpaqueCaptureDataEXT-pImages-11285");
vk::GetImageOpaqueCaptureDataEXT(device(), 1, &image.handle(), &range2);
m_errorMonitor->VerifyFound();
}
{
range2.size = 0;
m_errorMonitor->SetDesiredError("VUID-VkHostAddressRangeEXT-size-arraylength");
vk::GetImageOpaqueCaptureDataEXT(device(), 1, &image.handle(), &range2);
m_errorMonitor->VerifyFound();
}
}
TEST_F(NegativeDescriptorHeap, RegisterCustomBorderColor) {
SetTargetApiVersion(VK_API_VERSION_1_2);
AddRequiredExtensions(VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::customBorderColors);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
VkPhysicalDeviceCustomBorderColorPropertiesEXT custom_border_color_properties = vku::InitStructHelper();
GetPhysicalDeviceProperties2(custom_border_color_properties);
VkSamplerCustomBorderColorCreateInfoEXT custom_border_color_create_info = vku::InitStructHelper();
uint32_t index = custom_border_color_properties.maxCustomBorderColorSamplers;
m_errorMonitor->SetDesiredError("VUID-vkRegisterCustomBorderColorEXT-requestIndex-11287");
vk::RegisterCustomBorderColorEXT(device(), &custom_border_color_create_info, VK_TRUE, &index);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDescriptorHeap, UnregisterCustomBorderColor) {
SetTargetApiVersion(VK_API_VERSION_1_2);
AddRequiredExtensions(VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::customBorderColors);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
VkPhysicalDeviceCustomBorderColorPropertiesEXT custom_border_color_properties = vku::InitStructHelper();
GetPhysicalDeviceProperties2(custom_border_color_properties);
m_errorMonitor->SetDesiredError("VUID-vkUnregisterCustomBorderColorEXT-index-11288");
vk::UnregisterCustomBorderColorEXT(device(), custom_border_color_properties.maxCustomBorderColorSamplers);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDescriptorHeap, SamplerCreateWithBorder) {
SetTargetApiVersion(VK_API_VERSION_1_2);
AddRequiredExtensions(VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::customBorderColors);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
VkPhysicalDeviceCustomBorderColorPropertiesEXT custom_border_color_properties = vku::InitStructHelper();
GetPhysicalDeviceProperties2(custom_border_color_properties);
VkSamplerCustomBorderColorIndexCreateInfoEXT custom_border_color_index_create_info = vku::InitStructHelper();
custom_border_color_index_create_info.index = custom_border_color_properties.maxCustomBorderColorSamplers;
VkSamplerCreateInfo sampler_ci = SafeSaneSamplerCreateInfo(&custom_border_color_index_create_info);
VkSampler sampler = VK_NULL_HANDLE;
m_errorMonitor->SetDesiredError("VUID-VkSamplerCustomBorderColorIndexCreateInfoEXT-index-11289");
vk::CreateSampler(device(), &sampler_ci, nullptr, &sampler);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDescriptorHeap, DescriptorHeapPipelineCreateFlag) {
RETURN_IF_SKIP(InitBasicDescriptorHeap());
VkPipelineCreateFlags2CreateInfoKHR flags2_ci = vku::InitStructHelper();
flags2_ci.flags = VK_PIPELINE_CREATE_2_DESCRIPTOR_HEAP_BIT_EXT;
{
CreateComputePipelineHelper pipe(*this, &flags2_ci);
pipe.LateBindPipelineInfo();
m_errorMonitor->SetDesiredError("VUID-VkComputePipelineCreateInfo-flags-11311");
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
{
CreatePipelineHelper pipe(*this, &flags2_ci);
m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-flags-11311");
pipe.CreateGraphicsPipeline();
m_errorMonitor->VerifyFound();
}
{
CreateComputePipelineHelper pipe(*this);
pipe.LateBindPipelineInfo();
pipe.cp_ci_.layout = VK_NULL_HANDLE;
m_errorMonitor->SetDesiredError("VUID-VkComputePipelineCreateInfo-None-11367");
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
}
TEST_F(NegativeDescriptorHeap, PipelineShaderStageCreateInfoNotEnabled) {
TEST_DESCRIPTION("Validate VkPipelineShaderStageCreateInfo mappingCount to be zero when descriptorHeap is not enabled");
SetTargetApiVersion(VK_API_VERSION_1_2);
AddRequiredExtensions(VK_EXT_DESCRIPTOR_HEAP_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
VkDescriptorSetAndBindingMappingEXT mapping =
MakeSetAndBindingMapping(0, 0, 1, VK_SPIRV_RESOURCE_TYPE_READ_ONLY_STORAGE_BUFFER_BIT_EXT);
mapping.source = VK_DESCRIPTOR_MAPPING_SOURCE_INDIRECT_ADDRESS_EXT;
VkShaderDescriptorSetAndBindingMappingInfoEXT mapping_info = vku::InitStructHelper();
mapping_info.mappingCount = 1;
mapping_info.pMappings = &mapping;
CreateComputePipelineHelper pipe(*this);
pipe.LateBindPipelineInfo();
pipe.cp_ci_.stage.pNext = &mapping_info;
m_errorMonitor->SetDesiredError("VUID-VkPipelineShaderStageCreateInfo-descriptorHeap-11314");
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDescriptorHeap, IndirectExecutionSetShaderInfoInitialShaderFlagSame) {
TEST_DESCRIPTION(
"Validate that all VkIndirectExecutionSetShaderInfoEXT.pInitialShaders are created with same descriptor heap "
"flag state");
AddRequiredExtensions(VK_EXT_DEVICE_GENERATED_COMMANDS_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_SHADER_OBJECT_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::deviceGeneratedCommands);
AddRequiredFeature(vkt::Feature::shaderObject);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
VkPhysicalDeviceDeviceGeneratedCommandsPropertiesEXT dgc_props = vku::InitStructHelper();
GetPhysicalDeviceProperties2(dgc_props);
if ((dgc_props.supportedIndirectCommandsShaderStagesShaderBinding & VK_SHADER_STAGE_VERTEX_BIT) == 0) {
GTEST_SKIP() << "VK_SHADER_STAGE_VERTEX_BIT is not supported.";
}
if ((dgc_props.supportedIndirectCommandsShaderStagesShaderBinding & VK_SHADER_STAGE_FRAGMENT_BIT) == 0) {
GTEST_SKIP() << "VK_SHADER_STAGE_FRAGMENT_BIT is not supported.";
}
for (int i = 0; i < 2; i++) {
const VkShaderCreateFlagsEXT flags1 = VK_SHADER_CREATE_INDIRECT_BINDABLE_BIT_EXT | VK_SHADER_CREATE_DESCRIPTOR_HEAP_BIT_EXT;
const VkShaderCreateFlagsEXT flags2 = VK_SHADER_CREATE_INDIRECT_BINDABLE_BIT_EXT;
const auto vert_spv = GLSLToSPV(VK_SHADER_STAGE_VERTEX_BIT, kVertexMinimalGlsl);
VkShaderCreateInfoEXT vert_ci = ShaderCreateInfoFlag(vert_spv, VK_SHADER_STAGE_VERTEX_BIT, (i == 0) ? flags1 : flags2);
const vkt::Shader vertShader(*m_device, vert_ci);
const auto frag_spv = GLSLToSPV(VK_SHADER_STAGE_FRAGMENT_BIT, kFragmentMinimalGlsl);
VkShaderCreateInfoEXT frag_ci = ShaderCreateInfoFlag(frag_spv, VK_SHADER_STAGE_FRAGMENT_BIT, (i == 0) ? flags2 : flags1);
const vkt::Shader fragShader(*m_device, frag_ci);
VkIndirectExecutionSetEXT indirectExecutionSet = VK_NULL_HANDLE;
VkShaderEXT shaders[2] = {vertShader, fragShader};
VkIndirectExecutionSetShaderInfoEXT shader_info = vku::InitStructHelper();
shader_info.maxShaderCount = 2;
shader_info.shaderCount = 2;
shader_info.pInitialShaders = shaders;
shader_info.pSetLayoutInfos = nullptr;
VkIndirectExecutionSetCreateInfoEXT indirect_execution_set_create_info = vku::InitStructHelper();
indirect_execution_set_create_info.type = VK_INDIRECT_EXECUTION_SET_INFO_TYPE_SHADER_OBJECTS_EXT;
indirect_execution_set_create_info.info.pShaderInfo = &shader_info;
if (i == 0) {
m_errorMonitor->SetDesiredError("VUID-VkIndirectExecutionSetShaderInfoEXT-pInitialShaders-11321");
} else {
m_errorMonitor->SetDesiredError("VUID-VkIndirectExecutionSetShaderInfoEXT-pInitialShaders-11322");
}
vk::CreateIndirectExecutionSetEXT(device(), &indirect_execution_set_create_info, nullptr, &indirectExecutionSet);
m_errorMonitor->VerifyFound();
}
}
TEST_F(NegativeDescriptorHeap, IndirectExecutionSetShaderInfoSetLayoutNull) {
TEST_DESCRIPTION("Validate that all VkIndirectExecutionSetShaderInfoEXT.pSetLayoutInfos is null");
AddRequiredExtensions(VK_EXT_DEVICE_GENERATED_COMMANDS_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_SHADER_OBJECT_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::deviceGeneratedCommands);
AddRequiredFeature(vkt::Feature::shaderObject);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
VkPhysicalDeviceDeviceGeneratedCommandsPropertiesEXT dgc_props = vku::InitStructHelper();
GetPhysicalDeviceProperties2(dgc_props);
if ((dgc_props.supportedIndirectCommandsShaderStagesShaderBinding & VK_SHADER_STAGE_VERTEX_BIT) == 0) {
GTEST_SKIP() << "VK_SHADER_STAGE_VERTEX_BIT is not supported.";
}
const auto vert_spv = GLSLToSPV(VK_SHADER_STAGE_VERTEX_BIT, kVertexMinimalGlsl);
const VkShaderCreateFlagsEXT flags = VK_SHADER_CREATE_INDIRECT_BINDABLE_BIT_EXT | VK_SHADER_CREATE_DESCRIPTOR_HEAP_BIT_EXT;
VkShaderCreateInfoEXT vert_ci = ShaderCreateInfoFlag(vert_spv, VK_SHADER_STAGE_VERTEX_BIT, flags);
const vkt::Shader vertShader(*m_device, vert_ci);
VkIndirectExecutionSetEXT indirectExecutionSet = VK_NULL_HANDLE;
VkDescriptorSetLayout set_layout = VK_NULL_HANDLE;
VkIndirectExecutionSetShaderLayoutInfoEXT set_layout_info = vku::InitStructHelper();
set_layout_info.setLayoutCount = 1;
set_layout_info.pSetLayouts = &set_layout;
VkIndirectExecutionSetShaderInfoEXT shader_info = vku::InitStructHelper();
shader_info.maxShaderCount = 1;
shader_info.shaderCount = 1;
shader_info.pInitialShaders = &vertShader.handle();
shader_info.pSetLayoutInfos = &set_layout_info;
VkIndirectExecutionSetCreateInfoEXT indirect_execution_set_create_info = vku::InitStructHelper();
indirect_execution_set_create_info.type = VK_INDIRECT_EXECUTION_SET_INFO_TYPE_SHADER_OBJECTS_EXT;
indirect_execution_set_create_info.info.pShaderInfo = &shader_info;
m_errorMonitor->SetDesiredError("VUID-VkIndirectExecutionSetShaderInfoEXT-pInitialShaders-11323");
vk::CreateIndirectExecutionSetEXT(device(), &indirect_execution_set_create_info, nullptr, &indirectExecutionSet);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDescriptorHeap, ShaderCreateInfoPushConstant) {
AddRequiredExtensions(VK_EXT_SHADER_OBJECT_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::shaderObject);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
{
const auto vert_spv = GLSLToSPV(VK_SHADER_STAGE_VERTEX_BIT, kVertexMinimalGlsl);
const VkShaderCreateFlagsEXT flags = VK_SHADER_CREATE_DESCRIPTOR_HEAP_BIT_EXT;
VkShaderCreateInfoEXT vert_ci = ShaderCreateInfoFlag(vert_spv, VK_SHADER_STAGE_VERTEX_BIT, flags);
vert_ci.pushConstantRangeCount = 1;
vert_ci.pPushConstantRanges = nullptr;
m_errorMonitor->SetDesiredError("VUID-VkShaderCreateInfoEXT-flags-11370");
const vkt::Shader vertShader(*m_device, vert_ci);
m_errorMonitor->VerifyFound();
}
{
const auto vert_spv = GLSLToSPV(VK_SHADER_STAGE_VERTEX_BIT, kVertexMinimalGlsl);
const VkShaderCreateFlagsEXT flags = VK_SHADER_CREATE_DESCRIPTOR_HEAP_BIT_EXT;
VkShaderCreateInfoEXT vert_ci = ShaderCreateInfoFlag(vert_spv, VK_SHADER_STAGE_VERTEX_BIT, flags);
VkPushConstantRange push_constant_range = {};
vert_ci.pushConstantRangeCount = 0;
vert_ci.pPushConstantRanges = &push_constant_range;
m_errorMonitor->SetDesiredError("VUID-VkShaderCreateInfoEXT-flags-11371");
const vkt::Shader vertShader(*m_device, vert_ci);
m_errorMonitor->VerifyFound();
}
}
TEST_F(NegativeDescriptorHeap, DescriptorType) {
RETURN_IF_SKIP(InitBasicDescriptorHeap());
m_errorMonitor->SetDesiredError("VUID-vkGetPhysicalDeviceDescriptorSizeEXT-type-11362");
vk::GetPhysicalDeviceDescriptorSizeEXT(Gpu(), VK_DESCRIPTOR_TYPE_MAX_ENUM);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDescriptorHeap, BindHeapInfoBufferHeapUsage) {
TEST_DESCRIPTION("Validate VkBindHeapInfoEXT uses buffer address from buffer with heap usage and memory usage for the command");
AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
{
const VkDeviceSize bdsize = heap_props.samplerDescriptorSize + heap_props.minSamplerHeapReservedRange;
vkt::Buffer buffer(*m_device, bdsize, 0, vkt::device_address);
VkBindHeapInfoEXT bind_info = vku::InitStructHelper();
bind_info.heapRange = buffer.AddressRange();
bind_info.reservedRangeSize = heap_props.minSamplerHeapReservedRange;
m_errorMonitor->SetDesiredError("VUID-vkCmdBindSamplerHeapEXT-heapRange-11230");
m_command_buffer.Begin();
vk::CmdBindSamplerHeapEXT(m_command_buffer, &bind_info);
m_command_buffer.End();
m_errorMonitor->VerifyFound();
}
{
const VkDeviceSize bdsize = heap_props.bufferDescriptorSize + heap_props.minResourceHeapReservedRange;
vkt::Buffer buffer(*m_device, bdsize, 0, vkt::device_address);
VkBindHeapInfoEXT bind_info = vku::InitStructHelper();
bind_info.heapRange = buffer.AddressRange();
bind_info.reservedRangeSize = heap_props.minResourceHeapReservedRange;
m_errorMonitor->SetDesiredError("VUID-vkCmdBindResourceHeapEXT-heapRange-11237");
m_command_buffer.Begin();
vk::CmdBindResourceHeapEXT(m_command_buffer, &bind_info);
m_command_buffer.End();
m_errorMonitor->VerifyFound();
}
// Validate memory overflow corruption and binding
{
const VkDeviceSize heap_size = heap_props.samplerDescriptorSize + heap_props.minSamplerHeapReservedRange;
vkt::Buffer heap(*m_device, heap_size, VK_BUFFER_USAGE_DESCRIPTOR_HEAP_BIT_EXT, vkt::device_address);
VkBindHeapInfoEXT bind_info = vku::InitStructHelper();
bind_info.heapRange = {heap.Address(), heap_size + 1};
bind_info.reservedRangeSize = heap_props.minSamplerHeapReservedRange;
m_errorMonitor->SetDesiredError("VUID-VkDeviceAddressRangeKHR-address-11365");
m_command_buffer.Begin();
vk::CmdBindSamplerHeapEXT(m_command_buffer, &bind_info);
m_command_buffer.End();
m_errorMonitor->VerifyFound();
}
{
const VkDeviceSize heap_size = heap_props.samplerDescriptorSize + heap_props.minSamplerHeapReservedRange;
vkt::Buffer heap(*m_device, heap_size, VK_BUFFER_USAGE_DESCRIPTOR_HEAP_BIT_EXT, vkt::device_address);
VkBindHeapInfoEXT bind_info = vku::InitStructHelper();
bind_info.heapRange = heap.AddressRange();
bind_info.reservedRangeSize = heap_props.minSamplerHeapReservedRange;
heap.Memory().Destroy();
m_errorMonitor->SetDesiredError("VUID-VkDeviceAddress-None-10894");
m_command_buffer.Begin();
vk::CmdBindSamplerHeapEXT(m_command_buffer, &bind_info);
m_command_buffer.End();
m_errorMonitor->VerifyFound();
}
{
const VkDeviceSize heap_size = heap_props.bufferDescriptorSize + heap_props.minResourceHeapReservedRange;
vkt::Buffer heap(*m_device, heap_size, VK_BUFFER_USAGE_DESCRIPTOR_HEAP_BIT_EXT, vkt::device_address);
VkBindHeapInfoEXT bind_info = vku::InitStructHelper();
bind_info.heapRange = {heap.Address(), heap_size + 1};
bind_info.reservedRangeSize = heap_props.minResourceHeapReservedRange;
m_errorMonitor->SetDesiredError("VUID-VkDeviceAddressRangeKHR-address-11365");
m_command_buffer.Begin();
vk::CmdBindResourceHeapEXT(m_command_buffer, &bind_info);
m_command_buffer.End();
m_errorMonitor->VerifyFound();
}
{
const VkDeviceSize heap_size = heap_props.bufferDescriptorSize + heap_props.minResourceHeapReservedRange;
vkt::Buffer heap(*m_device, heap_size, VK_BUFFER_USAGE_DESCRIPTOR_HEAP_BIT_EXT, vkt::device_address);
VkBindHeapInfoEXT bind_info = vku::InitStructHelper();
bind_info.heapRange = heap.AddressRange();
bind_info.reservedRangeSize = heap_props.minResourceHeapReservedRange;
heap.Memory().Destroy();
m_errorMonitor->SetDesiredError("VUID-VkDeviceAddress-None-10894");
m_command_buffer.Begin();
vk::CmdBindResourceHeapEXT(m_command_buffer, &bind_info);
m_command_buffer.End();
m_errorMonitor->VerifyFound();
}
}
TEST_F(NegativeDescriptorHeap, BindOverlappingRangesSampler) {
AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
// std::max allows the test to run when minSamplerHeapReservedRange is zero or smaller than samplerDescriptorSize
const VkDeviceSize heap_size = 4 * std::max(heap_props.samplerDescriptorSize, heap_props.minSamplerHeapReservedRange);
vkt::Buffer heap(*m_device, heap_size, VK_BUFFER_USAGE_DESCRIPTOR_HEAP_BIT_EXT, vkt::device_address);
vkt::CommandPool command_pool(*m_device, m_device->graphics_queue_node_index_);
vkt::CommandBuffer cmd_buffer1(*m_device, command_pool);
vkt::CommandBuffer cmd_buffer2(*m_device, command_pool);
vkt::CommandBuffer cmd_buffer3(*m_device, command_pool);
cmd_buffer1.Begin();
cmd_buffer2.Begin();
cmd_buffer3.Begin();
VkBindHeapInfoEXT bind_info1 = vku::InitStructHelper();
bind_info1.heapRange = heap.AddressRange();
bind_info1.reservedRangeOffset = 0;
bind_info1.reservedRangeSize = heap_size / 2;
VkBindHeapInfoEXT bind_info2 = vku::InitStructHelper();
bind_info2.heapRange = heap.AddressRange();
bind_info2.reservedRangeOffset = heap_size / 4;
bind_info2.reservedRangeSize = heap_size / 2;
vk::CmdBindSamplerHeapEXT(cmd_buffer1, &bind_info1);
// Bind overlapping reserved areas: not allowed
m_errorMonitor->SetDesiredError("VUID-vkCmdBindSamplerHeapEXT-pBindInfo-11228");
vk::CmdBindSamplerHeapEXT(cmd_buffer2, &bind_info2);
m_errorMonitor->VerifyFound();
// Bind same reserved area to different buffer: allowed
vk::CmdBindSamplerHeapEXT(cmd_buffer3, &bind_info1);
// Rebind same reserved area to same buffer: allowed
vk::CmdBindSamplerHeapEXT(cmd_buffer1, &bind_info1);
// Rebind same reserved area to different type buffer: not allowed
m_errorMonitor->SetDesiredError("VUID-vkCmdBindResourceHeapEXT-pBindInfo-11236");
if (bind_info1.reservedRangeOffset < heap_props.minResourceHeapReservedRange) {
// We use allow here, otherwise validation layers return before getting to 11236
m_errorMonitor->SetAllowedFailureMsg("VUID-vkCmdBindResourceHeapEXT-pBindInfo-11233");
}
vk::CmdBindResourceHeapEXT(cmd_buffer1, &bind_info1);
m_errorMonitor->VerifyFound();
cmd_buffer3.End();
cmd_buffer2.End();
cmd_buffer1.End();
}
TEST_F(NegativeDescriptorHeap, BindOverlappingRangesResource) {
AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
// std::max allows the test to run when minResourceHeapReservedRange is zero or smaller than bufferDescriptorSize
const VkDeviceSize heap_size = 4 * std::max(heap_props.imageDescriptorSize,
std::max(heap_props.bufferDescriptorSize, heap_props.minResourceHeapReservedRange));
vkt::Buffer heap(*m_device, heap_size, VK_BUFFER_USAGE_DESCRIPTOR_HEAP_BIT_EXT, vkt::device_address);
vkt::CommandPool command_pool(*m_device, m_device->graphics_queue_node_index_);
vkt::CommandBuffer cmd_buffer1(*m_device, command_pool);
vkt::CommandBuffer cmd_buffer2(*m_device, command_pool);
vkt::CommandBuffer cmd_buffer3(*m_device, command_pool);
cmd_buffer1.Begin();
cmd_buffer2.Begin();
cmd_buffer3.Begin();
VkBindHeapInfoEXT bind_info1 = vku::InitStructHelper();
bind_info1.heapRange = heap.AddressRange();
bind_info1.reservedRangeOffset = 0;
bind_info1.reservedRangeSize = heap_size / 2;
VkBindHeapInfoEXT bind_info2 = vku::InitStructHelper();
bind_info2.heapRange = heap.AddressRange();
bind_info2.reservedRangeOffset = heap_size / 4;
bind_info2.reservedRangeSize = heap_size / 2;
vk::CmdBindResourceHeapEXT(cmd_buffer1, &bind_info1);
// Bind overlapping reserved areas: not allowed
m_errorMonitor->SetDesiredError("VUID-vkCmdBindResourceHeapEXT-pBindInfo-11236");
vk::CmdBindResourceHeapEXT(cmd_buffer2, &bind_info2);
m_errorMonitor->VerifyFound();
// Bind same reserved area to different buffer: allowed
vk::CmdBindResourceHeapEXT(cmd_buffer3, &bind_info1);
// Rebind same reserved area to same buffer: allowed
vk::CmdBindResourceHeapEXT(cmd_buffer1, &bind_info1);
// Rebind same reserved area to different type buffer: not allowed
if (bind_info1.heapRange.size > heap_props.maxSamplerHeapSize) {
// We use allow here, otherwise validation layers return before getting to 11236
m_errorMonitor->SetAllowedFailureMsg("VUID-vkCmdBindSamplerHeapEXT-pBindInfo-11225");
}
if (bind_info1.reservedRangeSize < heap_props.minSamplerHeapReservedRange) {
m_errorMonitor->SetDesiredError("VUID-vkCmdBindSamplerHeapEXT-pBindInfo-11224");
} else {
m_errorMonitor->SetDesiredError("VUID-vkCmdBindSamplerHeapEXT-pBindInfo-11228");
}
vk::CmdBindSamplerHeapEXT(cmd_buffer1, &bind_info1);
m_errorMonitor->VerifyFound();
cmd_buffer3.End();
cmd_buffer2.End();
cmd_buffer1.End();
}
TEST_F(NegativeDescriptorHeap, WriteResourceDescriptorsMemoryTests) {
AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT align_props = vku::InitStructHelper();
GetPhysicalDeviceProperties2(align_props);
const VkFormat format = VK_FORMAT_R8G8B8A8_UNORM;
const VkDeviceSize buffer_size = std::max(heap_props.imageDescriptorSize, align_props.uniformTexelBufferOffsetAlignmentBytes);
auto data = std::vector<uint8_t>(static_cast<size_t>(buffer_size));
VkHostAddressRangeEXT descriptors = {&data[0], data.size()};
{
vkt::Buffer buffer(*m_device, buffer_size, VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, vkt::device_address);
VkTexelBufferDescriptorInfoEXT texel_buffer_info = vku::InitStructHelper();
texel_buffer_info.addressRange = {buffer.Address(), 2 * buffer_size};
texel_buffer_info.format = format;
VkResourceDescriptorInfoEXT desc_info = vku::InitStructHelper();
desc_info.type = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
desc_info.data.pTexelBuffer = &texel_buffer_info;
m_errorMonitor->SetDesiredError("VUID-VkDeviceAddressRangeKHR-address-11365");
vk::WriteResourceDescriptorsEXT(device(), 1u, &desc_info, &descriptors);
m_errorMonitor->VerifyFound();
}
{
vkt::Buffer buffer(*m_device, buffer_size, VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, vkt::device_address);
VkTexelBufferDescriptorInfoEXT texel_buffer_info = vku::InitStructHelper();
texel_buffer_info.addressRange = {buffer.Address(), buffer_size};
texel_buffer_info.format = format;
VkResourceDescriptorInfoEXT desc_info = vku::InitStructHelper();
desc_info.type = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
desc_info.data.pTexelBuffer = &texel_buffer_info;
buffer.Memory().Destroy();
m_errorMonitor->SetDesiredError("VUID-VkDeviceAddress-None-10894");
vk::WriteResourceDescriptorsEXT(device(), 1u, &desc_info, &descriptors);
m_errorMonitor->VerifyFound();
}
}
TEST_F(NegativeDescriptorHeap, WriteResourceDescriptorsMemoryTestsAS) {
AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
AddRequiredExtensions(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::accelerationStructure);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT align_props = vku::InitStructHelper();
GetPhysicalDeviceProperties2(align_props);
const VkDeviceSize bdsize = std::max(heap_props.bufferDescriptorSize, align_props.uniformTexelBufferOffsetAlignmentBytes);
const uint32_t as_size = 4096;
{
vkt::Buffer as_buffer(*m_device, as_size, VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR, vkt::device_address);
VkAccelerationStructureKHR as = VK_NULL_HANDLE;
VkAccelerationStructureCreateInfoKHR asci = vku::InitStructHelper();
asci.buffer = as_buffer;
vk::CreateAccelerationStructureKHR(device(), &asci, nullptr, &as);
VkDeviceAddressRangeEXT address_range = {as_buffer.Address(), as_size + 256};
VkResourceDescriptorInfoEXT desc_info = vku::InitStructHelper();
desc_info.type = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR;
desc_info.data.pAddressRange = &address_range;
auto data = std::vector<uint8_t>(static_cast<size_t>(bdsize));
VkHostAddressRangeEXT descriptors = {&data[0], data.size()};
m_errorMonitor->SetDesiredError("VUID-VkResourceDescriptorInfoEXT-type-11483");
vk::WriteResourceDescriptorsEXT(device(), 1u, &desc_info, &descriptors);
m_errorMonitor->VerifyFound();
vk::DestroyAccelerationStructureKHR(device(), as, nullptr);
}
{
vkt::Buffer as_buffer(*m_device, as_size, VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR, vkt::device_address);
VkAccelerationStructureKHR as = VK_NULL_HANDLE;
VkAccelerationStructureCreateInfoKHR asci = vku::InitStructHelper();
asci.buffer = as_buffer;
vk::CreateAccelerationStructureKHR(device(), &asci, nullptr, &as);
VkDeviceAddressRangeEXT address_range = {as_buffer.Address(), as_size};
VkResourceDescriptorInfoEXT desc_info = vku::InitStructHelper();
desc_info.type = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR;
desc_info.data.pAddressRange = &address_range;
auto data = std::vector<uint8_t>(static_cast<size_t>(bdsize));
VkHostAddressRangeEXT descriptors = {&data[0], data.size()};
as_buffer.Memory().Destroy();
m_errorMonitor->SetDesiredError("VUID-VkResourceDescriptorInfoEXT-type-11483");
vk::WriteResourceDescriptorsEXT(device(), 1u, &desc_info, &descriptors);
m_errorMonitor->VerifyFound();
vk::DestroyAccelerationStructureKHR(device(), as, nullptr);
}
}
TEST_F(NegativeDescriptorHeap, OpTypeImage) {
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
RETURN_IF_SKIP(CheckSlangSupport());
if (heap_props.imageDescriptorAlignment < 2) {
GTEST_SKIP() << "Cannot be unaligned with imageDescriptorAlignment less than 2";
}
VkDescriptorSetAndBindingMappingEXT mappings = MakeSetAndBindingMapping(0, 0);
mappings.source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT;
mappings.sourceData.constantOffset.heapOffset = 1;
mappings.sourceData.constantOffset.heapArrayStride = 0;
VkShaderDescriptorSetAndBindingMappingInfoEXT mapping_info = vku::InitStructHelper();
mapping_info.mappingCount = 1;
mapping_info.pMappings = &mappings;
char const* cs_source = R"glsl(
#version 450
layout(local_size_x = 1) in;
layout(set = 0, binding = 0, rgba8) uniform image2D color_out;
void main() {
vec4 color = gl_GlobalInvocationID.xxyy;
ivec2 pixelCoords = ivec2(gl_GlobalInvocationID.xy);
imageStore(color_out, pixelCoords, color);
}
)glsl";
const char* slang_shader = R"slang(
[[vk::binding(0, 0)]]
RWTexture2D<float4> color_out;
[numthreads(1, 1, 1)]
void main(uint3 dispatchThreadID : SV_DispatchThreadID) {
float4 color = float4(dispatchThreadID.xxyy);
int2 pixelCoords = int2(dispatchThreadID.xy);
color_out[pixelCoords] = color;
}
)slang";
VkShaderObj cs_modules[2];
cs_modules[0] = VkShaderObj(*m_device, cs_source, VK_SHADER_STAGE_COMPUTE_BIT);
cs_modules[1] = VkShaderObj(*m_device, slang_shader, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_0, SPV_SOURCE_SLANG);
VkPipelineCreateFlags2CreateInfo pipeline_create_flags_2_create_info = vku::InitStructHelper();
pipeline_create_flags_2_create_info.flags = VK_PIPELINE_CREATE_2_DESCRIPTOR_HEAP_BIT_EXT;
for (int i = 0; i < 4; i++) {
CreateComputePipelineHelper pipe(*this, &pipeline_create_flags_2_create_info);
pipe.cp_ci_.layout = VK_NULL_HANDLE;
if (i < 2) {
pipe.cp_ci_.stage = cs_modules[0].GetStageCreateInfo();
} else {
pipe.cp_ci_.stage = cs_modules[1].GetStageCreateInfo();
}
pipe.cp_ci_.stage.pNext = &mapping_info;
mappings.sourceData.constantOffset.heapOffset = (i % 2 == 0) ? 1 : 0;
mappings.sourceData.constantOffset.heapArrayStride = (i % 2 == 0) ? 0 : 1;
m_errorMonitor->SetDesiredError("VUID-VkDescriptorSetAndBindingMappingEXT-source-11251");
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
}
TEST_F(NegativeDescriptorHeap, MappedPushIsBlockUniform) {
TEST_DESCRIPTION("Validate that mapped push data is backed by block uniform");
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
RETURN_IF_SKIP(CheckSlangSupport());
VkDescriptorSetAndBindingMappingEXT mappings = MakeSetAndBindingMapping(0, 0);
mappings.source = VK_DESCRIPTOR_MAPPING_SOURCE_PUSH_DATA_EXT;
VkShaderDescriptorSetAndBindingMappingInfoEXT mapping_info = vku::InitStructHelper();
mapping_info.mappingCount = 1;
mapping_info.pMappings = &mappings;
VkPipelineCreateFlags2CreateInfo pipeline_create_flags_2_create_info = vku::InitStructHelper();
pipeline_create_flags_2_create_info.flags = VK_PIPELINE_CREATE_2_DESCRIPTOR_HEAP_BIT_EXT;
const char* cs_source = R"glsl(
#version 450
layout(local_size_x = 1) in;
layout(set = 0, binding = 0) buffer Output { uint a[2]; } x[];
void main() {
x[0].a[0] = 0;
}
)glsl";
const char* slang_shader = R"slang(
struct Output {
uint a[2];
};
[[vk::binding(0, 0)]]
RWStructuredBuffer<Output> x;
[numthreads(1, 1, 1)]
void main(uint3 dispatchThreadID : SV_DispatchThreadID) {
x[0].a[dispatchThreadID.x] = 0;
}
)slang";
VkShaderObj cs_modules[2];
cs_modules[0] = VkShaderObj(*m_device, cs_source, VK_SHADER_STAGE_COMPUTE_BIT);
cs_modules[1] = VkShaderObj(*m_device, slang_shader, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_0, SPV_SOURCE_SLANG);
CreateComputePipelineHelper pipe(*this, &pipeline_create_flags_2_create_info);
pipe.cp_ci_.layout = VK_NULL_HANDLE;
pipe.cp_ci_.stage = cs_modules[0].GetStageCreateInfo(&mapping_info);
m_errorMonitor->SetDesiredError("VUID-VkPipelineShaderStageCreateInfo-pNext-11315");
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
pipe.cp_ci_.stage = cs_modules[1].GetStageCreateInfo(&mapping_info);
m_errorMonitor->SetDesiredError("VUID-VkPipelineShaderStageCreateInfo-pNext-11315");
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDescriptorHeap, MappedStructLessThanMaxPushDataSize) {
TEST_DESCRIPTION("Validate that mapped structure is less than maxPushDataSize");
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
RETURN_IF_SKIP(CheckSlangSupport());
VkDescriptorSetAndBindingMappingEXT mappings[2];
mappings[0] = MakeSetAndBindingMapping(0, 0);
mappings[0].source = VK_DESCRIPTOR_MAPPING_SOURCE_PUSH_DATA_EXT;
mappings[0].sourceData.pushDataOffset = 0;
mappings[1] = MakeSetAndBindingMapping(0, 1);
mappings[1].source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT;
VkShaderDescriptorSetAndBindingMappingInfoEXT mapping_info = vku::InitStructHelper();
mapping_info.mappingCount = 2;
mapping_info.pMappings = mappings;
VkPipelineCreateFlags2CreateInfo pipeline_create_flags_2_create_info = vku::InitStructHelper();
pipeline_create_flags_2_create_info.flags = VK_PIPELINE_CREATE_2_DESCRIPTOR_HEAP_BIT_EXT;
std::stringstream cs_source;
cs_source << R"glsl(
#version 450
layout(local_size_x = 1) in;
layout(set = 0, binding = 0) uniform Input { uint a[)glsl";
cs_source << heap_props.maxPushDataSize;
cs_source << R"glsl(]; } x[];
layout(set = 0, binding = 1) buffer Output { uint b[2]; } y[];
void main() {
y[0].b[gl_GlobalInvocationID.x] = x[0].a[0];
}
)glsl";
std::stringstream slang_shader;
slang_shader << R"slang(
struct Input {
uint a[)slang";
slang_shader << heap_props.maxPushDataSize;
slang_shader << R"slang(];
};
[[vk::binding(0, 0)]]
StructuredBuffer<Input> x;
struct Output {
uint b[2];
};
[[vk::binding(1, 0)]]
RWStructuredBuffer<Output> y;
[numthreads(1, 1, 1)]
void main(uint3 dispatchThreadID : SV_DispatchThreadID) {
y[0].b[dispatchThreadID.x] = x[0].a[dispatchThreadID.x];
}
)slang";
VkShaderObj cs_modules[2];
cs_modules[0] = VkShaderObj(*m_device, cs_source.str().c_str(), VK_SHADER_STAGE_COMPUTE_BIT);
cs_modules[1] =
VkShaderObj(*m_device, slang_shader.str().c_str(), VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_0, SPV_SOURCE_SLANG);
CreateComputePipelineHelper pipe(*this, &pipeline_create_flags_2_create_info);
pipe.cp_ci_.layout = VK_NULL_HANDLE;
pipe.cp_ci_.stage = cs_modules[0].GetStageCreateInfo();
pipe.cp_ci_.stage.pNext = &mapping_info;
m_errorMonitor->SetDesiredError("VUID-VkPipelineShaderStageCreateInfo-pNext-11316");
m_errorMonitor->SetDesiredError("VUID-VkPipelineShaderStageCreateInfo-pNext-11315");
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
pipe.cp_ci_.stage = cs_modules[1].GetStageCreateInfo(&mapping_info);
m_errorMonitor->SetDesiredError("VUID-VkPipelineShaderStageCreateInfo-pNext-11315");
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDescriptorHeap, OpTypeStruct) {
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
RETURN_IF_SKIP(CheckSlangSupport());
if (heap_props.bufferDescriptorAlignment < 2) {
GTEST_SKIP() << "Cannot be unaligned with bufferDescriptorAlignment less than 2";
}
VkDescriptorSetAndBindingMappingEXT mappings = MakeSetAndBindingMapping(0, 0);
mappings.source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT;
mappings.sourceData.constantOffset.heapOffset = 1;
mappings.sourceData.constantOffset.heapArrayStride = 0;
VkShaderDescriptorSetAndBindingMappingInfoEXT mapping_info = vku::InitStructHelper();
mapping_info.mappingCount = 1;
mapping_info.pMappings = &mappings;
char const* cs_source = R"glsl(
#version 450
layout(local_size_x = 1) in;
layout(set = 0, binding = 0) buffer storage_buffer1 { int result[]; };
void main() {
result[int(256.0 * gl_GlobalInvocationID.x)] = 1;
}
)glsl";
const char* slang_shader = R"slang(
[[vk::binding(0, 0)]]
RWStructuredBuffer<int> result;
[numthreads(1, 1, 1)]
void main(uint3 dispatchThreadID : SV_DispatchThreadID)
{
result[int(256.0 * dispatchThreadID.x)] = 1;
}
)slang";
VkShaderObj cs_modules[2];
cs_modules[0] = VkShaderObj(*m_device, cs_source, VK_SHADER_STAGE_COMPUTE_BIT);
cs_modules[1] = VkShaderObj(*m_device, slang_shader, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_0, SPV_SOURCE_SLANG);
VkPipelineCreateFlags2CreateInfo pipeline_create_flags_2_create_info = vku::InitStructHelper();
pipeline_create_flags_2_create_info.flags = VK_PIPELINE_CREATE_2_DESCRIPTOR_HEAP_BIT_EXT;
for (int i = 0; i < 4; i++) {
CreateComputePipelineHelper pipe(*this, &pipeline_create_flags_2_create_info);
pipe.cp_ci_.stage = cs_modules[i / 2].GetStageCreateInfo(&mapping_info);
mappings.sourceData.constantOffset.heapOffset = (i % 2 == 0) ? 1 : 0;
mappings.sourceData.constantOffset.heapArrayStride = (i % 2 == 0) ? 0 : 1;
m_errorMonitor->SetDesiredError("VUID-VkDescriptorSetAndBindingMappingEXT-source-11252");
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
}
TEST_F(NegativeDescriptorHeap, OpTypeSampler) {
AddRequiredExtensions(VK_KHR_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::computeDerivativeGroupQuads);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
AddRequiredFeature(vkt::Feature::runtimeDescriptorArray);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
RETURN_IF_SKIP(CheckSlangSupport());
if (heap_props.samplerDescriptorAlignment < 2) {
GTEST_SKIP() << "Cannot be unaligned with samplerDescriptorAlignment less than 2";
}
VkDescriptorSetAndBindingMappingEXT mappings[3];
mappings[0] = MakeSetAndBindingMapping(0, 0);
mappings[0].source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT;
mappings[0].sourceData.constantOffset.heapOffset = 0u;
mappings[0].sourceData.constantOffset.heapArrayStride = 0;
mappings[1] = MakeSetAndBindingMapping(0, 1);
mappings[1].source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT;
mappings[2] = MakeSetAndBindingMapping(0, 2);
mappings[2].source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT;
VkShaderDescriptorSetAndBindingMappingInfoEXT mapping_info = vku::InitStructHelper();
mapping_info.mappingCount = 3;
mapping_info.pMappings = mappings;
char const* cs_source0 = R"glsl(
#version 450
layout(local_size_x = 1) in;
layout(set = 0, binding = 0) buffer Output { int result[]; };
layout(set = 0, binding = 1) uniform sampler samp;
layout(set = 0, binding = 2) uniform texture2D tex;
void main() {
ivec2 uv = ivec2(gl_GlobalInvocationID.xy);
vec2 texCoord = vec2(gl_GlobalInvocationID.xy) / 1.0;
vec4 color = texture(sampler2D(tex, samp), texCoord);
result[gl_LocalInvocationIndex] = int(color.r);
}
)glsl";
char const* cs_source1 = R"glsl(
#version 450
layout(local_size_x = 1) in;
layout(set = 0, binding = 0) buffer Output { int result[]; };
layout(set = 0, binding = 1) uniform sampler samp[];
layout(set = 0, binding = 2) uniform texture2D tex;
void main() {
ivec2 uv = ivec2(gl_GlobalInvocationID.xy);
vec2 texCoord = vec2(gl_GlobalInvocationID.xy) / 1.0;
vec4 color = texture(sampler2D(tex, samp[0]), texCoord);
result[gl_LocalInvocationIndex] = int(color.r);
}
)glsl";
const char* slang_shader0 = R"slang(
[[vk::binding(0, 0)]]
RWStructuredBuffer<int> result;
[[vk::binding(1, 0)]]
SamplerState samp;
[[vk::binding(2, 0)]]
Texture2D tex;
[numthreads(2, 2, 2)]
void main(uint3 dispatchThreadID : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex)
{
int2 uv = int2(dispatchThreadID.xy);
float2 texCoord = float2(dispatchThreadID.xy) / 1.0;
float4 color = tex.Sample(samp, texCoord);
result[groupIndex] = int(color.r);
}
)slang";
const char* slang_shader1 = R"slang(
[[vk::binding(0, 0)]]
RWStructuredBuffer<int> result;
[[vk::binding(1, 0)]]
SamplerState samp[];
[[vk::binding(2, 0)]]
Texture2D tex;
[numthreads(2, 2, 2)]
void main(uint3 dispatchThreadID : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex)
{
int2 uv = int2(dispatchThreadID.xy);
float2 texCoord = float2(dispatchThreadID.xy) / 1.0;
float4 color = tex.Sample(samp[0], texCoord);
result[groupIndex] = int(color.r);
}
)slang";
VkShaderObj cs_modules[4];
cs_modules[0] = VkShaderObj(*m_device, cs_source0, VK_SHADER_STAGE_COMPUTE_BIT);
cs_modules[1] = VkShaderObj(*m_device, cs_source1, VK_SHADER_STAGE_COMPUTE_BIT);
cs_modules[2] = VkShaderObj(*m_device, slang_shader0, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_0, SPV_SOURCE_SLANG);
cs_modules[3] = VkShaderObj(*m_device, slang_shader1, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_0, SPV_SOURCE_SLANG);
for (int j = 0; j < 4; j++) {
VkPipelineCreateFlags2CreateInfo pipeline_create_flags_2_create_info = vku::InitStructHelper();
pipeline_create_flags_2_create_info.flags = VK_PIPELINE_CREATE_2_DESCRIPTOR_HEAP_BIT_EXT;
for (int i = 0; i < 2; i++) {
CreateComputePipelineHelper pipe(*this, &pipeline_create_flags_2_create_info);
pipe.cp_ci_.layout = VK_NULL_HANDLE;
pipe.cp_ci_.stage = cs_modules[j].GetStageCreateInfo(&mapping_info);
mappings[1].sourceData.constantOffset.heapOffset = (i == 0) ? 1 : 0;
mappings[1].sourceData.constantOffset.heapArrayStride = (i == 0) ? 0 : 1;
m_errorMonitor->SetDesiredError("VUID-VkDescriptorSetAndBindingMappingEXT-source-11253");
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
}
}
TEST_F(NegativeDescriptorHeap, OpTypeSampledImage) {
TEST_DESCRIPTION("Validate that mapping is aligned for OpTypeSampledImage");
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
RETURN_IF_SKIP(CheckSlangSupport());
if (heap_props.samplerDescriptorAlignment < 2) {
GTEST_SKIP() << "Cannot be unaligned with samplerDescriptorAlignment less than 2";
}
VkDescriptorSetAndBindingMappingEXT mappings[2];
mappings[0] = MakeSetAndBindingMapping(0, 0);
mappings[0].source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT;
mappings[0].sourceData.constantOffset.heapOffset = 0;
mappings[0].sourceData.constantOffset.heapArrayStride = 0;
mappings[1] = MakeSetAndBindingMapping(0, 1);
mappings[1].source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT;
VkShaderDescriptorSetAndBindingMappingInfoEXT mapping_info = vku::InitStructHelper();
mapping_info.mappingCount = 2;
mapping_info.pMappings = mappings;
char const* cs_source = R"glsl(
#version 450
layout(local_size_x = 1) in;
layout(set = 0, binding = 0) buffer Output { int result[]; };
layout(set = 0, binding = 1) uniform sampler2D tex;
void main() {
vec4 color = textureLod(tex, vec2(gl_GlobalInvocationID.xy), 0);
result[gl_LocalInvocationIndex] = int(color.r);
}
)glsl";
const char* slang_shader = R"slang(
[[vk::binding(0, 0)]]
RWTexture2D<float4> result;
[[vk::combinedImageSampler]]
Sampler2D<float4> tex;
[numthreads(1, 1, 1)]
void main(uint3 dispatchThreadID : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex) {
float4 color = tex.SampleLevel(float2(dispatchThreadID.xy), 0);
result[groupIndex] = int(color.r);
}
)slang";
VkShaderObj cs_modules[2];
cs_modules[0] = VkShaderObj(*m_device, cs_source, VK_SHADER_STAGE_COMPUTE_BIT);
cs_modules[1] = VkShaderObj(*m_device, slang_shader, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_0, SPV_SOURCE_SLANG);
VkPipelineCreateFlags2CreateInfo pipeline_create_flags_2_create_info = vku::InitStructHelper();
pipeline_create_flags_2_create_info.flags = VK_PIPELINE_CREATE_2_DESCRIPTOR_HEAP_BIT_EXT;
for (int i = 0; i < 4; i++) {
CreateComputePipelineHelper pipe(*this, &pipeline_create_flags_2_create_info);
pipe.cp_ci_.layout = VK_NULL_HANDLE;
pipe.cp_ci_.stage = cs_modules[i / 2].GetStageCreateInfo(&mapping_info);
mappings[1].sourceData.constantOffset.samplerHeapOffset = (i % 2 == 0) ? 1 : 0;
mappings[1].sourceData.constantOffset.samplerHeapArrayStride = (i % 2 == 0) ? 0 : 1;
m_errorMonitor->SetDesiredError("VUID-VkDescriptorSetAndBindingMappingEXT-source-11254");
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
}
TEST_F(NegativeDescriptorHeap, NoMappingStruct) {
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
AddRequiredFeature(vkt::Feature::runtimeDescriptorArray);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
char const* cs_source = R"glsl(
#version 450
layout(local_size_x = 1) in;
layout(set = 0, binding = 0) buffer Output { int result[]; } x[];
layout(set = 0, binding = 1) buffer Input0 { int data[]; } y[];
void main() {
x[0].result[gl_LocalInvocationID.x] = y[0].data[gl_LocalInvocationID.x];
}
)glsl";
VkShaderObj cs_module = VkShaderObj(*m_device, cs_source, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_2);
VkPipelineCreateFlags2CreateInfo pipeline_create_flags_2_create_info = vku::InitStructHelper();
pipeline_create_flags_2_create_info.flags = VK_PIPELINE_CREATE_2_DESCRIPTOR_HEAP_BIT_EXT;
CreateComputePipelineHelper pipe(*this, &pipeline_create_flags_2_create_info);
pipe.cp_ci_.layout = VK_NULL_HANDLE;
pipe.cp_ci_.stage = cs_module.GetStageCreateInfo();
m_errorMonitor->SetDesiredError("VUID-VkComputePipelineCreateInfo-flags-11312");
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDescriptorHeap, MappingWithoutFlag) {
RETURN_IF_SKIP(InitBasicDescriptorHeap());
VkDescriptorSetAndBindingMappingEXT mappings = MakeSetAndBindingMapping(0, 0);
VkShaderDescriptorSetAndBindingMappingInfoEXT mapping_info = vku::InitStructHelper();
mapping_info.mappingCount = 1;
mapping_info.pMappings = &mappings;
char const* cs_source = R"glsl(
#version 450
layout(set = 0, binding = 0) buffer A0 { int a_0; };
void main() {
a_0 = 0;
}
)glsl";
VkShaderObj cs_module = VkShaderObj(*m_device, cs_source, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_2);
OneOffDescriptorSet descriptor_set(m_device, {
{0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr},
});
const vkt::PipelineLayout pipeline_layout(*m_device, {&descriptor_set.layout_});
CreateComputePipelineHelper pipe(*this);
pipe.cp_ci_.layout = pipeline_layout;
pipe.cp_ci_.stage = cs_module.GetStageCreateInfo(&mapping_info);
m_errorMonitor->SetDesiredWarning("WARNING-VkShaderDescriptorSetAndBindingMappingInfoEXT-ignored");
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDescriptorHeap, NoMappingShaderObject) {
TEST_DESCRIPTION("Check that descriptor set bindings have a mappings when using VkShaderCreateFlagsEXT");
AddRequiredExtensions(VK_EXT_SHADER_OBJECT_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::shaderObject);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
char const* cs_source = R"glsl(
#version 450
layout(local_size_x = 1) in;
layout(set = 0, binding = 0) buffer Output { int result[]; } x[];
void main() {
x[0].result[gl_LocalInvocationID.x] = 0;
}
)glsl";
VkDescriptorSetAndBindingMappingEXT mappings = MakeSetAndBindingMapping(1, 0);
mappings.source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT;
mappings.sourceData.constantOffset.heapOffset = 0u;
mappings.sourceData.constantOffset.heapArrayStride = 0;
VkShaderDescriptorSetAndBindingMappingInfoEXT mapping_info = vku::InitStructHelper();
mapping_info.mappingCount = 1;
mapping_info.pMappings = &mappings;
const auto spv = GLSLToSPV(VK_SHADER_STAGE_COMPUTE_BIT, cs_source);
const VkShaderCreateFlagsEXT flags = VK_SHADER_CREATE_DESCRIPTOR_HEAP_BIT_EXT;
VkShaderCreateInfoEXT comp_ci = ShaderCreateInfoFlag(spv, VK_SHADER_STAGE_COMPUTE_BIT, flags);
comp_ci.pNext = &mapping_info;
m_errorMonitor->SetDesiredError("VUID-VkShaderCreateInfoEXT-flags-11292");
const vkt::Shader compShader(*m_device, comp_ci);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDescriptorHeap, NoMappingComputePipeline) {
TEST_DESCRIPTION("Check that descriptor set bindings have a mappings");
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
AddRequiredFeature(vkt::Feature::runtimeDescriptorArray);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
RETURN_IF_SKIP(CheckSlangSupport());
VkDescriptorSetAndBindingMappingEXT mappings = MakeSetAndBindingMapping(0, 0);
mappings.source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT;
mappings.sourceData.constantOffset.heapOffset = 0;
mappings.sourceData.constantOffset.heapArrayStride = 0;
VkShaderDescriptorSetAndBindingMappingInfoEXT mapping_info = vku::InitStructHelper();
mapping_info.mappingCount = 1;
mapping_info.pMappings = &mappings;
char const* cs_source = R"glsl(
#version 450
layout(local_size_x = 1) in;
layout(set = 0, binding = 0) buffer Output { int result[]; } x[];
layout(set = 0, binding = 1) buffer Input0 { int data[]; } y[];
void main() {
x[0].result[gl_LocalInvocationID.x] = y[0].data[gl_LocalInvocationID.x];
}
)glsl";
const char* slang_shader = R"slang(
[[vk::binding(0, 0)]]
RWStructuredBuffer<int> x[];
[[vk::binding(1, 0)]]
RWStructuredBuffer<int> y[];
[numthreads(1, 1, 1)]
void main(uint3 dispatchThreadID : SV_DispatchThreadID) {
x[0][dispatchThreadID.x] = y[0][dispatchThreadID.x];
}
)slang";
VkShaderObj cs_modules[2];
cs_modules[0] = VkShaderObj(*m_device, cs_source, VK_SHADER_STAGE_COMPUTE_BIT);
cs_modules[1] = VkShaderObj(*m_device, slang_shader, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_0, SPV_SOURCE_SLANG);
VkPipelineCreateFlags2CreateInfo pipeline_create_flags_2_create_info = vku::InitStructHelper();
pipeline_create_flags_2_create_info.flags = VK_PIPELINE_CREATE_2_DESCRIPTOR_HEAP_BIT_EXT;
CreateComputePipelineHelper pipe(*this, &pipeline_create_flags_2_create_info);
pipe.cp_ci_.layout = VK_NULL_HANDLE;
for (uint32_t i = 0; i < 2; ++i) {
pipe.cp_ci_.stage = cs_modules[i].GetStageCreateInfo(&mapping_info);
m_errorMonitor->SetDesiredError("VUID-VkComputePipelineCreateInfo-flags-11312");
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
}
TEST_F(NegativeDescriptorHeap, NoMappingMultipleMappings) {
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
AddRequiredFeature(vkt::Feature::runtimeDescriptorArray);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
VkDescriptorSetAndBindingMappingEXT mappings[5];
mappings[0] = MakeSetAndBindingMapping(1, 0);
mappings[0].source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT;
mappings[0].sourceData.constantOffset.heapOffset = 0u;
mappings[0].sourceData.constantOffset.heapArrayStride = 0;
mappings[1] = MakeSetAndBindingMapping(0, 3);
mappings[1].source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT;
mappings[1].sourceData.constantOffset.heapOffset = 0u;
mappings[1].sourceData.constantOffset.heapArrayStride = 0;
mappings[2] = MakeSetAndBindingMapping(0, 0, 2);
mappings[2].source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT;
mappings[2].sourceData.constantOffset.heapOffset = 0u;
mappings[2].sourceData.constantOffset.heapArrayStride = 0;
mappings[3] = MakeSetAndBindingMapping(0, 2, 1, VK_SPIRV_RESOURCE_TYPE_UNIFORM_BUFFER_BIT_EXT);
mappings[3].source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT;
mappings[3].sourceData.constantOffset.heapOffset = 0u;
mappings[3].sourceData.constantOffset.heapArrayStride = 0;
mappings[4] = MakeSetAndBindingMapping(0, 2, 1, VK_SPIRV_RESOURCE_TYPE_READ_ONLY_STORAGE_BUFFER_BIT_EXT);
mappings[4].source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT;
mappings[4].sourceData.constantOffset.heapOffset = 0u;
mappings[4].sourceData.constantOffset.heapArrayStride = 0;
VkShaderDescriptorSetAndBindingMappingInfoEXT mapping_info = vku::InitStructHelper();
mapping_info.mappingCount = 5;
mapping_info.pMappings = mappings;
char const* cs_source = R"glsl(
#version 450
layout(set = 0, binding = 2) buffer Output { int result; };
void main() {
result = 0;
}
)glsl";
VkShaderObj cs_module = VkShaderObj(*m_device, cs_source, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_2);
VkPipelineCreateFlags2CreateInfo pipeline_create_flags_2_create_info = vku::InitStructHelper();
pipeline_create_flags_2_create_info.flags = VK_PIPELINE_CREATE_2_DESCRIPTOR_HEAP_BIT_EXT;
CreateComputePipelineHelper pipe(*this, &pipeline_create_flags_2_create_info);
pipe.cp_ci_.layout = VK_NULL_HANDLE;
pipe.cp_ci_.stage = cs_module.GetStageCreateInfo(&mapping_info);
m_errorMonitor->SetDesiredError("VUID-VkComputePipelineCreateInfo-flags-11312");
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDescriptorHeap, NoMappingMultipleMappingsAllUsed) {
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
AddRequiredFeature(vkt::Feature::runtimeDescriptorArray);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
VkDescriptorSetAndBindingMappingEXT mappings[3];
for (uint32_t i = 0; i < 3; i++) {
mappings[i] = MakeSetAndBindingMapping(0, i);
mappings[i].source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT;
mappings[i].sourceData.constantOffset.heapOffset = 0u;
mappings[i].sourceData.constantOffset.heapArrayStride = 0;
}
VkShaderDescriptorSetAndBindingMappingInfoEXT mapping_info = vku::InitStructHelper();
mapping_info.mappingCount = 3;
mapping_info.pMappings = mappings;
char const* cs_source = R"glsl(
#version 450
layout(set = 0, binding = 0) buffer A0 { int a_0; };
layout(set = 0, binding = 1) buffer A1 { int a_1; };
layout(set = 0, binding = 2) buffer A2 { int a_2; };
layout(set = 0, binding = 3) buffer A3 { int a_3; };
void main() {
a_0 = 0;
a_1 = 0;
a_2 = 0;
a_3 = 0;
}
)glsl";
VkShaderObj cs_module = VkShaderObj(*m_device, cs_source, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_2);
VkPipelineCreateFlags2CreateInfo pipeline_create_flags_2_create_info = vku::InitStructHelper();
pipeline_create_flags_2_create_info.flags = VK_PIPELINE_CREATE_2_DESCRIPTOR_HEAP_BIT_EXT;
CreateComputePipelineHelper pipe(*this, &pipeline_create_flags_2_create_info);
pipe.cp_ci_.layout = VK_NULL_HANDLE;
pipe.cp_ci_.stage = cs_module.GetStageCreateInfo(&mapping_info);
m_errorMonitor->SetDesiredError("VUID-VkComputePipelineCreateInfo-flags-11312");
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDescriptorHeap, NoMappingMultipleMappingsMostUsed) {
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
AddRequiredFeature(vkt::Feature::runtimeDescriptorArray);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
VkDescriptorSetAndBindingMappingEXT mappings[9];
for (uint32_t i = 0; i < 9; i++) {
mappings[i] = MakeSetAndBindingMapping(0, i);
mappings[i].source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT;
mappings[i].sourceData.constantOffset.heapOffset = 0u;
mappings[i].sourceData.constantOffset.heapArrayStride = 0;
}
VkShaderDescriptorSetAndBindingMappingInfoEXT mapping_info = vku::InitStructHelper();
mapping_info.mappingCount = 9;
mapping_info.pMappings = mappings;
char const* cs_source = R"glsl(
#version 450
layout(set = 0, binding = 0) buffer A0 { int a_0; };
layout(set = 0, binding = 1) buffer A1 { int a_1; };
layout(set = 0, binding = 2) buffer A2 { int a_2; };
layout(set = 0, binding = 3) buffer A3 { int a_3; };
layout(set = 0, binding = 4) buffer A4 { int a_4; };
layout(set = 0, binding = 6) buffer A6 { int a_6; };
layout(set = 0, binding = 7) buffer A7 { int a_7; };
layout(set = 0, binding = 8) buffer A8 { int a_8; };
layout(set = 0, binding = 9) buffer A9 { int a_9; };
void main() {
a_0 = 0;
a_1 = 0;
a_2 = 0;
a_3 = 0;
a_4 = 0;
a_6 = 0;
a_7 = 0;
a_8 = 0;
a_9 = 0;
}
)glsl";
VkShaderObj cs_module = VkShaderObj(*m_device, cs_source, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_2);
VkPipelineCreateFlags2CreateInfo pipeline_create_flags_2_create_info = vku::InitStructHelper();
pipeline_create_flags_2_create_info.flags = VK_PIPELINE_CREATE_2_DESCRIPTOR_HEAP_BIT_EXT;
CreateComputePipelineHelper pipe(*this, &pipeline_create_flags_2_create_info);
pipe.cp_ci_.layout = VK_NULL_HANDLE;
pipe.cp_ci_.stage = cs_module.GetStageCreateInfo(&mapping_info);
m_errorMonitor->SetDesiredError("VUID-VkComputePipelineCreateInfo-flags-11312");
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDescriptorHeap, NoMappingMultipleMappingsMany) {
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
AddRequiredFeature(vkt::Feature::runtimeDescriptorArray);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
VkDescriptorSetAndBindingMappingEXT mappings[512];
for (uint32_t i = 0; i < 512; i++) {
mappings[i] = MakeSetAndBindingMapping(0, i + 1);
mappings[i].source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT;
mappings[i].sourceData.constantOffset.heapOffset = 0u;
mappings[i].sourceData.constantOffset.heapArrayStride = 0;
}
VkShaderDescriptorSetAndBindingMappingInfoEXT mapping_info = vku::InitStructHelper();
mapping_info.mappingCount = 512;
mapping_info.pMappings = mappings;
char const* cs_source = R"glsl(
#version 450
layout(set = 0, binding = 0) buffer A0 { int a_0; };
layout(set = 0, binding = 10) buffer A1 { int a_1; };
layout(set = 0, binding = 20) buffer A2 { int a_2; };
layout(set = 0, binding = 30) buffer A3 { int a_3; };
layout(set = 0, binding = 40) buffer A4 { int a_4; };
layout(set = 0, binding = 60) buffer A6 { int a_6; };
layout(set = 0, binding = 70) buffer A7 { int a_7; };
layout(set = 0, binding = 80) buffer A8 { int a_8; };
layout(set = 0, binding = 90) buffer A9 { int a_9; };
void main() {
a_0 = 0;
a_1 = 0;
a_2 = 0;
a_3 = 0;
a_4 = 0;
a_6 = 0;
a_7 = 0;
a_8 = 0;
a_9 = 0;
}
)glsl";
VkShaderObj cs_module = VkShaderObj(*m_device, cs_source, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_2);
VkPipelineCreateFlags2CreateInfo pipeline_create_flags_2_create_info = vku::InitStructHelper();
pipeline_create_flags_2_create_info.flags = VK_PIPELINE_CREATE_2_DESCRIPTOR_HEAP_BIT_EXT;
CreateComputePipelineHelper pipe(*this, &pipeline_create_flags_2_create_info);
pipe.cp_ci_.layout = VK_NULL_HANDLE;
pipe.cp_ci_.stage = cs_module.GetStageCreateInfo(&mapping_info);
m_errorMonitor->SetDesiredError("VUID-VkComputePipelineCreateInfo-flags-11312");
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDescriptorHeap, EmbeddedSamplerReservedArea) {
TEST_DESCRIPTION("Validate that embedded sampler mapping have reserved area");
AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
AddRequiredFeature(vkt::Feature::computeDerivativeGroupQuads);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
RETURN_IF_SKIP(CheckSlangSupport());
if (heap_props.minSamplerHeapReservedRangeWithEmbedded < 1) {
GTEST_SKIP() << "Cannot test minSamplerHeapReservedRangeWithEmbedded less than 1";
}
const VkDeviceSize bdsize = 2 * heap_props.samplerDescriptorSize + heap_props.minSamplerHeapReservedRangeWithEmbedded;
vkt::Buffer buffer(*m_device, bdsize, VK_BUFFER_USAGE_DESCRIPTOR_HEAP_BIT_EXT, vkt::device_address);
// reservedRangeOffset check
VkBindHeapInfoEXT bind_info = vku::InitStructHelper();
bind_info.heapRange = buffer.AddressRange();
bind_info.reservedRangeSize = heap_props.minSamplerHeapReservedRangeWithEmbedded - 1;
// Resource descriptor heap buffer
const VkDeviceSize resource_stride = Align(heap_props.bufferDescriptorSize, heap_props.samplerDescriptorAlignment);
const VkDeviceSize resource_descriptor_count = 4;
const VkDeviceSize resource_heap_size_app = AlignResource(resource_descriptor_count * resource_stride);
const VkDeviceSize resource_heap_size = resource_heap_size_app + heap_props.minResourceHeapReservedRange;
const VkDeviceSize out_data_buffer_size = 256;
vkt::Buffer resource_heap(*m_device, resource_heap_size, VK_BUFFER_USAGE_2_DESCRIPTOR_HEAP_BIT_EXT, vkt::device_address);
const auto resource_heap_ptr = static_cast<char*>(resource_heap.Memory().Map());
// Sampler descriptor heap buffer
const VkDeviceSize sampler_stride = heap_props.samplerDescriptorSize;
const VkDeviceSize sampler_descriptor_count = 4;
const VkDeviceSize sampler_heap_size_app = AlignResource(sampler_descriptor_count * sampler_stride);
const VkDeviceSize sampler_heap_size = sampler_heap_size_app + heap_props.minSamplerHeapReservedRange;
vkt::Buffer sampler_heap(*m_device, sampler_heap_size, VK_BUFFER_USAGE_2_DESCRIPTOR_HEAP_BIT_EXT, vkt::device_address);
const auto sampler_heap_ptr = static_cast<char*>(sampler_heap.Memory().Map());
// Output buffer descriptor
vkt::Buffer out_buffer(*m_device, out_data_buffer_size, VK_BUFFER_USAGE_2_STORAGE_BUFFER_BIT_KHR, vkt::device_address);
VkHostAddressRangeEXT out_descriptor{resource_heap_ptr, static_cast<size_t>(resource_stride)};
VkDeviceAddressRangeEXT out_address_range = out_buffer.AddressRange();
VkResourceDescriptorInfoEXT out_descriptor_info = vku::InitStructHelper();
out_descriptor_info.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
out_descriptor_info.data.pAddressRange = &out_address_range;
vk::WriteResourceDescriptorsEXT(*m_device, 1, &out_descriptor_info, &out_descriptor);
VkSamplerCreateInfo sampler_ci = vku::InitStructHelper();
VkHostAddressRangeEXT input_descriptor{sampler_heap_ptr + sampler_stride, static_cast<size_t>(sampler_stride)};
vk::WriteSamplerDescriptorsEXT(*m_device, 1, &sampler_ci, &input_descriptor);
VkDescriptorSetAndBindingMappingEXT mappings[3];
mappings[0] = MakeSetAndBindingMapping(0, 0);
mappings[0].source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT;
mappings[0].sourceData.constantOffset.heapOffset = 0u * (uint32_t)resource_stride;
mappings[0].sourceData.constantOffset.heapArrayStride = 0;
VkSamplerCreateInfo embedded_sampler = vku::InitStructHelper();
mappings[1] = MakeSetAndBindingMapping(0, 1);
mappings[1].source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT;
mappings[1].sourceData.constantOffset.heapOffset = 1u * (uint32_t)resource_stride;
mappings[1].sourceData.constantOffset.heapArrayStride = 0;
mappings[1].sourceData.constantOffset.pEmbeddedSampler = &embedded_sampler;
mappings[2] = MakeSetAndBindingMapping(0, 2);
mappings[2].source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT;
mappings[2].sourceData.constantOffset.heapOffset = 2u * (uint32_t)resource_stride;
mappings[2].sourceData.constantOffset.heapArrayStride = 0;
VkShaderDescriptorSetAndBindingMappingInfoEXT mapping_info = vku::InitStructHelper();
mapping_info.mappingCount = 3;
mapping_info.pMappings = mappings;
char const* cs_source = R"glsl(
#version 450
layout(local_size_x = 1) in;
layout(set = 0, binding = 0) buffer Output { int result[]; };
layout(set = 0, binding = 1) uniform sampler samp;
layout(set = 0, binding = 2) uniform texture2D tex;
void main() {
ivec2 uv = ivec2(gl_GlobalInvocationID.xy);
vec2 texCoord = vec2(gl_GlobalInvocationID.xy) / 1.0;
vec4 color = texture(sampler2D(tex, samp), texCoord);
result[gl_LocalInvocationIndex] = int(color.r);
}
)glsl";
const char* slang_shader = R"slang(
[[vk::binding(0, 0)]]
RWStructuredBuffer<int> result;
[[vk::binding(1, 0)]]
SamplerState samp;
[[vk::binding(2, 0)]]
Texture2D<float4> tex;
[numthreads(2, 2, 2)]
void main(uint3 dispatchThreadID : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex) {
int2 uv = int2(dispatchThreadID.xy);
float2 texCoord = float2(dispatchThreadID.xy) / 1.0;
float4 color = tex.Sample(samp, texCoord);
result[groupIndex] = int(color.r);
}
)slang";
VkShaderObj cs_modules[2];
cs_modules[0] = VkShaderObj(*m_device, cs_source, VK_SHADER_STAGE_COMPUTE_BIT);
cs_modules[1] = VkShaderObj(*m_device, slang_shader, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_0, SPV_SOURCE_SLANG);
for (int i = 0; i < 2; ++i) {
VkPipelineCreateFlags2CreateInfo pipeline_create_flags_2_create_info = vku::InitStructHelper();
pipeline_create_flags_2_create_info.flags = VK_PIPELINE_CREATE_2_DESCRIPTOR_HEAP_BIT_EXT;
CreateComputePipelineHelper pipe(*this, &pipeline_create_flags_2_create_info);
pipe.cp_ci_.layout = VK_NULL_HANDLE;
pipe.cp_ci_.stage = cs_modules[i].GetStageCreateInfo(&mapping_info);
pipe.CreateComputePipeline(false);
m_command_buffer.Begin();
VkBindHeapInfoEXT bind_resource_info = vku::InitStructHelper();
bind_resource_info.heapRange = resource_heap.AddressRange();
bind_resource_info.reservedRangeOffset = resource_heap_size_app;
bind_resource_info.reservedRangeSize = heap_props.minResourceHeapReservedRange;
vk::CmdBindResourceHeapEXT(m_command_buffer, &bind_resource_info);
vk::CmdBindSamplerHeapEXT(m_command_buffer, &bind_info);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDispatch-pBindInfo-11375");
vk::CmdDispatch(m_command_buffer, 1, 1, 1);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
m_default_queue->SubmitAndWait(m_command_buffer);
}
}
TEST_F(NegativeDescriptorHeap, EmbeddedSamplerArray) {
TEST_DESCRIPTION("Validate that embedded sampler mapping as an array");
SetTargetApiVersion(VK_API_VERSION_1_3);
AddRequiredExtensions(VK_KHR_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::computeDerivativeGroupQuads);
AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
AddRequiredFeature(vkt::Feature::runtimeDescriptorArray);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
RETURN_IF_SKIP(CheckSlangSupport());
char const* cs_source_glsl = R"glsl(
#version 450
layout(local_size_x = 1) in;
layout(set = 0, binding = 0) buffer Output { int result[]; };
layout(set = 0, binding = 1) uniform sampler samp[2];
layout(set = 0, binding = 2) uniform texture2D tex;
void main() {
ivec2 uv = ivec2(gl_GlobalInvocationID.xy);
vec2 texCoord = vec2(uv) / 1.0;
vec4 color = texture(sampler2D(tex, samp[0]), texCoord);
result[gl_LocalInvocationIndex] = int(color.r);
}
)glsl";
const char* cs_source_hlsl = R"slang(
[[vk::binding(0, 0)]]
RWStructuredBuffer<int> result[];
[[vk::binding(1, 0)]]
uniform SamplerState samp[2];
[[vk::binding(2, 0)]]
uniform Texture2D tex;
[numthreads(2, 2, 2)]
void main(uint3 dispatchThreadID : SV_DispatchThreadID) {
int2 uv = int2(dispatchThreadID[0], dispatchThreadID[1]);
float2 texCoord = float2(uv);
float4 color = tex.Sample(samp[0], texCoord);
result[dispatchThreadID.x][0] = int(color.r);
}
)slang";
VkShaderObj cs_modules[2] = {};
cs_modules[0] = VkShaderObj(*m_device, cs_source_glsl, VK_SHADER_STAGE_COMPUTE_BIT);
cs_modules[1] = VkShaderObj(*m_device, cs_source_hlsl, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_0, SPV_SOURCE_SLANG);
m_errorMonitor->VerifyFound();
const VkDeviceSize bdsize = 2 * heap_props.samplerDescriptorSize + heap_props.minSamplerHeapReservedRangeWithEmbedded;
vkt::Buffer buffer(*m_device, bdsize, VK_BUFFER_USAGE_DESCRIPTOR_HEAP_BIT_EXT, vkt::device_address);
// reservedRangeOffset check
VkBindHeapInfoEXT bind_info = vku::InitStructHelper();
bind_info.heapRange = buffer.AddressRange();
bind_info.reservedRangeSize = heap_props.minSamplerHeapReservedRangeWithEmbedded;
m_command_buffer.Begin();
vk::CmdBindSamplerHeapEXT(m_command_buffer, &bind_info);
m_command_buffer.End();
const VkDeviceSize resource_stride = Align(heap_props.bufferDescriptorSize, heap_props.samplerDescriptorAlignment);
VkDescriptorSetAndBindingMappingEXT mappings[3];
mappings[0] = MakeSetAndBindingMapping(0, 0);
mappings[0].source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT;
mappings[0].sourceData.constantOffset.heapOffset = 0u * (uint32_t)resource_stride;
mappings[0].sourceData.constantOffset.heapArrayStride = 0;
VkSamplerCreateInfo embedded_sampler = vku::InitStructHelper();
mappings[1] = MakeSetAndBindingMapping(0, 1);
mappings[1].source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT;
mappings[1].sourceData.constantOffset.heapOffset = 1u * (uint32_t)resource_stride;
mappings[1].sourceData.constantOffset.heapArrayStride = 0;
mappings[1].sourceData.constantOffset.pEmbeddedSampler = &embedded_sampler;
mappings[2] = MakeSetAndBindingMapping(0, 2);
mappings[2].source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT;
mappings[2].sourceData.constantOffset.heapOffset = 2u * (uint32_t)resource_stride;
mappings[2].sourceData.constantOffset.heapArrayStride = 0;
VkShaderDescriptorSetAndBindingMappingInfoEXT mapping_info = vku::InitStructHelper();
mapping_info.mappingCount = 3;
mapping_info.pMappings = mappings;
VkPipelineCreateFlags2CreateInfo pipeline_create_flags_2_create_info = vku::InitStructHelper();
pipeline_create_flags_2_create_info.flags = VK_PIPELINE_CREATE_2_DESCRIPTOR_HEAP_BIT_EXT;
for (int i = 0; i < 2; ++i) {
CreateComputePipelineHelper pipe(*this, &pipeline_create_flags_2_create_info);
pipe.cp_ci_.layout = VK_NULL_HANDLE;
pipe.cp_ci_.stage = cs_modules[i].GetStageCreateInfo(&mapping_info);
m_errorMonitor->SetDesiredError("VUID-VkPipelineShaderStageCreateInfo-pNext-11399");
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
}
TEST_F(NegativeDescriptorHeap, PushDataAssignedPipeline) {
TEST_DESCRIPTION("Check that push data used in shader code has been set for pipeline based shaders");
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
const char* cs_source = R"glsl(
#version 450
layout(local_size_x = 1) in;
layout(push_constant, std430) uniform foo { int x[4]; } constants;
layout(set = 0, binding = 0) buffer Output { int result[]; };
void main() {
result[gl_LocalInvocationID.x] = constants.x[gl_LocalInvocationID.x];
}
)glsl";
const VkDeviceSize resource_stride = heap_props.bufferDescriptorSize;
const VkDeviceSize resource_descriptor_count = 4;
const VkDeviceSize resource_heap_size_app = AlignResource(resource_descriptor_count * resource_stride);
const VkDeviceSize resource_heap_size = resource_heap_size_app + heap_props.minResourceHeapReservedRange;
const VkDeviceSize dataBufferSize = 256;
for (int i = 0; i < 2; i++) {
vkt::Buffer resource_heap(*m_device, resource_heap_size, VK_BUFFER_USAGE_2_DESCRIPTOR_HEAP_BIT_EXT, vkt::device_address);
const auto resource_heap_ptr = static_cast<char*>(resource_heap.Memory().Map());
// Output buffer descriptor
vkt::Buffer out_buffer(*m_device, dataBufferSize, VK_BUFFER_USAGE_2_STORAGE_BUFFER_BIT, vkt::device_address);
VkHostAddressRangeEXT out_descriptor{resource_heap_ptr, static_cast<size_t>(resource_stride)};
VkDeviceAddressRangeEXT out_address_range = out_buffer.AddressRange();
VkResourceDescriptorInfoEXT out_descriptor_info = vku::InitStructHelper();
out_descriptor_info.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
out_descriptor_info.data.pAddressRange = &out_address_range;
vk::WriteResourceDescriptorsEXT(*m_device, 1, &out_descriptor_info, &out_descriptor);
VkDescriptorSetAndBindingMappingEXT mappings = MakeSetAndBindingMapping(0, 0);
mappings.source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT;
mappings.sourceData.constantOffset.heapOffset = 0u * (uint32_t)resource_stride;
mappings.sourceData.constantOffset.heapArrayStride = 0;
VkShaderDescriptorSetAndBindingMappingInfoEXT mapping_info = vku::InitStructHelper();
mapping_info.mappingCount = 1;
mapping_info.pMappings = &mappings;
VkShaderObj cs_module = VkShaderObj(*m_device, cs_source, VK_SHADER_STAGE_COMPUTE_BIT);
VkPipelineCreateFlags2CreateInfo pipeline_create_flags_2_create_info = vku::InitStructHelper();
pipeline_create_flags_2_create_info.flags = VK_PIPELINE_CREATE_2_DESCRIPTOR_HEAP_BIT_EXT;
CreateComputePipelineHelper pipe(*this, &pipeline_create_flags_2_create_info);
pipe.cp_ci_.layout = VK_NULL_HANDLE;
pipe.cp_ci_.stage = cs_module.GetStageCreateInfo(&mapping_info);
std::vector<uint8_t> payload(4);
VkPushDataInfoEXT push_data_info = vku::InitStructHelper();
push_data_info.data.address = payload.data();
push_data_info.data.size = payload.size();
push_data_info.offset = 0;
pipe.CreateComputePipeline(false);
m_command_buffer.Begin();
VkBindHeapInfoEXT bind_resource_info = vku::InitStructHelper();
bind_resource_info.heapRange = resource_heap.AddressRange();
bind_resource_info.reservedRangeOffset = resource_heap_size_app;
bind_resource_info.reservedRangeSize = heap_props.minResourceHeapReservedRange;
vk::CmdBindResourceHeapEXT(m_command_buffer, &bind_resource_info);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe);
if (i != 0) {
vk::CmdPushDataEXT(m_command_buffer, &push_data_info);
}
m_errorMonitor->SetDesiredError("VUID-vkCmdDispatch-None-11376");
vk::CmdDispatch(m_command_buffer, 1, 1, 1);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
}
TEST_F(NegativeDescriptorHeap, PushDataAssignedShaderObject) {
TEST_DESCRIPTION("Check that push data used in shader code has been set using shader object");
AddRequiredExtensions(VK_EXT_SHADER_OBJECT_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::shaderObject);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
static const char cs_source[] = R"glsl(
#version 450
layout(local_size_x = 1) in;
layout(push_constant, std430) uniform foo { int x[4]; } constants;
layout(set = 0, binding = 0) buffer Output { int result[]; };
void main() {
result[gl_LocalInvocationID.x] = constants.x[gl_LocalInvocationID.x];
}
)glsl";
const auto spv = GLSLToSPV(VK_SHADER_STAGE_COMPUTE_BIT, cs_source);
const VkDeviceSize resource_stride = heap_props.bufferDescriptorSize;
const VkDeviceSize resource_descriptor_count = 4;
const VkDeviceSize resource_heap_size_app = AlignResource(resource_descriptor_count * resource_stride);
const VkDeviceSize resource_heap_size = resource_heap_size_app + heap_props.minResourceHeapReservedRange;
const VkDeviceSize dataBufferSize = 256;
for (int i = 0; i < 2; i++) {
vkt::Buffer resource_heap(*m_device, resource_heap_size, VK_BUFFER_USAGE_2_DESCRIPTOR_HEAP_BIT_EXT, vkt::device_address);
const auto resource_heap_ptr = static_cast<char*>(resource_heap.Memory().Map());
// Output buffer descriptor
vkt::Buffer out_buffer(*m_device, dataBufferSize, VK_BUFFER_USAGE_2_STORAGE_BUFFER_BIT, vkt::device_address);
VkHostAddressRangeEXT out_descriptor{resource_heap_ptr, static_cast<size_t>(resource_stride)};
VkDeviceAddressRangeEXT out_address_range = out_buffer.AddressRange();
VkResourceDescriptorInfoEXT out_descriptor_info = vku::InitStructHelper();
out_descriptor_info.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
out_descriptor_info.data.pAddressRange = &out_address_range;
vk::WriteResourceDescriptorsEXT(*m_device, 1, &out_descriptor_info, &out_descriptor);
VkDescriptorSetAndBindingMappingEXT mappings = MakeSetAndBindingMapping(0, 0);
mappings.source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT;
mappings.sourceData.constantOffset.heapOffset = 0u * (uint32_t)resource_stride;
mappings.sourceData.constantOffset.heapArrayStride = 0;
VkShaderDescriptorSetAndBindingMappingInfoEXT mapping_info = vku::InitStructHelper();
mapping_info.mappingCount = 1;
mapping_info.pMappings = &mappings;
std::vector<uint8_t> payload(4);
VkPushDataInfoEXT push_data_info = vku::InitStructHelper();
push_data_info.data.address = payload.data();
push_data_info.data.size = payload.size();
push_data_info.offset = 0;
auto shader_ci = ShaderCreateInfoFlag(spv, VK_SHADER_STAGE_COMPUTE_BIT, VK_SHADER_CREATE_DESCRIPTOR_HEAP_BIT_EXT);
shader_ci.pNext = &mapping_info;
const vkt::Shader comp_shader(*m_device, shader_ci);
m_command_buffer.Begin();
VkBindHeapInfoEXT bind_resource_info = vku::InitStructHelper();
bind_resource_info.heapRange = resource_heap.AddressRange();
bind_resource_info.reservedRangeOffset = resource_heap_size_app;
bind_resource_info.reservedRangeSize = heap_props.minResourceHeapReservedRange;
vk::CmdBindResourceHeapEXT(m_command_buffer, &bind_resource_info);
if (i != 0) {
vk::CmdPushDataEXT(m_command_buffer, &push_data_info);
}
m_command_buffer.BindCompShader(comp_shader);
m_errorMonitor->SetDesiredError("VUID-vkCmdDispatch-None-11376");
vk::CmdDispatch(m_command_buffer, 1u, 1u, 1u);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
}
TEST_F(NegativeDescriptorHeap, BufferDescriptorHeapUsageMemoryAllocationInfo) {
TEST_DESCRIPTION("Validate that memory allocated for descriptor heap contains buffer device address");
RETURN_IF_SKIP(InitBasicDescriptorHeap());
VkMemoryAllocateFlagsInfo allocate_flag_info = vku::InitStructHelper();
allocate_flag_info.flags = 0;
m_errorMonitor->SetDesiredError("VUID-vkBindBufferMemory-buffer-11408");
vkt::Buffer buffer(*m_device, heap_props.bufferDescriptorSize, VK_BUFFER_USAGE_DESCRIPTOR_HEAP_BIT_EXT, kHostVisibleMemProps,
&allocate_flag_info);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDescriptorHeap, DuplicatedPushDataSequenceIndex) {
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_EXT_DEVICE_GENERATED_COMMANDS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::deviceGeneratedCommands);
AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
VkIndirectCommandsPushConstantTokenEXT pc_token_0;
pc_token_0.updateRange = {VK_SHADER_STAGE_ALL, 0, 4};
VkIndirectCommandsPushConstantTokenEXT pc_token_1;
pc_token_1.updateRange = {VK_SHADER_STAGE_ALL, 4, 4};
VkIndirectCommandsPushConstantTokenEXT pc_token_2;
pc_token_2.updateRange = {VK_SHADER_STAGE_ALL, 8, 4};
VkIndirectCommandsLayoutTokenEXT tokens[3];
tokens[0] = vku::InitStructHelper();
tokens[0].type = VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_DATA_SEQUENCE_INDEX_EXT;
tokens[0].data.pPushConstant = &pc_token_0;
tokens[0].offset = 0;
tokens[1] = vku::InitStructHelper();
tokens[1].type = VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_DATA_SEQUENCE_INDEX_EXT;
tokens[1].data.pPushConstant = &pc_token_1;
tokens[1].offset = 0;
tokens[2] = vku::InitStructHelper();
tokens[2].type = VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_EXT;
tokens[2].data.pPushConstant = &pc_token_2;
tokens[2].offset = 0;
const std::vector<VkPushConstantRange> pc_range = {{VK_SHADER_STAGE_VERTEX_BIT, 0, 64}};
vkt::PipelineLayout pipeline_layout(*m_device, {}, pc_range);
VkIndirectCommandsLayoutCreateInfoEXT command_layout_ci = vku::InitStructHelper();
command_layout_ci.shaderStages = VK_SHADER_STAGE_VERTEX_BIT;
command_layout_ci.pipelineLayout = pipeline_layout;
command_layout_ci.tokenCount = sizeof(tokens) / sizeof(tokens[0]);
command_layout_ci.pTokens = tokens;
VkIndirectCommandsLayoutEXT command_layout;
m_errorMonitor->SetDesiredError("VUID-VkIndirectCommandsLayoutCreateInfoEXT-pTokens-11145");
vk::CreateIndirectCommandsLayoutEXT(device(), &command_layout_ci, nullptr, &command_layout);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDescriptorHeap, CaptureReplayBit) {
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredFeature(vkt::Feature::descriptorHeapCaptureReplay);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
VkImageCreateInfo image_create_info = vku::InitStructHelper();
image_create_info.flags = VK_IMAGE_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_EXT;
image_create_info.imageType = VK_IMAGE_TYPE_2D;
image_create_info.extent.width = 128;
image_create_info.extent.height = 128;
image_create_info.extent.depth = 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.format = VK_FORMAT_D32_SFLOAT;
image_create_info.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
vkt::Image temp_image(*m_device, image_create_info, vkt::no_mem);
VkMemoryRequirements mem_reqs;
vk::GetImageMemoryRequirements(device(), temp_image, &mem_reqs);
auto mem_alloc_info = vkt::DeviceMemory::GetResourceAllocInfo(*m_device, mem_reqs, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
vkt::DeviceMemory mem(*m_device, mem_alloc_info);
m_errorMonitor->SetDesiredError("VUID-vkBindImageMemory-image-08113");
m_errorMonitor->SetDesiredError("VUID-vkBindImageMemory-image-09202");
vk::BindImageMemory(device(), temp_image, mem, 0);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDescriptorHeap, ImageType3DView3D) {
TEST_DESCRIPTION("Validate that input attachment cannot be a 3D image");
RETURN_IF_SKIP(InitBasicDescriptorHeap());
const VkDescriptorType type = {VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT};
const VkDeviceSize size = vk::GetPhysicalDeviceDescriptorSizeEXT(Gpu(), type);
if (size > 0) {
VkImageCreateInfo image_ci = vku::InitStructHelper();
image_ci.format = VK_FORMAT_R8G8B8A8_UNORM;
image_ci.usage = VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
image_ci.tiling = VK_IMAGE_TILING_OPTIMAL;
image_ci.samples = VK_SAMPLE_COUNT_1_BIT;
image_ci.mipLevels = 1;
image_ci.arrayLayers = 1;
image_ci.extent = {8, 8, 8};
image_ci.imageType = VK_IMAGE_TYPE_3D;
vkt::Image image(*m_device, image_ci);
VkResourceDescriptorInfoEXT resource_desc_info = vku::InitStructHelper();
resource_desc_info.type = type;
VkImageViewCreateInfo image_view_ci = vku::InitStructHelper();
image_view_ci.viewType = VK_IMAGE_VIEW_TYPE_3D;
image_view_ci.format = image_ci.format;
image_view_ci.image = image;
image_view_ci.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
image_view_ci.components = {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A};
VkImageDescriptorInfoEXT image_info = vku::InitStructHelper();
image_info.pView = &image_view_ci;
image_info.layout = VK_IMAGE_LAYOUT_GENERAL;
resource_desc_info.data.pImage = &image_info;
auto data = std::make_unique<uint8_t[]>(static_cast<size_t>(size));
VkHostAddressRangeEXT descriptors = {data.get(), static_cast<size_t>(size)};
m_errorMonitor->SetDesiredError("VUID-VkResourceDescriptorInfoEXT-type-11422");
vk::WriteResourceDescriptorsEXT(device(), 1u, &resource_desc_info, &descriptors);
m_errorMonitor->VerifyFound();
}
}
TEST_F(NegativeDescriptorHeap, ImageType3DView2DArray) {
TEST_DESCRIPTION("Validate that input attachment cannot be a 3D image even if viewtype is 2D array");
RETURN_IF_SKIP(InitBasicDescriptorHeap());
const VkDescriptorType types[] = {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT};
for (auto type : types) {
const VkDeviceSize size = vk::GetPhysicalDeviceDescriptorSizeEXT(Gpu(), type);
if (size > 0) {
const VkImageUsageFlagBits usage = {type == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ? VK_IMAGE_USAGE_SAMPLED_BIT
: type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE ? VK_IMAGE_USAGE_STORAGE_BIT
: VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT};
VkImageCreateInfo image_ci = vku::InitStructHelper();
image_ci.flags = VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT;
image_ci.format = VK_FORMAT_R8G8B8A8_UNORM;
image_ci.usage = usage;
image_ci.tiling = VK_IMAGE_TILING_OPTIMAL;
image_ci.samples = VK_SAMPLE_COUNT_1_BIT;
image_ci.mipLevels = 1;
image_ci.arrayLayers = 1;
image_ci.extent = {8, 8, 8};
image_ci.imageType = VK_IMAGE_TYPE_3D;
vkt::Image image(*m_device, image_ci);
VkResourceDescriptorInfoEXT resource_desc_info = vku::InitStructHelper();
resource_desc_info.type = type;
VkImageViewCreateInfo image_view_ci = vku::InitStructHelper();
image_view_ci.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
image_view_ci.format = image_ci.format;
image_view_ci.image = image;
image_view_ci.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
image_view_ci.components = {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B,
VK_COMPONENT_SWIZZLE_A};
VkImageDescriptorInfoEXT image_info = vku::InitStructHelper();
image_info.pView = &image_view_ci;
image_info.layout = VK_IMAGE_LAYOUT_GENERAL;
resource_desc_info.data.pImage = &image_info;
auto data = std::make_unique<uint8_t[]>(static_cast<size_t>(size));
VkHostAddressRangeEXT descriptors = {data.get(), static_cast<size_t>(size)};
if (type == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT) {
m_errorMonitor->SetDesiredError("VUID-VkResourceDescriptorInfoEXT-type-11422");
}
m_errorMonitor->SetDesiredError("VUID-VkImageDescriptorInfoEXT-pView-11426");
vk::WriteResourceDescriptorsEXT(device(), 1u, &resource_desc_info, &descriptors);
m_errorMonitor->VerifyFound();
}
}
}
TEST_F(NegativeDescriptorHeap, ImageType3DViewImage2DViewOf3D) {
TEST_DESCRIPTION(
"Validate that input attachment cannot be a 3D image even if view type 2D and image2DViewOf3D feature is not enabled");
AddRequiredExtensions(VK_EXT_IMAGE_2D_VIEW_OF_3D_EXTENSION_NAME);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
const VkDescriptorType type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
const VkDeviceSize size = vk::GetPhysicalDeviceDescriptorSizeEXT(Gpu(), type);
if (size > 0) {
VkImageCreateInfo image_ci = vku::InitStructHelper();
image_ci.format = VK_FORMAT_R8G8B8A8_UNORM;
image_ci.usage = VK_IMAGE_USAGE_STORAGE_BIT;
image_ci.tiling = VK_IMAGE_TILING_OPTIMAL;
image_ci.samples = VK_SAMPLE_COUNT_1_BIT;
image_ci.mipLevels = 1;
image_ci.arrayLayers = 1;
image_ci.extent = {8, 8, 8};
image_ci.imageType = VK_IMAGE_TYPE_3D;
image_ci.flags = VK_IMAGE_CREATE_2D_VIEW_COMPATIBLE_BIT_EXT;
vkt::Image image(*m_device, image_ci);
VkResourceDescriptorInfoEXT resource_desc_info = vku::InitStructHelper();
resource_desc_info.type = type;
VkImageViewCreateInfo image_view_ci = vku::InitStructHelper();
image_view_ci.viewType = VK_IMAGE_VIEW_TYPE_2D;
image_view_ci.format = image_ci.format;
image_view_ci.image = image;
image_view_ci.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
image_view_ci.components = {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A};
VkImageDescriptorInfoEXT image_info = vku::InitStructHelper();
image_info.pView = &image_view_ci;
image_info.layout = VK_IMAGE_LAYOUT_GENERAL;
resource_desc_info.data.pImage = &image_info;
auto data = std::make_unique<uint8_t[]>(static_cast<size_t>(size));
VkHostAddressRangeEXT descriptors = {data.get(), static_cast<size_t>(size)};
m_errorMonitor->SetDesiredError("VUID-VkResourceDescriptorInfoEXT-type-11424");
vk::WriteResourceDescriptorsEXT(device(), 1u, &resource_desc_info, &descriptors);
m_errorMonitor->VerifyFound();
}
}
TEST_F(NegativeDescriptorHeap, ImageType3DViewSampler2DViewOf3D) {
TEST_DESCRIPTION(
"Validate that input attachment cannot be a 3D image even if view type 2D and sampler2DViewOf3D feature is not enabled");
AddRequiredExtensions(VK_EXT_IMAGE_2D_VIEW_OF_3D_EXTENSION_NAME);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
const VkDescriptorType type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
const VkDeviceSize size = vk::GetPhysicalDeviceDescriptorSizeEXT(Gpu(), type);
if (size > 0) {
VkImageCreateInfo image_ci = vku::InitStructHelper();
image_ci.format = VK_FORMAT_R8G8B8A8_UNORM;
image_ci.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
image_ci.tiling = VK_IMAGE_TILING_OPTIMAL;
image_ci.samples = VK_SAMPLE_COUNT_1_BIT;
image_ci.mipLevels = 1;
image_ci.arrayLayers = 1;
image_ci.extent = {8, 8, 8};
image_ci.imageType = VK_IMAGE_TYPE_3D;
image_ci.flags = VK_IMAGE_CREATE_2D_VIEW_COMPATIBLE_BIT_EXT;
vkt::Image image(*m_device, image_ci);
VkResourceDescriptorInfoEXT resource_desc_info = vku::InitStructHelper();
resource_desc_info.type = type;
VkImageViewCreateInfo image_view_ci = vku::InitStructHelper();
image_view_ci.viewType = VK_IMAGE_VIEW_TYPE_2D;
image_view_ci.format = image_ci.format;
image_view_ci.image = image;
image_view_ci.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
image_view_ci.components = {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A};
VkImageDescriptorInfoEXT image_info = vku::InitStructHelper();
image_info.pView = &image_view_ci;
image_info.layout = VK_IMAGE_LAYOUT_GENERAL;
resource_desc_info.data.pImage = &image_info;
auto data = std::make_unique<uint8_t[]>(static_cast<size_t>(size));
VkHostAddressRangeEXT descriptors = {data.get(), static_cast<size_t>(size)};
m_errorMonitor->SetDesiredError("VUID-VkResourceDescriptorInfoEXT-type-11425");
vk::WriteResourceDescriptorsEXT(device(), 1u, &resource_desc_info, &descriptors);
m_errorMonitor->VerifyFound();
}
}
TEST_F(NegativeDescriptorHeap, ImageType3DView2DWithoutCompatibility) {
TEST_DESCRIPTION("Validate that image cannot be a 3D image if viewtype is 2D and no compatibility bit");
RETURN_IF_SKIP(InitBasicDescriptorHeap());
const VkDeviceSize size = vk::GetPhysicalDeviceDescriptorSizeEXT(Gpu(), VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT);
VkImageCreateInfo image_ci = vku::InitStructHelper();
image_ci.format = VK_FORMAT_R8G8B8A8_UNORM;
image_ci.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
image_ci.tiling = VK_IMAGE_TILING_OPTIMAL;
image_ci.samples = VK_SAMPLE_COUNT_1_BIT;
image_ci.mipLevels = 1;
image_ci.arrayLayers = 1;
image_ci.extent = {8, 8, 8};
image_ci.imageType = VK_IMAGE_TYPE_3D;
image_ci.flags = VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT;
vkt::Image image(*m_device, image_ci);
VkResourceDescriptorInfoEXT resource_desc_info = vku::InitStructHelper();
resource_desc_info.type = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
VkImageViewCreateInfo image_view_ci = vku::InitStructHelper();
image_view_ci.viewType = VK_IMAGE_VIEW_TYPE_2D;
image_view_ci.format = image_ci.format;
image_view_ci.image = image;
image_view_ci.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
image_view_ci.components = {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A};
VkImageDescriptorInfoEXT image_info = vku::InitStructHelper();
image_info.pView = &image_view_ci;
image_info.layout = VK_IMAGE_LAYOUT_GENERAL;
resource_desc_info.data.pImage = &image_info;
auto data = std::make_unique<uint8_t[]>(static_cast<size_t>(size));
VkHostAddressRangeEXT descriptors = {data.get(), static_cast<size_t>(size)};
m_errorMonitor->SetDesiredError("VUID-VkImageDescriptorInfoEXT-pView-11427");
m_errorMonitor->SetDesiredError("VUID-VkResourceDescriptorInfoEXT-type-11422");
vk::WriteResourceDescriptorsEXT(device(), 1u, &resource_desc_info, &descriptors);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDescriptorHeap, ImageTypeDepthStencilAttachment) {
TEST_DESCRIPTION("Validate that aspectMask contains depth or stencil if image is a depth stencil format");
RETURN_IF_SKIP(InitBasicDescriptorHeap());
const VkDeviceSize size = vk::GetPhysicalDeviceDescriptorSizeEXT(Gpu(), VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT);
auto ds_format = FindSupportedDepthStencilFormat(Gpu());
VkImageCreateInfo image_ci = vku::InitStructHelper();
image_ci.format = ds_format;
image_ci.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
image_ci.tiling = VK_IMAGE_TILING_OPTIMAL;
image_ci.samples = VK_SAMPLE_COUNT_1_BIT;
image_ci.mipLevels = 1;
image_ci.arrayLayers = 1;
image_ci.extent = {8, 8, 1};
image_ci.imageType = VK_IMAGE_TYPE_2D;
vkt::Image image(*m_device, image_ci);
VkResourceDescriptorInfoEXT resource_desc_info = vku::InitStructHelper();
resource_desc_info.type = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
VkImageViewCreateInfo image_view_ci = vku::InitStructHelper();
image_view_ci.viewType = VK_IMAGE_VIEW_TYPE_2D;
image_view_ci.format = image_ci.format;
image_view_ci.image = image;
image_view_ci.subresourceRange = {VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, 0, 1, 0, 1};
image_view_ci.components = {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A};
VkImageDescriptorInfoEXT image_info = vku::InitStructHelper();
image_info.pView = &image_view_ci;
image_info.layout = VK_IMAGE_LAYOUT_GENERAL;
resource_desc_info.data.pImage = &image_info;
auto data = std::make_unique<uint8_t[]>(static_cast<size_t>(size));
VkHostAddressRangeEXT descriptors = {data.get(), static_cast<size_t>(size)};
m_errorMonitor->SetDesiredError("VUID-VkImageDescriptorInfoEXT-pView-11430");
vk::WriteResourceDescriptorsEXT(device(), 1u, &resource_desc_info, &descriptors);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDescriptorHeap, PushDataRange) {
TEST_DESCRIPTION("Descriptor heap with VkPushDataInfoEXT but part of the range is missing");
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
const VkDeviceSize resource_stride = heap_props.bufferDescriptorSize;
const VkDeviceSize resource_descriptor_count = 1u;
const VkDeviceSize resource_heap_size_app = AlignResource(resource_descriptor_count);
const VkDeviceSize resource_heap_size = resource_heap_size_app + heap_props.minResourceHeapReservedRange;
vkt::Buffer descriptor_heap(*m_device, resource_heap_size, VK_BUFFER_USAGE_2_DESCRIPTOR_HEAP_BIT_EXT, vkt::device_address);
const auto descriptor_heap_ptr = static_cast<char*>(descriptor_heap.Memory().Map());
vkt::Buffer buffer(*m_device, 32, VK_BUFFER_USAGE_2_STORAGE_BUFFER_BIT_KHR, vkt::device_address);
VkHostAddressRangeEXT descriptor_host = {descriptor_heap_ptr, static_cast<size_t>(resource_stride)};
VkDeviceAddressRangeEXT device_range = {buffer.Address(), 16};
VkResourceDescriptorInfoEXT descriptor_info = vku::InitStructHelper();
descriptor_info.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
descriptor_info.data.pAddressRange = &device_range;
vk::WriteResourceDescriptorsEXT(*m_device, 1u, &descriptor_info, &descriptor_host);
VkDescriptorSetAndBindingMappingEXT mapping = MakeSetAndBindingMapping(0, 0);
mapping.source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT;
mapping.sourceData.constantOffset.heapOffset = 0;
mapping.sourceData.constantOffset.heapArrayStride = 0;
VkShaderDescriptorSetAndBindingMappingInfoEXT mapping_info = vku::InitStructHelper();
mapping_info.mappingCount = 1u;
mapping_info.pMappings = &mapping;
char const* cs_source = R"glsl(
#version 450
layout(local_size_x = 1) in;
layout(set = 0, binding = 0) buffer A { vec4 a; };
layout(push_constant) uniform PushConstant {
vec4 b;
};
void main() {
a = b;
}
)glsl";
VkShaderObj cs_module = VkShaderObj(*m_device, cs_source, VK_SHADER_STAGE_COMPUTE_BIT);
VkPipelineCreateFlags2CreateInfoKHR pipeline_create_flags_2_create_info = vku::InitStructHelper();
pipeline_create_flags_2_create_info.flags = VK_PIPELINE_CREATE_2_DESCRIPTOR_HEAP_BIT_EXT;
CreateComputePipelineHelper pipe(*this, &pipeline_create_flags_2_create_info);
pipe.cp_ci_.layout = VK_NULL_HANDLE;
pipe.cp_ci_.stage = cs_module.GetStageCreateInfo(&mapping_info);
pipe.CreateComputePipeline(false);
VkBindHeapInfoEXT bind_resource_info = vku::InitStructHelper();
bind_resource_info.heapRange = descriptor_heap.AddressRange();
bind_resource_info.reservedRangeOffset = resource_heap_size_app;
bind_resource_info.reservedRangeSize = heap_props.minResourceHeapReservedRange;
float src_data[4] = {1.0f, 2.0f, 3.0f, 4.0f};
VkPushDataInfoEXT push_data_info1 = vku::InitStructHelper();
push_data_info1.offset = 0u;
push_data_info1.data.size = 8u;
push_data_info1.data.address = src_data;
VkPushDataInfoEXT push_data_info2 = vku::InitStructHelper();
push_data_info2.offset = 12u;
push_data_info2.data.size = 4u;
push_data_info2.data.address = src_data;
// Set from 0-7 and 12-15, unset from 8-11
m_command_buffer.Begin();
vk::CmdBindResourceHeapEXT(m_command_buffer, &bind_resource_info);
vk::CmdPushDataEXT(m_command_buffer, &push_data_info1);
vk::CmdPushDataEXT(m_command_buffer, &push_data_info2);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDispatch-None-11376");
vk::CmdDispatch(m_command_buffer, 1, 1, 1);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
m_default_queue->SubmitAndWait(m_command_buffer);
push_data_info1.offset = 4u;
push_data_info1.data.size = 16u;
// Set from 4-19, unset from 0-3
m_command_buffer.Begin();
vk::CmdBindResourceHeapEXT(m_command_buffer, &bind_resource_info);
vk::CmdPushDataEXT(m_command_buffer, &push_data_info1);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDispatch-None-11376");
vk::CmdDispatch(m_command_buffer, 1, 1, 1);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
m_default_queue->SubmitAndWait(m_command_buffer);
push_data_info1.offset = 0u;
push_data_info1.data.size = 8u;
push_data_info2.offset = 4u;
push_data_info2.data.size = 8u;
VkPushDataInfoEXT push_data_info3 = vku::InitStructHelper();
push_data_info3.offset = 8u;
push_data_info3.data.size = 8u;
push_data_info3.data.address = src_data;
// Set multiple times with overlap
m_command_buffer.Begin();
vk::CmdBindResourceHeapEXT(m_command_buffer, &bind_resource_info);
vk::CmdPushDataEXT(m_command_buffer, &push_data_info1);
vk::CmdPushDataEXT(m_command_buffer, &push_data_info2);
vk::CmdPushDataEXT(m_command_buffer, &push_data_info3);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe);
vk::CmdDispatch(m_command_buffer, 1, 1, 1);
m_command_buffer.End();
m_default_queue->SubmitAndWait(m_command_buffer);
// Unset after command buffer reset
m_command_buffer.Begin();
vk::CmdBindResourceHeapEXT(m_command_buffer, &bind_resource_info);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDispatch-None-11376");
vk::CmdDispatch(m_command_buffer, 1, 1, 1);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
m_default_queue->SubmitAndWait(m_command_buffer);
push_data_info1.offset = 0u;
push_data_info1.data.size = 16u;
const std::vector<VkPushConstantRange> pc_range = {{VK_SHADER_STAGE_COMPUTE_BIT, 0, 16}};
vkt::PipelineLayout pipeline_layout(*m_device, {}, pc_range);
// Full range set, invalidated by vkCmdPushConstants, only part of the range set again
m_command_buffer.Begin();
vk::CmdBindResourceHeapEXT(m_command_buffer, &bind_resource_info);
vk::CmdPushDataEXT(m_command_buffer, &push_data_info1);
vk::CmdPushConstants(m_command_buffer, pipeline_layout, VK_SHADER_STAGE_COMPUTE_BIT, 0u, 16u, src_data);
push_data_info1.data.size = 8u;
vk::CmdBindResourceHeapEXT(m_command_buffer, &bind_resource_info);
vk::CmdPushDataEXT(m_command_buffer, &push_data_info1);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDispatch-None-11376");
vk::CmdDispatch(m_command_buffer, 1, 1, 1);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
m_default_queue->SubmitAndWait(m_command_buffer);
}
TEST_F(NegativeDescriptorHeap, NonConstantImageMemoryAccess) {
TEST_DESCRIPTION("Non constant image memory access with incompatible mapping source");
AddRequiredFeature(vkt::Feature::runtimeDescriptorArray);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
VkDescriptorSetAndBindingMappingEXT mappings[3];
mappings[0] = MakeSetAndBindingMapping(0, 0, 1, VK_SPIRV_RESOURCE_TYPE_SAMPLED_IMAGE_BIT_EXT);
mappings[0].source = VK_DESCRIPTOR_MAPPING_SOURCE_INDIRECT_ADDRESS_EXT;
mappings[0].sourceData.pushAddressOffset = 0;
mappings[1] = MakeSetAndBindingMapping(0, 1, 1, VK_SPIRV_RESOURCE_TYPE_SAMPLER_BIT_EXT);
mappings[1].source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT;
mappings[1].sourceData.constantOffset = {};
mappings[1].sourceData.constantOffset.heapOffset = 1024;
mappings[2] = MakeSetAndBindingMapping(1, 0);
mappings[2].source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT;
mappings[2].sourceData.constantOffset = {};
mappings[2].sourceData.constantOffset.heapOffset = 2048;
VkShaderDescriptorSetAndBindingMappingInfoEXT mapping_info = vku::InitStructHelper();
mapping_info.mappingCount = 3u;
mapping_info.pMappings = mappings;
char const* cs_source = R"glsl(
#version 450
#extension GL_EXT_nonuniform_qualifier : enable
layout(set = 0, binding = 0) uniform texture2D tex[];
layout(set = 0, binding = 1) uniform sampler sampl;
layout(set = 1, binding = 0) buffer ssbo {
uint index;
vec4 data;
};
void main() {
data = texture(sampler2D(tex[index], sampl), vec2(0.5f));
}
)glsl";
VkShaderObj cs_module = VkShaderObj(*m_device, cs_source, VK_SHADER_STAGE_COMPUTE_BIT);
VkPipelineCreateFlags2CreateInfoKHR flags2_ci = vku::InitStructHelper();
flags2_ci.flags = VK_PIPELINE_CREATE_2_DESCRIPTOR_HEAP_BIT_EXT;
CreateComputePipelineHelper pipe(*this, &flags2_ci);
pipe.cp_ci_.layout = VK_NULL_HANDLE;
pipe.cp_ci_.stage = cs_module.GetStageCreateInfo(&mapping_info);
m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-DescriptorSet-11385");
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDescriptorHeap, ArrayLengthOnMappingSourceAddress) {
TEST_DESCRIPTION("OpArrayLength instruction on incompatible mapping source type");
RETURN_IF_SKIP(InitBasicDescriptorHeap());
VkDescriptorSetAndBindingMappingEXT mapping = MakeSetAndBindingMapping(0, 0);
mapping.source = VK_DESCRIPTOR_MAPPING_SOURCE_PUSH_ADDRESS_EXT;
mapping.sourceData.pushAddressOffset = 0u;
VkShaderDescriptorSetAndBindingMappingInfoEXT mapping_info = vku::InitStructHelper();
mapping_info.mappingCount = 1u;
mapping_info.pMappings = &mapping;
char const* cs_source = R"glsl(
#version 450
layout(local_size_x = 1) in;
layout(set = 0, binding = 0) buffer Data { uint data[]; };
void main() {
data[0] = data.length();
}
)glsl";
VkShaderObj cs_module = VkShaderObj(*m_device, cs_source, VK_SHADER_STAGE_COMPUTE_BIT);
VkPipelineCreateFlags2CreateInfoKHR flags2_ci = vku::InitStructHelper();
flags2_ci.flags = VK_PIPELINE_CREATE_2_DESCRIPTOR_HEAP_BIT_EXT;
CreateComputePipelineHelper pipe(*this, &flags2_ci);
pipe.cp_ci_.layout = VK_NULL_HANDLE;
pipe.cp_ci_.stage = cs_module.GetStageCreateInfo(&mapping_info);
m_errorMonitor->SetDesiredError("VUID-VkPipelineShaderStageCreateInfo-pNext-11378");
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDescriptorHeap, SamplerAllocationCount) {
SetTargetApiVersion(VK_API_VERSION_1_3);
AddRequiredExtensions(VK_EXT_DESCRIPTOR_HEAP_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::descriptorHeap);
RETURN_IF_SKIP(InitFramework());
const int max_samplers = 8;
VkSampler samplers[max_samplers + 1] = {};
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.maxSamplerAllocationCount > max_samplers) {
props.limits.maxSamplerAllocationCount = max_samplers;
fpvkSetPhysicalDeviceLimitsEXT(Gpu(), &props.limits);
}
RETURN_IF_SKIP(InitState());
GetPhysicalDeviceProperties2(heap_props);
if (heap_props.minSamplerHeapReservedRangeWithEmbedded == 0) {
GTEST_SKIP() << "minSamplerHeapReservedRangeWithEmbedded is 0";
}
if (heap_props.minSamplerHeapReservedRangeWithEmbedded / heap_props.samplerDescriptorSize > max_samplers) {
GTEST_SKIP() << "minSamplerHeapReservedRangeWithEmbedded / samplerDescriptorSize is too large";
}
VkSamplerCreateInfo embedded_sampler = vku::InitStructHelper();
VkDescriptorSetAndBindingMappingEXT mapping = MakeSetAndBindingMapping(0, 0, 1, VK_SPIRV_RESOURCE_TYPE_READ_ONLY_IMAGE_BIT_EXT);
mapping.source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT;
mapping.sourceData.constantOffset.pEmbeddedSampler = &embedded_sampler;
VkShaderDescriptorSetAndBindingMappingInfoEXT mapping_info = vku::InitStructHelper();
mapping_info.mappingCount = 1;
mapping_info.pMappings = &mapping;
VkPipelineCreateFlags2CreateInfoKHR flags2_ci = vku::InitStructHelper();
flags2_ci.flags = VK_PIPELINE_CREATE_2_DESCRIPTOR_HEAP_BIT_EXT;
CreateComputePipelineHelper pipe(*this, &flags2_ci);
pipe.LateBindPipelineInfo();
pipe.cp_ci_.layout = VK_NULL_HANDLE;
pipe.cp_ci_.stage.pNext = &mapping_info;
pipe.CreateComputePipeline(false);
m_errorMonitor->SetDesiredError("VUID-vkCreateSampler-maxSamplerAllocationCount-11412");
VkSamplerCreateInfo sampler_create_info = SafeSaneSamplerCreateInfo();
VkResult err = VK_SUCCESS;
int i;
for (i = 0; i < max_samplers; i++) {
err = vk::CreateSampler(device(), &sampler_create_info, NULL, &samplers[i]);
if (err != VK_SUCCESS) {
break;
}
}
m_errorMonitor->VerifyFound();
for (int j = 0; j < i; j++) {
vk::DestroySampler(device(), samplers[j], NULL);
}
}
TEST_F(NegativeDescriptorHeap, SamplerAllocationCountPipeline) {
SetTargetApiVersion(VK_API_VERSION_1_3);
RETURN_IF_SKIP(InitFramework());
const int max_samplers = 8;
VkSampler samplers[max_samplers + 1] = {};
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.maxSamplerAllocationCount > max_samplers) {
props.limits.maxSamplerAllocationCount = max_samplers;
fpvkSetPhysicalDeviceLimitsEXT(Gpu(), &props.limits);
}
RETURN_IF_SKIP(InitState());
GetPhysicalDeviceProperties2(heap_props);
if (heap_props.minSamplerHeapReservedRangeWithEmbedded == 0) {
GTEST_SKIP() << "minSamplerHeapReservedRangeWithEmbedded is 0";
}
if (heap_props.minSamplerHeapReservedRangeWithEmbedded / heap_props.samplerDescriptorSize > max_samplers) {
GTEST_SKIP() << "minSamplerHeapReservedRangeWithEmbedded / samplerDescriptorSize is too large";
}
VkSamplerCreateInfo sampler_create_info = SafeSaneSamplerCreateInfo();
VkResult err = VK_SUCCESS;
int i;
for (i = 0; i < max_samplers; i++) {
err = vk::CreateSampler(device(), &sampler_create_info, NULL, &samplers[i]);
if (err != VK_SUCCESS) {
break;
}
}
m_errorMonitor->SetDesiredError("VUID-vkCreateComputePipelines-pCreateInfos-11414");
VkSamplerCreateInfo embedded_sampler = vku::InitStructHelper();
VkDescriptorSetAndBindingMappingEXT mapping = MakeSetAndBindingMapping(0, 0, 1, VK_SPIRV_RESOURCE_TYPE_READ_ONLY_IMAGE_BIT_EXT);
mapping.source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT;
mapping.sourceData.constantOffset.pEmbeddedSampler = &embedded_sampler;
VkShaderDescriptorSetAndBindingMappingInfoEXT mapping_info = vku::InitStructHelper();
mapping_info.mappingCount = 1;
mapping_info.pMappings = &mapping;
VkPipelineCreateFlags2CreateInfo pipeline_create_flags_2_create_info = vku::InitStructHelper();
pipeline_create_flags_2_create_info.flags = VK_PIPELINE_CREATE_2_DESCRIPTOR_HEAP_BIT_EXT;
CreateComputePipelineHelper pipe(*this, &pipeline_create_flags_2_create_info);
pipe.LateBindPipelineInfo();
pipe.cp_ci_.layout = VK_NULL_HANDLE;
pipe.cp_ci_.stage.pNext = &mapping_info;
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
for (int j = 0; j < i; j++) {
vk::DestroySampler(device(), samplers[j], NULL);
}
}
TEST_F(NegativeDescriptorHeap, SamplerAllocationCountShaderObject) {
SetTargetApiVersion(VK_API_VERSION_1_3);
AddRequiredExtensions(VK_EXT_SHADER_OBJECT_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::shaderObject);
RETURN_IF_SKIP(InitFramework());
const int max_samplers = 8;
VkSampler samplers[max_samplers + 1] = {};
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.maxSamplerAllocationCount > max_samplers) {
props.limits.maxSamplerAllocationCount = max_samplers;
fpvkSetPhysicalDeviceLimitsEXT(Gpu(), &props.limits);
}
RETURN_IF_SKIP(InitState());
GetPhysicalDeviceProperties2(heap_props);
if (heap_props.minSamplerHeapReservedRangeWithEmbedded == 0) {
GTEST_SKIP() << "minSamplerHeapReservedRangeWithEmbedded is 0";
}
if (heap_props.minSamplerHeapReservedRangeWithEmbedded / heap_props.samplerDescriptorSize > max_samplers) {
GTEST_SKIP() << "minSamplerHeapReservedRangeWithEmbedded / samplerDescriptorSize is too large";
}
VkSamplerCreateInfo sampler_create_info = SafeSaneSamplerCreateInfo();
VkResult err = VK_SUCCESS;
int i;
for (i = 0; i < max_samplers; i++) {
err = vk::CreateSampler(device(), &sampler_create_info, NULL, &samplers[i]);
if (err != VK_SUCCESS) {
break;
}
}
VkSamplerCreateInfo embedded_sampler = vku::InitStructHelper();
VkDescriptorSetAndBindingMappingEXT mapping = MakeSetAndBindingMapping(0, 0, 1, VK_SPIRV_RESOURCE_TYPE_READ_ONLY_IMAGE_BIT_EXT);
mapping.source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT;
mapping.sourceData.constantOffset.pEmbeddedSampler = &embedded_sampler;
VkShaderDescriptorSetAndBindingMappingInfoEXT mapping_info = vku::InitStructHelper();
mapping_info.mappingCount = 1;
mapping_info.pMappings = &mapping;
const auto vert_spv = GLSLToSPV(VK_SHADER_STAGE_VERTEX_BIT, kVertexMinimalGlsl);
const VkShaderCreateFlagsEXT flags = VK_SHADER_CREATE_DESCRIPTOR_HEAP_BIT_EXT;
VkShaderCreateInfoEXT vert_ci = ShaderCreateInfoFlag(vert_spv, VK_SHADER_STAGE_VERTEX_BIT, flags);
vert_ci.pNext = &mapping_info;
m_errorMonitor->SetDesiredError("VUID-vkCreateShadersEXT-pCreateInfos-11413");
const vkt::Shader vertShader(*m_device, vert_ci);
m_errorMonitor->VerifyFound();
for (int j = 0; j < i; j++) {
vk::DestroySampler(device(), samplers[j], NULL);
}
}
TEST_F(NegativeDescriptorHeap, MaxEmbeddedSamplers) {
RETURN_IF_SKIP(InitBasicDescriptorHeap());
const size_t max_samplers = heap_props.maxDescriptorHeapEmbeddedSamplers;
if (max_samplers > 2048) {
GTEST_SKIP() << "maxDescriptorHeapEmbeddedSamplers too large to run the test";
}
VkSamplerCreateInfo embedded_sampler = vku::InitStructHelper();
VkDescriptorSetAndBindingMappingEXT mapping;
mapping = MakeSetAndBindingMapping(0, 0, 1, VK_SPIRV_RESOURCE_TYPE_READ_ONLY_IMAGE_BIT_EXT);
mapping.source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT;
mapping.sourceData.constantOffset.pEmbeddedSampler = &embedded_sampler;
VkShaderDescriptorSetAndBindingMappingInfoEXT mapping_info = vku::InitStructHelper();
mapping_info.mappingCount = 1u;
mapping_info.pMappings = &mapping;
VkPipelineCreateFlags2CreateInfo pipeline_create_flags_2_create_info = vku::InitStructHelper();
pipeline_create_flags_2_create_info.flags = VK_PIPELINE_CREATE_2_DESCRIPTOR_HEAP_BIT_EXT;
std::vector<CreateComputePipelineHelper> pipes(max_samplers + 1);
for (size_t i = 0; i < max_samplers; i++) {
pipes[i] = CreateComputePipelineHelper(*this, &pipeline_create_flags_2_create_info);
pipes[i].LateBindPipelineInfo();
pipes[i].cp_ci_.layout = VK_NULL_HANDLE;
pipes[i].cp_ci_.stage.pNext = &mapping_info;
pipes[i].CreateComputePipeline(false);
}
pipes[max_samplers] = CreateComputePipelineHelper(*this, &pipeline_create_flags_2_create_info);
pipes[max_samplers].LateBindPipelineInfo();
pipes[max_samplers].cp_ci_.layout = VK_NULL_HANDLE;
pipes[max_samplers].cp_ci_.stage.pNext = &mapping_info;
m_errorMonitor->SetDesiredError("VUID-vkCreateComputePipelines-pCreateInfos-11429");
pipes[max_samplers].CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDescriptorHeap, PipelineLayoutNotNull) {
AddRequiredExtensions(VK_KHR_SHADER_UNTYPED_POINTERS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::shaderUntypedPointers);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
char const* cs_source = R"glsl(
#version 450
#extension GL_EXT_descriptor_heap : require
layout(local_size_x = 1) in;
layout(descriptor_heap) buffer A { uint a; } heap[];
void main() {
heap[0].a = 0;
}
)glsl";
CreateComputePipelineHelper pipe(*this);
pipe.cs_ = VkShaderObj(*m_device, cs_source, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_3);
pipe.dsl_bindings_ = {{0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_COMPUTE_BIT, nullptr}};
m_errorMonitor->SetDesiredError("VUID-VkComputePipelineCreateInfo-layout-07988");
pipe.CreateComputePipeline();
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDescriptorHeap, SamplerAllocationTotalCountShaderObject) {
AddRequiredExtensions(VK_EXT_SHADER_OBJECT_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::shaderObject);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
const size_t max_samplers = heap_props.maxDescriptorHeapEmbeddedSamplers;
if (heap_props.maxDescriptorHeapEmbeddedSamplers > 2048) {
GTEST_SKIP() << "maxDescriptorHeapEmbeddedSamplers too large to run the test";
}
VkSamplerCreateInfo embedded_sampler = vku::InitStructHelper();
VkDescriptorSetAndBindingMappingEXT mapping;
mapping = MakeSetAndBindingMapping(0, 0, 1, VK_SPIRV_RESOURCE_TYPE_READ_ONLY_IMAGE_BIT_EXT);
mapping.source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT;
mapping.sourceData.constantOffset.pEmbeddedSampler = &embedded_sampler;
VkShaderDescriptorSetAndBindingMappingInfoEXT mapping_info = vku::InitStructHelper();
mapping_info.mappingCount = 1u;
mapping_info.pMappings = &mapping;
const auto vert_spv = GLSLToSPV(VK_SHADER_STAGE_VERTEX_BIT, kVertexMinimalGlsl);
const VkShaderCreateFlagsEXT flags = VK_SHADER_CREATE_DESCRIPTOR_HEAP_BIT_EXT;
VkShaderCreateInfoEXT vert_ci = ShaderCreateInfoFlag(vert_spv, VK_SHADER_STAGE_VERTEX_BIT, flags);
vert_ci.pNext = &mapping_info;
std::vector<vkt::Shader*> shaders(max_samplers + 1);
for (size_t i = 0; i < max_samplers; i++) {
shaders[i] = new vkt::Shader(*m_device, vert_ci);
}
m_errorMonitor->SetDesiredError("VUID-vkCreateShadersEXT-pCreateInfos-11428");
shaders[max_samplers] = new vkt::Shader(*m_device, vert_ci);
m_errorMonitor->VerifyFound();
for (size_t i = 0; i < max_samplers + 1; i++) {
delete shaders[i];
}
}
TEST_F(NegativeDescriptorHeap, NonConstantMemoryAccess) {
AddRequiredFeature(vkt::Feature::runtimeDescriptorArray);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
VkDescriptorSetAndBindingMappingEXT mappings[2];
mappings[0] = MakeSetAndBindingMapping(0, 0);
mappings[0].source = VK_DESCRIPTOR_MAPPING_SOURCE_PUSH_ADDRESS_EXT;
mappings[0].sourceData.pushAddressOffset = 0u;
mappings[1] = MakeSetAndBindingMapping(0, 1);
mappings[1].source = VK_DESCRIPTOR_MAPPING_SOURCE_PUSH_ADDRESS_EXT;
mappings[1].sourceData.pushAddressOffset = 8u;
VkShaderDescriptorSetAndBindingMappingInfoEXT mapping_info = vku::InitStructHelper();
mapping_info.mappingCount = 2u;
mapping_info.pMappings = mappings;
char const* cs_source1 = R"glsl(
#version 450
#extension GL_EXT_nonuniform_qualifier : enable
layout(local_size_x = 1) in;
layout(set = 0, binding = 0) uniform Index {
uint index;
};
layout(set = 0, binding = 1) buffer Data {
uint data[];
} ssbos[];
void main() {
ssbos[index].data[4] = 4u;
}
)glsl";
char const* cs_source2 = R"glsl(
#version 450
#extension GL_EXT_nonuniform_qualifier : enable
layout(local_size_x = 1) in;
layout(set = 0, binding = 0) uniform Index {
uint index;
};
layout(set = 0, binding = 1) buffer Data {
uint data[];
} ssbos[];
void main() {
ssbos[index].data[index] = 4u;
}
)glsl";
for (uint32_t i = 0; i < 2; ++i) {
VkShaderObj cs_module = VkShaderObj(*m_device, i == 0 ? cs_source1 : cs_source2, VK_SHADER_STAGE_COMPUTE_BIT);
VkPipelineCreateFlags2CreateInfoKHR flags2_ci = vku::InitStructHelper();
flags2_ci.flags = VK_PIPELINE_CREATE_2_DESCRIPTOR_HEAP_BIT_EXT;
CreateComputePipelineHelper pipe(*this, &flags2_ci);
pipe.cp_ci_.layout = VK_NULL_HANDLE;
pipe.cp_ci_.stage = cs_module.GetStageCreateInfo(&mapping_info);
m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-DescriptorSet-11385");
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
}
TEST_F(NegativeDescriptorHeap, ResourceHeapNotBound) {
AddRequiredExtensions(VK_KHR_SHADER_UNTYPED_POINTERS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::shaderUntypedPointers);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
vkt::Buffer buffer_a(*m_device, 32, VK_BUFFER_USAGE_2_STORAGE_BUFFER_BIT_KHR, vkt::device_address);
VkDescriptorSetAndBindingMappingEXT mapping = MakeSetAndBindingMapping(0, 0);
mapping.source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT;
mapping.sourceData.constantOffset.heapOffset = 0;
mapping.sourceData.constantOffset.heapArrayStride = 0;
VkShaderDescriptorSetAndBindingMappingInfoEXT mapping_info = vku::InitStructHelper();
mapping_info.mappingCount = 1u;
mapping_info.pMappings = &mapping;
char const* cs_source = R"glsl(
#version 450
#extension GL_EXT_descriptor_heap : require
layout(local_size_x = 1) in;
layout(descriptor_heap) buffer A { uint a; } heap[];
void main() {
heap[73].a = 2;
}
)glsl";
VkShaderObj cs_module = VkShaderObj(*m_device, cs_source, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_2);
VkPipelineCreateFlags2CreateInfoKHR pipeline_create_flags_2_create_info = vku::InitStructHelper();
pipeline_create_flags_2_create_info.flags = VK_PIPELINE_CREATE_2_DESCRIPTOR_HEAP_BIT_EXT;
CreateComputePipelineHelper pipe(*this, &pipeline_create_flags_2_create_info);
pipe.cp_ci_.layout = VK_NULL_HANDLE;
pipe.cp_ci_.stage = cs_module.GetStageCreateInfo(&mapping_info);
pipe.CreateComputePipeline(false);
m_command_buffer.Begin();
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDispatch-None-11308");
vk::CmdDispatch(m_command_buffer, 1, 1, 1);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeDescriptorHeap, SamplerHeapNotBound) {
AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_SHADER_UNTYPED_POINTERS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
AddRequiredFeature(vkt::Feature::shaderUntypedPointers);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
InitRenderTarget();
const uint32_t buffer_index = 16u;
VkDeviceSize resource_heap_tracker = 0u;
const VkDeviceSize image_offset = AlignedAppend(resource_heap_tracker, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
const VkDeviceSize image_size = resource_heap_tracker - image_offset;
const VkDeviceSize buffer_offset = sizeof(float) * 4u * buffer_index;
const VkDeviceSize buffer_size = resource_heap_tracker - buffer_offset + 256; // 256 padding
const VkDeviceSize resource_heap_app_size = resource_heap_tracker;
CreateResourceHeap(resource_heap_app_size);
vkt::Buffer buffer(*m_device, sizeof(float) * 4u, VK_BUFFER_USAGE_2_STORAGE_BUFFER_BIT_KHR, vkt::device_address);
vkt::Image image(*m_device, 32u, 32u, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
VkHostAddressRangeEXT resource_host[2];
resource_host[0].address = resource_heap_data_ + image_offset;
resource_host[0].size = static_cast<size_t>(image_size);
resource_host[1].address = resource_heap_data_ + buffer_offset;
resource_host[1].size = static_cast<size_t>(buffer_size);
VkImageViewCreateInfo view_info = image.BasicViewCreatInfo(VK_IMAGE_ASPECT_COLOR_BIT);
VkImageDescriptorInfoEXT image_info = vku::InitStructHelper();
image_info.pView = &view_info;
image_info.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
VkDeviceAddressRangeEXT buffer_address_range = buffer.AddressRange();
VkResourceDescriptorInfoEXT descriptor_info[2];
descriptor_info[0] = vku::InitStructHelper();
descriptor_info[0].type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
descriptor_info[0].data.pImage = &image_info;
descriptor_info[1] = vku::InitStructHelper();
descriptor_info[1].type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
descriptor_info[1].data.pAddressRange = &buffer_address_range;
vk::WriteResourceDescriptorsEXT(*m_device, 2u, descriptor_info, resource_host);
VkDeviceSize sampler_desc_heap_size_tracker = 0u;
const VkDeviceSize sampler_offset = AlignedAppend(sampler_desc_heap_size_tracker, VK_DESCRIPTOR_TYPE_SAMPLER);
const VkDeviceSize sampler_size = sampler_desc_heap_size_tracker - sampler_offset;
CreateSamplerHeap(sampler_desc_heap_size_tracker);
VkSamplerCreateInfo sampler_info = SafeSaneSamplerCreateInfo();
VkHostAddressRangeEXT sampler_host = {sampler_heap_data_ + sampler_offset, static_cast<size_t>(sampler_size)};
vk::WriteSamplerDescriptorsEXT(*m_device, 1u, &sampler_info, &sampler_host);
char const* cs_source = R"glsl(
#version 450
#extension GL_EXT_descriptor_heap : require
layout(descriptor_heap) uniform texture2D heapTextures[];
layout(descriptor_heap) uniform sampler heapSamplers[];
layout(descriptor_heap) buffer ssbo {
vec4 data;
} heapBuffer[];
void main() {
heapBuffer[16].data = texture(sampler2D(heapTextures[0], heapSamplers[0]), vec2(0.5f));
}
)glsl";
VkShaderObj cs_module = VkShaderObj(*m_device, cs_source, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_2);
VkPipelineCreateFlags2CreateInfoKHR pipeline_create_flags_2_create_info = vku::InitStructHelper();
pipeline_create_flags_2_create_info.flags = VK_PIPELINE_CREATE_2_DESCRIPTOR_HEAP_BIT_EXT;
CreateComputePipelineHelper pipe(*this, &pipeline_create_flags_2_create_info);
pipe.cp_ci_.layout = VK_NULL_HANDLE;
pipe.cp_ci_.stage = cs_module.GetStageCreateInfo();
pipe.CreateComputePipeline(false);
m_command_buffer.Begin();
VkImageMemoryBarrier image_barrier = vku::InitStructHelper();
image_barrier.srcAccessMask = VK_ACCESS_NONE;
image_barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
image_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
image_barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
image_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
image_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
image_barrier.image = image;
image_barrier.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u};
vk::CmdPipelineBarrier(m_command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u,
nullptr, 1u, &image_barrier);
VkClearColorValue color = {};
color.float32[0] = 0.2f;
color.float32[1] = 0.4f;
color.float32[2] = 0.6f;
color.float32[3] = 0.8f;
vk::CmdClearColorImage(m_command_buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &color, 1u,
&image_barrier.subresourceRange);
image_barrier.srcAccessMask = image_barrier.dstAccessMask;
image_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
image_barrier.oldLayout = image_barrier.newLayout;
image_barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
vk::CmdPipelineBarrier(m_command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u, 0u, nullptr,
0u, nullptr, 1u, &image_barrier);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe);
BindResourceHeap();
m_errorMonitor->SetDesiredError("VUID-vkCmdDispatch-None-11308");
vk::CmdDispatch(m_command_buffer, 1u, 1u, 1u);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeDescriptorHeap, UsagesValidation) {
TEST_DESCRIPTION("Tests that buffers and images were created with appropriate usage flags");
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
{
std::vector<uint8_t> data(static_cast<size_t>(heap_props.imageDescriptorSize));
vkt::Image image(*m_device, 32, 32, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
struct {
VkDescriptorType type;
const char* vuid;
} tests[] = {
{VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, "VUID-VkResourceDescriptorInfoEXT-type-11458"},
{VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, "VUID-VkResourceDescriptorInfoEXT-type-11459"},
{VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, "VUID-VkResourceDescriptorInfoEXT-type-11460"},
};
for (const auto test : tests) {
VkResourceDescriptorInfoEXT resource_desc_info = vku::InitStructHelper();
resource_desc_info.type = test.type;
VkImageViewCreateInfo image_view_ci = vku::InitStructHelper();
image_view_ci.image = image;
image_view_ci.viewType = VK_IMAGE_VIEW_TYPE_2D;
image_view_ci.format = image.CreateInfo().format;
image_view_ci.components = {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B,
VK_COMPONENT_SWIZZLE_A};
image_view_ci.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
VkImageDescriptorInfoEXT image_info = vku::InitStructHelper();
image_info.pView = &image_view_ci;
image_info.layout = VK_IMAGE_LAYOUT_GENERAL;
resource_desc_info.data.pImage = &image_info;
VkHostAddressRangeEXT descriptors = {data.data(), data.size()};
m_errorMonitor->SetDesiredError(test.vuid);
vk::WriteResourceDescriptorsEXT(device(), 1u, &resource_desc_info, &descriptors);
m_errorMonitor->VerifyFound();
}
}
{
const VkDeviceSize buffer_size = 256;
vkt::Buffer buffer(*m_device, buffer_size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, vkt::device_address);
VkDeviceAddressRangeEXT address_range = buffer.AddressRange();
VkResourceDescriptorInfoEXT desc_info = vku::InitStructHelper();
desc_info.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
desc_info.data.pAddressRange = &address_range;
VkHostAddressRangeEXT descriptors = {&desc_info, static_cast<size_t>(heap_props.bufferDescriptorSize)};
m_errorMonitor->SetDesiredError("VUID-VkResourceDescriptorInfoEXT-type-11461");
vk::WriteResourceDescriptorsEXT(device(), 1u, &desc_info, &descriptors);
m_errorMonitor->VerifyFound();
desc_info.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
m_errorMonitor->SetDesiredError("VUID-VkResourceDescriptorInfoEXT-type-11462");
vk::WriteResourceDescriptorsEXT(device(), 1u, &desc_info, &descriptors);
m_errorMonitor->VerifyFound();
}
{
const VkDeviceSize buffer_size = 256;
vkt::Buffer buffer(*m_device, buffer_size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, vkt::device_address);
VkTexelBufferDescriptorInfoEXT texel_buffer_info = vku::InitStructHelper();
texel_buffer_info.format = VK_FORMAT_R8G8B8A8_UNORM;
texel_buffer_info.addressRange.address = buffer.Address();
texel_buffer_info.addressRange.size = buffer_size;
VkResourceDescriptorInfoEXT desc_info = vku::InitStructHelper();
desc_info.type = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
desc_info.data.pTexelBuffer = &texel_buffer_info;
VkHostAddressRangeEXT descriptors = {&desc_info, static_cast<size_t>(heap_props.imageDescriptorSize)};
m_errorMonitor->SetDesiredError("VUID-VkResourceDescriptorInfoEXT-type-11463");
vk::WriteResourceDescriptorsEXT(device(), 1u, &desc_info, &descriptors);
m_errorMonitor->VerifyFound();
desc_info.type = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
m_errorMonitor->SetDesiredError("VUID-VkResourceDescriptorInfoEXT-type-11464");
vk::WriteResourceDescriptorsEXT(device(), 1u, &desc_info, &descriptors);
m_errorMonitor->VerifyFound();
}
}
TEST_F(NegativeDescriptorHeap, InputAttachmentIsNotNull) {
TEST_DESCRIPTION("Validate VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT cannot be nullDescriptor");
AddRequiredFeature(vkt::Feature::nullDescriptor);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
const VkDescriptorType type = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
const VkDeviceSize size = vk::GetPhysicalDeviceDescriptorSizeEXT(Gpu(), type);
if (size > 0) {
std::vector<uint8_t> data(static_cast<size_t>(size));
VkResourceDescriptorInfoEXT resource_desc_info = vku::InitStructHelper();
resource_desc_info.type = type;
VkHostAddressRangeEXT descriptors = {data.data(), static_cast<size_t>(size)};
m_errorMonitor->SetDesiredError("VUID-VkResourceDescriptorInfoEXT-type-11469");
vk::WriteResourceDescriptorsEXT(device(), 1u, &resource_desc_info, &descriptors);
m_errorMonitor->VerifyFound();
}
}
TEST_F(NegativeDescriptorHeap, MappedPushIsBlockUniformArray) {
TEST_DESCRIPTION("Validate that mapped push data is backed by block uniform");
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
VkDescriptorSetAndBindingMappingEXT mappings = MakeSetAndBindingMapping(0, 0);
mappings.source = VK_DESCRIPTOR_MAPPING_SOURCE_PUSH_DATA_EXT;
VkShaderDescriptorSetAndBindingMappingInfoEXT mapping_info = vku::InitStructHelper();
mapping_info.mappingCount = 1;
mapping_info.pMappings = &mappings;
VkPipelineCreateFlags2CreateInfo pipeline_create_flags_2_create_info = vku::InitStructHelper();
pipeline_create_flags_2_create_info.flags = VK_PIPELINE_CREATE_2_DESCRIPTOR_HEAP_BIT_EXT;
const char* cs_source = R"glsl(
#version 450
layout(local_size_x = 1) in;
layout(set = 0, binding = 0) uniform Output {
uvec4 x[2];
} y[2];
void main() {
uvec4 a = y[0].x[0];
uvec4 b = y[1].x[0];
}
)glsl";
VkShaderObj cs_module = VkShaderObj(*m_device, cs_source, VK_SHADER_STAGE_COMPUTE_BIT);
CreateComputePipelineHelper pipe(*this, &pipeline_create_flags_2_create_info);
pipe.cp_ci_.layout = VK_NULL_HANDLE;
pipe.cp_ci_.stage = cs_module.GetStageCreateInfo(&mapping_info);
m_errorMonitor->SetDesiredError("VUID-VkPipelineShaderStageCreateInfo-pNext-11315");
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDescriptorHeap, InvalidateComputeBoundDescriptorSetsBindDescriptorSets) {
TEST_DESCRIPTION("Descriptor heap cmd functions do reset previously bound with CmdBindDescriptorSets descriptor sets");
AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
const char* cs_source = R"glsl(
#version 450
layout(set=0, binding=0) buffer SSBO { uint x; };
void main() { x = 0; }
)glsl";
for (int i = 0; i < 3; i++) {
const auto ds_type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
OneOffDescriptorSet ds(m_device, {{0, ds_type, 1, VK_SHADER_STAGE_COMPUTE_BIT, nullptr}}, 0, nullptr);
const vkt::PipelineLayout pipeline_layout(*m_device, {&ds.layout_});
vkt::Buffer buffer(*m_device, 32, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
VkDescriptorBufferInfo buffer_info{buffer, 0, VK_WHOLE_SIZE};
VkWriteDescriptorSet descriptor_write = vku::InitStructHelper();
descriptor_write.dstSet = ds.set_;
descriptor_write.dstBinding = 0;
descriptor_write.descriptorCount = 1;
descriptor_write.descriptorType = ds_type;
descriptor_write.pBufferInfo = &buffer_info;
vk::UpdateDescriptorSets(device(), 1, &descriptor_write, 0, nullptr);
CreateComputePipelineHelper pipe(*this);
pipe.cs_ = VkShaderObj(*m_device, cs_source, VK_SHADER_STAGE_COMPUTE_BIT);
pipe.cp_ci_.layout = pipeline_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, pipeline_layout, 0, 1, &ds.set_, 0, nullptr);
// The following descriptor heap-based command invalidates previously bound descriptor set and causes an error in
// CmdDispatch
if (i == 0) {
CreateResourceHeap(heap_props.bufferDescriptorSize);
BindResourceHeap();
} else if (i == 1) {
CreateSamplerHeap(heap_props.samplerDescriptorSize);
BindSamplerHeap();
} else {
std::vector<uint8_t> payload(static_cast<size_t>(heap_props.maxPushDataSize / 2));
VkPushDataInfoEXT push_data_info = vku::InitStructHelper();
push_data_info.data.address = payload.data();
push_data_info.data.size = payload.size();
push_data_info.offset = 0;
vk::CmdPushDataEXT(m_command_buffer, &push_data_info);
}
m_errorMonitor->SetDesiredError("VUID-vkCmdDispatch-None-08600");
vk::CmdDispatch(m_command_buffer, 1, 1, 1);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
}
TEST_F(NegativeDescriptorHeap, InvalidateComputeBoundDescriptorSetsPushDescriptor) {
TEST_DESCRIPTION("Descriptor heap cmd functions do reset previously bound with CmdPushDataEXT descriptor sets");
AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
AddRequiredExtensions(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
const char* cs_source = R"glsl(
#version 450
layout(set=0, binding=0) buffer SSBO { uint x; };
void main() { x = 0; }
)glsl";
for (int i = 0; i < 3; i++) {
const auto ds_type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
OneOffDescriptorSet ds(m_device, {{0, ds_type, 1, VK_SHADER_STAGE_COMPUTE_BIT, nullptr}},
VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT);
const vkt::PipelineLayout pipeline_layout(*m_device, {&ds.layout_});
vkt::Buffer buffer(*m_device, 32, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
VkDescriptorBufferInfo buffer_info{buffer, 0, VK_WHOLE_SIZE};
VkWriteDescriptorSet descriptor_write = vku::InitStructHelper();
descriptor_write.dstSet = ds.set_;
descriptor_write.dstBinding = 0;
descriptor_write.descriptorCount = 1;
descriptor_write.descriptorType = ds_type;
descriptor_write.pBufferInfo = &buffer_info;
CreateComputePipelineHelper pipe(*this);
pipe.cs_ = VkShaderObj(*m_device, cs_source, VK_SHADER_STAGE_COMPUTE_BIT);
pipe.cp_ci_.layout = pipeline_layout;
pipe.CreateComputePipeline();
m_command_buffer.Begin();
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe);
vk::CmdPushDescriptorSetKHR(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_layout, 0u, 1u, &descriptor_write);
// The following descriptor heap-based command invalidates previously bound descriptor set and causes an error
if (i == 0) {
CreateResourceHeap(heap_props.bufferDescriptorSize);
BindResourceHeap();
} else if (i == 1) {
CreateSamplerHeap(heap_props.samplerDescriptorSize);
BindSamplerHeap();
} else {
std::vector<uint8_t> payload(static_cast<size_t>(heap_props.maxPushDataSize / 2));
VkPushDataInfoEXT push_data_info = vku::InitStructHelper();
push_data_info.data.address = payload.data();
push_data_info.data.size = payload.size();
push_data_info.offset = 0;
vk::CmdPushDataEXT(m_command_buffer, &push_data_info);
}
m_errorMonitor->SetDesiredError("VUID-vkCmdDispatch-None-08600");
vk::CmdDispatch(m_command_buffer, 1, 1, 1);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
}
TEST_F(NegativeDescriptorHeap, SecondaryCmdBufferHeapMissingInheritance) {
AddRequiredExtensions(VK_KHR_SHADER_UNTYPED_POINTERS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::shaderUntypedPointers);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
InitRenderTarget();
const VkDeviceSize resource_stride = heap_props.bufferDescriptorSize;
CreateResourceHeap(resource_stride);
vkt::Buffer buffer(*m_device, 256, VK_BUFFER_USAGE_2_STORAGE_BUFFER_BIT_KHR, vkt::device_address);
VkHostAddressRangeEXT descriptor_host = {resource_heap_data_, static_cast<size_t>(resource_stride)};
VkDeviceAddressRangeEXT device_range = buffer.AddressRange();
VkResourceDescriptorInfoEXT descriptor_info = vku::InitStructHelper();
descriptor_info.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
descriptor_info.data.pAddressRange = &device_range;
vk::WriteResourceDescriptorsEXT(*m_device, 1u, &descriptor_info, &descriptor_host);
char const* vs_source = R"glsl(
#version 450
#extension GL_EXT_descriptor_heap : require
layout(descriptor_heap) buffer A { uint a; } heap[];
layout(push_constant) uniform PushConstant {
uint b;
};
void main() {
heap[0].a = b;
gl_Position = vec4(1.0f);
}
)glsl";
VkShaderObj vert_module = VkShaderObj(*m_device, vs_source, VK_SHADER_STAGE_VERTEX_BIT, SPV_ENV_VULKAN_1_2);
VkPipelineCreateFlags2CreateInfoKHR pipeline_create_flags_2_create_info = vku::InitStructHelper();
pipeline_create_flags_2_create_info.flags = VK_PIPELINE_CREATE_2_DESCRIPTOR_HEAP_BIT_EXT;
VkPipelineShaderStageCreateInfo stage;
stage = vert_module.GetStageCreateInfo();
CreatePipelineHelper pipe(*this, &pipeline_create_flags_2_create_info);
pipe.gp_ci_.layout = VK_NULL_HANDLE;
pipe.gp_ci_.stageCount = 1;
pipe.gp_ci_.pStages = &stage;
pipe.CreateGraphicsPipeline(false);
uint32_t src_data = 4321u;
VkPushDataInfoEXT push_data_info = vku::InitStructHelper();
push_data_info.offset = 0u;
push_data_info.data.size = sizeof(uint32_t);
push_data_info.data.address = &src_data;
VkPushConstantRange push_const_range = {VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(uint32_t)};
VkPipelineLayoutCreateInfo pipeline_layout_info = vku::InitStructHelper();
pipeline_layout_info.pushConstantRangeCount = 1u;
pipeline_layout_info.pPushConstantRanges = &push_const_range;
vkt::PipelineLayout pipeline_layout(*m_device, pipeline_layout_info);
vkt::CommandBuffer secondary(*m_device, m_command_pool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
VkCommandBufferInheritanceDescriptorHeapInfoEXT inheritance_heap_info = vku::InitStructHelper();
VkCommandBufferInheritanceInfo inheritance_info = vku::InitStructHelper(&inheritance_heap_info);
inheritance_info.renderPass = RenderPass();
inheritance_info.framebuffer = Framebuffer();
VkCommandBufferBeginInfo begin_info = vku::InitStructHelper();
begin_info.flags = VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
begin_info.pInheritanceInfo = &inheritance_info;
secondary.Begin(&begin_info);
vk::CmdBindPipeline(secondary, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
vk::CmdPushDataEXT(secondary, &push_data_info);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-11308");
vk::CmdDraw(secondary, 3u, 1u, 0u, 0u);
m_errorMonitor->VerifyFound();
secondary.End();
}
TEST_F(NegativeDescriptorHeap, SecondaryCmdBufferResourceHeapUnbound) {
AddRequiredExtensions(VK_KHR_SHADER_UNTYPED_POINTERS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::shaderUntypedPointers);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
InitRenderTarget();
const VkDeviceSize resource_stride = heap_props.bufferDescriptorSize;
CreateResourceHeap(resource_stride);
vkt::Buffer buffer(*m_device, 256, VK_BUFFER_USAGE_2_STORAGE_BUFFER_BIT_KHR, vkt::device_address);
VkHostAddressRangeEXT descriptor_host = {resource_heap_data_, static_cast<size_t>(resource_stride)};
VkDeviceAddressRangeEXT device_range = buffer.AddressRange();
VkResourceDescriptorInfoEXT descriptor_info = vku::InitStructHelper();
descriptor_info.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
descriptor_info.data.pAddressRange = &device_range;
vk::WriteResourceDescriptorsEXT(*m_device, 1u, &descriptor_info, &descriptor_host);
char const* vs_source = R"glsl(
#version 450
#extension GL_EXT_descriptor_heap : require
layout(descriptor_heap) buffer A { uint a; } heap[];
layout(push_constant) uniform PushConstant {
uint b;
};
void main() {
heap[0].a = b;
gl_Position = vec4(1.0f);
}
)glsl";
VkShaderObj vert_module = VkShaderObj(*m_device, vs_source, VK_SHADER_STAGE_VERTEX_BIT, SPV_ENV_VULKAN_1_2);
VkPipelineCreateFlags2CreateInfoKHR pipeline_create_flags_2_create_info = vku::InitStructHelper();
pipeline_create_flags_2_create_info.flags = VK_PIPELINE_CREATE_2_DESCRIPTOR_HEAP_BIT_EXT;
VkPipelineShaderStageCreateInfo stage;
stage = vert_module.GetStageCreateInfo();
CreatePipelineHelper pipe(*this, &pipeline_create_flags_2_create_info);
pipe.gp_ci_.layout = VK_NULL_HANDLE;
pipe.gp_ci_.stageCount = 1;
pipe.gp_ci_.pStages = &stage;
pipe.CreateGraphicsPipeline(false);
uint32_t src_data = 4321u;
VkPushDataInfoEXT push_data_info = vku::InitStructHelper();
push_data_info.offset = 0u;
push_data_info.data.size = sizeof(uint32_t);
push_data_info.data.address = &src_data;
VkPushConstantRange push_const_range = {VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(uint32_t)};
VkPipelineLayoutCreateInfo pipeline_layout_info = vku::InitStructHelper();
pipeline_layout_info.pushConstantRangeCount = 1u;
pipeline_layout_info.pPushConstantRanges = &push_const_range;
vkt::PipelineLayout pipeline_layout(*m_device, pipeline_layout_info);
vkt::CommandBuffer secondary(*m_device, m_command_pool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
VkBindHeapInfoEXT bind_resource_info = vku::InitStructHelper();
bind_resource_info.heapRange = resource_heap_.AddressRange();
bind_resource_info.reservedRangeOffset = resource_heap_.CreateInfo().size - heap_props.minResourceHeapReservedRange;
bind_resource_info.reservedRangeSize = heap_props.minResourceHeapReservedRange;
VkCommandBufferInheritanceDescriptorHeapInfoEXT inheritance_heap_info = vku::InitStructHelper();
inheritance_heap_info.pResourceHeapBindInfo = &bind_resource_info;
VkCommandBufferInheritanceInfo inheritance_info = vku::InitStructHelper(&inheritance_heap_info);
inheritance_info.renderPass = RenderPass();
inheritance_info.framebuffer = Framebuffer();
VkCommandBufferBeginInfo begin_info = vku::InitStructHelper();
begin_info.flags = VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
begin_info.pInheritanceInfo = &inheritance_info;
secondary.Begin(&begin_info);
vk::CmdBindPipeline(secondary, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
vk::CmdPushDataEXT(secondary, &push_data_info);
vk::CmdDraw(secondary, 3u, 1u, 0u, 0u);
secondary.End();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
m_errorMonitor->SetDesiredError("VUID-vkCmdExecuteCommands-commandBuffer-11474");
vk::CmdExecuteCommands(m_command_buffer, 1, &secondary.handle());
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDescriptorHeap, SecondaryCmdBufferSamplerHeapUnbound) {
AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
VkDeviceSize resource_heap_tracker = 0u;
const VkDeviceSize image_offset = AlignedAppend(resource_heap_tracker, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
const VkDeviceSize image_size = resource_heap_tracker - image_offset;
const VkDeviceSize buffer_offset = AlignedAppend(resource_heap_tracker, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
const VkDeviceSize buffer_size = resource_heap_tracker - buffer_offset;
const VkDeviceSize resource_heap_size = resource_heap_tracker;
CreateResourceHeap(resource_heap_size);
vkt::Buffer buffer(*m_device, sizeof(float) * 4u, VK_BUFFER_USAGE_2_STORAGE_BUFFER_BIT_KHR, vkt::device_address);
vkt::Image image(*m_device, 32u, 32u, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
VkHostAddressRangeEXT resource_host[2];
resource_host[0].address = resource_heap_data_ + image_offset;
resource_host[0].size = static_cast<size_t>(image_size);
resource_host[1].address = resource_heap_data_ + buffer_offset;
resource_host[1].size = static_cast<size_t>(buffer_size);
VkImageViewCreateInfo view_info = image.BasicViewCreatInfo(VK_IMAGE_ASPECT_COLOR_BIT);
VkImageDescriptorInfoEXT image_info = vku::InitStructHelper();
image_info.pView = &view_info;
image_info.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
VkDeviceAddressRangeEXT buffer_address_range = buffer.AddressRange();
VkResourceDescriptorInfoEXT descriptor_info[2];
descriptor_info[0] = vku::InitStructHelper();
descriptor_info[0].type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
descriptor_info[0].data.pImage = &image_info;
descriptor_info[1] = vku::InitStructHelper();
descriptor_info[1].type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
descriptor_info[1].data.pAddressRange = &buffer_address_range;
vk::WriteResourceDescriptorsEXT(*m_device, 2u, descriptor_info, resource_host);
VkDeviceSize sampler_desc_heap_size_tracker =
Align(heap_props.minSamplerHeapReservedRange, heap_props.samplerDescriptorAlignment);
const VkDeviceSize sampler_offset = AlignedAppend(sampler_desc_heap_size_tracker, VK_DESCRIPTOR_TYPE_SAMPLER);
const VkDeviceSize sampler_size = sampler_desc_heap_size_tracker - sampler_offset;
const VkDeviceSize sampler_heap_size = sampler_desc_heap_size_tracker;
vkt::Buffer sampler_heap(*m_device, sampler_heap_size, VK_BUFFER_USAGE_DESCRIPTOR_HEAP_BIT_EXT, vkt::device_address);
uint8_t* sampler_heap_data = static_cast<uint8_t*>(sampler_heap.Memory().Map());
VkSamplerCreateInfo sampler_info = SafeSaneSamplerCreateInfo();
VkHostAddressRangeEXT sampler_host = {sampler_heap_data + sampler_offset, static_cast<size_t>(sampler_size)};
vk::WriteSamplerDescriptorsEXT(*m_device, 1u, &sampler_info, &sampler_host);
VkBindHeapInfoEXT sampler_bind_info = vku::InitStructHelper();
sampler_bind_info.heapRange = sampler_heap.AddressRange();
sampler_bind_info.reservedRangeOffset = 0;
sampler_bind_info.reservedRangeSize = heap_props.minSamplerHeapReservedRange;
char const* cs_source = R"glsl(
#version 450
layout(set = 0, binding = 0) uniform texture2D tex;
layout(set = 0, binding = 1) uniform sampler sampl;
layout(set = 1, binding = 0) buffer ssbo {
vec4 data;
};
void main() {
data = texture(sampler2D(tex, sampl), vec2(0.5f));
}
)glsl";
VkShaderObj cs_module = VkShaderObj(*m_device, cs_source, VK_SHADER_STAGE_COMPUTE_BIT);
VkPipelineCreateFlags2CreateInfoKHR pipeline_create_flags_2_create_info = vku::InitStructHelper();
pipeline_create_flags_2_create_info.flags = VK_PIPELINE_CREATE_2_DESCRIPTOR_HEAP_BIT_EXT;
VkDescriptorSetAndBindingMappingEXT mappings[3];
mappings[0] = MakeSetAndBindingMapping(0, 0, 1, VK_SPIRV_RESOURCE_TYPE_SAMPLED_IMAGE_BIT_EXT);
mappings[0].source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT;
mappings[0].sourceData.constantOffset = {};
mappings[0].sourceData.constantOffset.heapOffset = static_cast<uint32_t>(image_offset);
mappings[1] = MakeSetAndBindingMapping(0, 1, 1, VK_SPIRV_RESOURCE_TYPE_SAMPLER_BIT_EXT);
mappings[1].source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT;
mappings[1].sourceData.constantOffset = {};
mappings[1].sourceData.constantOffset.heapOffset = static_cast<uint32_t>(sampler_offset);
mappings[2] = MakeSetAndBindingMapping(1, 0);
mappings[2].source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT;
mappings[2].sourceData.constantOffset = {};
mappings[2].sourceData.constantOffset.heapOffset = static_cast<uint32_t>(buffer_offset);
VkShaderDescriptorSetAndBindingMappingInfoEXT mapping_info = vku::InitStructHelper();
mapping_info.mappingCount = 3u;
mapping_info.pMappings = mappings;
CreateComputePipelineHelper pipe(*this, &pipeline_create_flags_2_create_info);
pipe.cp_ci_.layout = VK_NULL_HANDLE;
pipe.cp_ci_.stage = cs_module.GetStageCreateInfo(&mapping_info);
pipe.CreateComputePipeline(false);
vkt::CommandBuffer secondary(*m_device, m_command_pool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
VkBindHeapInfoEXT resource_bind_info = vku::InitStructHelper();
resource_bind_info.heapRange = resource_heap_.AddressRange();
resource_bind_info.reservedRangeOffset = resource_heap_.CreateInfo().size - heap_props.minResourceHeapReservedRange;
resource_bind_info.reservedRangeSize = heap_props.minResourceHeapReservedRange;
VkCommandBufferInheritanceDescriptorHeapInfoEXT inheritance_heap_info = vku::InitStructHelper();
inheritance_heap_info.pResourceHeapBindInfo = &resource_bind_info;
inheritance_heap_info.pSamplerHeapBindInfo = &sampler_bind_info;
VkCommandBufferInheritanceInfo inheritance_info = vku::InitStructHelper(&inheritance_heap_info);
VkCommandBufferBeginInfo begin_info = vku::InitStructHelper();
begin_info.pInheritanceInfo = &inheritance_info;
secondary.Begin(&begin_info);
vk::CmdBindPipeline(secondary, VK_PIPELINE_BIND_POINT_COMPUTE, pipe);
vk::CmdDispatch(secondary, 1u, 1u, 1u);
secondary.End();
m_command_buffer.Begin();
BindResourceHeap();
m_errorMonitor->SetDesiredError("VUID-vkCmdExecuteCommands-commandBuffer-11473");
vk::CmdExecuteCommands(m_command_buffer, 1, &secondary.handle());
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeDescriptorHeap, OffsetIdNotAlignedBuffer) {
AddRequiredExtensions(VK_KHR_SHADER_UNTYPED_POINTERS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::shaderUntypedPointers);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
// What the shader looks like
//
// layout(descriptor_heap) struct {
// layout(offset = 0) buffer a { uint data; } x;
// layout(offset = 5) buffer a { uint data; } y;
// };
char const* cs_source = R"(
OpCapability Shader
OpCapability UntypedPointersKHR
OpCapability DescriptorHeapEXT
OpExtension "SPV_EXT_descriptor_heap"
OpExtension "SPV_KHR_untyped_pointers"
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %main "main" %resource_heap %_
OpExecutionMode %main LocalSize 1 1 1
OpName %heap_struct "heap_struct"
OpDecorate %resource_heap BuiltIn ResourceHeapEXT
OpDecorate %A Block
OpMemberDecorate %A 0 Offset 0
OpDecorate %PushConstant Block
OpMemberDecorate %PushConstant 0 Offset 0
OpMemberDecorate %heap_struct 0 Offset 0
OpMemberDecorate %heap_struct 1 Offset 5
%void = OpTypeVoid
%3 = OpTypeFunction %void
%_ptr_UniformConstant = OpTypeUntypedPointerKHR UniformConstant
%resource_heap = OpUntypedVariableKHR %_ptr_UniformConstant UniformConstant
%int = OpTypeInt 32 1
%int_1 = OpConstant %int 1
%uint = OpTypeInt 32 0
%A = OpTypeStruct %uint
%int_0 = OpConstant %int 0
%PushConstant = OpTypeStruct %uint
%_ptr_PushConstant_PushConstant = OpTypePointer PushConstant %PushConstant
%_ = OpVariable %_ptr_PushConstant_PushConstant PushConstant
%_ptr_PushConstant_uint = OpTypePointer PushConstant %uint
%_ptr_StorageBuffer = OpTypeUntypedPointerKHR StorageBuffer
%21 = OpTypeBufferEXT StorageBuffer
%heap_struct = OpTypeStruct %21 %21
%main = OpFunction %void None %3
%5 = OpLabel
%17 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0
%18 = OpLoad %uint %17
%20 = OpUntypedAccessChainKHR %_ptr_UniformConstant %heap_struct %resource_heap %int_1
%24 = OpBufferPointerEXT %_ptr_StorageBuffer %20
%25 = OpUntypedAccessChainKHR %_ptr_StorageBuffer %A %24 %int_0
OpStore %25 %18
OpReturn
OpFunctionEnd
)";
VkShaderObj cs_module = VkShaderObj(*m_device, cs_source, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_3, SPV_SOURCE_ASM);
VkPipelineCreateFlags2CreateInfoKHR pipeline_create_flags_2_create_info = vku::InitStructHelper();
pipeline_create_flags_2_create_info.flags = VK_PIPELINE_CREATE_2_DESCRIPTOR_HEAP_BIT_EXT;
CreateComputePipelineHelper pipe(*this, &pipeline_create_flags_2_create_info);
pipe.cp_ci_.layout = VK_NULL_HANDLE;
pipe.cp_ci_.stage = cs_module.GetStageCreateInfo();
m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-bufferDescriptorAlignment-11478");
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDescriptorHeap, OffsetIdNotAlignedImageAndSampler) {
AddRequiredExtensions(VK_KHR_SHADER_UNTYPED_POINTERS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::shaderUntypedPointers);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
char const* cs_source = R"(
OpCapability Shader
OpCapability UntypedPointersKHR
OpCapability DescriptorHeapEXT
OpExtension "SPV_EXT_descriptor_heap"
OpExtension "SPV_KHR_untyped_pointers"
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %main "main"
OpExecutionMode %main LocalSize 1 1 1
OpName %struct_a "struct_a"
OpName %struct_b "struct_b"
OpMemberDecorate %struct_a 0 Offset 0
OpMemberDecorate %struct_a 1 Offset 7
OpMemberDecorate %struct_b 0 Offset 0
OpMemberDecorate %struct_b 1 Offset 32
OpMemberDecorate %struct_b 2 Offset 39
%void = OpTypeVoid
%3 = OpTypeFunction %void
%int = OpTypeInt 32 1
%float = OpTypeFloat 32
%image = OpTypeImage %float 2D 0 0 0 1 Unknown
%sampler = OpTypeSampler
%struct_a = OpTypeStruct %int %image
%struct_b = OpTypeStruct %struct_a %int %sampler
%main = OpFunction %void None %3
%5 = OpLabel
OpReturn
OpFunctionEnd
)";
VkShaderObj cs_module = VkShaderObj(*m_device, cs_source, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_3, SPV_SOURCE_ASM);
VkPipelineCreateFlags2CreateInfoKHR pipeline_create_flags_2_create_info = vku::InitStructHelper();
pipeline_create_flags_2_create_info.flags = VK_PIPELINE_CREATE_2_DESCRIPTOR_HEAP_BIT_EXT;
CreateComputePipelineHelper pipe(*this, &pipeline_create_flags_2_create_info);
pipe.cp_ci_.layout = VK_NULL_HANDLE;
pipe.cp_ci_.stage = cs_module.GetStageCreateInfo();
m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-samplerDescriptorAlignment-11476");
m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-imageDescriptorAlignment-11477");
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDescriptorHeap, OffsetIdNotAlignedConstant) {
AddRequiredExtensions(VK_KHR_SHADER_UNTYPED_POINTERS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::shaderUntypedPointers);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
char const* cs_source = R"(
OpCapability Shader
OpCapability UntypedPointersKHR
OpCapability DescriptorHeapEXT
OpExtension "SPV_EXT_descriptor_heap"
OpExtension "SPV_KHR_untyped_pointers"
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %main "main"
OpExecutionMode %main LocalSize 1 1 1
OpName %struct_a "struct_a"
OpMemberDecorateIdEXT %struct_a 0 OffsetIdEXT %int_0
OpMemberDecorateIdEXT %struct_a 1 OffsetIdEXT %int_7
%void = OpTypeVoid
%3 = OpTypeFunction %void
%int = OpTypeInt 32 1
%int_0 = OpConstant %int 0
%int_7 = OpConstant %int 7
%float = OpTypeFloat 32
%image = OpTypeImage %float 2D 0 0 0 1 Unknown
%struct_a = OpTypeStruct %int %image
%main = OpFunction %void None %3
%5 = OpLabel
OpReturn
OpFunctionEnd
)";
VkShaderObj cs_module = VkShaderObj(*m_device, cs_source, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_3, SPV_SOURCE_ASM);
VkPipelineCreateFlags2CreateInfoKHR pipeline_create_flags_2_create_info = vku::InitStructHelper();
pipeline_create_flags_2_create_info.flags = VK_PIPELINE_CREATE_2_DESCRIPTOR_HEAP_BIT_EXT;
CreateComputePipelineHelper pipe(*this, &pipeline_create_flags_2_create_info);
pipe.cp_ci_.layout = VK_NULL_HANDLE;
pipe.cp_ci_.stage = cs_module.GetStageCreateInfo();
m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-imageDescriptorAlignment-11477");
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDescriptorHeap, OffsetIdNotAlignedSpecConstantDefault) {
AddRequiredExtensions(VK_KHR_SHADER_UNTYPED_POINTERS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::shaderUntypedPointers);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
char const* cs_source = R"(
OpCapability Shader
OpCapability UntypedPointersKHR
OpCapability DescriptorHeapEXT
OpExtension "SPV_EXT_descriptor_heap"
OpExtension "SPV_KHR_untyped_pointers"
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %main "main"
OpExecutionMode %main LocalSize 1 1 1
OpName %struct_a "struct_a"
OpMemberDecorateIdEXT %struct_a 0 OffsetIdEXT %uint_0
OpMemberDecorateIdEXT %struct_a 1 OffsetIdEXT %result
%void = OpTypeVoid
%3 = OpTypeFunction %void
%uint = OpTypeInt 32 0
%uint_0 = OpConstant %uint 0
%uint_1 = OpConstant %uint 1
%uint_4 = OpConstant %uint 4
%uint_8 = OpConstant %uint 8
%mul = OpSpecConstantOp %uint IMul %uint_4 %uint_8
%result = OpSpecConstantOp %uint IAdd %mul %uint_1
%float = OpTypeFloat 32
%image = OpTypeImage %float 2D 0 0 0 1 Unknown
%struct_a = OpTypeStruct %uint %image
%main = OpFunction %void None %3
%5 = OpLabel
OpReturn
OpFunctionEnd
)";
VkShaderObj cs_module = VkShaderObj(*m_device, cs_source, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_3, SPV_SOURCE_ASM);
VkPipelineCreateFlags2CreateInfoKHR pipeline_create_flags_2_create_info = vku::InitStructHelper();
pipeline_create_flags_2_create_info.flags = VK_PIPELINE_CREATE_2_DESCRIPTOR_HEAP_BIT_EXT;
CreateComputePipelineHelper pipe(*this, &pipeline_create_flags_2_create_info);
pipe.cp_ci_.layout = VK_NULL_HANDLE;
pipe.cp_ci_.stage = cs_module.GetStageCreateInfo();
m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-imageDescriptorAlignment-11477");
pipe.CreateComputePipeline(false);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDescriptorHeap, UnboundResourceHeap) {
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
const VkDeviceSize resource_stride = heap_props.bufferDescriptorSize;
CreateResourceHeap(resource_stride * 2);
vkt::Buffer buffer_a(*m_device, 512, VK_BUFFER_USAGE_2_STORAGE_BUFFER_BIT_KHR, vkt::device_address);
vkt::Buffer buffer_b(*m_device, 256, VK_BUFFER_USAGE_2_STORAGE_BUFFER_BIT_KHR, vkt::device_address);
VkHostAddressRangeEXT descriptor_host[2];
descriptor_host[0].address = resource_heap_data_;
descriptor_host[0].size = static_cast<size_t>(resource_stride);
descriptor_host[1].address = resource_heap_data_ + resource_stride;
descriptor_host[1].size = static_cast<size_t>(resource_stride);
VkDeviceAddressRangeEXT device_ranges[2];
device_ranges[0].address = buffer_a.Address() + 256;
device_ranges[0].size = 256;
device_ranges[1].address = buffer_b.Address();
device_ranges[1].size = 256;
VkResourceDescriptorInfoEXT descriptor_info[2];
descriptor_info[0] = vku::InitStructHelper();
descriptor_info[0].type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
descriptor_info[0].data.pAddressRange = &device_ranges[0];
descriptor_info[1] = vku::InitStructHelper();
descriptor_info[1].type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
descriptor_info[1].data.pAddressRange = &device_ranges[1];
vk::WriteResourceDescriptorsEXT(*m_device, 2, descriptor_info, descriptor_host);
VkDescriptorSetAndBindingMappingEXT mappings[2];
mappings[0] = MakeSetAndBindingMapping(0, 0);
mappings[0].source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT;
mappings[0].sourceData.constantOffset.heapOffset = 0;
mappings[0].sourceData.constantOffset.heapArrayStride = 0;
mappings[1] = MakeSetAndBindingMapping(0, 1);
mappings[1].source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT;
mappings[1].sourceData.constantOffset.heapOffset = static_cast<uint32_t>(resource_stride);
mappings[1].sourceData.constantOffset.heapArrayStride = 0;
VkShaderDescriptorSetAndBindingMappingInfoEXT mapping_info = vku::InitStructHelper();
mapping_info.mappingCount = 2;
mapping_info.pMappings = mappings;
char const* cs_source = R"glsl(
#version 450
layout(local_size_x = 1) in;
layout(set = 0, binding = 0) buffer A { uint a; };
layout(set = 0, binding = 1) buffer B { uint b; };
void main() {
a = 2;
b = 4;
}
)glsl";
VkShaderObj cs_module = VkShaderObj(*m_device, cs_source, VK_SHADER_STAGE_COMPUTE_BIT);
VkPipelineCreateFlags2CreateInfoKHR pipeline_create_flags_2_create_info = vku::InitStructHelper();
pipeline_create_flags_2_create_info.flags = VK_PIPELINE_CREATE_2_DESCRIPTOR_HEAP_BIT_EXT;
CreateComputePipelineHelper pipe(*this, &pipeline_create_flags_2_create_info);
pipe.cp_ci_.layout = VK_NULL_HANDLE;
pipe.cp_ci_.stage = cs_module.GetStageCreateInfo(&mapping_info);
pipe.CreateComputePipeline(false);
OneOffDescriptorSet descriptor_set(m_device, {
{0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 2, VK_SHADER_STAGE_ALL, nullptr},
});
const vkt::PipelineLayout pipeline_layout(*m_device, {&descriptor_set.layout_});
m_command_buffer.Begin();
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDispatch-None-11308");
vk::CmdDispatch(m_command_buffer, 1, 1, 1);
m_errorMonitor->VerifyFound();
BindResourceHeap();
vk::CmdDispatch(m_command_buffer, 1, 1, 1);
vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_layout, 0, 1, &descriptor_set.set_, 0,
nullptr);
m_errorMonitor->SetDesiredError("VUID-vkCmdDispatch-None-11308");
vk::CmdDispatch(m_command_buffer, 1, 1, 1);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeDescriptorHeap, PushDescriptorSet) {
AddRequiredExtensions(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
const VkDeviceSize heap_size = heap_props.samplerDescriptorSize + heap_props.minSamplerHeapReservedRange;
vkt::Buffer heap(*m_device, heap_size, VK_BUFFER_USAGE_DESCRIPTOR_HEAP_BIT_EXT, vkt::device_address);
vkt::CommandBuffer secondary(*m_device, m_command_pool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
const auto ds_type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
OneOffDescriptorSet ds(m_device, {{0, ds_type, 1, VK_SHADER_STAGE_COMPUTE_BIT, nullptr}},
VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT);
const vkt::PipelineLayout pipeline_layout(*m_device, {&ds.layout_});
vkt::Buffer buffer(*m_device, 32, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
VkDescriptorBufferInfo buffer_info{buffer, 0, VK_WHOLE_SIZE};
VkWriteDescriptorSet descriptor_write = vku::InitStructHelper();
descriptor_write.dstSet = ds.set_;
descriptor_write.dstBinding = 0;
descriptor_write.descriptorCount = 1;
descriptor_write.descriptorType = ds_type;
descriptor_write.pBufferInfo = &buffer_info;
VkCommandBufferInheritanceDescriptorHeapInfoEXT inh_desc_heap_info = vku::InitStructHelper();
VkBindHeapInfoEXT samplerHeapBindInfo = vku::InitStructHelper();
inh_desc_heap_info.pSamplerHeapBindInfo = &samplerHeapBindInfo;
VkCommandBufferInheritanceInfo inh = vku::InitStructHelper(&inh_desc_heap_info);
VkCommandBufferBeginInfo cbbi = vku::InitStructHelper();
cbbi.pInheritanceInfo = &inh;
secondary.Begin(&cbbi);
m_errorMonitor->SetDesiredError("VUID-vkCmdPushDescriptorSet-commandBuffer-11295");
vk::CmdPushDescriptorSetKHR(secondary, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_layout, 0u, 1u, &descriptor_write);
m_errorMonitor->VerifyFound();
secondary.End();
}
TEST_F(NegativeDescriptorHeap, DescriptorBufferInvalidatingHeap) {
AddRequiredExtensions(VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::descriptorBuffer);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
vkt::Buffer descriptor_buffer(*m_device, 256u, VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT, vkt::device_address);
const VkDeviceSize resource_stride = heap_props.bufferDescriptorSize;
CreateResourceHeap(resource_stride * 2);
vkt::Buffer buffer_a(*m_device, 512, VK_BUFFER_USAGE_2_STORAGE_BUFFER_BIT_KHR, vkt::device_address);
vkt::Buffer buffer_b(*m_device, 256, VK_BUFFER_USAGE_2_STORAGE_BUFFER_BIT_KHR, vkt::device_address);
VkHostAddressRangeEXT descriptor_host[2];
descriptor_host[0].address = resource_heap_data_;
descriptor_host[0].size = static_cast<size_t>(resource_stride);
descriptor_host[1].address = resource_heap_data_ + resource_stride;
descriptor_host[1].size = static_cast<size_t>(resource_stride);
VkDeviceAddressRangeEXT device_ranges[2];
device_ranges[0].address = buffer_a.Address() + 256;
device_ranges[0].size = 256;
device_ranges[1].address = buffer_b.Address();
device_ranges[1].size = 256;
VkResourceDescriptorInfoEXT descriptor_info[2];
descriptor_info[0] = vku::InitStructHelper();
descriptor_info[0].type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
descriptor_info[0].data.pAddressRange = &device_ranges[0];
descriptor_info[1] = vku::InitStructHelper();
descriptor_info[1].type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
descriptor_info[1].data.pAddressRange = &device_ranges[1];
vk::WriteResourceDescriptorsEXT(*m_device, 2, descriptor_info, descriptor_host);
VkDescriptorSetAndBindingMappingEXT mappings[2];
mappings[0] = MakeSetAndBindingMapping(0, 0);
mappings[0].source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT;
mappings[0].sourceData.constantOffset.heapOffset = 0;
mappings[0].sourceData.constantOffset.heapArrayStride = 0;
mappings[1] = MakeSetAndBindingMapping(0, 1);
mappings[1].source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT;
mappings[1].sourceData.constantOffset.heapOffset = static_cast<uint32_t>(resource_stride);
mappings[1].sourceData.constantOffset.heapArrayStride = 0;
VkShaderDescriptorSetAndBindingMappingInfoEXT mapping_info = vku::InitStructHelper();
mapping_info.mappingCount = 2;
mapping_info.pMappings = mappings;
char const* cs_source = R"glsl(
#version 450
layout(local_size_x = 1) in;
layout(set = 0, binding = 0) buffer A { uint a; };
layout(set = 0, binding = 1) buffer B { uint b; };
void main() {
a = 2;
b = 4;
}
)glsl";
VkShaderObj cs_module = VkShaderObj(*m_device, cs_source, VK_SHADER_STAGE_COMPUTE_BIT);
VkPipelineCreateFlags2CreateInfoKHR pipeline_create_flags_2_create_info = vku::InitStructHelper();
pipeline_create_flags_2_create_info.flags = VK_PIPELINE_CREATE_2_DESCRIPTOR_HEAP_BIT_EXT;
CreateComputePipelineHelper pipe(*this, &pipeline_create_flags_2_create_info);
pipe.cp_ci_.layout = VK_NULL_HANDLE;
pipe.cp_ci_.stage = cs_module.GetStageCreateInfo(&mapping_info);
pipe.CreateComputePipeline(false);
OneOffDescriptorSet descriptor_set(m_device, {
{0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 2, VK_SHADER_STAGE_ALL, nullptr},
});
const vkt::PipelineLayout pipeline_layout(*m_device, {&descriptor_set.layout_});
m_command_buffer.Begin();
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe);
BindResourceHeap();
VkDescriptorBufferBindingInfoEXT descriptor_buffer_binding_info = vku::InitStructHelper();
descriptor_buffer_binding_info.address = descriptor_buffer.Address();
descriptor_buffer_binding_info.usage = VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT;
vk::CmdBindDescriptorBuffersEXT(m_command_buffer, 1u, &descriptor_buffer_binding_info);
m_errorMonitor->SetDesiredError("VUID-vkCmdDispatch-None-11308");
vk::CmdDispatch(m_command_buffer, 1, 1, 1);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDescriptorHeap, ImageDescriptorLayout) {
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
vkt::Image image(*m_device, 32u, 32u, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT);
VkImageViewCreateInfo image_view_ci = vku::InitStructHelper();
image_view_ci.flags = 0u;
image_view_ci.image = image;
image_view_ci.viewType = VK_IMAGE_VIEW_TYPE_2D;
image_view_ci.format = VK_FORMAT_R8G8B8A8_UNORM;
image_view_ci.components = {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A};
image_view_ci.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u};
VkImageDescriptorInfoEXT image_info = vku::InitStructHelper();
image_info.pView = &image_view_ci;
image_info.layout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
VkResourceDescriptorInfoEXT resource_desc_info = vku::InitStructHelper();
resource_desc_info.type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
resource_desc_info.data.pImage = &image_info;
std::vector<uint8_t> data(static_cast<size_t>(heap_props.imageDescriptorSize));
VkHostAddressRangeEXT descriptors;
descriptors.address = data.data();
descriptors.size = heap_props.imageDescriptorSize;
m_errorMonitor->SetDesiredError("VUID-VkImageDescriptorInfoEXT-layout-11219");
vk::WriteResourceDescriptorsEXT(device(), 1u, &resource_desc_info, &descriptors);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDescriptorHeap, ImageDescriptorAspect) {
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
VkFormat depth_format = FindSupportedDepthStencilFormat(gpu_);
vkt::Image image(*m_device, 32u, 32u, depth_format, VK_IMAGE_USAGE_SAMPLED_BIT);
VkImageViewCreateInfo image_view_ci = vku::InitStructHelper();
image_view_ci.flags = 0u;
image_view_ci.image = image;
image_view_ci.viewType = VK_IMAGE_VIEW_TYPE_2D;
image_view_ci.format = depth_format;
image_view_ci.components = {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A};
image_view_ci.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u};
VkImageDescriptorInfoEXT image_info = vku::InitStructHelper();
image_info.pView = &image_view_ci;
image_info.layout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL;
VkResourceDescriptorInfoEXT resource_desc_info = vku::InitStructHelper();
resource_desc_info.type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
resource_desc_info.data.pImage = &image_info;
std::vector<uint8_t> data(static_cast<size_t>(heap_props.imageDescriptorSize));
VkHostAddressRangeEXT descriptors;
descriptors.address = data.data();
descriptors.size = heap_props.imageDescriptorSize;
m_errorMonitor->SetDesiredError("VUID-VkImageDescriptorInfoEXT-layout-11221");
vk::WriteResourceDescriptorsEXT(device(), 1u, &resource_desc_info, &descriptors);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDescriptorHeap, SamplerHeapBoundResourceHeapNotBound) {
AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_SHADER_UNTYPED_POINTERS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
AddRequiredFeature(vkt::Feature::shaderUntypedPointers);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
InitRenderTarget();
const uint32_t buffer_index = 16u;
const VkDeviceSize image_offset = 0u;
const VkDeviceSize image_size = heap_props.imageDescriptorSize;
const VkDeviceSize buffer_offset = heap_props.bufferDescriptorSize * buffer_index;
const VkDeviceSize buffer_size = heap_props.bufferDescriptorSize;
const VkDeviceSize resource_heap_app_size = buffer_offset + buffer_size;
CreateResourceHeap(resource_heap_app_size);
vkt::Buffer buffer(*m_device, 256, VK_BUFFER_USAGE_2_STORAGE_BUFFER_BIT_KHR, vkt::device_address);
vkt::Image image(*m_device, 32u, 32u, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
VkHostAddressRangeEXT resource_host[2];
resource_host[0].address = resource_heap_data_ + image_offset;
resource_host[0].size = static_cast<size_t>(image_size);
resource_host[1].address = resource_heap_data_ + buffer_offset;
resource_host[1].size = static_cast<size_t>(buffer_size);
VkImageViewCreateInfo view_info = image.BasicViewCreatInfo(VK_IMAGE_ASPECT_COLOR_BIT);
VkImageDescriptorInfoEXT image_info = vku::InitStructHelper();
image_info.pView = &view_info;
image_info.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
VkDeviceAddressRangeEXT buffer_address_range = buffer.AddressRange();
VkResourceDescriptorInfoEXT descriptor_info[2];
descriptor_info[0] = vku::InitStructHelper();
descriptor_info[0].type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
descriptor_info[0].data.pImage = &image_info;
descriptor_info[1] = vku::InitStructHelper();
descriptor_info[1].type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
descriptor_info[1].data.pAddressRange = &buffer_address_range;
vk::WriteResourceDescriptorsEXT(*m_device, 2u, descriptor_info, resource_host);
VkDeviceSize sampler_desc_heap_size_tracker = 0u;
const VkDeviceSize sampler_offset = AlignedAppend(sampler_desc_heap_size_tracker, VK_DESCRIPTOR_TYPE_SAMPLER);
const VkDeviceSize sampler_size = sampler_desc_heap_size_tracker - sampler_offset;
CreateSamplerHeap(sampler_desc_heap_size_tracker);
VkSamplerCreateInfo sampler_info = SafeSaneSamplerCreateInfo();
VkHostAddressRangeEXT sampler_host = {sampler_heap_data_ + sampler_offset, static_cast<size_t>(sampler_size)};
vk::WriteSamplerDescriptorsEXT(*m_device, 1u, &sampler_info, &sampler_host);
char const* cs_source = R"glsl(
#version 450
#extension GL_EXT_descriptor_heap : require
layout(descriptor_heap) uniform texture2D heapTextures[];
layout(descriptor_heap) uniform sampler heapSamplers[];
layout(descriptor_heap) buffer ssbo {
vec4 data;
} heapBuffer[];
void main() {
heapBuffer[16].data = texture(sampler2D(heapTextures[0], heapSamplers[0]), vec2(0.5f));
}
)glsl";
VkShaderObj cs_module = VkShaderObj(*m_device, cs_source, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_2);
VkPipelineCreateFlags2CreateInfoKHR pipeline_create_flags_2_create_info = vku::InitStructHelper();
pipeline_create_flags_2_create_info.flags = VK_PIPELINE_CREATE_2_DESCRIPTOR_HEAP_BIT_EXT;
CreateComputePipelineHelper pipe(*this, &pipeline_create_flags_2_create_info);
pipe.cp_ci_.layout = VK_NULL_HANDLE;
pipe.cp_ci_.stage = cs_module.GetStageCreateInfo();
pipe.CreateComputePipeline(false);
m_command_buffer.Begin();
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe);
BindSamplerHeap();
m_errorMonitor->SetDesiredError("VUID-vkCmdDispatch-None-11308");
vk::CmdDispatch(m_command_buffer, 1u, 1u, 1u);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeDescriptorHeap, ResetPushConstsWithPushData) {
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
AddRequiredFeature(vkt::Feature::vertexPipelineStoresAndAtomics);
RETURN_IF_SKIP(InitBasicDescriptorHeap());
InitRenderTarget();
char const* vert_source = R"glsl(
#version 450
layout(push_constant) uniform PushConstant {
float pos;
};
void main() {
gl_Position = vec4(pos);
}
)glsl";
VkShaderObj vert_module = VkShaderObj(*m_device, vert_source, VK_SHADER_STAGE_VERTEX_BIT);
VkShaderObj frag_module = VkShaderObj(*m_device, kFragmentMinimalGlsl, VK_SHADER_STAGE_FRAGMENT_BIT);
const float push_data = 0.5f;
VkPushConstantRange push_const_range;
push_const_range.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
push_const_range.offset = 0u;
push_const_range.size = sizeof(push_data);
vkt::PipelineLayout pipelineLayout(*m_device, {}, {push_const_range});
CreatePipelineHelper pipe(*this);
pipe.shader_stages_ = {vert_module.GetStageCreateInfo(), frag_module.GetStageCreateInfo()};
pipe.gp_ci_.layout = pipelineLayout;
pipe.CreateGraphicsPipeline();
VkPushDataInfoEXT push_data_info = vku::InitStructHelper();
push_data_info.offset = 0;
push_data_info.data.size = sizeof(push_data);
push_data_info.data.address = &push_data;
m_command_buffer.Begin();
vk::CmdPushConstants(m_command_buffer, pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0u, sizeof(push_data), &push_data);
vk::CmdPushDataEXT(m_command_buffer, &push_data_info);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-maintenance4-08602");
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}