blob: d9e80949ed93fcb2ba08765a1bc94698489a2118 [file]
/*
* Copyright (c) 2026 Valve Corporation
* Copyright (c) 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 <vulkan/vulkan_core.h>
#include "../framework/layer_validation_tests.h"
#include "../framework/pipeline_helper.h"
#include "../framework/buffer_helper.h"
#include "test_framework.h"
#include "utils/math_utils.h"
class NegativeGpuAVDescriptorBuffer : public GpuAVDescriptorBuffer {};
// TODO - Add support in GPU-AV for this
TEST_F(NegativeGpuAVDescriptorBuffer, DISABLED_BasicNoDescriptor) {
TEST_DESCRIPTION("Never even call vkGetDescriptorEXT and try to access something");
RETURN_IF_SKIP(InitBasicDescriptorBuffer({}));
const char* cs_source = R"glsl(
#version 450
layout (set = 0, binding = 0) buffer SSBO_0 {
uint a;
};
void main() {
a = 0;
}
)glsl";
VkDescriptorSetLayoutBinding binding = {0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr};
vkt::DescriptorSetLayout ds_layout(*m_device, binding, VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT);
vkt::PipelineLayout pipeline_layout(*m_device, {&ds_layout});
CreateComputePipelineHelper pipe(*this);
pipe.cs_ = VkShaderObj(*m_device, cs_source, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_2);
pipe.cp_ci_.flags |= VK_PIPELINE_CREATE_DESCRIPTOR_BUFFER_BIT_EXT;
pipe.cp_ci_.layout = pipeline_layout;
pipe.CreateComputePipeline();
VkMemoryAllocateFlagsInfo allocate_flag_info = vku::InitStructHelper();
allocate_flag_info.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT;
vkt::Buffer descriptor_buffer(*m_device, 1024,
VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT |
VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &allocate_flag_info);
m_command_buffer.Begin();
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe);
VkDeviceSize buffer_address = Align(descriptor_buffer.Address(), descriptor_buffer_properties.descriptorBufferOffsetAlignment);
VkDescriptorBufferBindingInfoEXT descriptor_buffer_binding_info = vku::InitStructHelper();
descriptor_buffer_binding_info.address = buffer_address;
descriptor_buffer_binding_info.usage = VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT;
vk::CmdBindDescriptorBuffersEXT(m_command_buffer, 1, &descriptor_buffer_binding_info);
uint32_t buffer_index = 0;
VkDeviceSize buffer_offset = 0;
vk::CmdSetDescriptorBufferOffsetsEXT(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_layout, 0, 1, &buffer_index,
&buffer_offset);
vk::CmdDispatch(m_command_buffer, 1, 1, 1);
m_command_buffer.End();
m_default_queue->SubmitAndWait(m_command_buffer);
}
// TODO - Add support in GPU-AV for this
TEST_F(NegativeGpuAVDescriptorBuffer, DISABLED_BasicDescriptorWrongAddress) {
RETURN_IF_SKIP(InitBasicDescriptorBuffer({}));
const char* cs_source = R"glsl(
#version 450
layout (set = 0, binding = 0) buffer SSBO_0 {
uint a;
};
void main() {
a = 0;
}
)glsl";
VkDescriptorSetLayoutBinding binding = {0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr};
vkt::DescriptorSetLayout ds_layout(*m_device, binding, VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT);
vkt::PipelineLayout pipeline_layout(*m_device, {&ds_layout});
CreateComputePipelineHelper pipe(*this);
pipe.cs_ = VkShaderObj(*m_device, cs_source, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_2);
pipe.cp_ci_.flags |= VK_PIPELINE_CREATE_DESCRIPTOR_BUFFER_BIT_EXT;
pipe.cp_ci_.layout = pipeline_layout;
pipe.CreateComputePipeline();
vkt::Buffer ssbo_buffer(*m_device, 16, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, vkt::device_address);
vkt::DescriptorGetInfo get_info(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, ssbo_buffer, 16u);
vkt::Buffer src_buffer(*m_device, 1024, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
uint8_t* mapped_descriptor_data = (uint8_t*)src_buffer.Memory().Map();
vk::GetDescriptorEXT(device(), get_info, descriptor_buffer_properties.storageBufferDescriptorSize, mapped_descriptor_data);
VkMemoryAllocateFlagsInfo allocate_flag_info = vku::InitStructHelper();
allocate_flag_info.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT;
vkt::Buffer descriptor_buffer(*m_device, 1024,
VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT |
VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &allocate_flag_info);
m_command_buffer.Begin();
// Put a descriptor twice in the wrong spot
VkBufferCopy buffer_copy = {0, 0, descriptor_buffer_properties.storageBufferDescriptorSize};
vk::CmdCopyBuffer(m_command_buffer, src_buffer, descriptor_buffer, 1u, &buffer_copy);
buffer_copy.dstOffset = 256;
vk::CmdCopyBuffer(m_command_buffer, src_buffer, descriptor_buffer, 1u, &buffer_copy);
m_command_buffer.FullMemoryBarrier();
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe);
// somewhere randomly bad
VkDeviceSize buffer_address =
Align(descriptor_buffer.Address() + 512, descriptor_buffer_properties.descriptorBufferOffsetAlignment);
VkDescriptorBufferBindingInfoEXT descriptor_buffer_binding_info = vku::InitStructHelper();
descriptor_buffer_binding_info.address = buffer_address;
descriptor_buffer_binding_info.usage = VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT;
vk::CmdBindDescriptorBuffersEXT(m_command_buffer, 1, &descriptor_buffer_binding_info);
uint32_t buffer_index = 0;
VkDeviceSize buffer_offset = 0;
vk::CmdSetDescriptorBufferOffsetsEXT(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_layout, 0, 1, &buffer_index,
&buffer_offset);
vk::CmdDispatch(m_command_buffer, 1, 1, 1);
m_command_buffer.End();
m_default_queue->SubmitAndWait(m_command_buffer);
}
// TODO - Add support in GPU-AV for this
TEST_F(NegativeGpuAVDescriptorBuffer, DISABLED_PostProcesingOnly) {
std::vector<VkLayerSettingEXT> layer_settings = {
{OBJECT_LAYER_NAME, "gpuav_descriptor_checks", VK_LAYER_SETTING_TYPE_BOOL32_EXT, 1, &kVkFalse},
{OBJECT_LAYER_NAME, "gpuav_buffer_address_oob", VK_LAYER_SETTING_TYPE_BOOL32_EXT, 1, &kVkFalse},
{OBJECT_LAYER_NAME, "gpuav_vertex_attribute_fetch_oob", VK_LAYER_SETTING_TYPE_BOOL32_EXT, 1, &kVkFalse},
};
SetTargetApiVersion(VK_API_VERSION_1_2);
AddRequiredExtensions(VK_KHR_MAINTENANCE_5_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::descriptorBindingSampledImageUpdateAfterBind);
AddRequiredFeature(vkt::Feature::maintenance5);
RETURN_IF_SKIP(InitBasicDescriptorBuffer(layer_settings));
InitRenderTarget();
const char* fs_source = R"glsl(
#version 450
layout(set=0, binding=0) uniform sampler3D s;
layout(location=0) out vec4 color;
void main() {
color = texture(s, vec3(0));
}
)glsl";
VkShaderObj vs(*m_device, kVertexDrawPassthroughGlsl, VK_SHADER_STAGE_VERTEX_BIT);
VkShaderObj fs(*m_device, fs_source, VK_SHADER_STAGE_FRAGMENT_BIT);
vkt::Image image(*m_device, 16, 16, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT);
image.SetLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
vkt::ImageView image_view = image.CreateView();
vkt::Sampler sampler(*m_device, SafeSaneSamplerCreateInfo());
std::vector<VkDescriptorSetLayoutBinding> bindings = {
{0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_ALL, nullptr}};
vkt::DescriptorSetLayout ds_layout(*m_device, bindings, VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT);
vkt::PipelineLayout pipeline_layout(*m_device, {&ds_layout});
VkDeviceSize ds_layout_size = ds_layout.GetDescriptorBufferSize();
vkt::Buffer descriptor_buffer(
*m_device, ds_layout_size,
VK_BUFFER_USAGE_SAMPLER_DESCRIPTOR_BUFFER_BIT_EXT | VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT,
vkt::device_address);
uint8_t* mapped_descriptor_data = (uint8_t*)descriptor_buffer.Memory().Map();
vkt::DescriptorGetInfo get_info_combined(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, sampler, image_view,
VK_IMAGE_LAYOUT_GENERAL);
vk::GetDescriptorEXT(device(), get_info_combined, descriptor_buffer_properties.combinedImageSamplerDescriptorSize,
mapped_descriptor_data);
CreatePipelineHelper pipe(*this);
pipe.shader_stages_ = {vs.GetStageCreateInfo(), fs.GetStageCreateInfo()};
pipe.gp_ci_.flags |= VK_PIPELINE_CREATE_DESCRIPTOR_BUFFER_BIT_EXT;
pipe.gp_ci_.layout = pipeline_layout;
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
VkDescriptorBufferBindingInfoEXT descriptor_buffer_binding_info = vku::InitStructHelper();
descriptor_buffer_binding_info.address = descriptor_buffer.Address();
descriptor_buffer_binding_info.usage =
VK_BUFFER_USAGE_SAMPLER_DESCRIPTOR_BUFFER_BIT_EXT | VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT;
vk::CmdBindDescriptorBuffersEXT(m_command_buffer, 1, &descriptor_buffer_binding_info);
uint32_t buffer_index = 0;
VkDeviceSize buffer_offset = 0;
vk::CmdSetDescriptorBufferOffsetsEXT(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, 1, &buffer_index,
&buffer_offset);
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_command_buffer.EndRenderPass();
m_command_buffer.End();
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-viewType-07752");
m_default_queue->SubmitAndWait(m_command_buffer);
m_errorMonitor->VerifyFound();
}