From 621bd81c1ee0f8911c6dbf702eaa7c15f2f2bae3 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Samuel=20Iglesias=20Gons=C3=A1lvez?= Date: Fri, 17 May 2019 13:30:33 +0200 Subject: [PATCH] Add tests for VK_EXT_pipeline_creation_feedback extension Tests implement the following for both compute and graphics pipelines. They create a pipeline cache and checks the pipeline creation feedback for three different pipelines: first pipeline should not hit the cache, second pipeline is the same than the first one, third pipeline is a pipeline derivative from the first one. Then they verify that the creation feedback for all of the pipelines is valid, the first pipeline did not hit the cache and that first and second pipelines are not setting VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT_EXT as they are not pipeline derivatives. Also, if pPipelineStageCreationFeedbacks for each pipeline and stage is not valid, check that none of the flags is set. They also print to the test log the content of the pPipelineCreationFeedback for each pipeline and, if pPipelineStageCreationFeedbacks for each pipeline and stage is valid, its content too. New tests: dEQP-VK.pipeline.creation_feedback.* Components: Vulkan VK-GL-CTS issue: 1671 Change-Id: I5e8b728bd83c256b3b4f084c6d0840a132afbcae --- AndroidGen.mk | 1 + android/cts/master/vk-master.txt | 8 + .../vulkancts/framework/vulkan/vkBasicTypes.inl | 11 + .../framework/vulkan/vkGetStructureTypeImpl.inl | 5 + external/vulkancts/framework/vulkan/vkStrUtil.inl | 3 + .../vulkancts/framework/vulkan/vkStrUtilImpl.inl | 34 + .../vulkancts/framework/vulkan/vkStructTypes.inl | 15 + external/vulkancts/framework/vulkan/vkTypeUtil.inl | 8 + external/vulkancts/framework/vulkan/vkVulkan_c.inl | 26 +- .../modules/vulkan/pipeline/CMakeLists.txt | 2 + .../pipeline/vktPipelineCreationFeedbackTests.cpp | 1345 ++++++++++++++++++++ .../pipeline/vktPipelineCreationFeedbackTests.hpp | 39 + .../modules/vulkan/pipeline/vktPipelineTests.cpp | 2 + .../mustpass/master/vk-default-no-waivers.txt | 8 + external/vulkancts/mustpass/master/vk-default.txt | 8 + external/vulkancts/scripts/src/vulkan.h.in | 26 +- 16 files changed, 1539 insertions(+), 2 deletions(-) create mode 100644 external/vulkancts/modules/vulkan/pipeline/vktPipelineCreationFeedbackTests.cpp create mode 100644 external/vulkancts/modules/vulkan/pipeline/vktPipelineCreationFeedbackTests.hpp diff --git a/AndroidGen.mk b/AndroidGen.mk index fba8bda..b54dcb8 100644 --- a/AndroidGen.mk +++ b/AndroidGen.mk @@ -177,6 +177,7 @@ LOCAL_SRC_FILES := \ external/vulkancts/modules/vulkan/pipeline/vktPipelineBlendTests.cpp \ external/vulkancts/modules/vulkan/pipeline/vktPipelineCacheTests.cpp \ external/vulkancts/modules/vulkan/pipeline/vktPipelineClearUtil.cpp \ + external/vulkancts/modules/vulkan/pipeline/vktPipelineCreationFeedbackTests.cpp \ external/vulkancts/modules/vulkan/pipeline/vktPipelineDepthTests.cpp \ external/vulkancts/modules/vulkan/pipeline/vktPipelineDerivativeTests.cpp \ external/vulkancts/modules/vulkan/pipeline/vktPipelineDynamicOffsetTests.cpp \ diff --git a/android/cts/master/vk-master.txt b/android/cts/master/vk-master.txt index 564062d..3ca6367 100755 --- a/android/cts/master/vk-master.txt +++ b/android/cts/master/vk-master.txt @@ -178402,6 +178402,14 @@ dEQP-VK.pipeline.framebuffer_attachment.diff_attachments_2d_19x27_32x32_ms dEQP-VK.pipeline.shader_stencil_export.op_replace dEQP-VK.pipeline.derivative.compute.derivative_by_handle dEQP-VK.pipeline.derivative.compute.derivative_by_index +dEQP-VK.pipeline.creation_feedback.graphics_tests.vertex_stage_fragment_stage +dEQP-VK.pipeline.creation_feedback.graphics_tests.vertex_stage_geometry_stage_fragment_stage +dEQP-VK.pipeline.creation_feedback.graphics_tests.vertex_stage_tessellation_control_stage_tessellation_evaluation_stage_fragment_stage +dEQP-VK.pipeline.creation_feedback.graphics_tests.vertex_stage_fragment_stage_no_cache +dEQP-VK.pipeline.creation_feedback.graphics_tests.vertex_stage_geometry_stage_no_cache_fragment_stage_no_cache +dEQP-VK.pipeline.creation_feedback.graphics_tests.vertex_stage_tessellation_control_stage_no_cache_tessellation_evaluation_stage_no_cache_fragment_stage_no_cache +dEQP-VK.pipeline.creation_feedback.compute_tests.compute_stage +dEQP-VK.pipeline.creation_feedback.compute_tests.compute_stage_no_cache dEQP-VK.binding_model.shader_access.primary_cmd_buf.sampler_mutable.no_access.single_descriptor.1d dEQP-VK.binding_model.shader_access.primary_cmd_buf.sampler_mutable.no_access.single_descriptor.1d_base_mip dEQP-VK.binding_model.shader_access.primary_cmd_buf.sampler_mutable.no_access.single_descriptor.1d_base_slice diff --git a/external/vulkancts/framework/vulkan/vkBasicTypes.inl b/external/vulkancts/framework/vulkan/vkBasicTypes.inl index 0080c97..461969f 100644 --- a/external/vulkancts/framework/vulkan/vkBasicTypes.inl +++ b/external/vulkancts/framework/vulkan/vkBasicTypes.inl @@ -351,6 +351,7 @@ enum VkStructureType VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT = 1000190000, VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT = 1000190001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT = 1000190002, + VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO_EXT = 1000192000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR = 1000196000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES_KHR = 1000197000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES_KHR = 1000199000, @@ -1964,6 +1965,15 @@ enum VkDescriptorBindingFlagBitsEXT }; typedef deUint32 VkDescriptorBindingFlagsEXT; +enum VkPipelineCreationFeedbackFlagBitsEXT +{ + VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT_EXT = 0x00000001, + VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT = 0x00000002, + VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT_EXT = 0x00000004, + VK_PIPELINE_CREATION_FEEDBACK_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF, +}; +typedef deUint32 VkPipelineCreationFeedbackFlagsEXT; + typedef deUint32 VkInstanceCreateFlags; typedef deUint32 VkDeviceCreateFlags; @@ -2389,3 +2399,4 @@ VK_DEFINE_PLATFORM_TYPE(RROutput, void*); #define VK_EXT_MEMORY_BUDGET_SPEC_VERSION 1 #define VK_EXT_MEMORY_PRIORITY_SPEC_VERSION 1 #define VK_KHR_UNIFORM_BUFFER_STANDARD_LAYOUT_SPEC_VERSION 1 +#define VK_EXT_PIPELINE_CREATION_FEEDBACK_SPEC_VERSION 1 diff --git a/external/vulkancts/framework/vulkan/vkGetStructureTypeImpl.inl b/external/vulkancts/framework/vulkan/vkGetStructureTypeImpl.inl index c3f1e1e..f525a9d 100644 --- a/external/vulkancts/framework/vulkan/vkGetStructureTypeImpl.inl +++ b/external/vulkancts/framework/vulkan/vkGetStructureTypeImpl.inl @@ -1341,3 +1341,8 @@ template<> VkStructureType getStructureType VkStructureType getStructureType (void) +{ + return VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO_EXT; +} + diff --git a/external/vulkancts/framework/vulkan/vkStrUtil.inl b/external/vulkancts/framework/vulkan/vkStrUtil.inl index 8931624..1d274e7 100644 --- a/external/vulkancts/framework/vulkan/vkStrUtil.inl +++ b/external/vulkancts/framework/vulkan/vkStrUtil.inl @@ -242,6 +242,7 @@ tcu::Format::Bitfield<32> getIndirectCommandsLayoutUsageFlagsNVXStr (VkIndire tcu::Format::Bitfield<32> getObjectEntryUsageFlagsNVXStr (VkObjectEntryUsageFlagsNVX value); tcu::Format::Bitfield<32> getSurfaceCounterFlagsEXTStr (VkSurfaceCounterFlagsEXT value); tcu::Format::Bitfield<32> getDescriptorBindingFlagsEXTStr (VkDescriptorBindingFlagsEXT value); +tcu::Format::Bitfield<32> getPipelineCreationFeedbackFlagsEXTStr (VkPipelineCreationFeedbackFlagsEXT value); tcu::Format::Bitfield<32> getInstanceCreateFlagsStr (VkInstanceCreateFlags value); tcu::Format::Bitfield<32> getDeviceCreateFlagsStr (VkDeviceCreateFlags value); tcu::Format::Bitfield<32> getMemoryMapFlagsStr (VkMemoryMapFlags value); @@ -648,3 +649,5 @@ std::ostream& operator<< (std::ostream& s, const VkPhysicalDeviceMemoryBudgetPro std::ostream& operator<< (std::ostream& s, const VkPhysicalDeviceMemoryPriorityFeaturesEXT& value); std::ostream& operator<< (std::ostream& s, const VkMemoryPriorityAllocateInfoEXT& value); std::ostream& operator<< (std::ostream& s, const VkPhysicalDeviceUniformBufferStandardLayoutFeaturesKHR& value); +std::ostream& operator<< (std::ostream& s, const VkPipelineCreationFeedbackEXT& value); +std::ostream& operator<< (std::ostream& s, const VkPipelineCreationFeedbackCreateInfoEXT& value); diff --git a/external/vulkancts/framework/vulkan/vkStrUtilImpl.inl b/external/vulkancts/framework/vulkan/vkStrUtilImpl.inl index be454f5..90e64de 100644 --- a/external/vulkancts/framework/vulkan/vkStrUtilImpl.inl +++ b/external/vulkancts/framework/vulkan/vkStrUtilImpl.inl @@ -360,6 +360,7 @@ const char* getStructureTypeName (VkStructureType value) case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT: return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT"; case VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT: return "VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT"; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT: return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO_EXT: return "VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO_EXT"; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR: return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR"; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES_KHR: return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES_KHR"; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES_KHR: return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES_KHR"; @@ -2328,6 +2329,18 @@ tcu::Format::Bitfield<32> getDescriptorBindingFlagsEXTStr (VkDescriptorBindingFl return tcu::Format::Bitfield<32>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc)); } +tcu::Format::Bitfield<32> getPipelineCreationFeedbackFlagsEXTStr (VkPipelineCreationFeedbackFlagsEXT value) +{ + static const tcu::Format::BitDesc s_desc[] = + { + tcu::Format::BitDesc(VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT_EXT, "VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT_EXT"), + tcu::Format::BitDesc(VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT, "VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT"), + tcu::Format::BitDesc(VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT_EXT, "VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT_EXT"), + tcu::Format::BitDesc(VK_PIPELINE_CREATION_FEEDBACK_FLAG_BITS_MAX_ENUM_EXT, "VK_PIPELINE_CREATION_FEEDBACK_FLAG_BITS_MAX_ENUM_EXT"), + }; + return tcu::Format::Bitfield<32>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc)); +} + tcu::Format::Bitfield<32> getInstanceCreateFlagsStr (VkInstanceCreateFlags value) { return tcu::Format::Bitfield<32>(value, DE_NULL, DE_NULL); @@ -7015,3 +7028,24 @@ std::ostream& operator<< (std::ostream& s, const VkPhysicalDeviceUniformBufferSt s << '}'; return s; } + +std::ostream& operator<< (std::ostream& s, const VkPipelineCreationFeedbackEXT& value) +{ + s << "VkPipelineCreationFeedbackEXT = {\n"; + s << "\tflags = " << getPipelineCreationFeedbackFlagsEXTStr(value.flags) << '\n'; + s << "\tduration = " << value.duration << '\n'; + s << '}'; + return s; +} + +std::ostream& operator<< (std::ostream& s, const VkPipelineCreationFeedbackCreateInfoEXT& value) +{ + s << "VkPipelineCreationFeedbackCreateInfoEXT = {\n"; + s << "\tsType = " << value.sType << '\n'; + s << "\tpNext = " << value.pNext << '\n'; + s << "\tpPipelineCreationFeedback = " << value.pPipelineCreationFeedback << '\n'; + s << "\tpipelineStageCreationFeedbackCount = " << value.pipelineStageCreationFeedbackCount << '\n'; + s << "\tpPipelineStageCreationFeedbacks = " << value.pPipelineStageCreationFeedbacks << '\n'; + s << '}'; + return s; +} diff --git a/external/vulkancts/framework/vulkan/vkStructTypes.inl b/external/vulkancts/framework/vulkan/vkStructTypes.inl index fe01227..7c37698 100644 --- a/external/vulkancts/framework/vulkan/vkStructTypes.inl +++ b/external/vulkancts/framework/vulkan/vkStructTypes.inl @@ -3384,6 +3384,21 @@ struct VkPhysicalDeviceUniformBufferStandardLayoutFeaturesKHR VkBool32 uniformBufferStandardLayout; }; +struct VkPipelineCreationFeedbackEXT +{ + VkPipelineCreationFeedbackFlagsEXT flags; + deUint64 duration; +}; + +struct VkPipelineCreationFeedbackCreateInfoEXT +{ + VkStructureType sType; + const void* pNext; + VkPipelineCreationFeedbackEXT* pPipelineCreationFeedback; + deUint32 pipelineStageCreationFeedbackCount; + VkPipelineCreationFeedbackEXT* pPipelineStageCreationFeedbacks; +}; + diff --git a/external/vulkancts/framework/vulkan/vkTypeUtil.inl b/external/vulkancts/framework/vulkan/vkTypeUtil.inl index 323b24a..38e826f 100644 --- a/external/vulkancts/framework/vulkan/vkTypeUtil.inl +++ b/external/vulkancts/framework/vulkan/vkTypeUtil.inl @@ -574,3 +574,11 @@ inline VkVertexInputBindingDivisorDescriptionEXT makeVertexInputBindingDivisorDe res.divisor = divisor; return res; } + +inline VkPipelineCreationFeedbackEXT makePipelineCreationFeedbackEXT (VkPipelineCreationFeedbackFlagsEXT flags, deUint64 duration) +{ + VkPipelineCreationFeedbackEXT res; + res.flags = flags; + res.duration = duration; + return res; +} diff --git a/external/vulkancts/framework/vulkan/vkVulkan_c.inl b/external/vulkancts/framework/vulkan/vkVulkan_c.inl index 2a42b09..698772b 100644 --- a/external/vulkancts/framework/vulkan/vkVulkan_c.inl +++ b/external/vulkancts/framework/vulkan/vkVulkan_c.inl @@ -413,6 +413,7 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT = 1000190000, VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT = 1000190001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT = 1000190002, + VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO_EXT = 1000192000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR = 1000196000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES_KHR = 1000197000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES_KHR = 1000199000, @@ -8395,7 +8396,6 @@ VKAPI_ATTR void VKAPI_CALL vkResetQueryPoolEXT( deUint32 queryCount); #endif - #define VK_EXT_pci_bus_info 1 #define VK_EXT_PCI_BUS_INFO_SPEC_VERSION 2 #define VK_EXT_PCI_BUS_INFO_EXTENSION_NAME "VK_EXT_pci_bus_info" @@ -8437,6 +8437,7 @@ typedef struct VkMemoryPriorityAllocateInfoEXT { float priority; } VkMemoryPriorityAllocateInfoEXT; + #define VK_KHR_uniform_buffer_standard_layout 1 #define VK_KHR_UNIFORM_BUFFER_STANDARD_LAYOUT_SPEC_VERSION 1 #define VK_KHR_UNIFORM_BUFFER_STANDARD_LAYOUT_EXTENSION_NAME "VK_KHR_uniform_buffer_standard_layout" @@ -8448,6 +8449,29 @@ typedef struct VkPhysicalDeviceUniformBufferStandardLayoutFeaturesKHR { } VkPhysicalDeviceUniformBufferStandardLayoutFeaturesKHR; +#define VK_EXT_pipeline_creation_feedback 1 +#define VK_EXT_PIPELINE_CREATION_FEEDBACK_SPEC_VERSION 1 +#define VK_EXT_PIPELINE_CREATION_FEEDBACK_EXTENSION_NAME "VK_EXT_pipeline_creation_feedback" + +typedef enum VkPipelineCreationFeedbackFlagBitsEXT { + VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT_EXT = 0x00000001, + VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT = 0x00000002, + VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT_EXT = 0x00000004, + VK_PIPELINE_CREATION_FEEDBACK_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkPipelineCreationFeedbackFlagBitsEXT; +typedef VkFlags VkPipelineCreationFeedbackFlagsEXT; +typedef struct VkPipelineCreationFeedbackEXT { + VkPipelineCreationFeedbackFlagsEXT flags; + deUint64 duration; +} VkPipelineCreationFeedbackEXT; + +typedef struct VkPipelineCreationFeedbackCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkPipelineCreationFeedbackEXT* pPipelineCreationFeedback; + deUint32 pipelineStageCreationFeedbackCount; + VkPipelineCreationFeedbackEXT* pPipelineStageCreationFeedbacks; +} VkPipelineCreationFeedbackCreateInfoEXT; #ifdef __cplusplus } diff --git a/external/vulkancts/modules/vulkan/pipeline/CMakeLists.txt b/external/vulkancts/modules/vulkan/pipeline/CMakeLists.txt index af54fa4..3668a5a 100644 --- a/external/vulkancts/modules/vulkan/pipeline/CMakeLists.txt +++ b/external/vulkancts/modules/vulkan/pipeline/CMakeLists.txt @@ -80,6 +80,8 @@ set(DEQP_VK_PIPELINE_SRCS vktPipelineCacheTests.hpp vktPipelineMakeUtil.cpp vktPipelineMakeUtil.hpp + vktPipelineCreationFeedbackTests.cpp + vktPipelineCreationFeedbackTests.hpp ) set(DEQP_VK_PIPELINE_LIBS diff --git a/external/vulkancts/modules/vulkan/pipeline/vktPipelineCreationFeedbackTests.cpp b/external/vulkancts/modules/vulkan/pipeline/vktPipelineCreationFeedbackTests.cpp new file mode 100644 index 0000000..1344a90 --- /dev/null +++ b/external/vulkancts/modules/vulkan/pipeline/vktPipelineCreationFeedbackTests.cpp @@ -0,0 +1,1345 @@ +/*------------------------------------------------------------------------ + * Vulkan Conformance Tests + * ------------------------ + * + * Copyright (c) 2019 The Khronos Group Inc. + * Copyright (c) 2019 Valve Corporation. + * + * 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 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *//*! + * \file + * \brief Pipeline Cache Tests + *//*--------------------------------------------------------------------*/ + +#include "vktPipelineCreationFeedbackTests.hpp" +#include "vktPipelineVertexUtil.hpp" +#include "vktTestCase.hpp" +#include "vktTestCaseUtil.hpp" +#include "vkMemUtil.hpp" +#include "vkBuilderUtil.hpp" +#include "vkRefUtil.hpp" +#include "vkTypeUtil.hpp" +#include "vkObjUtil.hpp" +#include "tcuTestLog.hpp" + +#include +#include + +namespace vkt +{ +namespace pipeline +{ + +using namespace vk; + +namespace +{ +enum +{ + VK_MAX_SHADER_STAGES = 6, +}; + +enum +{ + PIPELINE_CACHE_NDX_NO_CACHE = 0, + PIPELINE_CACHE_NDX_DERIVATIVE = 1, + PIPELINE_CACHE_NDX_CACHED = 2, + PIPELINE_CACHE_NDX_COUNT, +}; + +// helper functions + +std::string getShaderFlagStr (const VkShaderStageFlagBits shader, + bool isDescription) +{ + std::ostringstream desc; + switch(shader) + { + case VK_SHADER_STAGE_VERTEX_BIT: + { + desc << ((isDescription) ? "vertex stage" : "vertex_stage"); + break; + } + case VK_SHADER_STAGE_FRAGMENT_BIT: + { + desc << ((isDescription) ? "fragment stage" : "fragment_stage"); + break; + } + case VK_SHADER_STAGE_GEOMETRY_BIT: + { + desc << ((isDescription) ? "geometry stage" : "geometry_stage"); + break; + } + case VK_SHADER_STAGE_COMPUTE_BIT: + { + desc << ((isDescription) ? "compute stage" : "compute_stage"); + break; + } + case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: + { + desc << ((isDescription) ? "tessellation control stage" : "tessellation_control_stage"); + break; + } + case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: + { + desc << ((isDescription) ? "tessellation evaluation stage" : "tessellation_evaluation_stage"); + break; + } + default: + desc << "unknown shader stage!"; + DE_FATAL("Unknown shader Stage!"); + break; + }; + + return desc.str(); +} + +std::string getCaseStr (const deUint32 ndx) +{ + std::ostringstream desc; + switch(ndx) + { + case PIPELINE_CACHE_NDX_NO_CACHE: + { + desc << "No cached pipeline"; + break; + } + case PIPELINE_CACHE_NDX_CACHED: + { + desc << "Cached pipeline"; + break; + } + case PIPELINE_CACHE_NDX_DERIVATIVE: + { + desc << "Pipeline derivative"; + break; + } + default: + desc << "Unknown case"; + DE_FATAL("Unknown case!"); + break; + }; + + return desc.str(); +} + +// helper classes +class CacheTestParam +{ +public: + CacheTestParam (const VkShaderStageFlagBits* shaders, + deUint32 count, + deBool noCache); + virtual ~CacheTestParam (void); + virtual const std::string generateTestName (void) const; + virtual const std::string generateTestDescription (void) const; + VkShaderStageFlagBits getShaderFlag (deUint32 ndx) const { return m_shaders[ndx]; } + deUint32 getShaderCount (void) const { return (deUint32)m_shaderCount; } + deBool isCacheDisabled (void) const { return m_noCache; } + +protected: + VkShaderStageFlagBits m_shaders[VK_MAX_SHADER_STAGES]; + size_t m_shaderCount; + bool m_noCache; +}; + +CacheTestParam::CacheTestParam (const VkShaderStageFlagBits* shaders, deUint32 count, deBool noCache) +{ + DE_ASSERT(count <= VK_MAX_SHADER_STAGES); + for (deUint32 ndx = 0; ndx < count; ndx++) + m_shaders[ndx] = shaders[ndx]; + m_shaderCount = count; + m_noCache = noCache; +} + +CacheTestParam::~CacheTestParam (void) +{ +} + +const std::string CacheTestParam::generateTestName (void) const +{ + std::string result(getShaderFlagStr(m_shaders[0], false)); + std::string cacheString [] = { "", "_no_cache" }; + + for(deUint32 ndx = 1; ndx < m_shaderCount; ndx++) + result += '_' + getShaderFlagStr(m_shaders[ndx], false) + cacheString[m_noCache ? 1 : 0]; + + if (m_shaderCount == 1) + result += cacheString[m_noCache ? 1 : 0]; + + return result; +} + +const std::string CacheTestParam::generateTestDescription (void) const +{ + std::string result("Get pipeline creation feedback with " + getShaderFlagStr(m_shaders[0], true)); + if (m_noCache) + result += " with no cache"; + + for(deUint32 ndx = 1; ndx < m_shaderCount; ndx++) + result += ' ' + getShaderFlagStr(m_shaders[ndx], true); + + return result; +} + +class SimpleGraphicsPipelineBuilder +{ +public: + SimpleGraphicsPipelineBuilder (Context& context); + ~SimpleGraphicsPipelineBuilder (void) { } + void bindShaderStage (VkShaderStageFlagBits stage, + const char* sourceName, + const char* entryName); + void enableTessellationStage (deUint32 patchControlPoints); + VkPipeline buildPipeline (tcu::UVec2 renderSize, + VkRenderPass renderPass, + VkPipelineCache cache, + VkPipelineLayout pipelineLayout, + VkPipelineCreationFeedbackEXT *pipelineCreationFeedback, + VkPipelineCreationFeedbackEXT *pipelineStageCreationFeedbacks, + VkPipeline basePipelineHandle); + void resetBuilder (void); + +protected: + Context& m_context; + + Move m_shaderModules[VK_MAX_SHADER_STAGES]; + deUint32 m_shaderStageCount; + VkPipelineShaderStageCreateInfo m_shaderStageInfo[VK_MAX_SHADER_STAGES]; + + deUint32 m_patchControlPoints; +}; + +SimpleGraphicsPipelineBuilder::SimpleGraphicsPipelineBuilder (Context& context) + : m_context(context) +{ + m_patchControlPoints = 0; + m_shaderStageCount = 0; +} + +void SimpleGraphicsPipelineBuilder::resetBuilder (void) +{ + m_shaderStageCount = 0; +} + +void SimpleGraphicsPipelineBuilder::bindShaderStage (VkShaderStageFlagBits stage, + const char* sourceName, + const char* entryName) +{ + const DeviceInterface& vk = m_context.getDeviceInterface(); + const VkDevice vkDevice = m_context.getDevice(); + + // Create shader module + deUint32* code = (deUint32*)m_context.getBinaryCollection().get(sourceName).getBinary(); + deUint32 codeSize = (deUint32)m_context.getBinaryCollection().get(sourceName).getSize(); + + const VkShaderModuleCreateInfo moduleCreateInfo = + { + VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkShaderModuleCreateFlags flags; + codeSize, // deUintptr codeSize; + code, // const deUint32* pCode; + }; + + m_shaderModules[m_shaderStageCount] = createShaderModule(vk, vkDevice, &moduleCreateInfo); + + // Prepare shader stage info + m_shaderStageInfo[m_shaderStageCount].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + m_shaderStageInfo[m_shaderStageCount].pNext = DE_NULL; + m_shaderStageInfo[m_shaderStageCount].flags = 0u; + m_shaderStageInfo[m_shaderStageCount].stage = stage; + m_shaderStageInfo[m_shaderStageCount].module = *m_shaderModules[m_shaderStageCount]; + m_shaderStageInfo[m_shaderStageCount].pName = entryName; + m_shaderStageInfo[m_shaderStageCount].pSpecializationInfo = DE_NULL; + + m_shaderStageCount++; +} + +VkPipeline SimpleGraphicsPipelineBuilder::buildPipeline (tcu::UVec2 renderSize, VkRenderPass renderPass, VkPipelineCache cache, + VkPipelineLayout pipelineLayout, VkPipelineCreationFeedbackEXT *pipelineCreationFeedback, + VkPipelineCreationFeedbackEXT *pipelineStageCreationFeedbacks, VkPipeline basePipelineHandle) +{ + const DeviceInterface& vk = m_context.getDeviceInterface(); + const VkDevice vkDevice = m_context.getDevice(); + + // Create pipeline + const VkVertexInputBindingDescription vertexInputBindingDescription = + { + 0u, // deUint32 binding; + sizeof(Vertex4RGBA), // deUint32 strideInBytes; + VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate; + }; + + const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] = + { + { + 0u, // deUint32 location; + 0u, // deUint32 binding; + VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; + 0u // deUint32 offsetInBytes; + }, + { + 1u, // deUint32 location; + 0u, // deUint32 binding; + VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; + DE_OFFSET_OF(Vertex4RGBA, color), // deUint32 offsetInBytes; + } + }; + + const VkPipelineVertexInputStateCreateInfo vertexInputStateParams = + { + VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkPipelineVertexInputStateCreateFlags flags; + 1u, // deUint32 vertexBindingDescriptionCount; + &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions; + 2u, // deUint32 vertexAttributeDescriptionCount; + vertexInputAttributeDescriptions, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; + }; + + const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateParams = + { + VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkPipelineInputAssemblyStateCreateFlags flags; + (m_patchControlPoints == 0 ? VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST + : VK_PRIMITIVE_TOPOLOGY_PATCH_LIST), // VkPrimitiveTopology topology; + VK_FALSE, // VkBool32 primitiveRestartEnable; + }; + + const VkViewport viewport = makeViewport(renderSize); + const VkRect2D scissor = makeRect2D(renderSize); + + const VkPipelineViewportStateCreateInfo viewportStateParams = + { + VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkPipelineViewportStateCreateFlags flags; + 1u, // deUint32 viewportCount; + &viewport, // const VkViewport* pViewports; + 1u, // deUint32 scissorCount; + &scissor // const VkRect2D* pScissors; + }; + + const VkPipelineRasterizationStateCreateInfo rasterStateParams = + { + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkPipelineRasterizationStateCreateFlags flags; + VK_FALSE, // VkBool32 depthClampEnable; + VK_FALSE, // VkBool32 rasterizerDiscardEnable; + VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode; + VK_CULL_MODE_NONE, // VkCullModeFlags cullMode; + VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace; + VK_FALSE, // VkBool32 depthBiasEnable; + 0.0f, // float depthBiasConstantFactor; + 0.0f, // float depthBiasClamp; + 0.0f, // float depthBiasSlopeFactor; + 1.0f, // float lineWidth; + }; + + const VkPipelineColorBlendAttachmentState colorBlendAttachmentState = + { + VK_FALSE, // VkBool32 blendEnable; + VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor; + VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor; + VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp; + VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor; + VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor; + VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp; + VK_COLOR_COMPONENT_R_BIT | + VK_COLOR_COMPONENT_G_BIT | + VK_COLOR_COMPONENT_B_BIT | + VK_COLOR_COMPONENT_A_BIT // VkColorComponentFlags colorWriteMask; + }; + + const VkPipelineColorBlendStateCreateInfo colorBlendStateParams = + { + VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkPipelineColorBlendStateCreateFlags flags; + VK_FALSE, // VkBool32 logicOpEnable; + VK_LOGIC_OP_COPY, // VkLogicOp logicOp; + 1u, // deUint32 attachmentCount; + &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments; + { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConst[4]; + }; + + const VkPipelineMultisampleStateCreateInfo multisampleStateParams = + { + VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkPipelineMultisampleStateCreateFlags flags; + VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples; + VK_FALSE, // VkBool32 sampleShadingEnable; + 0.0f, // float minSampleShading; + DE_NULL, // const VkSampleMask* pSampleMask; + VK_FALSE, // VkBool32 alphaToCoverageEnable; + VK_FALSE, // VkBool32 alphaToOneEnable; + }; + + VkPipelineDepthStencilStateCreateInfo depthStencilStateParams = + { + VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkPipelineDepthStencilStateCreateFlags flags; + VK_TRUE, // VkBool32 depthTestEnable; + VK_TRUE, // VkBool32 depthWriteEnable; + VK_COMPARE_OP_LESS_OR_EQUAL, // VkCompareOp depthCompareOp; + VK_FALSE, // VkBool32 depthBoundsTestEnable; + VK_FALSE, // VkBool32 stencilTestEnable; + // VkStencilOpState front; + { + VK_STENCIL_OP_KEEP, // VkStencilOp failOp; + VK_STENCIL_OP_KEEP, // VkStencilOp passOp; + VK_STENCIL_OP_KEEP, // VkStencilOp depthFailOp; + VK_COMPARE_OP_NEVER, // VkCompareOp compareOp; + 0u, // deUint32 compareMask; + 0u, // deUint32 writeMask; + 0u, // deUint32 reference; + }, + // VkStencilOpState back; + { + VK_STENCIL_OP_KEEP, // VkStencilOp failOp; + VK_STENCIL_OP_KEEP, // VkStencilOp passOp; + VK_STENCIL_OP_KEEP, // VkStencilOp depthFailOp; + VK_COMPARE_OP_NEVER, // VkCompareOp compareOp; + 0u, // deUint32 compareMask; + 0u, // deUint32 writeMask; + 0u, // deUint32 reference; + }, + 0.0f, // float minDepthBounds; + 1.0f, // float maxDepthBounds; + }; + + const VkPipelineTessellationStateCreateInfo tessStateCreateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkPipelineTesselationStateCreateFlags flags; + m_patchControlPoints, // deUint32 patchControlPoints; + }; + const VkPipelineTessellationStateCreateInfo* pTessCreateInfo = (m_patchControlPoints > 0) + ? &tessStateCreateInfo + : DE_NULL; + + const VkPipelineCreationFeedbackCreateInfoEXT pipelineCreationFeedbackCreateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO_EXT, // VkStructureType sType; + DE_NULL, // const void* pNext; + pipelineCreationFeedback, // VkPipelineCreationFeedbackEXT* pPipelineCreationFeedback; + m_shaderStageCount, // deUint32 pipelineStageCreationFeedbackCount; + pipelineStageCreationFeedbacks // VkPipelineCreationFeedbackEXT* pPipelineStageCreationFeedbacks; + }; + + deUint32 flagsCreateInfo = VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT; + if (basePipelineHandle != DE_NULL) + { + flagsCreateInfo = VK_PIPELINE_CREATE_DERIVATIVE_BIT; + } + + const VkGraphicsPipelineCreateInfo graphicsPipelineParams = + { + VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType; + &pipelineCreationFeedbackCreateInfo, // const void* pNext; + flagsCreateInfo, // VkPipelineCreateFlags flags; + m_shaderStageCount, // deUint32 stageCount; + m_shaderStageInfo, // const VkPipelineShaderStageCreateInfo* pStages; + &vertexInputStateParams, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState; + &inputAssemblyStateParams, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState; + pTessCreateInfo, // const VkPipelineTessellationStateCreateInfo* pTessellationState; + &viewportStateParams, // const VkPipelineViewportStateCreateInfo* pViewportState; + &rasterStateParams, // const VkPipelineRasterizationStateCreateInfo* pRasterState; + &multisampleStateParams, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState; + &depthStencilStateParams, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState; + &colorBlendStateParams, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState; + (const VkPipelineDynamicStateCreateInfo*)DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState; + pipelineLayout, // VkPipelineLayout layout; + renderPass, // VkRenderPass renderPass; + 0u, // deUint32 subpass; + basePipelineHandle, // VkPipeline basePipelineHandle; + basePipelineHandle != DE_NULL ? -1 : 0, // deInt32 basePipelineIndex; + }; + VkPipeline pipeline; + vk.createGraphicsPipelines(vkDevice, cache, 1u, &graphicsPipelineParams, DE_NULL, &pipeline); + return pipeline; +} + +void SimpleGraphicsPipelineBuilder::enableTessellationStage (deUint32 patchControlPoints) +{ + m_patchControlPoints = patchControlPoints; +} + +template +vkt::TestCase* newTestCase (tcu::TestContext& testContext, + const CacheTestParam* testParam) +{ + return new Test(testContext, + testParam->generateTestName().c_str(), + testParam->generateTestDescription().c_str(), + testParam); +} + +// Test Classes +class CacheTest : public vkt::TestCase +{ +public: + CacheTest(tcu::TestContext& testContext, + const std::string& name, + const std::string& description, + const CacheTestParam* param) + : vkt::TestCase (testContext, name, description) + , m_param (*param) + { } + virtual ~CacheTest (void) { } +protected: + const CacheTestParam m_param; +}; + +class CacheTestInstance : public vkt::TestInstance +{ +public: + CacheTestInstance (Context& context, + const CacheTestParam* param); + virtual ~CacheTestInstance (void); + virtual tcu::TestStatus iterate (void); +protected: + virtual tcu::TestStatus verifyTestResult (void) = 0; +protected: + const CacheTestParam* m_param; + + Move m_cache; + deBool m_extensions; +}; + +CacheTestInstance::CacheTestInstance (Context& context, + const CacheTestParam* param) + : TestInstance (context) + , m_param (param) + , m_extensions (m_context.requireDeviceExtension("VK_EXT_pipeline_creation_feedback")) +{ + const DeviceInterface& vk = m_context.getDeviceInterface(); + const VkDevice vkDevice = m_context.getDevice(); + + if (m_param->isCacheDisabled() == DE_FALSE) + { + const VkPipelineCacheCreateInfo pipelineCacheCreateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkPipelineCacheCreateFlags flags; + 0u, // deUintptr initialDataSize; + DE_NULL, // const void* pInitialData; + }; + + m_cache = createPipelineCache(vk, vkDevice, &pipelineCacheCreateInfo); + } +} + +CacheTestInstance::~CacheTestInstance (void) +{ +} + +tcu::TestStatus CacheTestInstance::iterate (void) +{ + return verifyTestResult(); +} + +class GraphicsCacheTest : public CacheTest +{ +public: + GraphicsCacheTest (tcu::TestContext& testContext, + const std::string& name, + const std::string& description, + const CacheTestParam* param) + : CacheTest (testContext, name, description, param) + { } + virtual ~GraphicsCacheTest (void) { } + virtual void initPrograms (SourceCollections& programCollection) const; + virtual TestInstance* createInstance (Context& context) const; +}; + +class GraphicsCacheTestInstance : public CacheTestInstance +{ +public: + GraphicsCacheTestInstance (Context& context, + const CacheTestParam* param); + virtual ~GraphicsCacheTestInstance (void); +protected: + virtual tcu::TestStatus verifyTestResult (void); + +protected: + const tcu::UVec2 m_renderSize; + const VkFormat m_colorFormat; + const VkFormat m_depthFormat; + Move m_pipelineLayout; + + SimpleGraphicsPipelineBuilder m_pipelineBuilder; + SimpleGraphicsPipelineBuilder m_missPipelineBuilder; + Move m_renderPass; + + VkPipeline m_pipeline[PIPELINE_CACHE_NDX_COUNT]; + VkPipelineCreationFeedbackEXT m_pipelineCreationFeedback[PIPELINE_CACHE_NDX_COUNT]; + VkPipelineCreationFeedbackEXT m_pipelineStageCreationFeedbacks[PIPELINE_CACHE_NDX_COUNT * VK_MAX_SHADER_STAGES]; +}; + +void GraphicsCacheTest::initPrograms (SourceCollections& programCollection) const +{ + for (deUint32 shaderNdx = 0; shaderNdx < m_param.getShaderCount(); shaderNdx++) + { + switch(m_param.getShaderFlag(shaderNdx)) + { + case VK_SHADER_STAGE_VERTEX_BIT: + programCollection.glslSources.add("color_vert_1") << glu::VertexSource( + "#version 310 es\n" + "layout(location = 0) in vec4 position;\n" + "layout(location = 1) in vec4 color;\n" + "layout(location = 0) out highp vec4 vtxColor;\n" + "void main (void)\n" + "{\n" + " gl_Position = position;\n" + " vtxColor = color;\n" + "}\n"); + programCollection.glslSources.add("color_vert_2") << glu::VertexSource( + "#version 310 es\n" + "layout(location = 0) in vec4 position;\n" + "layout(location = 1) in vec4 color;\n" + "layout(location = 0) out highp vec4 vtxColor;\n" + "void main (void)\n" + "{\n" + " gl_Position = position;\n" + " gl_PointSize = 1.0f;\n" + " vtxColor = color + vec4(0.1, 0.2, 0.3, 0.0);\n" + "}\n"); + break; + case VK_SHADER_STAGE_FRAGMENT_BIT: + programCollection.glslSources.add("color_frag") << glu::FragmentSource( + "#version 310 es\n" + "layout(location = 0) in highp vec4 vtxColor;\n" + "layout(location = 0) out highp vec4 fragColor;\n" + "void main (void)\n" + "{\n" + " fragColor = vtxColor;\n" + "}\n"); + break; + + case VK_SHADER_STAGE_GEOMETRY_BIT: + programCollection.glslSources.add("dummy_geo") << glu::GeometrySource( + "#version 450 \n" + "layout(triangles) in;\n" + "layout(triangle_strip, max_vertices = 3) out;\n" + "layout(location = 0) in highp vec4 in_vtxColor[];\n" + "layout(location = 0) out highp vec4 vtxColor;\n" + "out gl_PerVertex { vec4 gl_Position; float gl_PointSize; };\n" + "in gl_PerVertex { vec4 gl_Position; float gl_PointSize; } gl_in[];\n" + "void main (void)\n" + "{\n" + " for(int ndx=0; ndx<3; ndx++)\n" + " {\n" + " gl_Position = gl_in[ndx].gl_Position;\n" + " gl_PointSize = gl_in[ndx].gl_PointSize;\n" + " vtxColor = in_vtxColor[ndx];\n" + " EmitVertex();\n" + " }\n" + " EndPrimitive();\n" + "}\n"); + break; + + case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: + programCollection.glslSources.add("basic_tcs") << glu::TessellationControlSource( + "#version 450 \n" + "layout(vertices = 3) out;\n" + "layout(location = 0) in highp vec4 color[];\n" + "layout(location = 0) out highp vec4 vtxColor[];\n" + "out gl_PerVertex { vec4 gl_Position; float gl_PointSize; } gl_out[3];\n" + "in gl_PerVertex { vec4 gl_Position; float gl_PointSize; } gl_in[gl_MaxPatchVertices];\n" + "void main()\n" + "{\n" + " gl_TessLevelOuter[0] = 4.0;\n" + " gl_TessLevelOuter[1] = 4.0;\n" + " gl_TessLevelOuter[2] = 4.0;\n" + " gl_TessLevelInner[0] = 4.0;\n" + " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n" + " gl_out[gl_InvocationID].gl_PointSize = gl_in[gl_InvocationID].gl_PointSize;\n" + " vtxColor[gl_InvocationID] = color[gl_InvocationID];\n" + "}\n"); + break; + + case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: + programCollection.glslSources.add("basic_tes") << glu::TessellationEvaluationSource( + "#version 450 \n" + "layout(triangles, fractional_even_spacing, ccw) in;\n" + "layout(location = 0) in highp vec4 colors[];\n" + "layout(location = 0) out highp vec4 vtxColor;\n" + "out gl_PerVertex { vec4 gl_Position; float gl_PointSize; };\n" + "in gl_PerVertex { vec4 gl_Position; float gl_PointSize; } gl_in[gl_MaxPatchVertices];\n" + "void main() \n" + "{\n" + " float u = gl_TessCoord.x;\n" + " float v = gl_TessCoord.y;\n" + " float w = gl_TessCoord.z;\n" + " vec4 pos = vec4(0);\n" + " vec4 color = vec4(0);\n" + " pos.xyz += u * gl_in[0].gl_Position.xyz;\n" + " color.xyz += u * colors[0].xyz;\n" + " pos.xyz += v * gl_in[1].gl_Position.xyz;\n" + " color.xyz += v * colors[1].xyz;\n" + " pos.xyz += w * gl_in[2].gl_Position.xyz;\n" + " color.xyz += w * colors[2].xyz;\n" + " pos.w = 1.0;\n" + " color.w = 1.0;\n" + " gl_Position = pos;\n" + " gl_PointSize = gl_in[0].gl_PointSize;" + " vtxColor = color;\n" + "}\n"); + break; + + default: + DE_FATAL("Unknown Shader Stage!"); + break; + }; + } +} + +TestInstance* GraphicsCacheTest::createInstance (Context& context) const +{ + return new GraphicsCacheTestInstance(context, &m_param); +} + +GraphicsCacheTestInstance::GraphicsCacheTestInstance (Context& context, + const CacheTestParam* param) + : CacheTestInstance (context, param) + , m_renderSize (32u, 32u) + , m_colorFormat (VK_FORMAT_R8G8B8A8_UNORM) + , m_depthFormat (VK_FORMAT_D16_UNORM) + , m_pipelineBuilder (context) + , m_missPipelineBuilder (context) +{ + const DeviceInterface& vk = m_context.getDeviceInterface(); + const VkDevice vkDevice = m_context.getDevice(); + + // Create pipeline layout + { + const VkPipelineLayoutCreateInfo pipelineLayoutParams = + { + VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkPipelineLayoutCreateFlags flags; + 0u, // deUint32 setLayoutCount; + DE_NULL, // const VkDescriptorSetLayout* pSetLayouts; + 0u, // deUint32 pushConstantRangeCount; + DE_NULL // const VkPushConstantRange* pPushConstantRanges; + }; + + m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams); + } + + // Create render pass + m_renderPass = makeRenderPass(vk, vkDevice, m_colorFormat, m_depthFormat); + + // Bind shader stages + + VkPhysicalDeviceFeatures features = m_context.getDeviceFeatures(); + for (deUint32 ndx = 0; ndx < PIPELINE_CACHE_NDX_COUNT; ndx++) + { + for (deUint32 shaderNdx = 0; shaderNdx < m_param->getShaderCount(); shaderNdx++) + { + switch(m_param->getShaderFlag(shaderNdx)) + { + case VK_SHADER_STAGE_VERTEX_BIT: + { + std::string shader_name("color_vert_"); + shader_name += (ndx == PIPELINE_CACHE_NDX_DERIVATIVE) ? "2" : "1"; + m_pipelineBuilder.bindShaderStage(VK_SHADER_STAGE_VERTEX_BIT, shader_name.c_str(), "main"); + } + break; + case VK_SHADER_STAGE_FRAGMENT_BIT: + m_pipelineBuilder.bindShaderStage(VK_SHADER_STAGE_FRAGMENT_BIT, "color_frag", "main"); + break; + case VK_SHADER_STAGE_GEOMETRY_BIT: + if (features.geometryShader == VK_FALSE) + { + TCU_THROW(NotSupportedError, "Geometry Shader Not Supported"); + } + else + { + m_pipelineBuilder.bindShaderStage(VK_SHADER_STAGE_GEOMETRY_BIT, "dummy_geo", "main"); + } + break; + case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: + if (features.tessellationShader == VK_FALSE) + { + TCU_THROW(NotSupportedError, "Tessellation Not Supported"); + } + else + { + m_pipelineBuilder.bindShaderStage(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, "basic_tcs", "main"); + m_pipelineBuilder.enableTessellationStage(3); + } + break; + case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: + if (features.tessellationShader == VK_FALSE) + { + TCU_THROW(NotSupportedError, "Tessellation Not Supported"); + } + else + { + m_pipelineBuilder.bindShaderStage(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, "basic_tes", "main"); + m_pipelineBuilder.enableTessellationStage(3); + } + break; + default: + DE_FATAL("Unknown Shader Stage!"); + break; + }; + + } + if (ndx == PIPELINE_CACHE_NDX_CACHED) + { + // Destroy the NO_CACHE pipeline to check that the cached one really hits cache + vk.destroyPipeline(vkDevice, m_pipeline[PIPELINE_CACHE_NDX_NO_CACHE], DE_NULL); + } + + m_pipeline[ndx] = m_pipelineBuilder.buildPipeline(m_renderSize, *m_renderPass, *m_cache, *m_pipelineLayout, + &m_pipelineCreationFeedback[ndx], + &m_pipelineStageCreationFeedbacks[VK_MAX_SHADER_STAGES * ndx], + ndx == PIPELINE_CACHE_NDX_DERIVATIVE ? m_pipeline[PIPELINE_CACHE_NDX_NO_CACHE] : DE_NULL); + m_pipelineBuilder.resetBuilder(); + + if (ndx != PIPELINE_CACHE_NDX_NO_CACHE) + { + // Destroy the pipeline as soon as it is created, except the NO_CACHE because + // it is needed as a base pipeline for the derivative case. + vk.destroyPipeline(vkDevice, m_pipeline[ndx], DE_NULL); + } + } +} + +GraphicsCacheTestInstance::~GraphicsCacheTestInstance (void) +{ +} + +tcu::TestStatus GraphicsCacheTestInstance::verifyTestResult (void) +{ + tcu::TestLog &log = m_context.getTestContext().getLog(); + bool durationZeroWarning = DE_FALSE; + bool cachedPipelineWarning = DE_FALSE; + + for (deUint32 ndx = 0; ndx < PIPELINE_CACHE_NDX_COUNT; ndx++) + { + std::ostringstream message; + message << getCaseStr(ndx); + + // No need to check per stage status as it is compute pipeline (only one stage) and Vulkan spec mentions that: + // "One common scenario for an implementation to skip per-stage feedback is when + // VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT is set in pPipelineCreationFeedback." + // + // Check first that the no cached pipeline was missed in the pipeline cache + if (!(m_pipelineCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT_EXT)) + { + message << ": invalid data"; + return tcu::TestStatus::fail(message.str()); + } + + if (m_param->isCacheDisabled() && m_pipelineCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT) + { + message << ": feedback indicates pipeline hit cache when it shouldn't"; + return tcu::TestStatus::fail(message.str()); + } + + if (ndx == PIPELINE_CACHE_NDX_NO_CACHE && m_pipelineCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT) + { + message << ": hit the cache when it shouldn't"; + return tcu::TestStatus::fail(message.str()); + } + + if (ndx != PIPELINE_CACHE_NDX_DERIVATIVE && m_pipelineCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT_EXT) + { + message << ": feedback indicates base pipeline acceleration when it shouldn't"; + return tcu::TestStatus::fail(message.str()); + } + + if (ndx == PIPELINE_CACHE_NDX_CACHED && !m_param->isCacheDisabled() && (m_pipelineCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT) == 0) + { + message << "\nWarning: Cached pipeline case did not hit the cache"; + cachedPipelineWarning = DE_TRUE; + } + + if (m_pipelineCreationFeedback[ndx].duration == 0) + { + message << "\nWarning: Pipeline creation feedback reports duration spent creating a pipeline was zero nanoseconds\n"; + durationZeroWarning = DE_TRUE; + } + + message << "\n"; + message << "\t\t Hit cache ? \t\t\t" << (m_pipelineCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT ? "yes" : "no") << "\n"; + message << "\t\t Base Pipeline Acceleration ? \t" << (m_pipelineCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT_EXT ? "yes" : "no") << "\n"; + message << "\t\t Duration (ns): \t\t" << m_pipelineCreationFeedback[ndx].duration << "\n"; + + for(deUint32 shader = 0; shader < m_param->getShaderCount(); shader++) + { + const deUint32 index = VK_MAX_SHADER_STAGES * ndx + shader; + message << "\t" << getShaderFlagStr(m_param->getShaderFlag(shader), true) << "\n"; + + if (!(m_pipelineStageCreationFeedbacks[index].flags & VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT_EXT)) + { + if (m_pipelineStageCreationFeedbacks[index].flags) + { + std::ostringstream errorMsg; + errorMsg << getCaseStr(ndx) << ": Creation feedback is not valid for " + getShaderFlagStr(m_param->getShaderFlag(shader), true) + " but there are other flags written"; + return tcu::TestStatus::fail(errorMsg.str()); + } + message << "\t\t Pipeline Creation Feedback data is not valid\n"; + continue; + } + if (m_param->isCacheDisabled() && m_pipelineStageCreationFeedbacks[index].flags & VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT) + { + std::ostringstream errorMsg; + errorMsg << getCaseStr(ndx) << ": feedback indicates pipeline " + getShaderFlagStr(m_param->getShaderFlag(shader), true) + " stage hit cache when it shouldn't"; + return tcu::TestStatus::fail(errorMsg.str()); + } + + if (ndx == PIPELINE_CACHE_NDX_CACHED && !m_param->isCacheDisabled() && (m_pipelineStageCreationFeedbacks[index].flags & VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT) == 0) + { + message << "Warning: pipeline stage did not hit the cache\n"; + cachedPipelineWarning = DE_TRUE; + } + if (cachedPipelineWarning && m_pipelineStageCreationFeedbacks[index].flags & VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT) + { + // We only set the warning when the pipeline nor the pipeline stages hit the cache. If any of them did, them disable the warning. + cachedPipelineWarning = DE_FALSE; + } + + message << "\t\t Hit cache ? \t\t\t" << (m_pipelineStageCreationFeedbacks[index].flags & VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT ? "yes" : "no") << "\n"; + message << "\t\t Base Pipeline Acceleration ? \t" << (m_pipelineStageCreationFeedbacks[index].flags & VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT_EXT ? "yes" : "no") << "\n"; + message << "\t\t Duration (ns): \t\t" << m_pipelineStageCreationFeedbacks[index].duration << "\n"; + } + + log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage; + } + + if (cachedPipelineWarning) + { + return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Cached pipeline or stage did not hit the cache"); + } + if (durationZeroWarning) + { + return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Pipeline creation feedback reports duration spent creating a pipeline was zero nanoseconds"); + } + return tcu::TestStatus::pass("Pass"); +} + +class ComputeCacheTest : public CacheTest +{ +public: + ComputeCacheTest (tcu::TestContext& testContext, + const std::string& name, + const std::string& description, + const CacheTestParam* param) + : CacheTest (testContext, name, description, param) + { } + virtual ~ComputeCacheTest (void) { } + virtual void initPrograms (SourceCollections& programCollection) const; + virtual TestInstance* createInstance (Context& context) const; +}; + +class ComputeCacheTestInstance : public CacheTestInstance +{ +public: + ComputeCacheTestInstance (Context& context, + const CacheTestParam* param); + virtual ~ComputeCacheTestInstance (void); +protected: + virtual tcu::TestStatus verifyTestResult (void); + void buildDescriptorSets (deUint32 ndx); + void buildShader (deUint32 ndx); + void buildPipeline (deUint32 ndx); +protected: + Move m_inputBuf; + de::MovePtr m_inputBufferAlloc; + Move m_computeShaderModule[PIPELINE_CACHE_NDX_COUNT]; + + Move m_outputBuf[PIPELINE_CACHE_NDX_COUNT]; + de::MovePtr m_outputBufferAlloc[PIPELINE_CACHE_NDX_COUNT]; + + Move m_descriptorPool[PIPELINE_CACHE_NDX_COUNT]; + Move m_descriptorSetLayout[PIPELINE_CACHE_NDX_COUNT]; + Move m_descriptorSet[PIPELINE_CACHE_NDX_COUNT]; + + Move m_pipelineLayout[PIPELINE_CACHE_NDX_COUNT]; + VkPipeline m_pipeline[PIPELINE_CACHE_NDX_COUNT]; + VkPipelineCreationFeedbackEXT m_pipelineCreationFeedback[PIPELINE_CACHE_NDX_COUNT]; + VkPipelineCreationFeedbackEXT m_pipelineStageCreationFeedback[PIPELINE_CACHE_NDX_COUNT]; +}; + +void ComputeCacheTest::initPrograms (SourceCollections& programCollection) const +{ + programCollection.glslSources.add("basic_compute_1") << glu::ComputeSource( + "#version 310 es\n" + "layout(local_size_x = 1) in;\n" + "layout(std430) buffer;\n" + "layout(binding = 0) readonly buffer Input0\n" + "{\n" + " vec4 elements[];\n" + "} input_data0;\n" + "layout(binding = 1) writeonly buffer Output\n" + "{\n" + " vec4 elements[];\n" + "} output_data;\n" + "void main()\n" + "{\n" + " uint ident = gl_GlobalInvocationID.x;\n" + " output_data.elements[ident] = input_data0.elements[ident] * input_data0.elements[ident];\n" + "}"); + programCollection.glslSources.add("basic_compute_2") << glu::ComputeSource( + "#version 310 es\n" + "layout(local_size_x = 1) in;\n" + "layout(std430) buffer;\n" + "layout(binding = 0) readonly buffer Input0\n" + "{\n" + " vec4 elements[];\n" + "} input_data0;\n" + "layout(binding = 1) writeonly buffer Output\n" + "{\n" + " vec4 elements[];\n" + "} output_data;\n" + "void main()\n" + "{\n" + " uint ident = gl_GlobalInvocationID.x;\n" + " output_data.elements[ident] = input_data0.elements[ident];\n" + "}"); +} + +TestInstance* ComputeCacheTest::createInstance (Context& context) const +{ + return new ComputeCacheTestInstance(context, &m_param); +} + +void ComputeCacheTestInstance::buildDescriptorSets (deUint32 ndx) +{ + const DeviceInterface& vk = m_context.getDeviceInterface(); + const VkDevice vkDevice = m_context.getDevice(); + + // Create descriptor set layout + DescriptorSetLayoutBuilder descLayoutBuilder; + for (deUint32 bindingNdx = 0u; bindingNdx < 2u; bindingNdx++) + descLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT); + m_descriptorSetLayout[ndx] = descLayoutBuilder.build(vk, vkDevice); +} + +void ComputeCacheTestInstance::buildShader (deUint32 ndx) +{ + const DeviceInterface& vk = m_context.getDeviceInterface(); + const VkDevice vkDevice = m_context.getDevice(); + + std::string shader_name("basic_compute_"); + + shader_name += (ndx == PIPELINE_CACHE_NDX_DERIVATIVE) ? "2" : "1"; + + // Create compute shader + VkShaderModuleCreateInfo shaderModuleCreateInfo = + { + VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkShaderModuleCreateFlags flags; + m_context.getBinaryCollection().get(shader_name).getSize(), // deUintptr codeSize; + (deUint32*)m_context.getBinaryCollection().get(shader_name).getBinary(), // const deUint32* pCode; + }; + m_computeShaderModule[ndx] = createShaderModule(vk, vkDevice, &shaderModuleCreateInfo); +} + +void ComputeCacheTestInstance::buildPipeline (deUint32 ndx) +{ + const DeviceInterface& vk = m_context.getDeviceInterface(); + const VkDevice vkDevice = m_context.getDevice(); + + deMemset(&m_pipelineCreationFeedback[ndx], 0, sizeof(VkPipelineCreationFeedbackEXT)); + deMemset(&m_pipelineStageCreationFeedback[ndx], 0, sizeof(VkPipelineCreationFeedbackEXT)); + + const VkPipelineCreationFeedbackCreateInfoEXT pipelineCreationFeedbackCreateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO_EXT, // VkStructureType sType; + DE_NULL, // const void * pNext; + &m_pipelineCreationFeedback[ndx], // VkPipelineCreationFeedbackEXT* pPipelineCreationFeedback; + 1u, // deUint32 pipelineStageCreationFeedbackCount; + &m_pipelineStageCreationFeedback[ndx] // VkPipelineCreationFeedbackEXT* pPipelineStageCreationFeedbacks; + }; + + // Create compute pipeline layout + const VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkPipelineLayoutCreateFlags flags; + 1u, // deUint32 setLayoutCount; + &m_descriptorSetLayout[ndx].get(), // const VkDescriptorSetLayout* pSetLayouts; + 0u, // deUint32 pushConstantRangeCount; + DE_NULL, // const VkPushConstantRange* pPushConstantRanges; + }; + + m_pipelineLayout[ndx] = createPipelineLayout(vk, vkDevice, &pipelineLayoutCreateInfo); + + const VkPipelineShaderStageCreateInfo stageCreateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkPipelineShaderStageCreateFlags flags; + VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlagBits stage; + *m_computeShaderModule[ndx], // VkShaderModule module; + "main", // const char* pName; + DE_NULL, // const VkSpecializationInfo* pSpecializationInfo; + }; + + VkComputePipelineCreateInfo pipelineCreateInfo = + { + VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // VkStructureType sType; + &pipelineCreationFeedbackCreateInfo, // const void* pNext; + 0u, // VkPipelineCreateFlags flags; + stageCreateInfo, // VkPipelineShaderStageCreateInfo stage; + *m_pipelineLayout[ndx], // VkPipelineLayout layout; + (VkPipeline)0, // VkPipeline basePipelineHandle; + 0u, // deInt32 basePipelineIndex; + }; + + if (ndx == PIPELINE_CACHE_NDX_NO_CACHE) + { + pipelineCreateInfo.flags = VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT; + } + + if (ndx == PIPELINE_CACHE_NDX_DERIVATIVE) + { + pipelineCreateInfo.flags = VK_PIPELINE_CREATE_DERIVATIVE_BIT; + pipelineCreateInfo.basePipelineHandle = m_pipeline[PIPELINE_CACHE_NDX_NO_CACHE]; + pipelineCreateInfo.basePipelineIndex = -1; + } + + if (ndx == PIPELINE_CACHE_NDX_CACHED) + { + // Destroy the NO_CACHE pipeline to check that the cached one really hits cache + vk.destroyPipeline(vkDevice, m_pipeline[PIPELINE_CACHE_NDX_NO_CACHE], DE_NULL); + } + + vk.createComputePipelines(vkDevice, *m_cache, 1u, &pipelineCreateInfo, DE_NULL, &m_pipeline[ndx]); + + if (ndx != PIPELINE_CACHE_NDX_NO_CACHE) + { + // Destroy the pipeline as soon as it is created, except the NO_CACHE because + // it is needed as a base pipeline for the derivative case. + vk.destroyPipeline(vkDevice, m_pipeline[ndx], DE_NULL); + } +} + +ComputeCacheTestInstance::ComputeCacheTestInstance (Context& context, + const CacheTestParam* param) + : CacheTestInstance (context, param) +{ + for (deUint32 ndx = 0; ndx < PIPELINE_CACHE_NDX_COUNT; ndx++) + { + buildDescriptorSets(ndx); + buildShader(ndx); + buildPipeline(ndx); + } +} + +ComputeCacheTestInstance::~ComputeCacheTestInstance (void) +{ +} + +tcu::TestStatus ComputeCacheTestInstance::verifyTestResult (void) +{ + tcu::TestLog &log = m_context.getTestContext().getLog(); + deBool durationZeroWarning = DE_FALSE; + deBool cachedPipelineWarning = DE_FALSE; + + for (deUint32 ndx = 0; ndx < PIPELINE_CACHE_NDX_COUNT; ndx++) + { + std::ostringstream message; + message << getCaseStr(ndx); + + // No need to check per stage status as it is compute pipeline (only one stage) and Vulkan spec mentions that: + // "One common scenario for an implementation to skip per-stage feedback is when + // VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT is set in pPipelineCreationFeedback." + // + // Check first that the no cached pipeline was missed in the pipeline cache + if (!(m_pipelineCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT_EXT)) + { + message << ": invalid data"; + return tcu::TestStatus::fail(message.str()); + } + + if (m_param->isCacheDisabled() && m_pipelineCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT) + { + message << ": feedback indicates pipeline hit cache when it shouldn't"; + return tcu::TestStatus::fail(message.str()); + } + + if (ndx == PIPELINE_CACHE_NDX_NO_CACHE && m_pipelineCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT) + { + message << ": hit the cache when it shouldn't"; + return tcu::TestStatus::fail(message.str()); + } + + if (!(ndx == PIPELINE_CACHE_NDX_DERIVATIVE && !m_param->isCacheDisabled()) && m_pipelineCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT_EXT) + { + message << ": feedback indicates base pipeline acceleration when it shouldn't"; + return tcu::TestStatus::fail(message.str()); + } + + if (ndx == PIPELINE_CACHE_NDX_CACHED && !m_param->isCacheDisabled() && (m_pipelineCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT) == 0) + { + message << "\nWarning: Cached pipeline case did not hit the cache"; + cachedPipelineWarning = DE_TRUE; + } + + if (m_pipelineCreationFeedback[ndx].duration == 0) + { + message << "\nWarning: Pipeline creation feedback reports duration spent creating a pipeline was zero nanoseconds\n"; + durationZeroWarning = DE_TRUE; + } + + message << "\n"; + + message << "\t\t Hit cache ? \t\t\t" << (m_pipelineCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT ? "yes" : "no") << "\n"; + message << "\t\t Base Pipeline Acceleration ? \t" << (m_pipelineCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT_EXT ? "yes" : "no") << "\n"; + message << "\t\t Duration (ns): \t\t" << m_pipelineCreationFeedback[ndx].duration << "\n"; + + message << "\t Compute Stage\n"; + + // According to the spec: + // + // "An implementation should write pipeline creation feedback to pPipelineCreationFeedback and + // may write pipeline stage creation feedback to pPipelineStageCreationFeedbacks." + if (!(m_pipelineStageCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT_EXT)) + { + // According to the spec: + // "If the VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT_EXT is not set in flags, an implementation + // must not set any other bits in flags, and all other VkPipelineCreationFeedbackEXT data members are undefined." + if (m_pipelineStageCreationFeedback[ndx].flags) + { + std::ostringstream errorMsg; + errorMsg << getCaseStr(ndx) << ": Creation feedback is not valid for compute stage but there are other flags written"; + return tcu::TestStatus::fail(errorMsg.str()); + } + message << "\t\t Pipeline Creation Feedback data is not valid\n"; + } + else + { + if (m_param->isCacheDisabled() && m_pipelineStageCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT) + { + std::ostringstream errorMsg; + errorMsg << getCaseStr(ndx) << ": feedback indicates pipeline compute stage hit cache when it shouldn't"; + return tcu::TestStatus::fail(errorMsg.str()); + } + + if (ndx == PIPELINE_CACHE_NDX_CACHED && !m_param->isCacheDisabled() && (m_pipelineStageCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT) == 0) + { + message << "Warning: pipeline stage did not hit the cache\n"; + cachedPipelineWarning = DE_TRUE; + } + if (cachedPipelineWarning && m_pipelineStageCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT) + { + // We only set the warning when the pipeline nor the pipeline stages hit the cache. If any of them did, them disable the warning. + cachedPipelineWarning = DE_FALSE; + } + + message << "\t\t Hit cache ? \t\t\t" << (m_pipelineStageCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT ? "yes" : "no") << "\n"; + message << "\t\t Base Pipeline Acceleration ? \t" << (m_pipelineStageCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT_EXT ? "yes" : "no") << "\n"; + message << "\t\t Duration (ns): \t\t" << m_pipelineStageCreationFeedback[ndx].duration << "\n"; + } + + log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage; + } + + if (cachedPipelineWarning) + { + return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Cached pipeline or stage did not hit the cache"); + } + if (durationZeroWarning) + { + return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Pipeline creation feedback reports duration spent creating a pipeline was zero nanoseconds"); + } + return tcu::TestStatus::pass("Pass"); +} +} // anonymous + +tcu::TestCaseGroup* createCreationFeedbackTests (tcu::TestContext& testCtx) +{ + + de::MovePtr cacheTests (new tcu::TestCaseGroup(testCtx, "creation_feedback", "pipeline creation feedback tests")); + + // Graphics Pipeline Tests + { + de::MovePtr graphicsTests (new tcu::TestCaseGroup(testCtx, "graphics_tests", "Test pipeline creation feedback with graphics pipeline.")); + + const VkShaderStageFlagBits testParamShaders0[] = + { + VK_SHADER_STAGE_VERTEX_BIT, + VK_SHADER_STAGE_FRAGMENT_BIT, + }; + const VkShaderStageFlagBits testParamShaders1[] = + { + VK_SHADER_STAGE_VERTEX_BIT, + VK_SHADER_STAGE_GEOMETRY_BIT, + VK_SHADER_STAGE_FRAGMENT_BIT, + }; + const VkShaderStageFlagBits testParamShaders2[] = + { + VK_SHADER_STAGE_VERTEX_BIT, + VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, + VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, + VK_SHADER_STAGE_FRAGMENT_BIT, + }; + const CacheTestParam testParams[] = + { + CacheTestParam(testParamShaders0, DE_LENGTH_OF_ARRAY(testParamShaders0), DE_FALSE), + CacheTestParam(testParamShaders1, DE_LENGTH_OF_ARRAY(testParamShaders1), DE_FALSE), + CacheTestParam(testParamShaders2, DE_LENGTH_OF_ARRAY(testParamShaders2), DE_FALSE), + CacheTestParam(testParamShaders0, DE_LENGTH_OF_ARRAY(testParamShaders0), DE_TRUE), + CacheTestParam(testParamShaders1, DE_LENGTH_OF_ARRAY(testParamShaders1), DE_TRUE), + CacheTestParam(testParamShaders2, DE_LENGTH_OF_ARRAY(testParamShaders2), DE_TRUE), + }; + + for (deUint32 i = 0; i < DE_LENGTH_OF_ARRAY(testParams); i++) + graphicsTests->addChild(newTestCase(testCtx, &testParams[i])); + + cacheTests->addChild(graphicsTests.release()); + } + + // Compute Pipeline Tests + { + de::MovePtr computeTests (new tcu::TestCaseGroup(testCtx, "compute_tests", "Test pipeline creation feedback with compute pipeline.")); + + const VkShaderStageFlagBits testParamShaders0[] = + { + VK_SHADER_STAGE_COMPUTE_BIT, + }; + const CacheTestParam testParams[] = + { + CacheTestParam(testParamShaders0, DE_LENGTH_OF_ARRAY(testParamShaders0), DE_FALSE), + CacheTestParam(testParamShaders0, DE_LENGTH_OF_ARRAY(testParamShaders0), DE_TRUE), + }; + + for (deUint32 i = 0; i < DE_LENGTH_OF_ARRAY(testParams); i++) + computeTests->addChild(newTestCase(testCtx, &testParams[i])); + + cacheTests->addChild(computeTests.release()); + } + + return cacheTests.release(); +} + +} // pipeline + +} // vkt diff --git a/external/vulkancts/modules/vulkan/pipeline/vktPipelineCreationFeedbackTests.hpp b/external/vulkancts/modules/vulkan/pipeline/vktPipelineCreationFeedbackTests.hpp new file mode 100644 index 0000000..6ecd5dd --- /dev/null +++ b/external/vulkancts/modules/vulkan/pipeline/vktPipelineCreationFeedbackTests.hpp @@ -0,0 +1,39 @@ +#ifndef _VKTPIPELINECREATIONFEEDBACKTESTS_HPP +#define _VKTPIPELINECREATIONFEEDBACKTESTS_HPP +/*------------------------------------------------------------------------ + * Vulkan Conformance Tests + * ------------------------ + * + * Copyright (c) 2019 The Khronos Group Inc. + * Copyright (c) 2019 Valve Corporation. + * + * 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 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *//*! + * \file + * \brief Pipeline Creation Feedback Tests + *//*--------------------------------------------------------------------*/ + +#include "vktTestCase.hpp" + +namespace vkt +{ +namespace pipeline +{ + +tcu::TestCaseGroup* createCreationFeedbackTests (tcu::TestContext& testCtx); + +} // pipeline +} // vkt + +#endif // _VKTPIPELINECREATIONFEEDBACKTESTS_HPP diff --git a/external/vulkancts/modules/vulkan/pipeline/vktPipelineTests.cpp b/external/vulkancts/modules/vulkan/pipeline/vktPipelineTests.cpp index 707a8ac..4981891 100644 --- a/external/vulkancts/modules/vulkan/pipeline/vktPipelineTests.cpp +++ b/external/vulkancts/modules/vulkan/pipeline/vktPipelineTests.cpp @@ -46,6 +46,7 @@ #include "vktPipelineFramebufferAttachmentTests.hpp" #include "vktPipelineStencilExportTests.hpp" #include "vktPipelineDerivativeTests.hpp" +#include "vktPipelineCreationFeedbackTests.hpp" #include "vktTestGroupUtil.hpp" namespace vkt @@ -83,6 +84,7 @@ void createChildren (tcu::TestCaseGroup* pipelineTests) pipelineTests->addChild(createFramebufferAttachmentTests (testCtx)); pipelineTests->addChild(createStencilExportTests (testCtx)); pipelineTests->addChild(createDerivativeTests (testCtx)); + pipelineTests->addChild(createCreationFeedbackTests (testCtx)); } } // anonymous diff --git a/external/vulkancts/mustpass/master/vk-default-no-waivers.txt b/external/vulkancts/mustpass/master/vk-default-no-waivers.txt index e8b9291..858cf5a 100644 --- a/external/vulkancts/mustpass/master/vk-default-no-waivers.txt +++ b/external/vulkancts/mustpass/master/vk-default-no-waivers.txt @@ -178408,6 +178408,14 @@ dEQP-VK.pipeline.framebuffer_attachment.diff_attachments_2d_19x27_32x32_ms dEQP-VK.pipeline.shader_stencil_export.op_replace dEQP-VK.pipeline.derivative.compute.derivative_by_handle dEQP-VK.pipeline.derivative.compute.derivative_by_index +dEQP-VK.pipeline.creation_feedback.graphics_tests.vertex_stage_fragment_stage +dEQP-VK.pipeline.creation_feedback.graphics_tests.vertex_stage_geometry_stage_fragment_stage +dEQP-VK.pipeline.creation_feedback.graphics_tests.vertex_stage_tessellation_control_stage_tessellation_evaluation_stage_fragment_stage +dEQP-VK.pipeline.creation_feedback.graphics_tests.vertex_stage_fragment_stage_no_cache +dEQP-VK.pipeline.creation_feedback.graphics_tests.vertex_stage_geometry_stage_no_cache_fragment_stage_no_cache +dEQP-VK.pipeline.creation_feedback.graphics_tests.vertex_stage_tessellation_control_stage_no_cache_tessellation_evaluation_stage_no_cache_fragment_stage_no_cache +dEQP-VK.pipeline.creation_feedback.compute_tests.compute_stage +dEQP-VK.pipeline.creation_feedback.compute_tests.compute_stage_no_cache dEQP-VK.binding_model.shader_access.primary_cmd_buf.sampler_mutable.no_access.single_descriptor.1d dEQP-VK.binding_model.shader_access.primary_cmd_buf.sampler_mutable.no_access.single_descriptor.1d_base_mip dEQP-VK.binding_model.shader_access.primary_cmd_buf.sampler_mutable.no_access.single_descriptor.1d_base_slice diff --git a/external/vulkancts/mustpass/master/vk-default.txt b/external/vulkancts/mustpass/master/vk-default.txt index 830cdcb..001c332 100644 --- a/external/vulkancts/mustpass/master/vk-default.txt +++ b/external/vulkancts/mustpass/master/vk-default.txt @@ -178408,6 +178408,14 @@ dEQP-VK.pipeline.framebuffer_attachment.diff_attachments_2d_19x27_32x32_ms dEQP-VK.pipeline.shader_stencil_export.op_replace dEQP-VK.pipeline.derivative.compute.derivative_by_handle dEQP-VK.pipeline.derivative.compute.derivative_by_index +dEQP-VK.pipeline.creation_feedback.graphics_tests.vertex_stage_fragment_stage +dEQP-VK.pipeline.creation_feedback.graphics_tests.vertex_stage_geometry_stage_fragment_stage +dEQP-VK.pipeline.creation_feedback.graphics_tests.vertex_stage_tessellation_control_stage_tessellation_evaluation_stage_fragment_stage +dEQP-VK.pipeline.creation_feedback.graphics_tests.vertex_stage_fragment_stage_no_cache +dEQP-VK.pipeline.creation_feedback.graphics_tests.vertex_stage_geometry_stage_no_cache_fragment_stage_no_cache +dEQP-VK.pipeline.creation_feedback.graphics_tests.vertex_stage_tessellation_control_stage_no_cache_tessellation_evaluation_stage_no_cache_fragment_stage_no_cache +dEQP-VK.pipeline.creation_feedback.compute_tests.compute_stage +dEQP-VK.pipeline.creation_feedback.compute_tests.compute_stage_no_cache dEQP-VK.binding_model.shader_access.primary_cmd_buf.sampler_mutable.no_access.single_descriptor.1d dEQP-VK.binding_model.shader_access.primary_cmd_buf.sampler_mutable.no_access.single_descriptor.1d_base_mip dEQP-VK.binding_model.shader_access.primary_cmd_buf.sampler_mutable.no_access.single_descriptor.1d_base_slice diff --git a/external/vulkancts/scripts/src/vulkan.h.in b/external/vulkancts/scripts/src/vulkan.h.in index 5e26af3..c918df2 100755 --- a/external/vulkancts/scripts/src/vulkan.h.in +++ b/external/vulkancts/scripts/src/vulkan.h.in @@ -410,6 +410,7 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT = 1000190000, VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT = 1000190001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT = 1000190002, + VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO_EXT = 1000192000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR = 1000196000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES_KHR = 1000197000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES_KHR = 1000199000, @@ -8392,7 +8393,6 @@ VKAPI_ATTR void VKAPI_CALL vkResetQueryPoolEXT( uint32_t queryCount); #endif - #define VK_EXT_pci_bus_info 1 #define VK_EXT_PCI_BUS_INFO_SPEC_VERSION 2 #define VK_EXT_PCI_BUS_INFO_EXTENSION_NAME "VK_EXT_pci_bus_info" @@ -8434,6 +8434,7 @@ typedef struct VkMemoryPriorityAllocateInfoEXT { float priority; } VkMemoryPriorityAllocateInfoEXT; + #define VK_KHR_uniform_buffer_standard_layout 1 #define VK_KHR_UNIFORM_BUFFER_STANDARD_LAYOUT_SPEC_VERSION 1 #define VK_KHR_UNIFORM_BUFFER_STANDARD_LAYOUT_EXTENSION_NAME "VK_KHR_uniform_buffer_standard_layout" @@ -8445,6 +8446,29 @@ typedef struct VkPhysicalDeviceUniformBufferStandardLayoutFeaturesKHR { } VkPhysicalDeviceUniformBufferStandardLayoutFeaturesKHR; +#define VK_EXT_pipeline_creation_feedback 1 +#define VK_EXT_PIPELINE_CREATION_FEEDBACK_SPEC_VERSION 1 +#define VK_EXT_PIPELINE_CREATION_FEEDBACK_EXTENSION_NAME "VK_EXT_pipeline_creation_feedback" + +typedef enum VkPipelineCreationFeedbackFlagBitsEXT { + VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT_EXT = 0x00000001, + VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT = 0x00000002, + VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT_EXT = 0x00000004, + VK_PIPELINE_CREATION_FEEDBACK_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkPipelineCreationFeedbackFlagBitsEXT; +typedef VkFlags VkPipelineCreationFeedbackFlagsEXT; +typedef struct VkPipelineCreationFeedbackEXT { + VkPipelineCreationFeedbackFlagsEXT flags; + uint64_t duration; +} VkPipelineCreationFeedbackEXT; + +typedef struct VkPipelineCreationFeedbackCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkPipelineCreationFeedbackEXT* pPipelineCreationFeedback; + uint32_t pipelineStageCreationFeedbackCount; + VkPipelineCreationFeedbackEXT* pPipelineStageCreationFeedbacks; +} VkPipelineCreationFeedbackCreateInfoEXT; #ifdef __cplusplus } -- 2.7.4