Skip to content

Commit

Permalink
tests: Add Mutable Descriptor tests
Browse files Browse the repository at this point in the history
  • Loading branch information
spencer-lunarg committed Nov 26, 2024
1 parent 4ce616a commit 74c1155
Show file tree
Hide file tree
Showing 7 changed files with 393 additions and 39 deletions.
39 changes: 7 additions & 32 deletions layers/state_tracker/descriptor_sets.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1151,7 +1151,7 @@ void vvl::MutableDescriptor::WriteUpdate(DescriptorSet &set_state, const Validat

void vvl::MutableDescriptor::CopyUpdate(DescriptorSet &set_state, const ValidationStateTracker &dev_data,
const Descriptor &src, bool is_bindless, VkDescriptorType src_type) {
VkDeviceSize src_size = 0;
VkDeviceSize buffer_size = 0;
switch (src.GetClass()) {
case DescriptorClass::PlainSampler: {
auto &sampler_src = static_cast<const SamplerDescriptor &>(src);
Expand Down Expand Up @@ -1180,15 +1180,15 @@ void vvl::MutableDescriptor::CopyUpdate(DescriptorSet &set_state, const Validati
case DescriptorClass::TexelBuffer: {
ReplaceStatePtr(set_state, buffer_view_state_, static_cast<const TexelDescriptor &>(src).GetSharedBufferViewState(),
is_bindless);
src_size = buffer_view_state_ ? buffer_view_state_->Size() : vvl::kU32Max;
buffer_size = buffer_view_state_ ? buffer_view_state_->Size() : vvl::kU32Max;
break;
}
case DescriptorClass::GeneralBuffer: {
const auto buff_desc = static_cast<const BufferDescriptor &>(src);
offset_ = buff_desc.GetOffset();
range_ = buff_desc.GetRange();
ReplaceStatePtr(set_state, buffer_state_, buff_desc.GetSharedBufferState(), is_bindless);
src_size = range_;
buffer_size = range_;
break;
}
case DescriptorClass::AccelerationStructure: {
Expand Down Expand Up @@ -1250,45 +1250,20 @@ void vvl::MutableDescriptor::CopyUpdate(DescriptorSet &set_state, const Validati
case DescriptorClass::Invalid:
break;
}
src_size = mutable_src.GetBufferSize();
buffer_size = mutable_src.GetBufferSize();
break;
}
case vvl::DescriptorClass::InlineUniform:
case vvl::DescriptorClass::Invalid:
break;
}
SetDescriptorType(src_type, src_size);
SetDescriptorType(src_type, buffer_size);
}

void vvl::MutableDescriptor::SetDescriptorType(VkDescriptorType type, VkDeviceSize buffer_size) {
active_descriptor_type_ = type;
buffer_size_ = buffer_size;
}
void vvl::MutableDescriptor::SetDescriptorType(VkDescriptorType src_type, const Descriptor *src) {
active_descriptor_type_ = src_type;
if (src->GetClass() == vvl::DescriptorClass::GeneralBuffer) {
auto buffer = static_cast<const vvl::BufferDescriptor *>(src)->GetBuffer();
if (buffer == VK_NULL_HANDLE) {
buffer_size_ = vvl::kU32Max;
} else {
auto buffer_state = static_cast<const vvl::BufferDescriptor *>(src)->GetBufferState();
buffer_size_ = static_cast<uint32_t>(buffer_state->create_info.size);
}
} else if (src->GetClass() == vvl::DescriptorClass::TexelBuffer) {
auto buffer_view = static_cast<const vvl::TexelDescriptor *>(src)->GetBufferView();
if (buffer_view == VK_NULL_HANDLE) {
buffer_size_ = vvl::kU32Max;
} else {
auto buffer_view_state = static_cast<const vvl::TexelDescriptor *>(src)->GetBufferViewState();
buffer_size_ = static_cast<uint32_t>(buffer_view_state->buffer_state->create_info.size);
}
} else if (src->GetClass() == vvl::DescriptorClass::Mutable) {
auto descriptor = static_cast<const vvl::MutableDescriptor *>(src);
buffer_size_ = descriptor->GetBufferSize();
} else {
buffer_size_ = 0;
}
}

VkDeviceSize vvl::MutableDescriptor::GetEffectiveRange() const {
// The buffer can be null if using nullDescriptors, if that is the case, the size/range will not be accessed
Expand All @@ -1302,7 +1277,7 @@ VkDeviceSize vvl::MutableDescriptor::GetEffectiveRange() const {
}

void vvl::MutableDescriptor::UpdateDrawState(ValidationStateTracker *dev_data, vvl::CommandBuffer &cb_state) {
auto active_class = DescriptorTypeToClass(active_descriptor_type_);
const vvl::DescriptorClass active_class = ActiveClass();
if (active_class == DescriptorClass::Image || active_class == DescriptorClass::ImageSampler) {
if (image_view_state_) {
cb_state.SetImageViewInitialLayout(*image_view_state_, image_layout_);
Expand All @@ -1312,7 +1287,7 @@ void vvl::MutableDescriptor::UpdateDrawState(ValidationStateTracker *dev_data, v

bool vvl::MutableDescriptor::AddParent(StateObject *state_object) {
bool result = false;
auto active_class = DescriptorTypeToClass(active_descriptor_type_);
const vvl::DescriptorClass active_class = ActiveClass();
switch (active_class) {
case DescriptorClass::PlainSampler:
if (sampler_state_) {
Expand Down
1 change: 0 additions & 1 deletion layers/state_tracker/descriptor_sets.h
Original file line number Diff line number Diff line change
Expand Up @@ -589,7 +589,6 @@ class MutableDescriptor : public Descriptor {
VkDescriptorType type) override;

void SetDescriptorType(VkDescriptorType type, VkDeviceSize buffer_size);
void SetDescriptorType(VkDescriptorType src_type, const Descriptor *src);
VkDeviceSize GetBufferSize() const { return buffer_size_; }

std::shared_ptr<vvl::Sampler> GetSharedSamplerState() const { return sampler_state_; }
Expand Down
54 changes: 49 additions & 5 deletions tests/unit/descriptors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1488,6 +1488,54 @@ TEST_F(NegativeDescriptors, DISABLED_ConstantArrayElementNotBound) {
m_command_buffer.End();
}

// https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/8918
TEST_F(NegativeDescriptors, DISABLED_MutableBufferUpdate) {
AddRequiredExtensions(VK_EXT_MUTABLE_DESCRIPTOR_TYPE_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::mutableDescriptorType);
RETURN_IF_SKIP(Init());

VkDescriptorType desc_types[2] = {
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
};

VkMutableDescriptorTypeListEXT type_list = {};
type_list.descriptorTypeCount = 2;
type_list.pDescriptorTypes = desc_types;

VkMutableDescriptorTypeCreateInfoEXT mdtci = vku::InitStructHelper();
mdtci.mutableDescriptorTypeListCount = 1;
mdtci.pMutableDescriptorTypeLists = &type_list;

OneOffDescriptorSet descriptor_set(m_device, {{0, VK_DESCRIPTOR_TYPE_MUTABLE_EXT, 1, VK_SHADER_STAGE_COMPUTE_BIT, nullptr}}, 0,
&mdtci);
const vkt::PipelineLayout pipeline_layout(*m_device, {&descriptor_set.layout_});

vkt::Buffer buffer(*m_device, 32, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);

const char *cs_source = R"glsl(
#version 450
layout(set=0, binding=0) buffer SSBO { uint x; };
void main() {
x = 0;
}
)glsl";

CreateComputePipelineHelper pipe(*this);
pipe.cs_ = std::make_unique<VkShaderObj>(this, cs_source, VK_SHADER_STAGE_COMPUTE_BIT);
pipe.cp_ci_.layout = pipeline_layout.handle();
pipe.CreateComputePipeline();

m_command_buffer.Begin();
vk::CmdBindPipeline(m_command_buffer.handle(), VK_PIPELINE_BIND_POINT_COMPUTE, pipe.Handle());
vk::CmdBindDescriptorSets(m_command_buffer.handle(), VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_layout.handle(), 0, 1,
&descriptor_set.set_, 0, NULL);
m_errorMonitor->SetDesiredError("VUID-vkCmdDispatch-None-08114");
vk::CmdDispatch(m_command_buffer.handle(), 1, 1, 1);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}

TEST_F(NegativeDescriptors, UpdateDescriptorSetMismatchType) {
RETURN_IF_SKIP(Init());

Expand Down Expand Up @@ -3579,11 +3627,7 @@ TEST_F(NegativeDescriptors, MutableDescriptorSetLayoutMissingFeature) {
TEST_DESCRIPTION("Create mutable descriptor set layout without mutableDescriptorType feature enabled.");

AddRequiredExtensions(VK_EXT_MUTABLE_DESCRIPTOR_TYPE_EXTENSION_NAME);
RETURN_IF_SKIP(InitFramework());
VkPhysicalDeviceMutableDescriptorTypeFeaturesEXT mutable_descriptor_type_features = vku::InitStructHelper();
mutable_descriptor_type_features.mutableDescriptorType = VK_FALSE;
VkPhysicalDeviceFeatures2KHR features2 = vku::InitStructHelper(&mutable_descriptor_type_features);
RETURN_IF_SKIP(InitState(nullptr, &features2));
RETURN_IF_SKIP(Init());
InitRenderTarget();

VkDescriptorSetLayoutBinding binding = {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr};
Expand Down
74 changes: 74 additions & 0 deletions tests/unit/gpu_av_descriptor_indexing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
* 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/descriptor_helper.h"
Expand Down Expand Up @@ -1342,6 +1343,79 @@ TEST_F(NegativeGpuAVDescriptorIndexing, ImageArrayDynamicIndexing) {
m_errorMonitor->VerifyFound();
}

// TODO - cb_state.image_layout_map is empty after updating a mutable descriptor
// https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/8918
TEST_F(NegativeGpuAVDescriptorIndexing, DISABLED_ImageLayoutMutable) {
TEST_DESCRIPTION("Invalid image layout with mutable descriptors");
AddRequiredExtensions(VK_EXT_MUTABLE_DESCRIPTOR_TYPE_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::mutableDescriptorType);
RETURN_IF_SKIP(InitGpuVUDescriptorIndexing());

const char *cs = R"glsl(
#version 450
layout(set=0, binding=0) uniform sampler2D s[2];
layout(set=0, binding=1) buffer SSBO { uint index; };
void main(){
vec4 v = 2.0 * texture(s[index], vec2(0.0));
}
)glsl";

vkt::Buffer storage_buffer(*m_device, 32, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, kHostVisibleMemProps);
uint32_t *storage_buffer_ptr = (uint32_t *)storage_buffer.Memory().Map();
storage_buffer_ptr[0] = 1;
storage_buffer.Memory().Unmap();

VkDescriptorType desc_types[2] = {
VK_DESCRIPTOR_TYPE_SAMPLER,
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
};

VkMutableDescriptorTypeListEXT type_list = {};
type_list.descriptorTypeCount = 2;
type_list.pDescriptorTypes = desc_types;

VkMutableDescriptorTypeCreateInfoEXT mdtci = vku::InitStructHelper();
mdtci.mutableDescriptorTypeListCount = 1;
mdtci.pMutableDescriptorTypeLists = &type_list;

OneOffDescriptorSet descriptor_set(m_device,
{{0, VK_DESCRIPTOR_TYPE_MUTABLE_EXT, 2, VK_SHADER_STAGE_COMPUTE_BIT, nullptr},
{1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT, nullptr}},
0, &mdtci);
const vkt::PipelineLayout pipeline_layout(*m_device, {&descriptor_set.layout_});

CreateComputePipelineHelper pipe(*this);
pipe.cs_ = std::make_unique<VkShaderObj>(this, cs, VK_SHADER_STAGE_COMPUTE_BIT);
pipe.cp_ci_.layout = pipeline_layout.handle();
pipe.CreateComputePipeline();

const VkFormat fmt = VK_FORMAT_R8G8B8A8_UNORM;
vkt::Image image(*m_device, 64, 64, 1, fmt, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
image.SetLayout(VK_IMAGE_LAYOUT_GENERAL);

vkt::ImageView view = image.CreateView();
vkt::Sampler sampler(*m_device, SafeSaneSamplerCreateInfo());

descriptor_set.WriteDescriptorImageInfo(0, view, sampler, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, 0);
descriptor_set.WriteDescriptorImageInfo(0, view, sampler, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, 1);
descriptor_set.WriteDescriptorBufferInfo(1, storage_buffer, 0, VK_WHOLE_SIZE, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
descriptor_set.UpdateDescriptorSets();

m_command_buffer.Begin();
vk::CmdBindDescriptorSets(m_command_buffer.handle(), VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_layout.handle(), 0, 1,
&descriptor_set.set_, 0, nullptr);
vk::CmdBindPipeline(m_command_buffer.handle(), VK_PIPELINE_BIND_POINT_COMPUTE, pipe.Handle());
vk::CmdDispatch(m_command_buffer.handle(), 1, 1, 1);
m_command_buffer.End();

m_errorMonitor->SetDesiredError("UNASSIGNED-CoreValidation-DrawState-InvalidImageLayout");
m_default_queue->Submit(m_command_buffer);
m_default_queue->Wait();
m_errorMonitor->VerifyFound();
}

TEST_F(NegativeGpuAVDescriptorIndexing, UpdateAfterBind) {
TEST_DESCRIPTION("Exercise errors for updating a descriptor set after it is bound.");

Expand Down
61 changes: 61 additions & 0 deletions tests/unit/image.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5271,6 +5271,67 @@ TEST_F(NegativeImage, ComputeImageLayout11) {
m_errorMonitor->VerifyFound();
}

// https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/8918
// This fails to create descriptor on RADV, might need to adjust OneOffDescriptorSet
TEST_F(NegativeImage, DISABLED_ImageLayoutMutable) {
TEST_DESCRIPTION("Invalid image layout with mutable descriptors");
AddRequiredExtensions(VK_EXT_MUTABLE_DESCRIPTOR_TYPE_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::mutableDescriptorType);
RETURN_IF_SKIP(Init());

const char *cs = R"glsl(
#version 450
layout(set=0, binding=0) uniform sampler2D s;
void main(){
vec4 v = 2.0 * texture(s, vec2(0.0));
}
)glsl";

VkDescriptorType desc_types[2] = {
VK_DESCRIPTOR_TYPE_SAMPLER,
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
};

VkMutableDescriptorTypeListEXT type_list = {};
type_list.descriptorTypeCount = 2;
type_list.pDescriptorTypes = desc_types;

VkMutableDescriptorTypeCreateInfoEXT mdtci = vku::InitStructHelper();
mdtci.mutableDescriptorTypeListCount = 1;
mdtci.pMutableDescriptorTypeLists = &type_list;

OneOffDescriptorSet descriptor_set(m_device, {{0, VK_DESCRIPTOR_TYPE_MUTABLE_EXT, 1, VK_SHADER_STAGE_COMPUTE_BIT, nullptr}}, 0,
&mdtci);
const vkt::PipelineLayout pipeline_layout(*m_device, {&descriptor_set.layout_});

CreateComputePipelineHelper pipe(*this);
pipe.cs_ = std::make_unique<VkShaderObj>(this, cs, VK_SHADER_STAGE_COMPUTE_BIT);
pipe.cp_ci_.layout = pipeline_layout.handle();
pipe.CreateComputePipeline();

const VkFormat fmt = VK_FORMAT_R8G8B8A8_UNORM;
vkt::Image image(*m_device, 64, 64, 1, fmt, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
image.SetLayout(VK_IMAGE_LAYOUT_GENERAL);

vkt::ImageView view = image.CreateView();
vkt::Sampler sampler(*m_device, SafeSaneSamplerCreateInfo());

descriptor_set.WriteDescriptorImageInfo(0, view, sampler, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
descriptor_set.UpdateDescriptorSets();

m_command_buffer.Begin();
vk::CmdBindDescriptorSets(m_command_buffer.handle(), VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_layout.handle(), 0, 1,
&descriptor_set.set_, 0, nullptr);
vk::CmdBindPipeline(m_command_buffer.handle(), VK_PIPELINE_BIND_POINT_COMPUTE, pipe.Handle());
vk::CmdDispatch(m_command_buffer.handle(), 1, 1, 1);
m_command_buffer.End();

m_errorMonitor->SetDesiredError("UNASSIGNED-CoreValidation-DrawState-InvalidImageLayout");
m_default_queue->Submit(m_command_buffer);
m_default_queue->Wait();
m_errorMonitor->VerifyFound();
}

TEST_F(NegativeImage, GetPhysicalDeviceImageFormatProperties) {
TEST_DESCRIPTION("fail a call to GetPhysicalDeviceImageFormatProperties");
RETURN_IF_SKIP(Init());
Expand Down
Loading

0 comments on commit 74c1155

Please sign in to comment.