From b20c2824cd8c0fe8e6bffd70cb65062f91accee3 Mon Sep 17 00:00:00 2001 From: Michal Jakubek Date: Thu, 27 Dec 2018 09:54:56 +0000 Subject: [PATCH] Add tests for VK_EXT_descriptor_indexing Adds: dEQP-VK.descriptor_indexing.* Components: Vulkan, Framework VK-GL-CTS issue: 1003 Change-Id: Ia9790d6e60997aae4f448e2a0a98302cd5189bcd --- AndroidGen.mk | 4 + android/cts/master/vk-master.txt | 48 + external/vulkancts/modules/vulkan/CMakeLists.txt | 3 + .../vulkan/descriptor_indexing/CMakeLists.txt | 17 + .../vktDescriptorIndexingTests.cpp | 40 + .../vktDescriptorIndexingTests.hpp | 41 + .../vktDescriptorSetsIndexingTests.cpp | 3336 ++++++++++++++++++++ .../vktDescriptorSetsIndexingTests.hpp | 370 +++ .../vktDescriptorSetsIndexingTestsUtils.cpp | 765 +++++ .../vulkancts/modules/vulkan/vktTestPackage.cpp | 2 + .../mustpass/master/vk-default-no-waivers.txt | 48 + external/vulkancts/mustpass/master/vk-default.txt | 48 + 12 files changed, 4722 insertions(+) create mode 100644 external/vulkancts/modules/vulkan/descriptor_indexing/CMakeLists.txt create mode 100644 external/vulkancts/modules/vulkan/descriptor_indexing/vktDescriptorIndexingTests.cpp create mode 100644 external/vulkancts/modules/vulkan/descriptor_indexing/vktDescriptorIndexingTests.hpp create mode 100644 external/vulkancts/modules/vulkan/descriptor_indexing/vktDescriptorSetsIndexingTests.cpp create mode 100644 external/vulkancts/modules/vulkan/descriptor_indexing/vktDescriptorSetsIndexingTests.hpp create mode 100644 external/vulkancts/modules/vulkan/descriptor_indexing/vktDescriptorSetsIndexingTestsUtils.cpp diff --git a/AndroidGen.mk b/AndroidGen.mk index 9a32ee4..e14a04d 100644 --- a/AndroidGen.mk +++ b/AndroidGen.mk @@ -108,6 +108,9 @@ LOCAL_SRC_FILES := \ external/vulkancts/modules/vulkan/conditional_rendering/vktConditionalDrawTests.cpp \ external/vulkancts/modules/vulkan/conditional_rendering/vktConditionalRenderingTestUtil.cpp \ external/vulkancts/modules/vulkan/conditional_rendering/vktConditionalTests.cpp \ + external/vulkancts/modules/vulkan/descriptor_indexing/vktDescriptorIndexingTests.cpp \ + external/vulkancts/modules/vulkan/descriptor_indexing/vktDescriptorSetsIndexingTests.cpp \ + external/vulkancts/modules/vulkan/descriptor_indexing/vktDescriptorSetsIndexingTestsUtils.cpp \ external/vulkancts/modules/vulkan/device_group/vktDeviceGroupRendering.cpp \ external/vulkancts/modules/vulkan/draw/vktBasicDrawTests.cpp \ external/vulkancts/modules/vulkan/draw/vktDrawBaseClass.cpp \ @@ -1093,6 +1096,7 @@ LOCAL_C_INCLUDES := \ $(deqp_dir)/external/vulkancts/modules/vulkan/clipping \ $(deqp_dir)/external/vulkancts/modules/vulkan/compute \ $(deqp_dir)/external/vulkancts/modules/vulkan/conditional_rendering \ + $(deqp_dir)/external/vulkancts/modules/vulkan/descriptor_indexing \ $(deqp_dir)/external/vulkancts/modules/vulkan/device_group \ $(deqp_dir)/external/vulkancts/modules/vulkan/draw \ $(deqp_dir)/external/vulkancts/modules/vulkan/dynamic_state \ diff --git a/android/cts/master/vk-master.txt b/android/cts/master/vk-master.txt index 46bbe2a..8079130 100755 --- a/android/cts/master/vk-master.txt +++ b/android/cts/master/vk-master.txt @@ -419516,3 +419516,51 @@ dEQP-VK.transform_feedback.fuzz.random_geometry.all_unordered_and_missing.96 dEQP-VK.transform_feedback.fuzz.random_geometry.all_unordered_and_missing.97 dEQP-VK.transform_feedback.fuzz.random_geometry.all_unordered_and_missing.98 dEQP-VK.transform_feedback.fuzz.random_geometry.all_unordered_and_missing.99 +dEQP-VK.descriptor_indexing.storage_buffer +dEQP-VK.descriptor_indexing.storage_texel_buffer +dEQP-VK.descriptor_indexing.uniform_texel_buffer +dEQP-VK.descriptor_indexing.storage_image +dEQP-VK.descriptor_indexing.storage_buffer_in_loop +dEQP-VK.descriptor_indexing.storage_texel_buffer_in_loop +dEQP-VK.descriptor_indexing.uniform_texel_buffer_in_loop +dEQP-VK.descriptor_indexing.storage_image_in_loop +dEQP-VK.descriptor_indexing.storage_buffer_after_bind +dEQP-VK.descriptor_indexing.storage_texel_buffer_after_bind +dEQP-VK.descriptor_indexing.uniform_texel_buffer_after_bind +dEQP-VK.descriptor_indexing.storage_image_after_bind +dEQP-VK.descriptor_indexing.storage_buffer_after_bind_in_loop +dEQP-VK.descriptor_indexing.storage_texel_buffer_after_bind_in_loop +dEQP-VK.descriptor_indexing.uniform_texel_buffer_after_bind_in_loop +dEQP-VK.descriptor_indexing.storage_image_after_bind_in_loop +dEQP-VK.descriptor_indexing.sampler +dEQP-VK.descriptor_indexing.sampled_image +dEQP-VK.descriptor_indexing.combined_image_sampler +dEQP-VK.descriptor_indexing.sampler_with_lod +dEQP-VK.descriptor_indexing.sampled_image_with_lod +dEQP-VK.descriptor_indexing.combined_image_sampler_with_lod +dEQP-VK.descriptor_indexing.sampler_in_loop +dEQP-VK.descriptor_indexing.sampled_image_in_loop +dEQP-VK.descriptor_indexing.combined_image_sampler_in_loop +dEQP-VK.descriptor_indexing.sampler_in_loop_with_lod +dEQP-VK.descriptor_indexing.sampled_image_in_loop_with_lod +dEQP-VK.descriptor_indexing.combined_image_sampler_in_loop_with_lod +dEQP-VK.descriptor_indexing.sampler_after_bind +dEQP-VK.descriptor_indexing.sampled_image_after_bind +dEQP-VK.descriptor_indexing.combined_image_sampler_after_bind +dEQP-VK.descriptor_indexing.sampler_after_bind_with_lod +dEQP-VK.descriptor_indexing.sampled_image_after_bind_with_lod +dEQP-VK.descriptor_indexing.combined_image_sampler_after_bind_with_lod +dEQP-VK.descriptor_indexing.sampler_after_bind_in_loop +dEQP-VK.descriptor_indexing.sampled_image_after_bind_in_loop +dEQP-VK.descriptor_indexing.combined_image_sampler_after_bind_in_loop +dEQP-VK.descriptor_indexing.sampler_after_bind_in_loop_with_lod +dEQP-VK.descriptor_indexing.sampled_image_after_bind_in_loop_with_lod +dEQP-VK.descriptor_indexing.combined_image_sampler_after_bind_in_loop_with_lod +dEQP-VK.descriptor_indexing.uniform_buffer +dEQP-VK.descriptor_indexing.storage_buffer_dynamic +dEQP-VK.descriptor_indexing.uniform_buffer_dynamic +dEQP-VK.descriptor_indexing.input_attachment +dEQP-VK.descriptor_indexing.uniform_buffer_in_loop +dEQP-VK.descriptor_indexing.storage_buffer_dynamic_in_loop +dEQP-VK.descriptor_indexing.uniform_buffer_dynamic_in_loop +dEQP-VK.descriptor_indexing.input_attachment_in_loop diff --git a/external/vulkancts/modules/vulkan/CMakeLists.txt b/external/vulkancts/modules/vulkan/CMakeLists.txt index cfade52..2c315e1 100644 --- a/external/vulkancts/modules/vulkan/CMakeLists.txt +++ b/external/vulkancts/modules/vulkan/CMakeLists.txt @@ -36,6 +36,7 @@ add_subdirectory(transform_feedback) add_subdirectory(util) add_subdirectory(amber) add_subdirectory(imageless_framebuffer) +add_subdirectory(descriptor_indexing) include_directories( api @@ -74,6 +75,7 @@ include_directories( util amber imageless_framebuffer + descriptor_indexing ) set(DEQP_VK_SRCS @@ -131,6 +133,7 @@ set(DEQP_VK_LIBS deqp-vk-amber deqp-vk-imageless-framebuffer deqp-vk-transform-feedback + deqp-vk-descriptor-indexing ) if (DE_COMPILER_IS_MSC AND (DE_PTR_SIZE EQUAL 4)) diff --git a/external/vulkancts/modules/vulkan/descriptor_indexing/CMakeLists.txt b/external/vulkancts/modules/vulkan/descriptor_indexing/CMakeLists.txt new file mode 100644 index 0000000..2349c83 --- /dev/null +++ b/external/vulkancts/modules/vulkan/descriptor_indexing/CMakeLists.txt @@ -0,0 +1,17 @@ +include_directories(..) + +set(DEQP_VK_DESCRIPTOR_INDEXING_SRCS + vktDescriptorIndexingTests.hpp + vktDescriptorIndexingTests.cpp + vktDescriptorSetsIndexingTests.cpp + vktDescriptorSetsIndexingTests.hpp + vktDescriptorSetsIndexingTestsUtils.cpp +) + +set(DEQP_VK_DESCRIPTOR_INDEXING_LIBS + tcutil + vkutil +) + +add_library(deqp-vk-descriptor-indexing STATIC ${DEQP_VK_DESCRIPTOR_INDEXING_SRCS}) +target_link_libraries(deqp-vk-descriptor-indexing ${DEQP_VK_DESCRIPTOR_INDEXING_LIBS}) diff --git a/external/vulkancts/modules/vulkan/descriptor_indexing/vktDescriptorIndexingTests.cpp b/external/vulkancts/modules/vulkan/descriptor_indexing/vktDescriptorIndexingTests.cpp new file mode 100644 index 0000000..0c41b07 --- /dev/null +++ b/external/vulkancts/modules/vulkan/descriptor_indexing/vktDescriptorIndexingTests.cpp @@ -0,0 +1,40 @@ +/*------------------------------------------------------------------------ +* Vulkan Conformance Tests +* ------------------------ +* +* Copyright (c) 2019 The Khronos Group Inc. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* 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 Vulkan Descriptor Indexing Tests +*//*--------------------------------------------------------------------*/ + +#include "vktDescriptorIndexingTests.hpp" +#include "vktTestGroupUtil.hpp" + +namespace vkt +{ +namespace DescriptorIndexing +{ + +void descriptorIndexingDescriptorSetsCreateTests(tcu::TestCaseGroup* group); + +tcu::TestCaseGroup* createTests(tcu::TestContext& testCtx) +{ + return createTestGroup(testCtx, "descriptor_indexing", "Descriptor Indexing Tests", descriptorIndexingDescriptorSetsCreateTests); +} + +} // DescriptorIndexing +} // vkt diff --git a/external/vulkancts/modules/vulkan/descriptor_indexing/vktDescriptorIndexingTests.hpp b/external/vulkancts/modules/vulkan/descriptor_indexing/vktDescriptorIndexingTests.hpp new file mode 100644 index 0000000..4b21351 --- /dev/null +++ b/external/vulkancts/modules/vulkan/descriptor_indexing/vktDescriptorIndexingTests.hpp @@ -0,0 +1,41 @@ +#ifndef _VKTDESCRIPTORINDEXINGTESTS_HPP +#define _VKTDESCRIPTORINDEXINGTESTS_HPP +/*------------------------------------------------------------------------ +* Vulkan Conformance Tests +* ------------------------ +* +* Copyright (c) 2019 The Khronos Group Inc. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* 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 Vulkan Descriptor Indexing Tests +*//*--------------------------------------------------------------------*/ + +#include "tcuDefs.hpp" +#include "tcuTestCase.hpp" + +//#include "vulkan_stub.hpp" + +namespace vkt +{ +namespace DescriptorIndexing +{ + +tcu::TestCaseGroup* createTests(tcu::TestContext& testCtx); + +} // DescriptorIndexing +} // vkt + +#endif // _VKTDESCRIPTORINDEXINGTESTS_HPP diff --git a/external/vulkancts/modules/vulkan/descriptor_indexing/vktDescriptorSetsIndexingTests.cpp b/external/vulkancts/modules/vulkan/descriptor_indexing/vktDescriptorSetsIndexingTests.cpp new file mode 100644 index 0000000..afd7b77 --- /dev/null +++ b/external/vulkancts/modules/vulkan/descriptor_indexing/vktDescriptorSetsIndexingTests.cpp @@ -0,0 +1,3336 @@ +/*------------------------------------------------------------------------ +* Vulkan Conformance Tests +* ------------------------ +* +* Copyright (c) 2019 The Khronos Group Inc. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* 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 Vulkan Decriptor Indexing Tests +*//*--------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include +#include + +#include "vktDescriptorSetsIndexingTests.hpp" + +#include "vkBuilderUtil.hpp" +#include "vkCmdUtil.hpp" +#include "vkDefs.hpp" +#include "vkObjUtil.hpp" +#include "vkPlatform.hpp" +#include "vkPrograms.hpp" +#include "vkQueryUtil.hpp" +#include "vkTypeUtil.hpp" + +#include "tcuTestLog.hpp" +#include "tcuResource.hpp" +#include "tcuImageCompare.hpp" +#include "tcuCommandLine.hpp" +#include "tcuStringTemplate.hpp" +#include "tcuSurface.hpp" +#include "tcuVectorUtil.hpp" + +#include "deRandom.hpp" +#include "deMath.h" +#include "deStringUtil.hpp" + +namespace vkt +{ +namespace DescriptorIndexing +{ +namespace +{ +using namespace vk; +using tcu::UVec2; +using tcu::Vec4; +using tcu::TestStatus; +using tcu::PixelBufferAccess; +using tcu::Texture2D; + +#define RESOLUTION_width 64 +#define RESOLUTION_height 64 +static const VkExtent3D RESOLUTION = { RESOLUTION_width, RESOLUTION_height, 1 }; + +#define MAX_DESCRIPTORS 4200 +#define FUZZY_COMPARE DE_FALSE +#define CMP_THRESHOLD 0.02f + +#define BINDING_Undefined 0 +#define BINDING_UniformBuffer 1 +#define BINDING_StorageBuffer 2 +#define BINDING_UniformTexelBuffer 3 +#define BINDING_StorageTexelBuffer 4 +#define BINDING_Sampler 5 +#define BINDING_SampledImage 6 +#define BINDING_CombinedImageSampler 7 +#define BINDING_UniformBufferDynamic 8 +#define BINDING_StorageBufferDynamic 9 +#define BINDING_InputAttachment 10 +#define BINDING_StorageImage 11 +#define BINDING_DescriptorEnumerator 12 + +static const VkExtent3D smallImageExtent = { 4, 4, 1 }; +static const VkExtent3D bigImageExtent = { 32, 32, 1 }; +static const VkDescriptorType VK_DESCRIPTOR_TYPE_UNDEFINED = VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT; + +template +struct Binding +{ + static const deUint32 binding = BindingNumber; +}; + +struct BindingUniformBuffer : Binding +{ + typedef struct + { + tcu::Vec4 c; + } Data; +}; + +struct BindingStorageBuffer : Binding +{ + typedef struct + { + tcu::Vec4 cnew; + tcu::Vec4 cold; + } Data; +}; + +struct TestCaseParams +{ + VkDescriptorType descriptorType; // used only to distinguish test class instance + VkShaderStageFlags stageFlags; // used only to build a proper program + VkExtent3D frameResolution; // target frame buffer resolution + bool updateAfterBind; // whether a test will use update after bind feature + bool calculateInLoop; // perform calculation in a loop + bool usesMipMaps; // this makes a sense and affects in image test cases only + deBool fuzzyComparison; // if true then a test will use fuzzy comparison, otherwise float threshold + float thresholdValue; // a threshold that will be used for both, float and fuzzy comparisons +}; + +struct TestParams +{ + VkShaderStageFlags stageFlags; + VkDescriptorType descriptorType; + deUint32 descriptorBinding; + VkDescriptorType additionalDescriptorType; + deUint32 additionalDescriptorBinding; + bool copyBuffersToImages; + bool allowVertexStoring; + VkExtent3D frameResolution; + bool updateAfterBind; + bool calculateInLoop; + bool usesMipMaps; + deBool fuzzyComparison; + float thresholdValue; + + TestParams (VkShaderStageFlags stageFlags_, + VkDescriptorType descriptorType_, + deUint32 descriptorBinding_, + VkDescriptorType additionalDescriptorType_, + deUint32 additionalDescriptorBinding_, + bool copyBuffersToImages_, + bool allowVertexStoring_, + const TestCaseParams& caseParams) + : stageFlags (stageFlags_) + , descriptorType (descriptorType_) + , descriptorBinding (descriptorBinding_) + , additionalDescriptorType (additionalDescriptorType_) + , additionalDescriptorBinding (additionalDescriptorBinding_) + , copyBuffersToImages (copyBuffersToImages_) + , allowVertexStoring (allowVertexStoring_) + , frameResolution (caseParams.frameResolution) + , updateAfterBind (caseParams.updateAfterBind) + , calculateInLoop (caseParams.calculateInLoop) + , usesMipMaps (caseParams.usesMipMaps) + , fuzzyComparison (caseParams.fuzzyComparison ? true : false) + , thresholdValue (caseParams.thresholdValue) + { + } +}; + +struct DescriptorEnumerator +{ + ut::BufferHandleAllocSp buffer; + ut::BufferViewSp bufferView; + VkDeviceSize bufferSize; + + Move descriptorSetLayout; + Move descriptorPool; + Move descriptorSet; + + void init(const vkt::Context& context, deUint32 vertexCount, deUint32 availableDescriptorCount); + void update(const vkt::Context& context); +}; + +struct IterateCommonVariables +{ + // An amount of descriptors of a given type available on the platform + deUint32 availableDescriptorCount; + // An amount of valid descriptors that have connected a buffers to them + deUint32 validDescriptorCount; + // As the name suggests, sometimes it is used as invocationCount + deUint32 vertexCount; + VkRect2D renderArea; + VkDeviceSize dataAlignment; + deUint32 lowerBound; + deUint32 upperBound; + + DescriptorEnumerator descriptorEnumerator; + + ut::BufferHandleAllocSp vertexAttributesBuffer; + ut::BufferHandleAllocSp descriptorsBuffer; + std::vector descriptorsBufferInfos; + std::vector descriptorsBufferViews; + std::vector descriptorImageViews; + std::vector descriptorSamplers; + std::vector descriptorsImages; + ut::FrameBufferSp frameBuffer; + + Move descriptorSetLayout; + Move descriptorPool; + Move descriptorSet; + Move pipelineLayout; + Move renderPass; + Move pipeline; + Move commandBuffer; +}; + +class CommonDescriptorInstance : public TestInstance +{ +public: + CommonDescriptorInstance (Context& context, + const TestParams& testParams); + + void checkIndexingAvailable (const ut::DeviceProperties& devProps) const; + + deUint32 computeAvailableDescriptorCount (VkDescriptorType descriptorType) const; + + Move createDescriptorSetLayout (deUint32& descriptorCount) const; + + Move createDescriptorPool (deUint32 descriptorCount) const; + + Move createDescriptorSet (VkDescriptorPool dsPool, + VkDescriptorSetLayout dsLayout) const; + + struct attributes + { + typedef tcu::Vec4 vec4; + typedef tcu::Vec2 vec2; + typedef tcu::IVec4 ivec4; + vec4 position; + vec2 normalpos; + ivec4 index; + attributes& operator()(const vec4& pos) + { + position = pos; + + normalpos.x() = (pos.x() + 1.0f) / 2.0f; + normalpos.y() = (pos.y() + 1.0f) / 2.0f; + + return *this; + } + }; + void createVertexAttributeBuffer (ut::BufferHandleAllocSp& buffer, + deUint32 availableDescriptorCount) const; + + static std::string substBinding (deUint32 binding, + const char* str, + deUint32 count = 0, + const char* name = DE_NULL); + + static const char* getVertexShaderProlog (void); + + static const char* getFragmentShaderProlog (void); + + static const char* getShaderEpilog (void); + + static bool performWritesInVertex (VkDescriptorType descriptorType); + + static std::string getShaderSource (VkShaderStageFlagBits shaderType, + const TestCaseParams& testCaseParams, + bool allowVertexStoring); + + static std::string getColorAccess (VkDescriptorType descriptorType, + const char* indexVariableName, + bool usesMipMaps); + + static std::string getFragmentReturnSource (const std::string& colorAccess); + + static std::string getFragmentLoopSource (const std::string& colorAccess1, + const std::string& colorAccess2); + + virtual Move createRenderPass (const IterateCommonVariables& variables); + + struct push_constant + { + deInt32 lowerBound; + deInt32 upperBound; + }; + VkPushConstantRange makePushConstantRange (void) const; + + Move createPipelineLayout (const std::vector& descriptorSetLayouts) const; + + // Creates graphics or compute pipeline and appropriate shaders' modules according the testCaseParams.stageFlags + // In the case of compute pipeline renderPass parameter is ignored. + // Viewport will be created with a width and a height taken from testCaseParam.fragResolution. + Move createPipeline (VkPipelineLayout pipelineLayout, + VkRenderPass renderPass); + + virtual void createFramebuffer (ut::FrameBufferSp& frameBuffer, + VkRenderPass renderPass, + const IterateCommonVariables& variables); + + // Creates one big stagging buffer cutted out on chunks that can accomodate an element of elementSize size + VkDeviceSize createBuffers (std::vector& bufferInfos, + ut::BufferHandleAllocSp& buffer, + deUint32 elementCount, + deUint32 elementSize, + VkDeviceSize alignment, + VkBufferUsageFlags bufferUsage); + + // Creates and binds an imagesCount of images with given parameters. + // Additionally creates stagging buffer for their data and PixelBufferAccess for particular images. + VkDeviceSize createImages (std::vector& images, + std::vector& bufferInfos, + ut::BufferHandleAllocSp& buffer, + VkBufferUsageFlags bufferUsage, + const VkExtent3D& imageExtent, + VkFormat imageFormat, + VkImageLayout imageLayout, + deUint32 imageCount, + bool withMipMaps = false); + + void createBuffersViews (std::vector& views, + const std::vector& bufferInfos, + VkFormat format); + + void createImagesViews (std::vector& views, + const std::vector& images, + VkFormat format); + + virtual void copyBuffersToImages (IterateCommonVariables& variables); + + virtual void copyImagesToBuffers (IterateCommonVariables& variables); + + PixelBufferAccess getPixelAccess (deUint32 imageIndex, + const VkExtent3D& imageExtent, + VkFormat imageFormat, + const std::vector& bufferInfos, + const ut::BufferHandleAllocSp& buffer, + deUint32 mipLevel = 0u) const; + + virtual void createAndPopulateDescriptors (IterateCommonVariables& variables) = 0; + + virtual void updateDescriptors (IterateCommonVariables& variables); + + virtual void iterateCollectResults (ut::UpdatablePixelBufferAccessPtr& result, + const IterateCommonVariables& variables, + bool fromTest); + + + void iterateCommandBegin (IterateCommonVariables& variables); + + bool iterateCommandEnd (IterateCommonVariables& variables, + bool collectBeforeSubmit = true); + + Move createCmdBuffer (void); + + void commandBindPipeline (VkCommandBuffer commandBuffer, + VkPipeline pipeline); + + void commandBindVertexAttributes (VkCommandBuffer commandBuffer, + const ut::BufferHandleAllocSp& vertexAttributesBuffer); + + void commandBindDescriptorSets (VkCommandBuffer commandBuffer, + VkPipelineLayout pipelineLayout, + VkDescriptorSet descriptorSet, + deUint32 descriptorSetIndex); + + void commandReadFrameBuffer (ut::BufferHandleAllocSp& content, + VkCommandBuffer commandBuffer, + const ut::FrameBufferSp& frameBuffer); + ut::UpdatablePixelBufferAccessPtr + commandReadFrameBuffer (VkCommandBuffer commandBuffer, + const ut::FrameBufferSp& frameBuffer); + + Move commandSubmit (VkCommandBuffer commandBuffer); + + virtual bool verifyVertexWriteResults (IterateCommonVariables& variables); + +protected: + virtual tcu::TestStatus iterate (void); + +protected: + const VkDevice m_vkd; + const DeviceInterface& m_vki; + Allocator& m_allocator; + const VkQueue m_queue; + const deUint32 m_queueFamilyIndex; + const Move m_commandPool; + const VkFormat m_colorFormat; + const TestParams m_testParams; + static const tcu::Vec4 m_clearColor; + const std::vector m_colorScheme; + const deUint32 m_schemeSize; + +private: + + Move createGraphicsPipeline (VkPipelineLayout pipelineLayout, + VkRenderPass renderPass); + + Move createComputePipeline (VkPipelineLayout pipelineLayout); + + int constructShaderModules (void); + + static std::vector createColorScheme(); + + Move m_vertexModule; + Move m_fragmentModule; + Move m_computeModule; +}; +const tcu::Vec4 CommonDescriptorInstance::m_clearColor = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f); + +void DescriptorEnumerator::init (const vkt::Context& context, deUint32 vertexCount, deUint32 availableDescriptorCount) +{ + const VkDevice device = context.getDevice(); + const DeviceInterface& deviceInterface = context.getDeviceInterface(); + + const VkFormat imageFormat = VK_FORMAT_R32G32B32A32_SINT; + typedef ut::mapVkFormat2Type::type pixelType; + const VkDeviceSize dataSize = vertexCount * sizeof(pixelType); + const std::vector primes = ut::generatePrimes(availableDescriptorCount); + const deUint32 primeCount = static_cast(primes.size()); + + std::vector data(vertexCount); + // e.g. 2,3,5,7,11,13,2,3,5,7,... + for (deUint32 idx = 0; idx < vertexCount; ++idx) + { + data[idx].x() = static_cast(primes[idx % primeCount]); + data[idx].y() = static_cast(idx); + } + + bufferSize = ut::createBufferAndBind(buffer, context, VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, dataSize); + deMemcpy(buffer->alloc->getHostPtr(), data.data(), static_cast(dataSize)); + + const VkBufferViewCreateInfo bufferViewCreateInfo = + { + VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO, // sType + DE_NULL, // pNext + 0u, // flags + *(buffer.get()->buffer), // buffer + imageFormat, // format + 0u, // offset + bufferSize, // range + }; + + bufferView = ut::BufferViewSp(new Move(vk::createBufferView(deviceInterface, device, &bufferViewCreateInfo))); + + const VkDescriptorSetLayoutBinding binding = + { + BINDING_DescriptorEnumerator, // binding + VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, // descriptorType + 1u, // descriptorCount + VK_SHADER_STAGE_ALL, // stageFlags + DE_NULL, // pImmutableSamplers + }; + + const VkDescriptorSetLayoutCreateInfo layoutCreateInfo = + { + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, + DE_NULL, // pNext + 0u, // flags + 1u, // bindingCount + &binding, // pBindings + }; + + descriptorSetLayout = vk::createDescriptorSetLayout(deviceInterface, device, &layoutCreateInfo); + descriptorPool = DescriptorPoolBuilder().addType(binding.descriptorType) + .build(deviceInterface, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u); + + const VkDescriptorSetAllocateInfo dsAllocInfo = + { + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // sType + DE_NULL, // pNext + *descriptorPool, // descriptorPool + 1u, // descriptorSetCount + &(*descriptorSetLayout) // pSetLayouts + }; + + descriptorSet = vk::allocateDescriptorSet(deviceInterface, device, &dsAllocInfo); +} + +void DescriptorEnumerator::update (const vkt::Context& context) +{ + const VkDescriptorBufferInfo bufferInfo = + { + *(buffer.get()->buffer), // buffer + 0u, // offset + bufferSize, // range + }; + + const VkWriteDescriptorSet writeInfo = + { + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + DE_NULL, // pNext + *descriptorSet, // dstSet + BINDING_DescriptorEnumerator, // dstBinding + 0u, // dstArrayElement + 1u, // descriptorCount + VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, // descriptorType + DE_NULL, // pImageInfo + &bufferInfo, // pBufferInfo + &(**bufferView), // pTexelBufferView + }; + + context.getDeviceInterface().updateDescriptorSets(context.getDevice(), 1u, &writeInfo, 0u, DE_NULL); +} + +CommonDescriptorInstance::CommonDescriptorInstance (Context& context, + const TestParams& testParams) + : TestInstance (context) + , m_vkd (context.getDevice()) + , m_vki (context.getDeviceInterface()) + , m_allocator (context.getDefaultAllocator()) + , m_queue (context.getUniversalQueue()) + , m_queueFamilyIndex(context.getUniversalQueueFamilyIndex()) + , m_commandPool (vk::createCommandPool(m_vki, m_vkd, (VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT), m_queueFamilyIndex)) + , m_colorFormat (VK_FORMAT_R32G32B32A32_SFLOAT) + , m_testParams (testParams) + , m_colorScheme (createColorScheme()) + , m_schemeSize (static_cast(m_colorScheme.size())) +{ +} + +void CommonDescriptorInstance::checkIndexingAvailable (const ut::DeviceProperties& devProps) const +{ + DE_UNREF(devProps); + m_context.requireDeviceExtension("VK_EXT_descriptor_indexing"); +} + +deUint32 CommonDescriptorInstance::computeAvailableDescriptorCount (VkDescriptorType descriptorType) const +{ + DE_UNREF(descriptorType); + const deUint32 vertexCount = m_testParams.frameResolution.width * m_testParams.frameResolution.height; + const deUint32 availableDescriptorsOnDevice = ut::DeviceProperties(m_context).computeMaxPerStageDescriptorCount(m_testParams.descriptorType, m_testParams.updateAfterBind); + return deMinu32(deMinu32(vertexCount, availableDescriptorsOnDevice), MAX_DESCRIPTORS); +} + +Move CommonDescriptorInstance::createDescriptorSetLayout (deUint32& descriptorCount) const +{ + descriptorCount = computeAvailableDescriptorCount(m_testParams.descriptorType); + + bool optional = (m_testParams.additionalDescriptorBinding != BINDING_Undefined) && (m_testParams.additionalDescriptorType != VK_DESCRIPTOR_TYPE_UNDEFINED); + + const VkDescriptorSetLayoutBinding bindings[] = + { + { + m_testParams.descriptorBinding, // binding + m_testParams.descriptorType, // descriptorType + descriptorCount, // descriptorCount + m_testParams.stageFlags, // stageFlags + DE_NULL, // pImmutableSamplers + }, + { + m_testParams.additionalDescriptorBinding, // binding + m_testParams.additionalDescriptorType, // descriptorType + 1, // descriptorCount + m_testParams.stageFlags, // stageFlags + DE_NULL, // pImmutableSamplers + } + }; + + const VkDescriptorBindingFlagsEXT bindingFlagUpdateAfterBind = + m_testParams.updateAfterBind ? VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT : 0; + + const VkDescriptorBindingFlagsEXT bindingFlagsExt[] = + { + VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT | bindingFlagUpdateAfterBind, + VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT | bindingFlagUpdateAfterBind + }; + + const VkDescriptorSetLayoutBindingFlagsCreateInfoEXT bindingCreateInfoExt = + { + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO_EXT, + DE_NULL, + optional ? 2u : 1u, // bindingCount + bindingFlagsExt, // pBindingFlags + }; + + const VkDescriptorSetLayoutCreateFlags layoutCreateFlags = + m_testParams.updateAfterBind ? VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT : 0; + + const VkDescriptorSetLayoutCreateInfo layoutCreateInfo = + { + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, + &bindingCreateInfoExt, // pNext + layoutCreateFlags, // flags + optional ? 2u : 1u, // bindingCount + bindings, // pBindings + }; + + return vk::createDescriptorSetLayout(m_vki, m_vkd, &layoutCreateInfo); +} + +Move CommonDescriptorInstance::createDescriptorPool (deUint32 descriptorCount) const +{ + const VkDescriptorPoolCreateFlags pcf = m_testParams.updateAfterBind ? VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT : 0; + + DescriptorPoolBuilder builder; + + builder.addType(m_testParams.descriptorType, descriptorCount); + + if (m_testParams.additionalDescriptorType != VK_DESCRIPTOR_TYPE_UNDEFINED && m_testParams.additionalDescriptorBinding != BINDING_Undefined) + { + builder.addType(m_testParams.additionalDescriptorType, 1); + } + + return builder.build(m_vki, m_vkd, (VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT | pcf), 1u); +} + +Move CommonDescriptorInstance::createDescriptorSet (VkDescriptorPool dsPool, + VkDescriptorSetLayout dsLayout) const +{ + const VkDescriptorSetAllocateInfo dsAllocInfo = + { + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // sType; + DE_NULL, // pNext; + dsPool, // descriptorPool; + 1u, // descriptorSetCount + &dsLayout // pSetLayouts + }; + + return vk::allocateDescriptorSet(m_vki, m_vkd, &dsAllocInfo); +} + +void CommonDescriptorInstance::createVertexAttributeBuffer (ut::BufferHandleAllocSp& buffer, + deUint32 availableDescriptorCount) const +{ + float xSize = 0.0f; + float ySize = 0.0f; + + const deUint32 invocationCount = m_testParams.frameResolution.width * m_testParams.frameResolution.height; + const std::vector vertices = ut::createVertices(m_testParams.frameResolution.width, m_testParams.frameResolution.height, xSize, ySize); + const std::vector primes = ut::generatePrimes(availableDescriptorCount); + const deUint32 primeCount = static_cast(primes.size()); + + std::vector data(vertices.size()); + std::transform(vertices.begin(), vertices.end(), data.begin(), attributes()); + + for (deUint32 invIdx = 0; invIdx < invocationCount; ++invIdx) + { + // r: 2,3,5,7,11,13,2,3,5,7,... + data[invIdx].index.x() = primes[invIdx % primeCount]; + + // b: x index in texel coordinate + data[invIdx].index.z() = invIdx % m_testParams.frameResolution.width; + + //a: y index in texel coordinate + data[invIdx].index.w() = invIdx / m_testParams.frameResolution.width; + } + + // g: 0,0,2,3,0,5,0,7,0,0,0,11,0,13,... + for (deUint32 primeIdx = 0; primeIdx < primeCount; ++primeIdx) + { + const deUint32 prime = primes[primeIdx]; + DE_ASSERT(prime < invocationCount); + data[prime].index.y() = prime; + } + + const VkDeviceSize dataSize = data.size() * sizeof(attributes); + + VkDeviceSize deviceSize = ut::createBufferAndBind(buffer, m_context, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, dataSize); + + deMemcpy(buffer->alloc->getHostPtr(), data.data(), static_cast(deviceSize)); + + vk::flushAlloc(m_vki, m_vkd, *buffer->alloc); +} + +std::string CommonDescriptorInstance::substBinding (deUint32 binding, + const char* str, + deUint32 count, + const char* name) +{ + std::map vars; + vars["?"] = de::toString(binding); + vars["*"] = (0 == count) ? "" : de::toString(count); + vars["VAR"] = (DE_NULL == name) ? "data" : name; + return tcu::StringTemplate(str).specialize(vars); +} + +const char* CommonDescriptorInstance::getVertexShaderProlog (void) +{ + return + "layout(location = 0) in vec4 in_position; \n" + "layout(location = 1) in vec2 in_normalpos; \n" + "layout(location = 2) in ivec4 index; \n" + "layout(location = 0) out vec4 position; \n" + "layout(location = 1) out vec2 normalpos; \n" + "layout(location = 2) out int vIndex; \n" + "layout(location = 3) out int rIndex; \n" + "layout(location = 4) out int gIndex; \n" + "layout(location = 5) out int bIndex; \n" + "layout(location = 6) out int aIndex; \n" + "void main() \n" + "{ \n" + " gl_PointSize = 0.2f; \n" + " position = in_position; \n" + " normalpos = in_normalpos; \n" + " gl_Position = position; \n" + " vIndex = gl_VertexIndex; \n" + " rIndex = index.x; \n" + " gIndex = index.y; \n" + " bIndex = index.z; \n" + " aIndex = index.w; \n"; +} + +const char* CommonDescriptorInstance::getFragmentShaderProlog (void) +{ + return + "layout(location = 0) out vec4 FragColor; \n" + "layout(location = 0) in flat vec4 position; \n" + "layout(location = 1) in flat vec2 normalpos; \n" + "layout(location = 2) in flat int vIndex; \n" + "layout(location = 3) in flat int rIndex; \n" + "layout(location = 4) in flat int gIndex; \n" + "layout(location = 5) in flat int bIndex; \n" + "layout(location = 6) in flat int aIndex; \n" + "void main() \n" + "{ \n"; +} + +const char* CommonDescriptorInstance::getShaderEpilog (void) +{ + return "} \n"; +} + +int CommonDescriptorInstance::constructShaderModules (void) +{ + int result = 0; + ut::DeviceProperties dp (m_context); + const VkPhysicalDeviceFeatures& feats = dp.physicalDeviceFeatures(); + tcu::TestLog& log = m_context.getTestContext().getLog(); + + if (m_testParams.stageFlags & VK_SHADER_STAGE_COMPUTE_BIT) + { + ++result; + const std::string name = ut::buildShaderName(VK_SHADER_STAGE_COMPUTE_BIT, m_testParams.descriptorType, m_testParams.updateAfterBind, m_testParams.calculateInLoop, false); + m_computeModule = vk::createShaderModule(m_vki, m_vkd, m_context.getBinaryCollection().get(name), (VkShaderModuleCreateFlags)0); + } + if (m_testParams.stageFlags & VK_SHADER_STAGE_FRAGMENT_BIT) + { + ++result; + const std::string name = ut::buildShaderName(VK_SHADER_STAGE_FRAGMENT_BIT, m_testParams.descriptorType, m_testParams.updateAfterBind, m_testParams.calculateInLoop, (feats.vertexPipelineStoresAndAtomics != DE_FALSE && m_testParams.allowVertexStoring)); + m_fragmentModule = vk::createShaderModule(m_vki, m_vkd, m_context.getBinaryCollection().get(name), (VkShaderModuleCreateFlags)0); + log << tcu::TestLog::Message << "Finally used fragment shader: " << name << '\n' << tcu::TestLog::EndMessage; + } + if (m_testParams.stageFlags & VK_SHADER_STAGE_VERTEX_BIT) + { + ++result; + const std::string name = ut::buildShaderName(VK_SHADER_STAGE_VERTEX_BIT, m_testParams.descriptorType, m_testParams.updateAfterBind, m_testParams.calculateInLoop, (feats.vertexPipelineStoresAndAtomics != DE_FALSE && m_testParams.allowVertexStoring)); + m_vertexModule = vk::createShaderModule(m_vki, m_vkd, m_context.getBinaryCollection().get(name), (VkShaderModuleCreateFlags)0); + log << tcu::TestLog::Message << "Finally used vertex shader: " << name << '\n' << tcu::TestLog::EndMessage; + } + + DE_ASSERT(result > 0); + + return result; +} + +Move CommonDescriptorInstance::createRenderPass (const IterateCommonVariables& variables) +{ + DE_UNREF(variables); + if ((m_testParams.stageFlags & VK_SHADER_STAGE_VERTEX_BIT) || (m_testParams.stageFlags & VK_SHADER_STAGE_FRAGMENT_BIT)) + { + return vk::makeRenderPass(m_vki, m_vkd, m_colorFormat); + } + return Move(); +} + +VkPushConstantRange CommonDescriptorInstance::makePushConstantRange (void) const +{ + const VkPushConstantRange pcr = + { + m_testParams.stageFlags, // stageFlags + 0u, // offset + static_cast(sizeof(push_constant)) // size + }; + return pcr; +} + +Move CommonDescriptorInstance::createPipelineLayout (const std::vector& descriptorSetLayouts) const +{ + const VkPushConstantRange pcr = makePushConstantRange(); + + const VkPipelineLayoutCreateInfo createInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // sType + DE_NULL, // pNext + (VkPipelineLayoutCreateFlags)0, // flags + static_cast(descriptorSetLayouts.size()), // setLayoutCount + descriptorSetLayouts.data(), // pSetLayouts; + m_testParams.calculateInLoop ? 1u : 0u, // pushConstantRangeCount + m_testParams.calculateInLoop ? &pcr : DE_NULL, // pPushConstantRanges + }; + + return vk::createPipelineLayout(m_vki, m_vkd, &createInfo); +} + +void CommonDescriptorInstance::createFramebuffer (ut::FrameBufferSp& frameBuffer, + VkRenderPass renderPass, + const IterateCommonVariables& variables) +{ + DE_UNREF(variables); + ut::createFrameBuffer(frameBuffer, m_context, m_testParams.frameResolution, m_colorFormat, renderPass); +} + +Move CommonDescriptorInstance::createPipeline (VkPipelineLayout pipelineLayout, + VkRenderPass renderPass) +{ DE_ASSERT(VK_SHADER_STAGE_ALL != m_testParams.stageFlags); + + constructShaderModules(); + + return (m_testParams.stageFlags & VK_SHADER_STAGE_COMPUTE_BIT) + ? createComputePipeline(pipelineLayout) + : createGraphicsPipeline(pipelineLayout, renderPass); +} + +Move CommonDescriptorInstance::createComputePipeline (VkPipelineLayout pipelineLayout) +{ + const VkPipelineShaderStageCreateInfo shaderStaegCreateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + DE_NULL, // pNext + (VkPipelineShaderStageCreateFlags)0, // flags + VK_SHADER_STAGE_COMPUTE_BIT, // stage + *m_computeModule, // module + "main", // pName + (VkSpecializationInfo*)DE_NULL // pSpecializationInfo + }; + + const VkComputePipelineCreateInfo pipelineCreateInfo = + { + VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, + DE_NULL, // pNext + 0u, // flags + shaderStaegCreateInfo, // stage + pipelineLayout, // layout + (VkPipeline)0, // basePipelineHandle + 0u, // basePipelineIndex + }; + return vk::createComputePipeline(m_vki, m_vkd, (VkPipelineCache)0u, &pipelineCreateInfo); +} + +Move CommonDescriptorInstance::createGraphicsPipeline (VkPipelineLayout pipelineLayout, + VkRenderPass renderPass) +{ + const VkVertexInputBindingDescription bindingDescriptions[] = + { + { + 0u, // binding + sizeof(attributes), // stride + VK_VERTEX_INPUT_RATE_VERTEX, // inputRate + }, + }; + + const VkVertexInputAttributeDescription attributeDescriptions[] = + { + { + 0u, // location + 0u, // binding + ut::mapType2vkFormat::value, // format + 0u // offset + }, // @in_position + { + 1u, // location + 0u, // binding + ut::mapType2vkFormat::value, // format + static_cast(sizeof(attributes::vec4)) // offset + }, // @normalpos + { + 2u, // location + 0u, // binding + ut::mapType2vkFormat::value, // format + static_cast(sizeof(attributes::vec2) + + sizeof(attributes::vec4)) // offset + }, // @index + }; + + const VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, + DE_NULL, + (VkPipelineVertexInputStateCreateFlags)0, // flags + DE_LENGTH_OF_ARRAY(bindingDescriptions), // vertexBindingDescriptionCount + bindingDescriptions, // pVertexBindingDescriptions + DE_LENGTH_OF_ARRAY(attributeDescriptions), // vertexAttributeDescriptionCount + attributeDescriptions // pVertexAttributeDescriptions + }; + + const std::vector viewports (1, makeViewport(m_testParams.frameResolution.width, m_testParams.frameResolution.height)); + const std::vector scissors (1, makeRect2D(m_testParams.frameResolution.width, m_testParams.frameResolution.height)); + + DE_ASSERT(m_vertexModule && m_fragmentModule); + + return vk::makeGraphicsPipeline( + m_vki, // vk + m_vkd, // device + pipelineLayout, // pipelineLayout + *m_vertexModule, // vertexShaderModule + DE_NULL, // tessellationControlModule + DE_NULL, // tessellationEvalModule + DE_NULL, // geometryShaderModule + *m_fragmentModule, // fragmentShaderModule + renderPass, // renderPass + viewports, // viewports + scissors, // scissors + VK_PRIMITIVE_TOPOLOGY_POINT_LIST, // topology + 0U, // subpass + 0U, // patchControlPoints + &vertexInputStateCreateInfo); // vertexInputStateCreateInfo +} + +VkDeviceSize CommonDescriptorInstance::createBuffers (std::vector& bufferInfos, + ut::BufferHandleAllocSp& buffer, + deUint32 elementCount, + deUint32 elementSize, + VkDeviceSize alignment, + VkBufferUsageFlags bufferUsage) +{ + const VkDeviceSize roundedSize = deAlign64(elementSize, alignment); + VkDeviceSize bufferSize = ut::createBufferAndBind(buffer, m_context, bufferUsage, (roundedSize * elementCount)); + + for (deUint32 elementIdx = 0; elementIdx < elementCount; ++elementIdx) + { + const VkDescriptorBufferInfo bufferInfo = + { + *buffer.get()->buffer, //buffer; + elementIdx * roundedSize, //offset; + elementSize, // range; + + }; + bufferInfos.push_back(bufferInfo); + } + + return bufferSize; +} + +VkDeviceSize CommonDescriptorInstance::createImages (std::vector& images, + std::vector& bufferInfos, + ut::BufferHandleAllocSp& buffer, + VkBufferUsageFlags bufferUsage, + const VkExtent3D& imageExtent, + VkFormat imageFormat, + VkImageLayout imageLayout, + deUint32 imageCount, + bool withMipMaps) + +{ + const deUint32 imageSize = ut::computeImageSize(imageExtent, imageFormat, withMipMaps); + + const VkDeviceSize bufferSize = createBuffers(bufferInfos, buffer, imageCount, imageSize, sizeof(tcu::Vec4), bufferUsage); + + for (deUint32 imageIdx = 0; imageIdx < imageCount; ++imageIdx) + { + ut::ImageHandleAllocSp image; + ut::createImageAndBind(image, m_context, imageFormat, imageExtent, imageLayout, withMipMaps); + images.push_back(image); + } + + return bufferSize; +} + +void CommonDescriptorInstance::createBuffersViews (std::vector& views, + const std::vector& bufferInfos, + VkFormat format) +{ + const deUint32 infoCount = static_cast(bufferInfos.size()); + for (deUint32 infoIdx = 0; infoIdx < infoCount; ++infoIdx) + { + const VkDescriptorBufferInfo& bufferInfo = bufferInfos[infoIdx]; + const VkBufferViewCreateInfo bufferViewInfo = + { + VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO, // sType + DE_NULL, // pNext + (VkBufferViewCreateFlags)0, // flags + bufferInfo.buffer, // buffer + format, // format + bufferInfo.offset, // offset + bufferInfo.range // range; + }; + views.push_back(ut::BufferViewSp(new Move(vk::createBufferView(m_vki, m_vkd, &bufferViewInfo)))); + } +} + +void CommonDescriptorInstance::createImagesViews (std::vector& views, + const std::vector& images, + VkFormat format) +{ + const deUint32 imageCount = static_cast(images.size()); + for (deUint32 imageIdx = 0; imageIdx < imageCount; ++imageIdx) + { + const VkImageViewCreateInfo createInfo = + { + VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // sType + DE_NULL, // pNext + (VkImageViewCreateFlags)0, // flags + *images[imageIdx]->image, // image + VK_IMAGE_VIEW_TYPE_2D, // viewType + format, // format + vk::makeComponentMappingRGBA(), // components + { + VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask + (deUint32)0, // baseMipLevel + images[imageIdx]->levels, // mipLevels + (deUint32)0, // baseArrayLayer + (deUint32)1u, // arraySize + }, + }; + views.push_back(ut::ImageViewSp(new Move(vk::createImageView(m_vki, m_vkd, &createInfo)))); + } +} + +void CommonDescriptorInstance::copyBuffersToImages (IterateCommonVariables& variables) +{ + const deUint32 infoCount = static_cast(variables.descriptorsBufferInfos.size()); + DE_ASSERT(variables.descriptorsImages.size() == infoCount); + const VkPipelineStageFlagBits dstStageMask = (m_testParams.stageFlags & VK_SHADER_STAGE_COMPUTE_BIT) + ? VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT + : VK_PIPELINE_STAGE_VERTEX_INPUT_BIT; + for (deUint32 infoIdx = 0; infoIdx < infoCount; ++infoIdx) + { + ut::recordCopyBufferToImage( + *variables.commandBuffer, // commandBuffer + m_vki, // interface + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, // srcStageMask + dstStageMask, // dstStageMask + variables.descriptorsBufferInfos[infoIdx], // bufferInfo + *(variables.descriptorsImages[infoIdx]->image), // image + variables.descriptorsImages[infoIdx]->extent, // imageExtent + variables.descriptorsImages[infoIdx]->format, // imageFormat + variables.descriptorsImages[infoIdx]->layout, // oldImageLayout + VK_IMAGE_LAYOUT_GENERAL, // newImageLayout + variables.descriptorsImages[infoIdx]->levels); // mipLevelCount + + variables.descriptorsImages[infoIdx]->layout = VK_IMAGE_LAYOUT_GENERAL; + } +} + +void CommonDescriptorInstance::copyImagesToBuffers (IterateCommonVariables& variables) +{ + const deUint32 infoCount = static_cast(variables.descriptorsBufferInfos.size()); + DE_ASSERT(variables.descriptorsImages.size() == infoCount); + const VkPipelineStageFlagBits srcStageMask = (m_testParams.stageFlags & VK_SHADER_STAGE_COMPUTE_BIT) + ? VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT + : VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + + for (deUint32 infoIdx = 0; infoIdx < infoCount; ++infoIdx) + { + ut::recordCopyImageToBuffer( + *variables.commandBuffer, // commandBuffer + m_vki, // interface + srcStageMask, // srcStageMask + VK_PIPELINE_STAGE_HOST_BIT, // dstStageMask + *(variables.descriptorsImages[infoIdx]->image), // image + variables.descriptorsImages[infoIdx]->extent, // imageExtent + variables.descriptorsImages[infoIdx]->format, // imageFormat + variables.descriptorsImages[infoIdx]->layout, // oldImageLayout + VK_IMAGE_LAYOUT_GENERAL, // newImageLayout + variables.descriptorsBufferInfos[infoIdx]); // bufferInfo + } +} + +PixelBufferAccess CommonDescriptorInstance::getPixelAccess (deUint32 imageIndex, + const VkExtent3D& imageExtent, + VkFormat imageFormat, + const std::vector& bufferInfos, + const ut::BufferHandleAllocSp& buffer, + deUint32 mipLevel) const +{ + DE_ASSERT(bufferInfos[imageIndex].buffer == *buffer.get()->buffer); + DE_ASSERT(ut::computeImageSize(imageExtent, imageFormat, true, (mipLevel ? ut::maxDeUint32 : 0)) <= bufferInfos[imageIndex].range); + DE_ASSERT(imageExtent.width >> mipLevel); + DE_ASSERT(imageExtent.height >> mipLevel); + + deUint32 mipOffset = 0; + + for (deUint32 level = 0; mipLevel && level < mipLevel; ++level) + { + mipOffset += ut::computeImageSize(imageExtent, imageFormat, true, level); + } + + unsigned char* hostPtr = static_cast(buffer->alloc->getHostPtr()); + unsigned char* data = hostPtr + bufferInfos[imageIndex].offset + mipOffset; + return tcu::PixelBufferAccess(vk::mapVkFormat(imageFormat), (imageExtent.width >> mipLevel), (imageExtent.height >> mipLevel), imageExtent.depth, data); +} + + +void CommonDescriptorInstance::updateDescriptors (IterateCommonVariables& variables) +{ + const std::vector primes = ut::generatePrimes(variables.availableDescriptorCount); + const deUint32 primeCount = static_cast(primes.size()); + + for (deUint32 primeIdx = 0; primeIdx < primeCount; ++primeIdx) + { + const VkDescriptorBufferInfo* pBufferInfo = DE_NULL; + const VkDescriptorImageInfo* pImageInfo = DE_NULL; + const VkBufferView* pTexelBufferView = DE_NULL; + + + VkDescriptorImageInfo imageInfo = + { + static_cast(0), + static_cast(0), + VK_IMAGE_LAYOUT_GENERAL + }; + + switch (m_testParams.descriptorType) + { + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: + case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: + case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: + { + pBufferInfo = &variables.descriptorsBufferInfos[primeIdx]; + switch (m_testParams.descriptorType) + { + case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: + case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: + pTexelBufferView = &(**variables.descriptorsBufferViews[primeIdx]); + break; + default: + break; + } + } + break; + + case VK_DESCRIPTOR_TYPE_SAMPLER: + imageInfo.sampler = **variables.descriptorSamplers[primeIdx]; + pImageInfo = &imageInfo; + break; + + case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: + case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: + case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: + imageInfo.imageView = **variables.descriptorImageViews[primeIdx]; + pImageInfo = &imageInfo; + break; + + default: break; + } + + const VkWriteDescriptorSet writeInfo = + { + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // sType + DE_NULL, // pNext + *variables.descriptorSet, // descriptorSet + m_testParams.descriptorBinding, // descriptorBinding; + primes[primeIdx], // elementIndex + 1u, // descriptorCount + m_testParams.descriptorType, // descriptorType + pImageInfo, // pImageInfo + pBufferInfo, // pBufferInfo + pTexelBufferView // pTexelBufferView + }; + + m_vki.updateDescriptorSets(m_vkd, 1u, &writeInfo, 0u, DE_NULL); + } +} + +void CommonDescriptorInstance::iterateCommandBegin (IterateCommonVariables& variables) +{ + variables.dataAlignment = 0; + + variables.renderArea.offset.x = 0; + variables.renderArea.offset.y = 0; + variables.renderArea.extent.width = m_testParams.frameResolution.width; + variables.renderArea.extent.height = m_testParams.frameResolution.height; + + variables.vertexCount = m_testParams.frameResolution.width * m_testParams.frameResolution.height; + + variables.lowerBound = 0; + variables.upperBound = variables.vertexCount; + + variables.descriptorSetLayout = createDescriptorSetLayout(variables.availableDescriptorCount); + variables.validDescriptorCount = ut::computePrimeCount(variables.availableDescriptorCount); + variables.descriptorPool = createDescriptorPool(variables.availableDescriptorCount); + variables.descriptorSet = createDescriptorSet(*variables.descriptorPool, *variables.descriptorSetLayout); + + std::vector descriptorSetLayouts; + descriptorSetLayouts.push_back(*variables.descriptorSetLayout); + if (m_testParams.calculateInLoop) + { + variables.descriptorEnumerator.init(m_context, variables.vertexCount, variables.availableDescriptorCount); + descriptorSetLayouts.push_back(*variables.descriptorEnumerator.descriptorSetLayout); + } + + variables.pipelineLayout = createPipelineLayout(descriptorSetLayouts); + + createAndPopulateDescriptors (variables); + + variables.renderPass = createRenderPass(variables); + variables.pipeline = createPipeline(*variables.pipelineLayout, *variables.renderPass); + + variables.commandBuffer = createCmdBuffer(); + + if ((m_testParams.stageFlags & VK_SHADER_STAGE_VERTEX_BIT) || (m_testParams.stageFlags & VK_SHADER_STAGE_FRAGMENT_BIT)) + { + createVertexAttributeBuffer (variables.vertexAttributesBuffer, variables.availableDescriptorCount); + createFramebuffer (variables.frameBuffer, *variables.renderPass, variables); + } + + if (m_testParams.calculateInLoop) + { + variables.descriptorEnumerator.update(m_context); + } + + if (!m_testParams.updateAfterBind) + { + updateDescriptors (variables); + } + + vk::beginCommandBuffer (m_vki, *variables.commandBuffer); + + if (m_testParams.calculateInLoop) + { + deRandom rnd; + deRandom_init(&rnd, static_cast(m_testParams.descriptorType)); + const deUint32 quarter = variables.vertexCount / 4; + + variables.lowerBound = deRandom_getUint32(&rnd) % quarter; + variables.upperBound = (deRandom_getUint32(&rnd) % quarter) + (3 * quarter); + + const push_constant pc = + { + static_cast(variables.lowerBound), + static_cast(variables.upperBound) + }; + + m_vki.cmdPushConstants(*variables.commandBuffer, *variables.pipelineLayout, m_testParams.stageFlags, 0u, static_cast(sizeof(pc)), &pc); + } + + if ((m_testParams.stageFlags & VK_SHADER_STAGE_VERTEX_BIT) || (m_testParams.stageFlags & VK_SHADER_STAGE_FRAGMENT_BIT)) + { + commandBindVertexAttributes (*variables.commandBuffer, variables.vertexAttributesBuffer); + } + + if (m_testParams.calculateInLoop) + { + commandBindDescriptorSets(*variables.commandBuffer, *variables.pipelineLayout, *variables.descriptorEnumerator.descriptorSet, 1); + } + + if (!ut::isDynamicDescriptor(m_testParams.descriptorType)) + { + commandBindDescriptorSets (*variables.commandBuffer, *variables.pipelineLayout, *variables.descriptorSet, 0); + } + + commandBindPipeline (*variables.commandBuffer, *variables.pipeline); +} + +tcu::TestStatus CommonDescriptorInstance::iterate (void) +{ + IterateCommonVariables v; + iterateCommandBegin (v); + + if (true == m_testParams.copyBuffersToImages) + { + copyBuffersToImages (v); + } + + if (true == m_testParams.updateAfterBind) + { + updateDescriptors (v); + } + + vk::beginRenderPass (m_vki, *v.commandBuffer, *v.renderPass, *v.frameBuffer->buffer, v.renderArea, m_clearColor); + m_vki.cmdDraw (*v.commandBuffer, v.vertexCount, 1u, 0u, 0u); + vk::endRenderPass (m_vki, *v.commandBuffer); + + return (iterateCommandEnd(v) ? tcu::TestStatus::pass : tcu::TestStatus::fail)(""); +} + +std::vector CommonDescriptorInstance::createColorScheme (void) +{ + std::vector cs; + int divider = 2; + for (int i = 0; i < 10; ++i) + { + cs.push_back(1.0f / float(divider)); + divider *= 2; + } + return cs; +} + +bool CommonDescriptorInstance::iterateCommandEnd (IterateCommonVariables& variables, + bool collectBeforeSubmit) +{ + ut::UpdatablePixelBufferAccessPtr programResult; + ut::UpdatablePixelBufferAccessPtr referenceResult; + + if (collectBeforeSubmit) + { + iterateCollectResults(programResult, variables, true); + iterateCollectResults(referenceResult, variables, false); + } + + VK_CHECK(m_vki.endCommandBuffer(*variables.commandBuffer)); + Move fence = commandSubmit(*variables.commandBuffer); + m_vki.waitForFences(m_vkd, 1, &(*fence), DE_TRUE, ~0ull); + + if (false == collectBeforeSubmit) + { + iterateCollectResults(programResult, variables, true); + iterateCollectResults(referenceResult, variables, false); + } + + bool result = false; + if (m_testParams.fuzzyComparison) + { + result = tcu::fuzzyCompare(m_context.getTestContext().getLog(), + "Fuzzy Compare", "Comparison result", *referenceResult.get(), *programResult.get(), 0.02f, tcu::COMPARE_LOG_EVERYTHING); + } + else + { + result = tcu::floatThresholdCompare(m_context.getTestContext().getLog(), + "Float Threshold Compare", "Comparison result", *referenceResult.get(), *programResult.get(), tcu::Vec4(0.02f, 0.02f, 0.02f, 0.02f), tcu::COMPARE_LOG_EVERYTHING); + } + + if (m_testParams.allowVertexStoring) + { + result = verifyVertexWriteResults(variables); + } + + return result; +} + +void CommonDescriptorInstance::iterateCollectResults (ut::UpdatablePixelBufferAccessPtr& result, + const IterateCommonVariables& variables, + bool fromTest) +{ + if (fromTest) + { + result = commandReadFrameBuffer(*variables.commandBuffer, variables.frameBuffer); + } + else + { + result = ut::UpdatablePixelBufferAccessPtr(new ut::PixelBufferAccessAllocation(vk::mapVkFormat(m_colorFormat), m_testParams.frameResolution)); + + for (deUint32 y = 0, pixelNum = 0; y < m_testParams.frameResolution.height; ++y) + { + for (deUint32 x = 0; x < m_testParams.frameResolution.width; ++x, ++pixelNum) + { + const float component = m_colorScheme[(pixelNum % variables.validDescriptorCount) % m_schemeSize]; + result->setPixel(tcu::Vec4(component, component, component, 1.0f), x, y); + } + } + } +} + +Move CommonDescriptorInstance::createCmdBuffer (void) +{ + return vk::allocateCommandBuffer(m_vki, m_vkd, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY); +} + +Move CommonDescriptorInstance::commandSubmit (VkCommandBuffer cmd) +{ + Move fence(vk::createFence(m_vki, m_vkd)); + + const VkSubmitInfo submitInfo = + { + VK_STRUCTURE_TYPE_SUBMIT_INFO, // sType + DE_NULL, // pNext + 0u, // waitSemaphoreCount + static_cast(DE_NULL), // pWaitSemaphores + static_cast(DE_NULL), // pWaitDstStageMask + 1u, // commandBufferCount + &cmd, // pCommandBuffers + 0u, // signalSemaphoreCount + static_cast(DE_NULL) // pSignalSemaphores + }; + + VK_CHECK(m_vki.queueSubmit(m_queue, 1u, &submitInfo, *fence)); + + return fence; +} + +bool CommonDescriptorInstance::verifyVertexWriteResults(IterateCommonVariables& variables) +{ + DE_UNREF(variables); + return true; +} + +void CommonDescriptorInstance::commandBindPipeline (VkCommandBuffer commandBuffer, + VkPipeline pipeline) +{ + const VkPipelineBindPoint pipelineBindingPoint = (m_testParams.stageFlags & VK_SHADER_STAGE_COMPUTE_BIT) ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS; + m_vki.cmdBindPipeline(commandBuffer, pipelineBindingPoint, pipeline); +} + +void CommonDescriptorInstance::commandBindVertexAttributes (VkCommandBuffer commandBuffer, + const ut::BufferHandleAllocSp& vertexAttributesBuffer) +{ + const VkDeviceSize offsets[] = { 0u }; + const VkBuffer buffers[] = { *vertexAttributesBuffer->buffer }; + m_vki.cmdBindVertexBuffers(commandBuffer, 0u, 1u, buffers, offsets); +} + +void CommonDescriptorInstance::commandBindDescriptorSets (VkCommandBuffer commandBuffer, + VkPipelineLayout pipelineLayout, + VkDescriptorSet descriptorSet, + deUint32 descriptorSetIndex) +{ + const VkPipelineBindPoint pipelineBindingPoint = (m_testParams.stageFlags & VK_SHADER_STAGE_COMPUTE_BIT) ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS; + m_vki.cmdBindDescriptorSets(commandBuffer, pipelineBindingPoint, pipelineLayout, descriptorSetIndex, 1u, &descriptorSet, 0u, static_cast(DE_NULL)); +} + +ut::UpdatablePixelBufferAccessPtr +CommonDescriptorInstance::commandReadFrameBuffer (VkCommandBuffer commandBuffer, + const ut::FrameBufferSp& frameBuffer) +{ + ut::BufferHandleAllocSp frameBufferContent; + commandReadFrameBuffer(frameBufferContent, commandBuffer, frameBuffer); + return ut::UpdatablePixelBufferAccessPtr(new ut::PixelBufferAccessBuffer( + m_vkd, m_vki, vk::mapVkFormat(m_colorFormat), m_testParams.frameResolution, + de::SharedPtr< Move >(new Move(frameBufferContent->buffer)), + de::SharedPtr< de::MovePtr >(new de::MovePtr(frameBufferContent->alloc)))); +} + +void CommonDescriptorInstance::commandReadFrameBuffer (ut::BufferHandleAllocSp& content, + VkCommandBuffer commandBuffer, + const ut::FrameBufferSp& frameBuffer) +{ + Move buffer; + de::MovePtr allocation; + + const VkDeviceSize bufferSize = ut::computeImageSize(frameBuffer->image); + + // create a buffer and an host allocation for it + { + const VkBufferCreateInfo bufferCreateInfo = + { + VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // sType + DE_NULL, // pNext + 0u, // flags + bufferSize, // size + VK_BUFFER_USAGE_TRANSFER_DST_BIT, // usage + VK_SHARING_MODE_EXCLUSIVE, // sharingMode + 1u, // queueFamilyIndexCoun + &m_queueFamilyIndex // pQueueFamilyIndices + }; + + buffer = vk::createBuffer(m_vki, m_vkd, &bufferCreateInfo); + const VkMemoryRequirements memRequirements(vk::getBufferMemoryRequirements(m_vki, m_vkd, *buffer)); + allocation = m_allocator.allocate(memRequirements, MemoryRequirement::HostVisible); + + VK_CHECK(m_vki.bindBufferMemory(m_vkd, *buffer, allocation->getMemory(), allocation->getOffset())); + } + + const VkImage& image = *frameBuffer->image->image; + + VkImageSubresourceRange subresourceRange = + { + VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask + 0u, // baseMipLevel + 1u, // levelCount + 0u, // baseArrayLayer + 1u, // layerCount + }; + + const VkImageMemoryBarrier imageBarrier = + { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType; + DE_NULL, // pNext; + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // srcAccessMask; + VK_ACCESS_TRANSFER_READ_BIT, // dstAccessMask; + VK_IMAGE_LAYOUT_UNDEFINED, // oldLayout + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // newLayout; + VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex; + VK_QUEUE_FAMILY_IGNORED, // dstQueueFamilyIndex; + image, // image; + subresourceRange, // subresourceRange; + }; + + const VkBufferImageCopy copyRegion = + { + 0u, // bufferOffset + frameBuffer->image->extent.width, // bufferRowLength + frameBuffer->image->extent.height, // bufferImageHeight + { // VkImageSubresourceLayers + VK_IMAGE_ASPECT_COLOR_BIT, // aspect + 0u, // mipLevel + 0u, // baseArrayLayer + 1u, // layerCount + }, + { 0, 0, 0 }, // imageOffset + frameBuffer->image->extent // imageExtent + }; + + const VkBufferMemoryBarrier bufferBarrier = + { + VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // sType; + DE_NULL, // pNext; + VK_ACCESS_TRANSFER_WRITE_BIT, // srcAccessMask; + VK_ACCESS_HOST_READ_BIT, // dstAccessMask; + VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex; + VK_QUEUE_FAMILY_IGNORED, // dstQueueFamilyIndex; + *buffer, // buffer; + 0u, // offset; + bufferSize // size; + }; + + m_vki.cmdPipelineBarrier(commandBuffer, // commandBuffer + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, // srcStageMask, dstStageMask + (VkDependencyFlags)0, // dependencyFlags + 0u, (const VkMemoryBarrier*)DE_NULL, // memoryBarrierCount, pMemoryBarriers + 0u, (const VkBufferMemoryBarrier*)DE_NULL, // bufferBarrierCount, pBufferBarriers + 1u, &imageBarrier); // imageBarrierCount, pImageBarriers + + m_vki.cmdCopyImageToBuffer(commandBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *buffer, 1u, ©Region); + + m_vki.cmdPipelineBarrier(commandBuffer, + VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, + (VkDependencyFlags)0, + 0, DE_NULL, + 1, &bufferBarrier, + 0u, DE_NULL); + + content = ut::BufferHandleAllocSp(new ut::BufferHandleAlloc(buffer, allocation)); +} + +std::string CommonDescriptorInstance::getColorAccess (VkDescriptorType descriptorType, + const char* indexVariableName, + bool usesMipMaps) +{ + std::string text; + std::map vars; + vars["INDEX"] = indexVariableName; + + switch (descriptorType) + { + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: + text = "data[nonuniformEXT(${INDEX})].c"; + break; + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: + text = "data[nonuniformEXT(${INDEX})].cold"; + break; + case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: + text = "subpassLoad(data[nonuniformEXT(${INDEX})]).rgba"; + break; + case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: + text = "texelFetch(data[nonuniformEXT(${INDEX})], 0)"; + break; + case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: + text = "imageLoad(data[nonuniformEXT(${INDEX})], 0)"; + break; + case VK_DESCRIPTOR_TYPE_SAMPLER: + text = usesMipMaps + ? "textureLod(sampler2D(tex[0], data[nonuniformEXT(${INDEX})]), normalpos, 1)" + : "texture( sampler2D(tex[0], data[nonuniformEXT(${INDEX})]), normalpos )"; + break; + case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: + text = usesMipMaps + ? "textureLod( sampler2D(data[nonuniformEXT(${INDEX})], samp[0]), vec2(0,0), textureQueryLevels(sampler2D(data[nonuniformEXT(${INDEX})], samp[0]))-1)" + : "texture( sampler2D(data[nonuniformEXT(${INDEX})], samp[0]), vec2(0,0) )"; + break; + case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: + text = usesMipMaps + ? "textureLod( data[nonuniformEXT(${INDEX})], uvec2(0,0), textureQueryLevels(data[nonuniformEXT(${INDEX})])-1)" + : "texture( data[nonuniformEXT(${INDEX})], uvec2(0,0) )"; + break; + default: + TCU_THROW(InternalError, "Not implemented descriptor type"); + } + + return tcu::StringTemplate(text).specialize(vars); +} + +std::string CommonDescriptorInstance::getFragmentReturnSource (const std::string& colorAccess) +{ + return " FragColor = " + colorAccess + ";\n"; +} + +std::string CommonDescriptorInstance::getFragmentLoopSource (const std::string& colorAccess1, + const std::string& colorAccess2) +{ + std::map < std::string, std::string > vars; + vars["COLOR_ACCESS_1"] = colorAccess1; + vars["COLOR_ACCESS_2"] = colorAccess2; + + const char* s = + " vec4 sumClr1 = vec4(0,0,0,0); \n" + " vec4 sumClr2 = vec4(0,0,0,0); \n" + " for (int i = pc.lowerBound; i < pc.upperBound; ++i) \n" + " {\n" + " int loopIdx = texelFetch(iter, i).x; \n" + " sumClr1 += ${COLOR_ACCESS_2} + ${COLOR_ACCESS_1}; \n" + " sumClr2 += ${COLOR_ACCESS_2}; \n" + " }\n" + " FragColor = vec4(((sumClr1 - sumClr2) / float(pc.upperBound - pc.lowerBound)).rgb, 1); \n"; + + return tcu::StringTemplate(s).specialize(vars); +} + +bool CommonDescriptorInstance::performWritesInVertex (VkDescriptorType descriptorType) +{ + bool result = false; + + switch (descriptorType) + { + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: + case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: + result = true; + break; + default: + result = false; + break; + } + + return result; +} + +std::string CommonDescriptorInstance::getShaderSource (VkShaderStageFlagBits shaderType, + const TestCaseParams& testCaseParams, + bool allowVertexStoring) +{ + std::stringstream s; + + s << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << '\n'; + s << "#extension GL_EXT_nonuniform_qualifier : require \n"; + + if (testCaseParams.calculateInLoop) + { + s << "layout(push_constant) uniform Block { int lowerBound, upperBound; } pc;\n"; + s << substBinding(BINDING_DescriptorEnumerator, + "layout(set=1,binding=${?}) uniform isamplerBuffer iter; \n"); + } + + switch (testCaseParams.descriptorType) + { + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: + s << substBinding(BINDING_StorageBuffer, + "layout(set=0,binding=${?}) buffer Data { vec4 cnew, cold; } data[]; \n"); + break; + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: + s << substBinding(BINDING_StorageBufferDynamic, + "layout(set=0,binding=${?}) buffer Data { vec4 cnew, cold; } data[]; \n"); + break; + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: + s << substBinding(BINDING_UniformBuffer, + "layout(set=0,binding=${?}) uniform Data { vec4 c; } data[]; \n"); + break; + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: + s << substBinding(BINDING_UniformBufferDynamic, + "layout(set=0,binding=${?}) uniform Data { vec4 c; } data[]; \n"); + break; + case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: + s << substBinding(BINDING_StorageTexelBuffer, + "layout(set=0,binding=${?},rgba32f) uniform imageBuffer data[];\n"); + break; + case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: + s << "#extension GL_EXT_texture_buffer : require \n"; + s << substBinding(BINDING_UniformTexelBuffer, + "layout(set=0,binding=${?}) uniform samplerBuffer data[];\n"); + break; + case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: + // Left for the consistent of code. + // Header is set one swicth below + break; + case VK_DESCRIPTOR_TYPE_SAMPLER: + s << "#extension GL_EXT_texture_buffer : require \n"; + s << substBinding(BINDING_SampledImage, + "layout(set=0,binding=${?}) uniform texture2D ${VAR}[${*}];\n", 1, "tex"); + s << substBinding(BINDING_Sampler, + "layout(set=0,binding=${?}) uniform sampler ${VAR}[${*}];\n"); + break; + case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: + s << "#extension GL_EXT_texture_buffer : require \n"; + s << substBinding(BINDING_Sampler, + "layout(set=0,binding=${?}) uniform sampler ${VAR}[${*}];\n", 1, "samp"); + s << substBinding(BINDING_SampledImage, + "layout(set=0,binding=${?}) uniform texture2D ${VAR}[${*}];\n"); + break; + case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: + s << "#extension GL_EXT_texture_buffer : require \n"; + s << substBinding(BINDING_CombinedImageSampler, + "layout(set=0,binding=${?}) uniform sampler2D data[];\n"); + break; + case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: + s << "layout(local_size_x=1,local_size_y=1,local_size_z=1) in; \n"; + s << substBinding(BINDING_StorageImage + 1, + "layout(r32ui,set=0,binding=${?}) uniform uimage2D idxs; \n"); + s << substBinding(BINDING_StorageImage, + "layout(r32ui,set=0,binding=${?}) uniform uimage2D data[]; \n"); + break; + default: + TCU_THROW(InternalError, "Not implemented descriptor type"); + } + + switch (shaderType) + { + case VK_SHADER_STAGE_VERTEX_BIT: s << getVertexShaderProlog(); break; + case VK_SHADER_STAGE_FRAGMENT_BIT: + { + if (testCaseParams.descriptorType == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT) + { + s << substBinding(BINDING_InputAttachment, + "layout(input_attachment_index=1,set=0,binding=${?}) uniform subpassInput data[]; \n"); + } + s << getFragmentShaderProlog(); + } + break; + case VK_SHADER_STAGE_COMPUTE_BIT: + break; + default: + TCU_THROW(InternalError, "Not implemented shader stage"); + } + + switch (shaderType) + { + case VK_SHADER_STAGE_VERTEX_BIT: + { + switch (testCaseParams.descriptorType) + { + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: + if (allowVertexStoring) + s << " if (gIndex != 0) data[nonuniformEXT(gIndex)].cnew = data[nonuniformEXT(rIndex)].cold; \n"; + break; + case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: + if (allowVertexStoring) + s << " if (gIndex != 0) imageStore(data[nonuniformEXT(gIndex)], 1, imageLoad(data[nonuniformEXT(rIndex)], 0)); \n"; + break; + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: + case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: + case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: + case VK_DESCRIPTOR_TYPE_SAMPLER: + case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: + case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: + break; + + default: + TCU_THROW(InternalError, "Not implemented descriptor type"); + } + } + break; + + case VK_SHADER_STAGE_FRAGMENT_BIT: + { + switch (testCaseParams.descriptorType) + { + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: + case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: + { + if (testCaseParams.calculateInLoop) + s << getFragmentLoopSource( + getColorAccess(testCaseParams.descriptorType, "rIndex", false), + getColorAccess(testCaseParams.descriptorType, "loopIdx", false)); + else + s << getFragmentReturnSource(getColorAccess(testCaseParams.descriptorType, "rIndex", false)); + } + break; + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: + case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: + case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: + case VK_DESCRIPTOR_TYPE_SAMPLER: + case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: + case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: + if (testCaseParams.calculateInLoop) + s << getFragmentLoopSource( + getColorAccess(testCaseParams.descriptorType, "rIndex", testCaseParams.usesMipMaps), + getColorAccess(testCaseParams.descriptorType, "loopIdx", testCaseParams.usesMipMaps)); + else + s << getFragmentReturnSource(getColorAccess(testCaseParams.descriptorType, "rIndex", testCaseParams.usesMipMaps)); + break; + default: TCU_THROW(InternalError, "Not implemented descriptor type"); + } + } + break; + + case VK_SHADER_STAGE_COMPUTE_BIT: // VK_DESCRIPTOR_TYPE_STORAGE_IMAGE + s << "void main(void)\n{\n"; + if (testCaseParams.calculateInLoop) + s << " for (int i = pc.lowerBound; i < pc.upperBound; ++i) \n" + " imageAtomicAdd(data[nonuniformEXT(texelFetch(iter, i).x)], ivec2(0, 0), 1); \n"; + else + s << " uvec4 c = imageLoad(idxs, ivec2(gl_WorkGroupID.x, gl_WorkGroupID.y)); \n" + " imageAtomicAdd( data[nonuniformEXT(c.r)], ivec2(0, 0), 1); \n"; + break; + + default: TCU_THROW(InternalError, "Not implemented shader stage"); + } + + s << getShaderEpilog(); + + return s.str(); +} + +class StorageBufferInstance : virtual public CommonDescriptorInstance +{ +public: + StorageBufferInstance (Context& context, + const TestCaseParams& testCaseParams); +protected: + virtual void createAndPopulateDescriptors (IterateCommonVariables& variables); + + virtual bool verifyVertexWriteResults (IterateCommonVariables& variables); +}; + +StorageBufferInstance::StorageBufferInstance (Context& context, + const TestCaseParams& testCaseParams) + : CommonDescriptorInstance(context, + TestParams(VK_SHADER_STAGE_ALL_GRAPHICS, + VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, + BINDING_StorageBuffer, + VK_DESCRIPTOR_TYPE_UNDEFINED, + BINDING_Undefined, + false, + performWritesInVertex(testCaseParams.descriptorType), + testCaseParams)) +{ + ut::DeviceProperties dp(context); + + checkIndexingAvailable(dp); + + const vk::VkPhysicalDeviceDescriptorIndexingFeaturesEXT& feats = dp.descriptorIndexingFeatures(); + + if (!(feats.shaderStorageBufferArrayNonUniformIndexing)) + TCU_THROW(NotSupportedError, "Non-uniform indexing over storage buffer descriptor arrays is not supported."); + + if (m_testParams.updateAfterBind) + { + if (!(feats.descriptorBindingStorageBufferUpdateAfterBind)) + TCU_THROW(NotSupportedError, "Update after bind for storage buffer descriptors is not supported."); + } +} + +void StorageBufferInstance::createAndPopulateDescriptors (IterateCommonVariables& variables) +{ + BindingStorageBuffer::Data data; + + bool vertexStores = false; + { + ut::DeviceProperties dp(m_context); + vertexStores = dp.physicalDeviceFeatures().vertexPipelineStoresAndAtomics != DE_FALSE; + } + const deUint32 alignment = static_cast(ut::DeviceProperties(m_context).physicalDeviceProperties().limits.minStorageBufferOffsetAlignment); + createBuffers(variables.descriptorsBufferInfos, variables.descriptorsBuffer, variables.validDescriptorCount, sizeof(data), alignment, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT); + + unsigned char* buffer = static_cast(variables.descriptorsBuffer->alloc->getHostPtr()); + for (deUint32 infoIdx = 0; infoIdx < variables.validDescriptorCount; ++infoIdx) + { + const float component = m_colorScheme[infoIdx % m_schemeSize]; + const tcu::Vec4 color (component, component, component, 1.0f); + VkDescriptorBufferInfo& info = variables.descriptorsBufferInfos[infoIdx]; + data.cnew = vertexStores ? m_clearColor : color; + data.cold = color; + + deMemcpy(buffer + info.offset, &data, sizeof(data)); + } + vk::flushAlloc(m_vki, m_vkd, *variables.descriptorsBuffer->alloc); + + variables.dataAlignment = deAlign64(sizeof(data), alignment); +} + +bool StorageBufferInstance::verifyVertexWriteResults (IterateCommonVariables& variables) +{ + const tcu::Vec4 threshold (0.002f, 0.002f, 0.002f, 0.002f); + const std::vector primes = ut::generatePrimes(variables.availableDescriptorCount); + + unsigned char* buffer = static_cast(variables.descriptorsBuffer->alloc->getHostPtr()); + BindingStorageBuffer::Data data; + for (deUint32 primeIdx = 0; primeIdx < variables.validDescriptorCount; ++primeIdx) + { + const deUint32 prime = primes[primeIdx]; + const float component = m_colorScheme[(prime % variables.validDescriptorCount) % m_schemeSize]; + const tcu::Vec4 referenceValue(component, component, component, 1.0f); + + VkDescriptorBufferInfo& info = variables.descriptorsBufferInfos[primeIdx]; + deMemcpy(&data, buffer + info.offset, sizeof(data)); + const tcu::Vec4 realValue = data.cnew; + + const tcu::Vec4 diff = tcu::absDiff(referenceValue, realValue); + if (!tcu::boolAll(tcu::lessThanEqual(diff, threshold))) + return false; + } + return true; +} + +class UniformBufferInstance : virtual public CommonDescriptorInstance +{ +public: + UniformBufferInstance (Context& context, + const TestCaseParams& testCaseParams); +protected: + virtual void createAndPopulateDescriptors (IterateCommonVariables& variables); +}; + +UniformBufferInstance::UniformBufferInstance (Context& context, + const TestCaseParams& testCaseParams) + : CommonDescriptorInstance(context, + TestParams(VK_SHADER_STAGE_ALL_GRAPHICS, + VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, + BINDING_UniformBuffer, + VK_DESCRIPTOR_TYPE_UNDEFINED, + BINDING_Undefined, + false, + performWritesInVertex(testCaseParams.descriptorType), + testCaseParams)) +{ + ut::DeviceProperties dp(context); + + checkIndexingAvailable(dp); + + const VkPhysicalDeviceDescriptorIndexingFeaturesEXT& feats = dp.descriptorIndexingFeatures(); + + if (!(feats.shaderUniformBufferArrayNonUniformIndexing)) + TCU_THROW(NotSupportedError, "Non-uniform indexing for uniform buffer descriptor arrays is not supported."); + + if (m_testParams.updateAfterBind) + { + if (!(feats.descriptorBindingUniformBufferUpdateAfterBind)) + TCU_THROW(NotSupportedError, "Update after bind for uniform buffer descriptors is not supported."); + } +} + +void UniformBufferInstance::createAndPopulateDescriptors (IterateCommonVariables& variables) +{ + BindingUniformBuffer::Data data; + + const deUint32 alignment = static_cast(ut::DeviceProperties(m_context).physicalDeviceProperties().limits.minUniformBufferOffsetAlignment); + createBuffers(variables.descriptorsBufferInfos, variables.descriptorsBuffer, variables.validDescriptorCount, sizeof(data), alignment, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); + + unsigned char* buffer = static_cast(variables.descriptorsBuffer->alloc->getHostPtr()); + for (deUint32 infoIdx = 0; infoIdx < variables.validDescriptorCount; ++infoIdx) + { + const float component = m_colorScheme[infoIdx % m_schemeSize]; + VkDescriptorBufferInfo& info = variables.descriptorsBufferInfos[infoIdx]; + data.c = tcu::Vec4(component, component, component, 1.0f); + deMemcpy(buffer + info.offset, &data, sizeof(data)); + } + vk::flushAlloc(m_vki, m_vkd, *variables.descriptorsBuffer->alloc); + + variables.dataAlignment = deAlign64(sizeof(data), alignment); +} + +class StorageTexelInstance : public CommonDescriptorInstance +{ +public: + StorageTexelInstance (Context& context, + const TestCaseParams& testCaseParams); +private: + virtual void createAndPopulateDescriptors (IterateCommonVariables& variables); + + virtual bool verifyVertexWriteResults (IterateCommonVariables& variables); +}; + +StorageTexelInstance::StorageTexelInstance (Context& context, + const TestCaseParams& testCaseParams) + : CommonDescriptorInstance(context, + TestParams(VK_SHADER_STAGE_ALL_GRAPHICS, + VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, + BINDING_StorageTexelBuffer, + VK_DESCRIPTOR_TYPE_UNDEFINED, + BINDING_Undefined, + false, + performWritesInVertex(testCaseParams.descriptorType), + testCaseParams)) +{ + ut::DeviceProperties dp(context); + + checkIndexingAvailable(dp); + + const VkPhysicalDeviceDescriptorIndexingFeaturesEXT& feats = dp.descriptorIndexingFeatures(); + + if (!(feats.shaderStorageTexelBufferArrayNonUniformIndexing)) + TCU_THROW(NotSupportedError, "Non-uniform indexing for storage texel buffer descriptor arrays is not supported."); + + if (m_testParams.updateAfterBind) + { + if (!(feats.descriptorBindingStorageTexelBufferUpdateAfterBind)) + TCU_THROW(NotSupportedError, "Update after bind for storage texel buffer descriptors is not supported."); + } +} + +void StorageTexelInstance::createAndPopulateDescriptors (IterateCommonVariables& variables) +{ + const VkExtent3D imageExtent = { 4, 4, 1 }; + const deUint32 imageSize = ut::computeImageSize(imageExtent, m_colorFormat); + + createBuffers(variables.descriptorsBufferInfos, variables.descriptorsBuffer, variables.validDescriptorCount, imageSize, sizeof(tcu::Vec4), VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT); + createBuffersViews(variables.descriptorsBufferViews, variables.descriptorsBufferInfos, m_colorFormat); + + for (deUint32 imageIdx = 0; imageIdx < variables.validDescriptorCount; ++imageIdx) + { + const float component = m_colorScheme[imageIdx % m_schemeSize]; + const PixelBufferAccess pa = getPixelAccess(imageIdx, imageExtent, m_colorFormat, variables.descriptorsBufferInfos, variables.descriptorsBuffer); + + tcu::clear(pa, m_clearColor); + pa.setPixel(tcu::Vec4(component, component, component, 1.0f), 0, 0); + } + vk::flushAlloc(m_vki, m_vkd, *variables.descriptorsBuffer->alloc); +} + +bool StorageTexelInstance::verifyVertexWriteResults(IterateCommonVariables& variables) +{ + const VkExtent3D imageExtent = { 4, 4, 1 }; + const tcu::Vec4 threshold (0.002f, 0.002f, 0.002f, 0.002f); + const std::vector primes = ut::generatePrimes(variables.availableDescriptorCount); + + for (deUint32 primeIdx = 0; primeIdx < variables.validDescriptorCount; ++primeIdx) + { + const deUint32 prime = primes[primeIdx]; + const float component = m_colorScheme[( prime % variables.validDescriptorCount ) % m_schemeSize]; + const tcu::Vec4 referenceValue(component, component, component, 1.0f); + + const PixelBufferAccess pa = getPixelAccess(primeIdx, imageExtent, m_colorFormat, variables.descriptorsBufferInfos, variables.descriptorsBuffer); + const tcu::Vec4 realValue = pa.getPixel(1, 0); + + const tcu::Vec4 diff = tcu::absDiff(referenceValue, realValue); + if (!tcu::boolAll(tcu::lessThanEqual(diff, threshold))) + return false; + } + return true; +} + +class UniformTexelInstance : public CommonDescriptorInstance +{ +public: + UniformTexelInstance (Context& context, + const TestCaseParams& testCaseParams); +private: + virtual void createAndPopulateDescriptors (IterateCommonVariables& variables); +}; + +UniformTexelInstance::UniformTexelInstance (Context& context, + const TestCaseParams& testCaseParams) + : CommonDescriptorInstance(context, + TestParams(VK_SHADER_STAGE_ALL_GRAPHICS, + VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, + BINDING_UniformTexelBuffer, + VK_DESCRIPTOR_TYPE_UNDEFINED, + BINDING_Undefined, + false, + performWritesInVertex(testCaseParams.descriptorType), + testCaseParams)) +{ + ut::DeviceProperties dp(context); + + checkIndexingAvailable(dp); + + const VkPhysicalDeviceDescriptorIndexingFeaturesEXT& feats = dp.descriptorIndexingFeatures(); + + if (!(feats.shaderUniformTexelBufferArrayNonUniformIndexing)) + TCU_THROW(NotSupportedError, "Non-uniform indexing for uniform texel buffer descriptor arrays is not supported."); + + if (m_testParams.updateAfterBind) + { + if (!(feats.descriptorBindingUniformTexelBufferUpdateAfterBind)) + TCU_THROW(NotSupportedError, "Update after bind for uniform texel buffer descriptors is not supported."); + } +} + +void UniformTexelInstance::createAndPopulateDescriptors (IterateCommonVariables& variables) +{ + const VkExtent3D imageExtent = { 4, 4, 1 }; + const deUint32 imageSize = ut::computeImageSize(imageExtent, m_colorFormat); + + createBuffers(variables.descriptorsBufferInfos, variables.descriptorsBuffer, variables.validDescriptorCount, imageSize, sizeof(tcu::Vec4), VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT); + createBuffersViews(variables.descriptorsBufferViews, variables.descriptorsBufferInfos, m_colorFormat); + + for (deUint32 imageIdx = 0; imageIdx < variables.validDescriptorCount; ++imageIdx) + { + const float component = m_colorScheme[imageIdx % m_schemeSize]; + const PixelBufferAccess pa = getPixelAccess(imageIdx, imageExtent, m_colorFormat, variables.descriptorsBufferInfos, variables.descriptorsBuffer); + + tcu::clear(pa, tcu::Vec4(component, component, component, 1.0f)); + } + vk::flushAlloc(m_vki, m_vkd, *variables.descriptorsBuffer->alloc); +} + +class DynamicBuffersInstance : virtual public CommonDescriptorInstance +{ +public: + DynamicBuffersInstance (Context& context, + const TestParams& testParams) + : CommonDescriptorInstance(context, testParams) {} + +protected: + virtual tcu::TestStatus iterate (void); + virtual void updateDescriptors (IterateCommonVariables& variables); +}; + +void DynamicBuffersInstance::updateDescriptors (IterateCommonVariables& variables) +{ + DE_ASSERT(variables.dataAlignment); + + VkDescriptorBufferInfo bufferInfo = + { + *variables.descriptorsBuffer.get()->buffer, + 0, // always 0, it will be taken from pDynamicOffsets + variables.dataAlignment + }; + + VkWriteDescriptorSet updateInfo = + { + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // sType + DE_NULL, // pNext + *variables.descriptorSet, // descriptorSet + m_testParams.descriptorBinding, // descriptorBinding; + 0, // to be set in below loop // dstArrayElement + 1u, // descriptorCount + m_testParams.descriptorType, // descriptorType + DE_NULL, // pImageInfo + &bufferInfo, // pBufferInfo + DE_NULL // pTexelBufferView + }; + + deUint32 descIdx = 0; + const std::vector primes = ut::generatePrimes(variables.availableDescriptorCount); + for (deUint32 validIdx = 0; validIdx < variables.validDescriptorCount; ++validIdx) + { + for (; descIdx < primes[validIdx]; ++descIdx) + { + updateInfo.dstArrayElement = descIdx; + m_vki.updateDescriptorSets (m_vkd, 1u, &updateInfo, 0u, DE_NULL); + } + + updateInfo.dstArrayElement = primes[validIdx]; + m_vki.updateDescriptorSets (m_vkd, 1u, &updateInfo, 0u, DE_NULL); + + ++descIdx; + } + for (; descIdx < variables.availableDescriptorCount; ++descIdx) + { + updateInfo.dstArrayElement = descIdx; + m_vki.updateDescriptorSets(m_vkd, 1u, &updateInfo, 0u, DE_NULL); + } +} + +tcu::TestStatus DynamicBuffersInstance::iterate (void) +{ + IterateCommonVariables v; + iterateCommandBegin (v); + + DE_ASSERT(v.dataAlignment); + + std::vector dynamicOffsets; + + deUint32 descIdx = 0; + const std::vector primes = ut::generatePrimes(v.availableDescriptorCount); + for (deUint32 validIdx = 0; validIdx < v.validDescriptorCount; ++validIdx) + { + for (; descIdx < primes[validIdx]; ++descIdx) + { + dynamicOffsets.push_back(0); + } + + dynamicOffsets.push_back(static_cast(validIdx * v.dataAlignment)); + + ++descIdx; + } + for (; descIdx < v.availableDescriptorCount; ++descIdx) + { + dynamicOffsets.push_back(0); + } + + // Unfortunatelly not lees and not more, only exactly + DE_ASSERT(dynamicOffsets.size() == v.availableDescriptorCount); + + const VkDescriptorSet descriptorSets[] = { *v.descriptorSet }; + + m_vki.cmdBindDescriptorSets( + *v.commandBuffer, // commandBuffer + VK_PIPELINE_BIND_POINT_GRAPHICS, // pipelineBindPoint + *v.pipelineLayout, // layout + 0u, // firstSet + DE_LENGTH_OF_ARRAY(descriptorSets), // descriptorSetCount + descriptorSets, // pDescriptorSets + v.availableDescriptorCount, // dynamicOffsetCount + dynamicOffsets.data()); // pDynamicOffsets + + vk::beginRenderPass (m_vki, *v.commandBuffer, *v.renderPass, *v.frameBuffer->buffer, v.renderArea, m_clearColor); + m_vki.cmdDraw (*v.commandBuffer, v.vertexCount, 1, 0, 0); + vk::endRenderPass (m_vki, *v.commandBuffer); + + return (iterateCommandEnd(v) ? tcu::TestStatus::pass : tcu::TestStatus::fail)(""); +} + +class DynamicStorageBufferInstance : public DynamicBuffersInstance, public StorageBufferInstance +{ +public: + DynamicStorageBufferInstance (Context& context, + const TestCaseParams& testCaseParams); + tcu::TestStatus iterate (void); + void createAndPopulateDescriptors (IterateCommonVariables& variables); + void updateDescriptors (IterateCommonVariables& variables); + bool verifyVertexWriteResults (IterateCommonVariables& variables); +}; + +DynamicStorageBufferInstance::DynamicStorageBufferInstance (Context& context, + const TestCaseParams& testCaseParams) + : CommonDescriptorInstance(context, + TestParams(VK_SHADER_STAGE_ALL_GRAPHICS, + VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, + BINDING_StorageBufferDynamic, + VK_DESCRIPTOR_TYPE_UNDEFINED, + BINDING_Undefined, + false, + performWritesInVertex(testCaseParams.descriptorType), + testCaseParams)), + DynamicBuffersInstance(context, m_testParams), StorageBufferInstance(context, testCaseParams) +{ + ut::DeviceProperties dp(context); + + checkIndexingAvailable(dp); + + const VkPhysicalDeviceDescriptorIndexingFeaturesEXT& feats = dp.descriptorIndexingFeatures(); + + if (!(feats.shaderStorageBufferArrayNonUniformIndexing)) + TCU_THROW(NotSupportedError, "Non-uniform indexing over storage buffer dynamic descriptor arrays is not supported."); + + if (testCaseParams.updateAfterBind) + { + TCU_THROW(NotSupportedError, "Update after bind for storage buffer dynamic descriptors is not supported."); + } +} + +tcu::TestStatus DynamicStorageBufferInstance::iterate(void) +{ + return DynamicBuffersInstance::iterate(); +} + +void DynamicStorageBufferInstance::createAndPopulateDescriptors(IterateCommonVariables& variables) +{ + StorageBufferInstance::createAndPopulateDescriptors(variables); +} + +void DynamicStorageBufferInstance::updateDescriptors(IterateCommonVariables& variables) +{ + DynamicBuffersInstance::updateDescriptors(variables); +} + +bool DynamicStorageBufferInstance::verifyVertexWriteResults(IterateCommonVariables& variables) +{ + return StorageBufferInstance::verifyVertexWriteResults(variables); +} + +class DynamicUniformBufferInstance : public DynamicBuffersInstance, public UniformBufferInstance +{ +public: + DynamicUniformBufferInstance (Context& context, + const TestCaseParams& testCaseParams); + tcu::TestStatus iterate(void); + void createAndPopulateDescriptors(IterateCommonVariables& variables); + void updateDescriptors(IterateCommonVariables& variables); +}; + +DynamicUniformBufferInstance::DynamicUniformBufferInstance (Context& context, + const TestCaseParams& testCaseParams) + : CommonDescriptorInstance(context, + TestParams(VK_SHADER_STAGE_ALL_GRAPHICS, + VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, + BINDING_UniformBufferDynamic, + VK_DESCRIPTOR_TYPE_UNDEFINED, + BINDING_Undefined, + false, + performWritesInVertex(testCaseParams.descriptorType), + testCaseParams)), + DynamicBuffersInstance(context, m_testParams), UniformBufferInstance(context, testCaseParams) +{ + ut::DeviceProperties dp(context); + + checkIndexingAvailable(dp); + + const VkPhysicalDeviceDescriptorIndexingFeaturesEXT& feats = dp.descriptorIndexingFeatures(); + + if (!(feats.shaderUniformBufferArrayNonUniformIndexing)) + TCU_THROW(NotSupportedError, "Non-uniform indexing over uniform buffer dynamic descriptor arrays is not supported."); + + if (testCaseParams.updateAfterBind) + { + TCU_THROW(NotSupportedError, "Update after bind for uniform buffer dynamic descriptors is not supported."); + } +} + +tcu::TestStatus DynamicUniformBufferInstance::iterate(void) +{ + return DynamicBuffersInstance::iterate(); +} + +void DynamicUniformBufferInstance::createAndPopulateDescriptors(IterateCommonVariables& variables) +{ + UniformBufferInstance::createAndPopulateDescriptors(variables); +} + +void DynamicUniformBufferInstance::updateDescriptors(IterateCommonVariables& variables) +{ + DynamicBuffersInstance::updateDescriptors(variables); +} + +class InputAttachmentInstance : public CommonDescriptorInstance +{ +public: + InputAttachmentInstance (Context& context, + const TestCaseParams& testCaseParams); +private: + virtual Move createRenderPass (const IterateCommonVariables& variables); + virtual void createFramebuffer (ut::FrameBufferSp& frameBuffer, + VkRenderPass renderPass, + const IterateCommonVariables& variables); + virtual void createAndPopulateDescriptors (IterateCommonVariables& variables); +}; + +InputAttachmentInstance::InputAttachmentInstance (Context& context, + const TestCaseParams& testCaseParams) + : CommonDescriptorInstance(context, + TestParams(VK_SHADER_STAGE_ALL_GRAPHICS, + VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, + BINDING_InputAttachment, + VK_DESCRIPTOR_TYPE_UNDEFINED, + BINDING_Undefined, + true, + performWritesInVertex(testCaseParams.descriptorType), + testCaseParams)) +{ + ut::DeviceProperties dp(context); + + checkIndexingAvailable(dp); + + const VkPhysicalDeviceDescriptorIndexingFeaturesEXT& feats = dp.descriptorIndexingFeatures(); + + if (!(feats.shaderInputAttachmentArrayNonUniformIndexing)) + TCU_THROW(NotSupportedError, "Non-uniform indexing over input attachment descriptor arrays is not supported."); + + if (testCaseParams.updateAfterBind) + { + TCU_THROW(NotSupportedError, "Update after bind for input attachment descriptors is not supported."); + } +} + +void InputAttachmentInstance::createAndPopulateDescriptors (IterateCommonVariables& variables) +{ + createImages(variables.descriptorsImages, variables.descriptorsBufferInfos, variables.descriptorsBuffer, + (VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT), m_testParams.frameResolution, m_colorFormat, VK_IMAGE_LAYOUT_UNDEFINED, variables.validDescriptorCount); + createImagesViews(variables.descriptorImageViews, variables.descriptorsImages, m_colorFormat); + + for (deUint32 descriptorIdx = 0; descriptorIdx < variables.validDescriptorCount; ++descriptorIdx) + { + const float component = m_colorScheme[descriptorIdx % m_schemeSize]; + const tcu::PixelBufferAccess pa = getPixelAccess(descriptorIdx, m_testParams.frameResolution, m_colorFormat, variables.descriptorsBufferInfos, variables.descriptorsBuffer); + tcu::clear(pa, tcu::Vec4(component, component, component, 1.0f)); + } +} + +Move InputAttachmentInstance::createRenderPass (const IterateCommonVariables& variables) +{ + std::vector attachmentDescriptions; + std::vector inputAttachmentRefs; + + const VkAttachmentDescription colorAttachmentDescription = + { + (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags; + m_colorFormat, // VkFormat format; + VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; + VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp; + VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; + VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; + VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; + VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout; + }; + const VkAttachmentReference colorAttachmentRef = + { + 0u, // deUint32 attachment; + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout; + }; + attachmentDescriptions.push_back(colorAttachmentDescription); + + // build input atachments + { + const deUint32 inputCount = static_cast(variables.descriptorImageViews.size()); + for (deUint32 inputIdx = 0; inputIdx < inputCount; ++inputIdx) + { + const VkAttachmentDescription inputAttachmentDescription = + { + VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT, // VkAttachmentDescriptionFlags flags; + variables.descriptorsImages[inputIdx]->format, // VkFormat format; + VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; + VK_ATTACHMENT_LOAD_OP_LOAD, // VkAttachmentLoadOp loadOp; + VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp storeOp; + VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; + VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; + variables.descriptorsImages[inputIdx]->layout, // VkImageLayout initialLayout; + VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout finalLayout; + }; + + const VkAttachmentReference inputAttachmentRef = + { + inputIdx + 1, // deUint32 attachment; + VK_IMAGE_LAYOUT_GENERAL // VkImageLayout layout; + }; + + inputAttachmentRefs.push_back(inputAttachmentRef); + attachmentDescriptions.push_back(inputAttachmentDescription); + } + } + + const VkSubpassDescription subpassDescription = + { + (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags; + VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; + static_cast(inputAttachmentRefs.size()), // deUint32 inputAttachmentCount; + inputAttachmentRefs.data(), // const VkAttachmentReference* pInputAttachments; + 1u, // deUint32 colorAttachmentCount; + &colorAttachmentRef, // const VkAttachmentReference* pColorAttachments; + DE_NULL, // const VkAttachmentReference* pResolveAttachments; + DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment; + 0u, // deUint32 preserveAttachmentCount; + DE_NULL // const deUint32* pPreserveAttachments; + }; + + const VkRenderPassCreateInfo renderPassInfo = + { + VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags; + static_cast(attachmentDescriptions.size()), // deUint32 attachmentCount; + attachmentDescriptions.data(), // const VkAttachmentDescription* pAttachments; + 1u, // deUint32 subpassCount; + &subpassDescription, // const VkSubpassDescription* pSubpasses; + 0u, // deUint32 dependencyCount; + DE_NULL // const VkSubpassDependency* pDependencies; + }; + + return vk::createRenderPass(m_vki, m_vkd, &renderPassInfo); +} + +void InputAttachmentInstance::createFramebuffer (ut::FrameBufferSp& frameBuffer, + VkRenderPass renderPass, + const IterateCommonVariables& variables) +{ + std::vector inputAttachments; + const deUint32 viewCount = static_cast(variables.descriptorImageViews.size()); + inputAttachments.resize(viewCount); + for (deUint32 viewIdx = 0; viewIdx < viewCount; ++viewIdx) + { + inputAttachments[viewIdx] = **variables.descriptorImageViews[viewIdx]; + } + ut::createFrameBuffer(frameBuffer, m_context, m_testParams.frameResolution, m_colorFormat, renderPass, viewCount, inputAttachments.data()); +} + +class SamplerInstance : public CommonDescriptorInstance +{ +public: + SamplerInstance (Context& context, + const TestCaseParams& testCaseParams); +private: + virtual void createAndPopulateDescriptors (IterateCommonVariables& variables); + virtual void updateDescriptors (IterateCommonVariables& variables); +}; + +SamplerInstance::SamplerInstance (Context& context, + const TestCaseParams& testCaseParams) + : CommonDescriptorInstance(context, + TestParams(VK_SHADER_STAGE_ALL_GRAPHICS, + VK_DESCRIPTOR_TYPE_SAMPLER, + BINDING_Sampler, + VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, + BINDING_SampledImage, + true, + performWritesInVertex(testCaseParams.descriptorType), + testCaseParams)) +{ + ut::DeviceProperties dp(context); + + checkIndexingAvailable(dp); + + const VkPhysicalDeviceDescriptorIndexingFeaturesEXT& feats = dp.descriptorIndexingFeatures(); + // Note: common flags for SAMPLER, SAMPLED_IMAGE, COMBINED_IMAGE_SAMPLER + + if (!(feats.shaderSampledImageArrayNonUniformIndexing)) + TCU_THROW(NotSupportedError, "Non-uniform indexing over sampler descriptor arrays is not supported."); + + if (testCaseParams.updateAfterBind) + { + if (!(feats.descriptorBindingSampledImageUpdateAfterBind)) + TCU_THROW(NotSupportedError, "Update after bind for sampler descriptors is not supported."); + } +} + +void SamplerInstance::updateDescriptors (IterateCommonVariables& variables) +{ + DE_ASSERT(variables.descriptorsImages.size() == 1); + DE_ASSERT(variables.descriptorImageViews.size() == 1); + DE_ASSERT(variables.descriptorsBufferInfos.size() == 1); + DE_ASSERT(m_testParams.additionalDescriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE); + DE_ASSERT(variables.descriptorSamplers.size() == variables.validDescriptorCount); + + // update an image + { + const VkDescriptorImageInfo imageInfo = + { + static_cast(0), + **variables.descriptorImageViews[0], + VK_IMAGE_LAYOUT_GENERAL + }; + + const VkWriteDescriptorSet writeInfo = + { + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // sType + DE_NULL, // pNext + *variables.descriptorSet, // descriptorSet + BINDING_SampledImage, // descriptorBinding; + 0, // elementIndex + 1u, // descriptorCount + VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, // descriptorType + &imageInfo, // pImageInfo + DE_NULL, // pBufferInfo + DE_NULL // pTexelBufferView + }; + + m_vki.updateDescriptorSets(m_vkd, 1u, &writeInfo, 0u, DE_NULL); + } + + // update samplers + CommonDescriptorInstance::updateDescriptors(variables); +} + +void SamplerInstance::createAndPopulateDescriptors (IterateCommonVariables& variables) +{ + DE_ASSERT(variables.descriptorsImages.size() == 0); + DE_ASSERT(variables.descriptorImageViews.size() == 0); + DE_ASSERT(variables.descriptorsBufferInfos.size() == 0); + DE_ASSERT(variables.descriptorSamplers.size() == 0); + + // create and populate an image + { + VkExtent3D imageExtent = m_testParams.frameResolution; + if (m_testParams.usesMipMaps) + { + imageExtent.width *= 2; + imageExtent.height *= 2; + }; + + createImages(variables.descriptorsImages, variables.descriptorsBufferInfos, variables.descriptorsBuffer, + (VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT), imageExtent, m_colorFormat, VK_IMAGE_LAYOUT_UNDEFINED, 1, m_testParams.usesMipMaps); + createImagesViews(variables.descriptorImageViews, variables.descriptorsImages, m_colorFormat); + + PixelBufferAccess pa = getPixelAccess(0, imageExtent, m_colorFormat, variables.descriptorsBufferInfos, variables.descriptorsBuffer, m_testParams.usesMipMaps ? 1 : 0); + + for (deUint32 y = 0, pixelNum = 0; y < m_testParams.frameResolution.height; ++y) + { + for (deUint32 x = 0; x < m_testParams.frameResolution.width; ++x, ++pixelNum) + { + const float component = m_colorScheme[(pixelNum % variables.validDescriptorCount) % m_schemeSize]; + pa.setPixel(tcu::Vec4(component, component, component, 1.0f), x, y); + } + } + + vk::flushAlloc(m_vki, m_vkd, *variables.descriptorsBuffer->alloc); + } + + const tcu::Sampler sampler( + tcu::Sampler::CLAMP_TO_BORDER, // wrapS + tcu::Sampler::CLAMP_TO_BORDER, // wrapT + tcu::Sampler::CLAMP_TO_BORDER, // wrapR + m_testParams.usesMipMaps ? tcu::Sampler::LINEAR_MIPMAP_NEAREST : tcu::Sampler::NEAREST, // minFilter + m_testParams.usesMipMaps ? tcu::Sampler::LINEAR_MIPMAP_NEAREST : tcu::Sampler::NEAREST, // magFilter + 0.0f, // lodTreshold + true); // normalizeCoords + const VkSamplerCreateInfo createInfo = vk::mapSampler(sampler, vk::mapVkFormat(m_colorFormat)); + variables.descriptorSamplers.resize(variables.validDescriptorCount); + + for (deUint32 samplerIdx = 0; samplerIdx < variables.validDescriptorCount; ++samplerIdx) + { + variables.descriptorSamplers[samplerIdx] = ut::SamplerSp(new Move(vk::createSampler(m_vki, m_vkd, &createInfo))); + } +} + +class SampledImageInstance : public CommonDescriptorInstance +{ +public: + SampledImageInstance (Context& context, + const TestCaseParams& testCaseParams); +private: + virtual void createAndPopulateDescriptors (IterateCommonVariables& variables); + virtual void updateDescriptors (IterateCommonVariables& variables); +}; + +SampledImageInstance::SampledImageInstance (Context& context, + const TestCaseParams& testCaseParams) + : CommonDescriptorInstance(context, + TestParams(VK_SHADER_STAGE_ALL_GRAPHICS, + VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, + BINDING_SampledImage, + VK_DESCRIPTOR_TYPE_SAMPLER, + BINDING_Sampler, + true, + performWritesInVertex(testCaseParams.descriptorType), + testCaseParams)) +{ + ut::DeviceProperties dp(context); + + checkIndexingAvailable(dp); + + const VkPhysicalDeviceDescriptorIndexingFeaturesEXT& feats = dp.descriptorIndexingFeatures(); + // Note: common flags for SAMPLER, SAMPLED_IMAGE, COMBINED_IMAGE_SAMPLER + + if (!(feats.shaderSampledImageArrayNonUniformIndexing)) + TCU_THROW(NotSupportedError, "Non-uniform indexing over sampled image descriptor arrays is not supported."); + + if (testCaseParams.updateAfterBind) + { + if (!(feats.descriptorBindingSampledImageUpdateAfterBind)) + TCU_THROW(NotSupportedError, "Update after bind for sampled image descriptors is not supported."); + } +} + +void SampledImageInstance::updateDescriptors (IterateCommonVariables& variables) +{ + DE_ASSERT(variables.descriptorSamplers.size() == 1); + DE_ASSERT(variables.descriptorsImages.size() == variables.validDescriptorCount); + DE_ASSERT(variables.descriptorImageViews.size() == variables.validDescriptorCount); + DE_ASSERT(variables.descriptorsBufferInfos.size() == variables.validDescriptorCount); + + // update a sampler + { + const VkDescriptorImageInfo samplerInfo = + { + **variables.descriptorSamplers[0], + static_cast(0), + static_cast(0) + }; + + const VkWriteDescriptorSet writeInfo = + { + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // sType + DE_NULL, // pNext + *variables.descriptorSet, // descriptorSet + BINDING_Sampler, // descriptorBinding; + 0, // elementIndex + 1u, // descriptorCount + VK_DESCRIPTOR_TYPE_SAMPLER, // descriptorType + &samplerInfo, // pImageInfo + DE_NULL, // pBufferInfo + DE_NULL // pTexelBufferView + }; + + m_vki.updateDescriptorSets(m_vkd, 1u, &writeInfo, 0u, DE_NULL); + } + + // update images + CommonDescriptorInstance::updateDescriptors(variables); +} + +void SampledImageInstance::createAndPopulateDescriptors (IterateCommonVariables& variables) +{ + DE_ASSERT(variables.descriptorSamplers.size() == 0); + DE_ASSERT(variables.descriptorsImages.size() == 0); + DE_ASSERT(variables.descriptorImageViews.size() == 0); + DE_ASSERT(variables.descriptorsBufferInfos.size() == 0); + + // create an only one sampler for all images + { + const tcu::Sampler sampler( + tcu::Sampler::CLAMP_TO_BORDER, // wrapS + tcu::Sampler::CLAMP_TO_BORDER, // wrapT + tcu::Sampler::CLAMP_TO_BORDER, // wrapR + m_testParams.usesMipMaps ? tcu::Sampler::NEAREST_MIPMAP_NEAREST : tcu::Sampler::NEAREST, // minFilter + m_testParams.usesMipMaps ? tcu::Sampler::NEAREST_MIPMAP_NEAREST : tcu::Sampler::NEAREST, // magFilter + 0.0f, // lodTreshold + true); // normalizeCoords + const VkSamplerCreateInfo createInfo = vk::mapSampler(sampler, vk::mapVkFormat(m_colorFormat)); + variables.descriptorSamplers.push_back(ut::SamplerSp(new Move(vk::createSampler(m_vki, m_vkd, &createInfo)))); + } + + const VkExtent3D& imageExtent = m_testParams.usesMipMaps ? bigImageExtent : smallImageExtent; + + createImages(variables.descriptorsImages, variables.descriptorsBufferInfos, variables.descriptorsBuffer, + (VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT), imageExtent, m_colorFormat, VK_IMAGE_LAYOUT_UNDEFINED, variables.validDescriptorCount, m_testParams.usesMipMaps); + createImagesViews(variables.descriptorImageViews, variables.descriptorsImages, m_colorFormat); + + PixelBufferAccess pixelAccess; + for (deUint32 imageIdx = 0; imageIdx < variables.validDescriptorCount; ++imageIdx) + { + const float component = m_colorScheme[imageIdx % m_schemeSize]; + + if (m_testParams.usesMipMaps) + { + const deUint32 mipCount = ut::computeMipMapCount(imageExtent); + DE_ASSERT(mipCount >= 2); + for (deUint32 mipIdx = 0; mipIdx < mipCount; ++mipIdx) + { + pixelAccess = getPixelAccess(imageIdx, imageExtent, m_colorFormat, variables.descriptorsBufferInfos, variables.descriptorsBuffer, mipIdx); + tcu::clear(pixelAccess, m_clearColor); + } + + pixelAccess = getPixelAccess(imageIdx, imageExtent, m_colorFormat, variables.descriptorsBufferInfos, variables.descriptorsBuffer, mipCount-1); + pixelAccess.setPixel(tcu::Vec4(component, component, component, 1.0f), 0, 0); + } + else + { + pixelAccess = getPixelAccess(imageIdx, imageExtent, m_colorFormat, variables.descriptorsBufferInfos, variables.descriptorsBuffer, 0); + pixelAccess.setPixel(tcu::Vec4(component, component, component, 1.0f), 0, 0); + } + } + vk::flushAlloc(m_vki, m_vkd, *variables.descriptorsBuffer->alloc); +} + +class CombinedImageInstance : public CommonDescriptorInstance +{ +public: + CombinedImageInstance (Context& context, + const TestCaseParams& testCaseParams); +private: + virtual void createAndPopulateDescriptors (IterateCommonVariables& variables); + virtual void updateDescriptors (IterateCommonVariables& variables); +}; + +CombinedImageInstance::CombinedImageInstance (Context& context, + const TestCaseParams& testCaseParams) + : CommonDescriptorInstance(context, + TestParams(VK_SHADER_STAGE_ALL_GRAPHICS, + testCaseParams.descriptorType, + BINDING_CombinedImageSampler, + VK_DESCRIPTOR_TYPE_UNDEFINED, + BINDING_Undefined, + true, + performWritesInVertex(testCaseParams.descriptorType), + testCaseParams)) +{ + ut::DeviceProperties dp(context); + + checkIndexingAvailable(dp); + + const VkPhysicalDeviceDescriptorIndexingFeaturesEXT& feats = dp.descriptorIndexingFeatures(); + // Note: common flags for SAMPLER, SAMPLED_IMAGE, COMBINED_IMAGE_SAMPLER + + if (!(feats.shaderSampledImageArrayNonUniformIndexing)) + TCU_THROW(NotSupportedError, "Non-uniform indexing over combined image sampler descriptor arrays is not supported."); + + if (testCaseParams.updateAfterBind) + { + if (!(feats.descriptorBindingSampledImageUpdateAfterBind)) + TCU_THROW(NotSupportedError, "Update after bind for combined image sampler descriptors is not supported."); + } +} + +void CombinedImageInstance::updateDescriptors (IterateCommonVariables& variables) +{ + const std::vector primes = ut::generatePrimes(variables.availableDescriptorCount); + const deUint32 primeCount = static_cast(primes.size()); + + DE_ASSERT(variables.descriptorSamplers.size() == 1); + DE_ASSERT(variables.descriptorsImages.size() == primeCount); + DE_ASSERT(variables.descriptorImageViews.size() == primeCount); + DE_ASSERT(variables.descriptorsBufferInfos.size() == primeCount); + + for (deUint32 primeIdx = 0; primeIdx < primeCount; ++primeIdx) + { + const VkDescriptorImageInfo imageInfo = + { + **variables.descriptorSamplers[0], + **variables.descriptorImageViews[primeIdx], + VK_IMAGE_LAYOUT_GENERAL + }; + + const VkWriteDescriptorSet writeInfo = + { + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // sType + DE_NULL, // pNext + *variables.descriptorSet, // descriptorSet + BINDING_CombinedImageSampler, // descriptorBinding; + primes[primeIdx], // elementIndex + 1u, // descriptorCount + m_testParams.descriptorType, // descriptorType + &imageInfo, // pImageInfo + DE_NULL, // pBufferInfo + DE_NULL // pTexelBufferView + }; + + m_vki.updateDescriptorSets(m_vkd, 1u, &writeInfo, 0u, DE_NULL); + } +} + +void CombinedImageInstance::createAndPopulateDescriptors (IterateCommonVariables& variables) +{ + DE_ASSERT(variables.descriptorSamplers.size() == 0); + DE_ASSERT(variables.descriptorsImages.size() == 0); + DE_ASSERT(variables.descriptorImageViews.size() == 0); + DE_ASSERT(variables.descriptorsBufferInfos.size() == 0); + DE_ASSERT(variables.descriptorSamplers.size() == 0); + + const tcu::Sampler sampler( + tcu::Sampler::CLAMP_TO_BORDER, // wrapS + tcu::Sampler::CLAMP_TO_BORDER, // wrapT + tcu::Sampler::CLAMP_TO_BORDER, // wrapR + m_testParams.usesMipMaps ? tcu::Sampler::NEAREST_MIPMAP_NEAREST : tcu::Sampler::NEAREST, // minFilter + m_testParams.usesMipMaps ? tcu::Sampler::NEAREST_MIPMAP_NEAREST : tcu::Sampler::NEAREST, // magFilter + 0.0f, // lodTreshold + true); // normalizeCoords + const VkSamplerCreateInfo createInfo = vk::mapSampler(sampler, vk::mapVkFormat(m_colorFormat)); + variables.descriptorSamplers.push_back(ut::SamplerSp(new Move(vk::createSampler(m_vki, m_vkd, &createInfo)))); + + const VkExtent3D& imageExtent = m_testParams.usesMipMaps ? bigImageExtent : smallImageExtent; + createImages(variables.descriptorsImages, variables.descriptorsBufferInfos, variables.descriptorsBuffer, (VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT), + imageExtent, m_colorFormat, VK_IMAGE_LAYOUT_UNDEFINED, variables.validDescriptorCount, m_testParams.usesMipMaps); + createImagesViews(variables.descriptorImageViews, variables.descriptorsImages, m_colorFormat); + + PixelBufferAccess pixelAccess; + for (deUint32 imageIdx = 0; imageIdx < variables.validDescriptorCount; ++imageIdx) + { + const float component = m_colorScheme[imageIdx % m_schemeSize]; + + if (m_testParams.usesMipMaps) + { + const deUint32 mipCount = ut::computeMipMapCount(imageExtent); + DE_ASSERT(mipCount >= 2); + for (deUint32 mipIdx = 0; mipIdx < mipCount; ++mipIdx) + { + pixelAccess = getPixelAccess(imageIdx, imageExtent, m_colorFormat, variables.descriptorsBufferInfos, variables.descriptorsBuffer, mipIdx); + tcu::clear(pixelAccess, m_clearColor); + } + + pixelAccess = getPixelAccess(imageIdx, imageExtent, m_colorFormat, variables.descriptorsBufferInfos, variables.descriptorsBuffer, mipCount-1); + pixelAccess.setPixel(tcu::Vec4(component, component, component, 1.0f), 0, 0); + } + else + { + pixelAccess = getPixelAccess(imageIdx, imageExtent, m_colorFormat, variables.descriptorsBufferInfos, variables.descriptorsBuffer, 0); + pixelAccess.setPixel(tcu::Vec4(component, component, component, 1.0f), 0, 0); + } + } + + vk::flushAlloc(m_vki, m_vkd, *variables.descriptorsBuffer->alloc); +} + +class StorageImageInstance : public CommonDescriptorInstance +{ +public: + StorageImageInstance (Context& context, + const TestCaseParams& testCaseParams); +private: + virtual tcu::TestStatus iterate (void); + virtual void createAndPopulateDescriptors (IterateCommonVariables& variables); + virtual void updateDescriptors (IterateCommonVariables& variables); + virtual void iterateCollectResults (ut::UpdatablePixelBufferAccessPtr& result, + const IterateCommonVariables& variables, + bool fromTest); + ut::BufferHandleAllocSp m_buffer; + const deUint32 m_fillColor; + typedef deUint32 m_imageFormat_t; +}; + +StorageImageInstance::StorageImageInstance (Context& context, + const TestCaseParams& testCaseParams) + : CommonDescriptorInstance(context, + TestParams (VK_SHADER_STAGE_COMPUTE_BIT, + VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, + BINDING_StorageImage, + VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, + (BINDING_StorageImage + 1), + true, + performWritesInVertex(testCaseParams.descriptorType), + testCaseParams)) + , m_buffer () + , m_fillColor (10) +{ + ut::DeviceProperties dp(context); + + checkIndexingAvailable(dp); + + const VkPhysicalDeviceDescriptorIndexingFeaturesEXT& features = dp.descriptorIndexingFeatures(); + + if (!(features.shaderStorageImageArrayNonUniformIndexing)) + TCU_THROW(NotSupportedError, "Non-uniform indexing over storage image descriptor arrays is not supported."); + + if (testCaseParams.updateAfterBind) + { + if (!(features.descriptorBindingStorageImageUpdateAfterBind)) + TCU_THROW(NotSupportedError, "Update after bind for storage image descriptors is not supported."); + } +} + +void StorageImageInstance::updateDescriptors (IterateCommonVariables& variables) +{ + // update image at last index + { + VkDescriptorImageInfo imageInfo = + { + static_cast(0), + **variables.descriptorImageViews[variables.validDescriptorCount], + VK_IMAGE_LAYOUT_GENERAL + }; + + const VkWriteDescriptorSet writeInfo = + { + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // sType + DE_NULL, // pNext + *variables.descriptorSet, // descriptorSet + m_testParams.additionalDescriptorBinding, // descriptorBinding; + 0, // elementIndex + 1u, // descriptorCount + m_testParams.additionalDescriptorType, // descriptorType + &imageInfo, // pImageInfo + DE_NULL, // pBufferInfo + DE_NULL // pTexelBufferView + }; + + m_vki.updateDescriptorSets(m_vkd, 1u, &writeInfo, 0u, DE_NULL); + } + + // update rest images + CommonDescriptorInstance::updateDescriptors(variables); +} + +void StorageImageInstance::createAndPopulateDescriptors (IterateCommonVariables& variables) +{ + const VkFormat imageFormat = ut::mapType2vkFormat::value; + const VkBufferUsageFlags bufferUsage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; + + // create descriptor buffer, images and views + { + const VkExtent3D imageExtent = { 4, 4, 1 }; + + createImages(variables.descriptorsImages, variables.descriptorsBufferInfos, variables.descriptorsBuffer, + bufferUsage, imageExtent, imageFormat, VK_IMAGE_LAYOUT_UNDEFINED, variables.validDescriptorCount); + + for (deUint32 imageIdx = 0; imageIdx < variables.validDescriptorCount; ++imageIdx) + { + const PixelBufferAccess pa = getPixelAccess(imageIdx, imageExtent, imageFormat, variables.descriptorsBufferInfos, variables.descriptorsBuffer); + tcu::clear(pa, tcu::UVec4(m_fillColor)); + } + vk::flushAlloc(m_vki, m_vkd, *variables.descriptorsBuffer->alloc); + } + + // create additional image that will be used as index container + { + createImages(variables.descriptorsImages, variables.descriptorsBufferInfos, m_buffer, + bufferUsage, m_testParams.frameResolution, imageFormat, VK_IMAGE_LAYOUT_UNDEFINED, 1); + + // populate buffer + const std::vector primes = ut::generatePrimes(variables.availableDescriptorCount); + const PixelBufferAccess pa = getPixelAccess(variables.validDescriptorCount, m_testParams.frameResolution, imageFormat, variables.descriptorsBufferInfos, m_buffer); + for (deUint32 y = 0, pixel = 0; y < m_testParams.frameResolution.height; ++y) + { + for (deUint32 x = 0; x < m_testParams.frameResolution.width; ++x, ++pixel) + { + const deUint32 component = primes[pixel % variables.validDescriptorCount]; + pa.setPixel(tcu::UVec4(component), x, y); + } + } + + // save changes + vk::flushAlloc(m_vki, m_vkd, *m_buffer->alloc); + } + + // create views for all previously created images + createImagesViews(variables.descriptorImageViews, variables.descriptorsImages, imageFormat); +} + +tcu::TestStatus StorageImageInstance::iterate (void) +{ + IterateCommonVariables v; + iterateCommandBegin (v); + + if (m_testParams.updateAfterBind) + { + updateDescriptors (v); + } + + copyBuffersToImages (v); + + m_vki.cmdDispatch (*v.commandBuffer, + m_testParams.calculateInLoop ? 1 : v.renderArea.extent.width, + m_testParams.calculateInLoop ? 1 : v.renderArea.extent.height, + 1); + + copyImagesToBuffers (v); + + return (iterateCommandEnd(v, false) ? tcu::TestStatus::pass : tcu::TestStatus::fail)(""); +} + +void StorageImageInstance::iterateCollectResults (ut::UpdatablePixelBufferAccessPtr& result, + const IterateCommonVariables& variables, + bool fromTest) +{ + result = ut::UpdatablePixelBufferAccessPtr(new ut::PixelBufferAccessAllocation( + vk::mapVkFormat(ut::mapType2vkFormat::value), m_testParams.frameResolution)); + const PixelBufferAccess& dst = *result.get(); + + if (fromTest) + { + vk::invalidateAlloc(m_vki, m_vkd, *variables.descriptorsBuffer->alloc); + for (deUint32 y = 0, pixelNum = 0; y < m_testParams.frameResolution.height; ++y) + { + for (deUint32 x = 0; x < m_testParams.frameResolution.width; ++x, ++pixelNum) + { + const deUint32 imageIdx = pixelNum % variables.validDescriptorCount; + const PixelBufferAccess src = getPixelAccess(imageIdx, + variables.descriptorsImages[imageIdx]->extent, variables.descriptorsImages[imageIdx]->format, + variables.descriptorsBufferInfos, variables.descriptorsBuffer); + dst.setPixel(tcu::Vector(src.getPixelT(0, 0).x()), x, y); + } + } + } + else + { + std::vector inc(variables.validDescriptorCount, m_fillColor); + + for (deUint32 invIdx = variables.lowerBound; invIdx < variables.upperBound; ++invIdx) + { + ++inc[invIdx % variables.validDescriptorCount]; + } + + for (deUint32 invIdx = 0; invIdx < variables.vertexCount; ++invIdx) + { + const deUint32 row = invIdx / m_testParams.frameResolution.width; + const deUint32 col = invIdx % m_testParams.frameResolution.width; + const m_imageFormat_t color = inc[invIdx % variables.validDescriptorCount]; + dst.setPixel(tcu::Vector(color), col, row); + } + } +} + +class DescriptorIndexingTestCase : public TestCase +{ + const TestCaseParams m_testCaseParams; +public: + DescriptorIndexingTestCase(tcu::TestContext &context, const char *name, const char *description, const TestCaseParams& testCaseParams) + : TestCase(context, name, description) + , m_testCaseParams(testCaseParams) + { + } + + vkt::TestInstance* createInstance(vkt::Context& context) const // override + { + switch (m_testCaseParams.descriptorType) + { + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: + return new StorageBufferInstance (context, m_testCaseParams); + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: + return new UniformBufferInstance (context, m_testCaseParams); + case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: + return new StorageTexelInstance (context, m_testCaseParams); + case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: + return new UniformTexelInstance (context, m_testCaseParams); + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: + return new DynamicStorageBufferInstance (context, m_testCaseParams); + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: + return new DynamicUniformBufferInstance (context, m_testCaseParams); + case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: + return new InputAttachmentInstance (context, m_testCaseParams); + case VK_DESCRIPTOR_TYPE_SAMPLER: + return new SamplerInstance (context, m_testCaseParams); + case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: + return new SampledImageInstance (context, m_testCaseParams); + case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: + return new CombinedImageInstance (context, m_testCaseParams); + case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: + return new StorageImageInstance (context, m_testCaseParams); + default: + TCU_THROW(InternalError, "Unknown Descriptor Type"); + } + return DE_NULL; + } + + virtual void initPrograms(SourceCollections& programCollection) const + { + std::string(*genShaderSource)(VkShaderStageFlagBits, const TestCaseParams&, bool) = &CommonDescriptorInstance::getShaderSource; + + if (VK_SHADER_STAGE_VERTEX_BIT & m_testCaseParams.stageFlags) + { + programCollection.glslSources.add( + ut::buildShaderName(VK_SHADER_STAGE_VERTEX_BIT, m_testCaseParams.descriptorType, m_testCaseParams.updateAfterBind, m_testCaseParams.calculateInLoop, false)) + << glu::VertexSource((*genShaderSource)(VK_SHADER_STAGE_VERTEX_BIT, m_testCaseParams, false)); + + if (CommonDescriptorInstance::performWritesInVertex(m_testCaseParams.descriptorType)) + { + programCollection.glslSources.add( + ut::buildShaderName(VK_SHADER_STAGE_VERTEX_BIT, m_testCaseParams.descriptorType, m_testCaseParams.updateAfterBind, m_testCaseParams.calculateInLoop, true)) + << glu::VertexSource((*genShaderSource)(VK_SHADER_STAGE_VERTEX_BIT, m_testCaseParams, true)); + } + } + if (VK_SHADER_STAGE_FRAGMENT_BIT & m_testCaseParams.stageFlags) + { + programCollection.glslSources.add( + ut::buildShaderName(VK_SHADER_STAGE_FRAGMENT_BIT, m_testCaseParams.descriptorType, m_testCaseParams.updateAfterBind, m_testCaseParams.calculateInLoop, false)) + << glu::FragmentSource((*genShaderSource)(VK_SHADER_STAGE_FRAGMENT_BIT, m_testCaseParams, false)); + + if (CommonDescriptorInstance::performWritesInVertex(m_testCaseParams.descriptorType)) + { + programCollection.glslSources.add( + ut::buildShaderName(VK_SHADER_STAGE_FRAGMENT_BIT, m_testCaseParams.descriptorType, m_testCaseParams.updateAfterBind, m_testCaseParams.calculateInLoop, true)) + << glu::FragmentSource((*genShaderSource)(VK_SHADER_STAGE_FRAGMENT_BIT, m_testCaseParams, true)); + } + } + if (VK_SHADER_STAGE_COMPUTE_BIT & m_testCaseParams.stageFlags) + { + programCollection.glslSources.add( + ut::buildShaderName(VK_SHADER_STAGE_COMPUTE_BIT, m_testCaseParams.descriptorType, m_testCaseParams.updateAfterBind, m_testCaseParams.calculateInLoop, false)) + << glu::ComputeSource((*genShaderSource)(VK_SHADER_STAGE_COMPUTE_BIT, m_testCaseParams, false)); + } + } +}; + +} // - unnamed namespace + +void descriptorIndexingDescriptorSetsCreateTests (tcu::TestCaseGroup* group) +{ + struct TestCaseInfo + { + const char* name; + const char* description; + TestCaseParams params; + }; + + tcu::TestContext& context(group->getTestContext()); + + TestCaseInfo casesAfterBindAndLoop[] = + { + { + "storage_buffer", "Regular Storage Buffer Descriptors", + { + VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, + (VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT), + RESOLUTION, + false, // updateAfterBind + false, // calculateInLoop + false, // useMipMaps + FUZZY_COMPARE, CMP_THRESHOLD + } + }, + { + "storage_texel_buffer", "Storage Texel Buffer Descriptors", + { + VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, + (VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT), + RESOLUTION, + false, // updateAfterBind + false, // calculateInLoop + false, // useMipMaps + FUZZY_COMPARE, CMP_THRESHOLD + } + }, + { + "uniform_texel_buffer", "Uniform Texel Buffer Descriptors", + { + VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, + (VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT), + RESOLUTION, + false, // updateAfterBind, + false, // calculateInLoop + false, // usesMipMaps + FUZZY_COMPARE, CMP_THRESHOLD + } + }, + { + "storage_image", "Storage Image Descriptors", + { + VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, + VK_SHADER_STAGE_COMPUTE_BIT, + RESOLUTION, + false, // updateAfterBind + false, // calculateInLoop + false, // useMipMaps + FUZZY_COMPARE, CMP_THRESHOLD + } + }, + }; + + for (int updateAfterBind = 0; updateAfterBind < 2; ++updateAfterBind) + { + for (int calculateInLoop = 0; calculateInLoop < 2; ++calculateInLoop) + { + for (deUint32 caseIdx = 0; caseIdx < DE_LENGTH_OF_ARRAY(casesAfterBindAndLoop); ++caseIdx) + { + TestCaseInfo& info (casesAfterBindAndLoop[caseIdx]); + std::string caseName (info.name); + std::string caseDescription (info.description); + TestCaseParams params (info.params); + + caseName += (updateAfterBind ? "_after_bind" : ""); + caseName += (calculateInLoop ? "_in_loop" : ""); + + caseDescription += (updateAfterBind ? " After Bind" : ""); + caseDescription += (calculateInLoop ? " In Loop" : ""); + + params.updateAfterBind = updateAfterBind ? true : false; + params.calculateInLoop = calculateInLoop ? true : false; + + group->addChild(new DescriptorIndexingTestCase(context, caseName.c_str(), caseDescription.c_str(), params)); + } + } + } + + TestCaseInfo casesAfterBindAndLoopAndLOD[] = + { + { + "sampler", "Sampler Descriptors", + { + VK_DESCRIPTOR_TYPE_SAMPLER, + (VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT), + RESOLUTION, + false, // updateAfterBind + false, // calculateInLoop + false, // usesMipMaps + FUZZY_COMPARE, CMP_THRESHOLD + } + }, + { + "sampled_image", "Sampled Image Descriptors", + { + VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, + (VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT), + RESOLUTION, + false, // updateAfterBind + false, // calculateInLoop + false, // usesMipMaps + FUZZY_COMPARE, CMP_THRESHOLD + } + }, + { + "combined_image_sampler", "Combined Image Sampler Descriptors", + { + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + (VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT), + RESOLUTION, + false, // updateAfterBind + false, // calculateInLoop + false, // usesMipMaps + FUZZY_COMPARE, CMP_THRESHOLD + } + }, + }; + + for (int updateAfterBind = 0; updateAfterBind < 2; ++updateAfterBind) + { + for (int calculateInLoop = 0; calculateInLoop < 2; ++calculateInLoop) + { + for (int usesMipMaps = 0; usesMipMaps < 2; ++usesMipMaps) + { + for (deUint32 caseIdx = 0; caseIdx < DE_LENGTH_OF_ARRAY(casesAfterBindAndLoopAndLOD); ++caseIdx) + { + TestCaseInfo& info (casesAfterBindAndLoopAndLOD[caseIdx]); + std::string caseName (info.name); + std::string caseDescription (info.description); + TestCaseParams params (info.params); + + caseName += (updateAfterBind ? "_after_bind" : ""); + caseName += (calculateInLoop ? "_in_loop" : ""); + caseName += (usesMipMaps ? "_with_lod" : ""); + + caseDescription += (updateAfterBind ? " After Bind" : ""); + caseDescription += (calculateInLoop ? " In Loop" : ""); + caseDescription += (usesMipMaps ? " Use LOD" : ""); + + params.updateAfterBind = updateAfterBind ? true : false; + params.calculateInLoop = calculateInLoop ? true : false; + params.usesMipMaps = usesMipMaps ? true : false; + + group->addChild(new DescriptorIndexingTestCase(context, caseName.c_str(), caseDescription.c_str(), params)); + } + } + } + } + + TestCaseInfo casesNonAfterBindAndLoop[] = + { + { + "uniform_buffer", "Regular Uniform Buffer Descriptors", + { + VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, + (VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT), + RESOLUTION, + false, // updateAfterBind + false, // calculateInLoop + false, // usesMipMaps + FUZZY_COMPARE, CMP_THRESHOLD + } + }, + { + "storage_buffer_dynamic", "Dynamic Storage Buffer Descriptors", + { + VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, + (VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT), + RESOLUTION, + false, // updateAfterBind + false, // calculateInLoop + false, // useMipMaps + FUZZY_COMPARE, CMP_THRESHOLD + } + }, + { + "uniform_buffer_dynamic", "Dynamic Uniform Buffer Descriptors", + { + VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, + (VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT), + RESOLUTION, + false, // updateAfterBind + false, // calculateInLoop + false, // useMipMaps + FUZZY_COMPARE, CMP_THRESHOLD + } + }, + { + "input_attachment", "Input Attachment Descriptors", + { + VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, + (VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT), + RESOLUTION, + false, // updateAfterBind + false, // calculateInLoop + false, // useMipMaps + FUZZY_COMPARE, CMP_THRESHOLD + } + }, + }; + + for (int calculateInLoop = 0; calculateInLoop < 2; ++calculateInLoop) + { + for (deUint32 caseIdx = 0; caseIdx < DE_LENGTH_OF_ARRAY(casesNonAfterBindAndLoop); ++caseIdx) + { + TestCaseInfo& info(casesNonAfterBindAndLoop[caseIdx]); + std::string caseName(info.name); + std::string caseDescription(info.description); + TestCaseParams params(info.params); + + caseName += (calculateInLoop ? "_in_loop" : ""); + + caseDescription += (calculateInLoop ? " In Loop" : ""); + + params.calculateInLoop = calculateInLoop ? true : false; + + group->addChild(new DescriptorIndexingTestCase(context, caseName.c_str(), caseDescription.c_str(), params)); + } + } +} + +} // - DescriptorIndexing +} // - vkt diff --git a/external/vulkancts/modules/vulkan/descriptor_indexing/vktDescriptorSetsIndexingTests.hpp b/external/vulkancts/modules/vulkan/descriptor_indexing/vktDescriptorSetsIndexingTests.hpp new file mode 100644 index 0000000..d0af3a4 --- /dev/null +++ b/external/vulkancts/modules/vulkan/descriptor_indexing/vktDescriptorSetsIndexingTests.hpp @@ -0,0 +1,370 @@ +#ifndef _VKTDESCRIPTORSETSINDEXINGTESTS_HPP +#define _VKTDESCRIPTORSETSINDEXINGTESTS_HPP +/*------------------------------------------------------------------------ +* Vulkan Conformance Tests +* ------------------------ +* +* Copyright (c) 2019 The Khronos Group Inc. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* 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 Vulkan Descriptor Indexing Tests +*//*--------------------------------------------------------------------*/ + +#include +#include +#include +#include "deSharedPtr.hpp" +#include "tcuTextureUtil.hpp" +#include "tcuRGBA.hpp" +#include "tcuSurface.hpp" +#include "vkDefs.hpp" +#include "vkImageUtil.hpp" +#include "vktTestCase.hpp" +#include "vkRefUtil.hpp" +#include "vkTypeUtil.hpp" + +namespace vkt +{ +namespace DescriptorIndexing +{ +using namespace vk; + +namespace ut +{ + +struct FrameBuffer; +struct ImageHandleAlloc; +struct BufferHandleAlloc; + +typedef de::SharedPtr FrameBufferSp; +typedef de::SharedPtr BufferHandleAllocSp; +typedef de::SharedPtr ImageHandleAllocSp; + +typedef de::MovePtr AllocMv; +typedef de::SharedPtr< Move > BufferViewSp; +typedef de::SharedPtr< Move > ImageViewSp; +typedef de::SharedPtr< Move > SamplerSp; + +static const deUint32 maxDeUint32 = static_cast(-1); + +struct ImageHandleAlloc +{ + Move image; + AllocMv alloc; + VkExtent3D extent; + VkFormat format; + VkImageLayout layout; + deUint32 levels; + + bool usesMipMaps (void) const { return levels > 0; } + + ImageHandleAlloc (void) + : image() + , alloc() {} + + ImageHandleAlloc (Move& image_, + AllocMv& alloc_, + const VkExtent3D& extent_, + VkFormat format_, + VkImageLayout layout_, + bool usesMipMaps_ = false); +private: + ImageHandleAlloc (const ImageHandleAlloc&) {} +}; + +struct FrameBuffer +{ + ImageHandleAllocSp image; + Move attachment0; + std::vector attachments; + Move buffer; + + FrameBuffer (void) + : image () + , attachment0 () + , attachments () + , buffer () {} +private: + FrameBuffer (const FrameBuffer&) {} +}; + +struct BufferHandleAlloc +{ + Move buffer; + AllocMv alloc; + + BufferHandleAlloc (void) + : buffer () + , alloc () {} + + BufferHandleAlloc (Move& buffer_, + AllocMv& alloc_) + : buffer (buffer_) + , alloc (alloc_) {} +private: + BufferHandleAlloc(const BufferHandleAlloc&) {} +}; + +std::string buildShaderName (VkShaderStageFlagBits stage, + VkDescriptorType descriptorType, + deBool updateAfterBind, + bool calculateInLoop, + bool performWritesInVertex); + +std::vector generatePrimes (deUint32 limit); + +deUint32 computePrimeCount (deUint32 limit); + +deUint32 computeImageSize (const ImageHandleAllocSp& image); + +deUint32 computeMipMapCount (const VkExtent3D& extent); + +deUint32 computeImageSize (const VkExtent3D& extent, + VkFormat format, + bool withMipMaps = false, + deUint32 level = maxDeUint32); + +std::vector createVertices (deUint32 width, + deUint32 height, + float& xSize, + float& ySize); + +VkDeviceSize createBufferAndBind (ut::BufferHandleAllocSp& output, + const vkt::Context& ctx, + VkBufferUsageFlags usage, + VkDeviceSize desiredSize); + +void createImageAndBind (ut::ImageHandleAllocSp& output, + const vkt::Context& ctx, + VkFormat colorFormat, + const VkExtent3D& extent, + VkImageLayout initialLayout, + bool withMipMaps = false, + VkImageType imageType = VK_IMAGE_TYPE_2D); + +void createFrameBuffer (ut::FrameBufferSp& outputFB, + const vkt::Context& context, + const VkExtent3D& extent, + VkFormat colorFormat, + VkRenderPass renderpass, + deUint32 additionalAttachmentCount = 0u, + const VkImageView additionalAttachments[] = DE_NULL); + +void recordCopyBufferToImage (VkCommandBuffer cmd, + const DeviceInterface& interface, + VkPipelineStageFlagBits srcStageMask, + VkPipelineStageFlagBits dstStageMask, + const VkDescriptorBufferInfo& bufferInfo, + VkImage image, + const VkExtent3D& imageExtent, + VkFormat imageFormat, + VkImageLayout oldImageLayout, + VkImageLayout newImageLayout, + deUint32 mipLevelCount); + +void recordCopyImageToBuffer (VkCommandBuffer cmd, + const DeviceInterface& interface, + VkPipelineStageFlagBits srcStageMask, + VkPipelineStageFlagBits dstStageMask, + VkImage image, + const VkExtent3D& imageExtent, + VkFormat imageFormat, + VkImageLayout oldimageLayout, + VkImageLayout newImageLayout, + const VkDescriptorBufferInfo& bufferInfo); + +VkAccessFlags pipelineAcceesFromStage (VkPipelineStageFlagBits stage, + bool readORwrite); + +bool isDynamicDescriptor (VkDescriptorType descriptorType); + +class DeviceProperties +{ + VkPhysicalDeviceDescriptorIndexingFeaturesEXT m_descriptorIndexingFeatures; + VkPhysicalDeviceFeatures2 m_features2; + + VkPhysicalDeviceDescriptorIndexingPropertiesEXT m_descriptorIndexingProperties; + VkPhysicalDeviceProperties2 m_properties2; + +public: + DeviceProperties (const DeviceProperties& src); + DeviceProperties (const vkt::Context& testContext); + + inline const VkPhysicalDeviceDescriptorIndexingFeaturesEXT& descriptorIndexingFeatures (void) const; + inline const VkPhysicalDeviceProperties& physicalDeviceProperties (void) const; + inline const VkPhysicalDeviceDescriptorIndexingPropertiesEXT& descriptorIndexingProperties(void) const; + inline const VkPhysicalDeviceFeatures& physicalDeviceFeatures (void) const; + + deUint32 computeMaxPerStageDescriptorCount (VkDescriptorType descriptorType, + bool enableUpdateAfterBind) const; +}; + +inline const VkPhysicalDeviceDescriptorIndexingFeaturesEXT& DeviceProperties::descriptorIndexingFeatures (void) const +{ + return m_descriptorIndexingFeatures; +} + +inline const VkPhysicalDeviceProperties& DeviceProperties::physicalDeviceProperties (void) const +{ + return m_properties2.properties; +} + +inline const VkPhysicalDeviceDescriptorIndexingPropertiesEXT& DeviceProperties::descriptorIndexingProperties (void) const +{ + return m_descriptorIndexingProperties; +} + +inline const VkPhysicalDeviceFeatures& DeviceProperties::physicalDeviceFeatures (void) const +{ + return m_features2.features; +} + +template struct VkFormatName +{ + static const VkFormat value = _Format; +}; +template struct mapType2vkFormat; +template<> struct mapType2vkFormat : public VkFormatName{}; +template<> struct mapType2vkFormat : public VkFormatName{}; +template<> struct mapType2vkFormat : public VkFormatName{}; +template<> struct mapType2vkFormat : public VkFormatName{}; +template<> struct mapType2vkFormat : public VkFormatName{}; +template<> struct mapType2vkFormat : public VkFormatName{}; + +template struct mapVkFormat2Type; +template<> struct mapVkFormat2Type : public VkFormatName +{ + typedef deUint32 type; +}; +template<> struct mapVkFormat2Type : public VkFormatName +{ + typedef tcu::IVec4 type; +}; + +struct UpdatablePixelBufferAccess : public tcu::PixelBufferAccess +{ + UpdatablePixelBufferAccess (const tcu::TextureFormat& format, const vk::VkExtent3D& extent, void* data) + : PixelBufferAccess(format, extent.width, extent.height, extent.depth, data) + { + } + virtual ~UpdatablePixelBufferAccess (void) { } + virtual void invalidate (void) const = 0; + virtual void fillColor (const tcu::Vec4& color) const = 0; + static deUint32 calcTexSize (const tcu::TextureFormat& format, const vk::VkExtent3D& extent) + { + return extent.width * extent.height * extent.depth * format.getPixelSize(); + } + static deUint32 calcTexSize (const tcu::TextureFormat& format, deUint32 width, deUint32 height, deUint32 depth) + { + return width * height * depth * format.getPixelSize(); + } +}; + +typedef de::SharedPtr UpdatablePixelBufferAccessPtr; + +struct PixelBufferAccessBuffer : public UpdatablePixelBufferAccess +{ + const VkDevice m_device; + const DeviceInterface& m_interface; + de::SharedPtr< Move > m_buffer; + de::SharedPtr< de::MovePtr > m_allocation; + + PixelBufferAccessBuffer (const VkDevice& device, const DeviceInterface& interface, + const tcu::TextureFormat& format, const vk::VkExtent3D& extent, + de::SharedPtr< Move > buffer, de::SharedPtr< de::MovePtr > allocation) + : UpdatablePixelBufferAccess(format, extent, (*allocation)->getHostPtr()) + , m_device(device), m_interface(interface), m_buffer(buffer), m_allocation(allocation) + { + } + void fillColor (const tcu::Vec4&) const { } + void invalidate (void) const + { + const VkDeviceSize bufferSize = calcTexSize(getFormat(), getWidth(), getHeight(), getDepth()); + vk::invalidateMappedMemoryRange(m_interface, m_device, (*m_allocation)->getMemory(), (*m_allocation)->getOffset(), bufferSize); + } +}; + +struct PixelBufferAccessAllocation : public UpdatablePixelBufferAccess +{ + std::vector m_data; + PixelBufferAccessAllocation (const tcu::TextureFormat& format, const VkExtent3D& extent) + : UpdatablePixelBufferAccess(format, extent, (new unsigned char[calcTexSize(format, extent)])) + , m_data(static_cast(getDataPtr()), (static_cast(getDataPtr()) + calcTexSize(format, extent))) + { + } + void invalidate (void) const { /* intentionally empty, only for compability */ } + void fillColor (const tcu::Vec4& color) const + { + tcu::clear(*this, color); + } +}; + +template +static std::ostream& operator<< (std::ostream& s, const std::pair& p) +{ + s << "{ " << p.first << ", " << p.second << " } "; + return s; +} + +template class TCont, class TItem, class TAlloc> +inline void printContainer (std::ostream& s, const std::string& header, const TCont& cont) +{ + typename TCont::const_iterator i, end = cont.end(); + s << header << '\n'; + for (i = cont.begin(); i != end; ++i) + { + s << *i; + } + s << '\n'; +} + +inline void printImage (std::ostream& s, const std::string& header, const tcu::PixelBufferAccess* pa, const deUint32& rgn = 4) +{ + if (header.length()) + { + s << header << std::endl; + } + for (deUint32 r = 0; r < rgn; ++r) + { + for (deUint32 c = 0; c < rgn; ++c) + { + s << pa->getPixel(c, r) << " (" << r << "," << c << ")\n"; + } + } +} + +inline bool readFile (const std::string& fileName, std::string& content) +{ + bool result = false; + std::ifstream file(fileName.c_str()); + + if (file.is_open()) + { + file >> std::noskipws; + content.resize(static_cast(file.tellg())); + content.assign(std::istream_iterator(file), + std::istream_iterator()); + result = true; + } + + return result; +} + +} // namespace ut +} // namespace DescriptorIndexing +} // namespace vkt + +#endif // _VKTDESCRIPTORSETSINDEXINGTESTS_HPP diff --git a/external/vulkancts/modules/vulkan/descriptor_indexing/vktDescriptorSetsIndexingTestsUtils.cpp b/external/vulkancts/modules/vulkan/descriptor_indexing/vktDescriptorSetsIndexingTestsUtils.cpp new file mode 100644 index 0000000..b6b1765 --- /dev/null +++ b/external/vulkancts/modules/vulkan/descriptor_indexing/vktDescriptorSetsIndexingTestsUtils.cpp @@ -0,0 +1,765 @@ +/*------------------------------------------------------------------------ +* Vulkan Conformance Tests +* ------------------------ +* +* Copyright (c) 2019 The Khronos Group Inc. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* 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 Vulkan Decriptor Indexing Tests +*//*--------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include +#include + +#include "vktDescriptorSetsIndexingTests.hpp" + +#include "vkBuilderUtil.hpp" +#include "vkCmdUtil.hpp" +#include "vkDefs.hpp" +#include "vkObjUtil.hpp" +#include "vkPlatform.hpp" +#include "vkPrograms.hpp" +#include "vkQueryUtil.hpp" +#include "vkTypeUtil.hpp" + +#include "tcuTestLog.hpp" +#include "tcuResource.hpp" +#include "tcuImageCompare.hpp" +#include "tcuCommandLine.hpp" +#include "tcuStringTemplate.hpp" + +#include "deRandom.hpp" +#include "deMath.h" +#include "deStringUtil.hpp" + +namespace vkt +{ +namespace DescriptorIndexing +{ +using namespace vk; +namespace ut +{ + +ImageHandleAlloc::ImageHandleAlloc (Move& image_, + AllocMv& alloc_, + const VkExtent3D& extent_, + VkFormat format_, + VkImageLayout layout_, + bool usesMipMaps_) + : image (image_) + , alloc (alloc_) + , extent (extent_) + , format (format_) + , layout (layout_) + , levels (usesMipMaps_ ? computeMipMapCount(extent_) : 1) +{ +} + +std::string buildShaderName (VkShaderStageFlagBits stage, + VkDescriptorType descriptorType, + deBool updateAfterBind, + bool calculateInLoop, + bool performWritesInVertex) +{ + const char* stageName = DE_NULL; + switch (stage) + { + case VK_SHADER_STAGE_VERTEX_BIT: stageName = "vert"; break; + case VK_SHADER_STAGE_FRAGMENT_BIT: stageName = "frag"; break; + case VK_SHADER_STAGE_COMPUTE_BIT: stageName = "comp"; break; + case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: stageName = "tesc"; break; + case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: stageName = "tese"; break; + case VK_SHADER_STAGE_GEOMETRY_BIT: stageName = "geom"; break; + default: stageName = "any"; break; + } + DE_ASSERT(stageName); + + std::map m; + m["STAGE"] = stageName; + m["DESC"] = de::toString(deUint32(descriptorType)); + m["ABIND"] = updateAfterBind ? "_afterBind" : ""; + m["LOOP"] = calculateInLoop ? "_inLoop" : ""; + m["SHWR"] = performWritesInVertex ? "_shaderWrites" : ""; + + return tcu::StringTemplate("descriptorIndexing_${STAGE}${DESC}${ABIND}${LOOP}${SHWR}").specialize(m); +} + +std::vector generatePrimes (deUint32 limit) +{ + deUint32 i, j, *data; + std::vector v(limit); + + data = v.data(); + + for (i = 0; i < limit; ++i) + data[i] = i; + + for (i = 2; i < limit; ++i) + { + if (data[i]) + { + for (j = i*2; j < limit; j += i) + data[j] = 0; + } + } + + std::vector::iterator x = std::stable_partition(v.begin(), v.end(), std::bind2nd(std::greater_equal(), 2)); + + return std::vector(v.begin(), x); +} + +deUint32 computePrimeCount (deUint32 limit) +{ + deUint32 i, j, k, *data; + std::vector v(limit); + + data = v.data(); + + for (i = 0; i < limit; ++i) + data[i] = i; + + k = 0; + for (i = 2; i < limit; ++i) + { + if (data[i]) + { + ++k; + for (j = i*2; j < limit; j += i) + data[j] = 0; + } + } + return k; +} + +deUint32 computeMipMapCount (const VkExtent3D& extent) +{ + return deUint32(floor(log2(std::max(extent.width, extent.height)))) + 1; +} + +deUint32 computeImageSize (const VkExtent3D& extent, + VkFormat format, + bool withMipMaps, + deUint32 level) +{ + deUint32 mipSize = extent.width * extent.height * extent.depth * vk::mapVkFormat(format).getPixelSize(); + if (withMipMaps) + { + deUint32 mipIdx = 0u; + deUint32 width = extent.width; + deUint32 height = extent.height; + const deUint32 mipCount = computeMipMapCount(extent) - 1; + do + { + width /= 2; + height /= 2; + deUint32 tmpSize = width * height * extent.depth * vk::mapVkFormat(format).getPixelSize(); + + if (level == mipIdx) + { + break; + } + else if (level == maxDeUint32) + { + mipSize += tmpSize; + } + else + { + mipSize = tmpSize; + } + + } while (++mipIdx < mipCount); + } + return mipSize; +} + +deUint32 computeImageSize (const ImageHandleAllocSp& image) +{ + return computeImageSize(image->extent, image->format); +} + +void createImageAndBind (ut::ImageHandleAllocSp& output, + const vkt::Context& ctx, + VkFormat colorFormat, + const VkExtent3D& extent, + VkImageLayout initialLayout, + bool withMipMaps, + VkImageType imageType) +{ + const bool isDepthStencilFormat = vk::isDepthStencilFormat(colorFormat); + + const VkImageUsageFlags imageUsageFlagsDependent = isDepthStencilFormat + ? VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT + : VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + + const VkImageUsageFlags imageUsageFlags = imageUsageFlagsDependent + | VK_IMAGE_USAGE_TRANSFER_SRC_BIT + | VK_IMAGE_USAGE_TRANSFER_DST_BIT + | VK_IMAGE_USAGE_SAMPLED_BIT + | VK_IMAGE_USAGE_STORAGE_BIT + | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; + + const deUint32 mipLevels = withMipMaps ? computeMipMapCount(extent) : 1; + const VkImageCreateInfo createInfo = + { + VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // sType + DE_NULL, // pNext + (VkImageCreateFlags)0, // flags + imageType, // imageType + colorFormat, // format + extent, // extent + mipLevels, // mipLevels + (deUint32)1, // arrayLayers + VK_SAMPLE_COUNT_1_BIT, // samples + VK_IMAGE_TILING_OPTIMAL, // tiling + imageUsageFlags, // usage + VK_SHARING_MODE_EXCLUSIVE, // sharingMode + (deUint32)0, // queueFamilyCount + DE_NULL, // pQueueFamilyIndices + initialLayout // initialLayout + }; + + Allocator& allocator = ctx.getDefaultAllocator(); + VkDevice device = ctx.getDevice(); + const DeviceInterface& dinterface = ctx.getDeviceInterface(); + + Move image = vk::createImage(dinterface, device, &createInfo); + + const VkMemoryRequirements memReqs = vk::getImageMemoryRequirements(dinterface, device, *image); + de::MovePtr allocation = allocator.allocate(memReqs, MemoryRequirement::Any); + + VK_CHECK(dinterface.bindImageMemory(device, *image, allocation->getMemory(), allocation->getOffset())); + + output = ImageHandleAllocSp(new ImageHandleAlloc(image, allocation, extent, colorFormat, initialLayout, withMipMaps)); +} + +void recordCopyBufferToImage (VkCommandBuffer cmd, + const DeviceInterface& interface, + VkPipelineStageFlagBits srcStageMask, + VkPipelineStageFlagBits dstStageMask, + const VkDescriptorBufferInfo& bufferInfo, + VkImage image, + const VkExtent3D& imageExtent, + VkFormat imageFormat, + VkImageLayout oldImageLayout, + VkImageLayout newImageLayout, + deUint32 mipLevelCount) +{ + const VkImageAspectFlags imageAspect = vk::isDepthStencilFormat(imageFormat) + ? VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT + : VK_IMAGE_ASPECT_COLOR_BIT; + + std::vector copyRegions; + { + deUint32 width = imageExtent.width; + deUint32 height = imageExtent.height; + VkDeviceSize bufferOffset = bufferInfo.offset; + + for (deUint32 mipIdx = 0; mipIdx < mipLevelCount; ++mipIdx) + { + VkDeviceSize imageSize = computeImageSize(imageExtent, imageFormat, true, mipIdx); + + const VkBufferImageCopy copyRegion = + { + bufferOffset, // bufferOffset + width, // bufferRowLength + height, // bufferImageHeight + { + imageAspect, // aspect + mipIdx, // mipLevel + 0u, // baseArrayLayer + 1u, // layerCount + }, // VkImageSubresourceLayers imageSubresource + { 0,0,0 }, // VkOffset3D imageOffset + { width, height, 1 } // VkExtent3D imageExtent + }; + + copyRegions.push_back(copyRegion); + + bufferOffset += imageSize; + width /= 2; + height /= 2; + } + } + + const VkImageSubresourceRange subresourceRange = + { + imageAspect, // aspectMask + 0u, // baseMipLevel + mipLevelCount, // levelCount + 0u, // baseArrayLayer + 1u, // layerCount + }; + + const VkImageMemoryBarrier transitionBarrier = + { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType; + DE_NULL, // pNext; + 0, // srcAccessMask; + VK_ACCESS_TRANSFER_WRITE_BIT, // dstAccessMask; + oldImageLayout, // oldLayout; + newImageLayout, // newLayout; + VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex; + VK_QUEUE_FAMILY_IGNORED, // dstQueueFamilyIndex; + image, // image + subresourceRange // subresourceRange + }; + + const VkBufferMemoryBarrier bufferBarrier = + { + VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // sType; + DE_NULL, // pNext; + pipelineAcceesFromStage(srcStageMask, false), // srcAccessMask; + VK_ACCESS_TRANSFER_READ_BIT, // dstAccessMask; + VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex; + VK_QUEUE_FAMILY_IGNORED, // dstQueueFamilyIndex; + bufferInfo.buffer, // buffer; + bufferInfo.offset, // offset; + bufferInfo.range // size; + }; + + const VkImageMemoryBarrier imageBarrier = + { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType; + DE_NULL, // pNext; + VK_ACCESS_TRANSFER_WRITE_BIT, // srcAccessMask; + pipelineAcceesFromStage(dstStageMask, true) + | pipelineAcceesFromStage(dstStageMask, false), // dstAccessMask; + oldImageLayout, // oldLayout; + newImageLayout, // newLayout; + VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex; + VK_QUEUE_FAMILY_IGNORED, // dstQueueFamilyIndex; + image, // image + subresourceRange // subresourceRange + }; + + interface.cmdPipelineBarrier(cmd, + srcStageMask, VK_PIPELINE_STAGE_TRANSFER_BIT, // srcStageMask, dstStageMask + (VkDependencyFlags)0, // dependencyFlags + 0u, (const VkMemoryBarrier*)DE_NULL, // memoryBarrierCount, pMemoryBarriers + 1u, &bufferBarrier, // bufferBarrierCount, pBufferBarriers + 1u, &transitionBarrier); // imageBarrierCount, pImageBarriers + + interface.cmdCopyBufferToImage(cmd, bufferInfo.buffer, image, newImageLayout, static_cast(copyRegions.size()), copyRegions.data()); + + interface.cmdPipelineBarrier(cmd, + VK_PIPELINE_STAGE_TRANSFER_BIT, dstStageMask, // srcStageMask, dstStageMask + (VkDependencyFlags)0, // dependencyFlags + 0u, (const VkMemoryBarrier*)DE_NULL, // memoryBarrierCount, pMemoryBarriers + 0u, (const VkBufferMemoryBarrier*)DE_NULL, // bufferBarrierCount, pBufferBarriers + 1u, &imageBarrier); // imageBarrierCount, pImageBarriers +} + +void recordCopyImageToBuffer (VkCommandBuffer cmd, + const DeviceInterface& interface, + VkPipelineStageFlagBits srcStageMask, + VkPipelineStageFlagBits dstStageMask, + VkImage image, + const VkExtent3D& imageExtent, + VkFormat imageFormat, + VkImageLayout oldImageLayout, + VkImageLayout newImageLayout, + const VkDescriptorBufferInfo& bufferInfo) +{ + const VkImageAspectFlags imageAspect = vk::isDepthStencilFormat(imageFormat) + ? VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT + : VK_IMAGE_ASPECT_COLOR_BIT; + + const VkBufferImageCopy copyRegion = + { + bufferInfo.offset, // bufferOffset + imageExtent.width, // bufferRowLength + imageExtent.height, // bufferImageHeight + { + imageAspect, // aspect + 0u, // mipLevel + 0u, // baseArrayLayer + 1u, // layerCount + }, // VkImageSubresourceLayers + { 0, 0, 0 }, // imageOffset + imageExtent // imageExtent + }; + + VkImageSubresourceRange subresourceRange = + { + VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask + 0u, // baseMipLevel + 1u, // levelCount + 0u, // baseArrayLayer + 1u, // layerCount + }; + + const VkImageMemoryBarrier imageBarrier = + { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType; + DE_NULL, // pNext; + pipelineAcceesFromStage(srcStageMask, false), // srcAccessMask; + VK_ACCESS_TRANSFER_READ_BIT, // dstAccessMask; + oldImageLayout, // oldLayout + newImageLayout, // newLayout; + VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex; + VK_QUEUE_FAMILY_IGNORED, // dstQueueFamilyIndex; + image, // image; + subresourceRange, // subresourceRange; + }; + + const VkBufferMemoryBarrier bufferBarrier = + { + VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // sType; + DE_NULL, // pNext; + VK_ACCESS_TRANSFER_WRITE_BIT, // srcAccessMask; + pipelineAcceesFromStage(dstStageMask, true), // dstAccessMask; + VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex; + VK_QUEUE_FAMILY_IGNORED, // dstQueueFamilyIndex; + bufferInfo.buffer, // buffer; + bufferInfo.offset, // offset; + bufferInfo.range // size; + }; + + interface.cmdPipelineBarrier(cmd, // commandBuffer + srcStageMask, VK_PIPELINE_STAGE_TRANSFER_BIT, // srcStageMask, dstStageMask + (VkDependencyFlags)0, // dependencyFlags + 0u, (const VkMemoryBarrier*)DE_NULL, // memoryBarrierCount, pMemoryBarriers + 0u, (const VkBufferMemoryBarrier*)DE_NULL, // bufferBarrierCount, pBufferBarriers + 1u, &imageBarrier); // imageBarrierCount, pImageBarriers + + interface.cmdCopyImageToBuffer(cmd, image, newImageLayout, bufferInfo.buffer, 1u, ©Region); + + interface.cmdPipelineBarrier(cmd, + VK_PIPELINE_STAGE_TRANSFER_BIT, dstStageMask, + (VkDependencyFlags)0, + 0, DE_NULL, + 1, &bufferBarrier, + 0u, DE_NULL); +} + +VkAccessFlags pipelineAcceesFromStage (VkPipelineStageFlagBits stage, bool readORwrite) +{ + VkAccessFlags access[2]; + VkAccessFlags& readAccess = access[1]; + VkAccessFlags& writeAccess = access[0]; + readAccess = writeAccess = static_cast(0); + + switch (stage) + { + case VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT: + case VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT: + readAccess = VK_ACCESS_INDIRECT_COMMAND_READ_BIT; + break; + + case VK_PIPELINE_STAGE_VERTEX_INPUT_BIT: + readAccess = static_cast(VK_ACCESS_INDEX_READ_BIT | VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT); + break; + + case VK_PIPELINE_STAGE_VERTEX_SHADER_BIT: + case VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT: + case VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT: + case VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT: + case VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT: + readAccess = VK_ACCESS_SHADER_READ_BIT; + writeAccess = VK_ACCESS_SHADER_WRITE_BIT; + break; + + case VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT: + readAccess = static_cast(VK_ACCESS_UNIFORM_READ_BIT | VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT); + writeAccess = VK_ACCESS_SHADER_READ_BIT;; + break; + + case VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT: + readAccess = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT; + writeAccess = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + break; + + case VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT: + case VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT: + readAccess = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; + writeAccess = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + break; + + case VK_PIPELINE_STAGE_TRANSFER_BIT: + readAccess = VK_ACCESS_TRANSFER_READ_BIT; + writeAccess = VK_ACCESS_TRANSFER_WRITE_BIT; + break; + + case VK_PIPELINE_STAGE_HOST_BIT: + readAccess = VK_ACCESS_HOST_READ_BIT; + writeAccess = VK_ACCESS_HOST_WRITE_BIT; + break; + + default: + if (stage == 0) + { + readAccess = VK_ACCESS_MEMORY_READ_BIT; + writeAccess = VK_ACCESS_MEMORY_WRITE_BIT; + break; + } + + DE_ASSERT(DE_FALSE); + } + return access[readORwrite ? 1 : 0]; +} + +void createFrameBuffer (FrameBufferSp& outputFB, + const vkt::Context& context, + const VkExtent3D& extent, + VkFormat colorFormat, + VkRenderPass renderpass, + deUint32 additionalAttachmentCount, + const VkImageView additionalAttachments[]) +{ + outputFB = FrameBufferSp(new ut::FrameBuffer); + VkDevice device = context.getDevice(); + const DeviceInterface& interface = context.getDeviceInterface(); + createImageAndBind(outputFB->image, context, colorFormat, extent, VK_IMAGE_LAYOUT_UNDEFINED); + + // create and attachment0 + { + const VkImageViewCreateInfo viewCreateInfo = + { + VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // sType + DE_NULL, // pNext + (VkImageViewCreateFlags)0, // flags + *outputFB->image->image, // image + VK_IMAGE_VIEW_TYPE_2D, // viewType + colorFormat, // format + vk::makeComponentMappingRGBA(), // components + { + VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask + (deUint32)0, // baseMipLevel + (deUint32)1, // mipLevels + (deUint32)0, // baseArrayLayer + (deUint32)1u, // arraySize + }, + }; + + outputFB->attachment0 = vk::createImageView(interface, device, &viewCreateInfo); + + std::vector& attachments(outputFB->attachments); + attachments.push_back(*outputFB->attachment0); + if (additionalAttachments && additionalAttachmentCount) + { + attachments.insert(attachments.end(), additionalAttachments, additionalAttachments + additionalAttachmentCount); + } + } + + // create a frame buffer + { + std::vector& attachments(outputFB->attachments); + + const VkFramebufferCreateInfo framebufferCreateInfo = + { + VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // sType + DE_NULL, // pNext + (VkFramebufferCreateFlags)0, // flags + renderpass, // renderPass + static_cast(attachments.size()), // attachmentCount + attachments.data(), // pAttachments + extent.width, // width + extent.height, // height + (deUint32)1 // layers + }; + + outputFB->buffer = vk::createFramebuffer(interface, device, &framebufferCreateInfo); + } +} + +VkDeviceSize createBufferAndBind (ut::BufferHandleAllocSp& output, + const vkt::Context& ctx, + VkBufferUsageFlags usage, + VkDeviceSize desiredSize) +{ + const size_t nonCoherentAtomSize (static_cast(ctx.getDeviceProperties().limits.nonCoherentAtomSize)); + const VkDeviceSize roundedSize (deAlignSize(static_cast(desiredSize), nonCoherentAtomSize)); + Allocator& allocator (ctx.getDefaultAllocator()); + VkDevice device (ctx.getDevice()); + const DeviceInterface& interface (ctx.getDeviceInterface()); + + const VkBufferCreateInfo createInfo = + { + VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // sType + DE_NULL, // pNext + (VkBufferCreateFlags)0, // flags + roundedSize, // size + usage, // usage + VK_SHARING_MODE_EXCLUSIVE, // sharingMode + 0u, // queueFamilyIndexCount + DE_NULL, // pQueueFamilyIndices + }; + + Move buffer = vk::createBuffer(interface, device, &createInfo); + + const VkMemoryRequirements memRequirements = vk::getBufferMemoryRequirements(interface, device, *buffer); + de::MovePtr allocation = allocator.allocate(memRequirements, MemoryRequirement::HostVisible); + + VK_CHECK(interface.bindBufferMemory(device, *buffer, allocation->getMemory(), allocation->getOffset())); + + output = BufferHandleAllocSp(new BufferHandleAlloc(buffer, allocation)); + + return roundedSize; +} + +std::vector createVertices (deUint32 width, deUint32 height, float& xSize, float& ySize) +{ + std::vector result; + + const float xStep = 2.0f / static_cast(width); + const float yStep = 2.0f / static_cast(height); + const float xStart = -1.0f + xStep / 2.0f; + const float yStart = -1.0f + yStep / 2.0f; + + xSize = xStep; + ySize = yStep; + + float x = xStart; + float y = yStart; + + result.reserve(width * height); + + for (deUint32 row = 0u; row < height; ++row) + { + for (deUint32 col = 0u; col < width; ++col) + { + result.push_back(tcu::Vec4(x, y, 1.0f, 1.0f)); + x += xStep; + } + + y += yStep; + x = xStart; + } + + return result; +} + +bool isDynamicDescriptor (VkDescriptorType descriptorType) +{ + return descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC || descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC; +} + +DeviceProperties::DeviceProperties (const DeviceProperties& src) +{ + m_descriptorIndexingFeatures = src.m_descriptorIndexingFeatures; + m_features2 = src.m_features2; + + m_descriptorIndexingProperties = src.m_descriptorIndexingProperties; + m_properties2 = src.m_properties2; +} + +DeviceProperties::DeviceProperties (const vkt::Context& testContext) +{ + VkPhysicalDevice device = testContext.getPhysicalDevice(); + const InstanceInterface& interface = testContext.getInstanceInterface(); + + deMemset(&m_descriptorIndexingFeatures, 0, sizeof(m_descriptorIndexingFeatures)); + m_descriptorIndexingFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT; + m_descriptorIndexingFeatures.pNext = DE_NULL; + + deMemset(&m_features2, 0, sizeof(m_features2)); + m_features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; + m_features2.pNext = &m_descriptorIndexingFeatures; + + interface.getPhysicalDeviceFeatures2(device, &m_features2); + + deMemset(&m_descriptorIndexingProperties, 0, sizeof(m_descriptorIndexingProperties)); + m_descriptorIndexingProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES_EXT; + m_descriptorIndexingProperties.pNext = DE_NULL; + + deMemset(&m_properties2, 0, sizeof(m_properties2)); + m_properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; + m_properties2.pNext = &m_descriptorIndexingProperties; + + interface.getPhysicalDeviceProperties2(device, &m_properties2); +} + +deUint32 DeviceProperties::computeMaxPerStageDescriptorCount (VkDescriptorType descriptorType, + bool enableUpdateAfterBind) const +{ + const VkPhysicalDeviceDescriptorIndexingPropertiesEXT& descriptorProps = descriptorIndexingProperties(); + const VkPhysicalDeviceProperties& deviceProps = physicalDeviceProperties(); + + deUint32 result = 0; + deUint32 samplers = 0; + deUint32 uniformBuffers = 0; + deUint32 uniformBuffersDynamic = 0; + deUint32 storageBuffers = 0; + deUint32 storageBuffersDynamic = 0; + deUint32 sampledImages = 0; + deUint32 storageImages = 0; + deUint32 inputAttachments = 0; + deUint32 inlineUniforms = 0; + const deUint32 resources = deviceProps.limits.maxPerStageResources; + + if (enableUpdateAfterBind) + { + samplers = deMinu32( descriptorProps.maxPerStageDescriptorUpdateAfterBindSamplers, descriptorProps.maxDescriptorSetUpdateAfterBindSamplers); // 1048576 + uniformBuffers = deMinu32( descriptorProps.maxPerStageDescriptorUpdateAfterBindUniformBuffers, descriptorProps.maxDescriptorSetUpdateAfterBindUniformBuffers); // 15 + uniformBuffersDynamic = deMinu32( descriptorProps.maxPerStageDescriptorUpdateAfterBindUniformBuffers, descriptorProps.maxDescriptorSetUpdateAfterBindUniformBuffersDynamic); // 8 + storageBuffers = deMinu32( descriptorProps.maxPerStageDescriptorUpdateAfterBindStorageBuffers, descriptorProps.maxDescriptorSetUpdateAfterBindStorageBuffers); // 1048576 + storageBuffersDynamic = deMinu32( descriptorProps.maxPerStageDescriptorUpdateAfterBindStorageBuffers, descriptorProps.maxDescriptorSetUpdateAfterBindStorageBuffersDynamic); // 8 + sampledImages = deMinu32( descriptorProps.maxPerStageDescriptorUpdateAfterBindSampledImages, descriptorProps.maxDescriptorSetUpdateAfterBindSampledImages); // 1048576 + storageImages = deMinu32( descriptorProps.maxPerStageDescriptorUpdateAfterBindStorageImages, descriptorProps.maxDescriptorSetUpdateAfterBindStorageImages); // 1048576 + inputAttachments = deMinu32( descriptorProps.maxPerStageDescriptorUpdateAfterBindInputAttachments, descriptorProps.maxDescriptorSetUpdateAfterBindInputAttachments); // 1048576 + } + else + { + samplers = deMinu32( deviceProps.limits.maxPerStageDescriptorSamplers, deviceProps.limits.maxDescriptorSetSamplers); // 1048576 + uniformBuffers = deMinu32( deviceProps.limits.maxPerStageDescriptorUniformBuffers, deviceProps.limits.maxDescriptorSetUniformBuffers); // 15 + uniformBuffersDynamic = deMinu32( deviceProps.limits.maxPerStageDescriptorUniformBuffers, deviceProps.limits.maxDescriptorSetUniformBuffersDynamic); // 8 + storageBuffers = deMinu32( deviceProps.limits.maxPerStageDescriptorStorageBuffers, deviceProps.limits.maxDescriptorSetStorageBuffers); // 1048576 + storageBuffersDynamic = deMinu32( deviceProps.limits.maxPerStageDescriptorStorageBuffers, deviceProps.limits.maxDescriptorSetStorageBuffersDynamic); // 8 + sampledImages = deMinu32( deviceProps.limits.maxPerStageDescriptorSampledImages-1, deviceProps.limits.maxDescriptorSetSampledImages-1); // 1048576. -1 because during in_loop tests a single texel buffer is created and is calculated against this limit + storageImages = deMinu32( deviceProps.limits.maxPerStageDescriptorStorageImages, deviceProps.limits.maxDescriptorSetStorageImages); // 1048576 + inputAttachments = deMinu32( deviceProps.limits.maxPerStageDescriptorInputAttachments, deviceProps.limits.maxDescriptorSetInputAttachments); // 1048576 + } + + // adding arbitrary upper bound limits to restrain the size of the test ( we are testing big arrays, not the maximum size arrays ) + samplers = deMinu32( samplers, 4096); + uniformBuffers = deMinu32( uniformBuffers, 16); + uniformBuffersDynamic = deMinu32( uniformBuffersDynamic, 16); + storageBuffers = deMinu32( storageBuffers, 8192); + storageBuffersDynamic = deMinu32( storageBuffersDynamic, 8192); + sampledImages = deMinu32( sampledImages, 8192); + storageImages = deMinu32( storageImages, 8192); + inputAttachments = deMinu32( inputAttachments, 16); + + switch (descriptorType) + { + case VK_DESCRIPTOR_TYPE_SAMPLER: result = samplers; break; + case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: result = deMinu32(resources, deMinu32(samplers, sampledImages)); break; + case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: result = deMinu32(resources, sampledImages); break; + case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: result = deMinu32(resources, storageImages); break; + case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: result = deMinu32(resources, sampledImages); break; + case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: result = deMinu32(resources, storageImages); break; + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: result = deMinu32(resources, uniformBuffers); break; + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: result = deMinu32(resources, storageBuffers); break; + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: result = deMinu32(resources, uniformBuffersDynamic); break; + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: result = deMinu32(resources, storageBuffersDynamic); break; + case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: result = deMinu32(resources, inputAttachments); break; + case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT: result = deMinu32(resources, inlineUniforms); break; + default: DE_ASSERT(0); + } + + DE_ASSERT(result); + + return result; +} + +} // - namespace ut +} // - namespace DescriptorIndexing +} // - namespace vkt diff --git a/external/vulkancts/modules/vulkan/vktTestPackage.cpp b/external/vulkancts/modules/vulkan/vktTestPackage.cpp index 61b0365..521798a 100644 --- a/external/vulkancts/modules/vulkan/vktTestPackage.cpp +++ b/external/vulkancts/modules/vulkan/vktTestPackage.cpp @@ -92,6 +92,7 @@ #include "vktAmberGraphicsFuzzTests.hpp" #include "vktImagelessFramebufferTests.hpp" #include "vktTransformFeedbackTests.hpp" +#include "vktDescriptorIndexingTests.hpp" #include #include @@ -516,6 +517,7 @@ void TestPackage::init (void) addChild(cts_amber::createGraphicsFuzzTests (m_testCtx)); addChild(imageless::createTests (m_testCtx)); addChild(TransformFeedback::createTests (m_testCtx)); + addChild(DescriptorIndexing::createTests (m_testCtx)); } } // vkt diff --git a/external/vulkancts/mustpass/master/vk-default-no-waivers.txt b/external/vulkancts/mustpass/master/vk-default-no-waivers.txt index 47ef51d..3bfd791 100644 --- a/external/vulkancts/mustpass/master/vk-default-no-waivers.txt +++ b/external/vulkancts/mustpass/master/vk-default-no-waivers.txt @@ -419989,3 +419989,51 @@ dEQP-VK.transform_feedback.fuzz.random_geometry.all_unordered_and_missing.96 dEQP-VK.transform_feedback.fuzz.random_geometry.all_unordered_and_missing.97 dEQP-VK.transform_feedback.fuzz.random_geometry.all_unordered_and_missing.98 dEQP-VK.transform_feedback.fuzz.random_geometry.all_unordered_and_missing.99 +dEQP-VK.descriptor_indexing.storage_buffer +dEQP-VK.descriptor_indexing.storage_texel_buffer +dEQP-VK.descriptor_indexing.uniform_texel_buffer +dEQP-VK.descriptor_indexing.storage_image +dEQP-VK.descriptor_indexing.storage_buffer_in_loop +dEQP-VK.descriptor_indexing.storage_texel_buffer_in_loop +dEQP-VK.descriptor_indexing.uniform_texel_buffer_in_loop +dEQP-VK.descriptor_indexing.storage_image_in_loop +dEQP-VK.descriptor_indexing.storage_buffer_after_bind +dEQP-VK.descriptor_indexing.storage_texel_buffer_after_bind +dEQP-VK.descriptor_indexing.uniform_texel_buffer_after_bind +dEQP-VK.descriptor_indexing.storage_image_after_bind +dEQP-VK.descriptor_indexing.storage_buffer_after_bind_in_loop +dEQP-VK.descriptor_indexing.storage_texel_buffer_after_bind_in_loop +dEQP-VK.descriptor_indexing.uniform_texel_buffer_after_bind_in_loop +dEQP-VK.descriptor_indexing.storage_image_after_bind_in_loop +dEQP-VK.descriptor_indexing.sampler +dEQP-VK.descriptor_indexing.sampled_image +dEQP-VK.descriptor_indexing.combined_image_sampler +dEQP-VK.descriptor_indexing.sampler_with_lod +dEQP-VK.descriptor_indexing.sampled_image_with_lod +dEQP-VK.descriptor_indexing.combined_image_sampler_with_lod +dEQP-VK.descriptor_indexing.sampler_in_loop +dEQP-VK.descriptor_indexing.sampled_image_in_loop +dEQP-VK.descriptor_indexing.combined_image_sampler_in_loop +dEQP-VK.descriptor_indexing.sampler_in_loop_with_lod +dEQP-VK.descriptor_indexing.sampled_image_in_loop_with_lod +dEQP-VK.descriptor_indexing.combined_image_sampler_in_loop_with_lod +dEQP-VK.descriptor_indexing.sampler_after_bind +dEQP-VK.descriptor_indexing.sampled_image_after_bind +dEQP-VK.descriptor_indexing.combined_image_sampler_after_bind +dEQP-VK.descriptor_indexing.sampler_after_bind_with_lod +dEQP-VK.descriptor_indexing.sampled_image_after_bind_with_lod +dEQP-VK.descriptor_indexing.combined_image_sampler_after_bind_with_lod +dEQP-VK.descriptor_indexing.sampler_after_bind_in_loop +dEQP-VK.descriptor_indexing.sampled_image_after_bind_in_loop +dEQP-VK.descriptor_indexing.combined_image_sampler_after_bind_in_loop +dEQP-VK.descriptor_indexing.sampler_after_bind_in_loop_with_lod +dEQP-VK.descriptor_indexing.sampled_image_after_bind_in_loop_with_lod +dEQP-VK.descriptor_indexing.combined_image_sampler_after_bind_in_loop_with_lod +dEQP-VK.descriptor_indexing.uniform_buffer +dEQP-VK.descriptor_indexing.storage_buffer_dynamic +dEQP-VK.descriptor_indexing.uniform_buffer_dynamic +dEQP-VK.descriptor_indexing.input_attachment +dEQP-VK.descriptor_indexing.uniform_buffer_in_loop +dEQP-VK.descriptor_indexing.storage_buffer_dynamic_in_loop +dEQP-VK.descriptor_indexing.uniform_buffer_dynamic_in_loop +dEQP-VK.descriptor_indexing.input_attachment_in_loop diff --git a/external/vulkancts/mustpass/master/vk-default.txt b/external/vulkancts/mustpass/master/vk-default.txt index 29f069f..8903371 100644 --- a/external/vulkancts/mustpass/master/vk-default.txt +++ b/external/vulkancts/mustpass/master/vk-default.txt @@ -419950,3 +419950,51 @@ dEQP-VK.transform_feedback.fuzz.random_geometry.all_unordered_and_missing.96 dEQP-VK.transform_feedback.fuzz.random_geometry.all_unordered_and_missing.97 dEQP-VK.transform_feedback.fuzz.random_geometry.all_unordered_and_missing.98 dEQP-VK.transform_feedback.fuzz.random_geometry.all_unordered_and_missing.99 +dEQP-VK.descriptor_indexing.storage_buffer +dEQP-VK.descriptor_indexing.storage_texel_buffer +dEQP-VK.descriptor_indexing.uniform_texel_buffer +dEQP-VK.descriptor_indexing.storage_image +dEQP-VK.descriptor_indexing.storage_buffer_in_loop +dEQP-VK.descriptor_indexing.storage_texel_buffer_in_loop +dEQP-VK.descriptor_indexing.uniform_texel_buffer_in_loop +dEQP-VK.descriptor_indexing.storage_image_in_loop +dEQP-VK.descriptor_indexing.storage_buffer_after_bind +dEQP-VK.descriptor_indexing.storage_texel_buffer_after_bind +dEQP-VK.descriptor_indexing.uniform_texel_buffer_after_bind +dEQP-VK.descriptor_indexing.storage_image_after_bind +dEQP-VK.descriptor_indexing.storage_buffer_after_bind_in_loop +dEQP-VK.descriptor_indexing.storage_texel_buffer_after_bind_in_loop +dEQP-VK.descriptor_indexing.uniform_texel_buffer_after_bind_in_loop +dEQP-VK.descriptor_indexing.storage_image_after_bind_in_loop +dEQP-VK.descriptor_indexing.sampler +dEQP-VK.descriptor_indexing.sampled_image +dEQP-VK.descriptor_indexing.combined_image_sampler +dEQP-VK.descriptor_indexing.sampler_with_lod +dEQP-VK.descriptor_indexing.sampled_image_with_lod +dEQP-VK.descriptor_indexing.combined_image_sampler_with_lod +dEQP-VK.descriptor_indexing.sampler_in_loop +dEQP-VK.descriptor_indexing.sampled_image_in_loop +dEQP-VK.descriptor_indexing.combined_image_sampler_in_loop +dEQP-VK.descriptor_indexing.sampler_in_loop_with_lod +dEQP-VK.descriptor_indexing.sampled_image_in_loop_with_lod +dEQP-VK.descriptor_indexing.combined_image_sampler_in_loop_with_lod +dEQP-VK.descriptor_indexing.sampler_after_bind +dEQP-VK.descriptor_indexing.sampled_image_after_bind +dEQP-VK.descriptor_indexing.combined_image_sampler_after_bind +dEQP-VK.descriptor_indexing.sampler_after_bind_with_lod +dEQP-VK.descriptor_indexing.sampled_image_after_bind_with_lod +dEQP-VK.descriptor_indexing.combined_image_sampler_after_bind_with_lod +dEQP-VK.descriptor_indexing.sampler_after_bind_in_loop +dEQP-VK.descriptor_indexing.sampled_image_after_bind_in_loop +dEQP-VK.descriptor_indexing.combined_image_sampler_after_bind_in_loop +dEQP-VK.descriptor_indexing.sampler_after_bind_in_loop_with_lod +dEQP-VK.descriptor_indexing.sampled_image_after_bind_in_loop_with_lod +dEQP-VK.descriptor_indexing.combined_image_sampler_after_bind_in_loop_with_lod +dEQP-VK.descriptor_indexing.uniform_buffer +dEQP-VK.descriptor_indexing.storage_buffer_dynamic +dEQP-VK.descriptor_indexing.uniform_buffer_dynamic +dEQP-VK.descriptor_indexing.input_attachment +dEQP-VK.descriptor_indexing.uniform_buffer_in_loop +dEQP-VK.descriptor_indexing.storage_buffer_dynamic_in_loop +dEQP-VK.descriptor_indexing.uniform_buffer_dynamic_in_loop +dEQP-VK.descriptor_indexing.input_attachment_in_loop -- 2.7.4