From 5477afea1f91760beb45bc9cf25efbada797edc7 Mon Sep 17 00:00:00 2001 From: Charlie Turner Date: Wed, 21 Dec 2022 19:59:23 +0000 Subject: [PATCH] Remove VK_AMD_shader_fragment from default device's extension list It conflicts with VK_EXT_buffer_descriptor, which is a sensible feature to keep as default, rather than vice versa. The single testsuite that uses this extension has been refactored to create a custom device for it instead. This fixes the following validation error, Validation Error: [ VUID-VkDeviceCreateInfo-None-08095 ] Object 0: VK_NULL_HANDLE, type = VK_OBJECT_TYPE_DEVICE; | MessageID = 0xe6a1c10a | vkCreateDevice(): If the descriptorBuffer feature is enabled, ppEnabledExtensionNames must not contain VK_AMD_shader_fragment_mask. The Vulkan spec states: If descriptorBuffer is enabled, ppEnabledExtensionNames must not contain VK_AMD_shader_fragment_mask (https://www.khronos.org/registry/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-VkDeviceCreateInfo-None-08095) The next validation error noticed was, Validation Error: [UNASSIGNED-CoreValidation-Shader-MissingInputAttachment ] Object 0:handle = 0x9fde6b0000000014, type = VK_OBJECT_TYPE_SHADER_MODULE; Object 1: handle = 0x980f360000000011, type = VK_OBJECT_TYPE_PIPELINE_LAYOUT; | MessageID = 0xbd90d7b7 | Shader consumes input attachment This was fixed by hard-coding the input attachment to zero, rather than numLayers (1) which was not being provided by the static subpass layout. There is a remaining validation error, Validation Error: [ VUID-VkGraphicsPipelineCreateInfo-renderPass-06061 ] Object 0: handle = 0x1426c490, type = VK_OBJECT_TYPE_DEVICE; | Me ssageID = 0x399b0a5e | vkCreateGraphicsPipelines(): pCreateInfos[0] is being created with fragment shader state and renderPass = VK_NULL_HANDLE, but fragme nt shader includes InputAttachment capability. The Vulkan spec states: If the pipeline is being created with fragment shader state and renderPass is VK_NUL L_HANDLE, fragment shaders in pStages must not include the InputAttachment capability (https://www.khronos.org/registry/vulkan/specs/1.3-extensions/html/vk spec.html#VUID-VkGraphicsPipelineCreateInfo-renderPass-06061) However, this one is a bug in layers, not taking into account the fact pipeline libraries are enabled when validation stages with input attachment capabilities. Reported https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/4989 VK-GL-CTS issue: 4187 Components: Framework, Vulkan Affects: dEQP-VK.pipeline.*.multisample.shader_fragment_mask.* Change-Id: I01fc1ca4f5e1872a7fabda945d24faad7c9bf622 --- .../modules/vulkan/pipeline/CMakeLists.txt | 4 +- ...tPipelineMultisampleShaderFragmentMaskTests.cpp | 170 +++++++++++++++++++-- external/vulkancts/modules/vulkan/vktTestCase.cpp | 1 - 3 files changed, 158 insertions(+), 17 deletions(-) diff --git a/external/vulkancts/modules/vulkan/pipeline/CMakeLists.txt b/external/vulkancts/modules/vulkan/pipeline/CMakeLists.txt index 832ebc3..c45b78b 100644 --- a/external/vulkancts/modules/vulkan/pipeline/CMakeLists.txt +++ b/external/vulkancts/modules/vulkan/pipeline/CMakeLists.txt @@ -59,8 +59,6 @@ set(DEQP_VK_VKSC_PIPELINE_SRCS vktPipelineMultisampleResolveRenderAreaTests.hpp vktPipelineMultisampleSampleLocationsExtTests.cpp vktPipelineMultisampleSampleLocationsExtTests.hpp - vktPipelineMultisampleShaderFragmentMaskTests.cpp - vktPipelineMultisampleShaderFragmentMaskTests.hpp vktPipelineInputAssemblyTests.cpp vktPipelineInputAssemblyTests.hpp vktPipelineInterfaceMatchingTests.cpp @@ -137,6 +135,8 @@ set(DEQP_VK_PIPELINE_SRCS vktPipelineAttachmentFeedbackLoopLayoutTests.hpp vktPipelineMultisampledRenderToSingleSampledTests.cpp vktPipelineMultisampledRenderToSingleSampledTests.hpp + vktPipelineMultisampleShaderFragmentMaskTests.cpp + vktPipelineMultisampleShaderFragmentMaskTests.hpp ) #vktPipelinePushDescriptorTests.cpp - missing VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR diff --git a/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleShaderFragmentMaskTests.cpp b/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleShaderFragmentMaskTests.cpp index 001d533..0426df7 100644 --- a/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleShaderFragmentMaskTests.cpp +++ b/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleShaderFragmentMaskTests.cpp @@ -27,6 +27,8 @@ #include "vktTestCase.hpp" #include "vktTestCaseUtil.hpp" #include "vktTestGroupUtil.hpp" +#include "vktCustomInstancesDevices.hpp" +#include "tcuCommandLine.hpp" #include "vkCmdUtil.hpp" #include "vkObjUtil.hpp" @@ -51,6 +53,7 @@ #include #include +#include namespace vkt { @@ -195,6 +198,142 @@ enum SampleSource SAMPLE_SOURCE_SUBPASS_INPUT, //!< texel fetch from an input attachment }; +static +std::vector removeExtensions (const std::vector& a, const std::vector& b) +{ + std::vector res; + std::set removeExts (b.begin(), b.end()); + + for (std::vector::const_iterator aIter = a.begin(); aIter != a.end(); ++aIter) + { + if (!de::contains(removeExts, *aIter)) + res.push_back(*aIter); + } + + return res; +} + +// Class to wrap a singleton device for use in fragment mask tests, +// which require the VK_AMD_shader_fragment extension. +class SingletonDevice +{ + SingletonDevice(Context& context, PipelineConstructionType pipelineType) + : m_context(context) + , m_logicalDevice() + { + const float queuePriority = 1.0; + const VkDeviceQueueCreateInfo queues[] = + { + { + VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, + DE_NULL, + (VkDeviceQueueCreateFlags)0, + m_context.getUniversalQueueFamilyIndex(), + 1u, // queueCount + &queuePriority, // pQueuePriorities + } + }; + + // All available device extensions from the Vulkan implementation and implicitly loaded layers. + auto extensionProperties = enumerateDeviceExtensionProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice(), nullptr); + + VkPhysicalDeviceDescriptorBufferFeaturesEXT descriptorBufferFeatures = initVulkanStructure(); + VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT graphicsPipelineLibraryFeaturesEXT = initVulkanStructure(); + descriptorBufferFeatures.pNext = &graphicsPipelineLibraryFeaturesEXT; + + VkPhysicalDeviceFeatures2 features2 = initVulkanStructure(&descriptorBufferFeatures); + m_context.getInstanceInterface().getPhysicalDeviceFeatures2(m_context.getPhysicalDevice(), &features2); + + if (m_context.isDeviceFunctionalitySupported("VK_EXT_descriptor_buffer")) + descriptorBufferFeatures.descriptorBuffer = VK_FALSE; + + std::vector enabledDeviceExtensions = m_context.getDeviceExtensions(); + + if (pipelineType != PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC) + { + if (!graphicsPipelineLibraryFeaturesEXT.graphicsPipelineLibrary) + TCU_THROW(NotSupportedError, "graphicsPipelineLibraryFeaturesEXT.graphicsPipelineLibrary required"); + + enabledDeviceExtensions.push_back("VK_KHR_pipeline_library"); + enabledDeviceExtensions.push_back("VK_EXT_graphics_pipeline_library"); + } + + // This should not be enabled by default. + DE_ASSERT(!de::contains(std::begin(enabledDeviceExtensions), std::end(enabledDeviceExtensions), "VK_AMD_shader_fragment_mask")); + enabledDeviceExtensions.push_back("VK_AMD_shader_fragment_mask"); + + std::vector coreExtensions; + std::vector extensionPtrs; + getCoreDeviceExtensions(m_context.getUsedApiVersion(), coreExtensions); + std::vector nonCoreExtensions(removeExtensions(enabledDeviceExtensions, coreExtensions)); + + extensionPtrs.resize(nonCoreExtensions.size()); + + for (size_t ndx = 0; ndx < nonCoreExtensions.size(); ++ndx) + extensionPtrs[ndx] = nonCoreExtensions[ndx].c_str(); + + VkDeviceCreateInfo createInfo = initVulkanStructure(&features2); + createInfo.flags = 0u; + createInfo.queueCreateInfoCount = de::arrayLength(queues); + createInfo.pQueueCreateInfos = queues; + createInfo.enabledLayerCount = 0u; + createInfo.ppEnabledLayerNames = nullptr; + createInfo.enabledExtensionCount = static_cast(extensionPtrs.size()); + createInfo.ppEnabledExtensionNames = extensionPtrs.data(); + createInfo.pEnabledFeatures = nullptr; + + m_logicalDevice = createCustomDevice( + m_context.getTestContext().getCommandLine().isValidationEnabled(), + m_context.getPlatformInterface(), + m_context.getInstance(), + m_context.getInstanceInterface(), + m_context.getPhysicalDevice(), + &createInfo, + nullptr); + + m_deviceDriver = de::MovePtr(new DeviceDriver(m_context.getPlatformInterface(), m_context.getInstance(), *m_logicalDevice)); + } + +public: + ~SingletonDevice() + { + } + + static VkDevice getDevice(Context& context, PipelineConstructionType pipelineType) + { + if (!m_singletonDevice) + m_singletonDevice = SharedPtr(new SingletonDevice(context, pipelineType)); + DE_ASSERT(m_singletonDevice); + return m_singletonDevice->m_logicalDevice.get(); + } + + static VkQueue getUniversalQueue(Context& context, PipelineConstructionType pipelineType) + { + return getDeviceQueue(getDeviceInterface(context, pipelineType), getDevice(context, pipelineType), context.getUniversalQueueFamilyIndex(), 0); + } + + static const DeviceInterface& getDeviceInterface(Context& context, PipelineConstructionType pipelineType) + { + if (!m_singletonDevice) + m_singletonDevice = SharedPtr(new SingletonDevice(context, pipelineType)); + DE_ASSERT(m_singletonDevice); + return *(m_singletonDevice->m_deviceDriver.get()); + } + + static void destroy() + { + m_singletonDevice.clear(); + } + +private: + const Context& m_context; + Move m_logicalDevice; + de::MovePtr m_deviceDriver; + static SharedPtr m_singletonDevice; +}; + +SharedPtr SingletonDevice::m_singletonDevice; + //! The parameters that define a test case struct TestParams { @@ -216,7 +355,9 @@ struct TestParams void checkRequirements (Context& context, TestParams params) { - context.requireDeviceFunctionality("VK_AMD_shader_fragment_mask"); + const auto supportedExtensions = enumerateDeviceExtensionProperties(context.getInstanceInterface(), context.getPhysicalDevice(), nullptr); + if (!isExtensionStructSupported(supportedExtensions, RequiredExtension("VK_AMD_shader_fragment_mask"))) + TCU_THROW(NotSupportedError, "VK_AMD_shader_fragment_mask not supported"); // In the subpass input case we have to store fetch results into a buffer for subsequent verification in a compute shader. const bool requireFragmentStores = (params.sampleSource == SAMPLE_SOURCE_SUBPASS_INPUT); @@ -389,7 +530,7 @@ void initPrograms (SourceCollections& programCollection, const TestParams params << "layout(set = 0, binding = 1, std430) writeonly buffer ColorOutput {\n" << " " << colorBufferType << " color[];\n" << "} sb_out;\n" - << "layout(input_attachment_index = " << params.numLayers << ", set = 0, binding = 2) uniform " << samplerPrefix << "subpassInputMS" << " input_attach;\n" + << "layout(input_attachment_index = 0, set = 0, binding = 2) uniform " << samplerPrefix << "subpassInputMS" << " input_attach;\n" << "\n" << "void main(void)\n" << "{\n" @@ -496,8 +637,8 @@ void drawAndSampleInputAttachment (Context& context, const TestParams& params, W { DE_ASSERT(params.numLayers == 1u); // subpass load with single-layer image - const DeviceInterface& vk = context.getDeviceInterface(); - const VkDevice device = context.getDevice(); + const DeviceInterface& vk = SingletonDevice::getDeviceInterface(context, params.pipelineConstructionType); + const VkDevice device = SingletonDevice::getDevice(context, params.pipelineConstructionType); Move renderPass; Move framebuffer; @@ -811,7 +952,7 @@ void drawAndSampleInputAttachment (Context& context, const TestParams& params, W } VK_CHECK(vk.endCommandBuffer(*cmdBuffer)); - submitCommandsAndWait(vk, device, context.getUniversalQueue(), *cmdBuffer); + submitCommandsAndWait(vk, device, SingletonDevice::getUniversalQueue(context, params.pipelineConstructionType), *cmdBuffer); invalidateMappedMemoryRange(vk, device, wd.colorBufferAlloc->getMemory(), wd.colorBufferAlloc->getOffset(), VK_WHOLE_SIZE); } @@ -819,8 +960,8 @@ void drawAndSampleInputAttachment (Context& context, const TestParams& params, W //! Only draw a multisampled image void draw (Context& context, const TestParams& params, WorkingData& wd) { - const DeviceInterface& vk = context.getDeviceInterface(); - const VkDevice device = context.getDevice(); + const DeviceInterface& vk = SingletonDevice::getDeviceInterface(context, params.pipelineConstructionType); + const VkDevice device = SingletonDevice::getDevice(context, params.pipelineConstructionType); std::vector imageViews; Move renderPass; @@ -1028,14 +1169,14 @@ void draw (Context& context, const TestParams& params, WorkingData& wd) vk.cmdEndRenderPass(*cmdBuffer); VK_CHECK(vk.endCommandBuffer(*cmdBuffer)); - submitCommandsAndWait(vk, device, context.getUniversalQueue(), *cmdBuffer); + submitCommandsAndWait(vk, device, SingletonDevice::getUniversalQueue(context, params.pipelineConstructionType), *cmdBuffer); } //! Sample from an image in a compute shader, storing the result in a color buffer void dispatchSampleImage (Context& context, const TestParams& params, WorkingData& wd, const std::string& shaderName) { - const DeviceInterface& vk = context.getDeviceInterface(); - const VkDevice device = context.getDevice(); + const DeviceInterface& vk = SingletonDevice::getDeviceInterface(context, params.pipelineConstructionType); + const VkDevice device = SingletonDevice::getDevice(context, params.pipelineConstructionType); // Create descriptor set @@ -1100,7 +1241,7 @@ void dispatchSampleImage (Context& context, const TestParams& params, WorkingDat } VK_CHECK(vk.endCommandBuffer(*cmdBuffer)); - submitCommandsAndWait(vk, device, context.getUniversalQueue(), *cmdBuffer); + submitCommandsAndWait(vk, device, SingletonDevice::getUniversalQueue(context, params.pipelineConstructionType), *cmdBuffer); invalidateMappedMemoryRange(vk, device, wd.colorBufferAlloc->getMemory(), wd.colorBufferAlloc->getOffset(), VK_WHOLE_SIZE); } @@ -1125,8 +1266,9 @@ tcu::ConstPixelBufferAccess getSingleSampledAccess (const void* const imageData, tcu::TestStatus test (Context& context, const TestParams params) { WorkingData wd; - const DeviceInterface& vk = context.getDeviceInterface(); - const VkDevice device = context.getDevice(); + const DeviceInterface& vk = SingletonDevice::getDeviceInterface(context, params.pipelineConstructionType); + const VkDevice device = SingletonDevice::getDevice(context, params.pipelineConstructionType); + MovePtr allocator = MovePtr(new SimpleAllocator(vk, device, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()))); // Initialize resources @@ -1281,7 +1423,7 @@ void createShaderFragmentMaskTestsInGroup (tcu::TestCaseGroup* rootGroup, Pipeli tcu::TestCaseGroup* createMultisampleShaderFragmentMaskTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType) { - return createTestGroup(testCtx, "shader_fragment_mask", "Access raw texel values in a compressed MSAA surface", createShaderFragmentMaskTestsInGroup, pipelineConstructionType); + return createTestGroup(testCtx, "shader_fragment_mask", "Access raw texel values in a compressed MSAA surface", createShaderFragmentMaskTestsInGroup, pipelineConstructionType, [](tcu::TestCaseGroup*, PipelineConstructionType) { SingletonDevice::destroy(); }); } } // pipeline diff --git a/external/vulkancts/modules/vulkan/vktTestCase.cpp b/external/vulkancts/modules/vulkan/vktTestCase.cpp index e05353c..5ec5a81 100644 --- a/external/vulkancts/modules/vulkan/vktTestCase.cpp +++ b/external/vulkancts/modules/vulkan/vktTestCase.cpp @@ -74,7 +74,6 @@ vector filterExtensions (const vector& extensions "VK_NV_inherited_viewport_scissor", "VK_NV_mesh_shader", "VK_AMD_mixed_attachment_samples", - "VK_AMD_shader_fragment_mask", "VK_AMD_buffer_marker", "VK_AMD_shader_explicit_vertex_parameter", "VK_AMD_shader_image_load_store_lod", -- 2.7.4