| /*------------------------------------------------------------------------ |
| * 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 <algorithm> |
| #include <iostream> |
| #include <iterator> |
| #include <functional> |
| #include <sstream> |
| #include <utility> |
| #include <vector> |
| |
| #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<deUint32 BindingNumber> |
| struct Binding |
| { |
| static const deUint32 binding = BindingNumber; |
| }; |
| |
| struct BindingUniformBuffer : Binding<BINDING_UniformBuffer> |
| { |
| typedef struct |
| { |
| tcu::Vec4 c; |
| } Data; |
| }; |
| |
| struct BindingStorageBuffer : Binding<BINDING_StorageBuffer> |
| { |
| 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<VkDescriptorSetLayout> descriptorSetLayout; |
| Move<VkDescriptorPool> descriptorPool; |
| Move<VkDescriptorSet> 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<VkDescriptorBufferInfo> descriptorsBufferInfos; |
| std::vector<ut::BufferViewSp> descriptorsBufferViews; |
| std::vector<ut::ImageViewSp> descriptorImageViews; |
| std::vector<ut::SamplerSp> descriptorSamplers; |
| std::vector<ut::ImageHandleAllocSp> descriptorsImages; |
| ut::FrameBufferSp frameBuffer; |
| |
| Move<VkDescriptorSetLayout> descriptorSetLayout; |
| Move<VkDescriptorPool> descriptorPool; |
| Move<VkDescriptorSet> descriptorSet; |
| Move<VkPipelineLayout> pipelineLayout; |
| Move<VkRenderPass> renderPass; |
| Move<VkPipeline> pipeline; |
| Move<VkCommandBuffer> commandBuffer; |
| }; |
| |
| class CommonDescriptorInstance : public TestInstance |
| { |
| public: |
| CommonDescriptorInstance (Context& context, |
| const TestParams& testParams); |
| |
| deUint32 computeAvailableDescriptorCount (VkDescriptorType descriptorType, |
| bool reserveUniformTexelBuffer) const; |
| |
| Move<VkDescriptorSetLayout> createDescriptorSetLayout (bool reserveUniformTexelBuffer, |
| deUint32& descriptorCount) const; |
| |
| Move<VkDescriptorPool> createDescriptorPool (deUint32 descriptorCount) const; |
| |
| Move<VkDescriptorSet> 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 bool performWritesInVertex (VkDescriptorType descriptorType, |
| const Context& context); |
| 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<VkRenderPass> createRenderPass (const IterateCommonVariables& variables); |
| |
| struct push_constant |
| { |
| deInt32 lowerBound; |
| deInt32 upperBound; |
| }; |
| VkPushConstantRange makePushConstantRange (void) const; |
| |
| Move<VkPipelineLayout> createPipelineLayout (const std::vector<VkDescriptorSetLayout>& 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<VkPipeline> 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<VkDescriptorBufferInfo>& 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<ut::ImageHandleAllocSp>& images, |
| std::vector<VkDescriptorBufferInfo>& bufferInfos, |
| ut::BufferHandleAllocSp& buffer, |
| VkBufferUsageFlags bufferUsage, |
| const VkExtent3D& imageExtent, |
| VkFormat imageFormat, |
| VkImageLayout imageLayout, |
| deUint32 imageCount, |
| bool withMipMaps = false); |
| |
| void createBuffersViews (std::vector<ut::BufferViewSp>& views, |
| const std::vector<VkDescriptorBufferInfo>& bufferInfos, |
| VkFormat format); |
| |
| void createImagesViews (std::vector<ut::ImageViewSp>& views, |
| const std::vector<ut::ImageHandleAllocSp>& 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<VkDescriptorBufferInfo>& 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 iterateCommandSetup (IterateCommonVariables& variables); |
| |
| void iterateCommandBegin (IterateCommonVariables& variables, |
| bool firstPass = true); |
| |
| void iterateCommandEnd (IterateCommonVariables& variables, |
| ut::UpdatablePixelBufferAccessPtr& programResult, |
| ut::UpdatablePixelBufferAccessPtr& referenceResult, |
| bool collectBeforeSubmit = true); |
| |
| bool iterateVerifyResults (IterateCommonVariables& variables, |
| ut::UpdatablePixelBufferAccessPtr programResult, |
| ut::UpdatablePixelBufferAccessPtr referenceResult); |
| |
| Move<VkCommandBuffer> 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<VkFence> 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<VkCommandPool> m_commandPool; |
| const VkFormat m_colorFormat; |
| const TestParams m_testParams; |
| static const tcu::Vec4 m_clearColor; |
| const std::vector<float> m_colorScheme; |
| const deUint32 m_schemeSize; |
| |
| private: |
| |
| Move<VkPipeline> createGraphicsPipeline (VkPipelineLayout pipelineLayout, |
| VkRenderPass renderPass); |
| |
| Move<VkPipeline> createComputePipeline (VkPipelineLayout pipelineLayout); |
| |
| int constructShaderModules (void); |
| |
| static std::vector<float> createColorScheme(); |
| |
| Move<VkShaderModule> m_vertexModule; |
| Move<VkShaderModule> m_fragmentModule; |
| Move<VkShaderModule> 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<imageFormat>::type pixelType; |
| const VkDeviceSize dataSize = vertexCount * sizeof(pixelType); |
| const std::vector<deUint32> primes = ut::generatePrimes(availableDescriptorCount); |
| const deUint32 primeCount = static_cast<deUint32>(primes.size()); |
| |
| std::vector<pixelType> 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<pixelType::Element>(primes[idx % primeCount]); |
| data[idx].y() = static_cast<pixelType::Element>(idx); |
| } |
| |
| bufferSize = ut::createBufferAndBind(buffer, context, VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, dataSize); |
| deMemcpy(buffer->alloc->getHostPtr(), data.data(), static_cast<size_t>(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<VkBufferView>(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<deUint32>(m_colorScheme.size())) |
| { |
| } |
| |
| deUint32 CommonDescriptorInstance::computeAvailableDescriptorCount (VkDescriptorType descriptorType, |
| bool reserveUniformTexelBuffer) 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, reserveUniformTexelBuffer); |
| return deMinu32(deMinu32(vertexCount, availableDescriptorsOnDevice), MAX_DESCRIPTORS); |
| } |
| |
| Move<VkDescriptorSetLayout> CommonDescriptorInstance::createDescriptorSetLayout (bool reserveUniformTexelBuffer, |
| deUint32& descriptorCount) const |
| { |
| descriptorCount = computeAvailableDescriptorCount(m_testParams.descriptorType, reserveUniformTexelBuffer); |
| |
| 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 VkDescriptorBindingFlags bindingFlagUpdateAfterBind = |
| m_testParams.updateAfterBind ? VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT : 0; |
| |
| const VkDescriptorBindingFlags bindingFlags[] = |
| { |
| VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT | bindingFlagUpdateAfterBind, |
| VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT | bindingFlagUpdateAfterBind |
| }; |
| |
| const VkDescriptorSetLayoutBindingFlagsCreateInfo bindingCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO, |
| DE_NULL, |
| optional ? 2u : 1u, // bindingCount |
| bindingFlags, // pBindingFlags |
| }; |
| |
| const VkDescriptorSetLayoutCreateFlags layoutCreateFlags = |
| m_testParams.updateAfterBind ? VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT : 0; |
| |
| const VkDescriptorSetLayoutCreateInfo layoutCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, |
| &bindingCreateInfo, // pNext |
| layoutCreateFlags, // flags |
| optional ? 2u : 1u, // bindingCount |
| bindings, // pBindings |
| }; |
| |
| return vk::createDescriptorSetLayout(m_vki, m_vkd, &layoutCreateInfo); |
| } |
| |
| Move<VkDescriptorPool> CommonDescriptorInstance::createDescriptorPool (deUint32 descriptorCount) const |
| { |
| const VkDescriptorPoolCreateFlags pcf = m_testParams.updateAfterBind ? VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT : 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<VkDescriptorSet> 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<Vec4> vertices = ut::createVertices(m_testParams.frameResolution.width, m_testParams.frameResolution.height, xSize, ySize); |
| const std::vector<deUint32> primes = ut::generatePrimes(availableDescriptorCount); |
| const deUint32 primeCount = static_cast<deUint32>(primes.size()); |
| |
| std::vector<attributes> 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<size_t>(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<std::string, std::string> 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; |
| 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, 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, 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<VkRenderPass> 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)) |
| { |
| // Use VK_ATTACHMENT_LOAD_OP_LOAD to make the utility function select initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL |
| return vk::makeRenderPass(m_vki, m_vkd, m_colorFormat, VK_FORMAT_UNDEFINED, VK_ATTACHMENT_LOAD_OP_LOAD); |
| } |
| return Move<VkRenderPass>(); |
| } |
| |
| VkPushConstantRange CommonDescriptorInstance::makePushConstantRange (void) const |
| { |
| const VkPushConstantRange pcr = |
| { |
| m_testParams.stageFlags, // stageFlags |
| 0u, // offset |
| static_cast<deUint32>(sizeof(push_constant)) // size |
| }; |
| return pcr; |
| } |
| |
| Move<VkPipelineLayout> CommonDescriptorInstance::createPipelineLayout (const std::vector<VkDescriptorSetLayout>& 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<deUint32>(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<VkPipeline> 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<VkPipeline> 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<VkPipeline> 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<attributes::vec4>::value, // format |
| 0u // offset |
| }, // @in_position |
| { |
| 1u, // location |
| 0u, // binding |
| ut::mapType2vkFormat<attributes::vec2>::value, // format |
| static_cast<deUint32>(sizeof(attributes::vec4)) // offset |
| }, // @normalpos |
| { |
| 2u, // location |
| 0u, // binding |
| ut::mapType2vkFormat<attributes::ivec4>::value, // format |
| static_cast<deUint32>(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 VkDynamicState dynamicStates[] = |
| { |
| VK_DYNAMIC_STATE_SCISSOR |
| }; |
| |
| const VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // sType |
| DE_NULL, // pNext |
| 0u, // flags |
| DE_LENGTH_OF_ARRAY(dynamicStates), // dynamicStateCount |
| dynamicStates // pDynamicStates |
| }; |
| |
| const std::vector<VkViewport> viewports (1, makeViewport(m_testParams.frameResolution.width, m_testParams.frameResolution.height)); |
| const std::vector<VkRect2D> scissors (1, makeRect2D(0u, 0u)); |
| |
| 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 |
| nullptr, // rasterizationStateCreateInfo |
| nullptr, // multisampleStateCreateInfo |
| nullptr, // depthStencilStateCreateInfo |
| nullptr, // colorBlendStateCreateInfo |
| &dynamicStateCreateInfo); // dynamicStateCreateInfo |
| } |
| |
| VkDeviceSize CommonDescriptorInstance::createBuffers (std::vector<VkDescriptorBufferInfo>& 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<ut::ImageHandleAllocSp>& images, |
| std::vector<VkDescriptorBufferInfo>& 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<ut::BufferViewSp>& views, |
| const std::vector<VkDescriptorBufferInfo>& bufferInfos, |
| VkFormat format) |
| { |
| const deUint32 infoCount = static_cast<deUint32>(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<VkBufferView>(vk::createBufferView(m_vki, m_vkd, &bufferViewInfo)))); |
| } |
| } |
| |
| void CommonDescriptorInstance::createImagesViews (std::vector<ut::ImageViewSp>& views, |
| const std::vector<ut::ImageHandleAllocSp>& images, |
| VkFormat format) |
| { |
| const deUint32 imageCount = static_cast<deUint32>(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<VkImageView>(vk::createImageView(m_vki, m_vkd, &createInfo)))); |
| } |
| } |
| |
| void CommonDescriptorInstance::copyBuffersToImages (IterateCommonVariables& variables) |
| { |
| const deUint32 infoCount = static_cast<deUint32>(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 |
| VK_IMAGE_LAYOUT_UNDEFINED, // oldImageLayout |
| VK_IMAGE_LAYOUT_GENERAL, // newImageLayout |
| variables.descriptorsImages[infoIdx]->levels); // mipLevelCount |
| } |
| } |
| |
| void CommonDescriptorInstance::copyImagesToBuffers (IterateCommonVariables& variables) |
| { |
| const deUint32 infoCount = static_cast<deUint32>(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 |
| VK_IMAGE_LAYOUT_GENERAL, // oldImageLayout |
| VK_IMAGE_LAYOUT_GENERAL, // newImageLayout |
| variables.descriptorsBufferInfos[infoIdx]); // bufferInfo |
| } |
| } |
| |
| PixelBufferAccess CommonDescriptorInstance::getPixelAccess (deUint32 imageIndex, |
| const VkExtent3D& imageExtent, |
| VkFormat imageFormat, |
| const std::vector<VkDescriptorBufferInfo>& 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<unsigned char*>(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<deUint32> primes = ut::generatePrimes(variables.availableDescriptorCount); |
| const deUint32 primeCount = static_cast<deUint32>(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<VkSampler>(0), |
| static_cast<VkImageView>(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::iterateCommandSetup (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(m_testParams.calculateInLoop, variables.availableDescriptorCount); |
| variables.validDescriptorCount = ut::computePrimeCount(variables.availableDescriptorCount); |
| variables.descriptorPool = createDescriptorPool(variables.availableDescriptorCount); |
| variables.descriptorSet = createDescriptorSet(*variables.descriptorPool, *variables.descriptorSetLayout); |
| |
| std::vector<VkDescriptorSetLayout> 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); |
| } |
| |
| } |
| |
| void CommonDescriptorInstance::iterateCommandBegin (IterateCommonVariables& variables, bool firstPass) |
| { |
| vk::beginCommandBuffer (m_vki, *variables.commandBuffer); |
| |
| // Clear color attachment, and transition it to VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL |
| if ((m_testParams.stageFlags & VK_SHADER_STAGE_VERTEX_BIT) || (m_testParams.stageFlags & VK_SHADER_STAGE_FRAGMENT_BIT)) |
| { |
| if (firstPass) |
| { |
| const VkImageMemoryBarrier preImageBarrier = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| 0u, // VkAccessFlags srcAccessMask |
| VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask |
| VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout |
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout |
| VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex |
| VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex |
| *variables.frameBuffer->image->image, // VkImage image |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask |
| 0u, // uint32_t baseMipLevel |
| VK_REMAINING_MIP_LEVELS, // uint32_t mipLevels, |
| 0u, // uint32_t baseArray |
| VK_REMAINING_ARRAY_LAYERS, // uint32_t arraySize |
| } |
| }; |
| |
| m_vki.cmdPipelineBarrier(*variables.commandBuffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, |
| (VkDependencyFlags)0, |
| 0, (const VkMemoryBarrier*)DE_NULL, |
| 0, (const VkBufferMemoryBarrier*)DE_NULL, |
| 1, &preImageBarrier); |
| |
| const VkClearColorValue clearColorValue = makeClearValueColor(m_clearColor).color; |
| |
| m_vki.cmdClearColorImage(*variables.commandBuffer, *variables.frameBuffer->image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColorValue, 1, &preImageBarrier.subresourceRange); |
| |
| const VkImageMemoryBarrier postImageBarrier = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask |
| VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask |
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout |
| VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex |
| VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex |
| *variables.frameBuffer->image->image, // VkImage image |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask |
| 0u, // uint32_t baseMipLevel |
| VK_REMAINING_MIP_LEVELS, // uint32_t mipLevels, |
| 0u, // uint32_t baseArray |
| VK_REMAINING_ARRAY_LAYERS, // uint32_t arraySize |
| } |
| }; |
| |
| m_vki.cmdPipelineBarrier(*variables.commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, |
| (VkDependencyFlags)0, |
| 0, (const VkMemoryBarrier*)DE_NULL, |
| 0, (const VkBufferMemoryBarrier*)DE_NULL, |
| 1, &postImageBarrier); |
| |
| } |
| } |
| |
| if (m_testParams.calculateInLoop) |
| { |
| deRandom rnd; |
| deRandom_init(&rnd, static_cast<deUint32>(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<deInt32>(variables.lowerBound), |
| static_cast<deInt32>(variables.upperBound) |
| }; |
| |
| m_vki.cmdPushConstants(*variables.commandBuffer, *variables.pipelineLayout, m_testParams.stageFlags, 0u, static_cast<deUint32>(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; |
| ut::UpdatablePixelBufferAccessPtr programResult; |
| ut::UpdatablePixelBufferAccessPtr referenceResult; |
| |
| bool firstPass = true; |
| |
| iterateCommandSetup (v); |
| |
| v.renderArea.extent.width = m_testParams.frameResolution.width/4; |
| v.renderArea.extent.height = m_testParams.frameResolution.height/4; |
| |
| for (int x = 0; x < 4; x++) |
| for (int y= 0; y < 4; y++) |
| { |
| iterateCommandBegin (v, firstPass); |
| |
| if (true == firstPass && true == m_testParams.copyBuffersToImages) |
| { |
| copyBuffersToImages (v); |
| } |
| |
| firstPass = false; |
| |
| if (true == m_testParams.updateAfterBind) |
| { |
| updateDescriptors (v); |
| } |
| |
| v.renderArea.offset.x = x * m_testParams.frameResolution.width/4; |
| v.renderArea.offset.y = y * m_testParams.frameResolution.height/4; |
| |
| vk::VkRect2D scissor = makeRect2D(v.renderArea.offset.x, v.renderArea.offset.y, v.renderArea.extent.width, v.renderArea.extent.height); |
| m_vki.cmdSetScissor(*v.commandBuffer, 0u, 1u, &scissor); |
| |
| 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); |
| |
| iterateCommandEnd(v, programResult, referenceResult); |
| } |
| |
| return ( iterateVerifyResults(v, programResult, referenceResult) ? tcu::TestStatus::pass : tcu::TestStatus::fail)(""); |
| } |
| |
| std::vector<float> CommonDescriptorInstance::createColorScheme (void) |
| { |
| std::vector<float> cs; |
| int divider = 2; |
| for (int i = 0; i < 10; ++i) |
| { |
| cs.push_back(1.0f / float(divider)); |
| divider *= 2; |
| } |
| return cs; |
| } |
| |
| void CommonDescriptorInstance::iterateCommandEnd (IterateCommonVariables& variables, |
| ut::UpdatablePixelBufferAccessPtr& programResult, |
| ut::UpdatablePixelBufferAccessPtr& referenceResult, |
| bool collectBeforeSubmit) |
| { |
| if (collectBeforeSubmit) |
| { |
| iterateCollectResults(programResult, variables, true); |
| iterateCollectResults(referenceResult, variables, false); |
| } |
| |
| VK_CHECK(m_vki.endCommandBuffer(*variables.commandBuffer)); |
| Move<VkFence> 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 CommonDescriptorInstance::iterateVerifyResults (IterateCommonVariables& variables, |
| ut::UpdatablePixelBufferAccessPtr programResult, |
| ut::UpdatablePixelBufferAccessPtr referenceResult) |
| { |
| 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<VkCommandBuffer> CommonDescriptorInstance::createCmdBuffer (void) |
| { |
| return vk::allocateCommandBuffer(m_vki, m_vkd, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY); |
| } |
| |
| Move<VkFence> CommonDescriptorInstance::commandSubmit (VkCommandBuffer cmd) |
| { |
| Move<VkFence> fence(vk::createFence(m_vki, m_vkd)); |
| |
| const VkSubmitInfo submitInfo = |
| { |
| VK_STRUCTURE_TYPE_SUBMIT_INFO, // sType |
| DE_NULL, // pNext |
| 0u, // waitSemaphoreCount |
| static_cast<VkSemaphore*>(DE_NULL), // pWaitSemaphores |
| static_cast<const VkPipelineStageFlags*>(DE_NULL), // pWaitDstStageMask |
| 1u, // commandBufferCount |
| &cmd, // pCommandBuffers |
| 0u, // signalSemaphoreCount |
| static_cast<VkSemaphore*>(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<deUint32*>(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<VkBuffer> >(new Move<VkBuffer>(frameBufferContent->buffer)), |
| de::SharedPtr< de::MovePtr<Allocation> >(new de::MovePtr<Allocation>(frameBufferContent->alloc)))); |
| } |
| |
| void CommonDescriptorInstance::commandReadFrameBuffer (ut::BufferHandleAllocSp& content, |
| VkCommandBuffer commandBuffer, |
| const ut::FrameBufferSp& frameBuffer) |
| { |
| Move<VkBuffer> buffer; |
| de::MovePtr<Allocation> 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 barrierBefore = |
| { |
| 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_COLOR_ATTACHMENT_OPTIMAL, // 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; |
| }; |
| |
| const VkImageMemoryBarrier barrierAfter = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType; |
| DE_NULL, // pNext; |
| VK_ACCESS_TRANSFER_READ_BIT, // srcAccessMask; |
| VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // dstAccessMask; |
| VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // oldLayout; |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // newLayout; |
| VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex; |
| VK_QUEUE_FAMILY_IGNORED, // dstQueueFamilyIndex; |
| image, // image |
| subresourceRange // subresourceRange |
| }; |
| |
| |
| m_vki.cmdPipelineBarrier(commandBuffer, // commandBuffer |
| VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, // srcStageMask, dstStageMask |
| (VkDependencyFlags)0, // dependencyFlags |
| 0u, DE_NULL, // memoryBarrierCount, pMemoryBarriers |
| 0u, DE_NULL, // bufferBarrierCount, pBufferBarriers |
| 1u, &barrierBefore); // 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 | VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, |
| (VkDependencyFlags)0, |
| 0u, DE_NULL, |
| 1u, &bufferBarrier, |
| 1u, &barrierAfter); |
| |
| content = ut::BufferHandleAllocSp(new ut::BufferHandleAlloc(buffer, allocation)); |
| } |
| |
| std::string CommonDescriptorInstance::getColorAccess (VkDescriptorType descriptorType, |
| const char* indexVariableName, |
| bool usesMipMaps) |
| { |
| std::string text; |
| std::map<std::string, std::string> 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; |
| } |
| |
| bool CommonDescriptorInstance::performWritesInVertex (VkDescriptorType descriptorType, |
| const Context& context) |
| { |
| bool result = false; |
| |
| ut::DeviceProperties dp (context); |
| const VkPhysicalDeviceFeatures& feats = dp.physicalDeviceFeatures(); |
| |
| if (feats.vertexPipelineStoresAndAtomics != DE_FALSE) |
| { |
| result = CommonDescriptorInstance::performWritesInVertex(descriptorType); |
| } |
| |
| 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, context), |
| testCaseParams)) |
| { |
| } |
| |
| 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<deUint32>(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<unsigned char*>(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<deUint32> primes = ut::generatePrimes(variables.availableDescriptorCount); |
| |
| unsigned char* buffer = static_cast<unsigned char*>(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, context), |
| testCaseParams)) |
| { |
| } |
| |
| void UniformBufferInstance::createAndPopulateDescriptors (IterateCommonVariables& variables) |
| { |
| BindingUniformBuffer::Data data; |
| |
| const deUint32 alignment = static_cast<deUint32>(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<unsigned char*>(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, context), |
| testCaseParams)) |
| { |
| } |
| |
| 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<deUint32> 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, context), |
| testCaseParams)) |
| { |
| } |
| |
| 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<deUint32> 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; |
| iterateCommandSetup (v); |
| |
| ut::UpdatablePixelBufferAccessPtr programResult; |
| ut::UpdatablePixelBufferAccessPtr referenceResult; |
| bool firstPass = true; |
| |
| DE_ASSERT(v.dataAlignment); |
| |
| std::vector<deUint32> dynamicOffsets; |
| |
| deUint32 descIdx = 0; |
| const std::vector<deUint32> 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<deUint32>(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 }; |
| |
| v.renderArea.extent.width = m_testParams.frameResolution.width/4; |
| v.renderArea.extent.height = m_testParams.frameResolution.height/4; |
| |
| for (int x = 0; x < 4; x++) |
| for (int y= 0; y < 4; y++) |
| { |
| |
| v.renderArea.offset.x = x * m_testParams.frameResolution.width/4; |
| v.renderArea.offset.y = y * m_testParams.frameResolution.height/4; |
| |
| iterateCommandBegin (v, firstPass); |
| firstPass = false; |
| |
| 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::VkRect2D scissor = makeRect2D(v.renderArea.offset.x, v.renderArea.offset.y, v.renderArea.extent.width, v.renderArea.extent.height); |
| m_vki.cmdSetScissor(*v.commandBuffer, 0u, 1u, &scissor); |
| |
| 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); |
| |
| iterateCommandEnd(v, programResult, referenceResult); |
| } |
| |
| return (iterateVerifyResults(v, programResult, referenceResult) ? 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, context), |
| testCaseParams)), |
| DynamicBuffersInstance(context, m_testParams), StorageBufferInstance(context, testCaseParams) |
| { |
| } |
| |
| 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, context), |
| testCaseParams)), |
| DynamicBuffersInstance(context, m_testParams), UniformBufferInstance(context, testCaseParams) |
| { |
| } |
| |
| 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<VkRenderPass> 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, context), |
| testCaseParams)) |
| { |
| } |
| |
| void InputAttachmentInstance::createAndPopulateDescriptors (IterateCommonVariables& variables) |
| { |
| createImages(variables.descriptorsImages, variables.descriptorsBufferInfos, variables.descriptorsBuffer, |
| 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)); |
| } |
| vk::flushAlloc(m_vki, m_vkd, *variables.descriptorsBuffer->alloc); |
| } |
| |
| Move<VkRenderPass> InputAttachmentInstance::createRenderPass (const IterateCommonVariables& variables) |
| { |
| std::vector<VkAttachmentDescription> attachmentDescriptions; |
| std::vector<VkAttachmentReference> 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_COLOR_ATTACHMENT_OPTIMAL, // 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 std::vector<deUint32> primes = ut::generatePrimes(variables.availableDescriptorCount); |
| const deUint32 inputCount = static_cast<deUint32>(variables.descriptorImageViews.size()); |
| for (deUint32 inputIdx = 0; inputIdx < inputCount; ++inputIdx) |
| { |
| // primes holds the indices of input attachments for shader binding 10 which has input_attachment_index=1 |
| deUint32 nextInputAttachmentIndex = primes[inputIdx] + 1; |
| |
| // Fill up the subpass description's input attachments with unused attachments forming gaps to the next referenced attachment |
| for (deUint32 unusedIdx = static_cast<deUint32>(inputAttachmentRefs.size()); unusedIdx < nextInputAttachmentIndex; ++unusedIdx) |
| { |
| const VkAttachmentReference inputAttachmentRef = |
| { |
| VK_ATTACHMENT_UNUSED, // deUint32 attachment; |
| VK_IMAGE_LAYOUT_GENERAL // VkImageLayout layout; |
| }; |
| |
| inputAttachmentRefs.push_back(inputAttachmentRef); |
| } |
| |
| 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_STORE, // VkAttachmentStoreOp storeOp; |
| VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; |
| VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; |
| VK_IMAGE_LAYOUT_GENERAL, // 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<deUint32>(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<deUint32>(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<VkImageView> inputAttachments; |
| const deUint32 viewCount = static_cast<deUint32>(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, context), |
| testCaseParams)) |
| { |
| } |
| |
| 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<VkSampler>(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_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<VkSampler>(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, context), |
| testCaseParams)) |
| { |
| } |
| |
| 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<VkImageView>(0), |
| static_cast<VkImageLayout>(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<VkSampler>(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_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)) |
| { |
| } |
| |
| void CombinedImageInstance::updateDescriptors (IterateCommonVariables& variables) |
| { |
| const std::vector<deUint32> primes = ut::generatePrimes(variables.availableDescriptorCount); |
| const deUint32 primeCount = static_cast<deUint32>(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<VkSampler>(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_TRANSFER_SRC_BIT, |
|