| /*------------------------------------------------------------------------ |
| * Vulkan Conformance Tests |
| * ------------------------ |
| * |
| * Copyright (c) 2019 Google Inc. |
| * 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 Tests for descriptor copying |
| *//*--------------------------------------------------------------------*/ |
| |
| #include "vktBindingDescriptorCopyTests.hpp" |
| |
| #include "vkBufferWithMemory.hpp" |
| #include "vkImageWithMemory.hpp" |
| #include "vkQueryUtil.hpp" |
| #include "vkBuilderUtil.hpp" |
| #include "vkCmdUtil.hpp" |
| #include "vkTypeUtil.hpp" |
| #include "vkImageUtil.hpp" |
| #include "vkObjUtil.hpp" |
| #include "vktTestGroupUtil.hpp" |
| #include "vktTestCase.hpp" |
| |
| #include "deDefs.h" |
| #include "deMath.h" |
| #include "deRandom.h" |
| #include "deSharedPtr.hpp" |
| #include "deString.h" |
| |
| #include "tcuTestCase.hpp" |
| #include "tcuTestLog.hpp" |
| |
| #include <string> |
| #include <sstream> |
| |
| namespace vkt |
| { |
| namespace BindingModel |
| { |
| namespace |
| { |
| using namespace vk; |
| using namespace std; |
| using tcu::Vec4; |
| using tcu::Vec2; |
| |
| enum PipelineType |
| { |
| PIPELINE_TYPE_COMPUTE = 0, |
| PIPELINE_TYPE_GRAPHICS = 1 |
| }; |
| |
| struct DescriptorCopy |
| { |
| deUint32 srcSet; |
| deUint32 srcBinding; |
| deUint32 srcArrayElement; |
| deUint32 dstSet; |
| deUint32 dstBinding; |
| deUint32 dstArrayElement; |
| deUint32 descriptorCount; |
| }; |
| |
| struct DescriptorData |
| { |
| vector<deUint32> data; // The actual data. One element per dynamic offset. |
| bool written; // Is the data written in descriptor update |
| bool copiedInto; // Is the data being overwritten by a copy operation |
| }; |
| |
| typedef de::SharedPtr<ImageWithMemory> ImageWithMemorySp; |
| typedef de::SharedPtr<Unique<VkImageView> > VkImageViewSp; |
| typedef de::SharedPtr<Unique<VkBufferView> > VkBufferViewSp; |
| typedef de::SharedPtr<Unique<VkSampler> > VkSamplerSp; |
| typedef de::SharedPtr<Unique<VkDescriptorSetLayout> > VkDescriptorSetLayoutSp; |
| |
| const tcu::IVec2 renderSize(64, 64); |
| |
| // Base class for descriptors |
| class Descriptor |
| { |
| public: |
| Descriptor (VkDescriptorType descriptorType, deUint32 arraySize = 1u, deUint32 writeStart = 0u, deUint32 elementsToWrite = 1u, deUint32 numDynamicAreas = 1u); |
| virtual ~Descriptor (void); |
| VkDescriptorType getType (void) const { return m_descriptorType; } |
| deUint32 getArraySize (void) const { return m_arraySize; } |
| virtual VkWriteDescriptorSet getDescriptorWrite (void) = 0; |
| virtual string getShaderDeclaration (void) const = 0; |
| virtual void init (Context& context, PipelineType pipelineType) = 0; |
| virtual void copyValue (const Descriptor& src, deUint32 srcElement, deUint32 dstElement, deUint32 numElements); |
| virtual void invalidate (Context& context) { DE_UNREF(context); } |
| virtual vector<deUint32> getData (void) { DE_FATAL("Unexpected"); return vector<deUint32>(); } |
| deUint32 getId (void) const { return m_id; } |
| virtual string getShaderVerifyCode (void) const = 0; |
| string getArrayString (deUint32 index) const; |
| deUint32 getFirstWrittenElement (void) const; |
| deUint32 getNumWrittenElements (void) const; |
| deUint32 getReferenceData (deUint32 arrayIdx, deUint32 dynamicAreaIdx = 0) const { return m_data[arrayIdx].data[dynamicAreaIdx]; } |
| virtual bool isDynamic (void) const { return false; } |
| virtual void setDynamicAreas (vector<deUint32> dynamicAreas) { DE_UNREF(dynamicAreas); } |
| virtual vector<VkImageViewSp> getImageViews (void) const { return vector<VkImageViewSp>(); } |
| virtual vector<VkAttachmentReference> getAttachmentReferences (void) const { return vector<VkAttachmentReference>(); } |
| |
| static deUint32 s_nextId; |
| protected: |
| VkDescriptorType m_descriptorType; |
| deUint32 m_arraySize; |
| deUint32 m_id; |
| vector<DescriptorData> m_data; |
| deUint32 m_numDynamicAreas; |
| }; |
| |
| typedef de::SharedPtr<Descriptor> DescriptorSp; |
| |
| // Base class for all buffer based descriptors |
| class BufferDescriptor : public Descriptor |
| { |
| public: |
| BufferDescriptor (VkDescriptorType type, deUint32 arraySize, deUint32 writeStart, deUint32 elementsToWrite, deUint32 numDynamicAreas = 1u); |
| virtual ~BufferDescriptor (void); |
| void init (Context& context, PipelineType pipelineType); |
| |
| VkWriteDescriptorSet getDescriptorWrite (void); |
| virtual string getShaderDeclaration (void) const = 0; |
| void invalidate (Context& context); |
| vector<deUint32> getData (void); |
| virtual string getShaderVerifyCode (void) const = 0; |
| virtual VkBufferUsageFlags getBufferUsageFlags (void) const = 0; |
| virtual bool usesBufferView (void) { return false; } |
| private: |
| vector<VkDescriptorBufferInfo> m_descriptorBufferInfos; |
| de::MovePtr<BufferWithMemory> m_buffer; |
| deUint32 m_bufferSize; |
| vector<VkBufferViewSp> m_bufferViews; |
| vector<VkBufferView> m_bufferViewHandles; |
| }; |
| |
| // Inline uniform block descriptor. |
| class InlineUniformBlockDescriptor : public Descriptor |
| { |
| public: |
| InlineUniformBlockDescriptor (deUint32 arraySize, deUint32 writeStart, deUint32 elementsToWrite, deUint32 numDynamicAreas = 1u); |
| virtual ~InlineUniformBlockDescriptor (void); |
| void init (Context& context, PipelineType pipelineType); |
| |
| VkWriteDescriptorSet getDescriptorWrite (void); |
| virtual string getShaderDeclaration (void) const; |
| virtual string getShaderVerifyCode (void) const; |
| virtual bool usesBufferView (void) { return false; } |
| deUint32 getElementSizeInBytes (void) const { return static_cast<deUint32>(sizeof(decltype(m_blockData)::value_type)); } |
| deUint32 getSizeInBytes (void) const { return m_blockElements * getElementSizeInBytes(); } |
| |
| private: |
| // Inline uniform blocks cannot form arrays, so we will reuse the array size to create a data array inside the uniform block as |
| // an array of integers. However, with std140, each of those ints will be padded to 16 bytes in the shader. The struct below |
| // allows memory to match between the host and the shader. |
| struct PaddedUint |
| { |
| PaddedUint () : value(0) { deMemset(padding, 0, sizeof(padding)); } |
| PaddedUint (deUint32 value_) : value(value_) { deMemset(padding, 0, sizeof(padding)); } |
| PaddedUint& operator= (deUint32 value_) { value = value_; return *this; } |
| |
| deUint32 value; |
| deUint32 padding[3]; |
| }; |
| |
| vector<PaddedUint> m_blockData; |
| VkWriteDescriptorSetInlineUniformBlockEXT m_inlineWrite; |
| deUint32 m_blockElements; |
| deUint32 m_writeStart; |
| deUint32 m_elementsToWrite; |
| deUint32 m_writeStartByteOffset; |
| deUint32 m_bytesToWrite; |
| }; |
| |
| class UniformBufferDescriptor : public BufferDescriptor |
| { |
| public: |
| UniformBufferDescriptor (deUint32 arraySize = 1u, deUint32 writeStart = 0u, deUint32 elementsToWrite = 1u, deUint32 numDynamicAreas = 1u); |
| virtual ~UniformBufferDescriptor (void); |
| |
| string getShaderDeclaration (void) const; |
| string getShaderVerifyCode (void) const; |
| VkBufferUsageFlags getBufferUsageFlags (void) const { return VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; } |
| private: |
| }; |
| |
| class DynamicUniformBufferDescriptor : public BufferDescriptor |
| { |
| public: |
| DynamicUniformBufferDescriptor (deUint32 arraySize, deUint32 writeStart, deUint32 elementsToWrite, deUint32 numDynamicAreas); |
| virtual ~DynamicUniformBufferDescriptor (void); |
| |
| string getShaderDeclaration (void) const; |
| string getShaderVerifyCode (void) const; |
| VkBufferUsageFlags getBufferUsageFlags (void) const { return VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; } |
| virtual void setDynamicAreas (vector<deUint32> dynamicAreas) { m_dynamicAreas = dynamicAreas; } |
| virtual bool isDynamic (void) const { return true; } |
| |
| private: |
| vector<deUint32> m_dynamicAreas; |
| }; |
| |
| class StorageBufferDescriptor : public BufferDescriptor |
| { |
| public: |
| StorageBufferDescriptor (deUint32 arraySize = 1u, deUint32 writeStart = 0u, deUint32 elementsToWrite = 1u, deUint32 numDynamicAreas = 1u); |
| virtual ~StorageBufferDescriptor (void); |
| |
| string getShaderDeclaration (void) const; |
| string getShaderVerifyCode (void) const; |
| VkBufferUsageFlags getBufferUsageFlags (void) const { return VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; } |
| private: |
| }; |
| |
| class DynamicStorageBufferDescriptor : public BufferDescriptor |
| { |
| public: |
| DynamicStorageBufferDescriptor (deUint32 arraySize, deUint32 writeStart, deUint32 elementsToWrite, deUint32 numDynamicAreas); |
| virtual ~DynamicStorageBufferDescriptor (void); |
| |
| string getShaderDeclaration (void) const; |
| string getShaderVerifyCode (void) const; |
| VkBufferUsageFlags getBufferUsageFlags (void) const { return VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; } |
| virtual void setDynamicAreas (vector<deUint32> dynamicAreas) { m_dynamicAreas = dynamicAreas; } |
| virtual bool isDynamic (void) const { return true; } |
| |
| private: |
| vector<deUint32> m_dynamicAreas; |
| }; |
| |
| class UniformTexelBufferDescriptor : public BufferDescriptor |
| { |
| public: |
| UniformTexelBufferDescriptor (deUint32 arraySize = 1, deUint32 writeStart = 0, deUint32 elementsToWrite = 1, deUint32 numDynamicAreas = 1); |
| virtual ~UniformTexelBufferDescriptor (void); |
| |
| string getShaderDeclaration (void) const; |
| string getShaderVerifyCode (void) const; |
| VkBufferUsageFlags getBufferUsageFlags (void) const { return VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT; } |
| bool usesBufferView (void) { return true; } |
| private: |
| }; |
| |
| class StorageTexelBufferDescriptor : public BufferDescriptor |
| { |
| public: |
| StorageTexelBufferDescriptor (deUint32 arraySize = 1u, deUint32 writeStart = 0u, deUint32 elementsToWrite = 1u, deUint32 numDynamicAreas = 1u); |
| virtual ~StorageTexelBufferDescriptor (void); |
| |
| string getShaderDeclaration (void) const; |
| string getShaderVerifyCode (void) const; |
| VkBufferUsageFlags getBufferUsageFlags (void) const { return VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT; } |
| bool usesBufferView (void) { return true; } |
| private: |
| }; |
| |
| // Base class for all image based descriptors |
| class ImageDescriptor : public Descriptor |
| { |
| public: |
| ImageDescriptor (VkDescriptorType type, deUint32 arraySize, deUint32 writeStart, deUint32 elementsToWrite, deUint32 numDynamicAreas); |
| virtual ~ImageDescriptor (void); |
| void init (Context& context, PipelineType pipelineType); |
| |
| VkWriteDescriptorSet getDescriptorWrite (void); |
| virtual VkImageUsageFlags getImageUsageFlags (void) const = 0; |
| virtual string getShaderDeclaration (void) const = 0; |
| virtual string getShaderVerifyCode (void) const = 0; |
| virtual VkAccessFlags getAccessFlags (void) const { return VK_ACCESS_SHADER_READ_BIT; } |
| virtual VkImageLayout getImageLayout (void) const { return VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; } |
| |
| protected: |
| vector<VkImageViewSp> m_imageViews; |
| |
| private: |
| vector<ImageWithMemorySp> m_images; |
| vector<VkDescriptorImageInfo> m_descriptorImageInfos; |
| Move<VkSampler> m_sampler; |
| }; |
| |
| class InputAttachmentDescriptor : public ImageDescriptor |
| { |
| public: |
| InputAttachmentDescriptor (deUint32 arraySize = 1u, deUint32 writeStart = 0u, deUint32 elementsToWrite = 1u, deUint32 numDynamicAreas = 1u); |
| virtual ~InputAttachmentDescriptor (void); |
| |
| VkImageUsageFlags getImageUsageFlags (void) const { return VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; } |
| string getShaderDeclaration (void) const; |
| string getShaderVerifyCode (void) const; |
| vector<VkImageViewSp> getImageViews (void) const { return m_imageViews; } |
| void copyValue (const Descriptor& src, deUint32 srcElement, deUint32 dstElement, deUint32 numElements); |
| VkAccessFlags getAccessFlags (void) const { return VK_ACCESS_INPUT_ATTACHMENT_READ_BIT; } |
| vector<VkAttachmentReference> getAttachmentReferences (void) const; |
| static deUint32 s_nextAttachmentIndex; |
| private: |
| vector<deUint32> m_attachmentIndices; |
| deUint32 m_originalAttachmentIndex; |
| }; |
| |
| class CombinedImageSamplerDescriptor : public ImageDescriptor |
| { |
| public: |
| CombinedImageSamplerDescriptor (deUint32 arraySize = 1u, deUint32 writeStart = 0u, deUint32 elementsToWrite = 1u, deUint32 numDynamicAreas = 1u); |
| virtual ~CombinedImageSamplerDescriptor (void); |
| |
| VkImageUsageFlags getImageUsageFlags (void) const { return VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; } |
| string getShaderDeclaration (void) const; |
| string getShaderVerifyCode (void) const; |
| private: |
| }; |
| |
| class SamplerDescriptor; |
| |
| class SampledImageDescriptor : public ImageDescriptor |
| { |
| public: |
| SampledImageDescriptor (deUint32 arraySize = 1u, deUint32 writeStart = 0u, deUint32 elementsToWrite = 1u, deUint32 numDynamicAreas = 1u); |
| virtual ~SampledImageDescriptor (void); |
| |
| VkImageUsageFlags getImageUsageFlags (void) const { return VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; } |
| string getShaderDeclaration (void) const; |
| string getShaderVerifyCode (void) const; |
| void addSampler (SamplerDescriptor* sampler, deUint32 count = 1u) { for (deUint32 i = 0; i < count; i++) m_samplers.push_back(sampler); } |
| private: |
| vector<SamplerDescriptor*> m_samplers; |
| }; |
| |
| class SamplerDescriptor : public Descriptor |
| { |
| public: |
| SamplerDescriptor (deUint32 arraySize = 1u, deUint32 writeStart = 0u, deUint32 elementsToWrite = 1u, deUint32 numDynamicAreas = 1u); |
| virtual ~SamplerDescriptor (void); |
| void init (Context& context, PipelineType pipelineType); |
| |
| void addImage (SampledImageDescriptor* image, deUint32 count = 1u) { for (deUint32 i = 0; i < count; i++ ) m_images.push_back(image); } |
| VkWriteDescriptorSet getDescriptorWrite (void); |
| string getShaderDeclaration (void) const; |
| string getShaderVerifyCode (void) const; |
| |
| private: |
| vector<VkSamplerSp> m_samplers; |
| vector<VkDescriptorImageInfo> m_descriptorImageInfos; |
| vector<SampledImageDescriptor*> m_images; |
| }; |
| |
| class StorageImageDescriptor : public ImageDescriptor |
| { |
| public: |
| StorageImageDescriptor (deUint32 arraySize = 1u, deUint32 writeStart = 0u, deUint32 elementsToWrite = 1u, deUint32 numDynamicAreas = 1u); |
| virtual ~StorageImageDescriptor (void); |
| |
| VkImageUsageFlags getImageUsageFlags (void) const { return VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; } |
| string getShaderDeclaration (void) const; |
| string getShaderVerifyCode (void) const; |
| VkImageLayout getImageLayout (void) const { return VK_IMAGE_LAYOUT_GENERAL; } |
| private: |
| }; |
| |
| class DescriptorSet |
| { |
| public: |
| DescriptorSet (void); |
| ~DescriptorSet (void); |
| void addBinding (DescriptorSp descriptor); |
| const vector<DescriptorSp> getBindings (void) const { return m_bindings; } |
| |
| private: |
| vector<DescriptorSp> m_bindings; |
| }; |
| |
| typedef de::SharedPtr<DescriptorSet> DescriptorSetSp; |
| |
| // Class that handles descriptor sets and descriptors bound to those sets. Keeps track of copy operations. |
| class DescriptorCommands |
| { |
| public: |
| DescriptorCommands (PipelineType pipelineType); |
| ~DescriptorCommands (void); |
| void addDescriptor (DescriptorSp descriptor, deUint32 descriptorSet); |
| void copyDescriptor (deUint32 srcSet, deUint32 srcBinding, deUint32 srcArrayElement, deUint32 dstSet, deUint32 dstBinding, deUint32 dstArrayElement, deUint32 descriptorCount); |
| void copyDescriptor (deUint32 srcSet, deUint32 srcBinding, deUint32 dstSet, deUint32 dstBinding) { copyDescriptor(srcSet, srcBinding, 0u, dstSet, dstBinding, 0u, 1u); } |
| string getShaderDeclarations (void) const; |
| string getDescriptorVerifications (void) const; |
| void addResultBuffer (void); |
| deUint32 getResultBufferId (void) const { return m_resultBuffer->getId(); } |
| void setDynamicAreas (vector<deUint32> areas); |
| bool hasDynamicAreas (void) const; |
| PipelineType getPipelineType (void) const { return m_pipelineType; } |
| |
| tcu::TestStatus run(Context& context); |
| |
| private: |
| PipelineType m_pipelineType; |
| vector<DescriptorSetSp> m_descriptorSets; |
| vector<DescriptorCopy> m_descriptorCopies; |
| vector<DescriptorSp> m_descriptors; |
| map<VkDescriptorType, deUint32> m_descriptorCounts; |
| DescriptorSp m_resultBuffer; |
| vector<deUint32> m_dynamicAreas; |
| }; |
| |
| typedef de::SharedPtr<DescriptorCommands> DescriptorCommandsSp; |
| |
| class DescriptorCopyTestInstance : public TestInstance |
| { |
| public: |
| DescriptorCopyTestInstance (Context& context, DescriptorCommandsSp commands); |
| ~DescriptorCopyTestInstance (void); |
| tcu::TestStatus iterate (void); |
| private: |
| DescriptorCommandsSp m_commands; |
| }; |
| |
| class DescriptorCopyTestCase : public TestCase |
| { |
| public: |
| DescriptorCopyTestCase (tcu::TestContext& context, const char* name, const char* desc, DescriptorCommandsSp commands); |
| virtual ~DescriptorCopyTestCase (void); |
| virtual void initPrograms (SourceCollections& programCollection) const; |
| virtual TestInstance* createInstance (Context& context) const; |
| |
| private: |
| DescriptorCommandsSp m_commands; |
| }; |
| |
| deUint32 Descriptor::s_nextId = 0xabc; // Random starting point for ID counter |
| deUint32 InputAttachmentDescriptor::s_nextAttachmentIndex = 0; |
| |
| Descriptor::Descriptor (VkDescriptorType descriptorType, |
| deUint32 arraySize, |
| deUint32 writeStart, |
| deUint32 elementsToWrite, |
| deUint32 numDynamicAreas) |
| : m_descriptorType(descriptorType) |
| , m_arraySize(arraySize) |
| , m_id(s_nextId++) |
| , m_numDynamicAreas(numDynamicAreas) |
| { |
| for (deUint32 arrayIdx = 0; arrayIdx < m_arraySize; arrayIdx++) |
| { |
| const bool written = arrayIdx >= writeStart && arrayIdx < writeStart + elementsToWrite; |
| vector<deUint32> data; |
| |
| for (deUint32 dynamicAreaIdx = 0; dynamicAreaIdx < m_numDynamicAreas; dynamicAreaIdx++) |
| data.push_back(m_id + arrayIdx * m_numDynamicAreas + dynamicAreaIdx); |
| |
| const DescriptorData descriptorData = |
| { |
| data, // vector<deUint32> data |
| written, // bool written |
| false // bool copiedInto |
| }; |
| |
| m_data.push_back(descriptorData); |
| } |
| } |
| |
| Descriptor::~Descriptor (void) |
| { |
| } |
| |
| // Copy refrence data from another descriptor |
| void Descriptor::copyValue (const Descriptor& src, |
| deUint32 srcElement, |
| deUint32 dstElement, |
| deUint32 numElements) |
| { |
| for (deUint32 elementIdx = 0; elementIdx < numElements; elementIdx++) |
| { |
| DE_ASSERT(src.m_data[elementIdx + srcElement].written); |
| |
| for (deUint32 dynamicAreaIdx = 0; dynamicAreaIdx < de::min(m_numDynamicAreas, src.m_numDynamicAreas); dynamicAreaIdx++) |
| m_data[elementIdx + dstElement].data[dynamicAreaIdx] = src.m_data[elementIdx + srcElement].data[dynamicAreaIdx]; |
| |
| m_data[elementIdx + dstElement].copiedInto = true; |
| } |
| } |
| |
| string Descriptor::getArrayString (deUint32 index) const |
| { |
| return m_arraySize > 1 ? (string("[") + de::toString(index) + "]") : ""; |
| } |
| |
| // Returns the first element to be written in descriptor update |
| deUint32 Descriptor::getFirstWrittenElement (void) const |
| { |
| for (deUint32 i = 0; i < (deUint32)m_data.size(); i++) |
| if (m_data[i].written) |
| return i; |
| |
| return 0; |
| } |
| |
| // Returns the number of array elements to be written for a descriptor array |
| deUint32 Descriptor::getNumWrittenElements (void) const |
| { |
| deUint32 numElements = 0; |
| |
| for (deUint32 i = 0; i < (deUint32)m_data.size(); i++) |
| if (m_data[i].written) |
| numElements++; |
| |
| return numElements; |
| } |
| |
| BufferDescriptor::BufferDescriptor (VkDescriptorType type, |
| deUint32 arraySize, |
| deUint32 writeStart, |
| deUint32 elementsToWrite, |
| deUint32 numDynamicAreas) |
| : Descriptor(type, arraySize, writeStart, elementsToWrite, numDynamicAreas) |
| , m_bufferSize(256u * arraySize * numDynamicAreas) |
| { |
| } |
| |
| BufferDescriptor::~BufferDescriptor (void) |
| { |
| } |
| |
| void BufferDescriptor::init (Context& context, |
| PipelineType pipelineType) |
| { |
| DE_UNREF(pipelineType); |
| |
| const DeviceInterface& vk = context.getDeviceInterface(); |
| const VkDevice device = context.getDevice(); |
| Allocator& allocator = context.getDefaultAllocator(); |
| |
| // Create buffer |
| { |
| const VkBufferCreateInfo bufferCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| 0u, // VkBufferCreateFlags flags |
| m_bufferSize, // VkDeviceSize size |
| getBufferUsageFlags(), // VkBufferUsageFlags usage |
| VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode |
| 0u, // uint32_t queueFamilyIndexCount |
| DE_NULL // const uint32_t* pQueueFamilyIndices |
| }; |
| |
| m_buffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible)); |
| } |
| |
| // Create descriptor buffer infos |
| { |
| for (deUint32 arrayIdx = 0; arrayIdx < m_arraySize; arrayIdx++) |
| { |
| const VkDescriptorBufferInfo bufferInfo = |
| { |
| m_buffer->get(), // VkBuffer buffer |
| 256u * m_numDynamicAreas * arrayIdx, // VkDeviceSize offset |
| isDynamic() ? 256u : 4u // VkDeviceSize range |
| }; |
| |
| m_descriptorBufferInfos.push_back(bufferInfo); |
| } |
| } |
| |
| // Create buffer views |
| if (usesBufferView()) |
| { |
| for (deUint32 viewIdx = 0; viewIdx < m_arraySize; viewIdx++) |
| { |
| const VkBufferViewCreateInfo bufferViewCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| 0u, // VkBufferViewCreateFlags flags |
| m_buffer->get(), // VkBuffer buffer |
| VK_FORMAT_R32_SFLOAT, // VkFormat format |
| 256u * viewIdx, // VkDeviceSize offset |
| 4u // VkDeviceSize range |
| }; |
| |
| m_bufferViews.push_back(VkBufferViewSp(new Unique<VkBufferView>(createBufferView(vk, device, &bufferViewCreateInfo)))); |
| m_bufferViewHandles.push_back(**m_bufferViews[viewIdx]); |
| } |
| } |
| |
| // Initialize buffer memory |
| { |
| deUint32* hostPtr = (deUint32*)m_buffer->getAllocation().getHostPtr(); |
| |
| for (deUint32 arrayIdx = 0; arrayIdx < m_arraySize; arrayIdx++) |
| { |
| for (deUint32 dynamicAreaIdx = 0; dynamicAreaIdx < m_numDynamicAreas; dynamicAreaIdx++) |
| { |
| union BufferValue |
| { |
| deUint32 uintValue; |
| float floatValue; |
| } bufferValue; |
| |
| bufferValue.uintValue = m_id + (arrayIdx * m_numDynamicAreas) + dynamicAreaIdx; |
| |
| if (usesBufferView()) |
| bufferValue.floatValue = (float)bufferValue.uintValue; |
| |
| hostPtr[(256 / 4) * (m_numDynamicAreas * arrayIdx + dynamicAreaIdx)] = bufferValue.uintValue; |
| } |
| } |
| |
| flushAlloc(vk, device, m_buffer->getAllocation()); |
| } |
| } |
| |
| VkWriteDescriptorSet BufferDescriptor::getDescriptorWrite (void) |
| { |
| const deUint32 firstElement = getFirstWrittenElement(); |
| |
| // Set and binding will be overwritten later |
| const VkWriteDescriptorSet descriptorWrite = |
| { |
| VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| (VkDescriptorSet)0u, // VkDescriptorSet dstSet |
| 0u, // deUint32 dstBinding |
| firstElement, // deUint32 dstArrayElement |
| getNumWrittenElements(), // deUint32 descriptorCount |
| getType(), // VkDescriptorType descriptorType |
| DE_NULL, // const VkDescriptorImageInfo pImageInfo |
| usesBufferView() ? DE_NULL : &m_descriptorBufferInfos[firstElement], // const VkDescriptorBufferInfo* pBufferInfo |
| usesBufferView() ? &m_bufferViewHandles[firstElement] : DE_NULL // const VkBufferView* pTexelBufferView |
| }; |
| |
| return descriptorWrite; |
| } |
| |
| void BufferDescriptor::invalidate (Context& context) |
| { |
| const DeviceInterface& vk = context.getDeviceInterface(); |
| const VkDevice device = context.getDevice(); |
| |
| invalidateAlloc(vk, device, m_buffer->getAllocation()); |
| } |
| |
| // Returns the buffer data as a vector |
| vector<deUint32> BufferDescriptor::getData (void) |
| { |
| vector<deUint32> data; |
| deInt32* hostPtr = (deInt32*)m_buffer->getAllocation().getHostPtr(); |
| |
| for (deUint32 i = 0; i < m_arraySize; i++) |
| data.push_back(hostPtr[i]); |
| |
| return data; |
| } |
| |
| // Inline Uniform Block descriptor. These are similar to uniform buffers, but they can't form arrays for spec reasons. |
| // The array size is reused, instead, as the size of a data array inside the uniform block. |
| InlineUniformBlockDescriptor::InlineUniformBlockDescriptor (deUint32 arraySize, |
| deUint32 writeStart, |
| deUint32 elementsToWrite, |
| deUint32 numDynamicAreas) |
| : Descriptor(VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT, arraySize, writeStart, elementsToWrite, 1u) |
| , m_blockElements(arraySize) |
| , m_writeStart(writeStart) |
| , m_elementsToWrite(elementsToWrite) |
| , m_writeStartByteOffset(m_writeStart * getElementSizeInBytes()) |
| , m_bytesToWrite(m_elementsToWrite * getElementSizeInBytes()) |
| { |
| DE_UNREF(numDynamicAreas); |
| } |
| |
| InlineUniformBlockDescriptor::~InlineUniformBlockDescriptor (void) |
| { |
| } |
| |
| void InlineUniformBlockDescriptor::init (Context& context, |
| PipelineType pipelineType) |
| { |
| DE_UNREF(context); |
| DE_UNREF(pipelineType); |
| |
| // Initialize host memory. |
| m_blockData.resize(m_blockElements); |
| for (deUint32 i = 0; i < m_blockElements; ++i) |
| m_blockData[i] = m_id + i; |
| |
| // Initialize descriptor write extension structure. |
| m_inlineWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT; |
| m_inlineWrite.pNext = DE_NULL; |
| m_inlineWrite.dataSize = m_bytesToWrite; |
| m_inlineWrite.pData = &m_blockData[m_writeStart]; |
| } |
| |
| VkWriteDescriptorSet InlineUniformBlockDescriptor::getDescriptorWrite (void) |
| { |
| // Set and binding will be overwritten later |
| const VkWriteDescriptorSet descriptorWrite = |
| { |
| VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // VkStructureType sType |
| &m_inlineWrite, // const void* pNext |
| (VkDescriptorSet)0u, // VkDescriptorSet dstSet |
| 0u, // deUint32 dstBinding |
| m_writeStartByteOffset, // deUint32 dstArrayElement |
| m_bytesToWrite, // deUint32 descriptorCount |
| getType(), // VkDescriptorType descriptorType |
| DE_NULL, // const VkDescriptorImageInfo pImageInfo |
| DE_NULL, // const VkDescriptorBufferInfo* pBufferInfo |
| DE_NULL // const VkBufferView* pTexelBufferView |
| }; |
| |
| return descriptorWrite; |
| } |
| |
| string InlineUniformBlockDescriptor::getShaderDeclaration (void) const |
| { |
| const string idStr = de::toString(m_id); |
| return string(") uniform InlineUniformBlock" + idStr + "\n" |
| "{\n" |
| " int data" + getArrayString(m_arraySize) + ";\n" |
| "} inlineUniformBlock" + idStr + ";\n"); |
| } |
| |
| string InlineUniformBlockDescriptor::getShaderVerifyCode (void) const |
| { |
| const string idStr = de::toString(m_id); |
| string ret; |
| |
| for (deUint32 i = 0; i < m_arraySize; i++) |
| { |
| if (m_data[i].written || m_data[i].copiedInto) |
| { |
| ret += string("if (inlineUniformBlock") + idStr + ".data" + getArrayString(i) + " != " + de::toString(m_data[i].data[0]) + ") result = 0;\n"; |
| } |
| } |
| |
| return ret; |
| } |
| |
| UniformBufferDescriptor::UniformBufferDescriptor (deUint32 arraySize, |
| deUint32 writeStart, |
| deUint32 elementsToWrite, |
| deUint32 numDynamicAreas) |
| : BufferDescriptor(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, arraySize, writeStart, elementsToWrite, 1u) |
| { |
| DE_UNREF(numDynamicAreas); |
| } |
| |
| UniformBufferDescriptor::~UniformBufferDescriptor (void) |
| { |
| } |
| |
| string UniformBufferDescriptor::getShaderDeclaration (void) const |
| { |
| return string( |
| ") uniform UniformBuffer" + de::toString(m_id) + "\n" |
| "{\n" |
| " int data;\n" |
| "} uniformBuffer" + de::toString(m_id) + getArrayString(m_arraySize) + ";\n"); |
| } |
| |
| string UniformBufferDescriptor::getShaderVerifyCode (void) const |
| { |
| string ret; |
| |
| for (deUint32 i = 0; i < m_arraySize; i++) |
| { |
| if (m_data[i].written || m_data[i].copiedInto) |
| ret += string("if (uniformBuffer") + de::toString(m_id) + getArrayString(i) + ".data != " + de::toString(m_data[i].data[0]) + ") result = 0;\n"; |
| } |
| |
| return ret; |
| } |
| |
| DynamicUniformBufferDescriptor::DynamicUniformBufferDescriptor (deUint32 arraySize, |
| deUint32 writeStart, |
| deUint32 elementsToWrite, |
| deUint32 numDynamicAreas) |
| : BufferDescriptor(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, arraySize, writeStart, elementsToWrite, numDynamicAreas) |
| { |
| } |
| |
| DynamicUniformBufferDescriptor::~DynamicUniformBufferDescriptor (void) |
| { |
| } |
| |
| string DynamicUniformBufferDescriptor::getShaderDeclaration (void) const |
| { |
| return string( |
| ") uniform UniformBuffer" + de::toString(m_id) + "\n" |
| "{\n" |
| " int data;\n" |
| "} dynamicUniformBuffer" + de::toString(m_id) + getArrayString(m_arraySize) + ";\n"); |
| } |
| |
| string DynamicUniformBufferDescriptor::getShaderVerifyCode (void) const |
| { |
| string ret; |
| |
| for (deUint32 arrayIdx = 0; arrayIdx < m_arraySize; arrayIdx++) |
| { |
| if (m_data[arrayIdx].written || m_data[arrayIdx].copiedInto) |
| ret += string("if (dynamicUniformBuffer") + de::toString(m_id) + getArrayString(arrayIdx) + ".data != " + de::toString(m_data[arrayIdx].data[m_dynamicAreas[arrayIdx]]) + ") result = 0;\n"; |
| } |
| |
| return ret; |
| } |
| |
| StorageBufferDescriptor::StorageBufferDescriptor (deUint32 arraySize, |
| deUint32 writeStart, |
| deUint32 elementsToWrite, |
| deUint32 numDynamicAreas) |
| : BufferDescriptor(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, arraySize, writeStart, elementsToWrite, 1u) |
| { |
| DE_UNREF(numDynamicAreas); |
| } |
| |
| StorageBufferDescriptor::~StorageBufferDescriptor (void) |
| { |
| } |
| |
| string StorageBufferDescriptor::getShaderDeclaration (void) const |
| { |
| return string( |
| ") buffer StorageBuffer" + de::toString(m_id) + "\n" |
| "{\n" |
| " int data;\n" |
| "} storageBuffer" + de::toString(m_id) + getArrayString(m_arraySize) + ";\n"); |
| } |
| |
| string StorageBufferDescriptor::getShaderVerifyCode (void) const |
| { |
| string ret; |
| |
| for (deUint32 i = 0; i < m_arraySize; i++) |
| { |
| if (m_data[i].written || m_data[i].copiedInto) |
| ret += string("if (storageBuffer") + de::toString(m_id) + getArrayString(i) + ".data != " + de::toString(m_data[i].data[0]) + ") result = 0;\n"; |
| } |
| |
| return ret; |
| } |
| |
| DynamicStorageBufferDescriptor::DynamicStorageBufferDescriptor (deUint32 arraySize, |
| deUint32 writeStart, |
| deUint32 elementsToWrite, |
| deUint32 numDynamicAreas) |
| : BufferDescriptor(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, arraySize, writeStart, elementsToWrite, numDynamicAreas) |
| { |
| } |
| |
| DynamicStorageBufferDescriptor::~DynamicStorageBufferDescriptor (void) |
| { |
| } |
| |
| string DynamicStorageBufferDescriptor::getShaderDeclaration (void) const |
| { |
| return string( |
| ") buffer StorageBuffer" + de::toString(m_id) + "\n" |
| "{\n" |
| " int data;\n" |
| "} dynamicStorageBuffer" + de::toString(m_id) + getArrayString(m_arraySize) + ";\n"); |
| } |
| |
| string DynamicStorageBufferDescriptor::getShaderVerifyCode (void) const |
| { |
| string ret; |
| |
| for (deUint32 arrayIdx = 0; arrayIdx < m_arraySize; arrayIdx++) |
| { |
| if (m_data[arrayIdx].written || m_data[arrayIdx].copiedInto) |
| ret += string("if (dynamicStorageBuffer") + de::toString(m_id) + getArrayString(arrayIdx) + ".data != " + de::toString(m_data[arrayIdx].data[m_dynamicAreas[arrayIdx]]) + ") result = 0;\n"; |
| } |
| |
| return ret; |
| } |
| |
| UniformTexelBufferDescriptor::UniformTexelBufferDescriptor (deUint32 arraySize, |
| deUint32 writeStart, |
| deUint32 elementsToWrite, |
| deUint32 numDynamicAreas) |
| : BufferDescriptor(VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, arraySize, writeStart, elementsToWrite, 1u) |
| { |
| DE_UNREF(numDynamicAreas); |
| } |
| |
| UniformTexelBufferDescriptor::~UniformTexelBufferDescriptor (void) |
| { |
| } |
| |
| string UniformTexelBufferDescriptor::getShaderDeclaration (void) const |
| { |
| return string(") uniform textureBuffer uniformTexelBuffer" + de::toString(m_id) + getArrayString(m_arraySize) + ";\n"); |
| } |
| |
| string UniformTexelBufferDescriptor::getShaderVerifyCode (void) const |
| { |
| string ret; |
| |
| for (deUint32 i = 0; i < m_arraySize; i++) |
| { |
| if (m_data[i].written || m_data[i].copiedInto) |
| ret += string("if (texelFetch(uniformTexelBuffer") + de::toString(m_id) + getArrayString(i) + ", 0).x != " + de::toString(m_data[i].data[0]) + ") result = 0;\n"; |
| } |
| |
| return ret; |
| } |
| |
| StorageTexelBufferDescriptor::StorageTexelBufferDescriptor (deUint32 arraySize, |
| deUint32 writeStart, |
| deUint32 elementsToWrite, |
| deUint32 numDynamicAreas) |
| : BufferDescriptor(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, arraySize, writeStart, elementsToWrite, 1u) |
| { |
| DE_UNREF(numDynamicAreas); |
| } |
| |
| StorageTexelBufferDescriptor::~StorageTexelBufferDescriptor (void) |
| { |
| } |
| |
| string StorageTexelBufferDescriptor::getShaderDeclaration (void) const |
| { |
| return string(", r32f) uniform imageBuffer storageTexelBuffer" + de::toString(m_id) + getArrayString(m_arraySize) + ";\n"); |
| } |
| |
| string StorageTexelBufferDescriptor::getShaderVerifyCode (void) const |
| { |
| string ret; |
| |
| for (deUint32 i = 0; i < m_arraySize; i++) |
| { |
| if (m_data[i].written || m_data[i].copiedInto) |
| ret += string("if (imageLoad(storageTexelBuffer") + de::toString(m_id) + getArrayString(i) + ", 0).x != " + de::toString(m_data[i].data[0]) + ") result = 0;\n"; |
| } |
| |
| return ret; |
| } |
| |
| ImageDescriptor::ImageDescriptor (VkDescriptorType type, |
| deUint32 arraySize, |
| deUint32 writeStart, |
| deUint32 elementsToWrite, |
| deUint32 numDynamicAreas) |
| : Descriptor(type, arraySize, writeStart, elementsToWrite, 1u) |
| { |
| DE_UNREF(numDynamicAreas); |
| } |
| |
| ImageDescriptor::~ImageDescriptor (void) |
| { |
| } |
| |
| void ImageDescriptor::init (Context& context, |
| PipelineType pipelineType) |
| { |
| const DeviceInterface& vk = context.getDeviceInterface(); |
| const VkDevice device = context.getDevice(); |
| Allocator& allocator = context.getDefaultAllocator(); |
| const VkQueue queue = context.getUniversalQueue(); |
| deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); |
| const VkFormat format = VK_FORMAT_R32_SFLOAT; |
| const VkComponentMapping componentMapping = makeComponentMappingRGBA(); |
| |
| const VkImageSubresourceRange subresourceRange = |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask |
| 0u, // deUint32 baseMipLevel |
| 1u, // deUint32 levelCount |
| 0u, // deUint32 baseArrayLayer |
| 1u, // deUint32 layerCount |
| }; |
| |
| // Create sampler |
| { |
| const tcu::Sampler sampler = tcu::Sampler(tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::NEAREST, tcu::Sampler::NEAREST); |
| const tcu::TextureFormat texFormat = mapVkFormat(format); |
| const VkSamplerCreateInfo samplerParams = mapSampler(sampler, texFormat); |
| |
| m_sampler = createSampler(vk, device, &samplerParams); |
| } |
| |
| // Create images |
| for (deUint32 imageIdx = 0; imageIdx < m_arraySize; imageIdx++) |
| { |
| const VkImageCreateInfo imageCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType stype |
| DE_NULL, // const void* pNext |
| 0u, // VkImageCreateFlags flags |
| VK_IMAGE_TYPE_2D, // VkImageType imageType |
| format, // VkFormat format |
| { (deUint32)renderSize.x(), (deUint32)renderSize.y(), 1 }, // VkExtent3D extent |
| 1u, // deUint32 mipLevels |
| 1u, // deUint32 arrayLayers |
| VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples |
| VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling |
| getImageUsageFlags(), // VkImageUsageFlags usage |
| VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode |
| 1u, // deUint32 queueFamilyIndexCount |
| &queueFamilyIndex, // const deUint32* pQueueFamilyIndices |
| VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout |
| }; |
| |
| m_images.push_back(ImageWithMemorySp(new ImageWithMemory(vk, device, allocator, imageCreateInfo, MemoryRequirement::Any))); |
| } |
| |
| // Create image views |
| for (deUint32 imageIdx = 0; imageIdx < m_arraySize; imageIdx++) |
| { |
| const VkImageViewCreateInfo imageViewCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| 0u, // VkImageViewCreateFlags flags |
| **m_images[imageIdx], // VkImage image |
| VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType |
| format, // VkFormat format |
| componentMapping, // VkComponentMapping components |
| subresourceRange // VkImageSubresourceRange subresourceRange |
| }; |
| |
| m_imageViews.push_back(VkImageViewSp(new Unique<VkImageView>(createImageView(vk, device, &imageViewCreateInfo)))); |
| } |
| |
| // Create descriptor image infos |
| { |
| for (deUint32 i = 0; i < m_arraySize; i++) |
| { |
| const VkDescriptorImageInfo imageInfo = |
| { |
| *m_sampler, // VkSampler sampler |
| **m_imageViews[i], // VkImageView imageView |
| getImageLayout() // VkImageLayout imageLayout |
| }; |
| |
| m_descriptorImageInfos.push_back(imageInfo); |
| } |
| } |
| |
| // Clear images to reference value |
| for (deUint32 imageIdx = 0; imageIdx < m_arraySize; imageIdx++) |
| { |
| const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex)); |
| const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY)); |
| |
| const float clearValue = (float)(m_id + imageIdx); |
| const VkClearValue clearColor = makeClearValueColorF32(clearValue, clearValue, clearValue, clearValue); |
| |
| 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 |
| queueFamilyIndex, // deUint32 srcQueueFamilyIndex |
| queueFamilyIndex, // deUint32 dstQueueFamilyIndex |
| **m_images[imageIdx], // VkImage image |
| subresourceRange // VkImageSubresourceRange subresourceRange |
| }; |
| |
| const VkImageMemoryBarrier postImageBarrier = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask |
| getAccessFlags(), // VkAccessFlags dstAccessMask |
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout |
| getImageLayout(), // VkImageLayout newLayout |
| queueFamilyIndex, // deUint32 srcQueueFamilyIndex |
| queueFamilyIndex, // deUint32 dstQueueFamilyIndex |
| **m_images[imageIdx], // VkImage image |
| subresourceRange // VkImageSubresourceRange subresourceRange |
| }; |
| |
| beginCommandBuffer(vk, *cmdBuffer); |
| vk.cmdPipelineBarrier(*cmdBuffer, |
| VK_PIPELINE_STAGE_HOST_BIT, |
| VK_PIPELINE_STAGE_TRANSFER_BIT, |
| (VkDependencyFlags)0u, |
| 0u, (const VkMemoryBarrier*)DE_NULL, |
| 0u, (const VkBufferMemoryBarrier*)DE_NULL, |
| 1u, &preImageBarrier); |
| vk.cmdClearColorImage(*cmdBuffer, **m_images[imageIdx], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColor.color, 1, &subresourceRange); |
| vk.cmdPipelineBarrier(*cmdBuffer, |
| VK_PIPELINE_STAGE_TRANSFER_BIT, |
| pipelineType == PIPELINE_TYPE_COMPUTE ? VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT : VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, |
| (VkDependencyFlags)0u, |
| 0u, (const VkMemoryBarrier*)DE_NULL, |
| 0u, (const VkBufferMemoryBarrier*)DE_NULL, |
| 1u, &postImageBarrier); |
| endCommandBuffer(vk, *cmdBuffer); |
| submitCommandsAndWait(vk, device, queue, *cmdBuffer); |
| } |
| } |
| |
| VkWriteDescriptorSet ImageDescriptor::getDescriptorWrite (void) |
| { |
| const deUint32 firstElement = getFirstWrittenElement(); |
| |
| // Set and binding will be overwritten later |
| const VkWriteDescriptorSet descriptorWrite = |
| { |
| VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| (VkDescriptorSet)0u, // VkDescriptorSet dstSet |
| 0u, // deUint32 dstBinding |
| firstElement, // deUint32 dstArrayElement |
| getNumWrittenElements(), // deUint32 descriptorCount |
| getType(), // VkDescriptorType descriptorType |
| &m_descriptorImageInfos[firstElement], // const VkDescriptorImageInfo pImageInfo |
| DE_NULL, // const VkDescriptorBufferInfo* pBufferInfo |
| DE_NULL // const VkBufferView* pTexelBufferView |
| }; |
| |
| return descriptorWrite; |
| } |
| |
| InputAttachmentDescriptor::InputAttachmentDescriptor (deUint32 arraySize, |
| deUint32 writeStart, |
| deUint32 elementsToWrite, |
| deUint32 numDynamicAreas) |
| : ImageDescriptor(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, arraySize, writeStart, elementsToWrite, 1u) |
| , m_originalAttachmentIndex(s_nextAttachmentIndex) |
| { |
| DE_UNREF(numDynamicAreas); |
| |
| for (deUint32 i = 0; i < m_arraySize; i++) |
| m_attachmentIndices.push_back(s_nextAttachmentIndex++); |
| } |
| |
| InputAttachmentDescriptor::~InputAttachmentDescriptor (void) |
| { |
| } |
| |
| string InputAttachmentDescriptor::getShaderDeclaration (void) const |
| { |
| return string(", input_attachment_index=" + de::toString(m_originalAttachmentIndex) + ") uniform subpassInput inputAttachment" + de::toString(m_id) + getArrayString(m_arraySize) + ";\n"); |
| } |
| |
| string InputAttachmentDescriptor::getShaderVerifyCode (void) const |
| { |
| string ret; |
| |
| for (deUint32 i = 0; i < m_arraySize; i++) |
| { |
| if (m_data[i].written || m_data[i].copiedInto) |
| ret += string("if (subpassLoad(inputAttachment") + de::toString(m_id) + getArrayString(i) + ").x != " + de::toString(m_data[i].data[0]) + ") result = 0;\n"; |
| } |
| |
| return ret; |
| } |
| |
| void InputAttachmentDescriptor::copyValue (const Descriptor& src, |
| deUint32 srcElement, |
| deUint32 dstElement, |
| deUint32 numElements) |
| { |
| Descriptor::copyValue(src, srcElement, dstElement, numElements); |
| |
| for (deUint32 elementIdx = 0; elementIdx < numElements; elementIdx++) |
| { |
| m_attachmentIndices[elementIdx + dstElement] = reinterpret_cast<const InputAttachmentDescriptor&>(src).m_attachmentIndices[elementIdx + srcElement]; |
| } |
| } |
| |
| vector<VkAttachmentReference> InputAttachmentDescriptor::getAttachmentReferences (void) const |
| { |
| vector<VkAttachmentReference> references; |
| for (deUint32 i = 0; i < m_arraySize; i++) |
| { |
| const VkAttachmentReference attachmentReference = |
| { |
| // The first attachment is the color buffer, thus +1 |
| m_attachmentIndices[i] + 1, // deUint32 attachment |
| getImageLayout() // VkImageLayout layout |
| }; |
| |
| references.push_back(attachmentReference); |
| } |
| |
| return references; |
| } |
| |
| CombinedImageSamplerDescriptor::CombinedImageSamplerDescriptor (deUint32 arraySize, |
| deUint32 writeStart, |
| deUint32 elementsToWrite, |
| deUint32 numDynamicAreas) |
| : ImageDescriptor(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, arraySize, writeStart, elementsToWrite, 1u) |
| { |
| DE_UNREF(numDynamicAreas); |
| } |
| |
| CombinedImageSamplerDescriptor::~CombinedImageSamplerDescriptor (void) |
| { |
| } |
| |
| string CombinedImageSamplerDescriptor::getShaderDeclaration (void) const |
| { |
| return string(") uniform sampler2D texSampler" + de::toString(m_id) + getArrayString(m_arraySize) + ";\n"); |
| } |
| |
| string CombinedImageSamplerDescriptor::getShaderVerifyCode (void) const |
| { |
| string ret; |
| |
| for (deUint32 i = 0; i < m_arraySize; i++) |
| { |
| if (m_data[i].written || m_data[i].copiedInto) |
| ret += string("if (texture(texSampler") + de::toString(m_id) + getArrayString(i) + ", vec2(0)).x != " + de::toString(m_data[i].data[0]) + ") result = 0;\n"; |
| } |
| |
| return ret; |
| } |
| |
| SampledImageDescriptor::SampledImageDescriptor (deUint32 arraySize, |
| deUint32 writeStart, |
| deUint32 elementsToWrite, |
| deUint32 numDynamicAreas) |
| : ImageDescriptor(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, arraySize, writeStart, elementsToWrite, 1u) |
| { |
| DE_UNREF(numDynamicAreas); |
| } |
| |
| SampledImageDescriptor::~SampledImageDescriptor (void) |
| { |
| } |
| |
| string SampledImageDescriptor::getShaderDeclaration (void) const |
| { |
| return string(") uniform texture2D sampledImage" + de::toString(m_id) + getArrayString(m_arraySize) + ";\n"); |
| } |
| |
| string SampledImageDescriptor::getShaderVerifyCode (void) const |
| { |
| string ret; |
| |
| for (deUint32 i = 0; i < m_arraySize; i++) |
| { |
| if ((m_data[i].written || m_data[i].copiedInto) && m_samplers.size() > i) |
| { |
| ret += string("if (texture(sampler2D(sampledImage") + de::toString(m_id) + getArrayString(i) + ", sampler" + de::toString(m_samplers[i]->getId()) + "), vec2(0)).x != " + de::toString(m_data[i].data[0]) + ") result = 0;\n"; |
| } |
| } |
| |
| return ret; |
| } |
| |
| StorageImageDescriptor::StorageImageDescriptor (deUint32 arraySize, |
| deUint32 writeStart, |
| deUint32 elementsToWrite, |
| deUint32 numDynamicAreas) |
| : ImageDescriptor(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, arraySize, writeStart, elementsToWrite, 1u) |
| { |
| DE_UNREF(numDynamicAreas); |
| } |
| |
| StorageImageDescriptor::~StorageImageDescriptor (void) |
| { |
| } |
| |
| string StorageImageDescriptor::getShaderDeclaration (void) const |
| { |
| return string(", r32f) readonly uniform image2D image" + de::toString(m_id) + getArrayString(m_arraySize) + ";\n"); |
| } |
| |
| string StorageImageDescriptor::getShaderVerifyCode (void) const |
| { |
| string ret; |
| |
| for (deUint32 i = 0; i < m_arraySize; i++) |
| { |
| if (m_data[i].written || m_data[i].copiedInto) |
| ret += string("if (imageLoad(image") + de::toString(m_id) + getArrayString(i) + ", ivec2(0)).x != " + de::toString(m_data[i].data[0]) + ") result = 0;\n"; |
| } |
| |
| return ret; |
| } |
| |
| SamplerDescriptor::SamplerDescriptor (deUint32 arraySize, |
| deUint32 writeStart, |
| deUint32 elementsToWrite, |
| deUint32 numDynamicAreas) |
| : Descriptor(VK_DESCRIPTOR_TYPE_SAMPLER, arraySize, writeStart, elementsToWrite, 1u) |
| { |
| DE_UNREF(numDynamicAreas); |
| } |
| |
| SamplerDescriptor::~SamplerDescriptor (void) |
| { |
| } |
| |
| void SamplerDescriptor::init (Context& context, |
| PipelineType pipelineType) |
| { |
| DE_UNREF(pipelineType); |
| |
| const DeviceInterface& vk = context.getDeviceInterface(); |
| const VkDevice device = context.getDevice(); |
| const VkFormat format = VK_FORMAT_R32_SFLOAT; |
| |
| // Create samplers |
| for (deUint32 i = 0; i < m_arraySize; i++) |
| { |
| const float borderValue = (float)((m_id + i) % 2); |
| const tcu::Sampler sampler = tcu::Sampler(tcu::Sampler::CLAMP_TO_BORDER, tcu::Sampler::CLAMP_TO_BORDER, tcu::Sampler::CLAMP_TO_BORDER, tcu::Sampler::NEAREST, tcu::Sampler::NEAREST, 0.0f, true, tcu::Sampler::COMPAREMODE_NONE, 0, Vec4(borderValue)); |
| const tcu::TextureFormat texFormat = mapVkFormat(format); |
| const VkSamplerCreateInfo samplerParams = mapSampler(sampler, texFormat); |
| |
| m_samplers.push_back(VkSamplerSp(new Unique<VkSampler>(createSampler(vk, device, &samplerParams)))); |
| } |
| |
| // Create descriptor image infos |
| for (deUint32 i = 0; i < m_arraySize; i++) |
| { |
| const VkDescriptorImageInfo imageInfo = |
| { |
| **m_samplers[i], // VkSampler sampler |
| DE_NULL, // VkImageView imageView |
| VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout imageLayout |
| }; |
| |
| m_descriptorImageInfos.push_back(imageInfo); |
| } |
| } |
| |
| VkWriteDescriptorSet SamplerDescriptor::getDescriptorWrite (void) |
| { |
| const deUint32 firstElement = getFirstWrittenElement(); |
| |
| // Set and binding will be overwritten later |
| const VkWriteDescriptorSet descriptorWrite = |
| { |
| VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| (VkDescriptorSet)0u, // VkDescriptorSet dstSet |
| 0u, // deUint32 dstBinding |
| firstElement, // deUint32 dstArrayElement |
| getNumWrittenElements(), // deUint32 descriptorCount |
| getType(), // VkDescriptorType descriptorType |
| &m_descriptorImageInfos[firstElement], // const VkDescriptorImageInfo pImageInfo |
| DE_NULL, // const VkDescriptorBufferInfo* pBufferInfo |
| DE_NULL // const VkBufferView* pTexelBufferView |
| }; |
| |
| return descriptorWrite; |
| } |
| |
| string SamplerDescriptor::getShaderDeclaration (void) const |
| { |
| return string(") uniform sampler sampler" + de::toString(m_id) + getArrayString(m_arraySize) + ";\n"); |
| } |
| |
| string SamplerDescriptor::getShaderVerifyCode (void) const |
| { |
| string ret; |
| |
| for (deUint32 i = 0; i < m_arraySize; i++) |
| { |
| if ((m_data[i].written || m_data[i].copiedInto) && m_images.size() > i) |
| { |
| // Sample from (-1, -1) to get border color. |
| ret += string("if (texture(sampler2D(sampledImage") + de::toString(m_images[i]->getId()) + ", sampler" + de::toString(m_id) + getArrayString(i) + "), vec2(-1)).x != " + de::toString(m_data[i].data[0] % 2) + ") result = 0;\n"; |
| } |
| } |
| |
| return ret; |
| } |
| |
| DescriptorSet::DescriptorSet (void) |
| { |
| } |
| |
| DescriptorSet::~DescriptorSet (void) |
| { |
| } |
| |
| void DescriptorSet::addBinding (DescriptorSp descriptor) |
| { |
| m_bindings.push_back(descriptor); |
| } |
| |
| DescriptorCommands::DescriptorCommands (PipelineType pipelineType) |
| : m_pipelineType(pipelineType) |
| { |
| // Reset counters |
| Descriptor::s_nextId = 0xabc; |
| InputAttachmentDescriptor::s_nextAttachmentIndex = 0; |
| } |
| |
| DescriptorCommands::~DescriptorCommands (void) |
| { |
| } |
| |
| void DescriptorCommands::addDescriptor (DescriptorSp descriptor, |
| deUint32 descriptorSet) |
| { |
| const VkDescriptorType type = descriptor->getType(); |
| |
| // Create descriptor set objects until one with the given index exists |
| while (m_descriptorSets.size() <= descriptorSet) |
| m_descriptorSets.push_back(DescriptorSetSp(new DescriptorSet())); |
| |
| m_descriptorSets[descriptorSet]->addBinding(descriptor); |
| |
| // Keep track of how many descriptors of each type is needed. Inline uniform blocks cannot form arrays. We reuse the array size |
| // as size of the data array for them, within a single descriptor. |
| const deUint32 count = ((type == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT) ? 1u : descriptor->getArraySize()); |
| if (m_descriptorCounts.find(type) != m_descriptorCounts.end()) |
| m_descriptorCounts[type] += count; |
| else |
| m_descriptorCounts[type] = count; |
| |
| // Keep descriptors also in a flat list for easier iteration |
| m_descriptors.push_back(descriptor); |
| } |
| |
| void DescriptorCommands::copyDescriptor (deUint32 srcSet, |
| deUint32 srcBinding, |
| deUint32 srcArrayElement, |
| deUint32 dstSet, |
| deUint32 dstBinding, |
| deUint32 dstArrayElement, |
| deUint32 descriptorCount) |
| { |
| // For inline uniform blocks, (src|dst)ArrayElement are data array indices and descriptorCount is the number of integers to copy. |
| DescriptorCopy descriptorCopy = { srcSet, srcBinding, srcArrayElement, dstSet, dstBinding, dstArrayElement, descriptorCount }; |
| |
| if (m_descriptorSets[srcSet]->getBindings()[srcBinding]->getType() == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT) |
| { |
| // For inline uniform blocks, these members of VkCopyDescriptorSet are offsets and sizes in bytes. |
| const InlineUniformBlockDescriptor* iub = static_cast<InlineUniformBlockDescriptor*>(m_descriptorSets[srcSet]->getBindings()[srcBinding].get()); |
| const deUint32 elementSize = iub->getElementSizeInBytes(); |
| |
| descriptorCopy.srcArrayElement *= elementSize; |
| descriptorCopy.dstArrayElement *= elementSize; |
| descriptorCopy.descriptorCount *= elementSize; |
| } |
| |
| m_descriptorCopies.push_back(descriptorCopy); |
| m_descriptorSets[descriptorCopy.dstSet]->getBindings()[descriptorCopy.dstBinding]->copyValue(*m_descriptorSets[descriptorCopy.srcSet]->getBindings()[descriptorCopy.srcBinding], srcArrayElement, dstArrayElement, descriptorCount); |
| } |
| |
| // Generates shader source code for declarations of all descriptors |
| string DescriptorCommands::getShaderDeclarations (void) const |
| { |
| string ret; |
| |
| for (size_t descriptorSetIdx = 0; descriptorSetIdx < m_descriptorSets.size(); descriptorSetIdx++) |
| { |
| const vector<DescriptorSp> bindings = m_descriptorSets[descriptorSetIdx]->getBindings(); |
| |
| for (size_t bindingIdx = 0; bindingIdx < bindings.size(); bindingIdx++) |
| { |
| ret += "layout (set=" + de::toString(descriptorSetIdx) + ", binding=" + de::toString(bindingIdx) + bindings[bindingIdx]->getShaderDeclaration(); |
| } |
| } |
| |
| return ret; |
| } |
| |
| // Generates shader source code for verification of all descriptor data |
| string DescriptorCommands::getDescriptorVerifications (void) const |
| { |
| string ret; |
| |
| for (size_t descriptorSetIdx = 0; descriptorSetIdx < m_descriptorSets.size(); descriptorSetIdx++) |
| { |
| const vector<DescriptorSp> bindings = m_descriptorSets[descriptorSetIdx]->getBindings(); |
| |
| for (size_t bindingIdx = 0; bindingIdx < bindings.size(); bindingIdx++) |
| { |
| if (m_pipelineType == PIPELINE_TYPE_COMPUTE && descriptorSetIdx == 0 && bindingIdx == bindings.size() - 1) continue; // Skip the result buffer which is always the last descriptor of set 0 |
| ret += bindings[bindingIdx]->getShaderVerifyCode(); |
| } |
| } |
| |
| return ret; |
| } |
| |
| void DescriptorCommands::addResultBuffer (void) |
| { |
| // Add result buffer if using compute pipeline |
| if (m_pipelineType == PIPELINE_TYPE_COMPUTE) |
| { |
| m_resultBuffer = DescriptorSp(new StorageBufferDescriptor()); |
| addDescriptor(m_resultBuffer, 0u); |
| } |
| } |
| |
| // Sets the list of dynamic areas selected for each dynamic descriptor when running the verification shader |
| void DescriptorCommands::setDynamicAreas (vector<deUint32> areas) |
| { |
| m_dynamicAreas = areas; |
| deUint32 areaIdx = 0; |
| |
| for (vector<DescriptorSp>::iterator desc = m_descriptors.begin(); desc != m_descriptors.end(); desc++) |
| { |
| if ((*desc)->isDynamic()) |
| { |
| vector<deUint32> dynamicAreas; |
| |
| for (deUint32 elementIdx = 0; elementIdx < (*desc)->getArraySize(); elementIdx++) |
| dynamicAreas.push_back(areas[areaIdx++]); |
| |
| (*desc)->setDynamicAreas(dynamicAreas); |
| } |
| } |
| } |
| |
| bool DescriptorCommands::hasDynamicAreas (void) const |
| { |
| for (vector<DescriptorSp>::const_iterator desc = m_descriptors.begin(); desc != m_descriptors.end(); desc++) |
| if ((*desc)->isDynamic()) |
| return true; |
| |
| return false; |
| } |
| |
| tcu::TestStatus DescriptorCommands::run (Context& context) |
| { |
| const InstanceInterface& vki = context.getInstanceInterface(); |
| const DeviceInterface& vk = context.getDeviceInterface(); |
| const VkDevice device = context.getDevice(); |
| const VkQueue queue = context.getUniversalQueue(); |
| const VkPhysicalDevice physicalDevice = context.getPhysicalDevice(); |
| const VkPhysicalDeviceLimits limits = getPhysicalDeviceProperties(vki, physicalDevice).limits; |
| const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); |
| Allocator& allocator = context.getDefaultAllocator(); |
| tcu::TestLog& log = context.getTestContext().getLog(); |
| const Unique<VkCommandPool> commandPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex)); |
| const Unique<VkCommandBuffer> commandBuffer (allocateCommandBuffer(vk, device, *commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY)); |
| const VkShaderStageFlags shaderStage = m_pipelineType == PIPELINE_TYPE_COMPUTE ? VK_SHADER_STAGE_COMPUTE_BIT : VK_SHADER_STAGE_FRAGMENT_BIT; |
| const VkFormat resultFormat = VK_FORMAT_R8G8B8A8_UNORM; |
| deUint32 numTotalIUBs = 0; |
| deUint32 iubTotalBytes = 0; |
| de::MovePtr<ImageWithMemory> resultImage; |
| de::MovePtr<BufferWithMemory> resultImageBuffer; |
| Move<VkImageView> resultImageView; |
| Move<VkRenderPass> renderPass; |
| Move<VkFramebuffer> framebuffer; |
| Move<VkDescriptorPool> descriptorPool; |
| vector<VkDescriptorSetLayoutSp> descriptorSetLayouts; |
| vector<VkDescriptorSet> descriptorSets; |
| Move<VkPipelineLayout> pipelineLayout; |
| Move<VkPipeline> pipeline; |
| vector<VkAttachmentReference> inputAttachments; |
| vector<VkAttachmentDescription> attachmentDescriptions; |
| vector<VkImageView> imageViews; |
| |
| if (limits.maxBoundDescriptorSets <= m_descriptorSets.size()) |
| TCU_THROW(NotSupportedError, "Maximum bound descriptor sets limit exceeded."); |
| |
| // Check if inline uniform blocks are supported. |
| VkPhysicalDeviceInlineUniformBlockFeaturesEXT iubFeatures = |
| { |
| VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES_EXT, |
| DE_NULL, |
| VK_FALSE, VK_FALSE |
| }; |
| VkPhysicalDeviceInlineUniformBlockPropertiesEXT iubProperties = |
| { |
| VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES_EXT, |
| DE_NULL, |
| 0u, 0u, 0u, 0u, 0u |
| }; |
| { |
| if (context.isDeviceFunctionalitySupported("VK_EXT_inline_uniform_block")) |
| { |
| VkPhysicalDeviceFeatures2 features2; |
| deMemset(&features2, 0, sizeof(features2)); |
| features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; |
| features2.pNext = &iubFeatures; |
| vki.getPhysicalDeviceFeatures2(physicalDevice, &features2); |
| |
| VkPhysicalDeviceProperties2 properties2; |
| deMemset(&properties2, 0, sizeof(properties2)); |
| properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; |
| properties2.pNext = &iubProperties; |
| vki.getPhysicalDeviceProperties2(physicalDevice, &properties2); |
| } |
| } |
| |
| // Check physical device limits of per stage and per desriptor set descriptor count |
| { |
| deUint32 numPerStageSamplers = 0; |
| deUint32 numPerStageUniformBuffers = 0; |
| deUint32 numPerStageStorageBuffers = 0; |
| deUint32 numPerStageSampledImages = 0; |
| deUint32 numPerStageStorageImages = 0; |
| deUint32 numPerStageInputAttachments = 0; |
| deUint32 numPerStageTotalResources = 0; |
| |
| for (size_t descriptorSetIdx = 0; descriptorSetIdx < m_descriptorSets.size(); descriptorSetIdx++) |
| { |
| deUint32 numSamplers = 0; |
| deUint32 numUniformBuffers = 0; |
| deUint32 numUniformBuffersDynamic = 0; |
| deUint32 numStorageBuffers = 0; |
| deUint32 numStorageBuffersDynamic = 0; |
| deUint32 numSampledImages = 0; |
| deUint32 numStorageImages = 0; |
| deUint32 numInputAttachments = 0; |
| deUint32 numIUBs = 0; |
| deUint32 numTotalResources = m_pipelineType == PIPELINE_TYPE_GRAPHICS ? 1u : 0u; // Color buffer counts as a resource. |
| |
| const vector<DescriptorSp>& bindings = m_descriptorSets[descriptorSetIdx]->getBindings(); |
| |
| for (size_t bindingIdx = 0; bindingIdx < bindings.size(); bindingIdx++) |
| { |
| const deUint32 arraySize = bindings[bindingIdx]->getArraySize(); |
| |
| // Inline uniform blocks cannot form arrays. The array size is the size of the data array in the descriptor. |
| if (bindings[bindingIdx]->getType() == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT) |
| { |
| const InlineUniformBlockDescriptor* iub = static_cast<InlineUniformBlockDescriptor*>(bindings[bindingIdx].get()); |
| const deUint32 bytes = iub->getSizeInBytes(); |
| |
| // Check inline uniform block size. |
| if (bytes > iubProperties.maxInlineUniformBlockSize) |
| { |
| std::ostringstream msg; |
| msg << "Maximum size for an inline uniform block exceeded by binding " |
| << bindingIdx << " from set " << descriptorSetIdx; |
| TCU_THROW(NotSupportedError, msg.str().c_str()); |
| } |
| |
| iubTotalBytes += bytes; |
| ++numTotalResources; |
| } |
| else |
| { |
| numTotalResources += arraySize; |
| } |
| |
| switch (bindings[bindingIdx]->getType()) |
| { |
| case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: |
| numUniformBuffers += arraySize; |
| break; |
| |
| case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: |
| numUniformBuffers += arraySize; |
| numUniformBuffersDynamic += arraySize; |
| break; |
| |
| case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: |
| numStorageBuffers += arraySize; |
| break; |
| |
| case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: |
| numStorageBuffers += arraySize; |
| numStorageBuffersDynamic += arraySize; |
| break; |
| |
| case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: |
| numSamplers += arraySize; |
| numSampledImages += arraySize; |
| break; |
| |
| case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: |
| case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: |
| numStorageImages += arraySize; |
| break; |
| |
| case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: |
| numInputAttachments += arraySize; |
| break; |
| |
| case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: |
| case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: |
| numSampledImages += arraySize; |
| break; |
| |
| case VK_DESCRIPTOR_TYPE_SAMPLER: |
| numSamplers += arraySize; |
| break; |
| |
| case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT: |
| ++numIUBs; |
| break; |
| |
| default: |
| DE_FATAL("Unexpected descriptor type"); |
| break; |
| } |
| } |
| |
| if (numSamplers > limits.maxDescriptorSetSamplers) |
| TCU_THROW(NotSupportedError, "Maximum per descriptor set sampler limit exceeded."); |
| |
| if (numUniformBuffers > limits.maxDescriptorSetUniformBuffers) |
| TCU_THROW(NotSupportedError, "Maximum per descriptor set uniform buffer limit exceeded."); |
| |
| if (numUniformBuffersDynamic > limits.maxDescriptorSetUniformBuffersDynamic) |
| TCU_THROW(NotSupportedError, "Maximum per descriptor set uniform buffer dynamic limit exceeded."); |
| |
| if (numStorageBuffers > limits.maxDescriptorSetStorageBuffers) |
| TCU_THROW(NotSupportedError, "Maximum per descriptor set storage buffer limit exceeded."); |
| |
| if (numStorageBuffersDynamic > limits.maxDescriptorSetStorageBuffersDynamic) |
| TCU_THROW(NotSupportedError, "Maximum per descriptor set storage buffer dynamic limit exceeded."); |
| |
| if (numSampledImages > limits.maxDescriptorSetSampledImages) |
| TCU_THROW(NotSupportedError, "Maximum per descriptor set sampled image limit exceeded."); |
| |
| if (numStorageImages > limits.maxDescriptorSetStorageImages) |
| TCU_THROW(NotSupportedError, "Maximum per descriptor set storage image limit exceeded."); |
| |
| if (numInputAttachments > limits.maxDescriptorSetInputAttachments) |
| TCU_THROW(NotSupportedError, "Maximum per descriptor set input attachment limit exceeded."); |
| |
| numPerStageSamplers += numSamplers; |
| numPerStageUniformBuffers += numUniformBuffers; |
| numPerStageStorageBuffers += numStorageBuffers; |
| numPerStageSampledImages += numSampledImages; |
| numPerStageStorageImages += numStorageImages; |
| numPerStageInputAttachments += numInputAttachments; |
| numPerStageTotalResources += numTotalResources; |
| numTotalIUBs += numIUBs; |
| } |
| |
| if (numPerStageTotalResources > limits.maxPerStageResources) |
| TCU_THROW(NotSupportedError, "Maximum per stage total resource limit exceeded."); |
| |
| if (numPerStageSamplers > limits.maxPerStageDescriptorSamplers) |
| TCU_THROW(NotSupportedError, "Maximum per stage sampler limit exceeded."); |
| |
| if (numPerStageUniformBuffers > limits.maxPerStageDescriptorUniformBuffers) |
| TCU_THROW(NotSupportedError, "Maximum per stage uniform buffer limit exceeded."); |
| |
| if (numPerStageStorageBuffers > limits.maxPerStageDescriptorStorageBuffers) |
| TCU_THROW(NotSupportedError, "Maximum per stage storage buffer limit exceeded."); |
| |
| if (numPerStageSampledImages > limits.maxPerStageDescriptorSampledImages) |
| TCU_THROW(NotSupportedError, "Maximum per stage sampled image limit exceeded."); |
| |
| if (numPerStageStorageImages > limits.maxPerStageDescriptorStorageImages) |
| TCU_THROW(NotSupportedError, "Maximum per stage storage image limit exceeded."); |
| |
| if (numPerStageInputAttachments > limits.maxPerStageDescriptorInputAttachments) |
| TCU_THROW(NotSupportedError, "Maximum per stage input attachment limit exceeded."); |
| |
| if (numTotalIUBs > iubProperties.maxDescriptorSetInlineUniformBlocks || |
| numTotalIUBs > iubProperties.maxPerStageDescriptorInlineUniformBlocks) |
| { |
| TCU_THROW(NotSupportedError, "Number of per stage inline uniform blocks exceeds limits."); |
| } |
| } |
| |
| // Initialize all descriptors |
| for (vector<DescriptorSp>::iterator desc = m_descriptors.begin(); desc != m_descriptors.end(); desc++) |
| (*desc)->init(context, m_pipelineType); |
| |
| // Create descriptor pool |
| { |
| vector<VkDescriptorPoolSize> poolSizes; |
| |
| for (map<VkDescriptorType, deUint32>::iterator i = m_descriptorCounts.begin(); i != m_descriptorCounts.end(); i++) |
| { |
| VkDescriptorPoolSize poolSize = |
| { |
| i->first, // VkDescriptorType type |
| i->second // deUint32 descriptorCount |
| }; |
| |
| // Inline uniform blocks have a special meaning for descriptorCount. |
| if (poolSize.type == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT) |
| poolSize.descriptorCount = iubTotalBytes; |
| |
| poolSizes.push_back(poolSize); |
| } |
| |
| VkDescriptorPoolCreateInfo descriptorPoolCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, // VkDescriptorPoolCreateFlags flags |
| (deUint32)m_descriptorSets.size(), // deUint32 maxSets |
| (deUint32)poolSizes.size(), // deUint32 poolSizeCount |
| poolSizes.data(), // const VkDescriptorPoolSize* pPoolSizes |
| }; |
| |
| // Include information about inline uniform blocks if needed. |
| VkDescriptorPoolInlineUniformBlockCreateInfoEXT iubPoolCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO_EXT, |
| DE_NULL, |
| numTotalIUBs |
| }; |
| if (numTotalIUBs > 0) |
| descriptorPoolCreateInfo.pNext = &iubPoolCreateInfo; |
| |
| descriptorPool = createDescriptorPool(vk, device, &descriptorPoolCreateInfo); |
| } |
| |
| // Create descriptor set layouts. One for each descriptor set used in this test. |
| { |
| for (size_t descriptorSetIdx = 0; descriptorSetIdx < m_descriptorSets.size(); descriptorSetIdx++) |
| { |
| vector<VkDescriptorSetLayoutBinding> layoutBindings; |
| const vector<DescriptorSp>& bindings = m_descriptorSets[descriptorSetIdx]->getBindings(); |
| |
| for (size_t bindingIdx = 0; bindingIdx < bindings.size(); bindingIdx++) |
| { |
| VkDescriptorSetLayoutBinding layoutBinding = |
| { |
| (deUint32)bindingIdx, // deUint32 binding |
| bindings[bindingIdx]->getType(), // VkDescriptorType descriptorType |
| bindings[bindingIdx]->getArraySize(), // deUint32 descriptorCount |
| shaderStage, // VkShaderStageFlags stageFlags |
| DE_NULL // const VkSampler* pImmutableSamplers |
| }; |
| |
| // Inline uniform blocks have a special meaning for descriptorCount. |
| if (layoutBinding.descriptorType == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT) |
| { |
| const InlineUniformBlockDescriptor* iub = static_cast<InlineUniformBlockDescriptor*>(bindings[bindingIdx].get()); |
| layoutBinding.descriptorCount = iub->getSizeInBytes(); |
| } |
| |
| layoutBindings.push_back(layoutBinding); |
| } |
| |
| const VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| 0u, // VkDescriptorSetLayoutCreateFlags flags |
| (deUint32)layoutBindings.size(), // deUint32 bindingCount |
| layoutBindings.data() // const VkDescriptorSetLayoutBinding* pBindings |
| }; |
| |
| descriptorSetLayouts.push_back(VkDescriptorSetLayoutSp(new Unique<VkDescriptorSetLayout>(createDescriptorSetLayout(vk, device, &descriptorSetLayoutCreateInfo, DE_NULL)))); |
| } |
| } |
| |
| // Create descriptor sets |
| { |
| for (size_t descriptorSetIdx = 0; descriptorSetIdx < m_descriptorSets.size(); descriptorSetIdx++) |
| { |
| const VkDescriptorSetAllocateInfo descriptorSetAllocateInfo = |
| { |
| VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| *descriptorPool, // VkDescriptorPool descriptorPool |
| 1u, // deUint32 descriptorSetCount |
| &(descriptorSetLayouts[descriptorSetIdx]->get()) // const VkDescriptorSetLayout* pSetLayouts |
| }; |
| |
| VkDescriptorSet descriptorSet = 0; |
| VK_CHECK(vk.allocateDescriptorSets(device, &descriptorSetAllocateInfo, &descriptorSet)); |
| descriptorSets.push_back(descriptorSet); |
| } |
| } |
| |
| // Descriptor writes and updates |
| { |
| vector<VkWriteDescriptorSet> descriptorWrites; |
| vector<VkCopyDescriptorSet> descriptorCopies; |
| |
| // Write descriptors that are marked as needing initialization |
| for (size_t descriptorSetIdx = 0; descriptorSetIdx < m_descriptorSets.size(); descriptorSetIdx++) |
| { |
| const vector<DescriptorSp>& bindings = m_descriptorSets[descriptorSetIdx]->getBindings(); |
| |
| for (size_t bindingIdx = 0; bindingIdx < bindings.size(); bindingIdx++) |
| { |
| VkWriteDescriptorSet descriptorWrite = bindings[bindingIdx]->getDescriptorWrite(); |
| |
| descriptorWrite.dstSet = descriptorSets[descriptorSetIdx]; |
| descriptorWrite.dstBinding = (deUint32)bindingIdx; |
| |
| if (descriptorWrite.descriptorCount > 0) |
| descriptorWrites.push_back(descriptorWrite); |
| } |
| } |
| |
| for (size_t copyIdx = 0; copyIdx < m_descriptorCopies.size(); copyIdx++) |
| { |
| const DescriptorCopy indices = m_descriptorCopies[copyIdx]; |
| const VkCopyDescriptorSet copy = |
| { |
| VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| descriptorSets[indices.srcSet], // VkDescriptorSet srcSet |
| indices.srcBinding, // deUint32 srcBinding |
| indices.srcArrayElement, // deUint32 srcArrayElement |
| descriptorSets[indices.dstSet], // VkDescriptorSet dstSet |
| indices.dstBinding, // deUint32 dstBinding |
| indices.dstArrayElement, // deUint32 dstArrayElement |
| indices.descriptorCount // deUint32 descriptorCount |
| }; |
| |
| descriptorCopies.push_back(copy); |
| } |
| |
| // Update descriptors with writes and copies |
| vk.updateDescriptorSets(device, (deUint32)descriptorWrites.size(), descriptorWrites.data(), (deUint32)descriptorCopies.size(), descriptorCopies.data()); |
| } |
| |
| // Create pipeline layout |
| { |
| vector<VkDescriptorSetLayout> descriptorSetLayoutHandles; |
| |
| for (size_t i = 0; i < descriptorSetLayouts.size(); i++) |
| descriptorSetLayoutHandles.push_back(descriptorSetLayouts[i]->get()); |
| |
| const VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| 0u, // VkPipelineLayoutCreateFlags flags |
| (deUint32)descriptorSetLayoutHandles.size(), // deUint32 setLayoutCount |
| descriptorSetLayoutHandles.data(), // const VkDescriptorSetLayout* pSetLayouts |
| 0u, // deUint32 pushConstantRangeCount |
| DE_NULL // const VkPushConstantRange* pPushConstantRanges |
| }; |
| |
| pipelineLayout = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo); |
| } |
| |
| if (m_pipelineType == PIPELINE_TYPE_COMPUTE) |
| { |
| // Create compute pipeline |
| { |
| const Unique<VkShaderModule> shaderModule (createShaderModule(vk, device, context.getBinaryCollection().get("compute"), 0u)); |
| const VkPipelineShaderStageCreateInfo shaderStageInfo = |
| { |
| VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags |
| VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlagBits stage |
| *shaderModule, // VkShaderModule module |
| "main", // const char* pName |
| DE_NULL // const VkSpecializationInfo* pSpecializationInfo |
| }; |
| |
| const VkComputePipelineCreateInfo pipelineInfo = |
| { |
| VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| (VkPipelineCreateFlags)0, // VkPipelineCreateFlags flags |
| shaderStageInfo, // VkPipelineShaderStageCreateInfo stage |
| *pipelineLayout, // VkPipelineLayout layout |
| DE_NULL, // VkPipeline basePipelineHandle |
| 0 // deInt32 basePipelineIndex |
| }; |
| |
| pipeline = createComputePipeline(vk, device, DE_NULL, &pipelineInfo); |
| } |
| } |
| else |
| { |
| // Create result image |
| { |
| const VkImageCreateInfo imageCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType stype |
| DE_NULL, // const void* pNext |
| 0u, // VkImageCreateFlags flags |
| VK_IMAGE_TYPE_2D, // VkImageType imageType |
| resultFormat, // VkFormat format |
| { (deUint32)renderSize.x(), (deUint32)renderSize.y(), 1 }, // VkExtent3D extent |
| 1u, // deUint32 mipLevels |
| 1u, // deUint32 arrayLayers |
| VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples |
| VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling |
| VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
| | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage |
| VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode |
| 1u, // deUint32 queueFamilyIndexCount |
| &queueFamilyIndex, // const deUint32* pQueueFamilyIndices |
| VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout |
| }; |
| |
| resultImage = de::MovePtr<ImageWithMemory>(new ImageWithMemory(vk, device, allocator, imageCreateInfo, MemoryRequirement::Any)); |
| } |
| |
| // Create result image view |
| { |
| const VkComponentMapping componentMapping = makeComponentMappingRGBA(); |
| |
| const VkImageSubresourceRange subresourceRange = |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask |
| 0u, // deUint32 baseMipLevel |
| 1u, // deUint32 levelCount |
| 0u, // deUint32 baseArrayLayer |
| 1u, // deUint32 layerCount |
| }; |
| |
| const VkImageViewCreateInfo imageViewCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| 0u, // VkImageViewCreateFlags flags |
| **resultImage, // VkImage image |
| VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType |
| resultFormat, // VkFormat format |
| componentMapping, // VkComponentMapping components |
| subresourceRange // VkImageSubresourceRange subresourceRange |
| }; |
| |
| resultImageView = createImageView(vk, device, &imageViewCreateInfo); |
| } |
| |
| // Create result buffer |
| { |
| const VkDeviceSize bufferSize = renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(resultFormat)); |
| const VkBufferCreateInfo bufferCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| 0u, // VkBufferCreateFlags flags |
| bufferSize, // VkDeviceSize size |
| VK_BUFFER_USAGE_TRANSFER_DST_BIT, // VkBufferUsageFlags usage |
| VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode |
| 0u, // uint32_t queueFamilyIndexCount |
| DE_NULL // const uint32_t* pQueueFamilyIndices |
| }; |
| |
| resultImageBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible)); |
| } |
| |
| // Create render pass |
| { |
| const VkAttachmentReference colorAttachmentRef = |
| { |
| 0u, // deUint32 attachment |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout |
| }; |
| |
| for (vector<DescriptorSp>::const_iterator desc = m_descriptors.begin(); desc != m_descriptors.end(); desc++) |
| { |
| vector<VkAttachmentReference> references = (*desc)->getAttachmentReferences(); |
| inputAttachments.insert(inputAttachments.end(), references.begin(), references.end()); |
| } |
| |
| const VkAttachmentDescription colorAttachmentDesc = |
| { |
| 0u, // VkAttachmentDescriptionFlags flags |
| VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format |
| VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples |
| VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp |
| VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp |
| VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp |
| VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp |
| VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout |
| }; |
| |
| attachmentDescriptions.push_back(colorAttachmentDesc); |
| |
| const VkAttachmentDescription inputAttachmentDesc = |
| { |
| 0u, // VkAttachmentDescriptionFlags flags |
| VK_FORMAT_R32_SFLOAT, // VkFormat format |
| VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples |
| VK_ATTACHMENT_LOAD_OP_LOAD, // VkAttachmentLoadOp loadOp |
| VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp storeOp |
| VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp |
| VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp |
| VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // VkImageLayout initialLayout |
| VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL // VkImageLayout finalLayout |
| }; |
| |
| for (size_t inputAttachmentIdx = 0; inputAttachmentIdx < inputAttachments.size(); inputAttachmentIdx++) |
| attachmentDescriptions.push_back(inputAttachmentDesc); |
| |
| const VkSubpassDescription subpassDescription = |
| { |
| 0u, // VkSubpassDescriptionFlags flags |
| VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint |
| (deUint32)inputAttachments.size(), // deUint32 inputAttachmentCount |
| inputAttachments.empty() ? DE_NULL : inputAttachments.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 renderPassCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| 0u, // VkRenderPassCreateFlags flags |
| (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 |
| }; |
| |
| renderPass = createRenderPass(vk, device, &renderPassCreateInfo); |
| } |
| |
| // Create framebuffer |
| { |
| imageViews.push_back(*resultImageView); |
| |
| // Add input attachment image views |
| for (vector<DescriptorSp>::const_iterator desc = m_descriptors.begin(); desc != m_descriptors.end(); desc++) |
| { |
| vector<VkImageViewSp> inputAttachmentViews = (*desc)->getImageViews(); |
| |
| for (size_t imageViewIdx = 0; imageViewIdx < inputAttachmentViews.size(); imageViewIdx++) |
| imageViews.push_back(**inputAttachmentViews[imageViewIdx]); |
| } |
| |
| const VkFramebufferCreateInfo framebufferCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| 0u, // VkFramebufferCreateFlags flags |
| *renderPass, // VkRenderPass renderPass |
| (deUint32)imageViews.size(), // deUint32 attachmentCount |
| imageViews.data(), // const VkImageView* pAttachments |
| (deUint32)renderSize.x(), // deUint32 width |
| (deUint32)renderSize.y(), // deUint32 height |
| 1u, // deUint32 layers |
| }; |
| |
| framebuffer = createFramebuffer(vk, device, &framebufferCreateInfo); |
| } |
| |
| // Create graphics pipeline |
| { |
| const Unique<VkShaderModule> vertexShaderModule (createShaderModule(vk, device, context.getBinaryCollection().get("vertex"), 0u)); |
| const Unique<VkShaderModule> fragmentShaderModule (createShaderModule(vk, device, context.getBinaryCollection().get("fragment"), 0u)); |
| |
| const VkPipelineVertexInputStateCreateInfo vertexInputStateParams = |
| { |
| VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags |
| 0u, // deUint32 bindingCount |
| DE_NULL, // const VkVertexInputBindingDescription* pVertexBindingDescriptions |
| 0u, // deUint32 attributeCount |
| DE_NULL, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions |
| }; |
| |
| const std::vector<VkViewport> viewports (1, makeViewport(renderSize)); |
| const std::vector<VkRect2D> scissors (1, makeRect2D(renderSize)); |
| |
| pipeline = makeGraphicsPipeline(vk, // const DeviceInterface& vk |
| device, // const VkDevice device |
| *pipelineLayout, // const VkPipelineLayout pipelineLayout |
| *vertexShaderModule, // const VkShaderModule vertexShaderModule |
| DE_NULL, // const VkShaderModule tessellationControlShaderModule |
| DE_NULL, // const VkShaderModule tessellationEvalShaderModule |
| DE_NULL, // const VkShaderModule geometryShaderModule |
| *fragmentShaderModule, // const VkShaderModule fragmentShaderModule |
| *renderPass, // const VkRenderPass renderPass |
| viewports, // const std::vector<VkViewport>& viewports |
| scissors, // const std::vector<VkRect2D>& scissors |
| VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // const VkPrimitiveTopology topology |
| 0u, // const deUint32 subpass |
| 0u, // const deUint32 patchControlPoints |
| &vertexInputStateParams); // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo |
| } |
| } |
| |
| // Run verification shader |
| { |
| const VkPipelineBindPoint pipelineBindPoint = m_pipelineType == PIPELINE_TYPE_COMPUTE ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS; |
| vector<deUint32> offsets; |
| |
| if (hasDynamicAreas()) |
| { |
| for (size_t areaIdx = 0; areaIdx < m_dynamicAreas.size(); areaIdx++) |
| offsets.push_back(m_dynamicAreas[areaIdx] * 256u); |
| } |
| |
| beginCommandBuffer(vk, *commandBuffer); |
| |
| if (m_pipelineType == PIPELINE_TYPE_GRAPHICS) |
| { |
| const VkRect2D renderArea = makeRect2D(renderSize); |
| const tcu::Vec4 clearColor (1.0f, 0.0f, 0.0f, 1.0f); |
| |
| beginRenderPass(vk, *commandBuffer, *renderPass, *framebuffer, renderArea, clearColor); |
| } |
| |
| vk.cmdBindPipeline(*commandBuffer, pipelineBindPoint, *pipeline); |
| vk.cmdBindDescriptorSets(*commandBuffer, pipelineBindPoint, *pipelineLayout, 0u, (deUint32)descriptorSets.size(), descriptorSets.data(), (deUint32)offsets.size(), offsets.empty() ? DE_NULL : offsets.data()); |
| |
| if (m_pipelineType == PIPELINE_TYPE_COMPUTE) |
| { |
| vk.cmdDispatch(*commandBuffer, 1u, 1u, 1u); |
| } |
| else |
| { |
| vk.cmdDraw(*commandBuffer, 6u, 1u, 0u, 0u); |
| endRenderPass(vk, *commandBuffer); |
| copyImageToBuffer(vk, *commandBuffer, **resultImage, resultImageBuffer->get(), renderSize); |
| } |
| |
| endCommandBuffer(vk, *commandBuffer); |
| submitCommandsAndWait(vk, device, queue, *commandBuffer); |
| } |
| |
| if (m_pipelineType == PIPELINE_TYPE_COMPUTE) |
| { |
| // Invalidate result buffer |
| m_resultBuffer->invalidate(context); |
| |
| // Verify result data |
| const auto data = m_resultBuffer->getData(); |
| if (data[0] == 1) |
| return tcu::TestStatus::pass("Pass"); |
| else |
| return tcu::TestStatus::fail("Data validation failed"); |
| } |
| else |
| { |
| invalidateAlloc(vk, device, resultImageBuffer->getAllocation()); |
| |
| // Verify result image |
| tcu::ConstPixelBufferAccess resultBufferAccess(mapVkFormat(resultFormat), renderSize.x(), renderSize.y(), 1, resultImageBuffer->getAllocation().getHostPtr()); |
| |
| for (deInt32 y = 0; y < renderSize.y(); y++) |
| for (deInt32 x = 0; x < renderSize.x(); x++) |
| { |
| Vec4 pixel = resultBufferAccess.getPixel(x, y, 0); |
| |
| if (pixel.x() != 0.0f || pixel.y() != 1.0f || pixel.z() != 0.0f || pixel.w() != 1.0f) |
| { |
| // Log result image before failing. |
| log << tcu::TestLog::ImageSet("Result", "") << tcu::TestLog::Image("Rendered", "Rendered image", resultBufferAccess) << tcu::TestLog::EndImageSet; |
| return tcu::TestStatus::fail("Result image validation failed"); |
| } |
| } |
| |
| return tcu::TestStatus::pass("Pass"); |
| } |
| } |
| |
| DescriptorCopyTestInstance::DescriptorCopyTestInstance (Context& context, |
| DescriptorCommandsSp commands) |
| : vkt::TestInstance (context) |
| , m_commands (commands) |
| { |
| } |
| |
| DescriptorCopyTestInstance::~DescriptorCopyTestInstance (void) |
| { |
| } |
| |
| DescriptorCopyTestCase::DescriptorCopyTestCase (tcu::TestContext& context, |
| const char* name, |
| const char* desc, |
| DescriptorCommandsSp commands) |
| : vkt::TestCase (context, name, desc) |
| , m_commands (commands) |
| { |
| } |
| |
| DescriptorCopyTestCase::~DescriptorCopyTestCase (void) |
| { |
| } |
| |
| void DescriptorCopyTestCase::initPrograms (SourceCollections& programCollection) const |
| { |
| if (m_commands->getPipelineType() == PIPELINE_TYPE_COMPUTE) |
| { |
| string computeSrc = |
| "#version 430\n" |
| "\n" |
| + m_commands->getShaderDeclarations() + |
| "\n" |
| "void main()\n" |
| "{\n" |
| "int result = 1;\n" |
| + m_commands->getDescriptorVerifications() + |
| "storageBuffer" + de::toString(m_commands->getResultBufferId()) + ".data = result;\n" |
| "}\n"; |
| |
| programCollection.glslSources.add("compute") << glu::ComputeSource(computeSrc); |
| } |
| else |
| { |
| // Produce quad vertices using vertex index |
| string vertexSrc = |
| "#version 450\n" |
| "out gl_PerVertex\n" |
| "{\n" |
| " vec4 gl_Position;\n" |
| "};\n" |
| "void main()\n" |
| "{\n" |
| " gl_Position = vec4(((gl_VertexIndex + 2) / 3) % 2 == 0 ? -1.0 : 1.0,\n" |
| " ((gl_VertexIndex + 1) / 3) % 2 == 0 ? -1.0 : 1.0, 0.0, 1.0);\n" |
| "}\n"; |
| |
| programCollection.glslSources.add("vertex") << glu::VertexSource(vertexSrc); |
| |
| string fragmentSrc = |
| "#version 430\n" |
| "\n" |
| + m_commands->getShaderDeclarations() + |
| "layout (location = 0) out vec4 outColor;\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| "int result = 1;\n" |
| + m_commands->getDescriptorVerifications() + |
| "if (result == 1) outColor = vec4(0, 1, 0, 1);\n" |
| "else outColor = vec4(1, 0, 1, 0);\n" |
| "}\n"; |
| |
| programCollection.glslSources.add("fragment") << glu::FragmentSource(fragmentSrc); |
| } |
| } |
| |
| TestInstance* DescriptorCopyTestCase::createInstance (Context& context) const |
| { |
| return new DescriptorCopyTestInstance(context, m_commands); |
| } |
| |
| tcu::TestStatus DescriptorCopyTestInstance::iterate (void) |
| { |
| return m_commands->run(m_context); |
| } |
| |
| template<class T> |
| void addDescriptorCopyTests (tcu::TestContext& testCtx, |
| de::MovePtr<tcu::TestCaseGroup>& group, |
| string name, |
| PipelineType pipelineType) |
| { |
| // Simple test copying inside the same set. |
| { |
| DescriptorCommandsSp commands (new DescriptorCommands(pipelineType)); |
| commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 3u)), 0u); |
| commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 2u)), 0u); |
| |
| commands->copyDescriptor(0u, 0u, // from |
| 0u, 1u); // to |
| |
| vector<deUint32> dynamicAreas; |
| dynamicAreas.push_back(2u); |
| dynamicAreas.push_back(1u); |
| commands->setDynamicAreas(dynamicAreas); |
| |
| commands->addResultBuffer(); |
| |
| group->addChild(new DescriptorCopyTestCase(testCtx, (name + "_0").c_str(), "", commands)); |
| } |
| |
| // Simple test copying between different sets. |
| { |
| DescriptorCommandsSp commands (new DescriptorCommands(pipelineType)); |
| commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 2u)), 0u); |
| commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 4u)), 1u); |
| |
| commands->copyDescriptor(0u, 0u, // from |
| 1u, 0u); // to |
| |
| vector<deUint32> dynamicAreas; |
| dynamicAreas.push_back(0u); |
| dynamicAreas.push_back(1u); |
| commands->setDynamicAreas(dynamicAreas); |
| |
| commands->addResultBuffer(); |
| |
| group->addChild(new DescriptorCopyTestCase(testCtx, (name + "_1").c_str(), "", commands)); |
| } |
| |
| // Simple test copying between different sets. Destination not updated. |
| { |
| DescriptorCommandsSp commands (new DescriptorCommands(pipelineType)); |
| commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 2u)), 0u); |
| commands->addDescriptor(DescriptorSp(new T(1u, 0u, 0u, 1u)), 1u); |
| |
| commands->copyDescriptor(0u, 0u, // from |
| 1u, 0u); // to |
| |
| vector<deUint32> dynamicAreas; |
| dynamicAreas.push_back(1u); |
| dynamicAreas.push_back(0u); |
| commands->setDynamicAreas(dynamicAreas); |
| |
| commands->addResultBuffer(); |
| |
| group->addChild(new DescriptorCopyTestCase(testCtx, (name + "_2").c_str(), "", commands)); |
| } |
| |
| // Five sets and several copies. |
| { |
| DescriptorCommandsSp commands (new DescriptorCommands(pipelineType)); |
| commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 3u)), 0u); |
| commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 4u)), 0u); |
| commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 2u)), 1u); |
| commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 1u)), 1u); |
| commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 2u)), 1u); |
| commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 5u)), 4u); |
| |
| commands->copyDescriptor(4u, 0u, // from |
| 0u, 0u); // to |
| |
| commands->copyDescriptor(0u, 1u, // from |
| 1u, 2u); // to |
| |
| commands->copyDescriptor(0u, 1u, // from |
| 1u, 1u); // to |
| |
| vector<deUint32> dynamicAreas; |
| dynamicAreas.push_back(1u); |
| dynamicAreas.push_back(0u); |
| dynamicAreas.push_back(1u); |
| dynamicAreas.push_back(0u); |
| dynamicAreas.push_back(0u); |
| dynamicAreas.push_back(4u); |
| commands->setDynamicAreas(dynamicAreas); |
| |
| commands->addResultBuffer(); |
| |
| group->addChild(new DescriptorCopyTestCase(testCtx, (name + "_3").c_str(), "", commands)); |
| } |
| |
| // Several identical copies |
| { |
| DescriptorCommandsSp commands (new DescriptorCommands(pipelineType)); |
| commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 2u)), 0u); |
| commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 4u)), 1u); |
| commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 2u)), 1u); |
| |
| for (deUint32 i = 0; i < 100; i++) |
| { |
| commands->copyDescriptor(0u, 0u, // from |
| 1u, 0u); // to |
| } |
| |
| commands->copyDescriptor(1u, 1u, // from |
| 0u, 0u); // to |
| |
| for (deUint32 i = 0; i < 100; i++) |
| { |
| commands->copyDescriptor(1u, 0u, // from |
| 1u, 1u); // to |
| } |
| |
| vector<deUint32> dynamicAreas; |
| dynamicAreas.push_back(0u); |
| dynamicAreas.push_back(1u); |
| dynamicAreas.push_back(1u); |
| commands->setDynamicAreas(dynamicAreas); |
| |
| commands->addResultBuffer(); |
| |
| group->addChild(new DescriptorCopyTestCase(testCtx, (name + "_4").c_str(), "", commands)); |
| } |
| |
| // Copy descriptors back and forth |
| { |
| DescriptorCommandsSp commands (new DescriptorCommands(pipelineType)); |
| commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 3u)), 0u); |
| commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 3u)), 1u); |
| commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 3u)), 1u); |
| |
| commands->copyDescriptor(0u, 0u, // from |
| 1u, 0u); // to |
| |
| commands->copyDescriptor(1u, 0u, // from |
| 0u, 0u); // to |
| |
| commands->copyDescriptor(1u, 1u, // from |
| 0u, 0u); // to |
| |
| commands->copyDescriptor(1u, 1u, // from |
| 0u, 0u); // to |
| |
| commands->copyDescriptor(1u, 0u, // from |
| 1u, 1u); // to |
| |
| vector<deUint32> dynamicAreas; |
| dynamicAreas.push_back(1u); |
| dynamicAreas.push_back(0u); |
| dynamicAreas.push_back(0u); |
| commands->setDynamicAreas(dynamicAreas); |
| |
| commands->addResultBuffer(); |
| |
| group->addChild(new DescriptorCopyTestCase(testCtx, (name + "_5").c_str(), "", commands)); |
| } |
| |
| // Copy between non-consecutive descriptor sets |
| { |
| DescriptorCommandsSp commands (new DescriptorCommands(pipelineType)); |
| commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 3u)), 0u); |
| commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 2u)), 5u); |
| commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 2u)), 5u); |
| |
| commands->copyDescriptor(0u, 0u, // from |
| 5u, 1u); // to |
| |
| vector<deUint32> dynamicAreas; |
| dynamicAreas.push_back(2u); |
| dynamicAreas.push_back(1u); |
| dynamicAreas.push_back(1u); |
| commands->setDynamicAreas(dynamicAreas); |
| |
| commands->addResultBuffer(); |
| |
| group->addChild(new DescriptorCopyTestCase(testCtx, (name + "_6").c_str(), "", commands)); |
| } |
| |
| // Simple 3 sized array to 3 sized array inside the same set. |
| { |
| DescriptorCommandsSp commands (new DescriptorCommands(pipelineType)); |
| commands->addDescriptor(DescriptorSp(new T(3u, 0u, 3u, 3u)), 0u); |
| commands->addDescriptor(DescriptorSp(new T(3u, 0u, 3u, 4u)), 0u); |
| |
| commands->copyDescriptor(0u, 0u, 0u, // from |
| 0u, 1u, 0u, // to |
| 3u); // num descriptors |
| |
| |
| vector<deUint32> dynamicAreas; |
| dynamicAreas.push_back(1u); |
| dynamicAreas.push_back(0u); |
| dynamicAreas.push_back(2u); |
| |
| dynamicAreas.push_back(2u); |
| dynamicAreas.push_back(1u); |
| dynamicAreas.push_back(0u); |
| commands->setDynamicAreas(dynamicAreas); |
| |
| commands->addResultBuffer(); |
| |
| group->addChild(new DescriptorCopyTestCase(testCtx, (name + "_array0").c_str(), "", commands)); |
| } |
| |
| // Simple 2 sized array to 3 sized array into different set. |
| { |
| DescriptorCommandsSp commands (new DescriptorCommands(pipelineType)); |
| commands->addDescriptor(DescriptorSp(new T(2u, 0u, 2u, 2u)), 0u); |
| commands->addDescriptor(DescriptorSp(new T(3u, 0u, 3u, 5u)), 1u); |
| |
| commands->copyDescriptor(0u, 0u, 0u, // from |
| 1u, 0u, 0u, // to |
| 2u); // num descriptors |
| |
| vector<deUint32> dynamicAreas; |
| dynamicAreas.push_back(1u); |
| dynamicAreas.push_back(0u); |
| |
| dynamicAreas.push_back(1u); |
| dynamicAreas.push_back(0u); |
| dynamicAreas.push_back(1u); |
| commands->setDynamicAreas(dynamicAreas); |
| |
| commands->addResultBuffer(); |
| |
| group->addChild(new DescriptorCopyTestCase(testCtx, (name + "_array1").c_str(), "", commands)); |
| } |
| |
| // Update array partially with writes and partially with a copy |
| { |
| DescriptorCommandsSp commands (new DescriptorCommands(pipelineType)); |
| commands->addDescriptor(DescriptorSp(new T(4u, 0u, 4u, 3u)), 0u); |
| commands->addDescriptor(DescriptorSp(new T(8u, 0u, 5u, 4u)), 0u); |
| |
| commands->copyDescriptor(0u, 0u, 1u, // from |
| 0u, 1u, 5u, // to |
| 3u); // num descriptors |
| |
| vector<deUint32> dynamicAreas; |
| dynamicAreas.push_back(2u); |
| dynamicAreas.push_back(0u); |
| dynamicAreas.push_back(1u); |
| dynamicAreas.push_back(1u); |
| |
| dynamicAreas.push_back(2u); |
| dynamicAreas.push_back(0u); |
| dynamicAreas.push_back(1u); |
| dynamicAreas.push_back(2u); |
| dynamicAreas.push_back(0u); |
| dynamicAreas.push_back(1u); |
| dynamicAreas.push_back(1u); |
| dynamicAreas.push_back(2u); |
| commands->setDynamicAreas(dynamicAreas); |
| |
| commands->addResultBuffer(); |
| |
| group->addChild(new DescriptorCopyTestCase(testCtx, (name + "_array2").c_str(), "", commands)); |
| } |
| } |
| |
| void addSamplerCopyTests (tcu::TestContext& testCtx, |
| de::MovePtr<tcu::TestCaseGroup>& group, |
| PipelineType pipelineType) |
| { |
| // Simple copy between two samplers in the same set |
| { |
| DescriptorCommandsSp commands (new DescriptorCommands(pipelineType)); |
| SamplerDescriptor* sampler0 (new SamplerDescriptor()); |
| SamplerDescriptor* sampler1 (new SamplerDescriptor()); |
| SampledImageDescriptor* image (new SampledImageDescriptor()); |
| sampler0->addImage(image); |
| sampler1->addImage(image); |
| |
| commands->addDescriptor(DescriptorSp(sampler0), 0u); |
| commands->addDescriptor(DescriptorSp(sampler1), 0u); |
| commands->addDescriptor(DescriptorSp(image), 0u); |
| |
| commands->copyDescriptor(0u, 0u, // from |
| 0u, 1u); // to |
| |
| commands->addResultBuffer(); |
| |
| group->addChild(new DescriptorCopyTestCase(testCtx, "sampler_0", "", commands)); |
| } |
| |
| // Simple 3 sized array to 3 sized array inside the same set. |
| { |
| DescriptorCommandsSp commands (new DescriptorCommands(pipelineType)); |
| SamplerDescriptor* sampler0 (new SamplerDescriptor(3u, 0u, 3u)); |
| // One sampler in between to get the border colors to originally mismatch between sampler0 and sampler1. |
| SamplerDescriptor* sampler1 (new SamplerDescriptor()); |
| SamplerDescriptor* sampler2 (new SamplerDescriptor(3u, 0u, 3u)); |
| SampledImageDescriptor* image (new SampledImageDescriptor()); |
| |
| sampler0->addImage(image, 3u); |
| sampler2->addImage(image, 3u); |
| |
| commands->addDescriptor(DescriptorSp(sampler0), 0u); |
| commands->addDescriptor(DescriptorSp(sampler1), 0u); |
| commands->addDescriptor(DescriptorSp(sampler2), 0u); |
| commands->addDescriptor(DescriptorSp(image), 0u); |
| |
| commands->copyDescriptor(0u, 0u, 0u, // from |
| 0u, 2u, 0u, // to |
| 3u); // num descriptors |
| |
| commands->addResultBuffer(); |
| |
| group->addChild(new DescriptorCopyTestCase(testCtx, "sampler_array0", "", commands)); |
| } |
| |
| // Simple 2 sized array to 3 sized array into different set. |
| { |
| DescriptorCommandsSp commands (new DescriptorCommands(pipelineType)); |
| SamplerDescriptor* sampler0 (new SamplerDescriptor(2u, 0u, 2u)); |
| SamplerDescriptor* sampler1 (new SamplerDescriptor(3u, 0u, 3u)); |
| SampledImageDescriptor* image (new SampledImageDescriptor()); |
| |
| sampler0->addImage(image, 2u); |
| sampler1->addImage(image, 3u); |
| |
| commands->addDescriptor(DescriptorSp(sampler0), 0u); |
| commands->addDescriptor(DescriptorSp(sampler1), 1u); |
| commands->addDescriptor(DescriptorSp(image), 0u); |
| |
| commands->copyDescriptor(0u, 0u, 0u, // from |
| 1u, 0u, 1u, // to |
| 2u); // num descriptors |
| |
| commands->addResultBuffer(); |
| |
| group->addChild(new DescriptorCopyTestCase(testCtx, "sampler_array1", "", commands)); |
| } |
| } |
| |
| void addSampledImageCopyTests (tcu::TestContext& testCtx, |
| de::MovePtr<tcu::TestCaseGroup>& group, |
| PipelineType pipelineType) |
| { |
| // Simple copy between two images in the same set |
| { |
| DescriptorCommandsSp commands (new DescriptorCommands(pipelineType)); |
| SamplerDescriptor* sampler (new SamplerDescriptor()); |
| SampledImageDescriptor* image0 (new SampledImageDescriptor()); |
| SampledImageDescriptor* image1 (new SampledImageDescriptor()); |
| image0->addSampler(sampler); |
| image1->addSampler(sampler); |
| |
| commands->addDescriptor(DescriptorSp(image0), 0u); |
| commands->addDescriptor(DescriptorSp(image1), 0u); |
| commands->addDescriptor(DescriptorSp(sampler), 0u); |
| |
| commands->copyDescriptor(0u, 0u, // from |
| 0u, 1u); // to |
| |
| commands->addResultBuffer(); |
| |
| group->addChild(new DescriptorCopyTestCase(testCtx, "sampled_image_0", "", commands)); |
| } |
| |
| // Simple 3 sized array to 3 sized array inside the same set. |
| { |
| DescriptorCommandsSp commands (new DescriptorCommands(pipelineType)); |
| SamplerDescriptor* sampler (new SamplerDescriptor()); |
| SampledImageDescriptor* image0 (new SampledImageDescriptor(3u, 0u, 3u)); |
| SampledImageDescriptor* image1 (new SampledImageDescriptor(3u, 0u, 3u)); |
| image0->addSampler(sampler, 3u); |
| image1->addSampler(sampler, 3u); |
| |
| commands->addDescriptor(DescriptorSp(sampler), 0u); |
| commands->addDescriptor(DescriptorSp(image0), 0u); |
| commands->addDescriptor(DescriptorSp(image1), 0u); |
| |
| commands->copyDescriptor(0u, 1u, 0u, // from |
| 0u, 2u, 0u, // to |
| 3u); // num descriptors |
| |
| commands->addResultBuffer(); |
| |
| group->addChild(new DescriptorCopyTestCase(testCtx, "sampled_image_array0", "", commands)); |
| } |
| } |
| |
| // Mixture of different descriptors in the same test |
| void addMixedDescriptorCopyTests (tcu::TestContext& testCtx, |
| de::MovePtr<tcu::TestCaseGroup>& group, |
| PipelineType pipelineType) |
| { |
| { |
| DescriptorCommandsSp commands (new DescriptorCommands(pipelineType)); |
| SamplerDescriptor* sampler0 (new SamplerDescriptor()); |
| SamplerDescriptor* sampler1 (new SamplerDescriptor()); |
| SampledImageDescriptor* image0 (new SampledImageDescriptor()); |
| SampledImageDescriptor* image1 (new SampledImageDescriptor()); |
| StorageBufferDescriptor* storageBuffer0 (new StorageBufferDescriptor()); |
| StorageBufferDescriptor* storageBuffer1 (new StorageBufferDescriptor()); |
| StorageBufferDescriptor* storageBuffer2 = new StorageBufferDescriptor(); |
| sampler0->addImage(image0); |
| sampler1->addImage(image1); |
| |
| commands->addDescriptor(DescriptorSp(sampler0), 0u); // Set 0, binding 0 |
| commands->addDescriptor(DescriptorSp(storageBuffer0), 0u); // Set 0, binding 1 |
| commands->addDescriptor(DescriptorSp(image0), 0u); // Set 0, binding 2 |
| commands->addDescriptor(DescriptorSp(storageBuffer1), 0u); // Set 0, binding 3 |
| commands->addDescriptor(DescriptorSp(sampler1), 1u); // Set 1, binding 0 |
| commands->addDescriptor(DescriptorSp(image1), 1u); // Set 1, binding 1 |
| commands->addDescriptor(DescriptorSp(storageBuffer2), 1u); // Set 1, binding 2 |
| |
| // image1 to image0 |
| commands->copyDescriptor(1u, 1u, // from |
| 0u, 2u); // to |
| |
| // storageBuffer0 to storageBuffer1 |
| commands->copyDescriptor(0u, 1u, // from |
| 0u, 3u); // to |
| |
| // storageBuffer1 to storageBuffer2 |
| commands->copyDescriptor(0u, 3u, // from |
| 1u, 2u); // to |
| |
| commands->addResultBuffer(); |
| |
| group->addChild(new DescriptorCopyTestCase(testCtx, "mix_0", "", commands)); |
| } |
| |
| { |
| DescriptorCommandsSp commands (new DescriptorCommands(pipelineType)); |
| StorageTexelBufferDescriptor* storageTexelBuffer0 (new StorageTexelBufferDescriptor()); |
| StorageTexelBufferDescriptor* storageTexelBuffer1 (new StorageTexelBufferDescriptor()); |
| UniformBufferDescriptor* uniformBuffer0 (new UniformBufferDescriptor()); |
| UniformBufferDescriptor* uniformBuffer1 (new UniformBufferDescriptor()); |
| UniformBufferDescriptor* uniformBuffer2 (new UniformBufferDescriptor()); |
| DynamicStorageBufferDescriptor* dynamicStorageBuffer0 (new DynamicStorageBufferDescriptor(1u, 0u, 1u, 3u)); |
| DynamicStorageBufferDescriptor* dynamicStorageBuffer1 (new DynamicStorageBufferDescriptor(1u, 0u, 1u, 4u)); |
| |
| commands->addDescriptor(DescriptorSp(storageTexelBuffer0), 0u); // Set 0, binding 0 |
| commands->addDescriptor(DescriptorSp(uniformBuffer0), 0u); // Set 0, binding 1 |
| commands->addDescriptor(DescriptorSp(dynamicStorageBuffer0), 0u); // Set 0, binding 2 |
| commands->addDescriptor(DescriptorSp(uniformBuffer1), 0u); // Set 0, binding 3 |
| commands->addDescriptor(DescriptorSp(dynamicStorageBuffer1), 1u); // Set 1, binding 0 |
| commands->addDescriptor(DescriptorSp(storageTexelBuffer1), 1u); // Set 1, binding 1 |
| commands->addDescriptor(DescriptorSp(uniformBuffer2), 1u); // Set 1, binding 2 |
| |
| vector<deUint32> dynamicAreas; |
| dynamicAreas.push_back(2u); |
| dynamicAreas.push_back(1u); |
| commands->setDynamicAreas(dynamicAreas); |
| |
| // uniformBuffer0 to uniformBuffer2 |
| commands->copyDescriptor(0u, 1u, // from |
| 1u, 2u); // to |
| |
| // uniformBuffer1 to uniformBuffer2 |
| commands->copyDescriptor(0u, 3u, // from |
| 1u, 2u); // to |
| |
| // storageTexelBuffer1 to storageTexelBuffer0 |
| commands->copyDescriptor(1u, 1u, // from |
| 0u, 0u); // to |
| |
| // dynamicStorageBuffer0 to dynamicStorageBuffer1 |
| commands->copyDescriptor(0u, 2u, // from |
| 1u, 0u); // to |
| |
| commands->addResultBuffer(); |
| |
| group->addChild(new DescriptorCopyTestCase(testCtx, "mix_1", "", commands)); |
| } |
| |
| if (pipelineType == PIPELINE_TYPE_GRAPHICS) |
| { |
| // Mixture of descriptors, including input attachment. |
| DescriptorCommandsSp commands (new DescriptorCommands(pipelineType)); |
| InputAttachmentDescriptor* inputAttachment0 (new InputAttachmentDescriptor()); |
| InputAttachmentDescriptor* inputAttachment1 (new InputAttachmentDescriptor()); |
| CombinedImageSamplerDescriptor* combinedImageSampler0 (new CombinedImageSamplerDescriptor()); |
| CombinedImageSamplerDescriptor* combinedImageSampler1 (new CombinedImageSamplerDescriptor()); |
| UniformTexelBufferDescriptor* uniformTexelBuffer0 (new UniformTexelBufferDescriptor(5u, 0u, 5u)); |
| UniformTexelBufferDescriptor* uniformTexelBuffer1 (new UniformTexelBufferDescriptor(3u, 1u, 1u)); |
| |
| commands->addDescriptor(DescriptorSp(combinedImageSampler0), 0u); // Set 0, binding 0 |
| commands->addDescriptor(DescriptorSp(inputAttachment0), 0u); // Set 0, binding 1 |
| commands->addDescriptor(DescriptorSp(uniformTexelBuffer0), 0u); // Set 0, binding 2 |
| commands->addDescriptor(DescriptorSp(combinedImageSampler1), 1u); // Set 1, binding 0 |
| commands->addDescriptor(DescriptorSp(inputAttachment1), 1u); // Set 1, binding 1 |
| commands->addDescriptor(DescriptorSp(uniformTexelBuffer1), 1u); // Set 1, binding 2 |
| |
| // uniformTexelBuffer0[1..3] to uniformTexelBuffer1[0..2] |
| commands->copyDescriptor(0u, 2u, 1u, // from |
| 1u, 2u, 0u, // to |
| 3u); // num descriptors |
| |
| // inputAttachment0 to inputAttachment1 |
| commands->copyDescriptor(0u, 1u, // from |
| 1u, 1u); // to |
| |
| // combinedImageSampler0 to combinedImageSampler1 |
| commands->copyDescriptor(0u, 0u, // from |
| 1u, 0u); // to |
| |
| commands->addResultBuffer(); |
| |
| group->addChild(new DescriptorCopyTestCase(testCtx, "mix_2", "", commands)); |
| } |
| |
| if (pipelineType == PIPELINE_TYPE_GRAPHICS) |
| { |
| // Similar to the previous one, but adding inline uniform blocks to the mix. |
| DescriptorCommandsSp commands (new DescriptorCommands(pipelineType)); |
| InlineUniformBlockDescriptor* iub0 (new InlineUniformBlockDescriptor(4u, 0u, 4u)); |
| InlineUniformBlockDescriptor* iub1 (new InlineUniformBlockDescriptor(4u, 0u, 1u)); |
| InputAttachmentDescriptor* inputAttachment0 (new InputAttachmentDescriptor()); |
| InputAttachmentDescriptor* inputAttachment1 (new InputAttachmentDescriptor()); |
| CombinedImageSamplerDescriptor* combinedImageSampler0 (new CombinedImageSamplerDescriptor()); |
| CombinedImageSamplerDescriptor* combinedImageSampler1 (new CombinedImageSamplerDescriptor()); |
| UniformTexelBufferDescriptor* uniformTexelBuffer0 (new UniformTexelBufferDescriptor(5u, 0u, 5u)); |
| UniformTexelBufferDescriptor* uniformTexelBuffer1 (new UniformTexelBufferDescriptor(3u, 1u, 1u)); |
| |
| commands->addDescriptor(DescriptorSp(iub0), 0u); // Set 0, binding 0 |
| commands->addDescriptor(DescriptorSp(combinedImageSampler0), 0u); // Set 0, binding 1 |
| commands->addDescriptor(DescriptorSp(inputAttachment0), 0u); // Set 0, binding 2 |
| commands->addDescriptor(DescriptorSp(uniformTexelBuffer0), 0u); // Set 0, binding 3 |
| commands->addDescriptor(DescriptorSp(iub1), 1u); // Set 1, binding 0 |
| commands->addDescriptor(DescriptorSp(combinedImageSampler1), 1u); // Set 1, binding 1 |
| commands->addDescriptor(DescriptorSp(inputAttachment1), 1u); // Set 1, binding 2 |
| commands->addDescriptor(DescriptorSp(uniformTexelBuffer1), 1u); // Set 1, binding 3 |
| |
| // iub0.data[0..2] to iub1.data[1..3] |
| commands->copyDescriptor(0u, 0u, 0u, // from |
| 1u, 0u, 1u, // to |
| 3u); // num descriptors |
| |
| // uniformTexelBuffer0[1..3] to uniformTexelBuffer1[0..2] |
| commands->copyDescriptor(0u, 3u, 1u, // from |
| 1u, 3u, 0u, // to |
| 3u); // num descriptors |
| |
| // inputAttachment0 to inputAttachment1 |
| commands->copyDescriptor(0u, 2u, // from |
| 1u, 2u); // to |
| |
| // combinedImageSampler0 to combinedImageSampler1 |
| commands->copyDescriptor(0u, 1u, // from |
| 1u, 1u); // to |
| |
| commands->addResultBuffer(); |
| |
| group->addChild(new DescriptorCopyTestCase(testCtx, "mix_3", "", commands)); |
| } |
| |
| // Mixture of descriptors using descriptor arrays |
| { |
| DescriptorCommandsSp commands (new DescriptorCommands(pipelineType)); |
| CombinedImageSamplerDescriptor* combinedImageSampler0 (new CombinedImageSamplerDescriptor(3u, 0u, 3u)); |
| CombinedImageSamplerDescriptor* combinedImageSampler1 (new CombinedImageSamplerDescriptor(4u, 0u, 2u)); |
| CombinedImageSamplerDescriptor* combinedImageSampler2 (new CombinedImageSamplerDescriptor(3u, 0u, 3u)); |
| StorageImageDescriptor* storageImage0 (new StorageImageDescriptor(5u, 0u, 5u)); |
| StorageImageDescriptor* storageImage1 (new StorageImageDescriptor(3u, 0u, 0u)); |
| StorageBufferDescriptor* storageBuffer0 (new StorageBufferDescriptor(2u, 0u, 1u)); |
| StorageBufferDescriptor* storageBuffer1 (new StorageBufferDescriptor(3u, 0u, 3u)); |
| |
| commands->addDescriptor(DescriptorSp(combinedImageSampler0), 0u); // Set 0, binding 0 |
| commands->addDescriptor(DescriptorSp(storageImage0), 0u); // Set 0, binding 1 |
| commands->addDescriptor(DescriptorSp(combinedImageSampler1), 0u); // Set 0, binding 2 |
| commands->addDescriptor(DescriptorSp(storageBuffer0), 0u); // Set 0, binding 3 |
| commands->addDescriptor(DescriptorSp(storageBuffer1), 0u); // Set 0, binding 4 |
| commands->addDescriptor(DescriptorSp(storageImage1), 1u); // Set 1, binding 0 |
| commands->addDescriptor(DescriptorSp(combinedImageSampler2), 1u); // Set 1, binding 1 |
| |
| // combinedImageSampler0[1..2] to combinedImageSampler1[2..3] |
| commands->copyDescriptor(0u, 0u, 1u, // from |
| 0u, 2u, 2u, // to |
| 2u); // num descriptors |
| |
| // storageImage0[2..4] to storageImage1[0..2] |
| commands->copyDescriptor(0u, 1u, 2u, // from |
| 1u, 0u, 0u, // to |
| 3u); // num descriptors |
| |
| // storageBuffer1[1..2] to storageBuffer0[0..1] |
| commands->copyDescriptor(0u, 4u, 1u, // from |
| 0u, 3u, 0u, // to |
| 2u); // num descriptors |
| |
| commands->addResultBuffer(); |
| |
| group->addChild(new DescriptorCopyTestCase(testCtx, "mix_array0", "", commands)); |
| } |
| |
| // Similar to the previous one but including inline uniform blocks. |
| { |
| DescriptorCommandsSp commands (new DescriptorCommands(pipelineType)); |
| InlineUniformBlockDescriptor* iub0 (new InlineUniformBlockDescriptor(4u, 0u, 1u)); |
| InlineUniformBlockDescriptor* iub1 (new InlineUniformBlockDescriptor(4u, 0u, 4u)); |
| CombinedImageSamplerDescriptor* combinedImageSampler0 (new CombinedImageSamplerDescriptor(3u, 0u, 3u)); |
| CombinedImageSamplerDescriptor* combinedImageSampler1 (new CombinedImageSamplerDescriptor(4u, 0u, 2u)); |
| CombinedImageSamplerDescriptor* combinedImageSampler2 (new CombinedImageSamplerDescriptor(3u, 0u, 3u)); |
| StorageImageDescriptor* storageImage0 (new StorageImageDescriptor(5u, 0u, 5u)); |
| StorageImageDescriptor* storageImage1 (new StorageImageDescriptor(3u, 0u, 0u)); |
| StorageBufferDescriptor* storageBuffer0 (new StorageBufferDescriptor(2u, 0u, 1u)); |
| StorageBufferDescriptor* storageBuffer1 (new StorageBufferDescriptor(3u, 0u, 3u)); |
| |
| commands->addDescriptor(DescriptorSp(iub0), 0u); // Set 0, binding 0 |
| commands->addDescriptor(DescriptorSp(combinedImageSampler0), 0u); // Set 0, binding 1 |
| commands->addDescriptor(DescriptorSp(storageImage0), 0u); // Set 0, binding 2 |
| commands->addDescriptor(DescriptorSp(combinedImageSampler1), 0u); // Set 0, binding 3 |
| commands->addDescriptor(DescriptorSp(storageBuffer0), 0u); // Set 0, binding 4 |
| commands->addDescriptor(DescriptorSp(storageBuffer1), 0u); // Set 0, binding 5 |
| commands->addDescriptor(DescriptorSp(combinedImageSampler2), 0u); // Set 0, binding 6 |
| commands->addDescriptor(DescriptorSp(iub1), 1u); // Set 1, binding 0 |
| commands->addDescriptor(DescriptorSp(storageImage1), 1u); // Set 1, binding 1 |
| |
| // iub1.data[0..2] to iub0.data[1..3] |
| commands->copyDescriptor(1u, 0u, 0u, // from |
| 0u, 0u, 1u, // to |
| 3u); // num descriptors |
| |
| // combinedImageSampler0[1..2] to combinedImageSampler1[2..3] |
| commands->copyDescriptor(0u, 1u, 1u, // from |
| 0u, 3u, 2u, // to |
| 2u); // num descriptors |
| |
| // storageImage0[2..4] to storageImage1[0..2] |
| commands->copyDescriptor(0u, 2u, 2u, // from |
| 1u, 1u, 0u, // to |
| 3u); // num descriptors |
| |
| // storageBuffer1[1..2] to storageBuffer0[0..1] |
| commands->copyDescriptor(0u, 5u, 1u, // from |
| 0u, 4u, 0u, // to |
| 2u); // num descriptors |
| |
| commands->addResultBuffer(); |
| |
| group->addChild(new DescriptorCopyTestCase(testCtx, "mix_array1", "", commands)); |
| } |
| } |
| |
| } // anonymous |
| |
| tcu::TestCaseGroup* createDescriptorCopyTests (tcu::TestContext& testCtx) |
| { |
| de::MovePtr<tcu::TestCaseGroup> descriptorCopyGroup(new tcu::TestCaseGroup(testCtx, "descriptor_copy", "Descriptor copy tests")); |
| |
| de::MovePtr<tcu::TestCaseGroup> computeGroup(new tcu::TestCaseGroup(testCtx, "compute", "Compute tests")); |
| de::MovePtr<tcu::TestCaseGroup> graphicsGroup(new tcu::TestCaseGroup(testCtx, "graphics", "Graphics tests")); |
| |
| // Compute tests |
| addDescriptorCopyTests<UniformBufferDescriptor>(testCtx, computeGroup, "uniform_buffer", PIPELINE_TYPE_COMPUTE); |
| addDescriptorCopyTests<InlineUniformBlockDescriptor>(testCtx, computeGroup, "inline_uniform_block", PIPELINE_TYPE_COMPUTE); |
| addDescriptorCopyTests<StorageBufferDescriptor>(testCtx, computeGroup, "storage_buffer", PIPELINE_TYPE_COMPUTE); |
| addDescriptorCopyTests<CombinedImageSamplerDescriptor>(testCtx, computeGroup, "combined_image_sampler", PIPELINE_TYPE_COMPUTE); |
| addDescriptorCopyTests<StorageImageDescriptor>(testCtx, computeGroup, "storage_image", PIPELINE_TYPE_COMPUTE); |
| addDescriptorCopyTests<UniformTexelBufferDescriptor>(testCtx, computeGroup, "uniform_texel_buffer", PIPELINE_TYPE_COMPUTE); |
| addDescriptorCopyTests<StorageTexelBufferDescriptor>(testCtx, computeGroup, "storage_texel_buffer", PIPELINE_TYPE_COMPUTE); |
| addDescriptorCopyTests<DynamicUniformBufferDescriptor>(testCtx, computeGroup, "uniform_buffer_dynamic", PIPELINE_TYPE_COMPUTE); |
| addDescriptorCopyTests<DynamicStorageBufferDescriptor>(testCtx, computeGroup, "storage_buffer_dynamic", PIPELINE_TYPE_COMPUTE); |
| addSamplerCopyTests(testCtx, computeGroup, PIPELINE_TYPE_COMPUTE); |
| addSampledImageCopyTests(testCtx, computeGroup, PIPELINE_TYPE_COMPUTE); |
| addMixedDescriptorCopyTests(testCtx, computeGroup, PIPELINE_TYPE_COMPUTE); |
| |
| // Graphics tests |
| addDescriptorCopyTests<UniformBufferDescriptor>(testCtx, graphicsGroup, "uniform_buffer", PIPELINE_TYPE_GRAPHICS); |
| addDescriptorCopyTests<InlineUniformBlockDescriptor>(testCtx, graphicsGroup, "inline_uniform_block", PIPELINE_TYPE_GRAPHICS); |
| addDescriptorCopyTests<StorageBufferDescriptor>(testCtx, graphicsGroup, "storage_buffer", PIPELINE_TYPE_GRAPHICS); |
| addDescriptorCopyTests<CombinedImageSamplerDescriptor>(testCtx, graphicsGroup, "combined_image_sampler", PIPELINE_TYPE_GRAPHICS); |
| addDescriptorCopyTests<StorageImageDescriptor>(testCtx, graphicsGroup, "storage_image", PIPELINE_TYPE_GRAPHICS); |
| addDescriptorCopyTests<InputAttachmentDescriptor>(testCtx, graphicsGroup, "input_attachment", PIPELINE_TYPE_GRAPHICS); |
| addDescriptorCopyTests<UniformTexelBufferDescriptor>(testCtx, graphicsGroup, "uniform_texel_buffer", PIPELINE_TYPE_GRAPHICS); |
| addDescriptorCopyTests<StorageTexelBufferDescriptor>(testCtx, graphicsGroup, "storage_texel_buffer", PIPELINE_TYPE_GRAPHICS); |
| addDescriptorCopyTests<DynamicUniformBufferDescriptor>(testCtx, graphicsGroup, "uniform_buffer_dynamic", PIPELINE_TYPE_GRAPHICS); |
| addDescriptorCopyTests<DynamicStorageBufferDescriptor>(testCtx, graphicsGroup, "storage_buffer_dynamic", PIPELINE_TYPE_GRAPHICS); |
| addSamplerCopyTests(testCtx, graphicsGroup, PIPELINE_TYPE_GRAPHICS); |
| addSampledImageCopyTests(testCtx, graphicsGroup, PIPELINE_TYPE_GRAPHICS); |
| addMixedDescriptorCopyTests(testCtx, graphicsGroup, PIPELINE_TYPE_GRAPHICS); |
| |
| descriptorCopyGroup->addChild(computeGroup.release()); |
| descriptorCopyGroup->addChild(graphicsGroup.release()); |
| |
| return descriptorCopyGroup.release(); |
| } |
| |
| } // BindingModel |
| } // vkt |