From 07f95e9b8975d32b81fe36234b607ef7702ffc1c Mon Sep 17 00:00:00 2001 From: Ricardo Garcia Date: Fri, 24 Jan 2020 09:39:06 +0100 Subject: [PATCH] Validate samplerless descriptor writes This commits adds a few tests that update image-related descriptors for descriptor types in which the sampler field of the VkDescriptorImageInfo structure, used in VkWriteDescriptorSet, is supposed to be ignored. Given that premise, the tests try to set the sampler field to different values like VK_NULL_HANDLE, a fixed value of 1 and the handler for a destroyed sampler. This should have no side effects. New tests: dEQP-VK.binding_model.descriptor_update.samplerless.* Components: Vulkan VK-GL-CTS issue: 2172 Change-Id: I87bf4226738ecd2ff7d2c7aa23551f22d43a8637 --- android/cts/master/vk-master.txt | 9 + .../vktBindingDescriptorUpdateTests.cpp | 567 ++++++++++++++++++ .../mustpass/master/vk-default-no-waivers.txt | 9 + .../vulkancts/mustpass/master/vk-default.txt | 9 + 4 files changed, 594 insertions(+) diff --git a/android/cts/master/vk-master.txt b/android/cts/master/vk-master.txt index e8b27e43c..b6f8b8023 100644 --- a/android/cts/master/vk-master.txt +++ b/android/cts/master/vk-master.txt @@ -298167,6 +298167,15 @@ dEQP-VK.binding_model.shader_access.secondary_cmd_buf.with_push_template.storage dEQP-VK.binding_model.shader_access.secondary_cmd_buf.with_push_template.storage_buffer.vertex_fragment.descriptor_array.offset_view_zero dEQP-VK.binding_model.shader_access.secondary_cmd_buf.with_push_template.storage_buffer.vertex_fragment.descriptor_array.offset_view_nonzero dEQP-VK.binding_model.descriptor_update.empty_descriptor.uniform_buffer +dEQP-VK.binding_model.descriptor_update.samplerless.sampled_img_sampler_zero +dEQP-VK.binding_model.descriptor_update.samplerless.sampled_img_sampler_one +dEQP-VK.binding_model.descriptor_update.samplerless.sampled_img_sampler_destroyed +dEQP-VK.binding_model.descriptor_update.samplerless.storage_img_sampler_zero +dEQP-VK.binding_model.descriptor_update.samplerless.storage_img_sampler_one +dEQP-VK.binding_model.descriptor_update.samplerless.storage_img_sampler_destroyed +dEQP-VK.binding_model.descriptor_update.samplerless.input_attachment_sampler_zero +dEQP-VK.binding_model.descriptor_update.samplerless.input_attachment_sampler_one +dEQP-VK.binding_model.descriptor_update.samplerless.input_attachment_sampler_destroyed dEQP-VK.binding_model.descriptorset_random.sets4.noarray.ubolimitlow.sbolimitlow.imglimitlow.noiub.comp.noia.0 dEQP-VK.binding_model.descriptorset_random.sets4.noarray.ubolimitlow.sbolimitlow.imglimitlow.noiub.comp.noia.1 dEQP-VK.binding_model.descriptorset_random.sets4.noarray.ubolimitlow.sbolimitlow.imglimitlow.noiub.comp.noia.2 diff --git a/external/vulkancts/modules/vulkan/binding_model/vktBindingDescriptorUpdateTests.cpp b/external/vulkancts/modules/vulkan/binding_model/vktBindingDescriptorUpdateTests.cpp index 67dfa046e..5cbd427fc 100644 --- a/external/vulkancts/modules/vulkan/binding_model/vktBindingDescriptorUpdateTests.cpp +++ b/external/vulkancts/modules/vulkan/binding_model/vktBindingDescriptorUpdateTests.cpp @@ -30,6 +30,20 @@ #include "vkMemUtil.hpp" #include "vkBuilderUtil.hpp" #include "vkQueryUtil.hpp" +#include "vkTypeUtil.hpp" +#include "vkObjUtil.hpp" +#include "vkCmdUtil.hpp" +#include "vkImageUtil.hpp" +#include "vkBarrierUtil.hpp" +#include "vkImageWithMemory.hpp" +#include "vkBufferWithMemory.hpp" + +#include "tcuTexture.hpp" +#include "tcuTestLog.hpp" + +#include +#include +#include namespace vkt { @@ -126,6 +140,558 @@ tcu::TestCaseGroup* createEmptyDescriptorUpdateTests (tcu::TestContext& testCtx) return group.release(); } +enum class PointerCase +{ + ZERO = 0, + ONE, + DESTROYED, +}; + +struct SamplerlessParams +{ + vk::VkDescriptorType type; + PointerCase pointer; +}; + +class SamplerlessDescriptorWriteTestCase : public vkt::TestCase +{ +public: + SamplerlessDescriptorWriteTestCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const SamplerlessParams& params); + virtual ~SamplerlessDescriptorWriteTestCase (void) {} + + virtual void initPrograms (vk::SourceCollections& programCollection) const; + virtual vkt::TestInstance* createInstance (Context& context) const; + virtual void checkSupport (Context& context) const; + + vk::VkFormatFeatureFlagBits getMainImageFeature (void) const; + + static const vk::VkFormat kImageFormat = vk::VK_FORMAT_R8G8B8A8_UNORM; +private: + SamplerlessParams m_params; +}; + +class SamplerlessDescriptorWriteTestInstance : public vkt::TestInstance +{ +public: + SamplerlessDescriptorWriteTestInstance (Context& context, const SamplerlessParams& params); + virtual ~SamplerlessDescriptorWriteTestInstance (void) {} + + vk::VkSampler getSamplerHandle (void) const; + virtual tcu::TestStatus iterate (void); + + vk::VkExtent3D getMainImageExtent (void) const; + vk::VkImageUsageFlags getMainImageUsage (void) const; + vk::VkImageLayout getMainImageShaderLayout (void) const; + + static const vk::VkFormat kImageFormat = SamplerlessDescriptorWriteTestCase::kImageFormat; + static const vk::VkExtent3D kFramebufferExtent; + static const vk::VkExtent3D kMinimumExtent; + static const tcu::Vec4 kDescriptorColor; +private: + SamplerlessParams m_params; +}; + +const vk::VkExtent3D SamplerlessDescriptorWriteTestInstance::kFramebufferExtent = vk::makeExtent3D(64u, 64u, 1u); +const vk::VkExtent3D SamplerlessDescriptorWriteTestInstance::kMinimumExtent = vk::makeExtent3D(1u, 1u, 1u); +const tcu::Vec4 SamplerlessDescriptorWriteTestInstance::kDescriptorColor {0.0f, 1.0f, 0.0f, 1.0f}; + +SamplerlessDescriptorWriteTestCase::SamplerlessDescriptorWriteTestCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const SamplerlessParams& params) + : vkt::TestCase{testCtx, name, description} + , m_params{params} +{ +} + +void SamplerlessDescriptorWriteTestCase::initPrograms (vk::SourceCollections& programCollection) const +{ + const std::string vertexShader = + "#version 450\n" + "layout(location=0) in vec4 position;\n" + "void main() { gl_Position = position; }\n"; + + programCollection.glslSources.add("vert") << glu::VertexSource(vertexShader); + + std::string descriptorDecl; + std::string readOp; + std::string extensions; + + switch (m_params.type) + { + case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: + extensions = "#extension GL_EXT_samplerless_texture_functions : require\n"; + descriptorDecl = "layout(set=0, binding=0) uniform texture2D img;"; + readOp = "texelFetch(img, ivec2(0, 0), 0)"; + break; + case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: + descriptorDecl = "layout(rgba8, set=0, binding=0) uniform image2D img;"; + readOp = "imageLoad(img, ivec2(0, 0))"; + break; + case vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: + descriptorDecl = "layout(input_attachment_index=0, set=0, binding=0) uniform subpassInput img;"; + readOp = "subpassLoad(img)"; + break; + default: + DE_ASSERT(false); + break; + } + + std::ostringstream fragmentShader; + + fragmentShader + << "#version 450\n" + << extensions + << descriptorDecl << "\n" + << "layout(location = 0) out vec4 color_out;\n" + << "void main()\n" + << "{\n" + << " color_out = " << readOp << ";\n" + << "}\n" + ; + + programCollection.glslSources.add("frag") << glu::FragmentSource(fragmentShader.str()); +} + +vk::VkFormatFeatureFlagBits SamplerlessDescriptorWriteTestCase::getMainImageFeature (void) const +{ + vk::VkFormatFeatureFlagBits feature = static_cast(0); + + switch (m_params.type) + { + case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: feature = vk::VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT; break; + case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: feature = vk::VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT; break; + case vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: feature = vk::VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT; break; + default: + DE_ASSERT(false); + break; + } + + return feature; +} + +void SamplerlessDescriptorWriteTestCase::checkSupport (Context& context) const +{ + const auto& vki = context.getInstanceInterface(); + const auto physicalDevice = context.getPhysicalDevice(); + const auto mainFeature = getMainImageFeature(); + + const vk::VkFormatFeatureFlags features = + ( + vk::VK_FORMAT_FEATURE_TRANSFER_DST_BIT | // For color clearing. + vk::VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | // For the separate frame buffer image (uses the same format). + mainFeature + ); + + const auto props = vk::getPhysicalDeviceFormatProperties(vki, physicalDevice, kImageFormat); + if ((props.optimalTilingFeatures & features) != features) + TCU_THROW(NotSupportedError, "Image format does not support the required features"); +} + +vkt::TestInstance* SamplerlessDescriptorWriteTestCase::createInstance (Context& context) const +{ + return new SamplerlessDescriptorWriteTestInstance{context, m_params}; +} + +SamplerlessDescriptorWriteTestInstance::SamplerlessDescriptorWriteTestInstance (Context& context, const SamplerlessParams& params) + : vkt::TestInstance{context} + , m_params{params} +{ +} + +struct DestroyedSampler +{ + vk::VkSampler sampler; + + DestroyedSampler (Context& context) + : sampler{DE_NULL} + { + const vk::VkSamplerCreateInfo createInfo = + { + vk::VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // VkStructureType sType; + nullptr, // const void* pNext; + 0u, // VkSamplerCreateFlags flags; + vk::VK_FILTER_NEAREST, // VkFilter magFilter; + vk::VK_FILTER_NEAREST, // VkFilter minFilter; + vk::VK_SAMPLER_MIPMAP_MODE_NEAREST, // VkSamplerMipmapMode mipmapMode; + vk::VK_SAMPLER_ADDRESS_MODE_REPEAT, // VkSamplerAddressMode addressModeU; + vk::VK_SAMPLER_ADDRESS_MODE_REPEAT, // VkSamplerAddressMode addressModeV; + vk::VK_SAMPLER_ADDRESS_MODE_REPEAT, // VkSamplerAddressMode addressModeW; + 0.0f, // float mipLodBias; + VK_FALSE, // VkBool32 anisotropyEnable; + 1.0f, // float maxAnisotropy; + VK_FALSE, // VkBool32 compareEnable; + vk::VK_COMPARE_OP_NEVER, // VkCompareOp compareOp; + 0.0f, // float minLod; + 0.0f, // float maxLod; + vk::VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, // VkBorderColor borderColor; + VK_FALSE, // VkBool32 unnormalizedCoordinates; + }; + const auto newSampler = vk::createSampler(context.getDeviceInterface(), context.getDevice(), &createInfo); + sampler = newSampler.get(); + // newSampler will be destroyed here and sampler will hold the former handle. + } +}; + +vk::VkSampler SamplerlessDescriptorWriteTestInstance::getSamplerHandle (void) const +{ + if (m_params.pointer == PointerCase::ZERO) return vk::VkSampler{DE_NULL}; + if (m_params.pointer == PointerCase::ONE) return vk::VkSampler{1}; + static const DestroyedSampler destroyedSampler{m_context}; + return destroyedSampler.sampler; +} + +vk::VkExtent3D SamplerlessDescriptorWriteTestInstance::getMainImageExtent (void) const +{ + const vk::VkExtent3D* extent = nullptr; + + switch (m_params.type) + { + case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: // fallthrough + case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: extent = &kMinimumExtent; break; + case vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: extent = &kFramebufferExtent; break; + default: + DE_ASSERT(false); + break; + } + + return *extent; +} + +vk::VkImageUsageFlags SamplerlessDescriptorWriteTestInstance::getMainImageUsage (void) const +{ + vk::VkImageUsageFlags usage = vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT; // Used when clearing the image. + + switch (m_params.type) + { + case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: usage |= vk::VK_IMAGE_USAGE_SAMPLED_BIT; break; + case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: usage |= vk::VK_IMAGE_USAGE_STORAGE_BIT; break; + case vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: usage |= vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; break; + default: + DE_ASSERT(false); + break; + } + + return usage; +} + +vk::VkImageLayout SamplerlessDescriptorWriteTestInstance::getMainImageShaderLayout (void) const +{ + vk::VkImageLayout layout = vk::VK_IMAGE_LAYOUT_UNDEFINED; + + switch (m_params.type) + { + case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: // fallthrough + case vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: layout = vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; break; + case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: layout = vk::VK_IMAGE_LAYOUT_GENERAL; break; + default: + DE_ASSERT(false); + break; + } + + return layout; +} + + +tcu::TestStatus SamplerlessDescriptorWriteTestInstance::iterate (void) +{ + const auto& vkd = m_context.getDeviceInterface(); + const auto device = m_context.getDevice(); + auto& allocator = m_context.getDefaultAllocator(); + const auto queue = m_context.getUniversalQueue(); + const auto queueIndex = m_context.getUniversalQueueFamilyIndex(); + const auto tcuFormat = vk::mapVkFormat(kImageFormat); + + const vk::VkImageCreateInfo mainImgCreateInfo = + { + vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; + nullptr, // const void* pNext; + 0u, // VkImageCreateFlags flags; + vk::VK_IMAGE_TYPE_2D, // VkImageType imageType; + kImageFormat, // VkFormat format; + getMainImageExtent(), // VkExtent3D extent; + 1u, // deUint32 mipLevels; + 1u, // deUint32 arrayLayers; + vk::VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; + vk::VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; + getMainImageUsage(), // VkImageUsageFlags usage; + vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; + 1u, // deUint32 queueFamilyIndexCount; + &queueIndex, // const deUint32* pQueueFamilyIndices; + vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; + }; + + const vk::VkImageCreateInfo fbImgCreateInfo = + { + vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; + nullptr, // const void* pNext; + 0u, // VkImageCreateFlags flags; + vk::VK_IMAGE_TYPE_2D, // VkImageType imageType; + kImageFormat, // VkFormat format; + kFramebufferExtent, // VkExtent3D extent; + 1u, // deUint32 mipLevels; + 1u, // deUint32 arrayLayers; + vk::VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; + vk::VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; + (vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | // VkImageUsageFlags usage; + vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT), // Used when verifying the image. + vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; + 1u, // deUint32 queueFamilyIndexCount; + &queueIndex, // const deUint32* pQueueFamilyIndices; + vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; + }; + + // Create main and framebuffer images. + const vk::ImageWithMemory mainImage {vkd, device, allocator, mainImgCreateInfo, vk::MemoryRequirement::Any}; + const vk::ImageWithMemory fbImage {vkd, device, allocator, fbImgCreateInfo, vk::MemoryRequirement::Any}; + + // Corresponding image views. + const auto colorSubresourceRange = vk::makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u); + const auto mainView = vk::makeImageView(vkd, device, mainImage.get(), vk::VK_IMAGE_VIEW_TYPE_2D, kImageFormat, colorSubresourceRange); + const auto fbView = vk::makeImageView(vkd, device, fbImage.get(), vk::VK_IMAGE_VIEW_TYPE_2D, kImageFormat, colorSubresourceRange); + + // Buffer to copy rendering result to. + const vk::VkDeviceSize resultsBufferSize = static_cast(static_cast(tcu::getPixelSize(tcuFormat)) * kFramebufferExtent.width * kFramebufferExtent.height * kFramebufferExtent.depth); + const auto resultsBufferInfo = vk::makeBufferCreateInfo(resultsBufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT); + const vk::BufferWithMemory resultsBuffer {vkd, device, allocator, resultsBufferInfo, vk::MemoryRequirement::HostVisible}; + + const std::vector fullScreenQuad = + { + { -1.f, -1.f, 0.f, 1.f }, + { 1.f, -1.f, 0.f, 1.f }, + { -1.f, 1.f, 0.f, 1.f }, + { -1.f, 1.f, 0.f, 1.f }, + { 1.f, -1.f, 0.f, 1.f }, + { 1.f, 1.f, 0.f, 1.f }, + }; + + // Vertex buffer. + const vk::VkDeviceSize vertexBufferSize = static_cast(fullScreenQuad.size() * sizeof(decltype(fullScreenQuad)::value_type)); + const auto vertexBufferInfo = vk::makeBufferCreateInfo(vertexBufferSize, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); + const vk::BufferWithMemory vertexBuffer {vkd, device, allocator, vertexBufferInfo, vk::MemoryRequirement::HostVisible}; + + // Copy data to vertex buffer. + const auto& vertexAlloc = vertexBuffer.getAllocation(); + const auto vertexDataPtr = reinterpret_cast(vertexAlloc.getHostPtr()) + vertexAlloc.getOffset(); + deMemcpy(vertexDataPtr, fullScreenQuad.data(), static_cast(vertexBufferSize)); + vk::flushAlloc(vkd, device, vertexAlloc); + + // Descriptor set layout. + vk::DescriptorSetLayoutBuilder layoutBuilder; + layoutBuilder.addSingleBinding(m_params.type, vk::VK_SHADER_STAGE_ALL_GRAPHICS); + const auto descriptorSetLayout = layoutBuilder.build(vkd, device); + + // Descriptor pool. + vk::DescriptorPoolBuilder poolBuilder; + poolBuilder.addType(m_params.type); + const auto descriptorPool = poolBuilder.build(vkd, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u); + + // Descriptor set. + const auto descriptorSet = vk::makeDescriptorSet(vkd, device, descriptorPool.get(), descriptorSetLayout.get()); + + // Update descriptor set with the descriptor. + // IMPORTANT: the chosen sampler handle is used here. + vk::DescriptorSetUpdateBuilder updateBuilder; + const auto descriptorImageInfo = vk::makeDescriptorImageInfo(getSamplerHandle(), mainView.get(), getMainImageShaderLayout()); + updateBuilder.writeSingle(descriptorSet.get(), vk::DescriptorSetUpdateBuilder::Location::binding(0u), m_params.type, &descriptorImageInfo); + updateBuilder.update(vkd, device); + + // Shader modules. + const auto vertexModule = vk::createShaderModule(vkd, device, m_context.getBinaryCollection().get("vert"), 0u); + const auto fragModule = vk::createShaderModule(vkd, device, m_context.getBinaryCollection().get("frag"), 0u); + + // Render pass. + const vk::VkAttachmentDescription fbAttachment = + { + 0u, // VkAttachmentDescriptionFlags flags; + kImageFormat, // VkFormat format; + vk::VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; + vk::VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp; + vk::VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; + vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; + vk::VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; + vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; + vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout; + }; + + std::vector attachmentDescs; + attachmentDescs.push_back(fbAttachment); + + if (m_params.type == vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT) + { + // Add it as a frame buffer attachment. + const vk::VkAttachmentDescription inputAttachment = + { + 0u, // VkAttachmentDescriptionFlags flags; + kImageFormat, // VkFormat format; + vk::VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; + vk::VK_ATTACHMENT_LOAD_OP_LOAD, // VkAttachmentLoadOp loadOp; + vk::VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp storeOp; + vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; + vk::VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; + getMainImageShaderLayout(), // VkImageLayout initialLayout; + getMainImageShaderLayout(), // VkImageLayout finalLayout; + }; + + attachmentDescs.push_back(inputAttachment); + } + + std::vector inputAttachments; + if (m_params.type == vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT) + { + const vk::VkAttachmentReference inputRef = + { + 1u, // deUint32 attachment; + getMainImageShaderLayout(), // VkImageLayout layout; + }; + + inputAttachments.push_back(inputRef); + } + + const vk::VkAttachmentReference colorRef = + { + 0u, // deUint32 attachment; + vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout layout; + }; + const std::vector colorAttachments(1u, colorRef); + + const vk::VkSubpassDescription subpass = + { + 0u, // VkSubpassDescriptionFlags flags; + vk::VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; + static_cast(inputAttachments.size()), // deUint32 inputAttachmentCount; + (inputAttachments.empty() ? nullptr : inputAttachments.data()), // const VkAttachmentReference* pInputAttachments; + static_cast(colorAttachments.size()), // deUint32 colorAttachmentCount; + colorAttachments.data(), // const VkAttachmentReference* pColorAttachments; + 0u, // const VkAttachmentReference* pResolveAttachments; + nullptr, // const VkAttachmentReference* pDepthStencilAttachment; + 0u, // deUint32 preserveAttachmentCount; + nullptr, // const deUint32* pPreserveAttachments; + }; + const std::vector subpasses(1u, subpass); + + const vk::VkRenderPassCreateInfo renderPassInfo = + { + vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType; + nullptr, // const void* pNext; + 0u, // VkRenderPassCreateFlags flags; + static_cast(attachmentDescs.size()), // deUint32 attachmentCount; + attachmentDescs.data(), // const VkAttachmentDescription* pAttachments; + static_cast(subpasses.size()), // deUint32 subpassCount; + subpasses.data(), // const VkSubpassDescription* pSubpasses; + 0u, // deUint32 dependencyCount; + nullptr, // const VkSubpassDependency* pDependencies; + }; + const auto renderPass = vk::createRenderPass(vkd, device, &renderPassInfo); + + // Framebuffer. + std::vector attachments; + attachments.push_back(fbView.get()); + if (m_params.type == vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT) + attachments.push_back(mainView.get()); + const auto framebuffer = vk::makeFramebuffer(vkd, device, renderPass.get(), static_cast(attachments.size()), attachments.data(), kFramebufferExtent.width, kFramebufferExtent.height, kFramebufferExtent.depth); + + // Pipeline layout. + const auto pipelineLayout = vk::makePipelineLayout(vkd, device, descriptorSetLayout.get()); + + // Graphics pipeline. + const std::vector viewports(1u, vk::makeViewport(kFramebufferExtent)); + const std::vector scissors(1u, vk::makeRect2D(kFramebufferExtent)); + + const auto pipeline = vk::makeGraphicsPipeline( + vkd, device, pipelineLayout.get(), + vertexModule.get(), DE_NULL, DE_NULL, DE_NULL, fragModule.get(), + renderPass.get(), viewports, scissors); + + // Command pool and command buffer. + const auto cmdPool = vk::createCommandPool(vkd, device, vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueIndex); + const auto cmdBufferPtr = vk::allocateCommandBuffer(vkd, device, cmdPool.get(), vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY); + const auto cmdBuffer = cmdBufferPtr.get(); + + // Draw quad. + const vk::VkRect2D renderArea = vk::makeRect2D(kFramebufferExtent); + const tcu::Vec4 clearFbColor (0.0f, 0.0f, 0.0f, 1.0f); + const vk::VkDeviceSize vertexBufferOffset = 0ull; + + const auto vtxBufferBarrier = vk::makeBufferMemoryBarrier(vk::VK_ACCESS_HOST_WRITE_BIT, vk::VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, vertexBuffer.get(), 0ull, vertexBufferSize); + const auto preClearBarrier = vk::makeImageMemoryBarrier(0u, vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, mainImage.get(), colorSubresourceRange); + const auto postClearBarrier = vk::makeImageMemoryBarrier(vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_ACCESS_SHADER_READ_BIT, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, getMainImageShaderLayout(), mainImage.get(), colorSubresourceRange); + const auto clearDescColor = vk::makeClearValueColor(kDescriptorColor); + + vk::beginCommandBuffer(vkd, cmdBuffer); + + vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0u, 0u, nullptr, 1u, &vtxBufferBarrier, 0u, nullptr); + vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &preClearBarrier); + vkd.cmdClearColorImage(cmdBuffer, mainImage.get(), vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearDescColor.color, 1u, &colorSubresourceRange); + vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &postClearBarrier); + + vk::beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), renderArea, clearFbColor); + vkd.cmdBindPipeline(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get()); + vkd.cmdBindDescriptorSets(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u, &descriptorSet.get(), 0u, nullptr); + vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset); + vkd.cmdDraw(cmdBuffer, static_cast(fullScreenQuad.size()), 1u, 0u, 0u); + vk::endRenderPass(vkd, cmdBuffer); + + const tcu::IVec2 copySize{static_cast(kFramebufferExtent.width), static_cast(kFramebufferExtent.height)}; + vk::copyImageToBuffer(vkd, cmdBuffer, fbImage.get(), resultsBuffer.get(), copySize); + + vk::endCommandBuffer(vkd, cmdBuffer); + vk::submitCommandsAndWait(vkd, device, queue, cmdBuffer); + + // Check results. + const auto& resultsBufferAlloc = resultsBuffer.getAllocation(); + vk::invalidateAlloc(vkd, device, resultsBufferAlloc); + + const auto resultsBufferPtr = reinterpret_cast(resultsBufferAlloc.getHostPtr()) + resultsBufferAlloc.getOffset(); + const tcu::ConstPixelBufferAccess resultPixels {tcuFormat, copySize[0], copySize[1], 1, resultsBufferPtr}; + + bool pass = true; + for (int x = 0; pass && x < resultPixels.getWidth(); ++x) + for (int y = 0; pass && y < resultPixels.getHeight(); ++y) + for (int z = 0; pass && z < resultPixels.getDepth(); ++z) + { + const auto pixel = resultPixels.getPixel(x, y, z); + pass = (pixel == kDescriptorColor); + } + + tcu::TestStatus status = tcu::TestStatus::pass("Pass"); + if (!pass) + { + auto& log = m_context.getTestContext().getLog(); + log << tcu::TestLog::Image("color", "Rendered image", resultPixels); + status = tcu::TestStatus::fail("Pixel mismatch; please check the rendered image"); + } + + return status; +} + +tcu::TestCaseGroup* createSamplerlessWriteTests (tcu::TestContext& testCtx) +{ + de::MovePtr group(new tcu::TestCaseGroup(testCtx, "samplerless", "Verify sampler unused with some descriptor image types")); + + const std::vector> descriptorTypes = + { + std::make_pair(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, "sampled_img"), + std::make_pair(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, "storage_img"), + std::make_pair(vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, "input_attachment"), + }; + + const std::vector> pointerCases = + { + std::make_pair(PointerCase::ZERO, "sampler_zero"), + std::make_pair(PointerCase::ONE, "sampler_one"), + std::make_pair(PointerCase::DESTROYED, "sampler_destroyed"), + }; + + for (const auto& typeCase : descriptorTypes) + for (const auto& pointerCase : pointerCases) + { + const std::string caseName = typeCase.second + "_" + pointerCase.second; + const SamplerlessParams params {typeCase.first, pointerCase.first}; + + group->addChild(new SamplerlessDescriptorWriteTestCase(testCtx, caseName, "", params)); + } + + return group.release(); +} + } // anonymous @@ -134,6 +700,7 @@ tcu::TestCaseGroup* createDescriptorUpdateTests (tcu::TestContext& testCtx) de::MovePtr group(new tcu::TestCaseGroup(testCtx, "descriptor_update", "Update descriptor sets")); group->addChild(createEmptyDescriptorUpdateTests(testCtx)); + group->addChild(createSamplerlessWriteTests(testCtx)); return group.release(); } diff --git a/external/vulkancts/mustpass/master/vk-default-no-waivers.txt b/external/vulkancts/mustpass/master/vk-default-no-waivers.txt index a6ba8283e..860e90012 100644 --- a/external/vulkancts/mustpass/master/vk-default-no-waivers.txt +++ b/external/vulkancts/mustpass/master/vk-default-no-waivers.txt @@ -298054,6 +298054,15 @@ dEQP-VK.binding_model.shader_access.secondary_cmd_buf.with_push_template.storage dEQP-VK.binding_model.shader_access.secondary_cmd_buf.with_push_template.storage_buffer.vertex_fragment.descriptor_array.offset_view_zero dEQP-VK.binding_model.shader_access.secondary_cmd_buf.with_push_template.storage_buffer.vertex_fragment.descriptor_array.offset_view_nonzero dEQP-VK.binding_model.descriptor_update.empty_descriptor.uniform_buffer +dEQP-VK.binding_model.descriptor_update.samplerless.sampled_img_sampler_zero +dEQP-VK.binding_model.descriptor_update.samplerless.sampled_img_sampler_one +dEQP-VK.binding_model.descriptor_update.samplerless.sampled_img_sampler_destroyed +dEQP-VK.binding_model.descriptor_update.samplerless.storage_img_sampler_zero +dEQP-VK.binding_model.descriptor_update.samplerless.storage_img_sampler_one +dEQP-VK.binding_model.descriptor_update.samplerless.storage_img_sampler_destroyed +dEQP-VK.binding_model.descriptor_update.samplerless.input_attachment_sampler_zero +dEQP-VK.binding_model.descriptor_update.samplerless.input_attachment_sampler_one +dEQP-VK.binding_model.descriptor_update.samplerless.input_attachment_sampler_destroyed dEQP-VK.binding_model.descriptorset_random.sets4.noarray.ubolimitlow.sbolimitlow.imglimitlow.noiub.comp.noia.0 dEQP-VK.binding_model.descriptorset_random.sets4.noarray.ubolimitlow.sbolimitlow.imglimitlow.noiub.comp.noia.1 dEQP-VK.binding_model.descriptorset_random.sets4.noarray.ubolimitlow.sbolimitlow.imglimitlow.noiub.comp.noia.2 diff --git a/external/vulkancts/mustpass/master/vk-default.txt b/external/vulkancts/mustpass/master/vk-default.txt index bfea8b2bb..f917c52d2 100644 --- a/external/vulkancts/mustpass/master/vk-default.txt +++ b/external/vulkancts/mustpass/master/vk-default.txt @@ -298054,6 +298054,15 @@ dEQP-VK.binding_model.shader_access.secondary_cmd_buf.with_push_template.storage dEQP-VK.binding_model.shader_access.secondary_cmd_buf.with_push_template.storage_buffer.vertex_fragment.descriptor_array.offset_view_zero dEQP-VK.binding_model.shader_access.secondary_cmd_buf.with_push_template.storage_buffer.vertex_fragment.descriptor_array.offset_view_nonzero dEQP-VK.binding_model.descriptor_update.empty_descriptor.uniform_buffer +dEQP-VK.binding_model.descriptor_update.samplerless.sampled_img_sampler_zero +dEQP-VK.binding_model.descriptor_update.samplerless.sampled_img_sampler_one +dEQP-VK.binding_model.descriptor_update.samplerless.sampled_img_sampler_destroyed +dEQP-VK.binding_model.descriptor_update.samplerless.storage_img_sampler_zero +dEQP-VK.binding_model.descriptor_update.samplerless.storage_img_sampler_one +dEQP-VK.binding_model.descriptor_update.samplerless.storage_img_sampler_destroyed +dEQP-VK.binding_model.descriptor_update.samplerless.input_attachment_sampler_zero +dEQP-VK.binding_model.descriptor_update.samplerless.input_attachment_sampler_one +dEQP-VK.binding_model.descriptor_update.samplerless.input_attachment_sampler_destroyed dEQP-VK.binding_model.descriptorset_random.sets4.noarray.ubolimitlow.sbolimitlow.imglimitlow.noiub.comp.noia.0 dEQP-VK.binding_model.descriptorset_random.sets4.noarray.ubolimitlow.sbolimitlow.imglimitlow.noiub.comp.noia.1 dEQP-VK.binding_model.descriptorset_random.sets4.noarray.ubolimitlow.sbolimitlow.imglimitlow.noiub.comp.noia.2 -- 2.34.1