• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2018 The Khronos Group Inc.
6  * Copyright (c) 2018 Google Inc.
7  * Copyright (c) 2018 ARM Limited.
8  * Copyright (c) 2023 LunarG, Inc.
9  * Copyright (c) 2023 Nintendo
10  *
11  * Licensed under the Apache License, Version 2.0 (the "License");
12  * you may not use this file except in compliance with the License.
13  * You may obtain a copy of the License at
14  *
15  *      http://www.apache.org/licenses/LICENSE-2.0
16  *
17  * Unless required by applicable law or agreed to in writing, software
18  * distributed under the License is distributed on an "AS IS" BASIS,
19  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20  * See the License for the specific language governing permissions and
21  * limitations under the License.
22  *
23  *//*!
24  * \file
25  * \brief Push Descriptor Tests
26  *//*--------------------------------------------------------------------*/
27 
28 #include "vktPipelinePushDescriptorTests.hpp"
29 #include "vktPipelineClearUtil.hpp"
30 #include "vktPipelineImageUtil.hpp"
31 #include "vktPipelineVertexUtil.hpp"
32 #include "vktPipelineReferenceRenderer.hpp"
33 #include "vktTestCase.hpp"
34 #include "vktCustomInstancesDevices.hpp"
35 #include "vkImageUtil.hpp"
36 #include "vkMemUtil.hpp"
37 #include "vkPrograms.hpp"
38 #include "vkQueryUtil.hpp"
39 #include "vkRef.hpp"
40 #include "vkRefUtil.hpp"
41 #include "vkTypeUtil.hpp"
42 #include "vkCmdUtil.hpp"
43 #include "vkObjUtil.hpp"
44 #include "vkDeviceUtil.hpp"
45 #include "tcuImageCompare.hpp"
46 #include "deMemory.h"
47 #include "deUniquePtr.hpp"
48 #include "tcuTestLog.hpp"
49 #include "tcuCommandLine.hpp"
50 #include <vector>
51 
52 namespace vkt
53 {
54 namespace pipeline
55 {
56 
57 using namespace vk;
58 using namespace std;
59 
60 namespace
61 {
62 typedef vector<VkExtensionProperties> Extensions;
63 typedef de::SharedPtr<Unique<VkBuffer>> VkBufferSp;
64 typedef de::SharedPtr<Unique<VkImage>> VkImageSp;
65 typedef de::SharedPtr<Unique<VkImageView>> VkImageViewSp;
66 typedef de::SharedPtr<Unique<VkBufferView>> VkBufferViewSp;
67 typedef de::SharedPtr<Allocation> AllocationSp;
68 typedef de::SharedPtr<RenderPassWrapper> VkRenderPassSp;
69 
70 constexpr VkDeviceSize kSizeofVec4 = static_cast<VkDeviceSize>(sizeof(tcu::Vec4));
71 
72 struct TestParams
73 {
74     PipelineConstructionType pipelineConstructionType; // Used only by graphics pipeline tests
75     VkDescriptorType descriptorType;
76     uint32_t binding;
77     uint32_t numCalls; // Number of draw or dispatch calls
78     bool useMaintenance5;
79 };
80 
calcItemSize(const InstanceInterface & vki,VkPhysicalDevice physicalDevice,uint32_t numElements=1u)81 VkDeviceSize calcItemSize(const InstanceInterface &vki, VkPhysicalDevice physicalDevice, uint32_t numElements = 1u)
82 {
83     const auto minAlignment = getPhysicalDeviceProperties(vki, physicalDevice).limits.minStorageBufferOffsetAlignment;
84     const auto lcm          = de::lcm(de::max(VkDeviceSize{1}, minAlignment), kSizeofVec4);
85     return de::roundUp(kSizeofVec4 * numElements, lcm);
86 }
87 
checkAllSupported(const Extensions & supportedExtensions,const vector<string> & requiredExtensions)88 void checkAllSupported(const Extensions &supportedExtensions, const vector<string> &requiredExtensions)
89 {
90     for (auto &requiredExtName : requiredExtensions)
91     {
92         if (!isExtensionStructSupported(supportedExtensions, RequiredExtension(requiredExtName)))
93             TCU_THROW(NotSupportedError, (requiredExtName + " is not supported").c_str());
94     }
95 }
96 
createInstanceWithGetPhysicalDeviceProperties2(Context & context,const Extensions & supportedExtensions)97 CustomInstance createInstanceWithGetPhysicalDeviceProperties2(Context &context, const Extensions &supportedExtensions)
98 {
99     vector<string> requiredExtensions = {"VK_KHR_get_physical_device_properties2"};
100     checkAllSupported(supportedExtensions, requiredExtensions);
101 
102     return createCustomInstanceWithExtensions(context, requiredExtensions);
103 }
104 
innerCString(const string & str)105 const char *innerCString(const string &str)
106 {
107     return str.c_str();
108 }
109 
createDeviceWithPushDescriptor(const Context & context,const PlatformInterface & vkp,VkInstance instance,const InstanceInterface & vki,VkPhysicalDevice physicalDevice,const Extensions & supportedExtensions,const uint32_t queueFamilyIndex,const TestParams & params,std::vector<std::string> & enabledExtensions)110 Move<VkDevice> createDeviceWithPushDescriptor(const Context &context, const PlatformInterface &vkp, VkInstance instance,
111                                               const InstanceInterface &vki, VkPhysicalDevice physicalDevice,
112                                               const Extensions &supportedExtensions, const uint32_t queueFamilyIndex,
113                                               const TestParams &params, std::vector<std::string> &enabledExtensions)
114 {
115 
116     const float queuePriority               = 1.0f;
117     const VkDeviceQueueCreateInfo queueInfo = {VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
118                                                DE_NULL,
119                                                (VkDeviceQueueCreateFlags)0,
120                                                queueFamilyIndex,
121                                                1u,
122                                                &queuePriority};
123 
124     VkPhysicalDeviceFeatures features;
125     deMemset(&features, 0, sizeof(features));
126 
127     vector<string> requiredExtensionsStr                                                  = {"VK_KHR_push_descriptor"};
128     VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT graphicsPipelineLibraryFeaturesEXT = initVulkanStructure();
129     VkPhysicalDeviceDynamicRenderingFeaturesKHR dynamicRenderingFeaturesKHR =
130         initVulkanStructure(&graphicsPipelineLibraryFeaturesEXT);
131     VkPhysicalDeviceShaderObjectFeaturesEXT shaderObjectFeaturesEXT = initVulkanStructure(&dynamicRenderingFeaturesKHR);
132     VkPhysicalDeviceFeatures2 features2                             = initVulkanStructure(&shaderObjectFeaturesEXT);
133     if (isConstructionTypeLibrary(params.pipelineConstructionType))
134     {
135         requiredExtensionsStr.push_back("VK_KHR_pipeline_library");
136         requiredExtensionsStr.push_back("VK_EXT_graphics_pipeline_library");
137         vki.getPhysicalDeviceFeatures2(physicalDevice, &features2);
138         if (!graphicsPipelineLibraryFeaturesEXT.graphicsPipelineLibrary)
139             TCU_THROW(NotSupportedError, "graphicsPipelineLibraryFeaturesEXT.graphicsPipelineLibrary required");
140     }
141     else if (isConstructionTypeShaderObject(params.pipelineConstructionType))
142     {
143         if (context.getUsedApiVersion() < VK_API_VERSION_1_3)
144             requiredExtensionsStr.push_back("VK_KHR_dynamic_rendering");
145         requiredExtensionsStr.push_back("VK_EXT_shader_object");
146         vki.getPhysicalDeviceFeatures2(physicalDevice, &features2);
147         if (!shaderObjectFeaturesEXT.shaderObject)
148             TCU_THROW(NotSupportedError, "shaderObjectFeaturesEXT.shaderObject required");
149         if (!dynamicRenderingFeaturesKHR.dynamicRendering)
150             TCU_THROW(NotSupportedError, "dynamicRendering required");
151     }
152     vector<const char *> requiredExtensions;
153     checkAllSupported(supportedExtensions, requiredExtensionsStr);
154     // We need the contents of requiredExtensionsStr as a vector<const char*> in VkDeviceCreateInfo.
155     transform(begin(requiredExtensionsStr), end(requiredExtensionsStr), back_inserter(requiredExtensions),
156               innerCString);
157 
158     // Enable validation layers on this device if validation has been requested from the command line.
159     const VkDeviceCreateInfo deviceParams = {
160         VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
161         params.pipelineConstructionType != PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC ? &features2 : DE_NULL,
162         (VkDeviceCreateFlags)0,
163         1u,
164         &queueInfo,
165         0u,
166         DE_NULL,
167         static_cast<uint32_t>(requiredExtensions.size()),
168         (requiredExtensions.empty() ? DE_NULL : requiredExtensions.data()),
169         params.pipelineConstructionType != PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC ? DE_NULL : &features};
170 
171     for (const auto &enabledExt : requiredExtensions)
172         enabledExtensions.push_back(enabledExt);
173 
174     return createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), vkp, instance, vki,
175                               physicalDevice, &deviceParams, DE_NULL);
176 }
177 
createQuads(uint32_t numQuads,float size)178 vector<Vertex4RGBA> createQuads(uint32_t numQuads, float size)
179 {
180     vector<Vertex4RGBA> vertices;
181 
182     for (uint32_t quadNdx = 0; quadNdx < numQuads; quadNdx++)
183     {
184         const float xOffset = -0.5f + (float)quadNdx;
185         const tcu::Vec4 color(0.0f);
186         const Vertex4RGBA lowerLeftVertex  = {tcu::Vec4(-size + xOffset, -size, 0.0f, 1.0f), color};
187         const Vertex4RGBA lowerRightVertex = {tcu::Vec4(size + xOffset, -size, 0.0f, 1.0f), color};
188         const Vertex4RGBA UpperLeftVertex  = {tcu::Vec4(-size + xOffset, size, 0.0f, 1.0f), color};
189         const Vertex4RGBA UpperRightVertex = {tcu::Vec4(size + xOffset, size, 0.0f, 1.0f), color};
190 
191         vertices.push_back(lowerLeftVertex);
192         vertices.push_back(lowerRightVertex);
193         vertices.push_back(UpperLeftVertex);
194         vertices.push_back(UpperLeftVertex);
195         vertices.push_back(lowerRightVertex);
196         vertices.push_back(UpperRightVertex);
197     }
198 
199     return vertices;
200 }
201 
createTexQuads(uint32_t numQuads,float size)202 vector<Vertex4Tex4> createTexQuads(uint32_t numQuads, float size)
203 {
204     vector<Vertex4Tex4> vertices;
205 
206     for (uint32_t quadNdx = 0; quadNdx < numQuads; quadNdx++)
207     {
208         const float xOffset                = -0.5f + (float)quadNdx;
209         const Vertex4Tex4 lowerLeftVertex  = {tcu::Vec4(-size + xOffset, -size, 0.0f, 1.0f),
210                                               tcu::Vec4(-0.2f, -0.2f, 0.0f, 0.0f)};
211         const Vertex4Tex4 lowerRightVertex = {tcu::Vec4(size + xOffset, -size, 0.0f, 1.0f),
212                                               tcu::Vec4(1.2f, -0.2f, 0.0f, 0.0f)};
213         const Vertex4Tex4 UpperLeftVertex  = {tcu::Vec4(-size + xOffset, size, 0.0f, 1.0f),
214                                               tcu::Vec4(-0.2f, 1.2f, 0.0f, 0.0f)};
215         const Vertex4Tex4 UpperRightVertex = {tcu::Vec4(size + xOffset, size, 0.0f, 1.0f),
216                                               tcu::Vec4(1.2f, 1.2f, 0.0f, 0.0f)};
217 
218         vertices.push_back(lowerLeftVertex);
219         vertices.push_back(lowerRightVertex);
220         vertices.push_back(UpperLeftVertex);
221         vertices.push_back(UpperLeftVertex);
222         vertices.push_back(lowerRightVertex);
223         vertices.push_back(UpperRightVertex);
224     }
225 
226     return vertices;
227 }
228 
229 static const tcu::Vec4 defaultTestColors[] =
230 
231     {tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f)};
232 
233 class PushDescriptorBufferGraphicsTestInstance : public vkt::TestInstance
234 {
235 public:
236     PushDescriptorBufferGraphicsTestInstance(Context &context, const TestParams &params);
237     virtual ~PushDescriptorBufferGraphicsTestInstance(void);
238     void init(void);
239     virtual tcu::TestStatus iterate(void);
240     tcu::TestStatus verifyImage(void);
241 
242 private:
243     const TestParams m_params;
244     const PlatformInterface &m_vkp;
245     const Extensions m_instanceExtensions;
246     const CustomInstance m_instance;
247     const InstanceDriver &m_vki;
248     const VkPhysicalDevice m_physicalDevice;
249     const uint32_t m_queueFamilyIndex;
250     const Extensions m_deviceExtensions;
251     std::vector<std::string> m_deviceEnabledExtensions;
252     const Unique<VkDevice> m_device;
253     const DeviceDriver m_vkd;
254     const VkQueue m_queue;
255     SimpleAllocator m_allocator;
256     const tcu::UVec2 m_renderSize;
257     const VkFormat m_colorFormat;
258     Move<VkImage> m_colorImage;
259     de::MovePtr<Allocation> m_colorImageAlloc;
260     Move<VkImageView> m_colorAttachmentView;
261     RenderPassWrapper m_renderPass;
262     Move<VkFramebuffer> m_framebuffer;
263     ShaderWrapper m_vertexShaderModule;
264     ShaderWrapper m_fragmentShaderModule;
265     Move<VkBuffer> m_vertexBuffer;
266     de::MovePtr<Allocation> m_vertexBufferAlloc;
267     vector<VkBufferSp> m_buffers;
268     vector<AllocationSp> m_bufferAllocs;
269     Move<VkDescriptorSetLayout> m_descriptorSetLayout;
270     PipelineLayoutWrapper m_preRasterizationStatePipelineLayout;
271     PipelineLayoutWrapper m_fragmentStatePipelineLayout;
272     GraphicsPipelineWrapper m_graphicsPipeline;
273     Move<VkCommandPool> m_cmdPool;
274     Move<VkCommandBuffer> m_cmdBuffer;
275     vector<Vertex4RGBA> m_vertices;
276 };
277 
PushDescriptorBufferGraphicsTestInstance(Context & context,const TestParams & params)278 PushDescriptorBufferGraphicsTestInstance::PushDescriptorBufferGraphicsTestInstance(Context &context,
279                                                                                    const TestParams &params)
280     : vkt::TestInstance(context)
281     , m_params(params)
282     , m_vkp(context.getPlatformInterface())
283     , m_instanceExtensions(enumerateInstanceExtensionProperties(m_vkp, DE_NULL))
284     , m_instance(createInstanceWithGetPhysicalDeviceProperties2(context, m_instanceExtensions))
285     , m_vki(m_instance.getDriver())
286     , m_physicalDevice(chooseDevice(m_vki, m_instance, context.getTestContext().getCommandLine()))
287     , m_queueFamilyIndex(findQueueFamilyIndexWithCaps(m_vki, m_physicalDevice, VK_QUEUE_GRAPHICS_BIT))
288     , m_deviceExtensions(enumerateDeviceExtensionProperties(m_vki, m_physicalDevice, DE_NULL))
289     , m_device(createDeviceWithPushDescriptor(context, m_vkp, m_instance, m_vki, m_physicalDevice, m_deviceExtensions,
290                                               m_queueFamilyIndex, params, m_deviceEnabledExtensions))
291     , m_vkd(m_vkp, m_instance, *m_device, context.getUsedApiVersion(), context.getTestContext().getCommandLine())
292     , m_queue(getDeviceQueue(m_vkd, *m_device, m_queueFamilyIndex, 0u))
293     , m_allocator(m_vkd, *m_device, getPhysicalDeviceMemoryProperties(m_vki, m_physicalDevice))
294     , m_renderSize(32, 32)
295     , m_colorFormat(VK_FORMAT_R8G8B8A8_UNORM)
296     , m_graphicsPipeline(m_vki, m_vkd, m_physicalDevice, *m_device, m_deviceEnabledExtensions,
297                          params.pipelineConstructionType)
298     , m_vertices(createQuads(params.numCalls, 0.25f))
299 {
300 }
301 
init(void)302 void PushDescriptorBufferGraphicsTestInstance::init(void)
303 {
304     const VkComponentMapping componentMappingRGBA = {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G,
305                                                      VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A};
306 
307     // Create color image
308     {
309 
310         const VkImageCreateInfo colorImageParams = {
311             VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                                   // VkStructureType sType;
312             DE_NULL,                                                               // const void* pNext;
313             0u,                                                                    // VkImageCreateFlags flags;
314             VK_IMAGE_TYPE_2D,                                                      // VkImageType imageType;
315             m_colorFormat,                                                         // VkFormat format;
316             {m_renderSize.x(), m_renderSize.y(), 1u},                              // VkExtent3D extent;
317             1u,                                                                    // uint32_t mipLevels;
318             1u,                                                                    // uint32_t arrayLayers;
319             VK_SAMPLE_COUNT_1_BIT,                                                 // VkSampleCountFlagBits samples;
320             VK_IMAGE_TILING_OPTIMAL,                                               // VkImageTiling tiling;
321             VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
322             VK_SHARING_MODE_EXCLUSIVE,                                             // VkSharingMode sharingMode;
323             1u,                                                                    // uint32_t queueFamilyIndexCount;
324             &m_queueFamilyIndex,       // const uint32_t* pQueueFamilyIndices;
325             VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
326         };
327 
328         m_colorImage = createImage(m_vkd, *m_device, &colorImageParams);
329 
330         // Allocate and bind color image memory
331         m_colorImageAlloc =
332             m_allocator.allocate(getImageMemoryRequirements(m_vkd, *m_device, *m_colorImage), MemoryRequirement::Any);
333         VK_CHECK(m_vkd.bindImageMemory(*m_device, *m_colorImage, m_colorImageAlloc->getMemory(),
334                                        m_colorImageAlloc->getOffset()));
335     }
336 
337     // Create color attachment view
338     {
339         const VkImageViewCreateInfo colorAttachmentViewParams = {
340             VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,    // VkStructureType sType;
341             DE_NULL,                                     // const void* pNext;
342             0u,                                          // VkImageViewCreateFlags flags;
343             *m_colorImage,                               // VkImage image;
344             VK_IMAGE_VIEW_TYPE_2D,                       // VkImageViewType viewType;
345             m_colorFormat,                               // VkFormat format;
346             componentMappingRGBA,                        // VkChannelMapping channels;
347             {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u}, // VkImageSubresourceRange subresourceRange;
348         };
349 
350         m_colorAttachmentView = createImageView(m_vkd, *m_device, &colorAttachmentViewParams);
351     }
352 
353     // Create render pass
354     m_renderPass = RenderPassWrapper(m_params.pipelineConstructionType, m_vkd, *m_device, m_colorFormat);
355 
356     // Create framebuffer
357     {
358         const VkImageView attachmentBindInfos[] = {*m_colorAttachmentView};
359 
360         const VkFramebufferCreateInfo framebufferParams = {
361             VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
362             DE_NULL,                                   // const void* pNext;
363             0u,                                        // VkFramebufferCreateFlags flags;
364             *m_renderPass,                             // VkRenderPass renderPass;
365             1u,                                        // uint32_t attachmentCount;
366             attachmentBindInfos,                       // const VkImageView* pAttachments;
367             (uint32_t)m_renderSize.x(),                // uint32_t width;
368             (uint32_t)m_renderSize.y(),                // uint32_t height;
369             1u                                         // uint32_t layers;
370         };
371 
372         m_renderPass.createFramebuffer(m_vkd, *m_device, &framebufferParams, *m_colorImage);
373     }
374 
375     // Create pipeline layout
376     {
377         // Create descriptor set layout
378         const VkDescriptorSetLayoutBinding descriptorSetLayoutBinding = {
379             m_params.binding,           // uint32_t binding;
380             m_params.descriptorType,    // VkDescriptorType descriptorType;
381             1u,                         // uint32_t descriptorCount;
382             VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlags stageFlags;
383             DE_NULL                     // const VkSampler* pImmutableSamplers;
384         };
385 
386         const VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {
387             VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,     // VkStructureType sType;
388             DE_NULL,                                                 // const void* pNext;
389             VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR, // VkDescriptorSetLayoutCreateFlags flags;
390             1u,                                                      // uint32_t bindingCount;
391             &descriptorSetLayoutBinding                              // const VkDescriptorSetLayoutBinding* pBindings;
392         };
393 
394         m_descriptorSetLayout = createDescriptorSetLayout(m_vkd, *m_device, &descriptorSetLayoutCreateInfo, DE_NULL);
395 
396         // Create pipeline layout
397         VkPipelineLayoutCreateFlags pipelineLayoutFlags =
398             (m_params.pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC) ?
399                 0u :
400                 uint32_t(VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT);
401         VkPipelineLayoutCreateInfo pipelineLayoutParams{
402             VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
403             DE_NULL,                                       // const void* pNext;
404             pipelineLayoutFlags,                           // VkPipelineLayoutCreateFlags flags;
405             1u,                                            // uint32_t setLayoutCount;
406             &(*m_descriptorSetLayout),                     // const VkDescriptorSetLayout* pSetLayouts;
407             0u,                                            // uint32_t pushConstantRangeCount;
408             DE_NULL                                        // const VkPushDescriptorRange* pPushDescriptorRanges;
409         };
410 
411         m_preRasterizationStatePipelineLayout =
412             PipelineLayoutWrapper(m_params.pipelineConstructionType, m_vkd, *m_device, &pipelineLayoutParams);
413         pipelineLayoutParams.setLayoutCount = 0u;
414         pipelineLayoutParams.pSetLayouts    = DE_NULL;
415         m_fragmentStatePipelineLayout =
416             PipelineLayoutWrapper(m_params.pipelineConstructionType, m_vkd, *m_device, &pipelineLayoutParams);
417     }
418 
419     // Create buffers. One color value in each buffer.
420     {
421         VkBufferUsageFlags2CreateInfoKHR bufferUsageFlags2 = vk::initVulkanStructure();
422         for (uint32_t bufIdx = 0; bufIdx < DE_LENGTH_OF_ARRAY(defaultTestColors); bufIdx++)
423         {
424             const VkBufferUsageFlags usageFlags = m_params.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ?
425                                                       VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT :
426                                                       VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
427 
428             VkBufferCreateInfo bufferCreateInfo{
429                 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
430                 DE_NULL,                              // const void* pNext;
431                 0u,                                   // VkBufferCreateFlags    flags
432                 kSizeofVec4,                          // VkDeviceSize size;
433                 usageFlags,                           // VkBufferUsageFlags usage;
434                 VK_SHARING_MODE_EXCLUSIVE,            // VkSharingMode sharingMode;
435                 1u,                                   // uint32_t queueFamilyCount;
436                 &m_queueFamilyIndex                   // const uint32_t* pQueueFamilyIndices;
437             };
438 
439             if (m_params.useMaintenance5)
440             {
441                 bufferUsageFlags2.usage = (VkBufferUsageFlagBits2KHR)usageFlags;
442                 bufferCreateInfo.pNext  = &bufferUsageFlags2;
443                 bufferCreateInfo.usage  = 0;
444             }
445 
446             m_buffers.push_back(VkBufferSp(new Unique<VkBuffer>(createBuffer(m_vkd, *m_device, &bufferCreateInfo))));
447             m_bufferAllocs.push_back(
448                 AllocationSp(m_allocator
449                                  .allocate(getBufferMemoryRequirements(m_vkd, *m_device, **m_buffers[bufIdx]),
450                                            MemoryRequirement::HostVisible)
451                                  .release()));
452             VK_CHECK(m_vkd.bindBufferMemory(*m_device, **m_buffers[bufIdx], m_bufferAllocs[bufIdx]->getMemory(),
453                                             m_bufferAllocs[bufIdx]->getOffset()));
454 
455             deMemcpy(m_bufferAllocs[bufIdx]->getHostPtr(), &defaultTestColors[bufIdx],
456                      static_cast<size_t>(kSizeofVec4));
457             flushAlloc(m_vkd, *m_device, *m_bufferAllocs[bufIdx]);
458         }
459     }
460 
461     // Create shaders
462     {
463         m_vertexShaderModule   = ShaderWrapper(m_vkd, *m_device, m_context.getBinaryCollection().get("vert"), 0u);
464         m_fragmentShaderModule = ShaderWrapper(m_vkd, *m_device, m_context.getBinaryCollection().get("frag"), 0u);
465     }
466 
467     // Create pipeline
468     {
469         const VkVertexInputBindingDescription vertexInputBindingDescription = {
470             0u,                         // uint32_t binding;
471             sizeof(Vertex4RGBA),        // uint32_t strideInBytes;
472             VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate stepRate;
473         };
474 
475         const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] = {
476             {
477                 0u,                            // uint32_t location;
478                 0u,                            // uint32_t binding;
479                 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
480                 0u                             // uint32_t offsetInBytes;
481             },
482             {
483                 1u,                            // uint32_t location;
484                 0u,                            // uint32_t binding;
485                 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
486                 offsetof(Vertex4RGBA, color),  // uint32_t offset;
487             }};
488 
489         const VkPipelineVertexInputStateCreateInfo vertexInputStateParams = {
490             VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
491             DE_NULL,                                                   // const void* pNext;
492             0u,                                                        // vkPipelineVertexInputStateCreateFlags flags;
493             1u,                                                        // uint32_t bindingCount;
494             &vertexInputBindingDescription,  // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
495             2u,                              // uint32_t attributeCount;
496             vertexInputAttributeDescriptions // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
497         };
498 
499         const VkPrimitiveTopology topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
500 
501         const vector<VkViewport> viewports{makeViewport(m_renderSize)};
502         const vector<VkRect2D> scissors{makeRect2D(m_renderSize)};
503 
504         m_graphicsPipeline.setDefaultRasterizationState()
505             .setDefaultDepthStencilState()
506             .setDefaultMultisampleState()
507             .setDefaultColorBlendState()
508             .setDefaultTopology(topology)
509             .setupVertexInputState(&vertexInputStateParams)
510             .setupPreRasterizationShaderState(viewports, scissors, m_preRasterizationStatePipelineLayout, *m_renderPass,
511                                               0u, m_vertexShaderModule)
512             .setupFragmentShaderState(m_fragmentStatePipelineLayout, *m_renderPass, 0u, m_fragmentShaderModule)
513             .setupFragmentOutputState(*m_renderPass)
514             .setMonolithicPipelineLayout(m_preRasterizationStatePipelineLayout)
515             .buildPipeline();
516     }
517 
518     // Create vertex buffer
519     {
520         const VkBufferCreateInfo vertexBufferParams = {
521             VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,                    // VkStructureType sType;
522             DE_NULL,                                                 // const void* pNext;
523             0u,                                                      // VkBufferCreateFlags flags;
524             (VkDeviceSize)(sizeof(Vertex4RGBA) * m_vertices.size()), // VkDeviceSize size;
525             VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,                       // VkBufferUsageFlags usage;
526             VK_SHARING_MODE_EXCLUSIVE,                               // VkSharingMode sharingMode;
527             1u,                                                      // uint32_t queueFamilyCount;
528             &m_queueFamilyIndex                                      // const uint32_t* pQueueFamilyIndices;
529         };
530 
531         m_vertexBuffer      = createBuffer(m_vkd, *m_device, &vertexBufferParams);
532         m_vertexBufferAlloc = m_allocator.allocate(getBufferMemoryRequirements(m_vkd, *m_device, *m_vertexBuffer),
533                                                    MemoryRequirement::HostVisible);
534 
535         VK_CHECK(m_vkd.bindBufferMemory(*m_device, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(),
536                                         m_vertexBufferAlloc->getOffset()));
537 
538         // Load vertices into vertex buffer
539         deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA));
540         flushAlloc(m_vkd, *m_device, *m_vertexBufferAlloc);
541     }
542 
543     // Create command pool
544     m_cmdPool = createCommandPool(m_vkd, *m_device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, m_queueFamilyIndex);
545 
546     // Create command buffer
547     {
548         const VkClearValue attachmentClearValue = defaultClearValue(m_colorFormat);
549         const VkDeviceSize vertexBufferOffset   = 0;
550 
551         m_cmdBuffer = allocateCommandBuffer(m_vkd, *m_device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
552         beginCommandBuffer(m_vkd, *m_cmdBuffer, 0u);
553         m_renderPass.begin(m_vkd, *m_cmdBuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()),
554                            attachmentClearValue);
555         m_graphicsPipeline.bind(*m_cmdBuffer);
556         m_vkd.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
557 
558         // Draw quads. Switch input buffer which contains the quad color for each draw call.
559         for (uint32_t quadNdx = 0; quadNdx < m_params.numCalls; quadNdx++)
560         {
561             VkDescriptorBufferInfo descriptorBufferInfo = {
562                 **m_buffers[quadNdx], // VkBuffer buffer;
563                 0u,                   // VkDeviceSize offset;
564                 kSizeofVec4,          // VkDeviceSize range;
565             };
566 
567             VkWriteDescriptorSet writeDescriptorSet = {
568                 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // VkStructureType sType;
569                 DE_NULL,                                // const void* pNext;
570                 0u,                                     // VkDescriptorSet dstSet;
571                 m_params.binding,                       // uint32_t dstBinding;
572                 0u,                                     // uint32_t dstArrayElement;
573                 1u,                                     // uint32_t descriptorCount;
574                 m_params.descriptorType,                // VkDescriptorType descriptorType;
575                 DE_NULL,                                // const VkDescriptorImageInfo* pImageInfo;
576                 &descriptorBufferInfo,                  // const VkDescriptorBufferInfo* pBufferInfo;
577                 DE_NULL                                 // const VkBufferView* pTexelBufferView;
578             };
579 
580             m_vkd.cmdPushDescriptorSetKHR(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
581                                           *m_preRasterizationStatePipelineLayout, 0, 1, &writeDescriptorSet);
582             m_vkd.cmdDraw(*m_cmdBuffer, 6, 1, 6 * quadNdx, 0);
583         }
584 
585         m_renderPass.end(m_vkd, *m_cmdBuffer);
586         endCommandBuffer(m_vkd, *m_cmdBuffer);
587     }
588 }
589 
~PushDescriptorBufferGraphicsTestInstance(void)590 PushDescriptorBufferGraphicsTestInstance::~PushDescriptorBufferGraphicsTestInstance(void)
591 {
592 }
593 
iterate(void)594 tcu::TestStatus PushDescriptorBufferGraphicsTestInstance::iterate(void)
595 {
596     init();
597 
598     submitCommandsAndWait(m_vkd, *m_device, m_queue, m_cmdBuffer.get());
599 
600     return verifyImage();
601 }
602 
verifyImage(void)603 tcu::TestStatus PushDescriptorBufferGraphicsTestInstance::verifyImage(void)
604 {
605     const tcu::TextureFormat tcuColorFormat = mapVkFormat(m_colorFormat);
606     const tcu::TextureFormat tcuDepthFormat = tcu::TextureFormat();
607     const ColorVertexShader vertexShader;
608     const ColorFragmentShader fragmentShader(tcuColorFormat, tcuDepthFormat);
609     const rr::Program program(&vertexShader, &fragmentShader);
610     ReferenceRenderer refRenderer(m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuDepthFormat, &program);
611     bool compareOk = false;
612 
613     // Render reference image
614     {
615         for (uint32_t quadIdx = 0; quadIdx < m_params.numCalls; quadIdx++)
616             for (uint32_t vertexIdx = 0; vertexIdx < 6; vertexIdx++)
617                 m_vertices[quadIdx * 6 + vertexIdx].color.xyzw() = defaultTestColors[quadIdx];
618 
619         refRenderer.draw(rr::RenderState(refRenderer.getViewportState(),
620                                          m_context.getDeviceProperties().limits.subPixelPrecisionBits),
621                          rr::PRIMITIVETYPE_TRIANGLES, m_vertices);
622     }
623 
624     // Compare result with reference image
625     {
626         de::MovePtr<tcu::TextureLevel> result = readColorAttachment(
627             m_vkd, *m_device, m_queue, m_queueFamilyIndex, m_allocator, *m_colorImage, m_colorFormat, m_renderSize);
628 
629         compareOk = tcu::intThresholdPositionDeviationCompare(
630             m_context.getTestContext().getLog(), "IntImageCompare", "Image comparison", refRenderer.getAccess(),
631             result->getAccess(), tcu::UVec4(2, 2, 2, 2), tcu::IVec3(1, 1, 0), true, tcu::COMPARE_LOG_RESULT);
632     }
633 
634     if (compareOk)
635         return tcu::TestStatus::pass("Result image matches reference");
636     else
637         return tcu::TestStatus::fail("Image mismatch");
638 }
639 
640 class PushDescriptorBufferGraphicsTest : public vkt::TestCase
641 {
642 public:
643     PushDescriptorBufferGraphicsTest(tcu::TestContext &testContext, const string &name, const TestParams &params);
644     ~PushDescriptorBufferGraphicsTest(void);
645     void checkSupport(Context &context) const;
646     void initPrograms(SourceCollections &sourceCollections) const;
647     TestInstance *createInstance(Context &context) const;
648 
649 protected:
650     const TestParams m_params;
651 };
652 
PushDescriptorBufferGraphicsTest(tcu::TestContext & testContext,const string & name,const TestParams & params)653 PushDescriptorBufferGraphicsTest::PushDescriptorBufferGraphicsTest(tcu::TestContext &testContext, const string &name,
654                                                                    const TestParams &params)
655     : vkt::TestCase(testContext, name)
656     , m_params(params)
657 {
658 }
659 
~PushDescriptorBufferGraphicsTest(void)660 PushDescriptorBufferGraphicsTest::~PushDescriptorBufferGraphicsTest(void)
661 {
662 }
663 
createInstance(Context & context) const664 TestInstance *PushDescriptorBufferGraphicsTest::createInstance(Context &context) const
665 {
666     return new PushDescriptorBufferGraphicsTestInstance(context, m_params);
667 }
668 
checkSupport(Context & context) const669 void PushDescriptorBufferGraphicsTest::checkSupport(Context &context) const
670 {
671     if (m_params.useMaintenance5)
672         context.requireDeviceFunctionality("VK_KHR_maintenance5");
673 
674     checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(),
675                                           m_params.pipelineConstructionType);
676 }
677 
initPrograms(SourceCollections & sourceCollections) const678 void PushDescriptorBufferGraphicsTest::initPrograms(SourceCollections &sourceCollections) const
679 {
680     const string bufferType =
681         m_params.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ? "uniform" : "readonly buffer";
682     const string vertexSrc = "#version 450\n"
683                              "layout(location = 0) in highp vec4 position;\n"
684                              "layout(location = 1) in highp vec4 color;\n"
685                              "layout(location = 0) out highp vec4 vtxColor;\n"
686                              "layout(set = 0, binding = " +
687                              de::toString(m_params.binding) + ") " + bufferType +
688                              " Block\n"
689                              "{\n"
690                              "    vec4 color;\n"
691                              "} inputData;\n"
692                              "\n"
693                              "out gl_PerVertex { vec4 gl_Position; };\n"
694                              "\n"
695                              "void main()\n"
696                              "{\n"
697                              "    gl_Position = position;\n"
698                              "    vtxColor = inputData.color;\n"
699                              "}\n";
700 
701     const string fragmentSrc = "#version 450\n"
702                                "layout(location = 0) in highp vec4 vtxColor;\n"
703                                "layout(location = 0) out highp vec4 fragColor;\n"
704                                "\n"
705                                "void main (void)\n"
706                                "{\n"
707                                "    fragColor = vtxColor;\n"
708                                "}\n";
709 
710     sourceCollections.glslSources.add("vert") << glu::VertexSource(vertexSrc);
711     sourceCollections.glslSources.add("frag") << glu::FragmentSource(fragmentSrc);
712 }
713 
714 class PushDescriptorBufferComputeTestInstance : public vkt::TestInstance
715 {
716 public:
717     PushDescriptorBufferComputeTestInstance(Context &context, const TestParams &params);
718     virtual ~PushDescriptorBufferComputeTestInstance(void);
719     void init(void);
720     virtual tcu::TestStatus iterate(void);
721     tcu::TestStatus verifyOutput(void);
722 
723 private:
724     const TestParams m_params;
725     const PlatformInterface &m_vkp;
726     const Extensions m_instanceExtensions;
727     const CustomInstance m_instance;
728     const InstanceDriver &m_vki;
729     const VkPhysicalDevice m_physicalDevice;
730     const uint32_t m_queueFamilyIndex;
731     const Extensions m_deviceExtensions;
732     std::vector<std::string> m_deviceEnabledExtensions;
733     const Unique<VkDevice> m_device;
734     const DeviceDriver m_vkd;
735     const VkQueue m_queue;
736     const VkDeviceSize m_itemSize;
737     SimpleAllocator m_allocator;
738     Move<VkShaderModule> m_computeShaderModule;
739     vector<VkBufferSp> m_buffers;
740     vector<AllocationSp> m_bufferAllocs;
741     Move<VkBuffer> m_outputBuffer;
742     de::MovePtr<Allocation> m_outputBufferAlloc;
743     Move<VkDescriptorSetLayout> m_descriptorSetLayout;
744     Move<VkPipelineLayout> m_pipelineLayout;
745     Move<VkPipeline> m_computePipeline;
746     Move<VkCommandPool> m_cmdPool;
747     Move<VkCommandBuffer> m_cmdBuffer;
748     std::vector<tcu::Vec4> m_testColors;
749 };
750 
PushDescriptorBufferComputeTestInstance(Context & context,const TestParams & params)751 PushDescriptorBufferComputeTestInstance::PushDescriptorBufferComputeTestInstance(Context &context,
752                                                                                  const TestParams &params)
753     : vkt::TestInstance(context)
754     , m_params(params)
755     , m_vkp(context.getPlatformInterface())
756     , m_instanceExtensions(enumerateInstanceExtensionProperties(m_vkp, DE_NULL))
757     , m_instance(createInstanceWithGetPhysicalDeviceProperties2(context, m_instanceExtensions))
758     , m_vki(m_instance.getDriver())
759     , m_physicalDevice(chooseDevice(m_vki, m_instance, context.getTestContext().getCommandLine()))
760     , m_queueFamilyIndex(findQueueFamilyIndexWithCaps(m_vki, m_physicalDevice, VK_QUEUE_COMPUTE_BIT))
761     , m_deviceExtensions(enumerateDeviceExtensionProperties(m_vki, m_physicalDevice, DE_NULL))
762     , m_device(createDeviceWithPushDescriptor(context, m_vkp, m_instance, m_vki, m_physicalDevice, m_deviceExtensions,
763                                               m_queueFamilyIndex, params, m_deviceEnabledExtensions))
764     , m_vkd(m_vkp, m_instance, *m_device, context.getUsedApiVersion(), context.getTestContext().getCommandLine())
765     , m_queue(getDeviceQueue(m_vkd, *m_device, m_queueFamilyIndex, 0u))
766     , m_itemSize(calcItemSize(m_vki, m_physicalDevice))
767     , m_allocator(m_vkd, *m_device, getPhysicalDeviceMemoryProperties(m_vki, m_physicalDevice))
768 {
769 }
770 
init(void)771 void PushDescriptorBufferComputeTestInstance::init(void)
772 {
773     // Create pipeline layout
774     {
775         // Create descriptor set layout
776         const VkDescriptorSetLayoutBinding descriptorSetLayoutBindings[] = {
777             {
778                 m_params.binding,            // uint32_t binding;
779                 m_params.descriptorType,     // VkDescriptorType descriptorType;
780                 1u,                          // uint32_t descriptorCount;
781                 VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlags stageFlags;
782                 DE_NULL                      // const VkSampler* pImmutableSamplers;
783             },
784             {
785                 m_params.binding + 1,              // uint32_t binding;
786                 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, // VkDescriptorType descriptorType;
787                 1u,                                // uint32_t descriptorCount;
788                 VK_SHADER_STAGE_COMPUTE_BIT,       // VkShaderStageFlags stageFlags;
789                 DE_NULL                            // const VkSampler* pImmutableSamplers;
790             }};
791 
792         const VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {
793             VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,     // VkStructureType sType;
794             DE_NULL,                                                 // const void* pNext;
795             VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR, // VkDescriptorSetLayoutCreateFlags flags;
796             2u,                                                      // uint32_t bindingCount;
797             descriptorSetLayoutBindings                              // const VkDescriptorSetLayoutBinding* pBindings;
798         };
799 
800         m_descriptorSetLayout = createDescriptorSetLayout(m_vkd, *m_device, &descriptorSetLayoutCreateInfo, DE_NULL);
801 
802         // Create pipeline layout
803         const VkPipelineLayoutCreateInfo pipelineLayoutParams = {
804             VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
805             DE_NULL,                                       // const void* pNext;
806             0u,                                            // VkPipelineLayoutCreateFlags flags;
807             1u,                                            // uint32_t descriptorSetCount;
808             &(*m_descriptorSetLayout),                     // const VkDescriptorSetLayout* pSetLayouts;
809             0u,                                            // uint32_t pushConstantRangeCount;
810             DE_NULL                                        // const VkPushDescriptorRange* pPushDescriptorRanges;
811         };
812 
813         m_pipelineLayout = createPipelineLayout(m_vkd, *m_device, &pipelineLayoutParams);
814     }
815 
816     // Fill the test colors table
817     m_testColors.resize(m_params.numCalls);
818     for (uint32_t colorIdx = 0; colorIdx < m_params.numCalls; colorIdx++)
819     {
820         if (colorIdx < DE_LENGTH_OF_ARRAY(defaultTestColors))
821             m_testColors[colorIdx] = defaultTestColors[colorIdx];
822         else
823         {
824             const float mix = static_cast<float>(colorIdx) / static_cast<float>(m_params.numCalls - 1);
825 
826             // interpolate between first and last color, require these colors to be different
827             DE_ASSERT(defaultTestColors[0] != defaultTestColors[DE_LENGTH_OF_ARRAY(defaultTestColors) - 1]);
828             m_testColors[colorIdx] = defaultTestColors[0] * mix +
829                                      defaultTestColors[DE_LENGTH_OF_ARRAY(defaultTestColors) - 1] * (1.0f - mix);
830         }
831     }
832 
833     // Create buffers. One color value in each buffer.
834     {
835         for (uint32_t bufIdx = 0; bufIdx < m_params.numCalls; bufIdx++)
836         {
837             const VkBufferUsageFlags usageFlags = m_params.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ?
838                                                       VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT :
839                                                       VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
840 
841             const VkBufferCreateInfo bufferCreateInfo = {
842                 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
843                 DE_NULL,                              // const void* pNext;
844                 0u,                                   // VkBufferCreateFlags    flags
845                 kSizeofVec4,                          // VkDeviceSize size;
846                 usageFlags,                           // VkBufferUsageFlags usage;
847                 VK_SHARING_MODE_EXCLUSIVE,            // VkSharingMode sharingMode;
848                 1u,                                   // uint32_t queueFamilyCount;
849                 &m_queueFamilyIndex                   // const uint32_t* pQueueFamilyIndices;
850             };
851 
852             m_buffers.push_back(VkBufferSp(new Unique<VkBuffer>(createBuffer(m_vkd, *m_device, &bufferCreateInfo))));
853             m_bufferAllocs.push_back(
854                 AllocationSp(m_allocator
855                                  .allocate(getBufferMemoryRequirements(m_vkd, *m_device, **m_buffers[bufIdx]),
856                                            MemoryRequirement::HostVisible)
857                                  .release()));
858             VK_CHECK(m_vkd.bindBufferMemory(*m_device, **m_buffers[bufIdx], m_bufferAllocs[bufIdx]->getMemory(),
859                                             m_bufferAllocs[bufIdx]->getOffset()));
860 
861             deMemcpy(m_bufferAllocs[bufIdx]->getHostPtr(), &m_testColors[bufIdx], static_cast<size_t>(kSizeofVec4));
862             flushAlloc(m_vkd, *m_device, *m_bufferAllocs[bufIdx]);
863         }
864     }
865 
866     // Create output buffer
867     {
868         const VkBufferCreateInfo bufferCreateInfo = {
869             VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
870             DE_NULL,                              // const void* pNext;
871             0u,                                   // VkBufferCreateFlags    flags
872             m_itemSize * m_params.numCalls,       // VkDeviceSize size;
873             VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,   // VkBufferUsageFlags usage;
874             VK_SHARING_MODE_EXCLUSIVE,            // VkSharingMode sharingMode;
875             1u,                                   // uint32_t queueFamilyCount;
876             &m_queueFamilyIndex                   // const uint32_t* pQueueFamilyIndices;
877         };
878 
879         m_outputBuffer      = createBuffer(m_vkd, *m_device, &bufferCreateInfo);
880         m_outputBufferAlloc = m_allocator.allocate(getBufferMemoryRequirements(m_vkd, *m_device, *m_outputBuffer),
881                                                    MemoryRequirement::HostVisible);
882         VK_CHECK(m_vkd.bindBufferMemory(*m_device, *m_outputBuffer, m_outputBufferAlloc->getMemory(),
883                                         m_outputBufferAlloc->getOffset()));
884     }
885 
886     // Create shader
887     {
888         m_computeShaderModule =
889             createShaderModule(m_vkd, *m_device, m_context.getBinaryCollection().get("compute"), 0u);
890     }
891 
892     // Create pipeline
893     {
894         const VkPipelineShaderStageCreateInfo stageCreateInfo = {
895             VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
896             DE_NULL,                                             // const void* pNext;
897             0u,                                                  // VkPipelineShaderStageCreateFlags flags;
898             VK_SHADER_STAGE_COMPUTE_BIT,                         // VkShaderStageFlagBits stage;
899             *m_computeShaderModule,                              // VkShaderModule module;
900             "main",                                              // const char* pName;
901             DE_NULL                                              // const VkSpecializationInfo* pSpecializationInfo;
902         };
903 
904         const VkComputePipelineCreateInfo createInfo = {
905             VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // VkStructureType sType;
906             DE_NULL,                                        // const void* pNext;
907             0u,                                             // VkPipelineCreateFlags flags;
908             stageCreateInfo,                                // VkPipelineShaderStageCreateInfo stage;
909             *m_pipelineLayout,                              // VkPipelineLayout layout;
910             (VkPipeline)0,                                  // VkPipeline basePipelineHandle;
911             0u,                                             // int32_t basePipelineIndex;
912         };
913 
914         m_computePipeline = createComputePipeline(m_vkd, *m_device, (vk::VkPipelineCache)0u, &createInfo);
915     }
916 
917     // Create command pool
918     m_cmdPool = createCommandPool(m_vkd, *m_device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, m_queueFamilyIndex);
919 
920     // Create command buffer
921     {
922         m_cmdBuffer = allocateCommandBuffer(m_vkd, *m_device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
923         beginCommandBuffer(m_vkd, *m_cmdBuffer, 0u);
924         m_vkd.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_computePipeline);
925 
926         // Dispatch: Each dispatch switches the input buffer.
927         // Output buffer is exposed as a vec4 sized window.
928         for (uint32_t dispatchNdx = 0; dispatchNdx < m_params.numCalls; dispatchNdx++)
929         {
930             VkDescriptorBufferInfo descriptorBufferInfoUbo = {
931                 **m_buffers[dispatchNdx], // VkBuffer buffer;
932                 0u,                       // VkDeviceSize offset;
933                 kSizeofVec4,              // VkDeviceSize range;
934             };
935 
936             VkDescriptorBufferInfo descriptorBufferInfoOutput = {
937                 *m_outputBuffer,          // VkBuffer buffer;
938                 m_itemSize * dispatchNdx, // VkDeviceSize offset;
939                 kSizeofVec4,              // VkDeviceSize range;
940             };
941 
942             VkWriteDescriptorSet writeDescriptorSets[] = {
943                 {
944                     VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // VkStructureType sType;
945                     DE_NULL,                                // const void* pNext;
946                     0u,                                     // VkDescriptorSet dstSet;
947                     m_params.binding,                       // uint32_t dstBinding;
948                     0u,                                     // uint32_t dstArrayElement;
949                     1u,                                     // uint32_t descriptorCount;
950                     m_params.descriptorType,                // VkDescriptorType descriptorType;
951                     DE_NULL,                                // const VkDescriptorImageInfo* pImageInfo;
952                     &descriptorBufferInfoUbo,               // const VkDescriptorBufferInfo* pBufferInfo;
953                     DE_NULL                                 // const VkBufferView* pTexelBufferView;
954                 },
955                 {
956                     VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // VkStructureType sType;
957                     DE_NULL,                                // const void* pNext;
958                     0u,                                     // VkDescriptorSet dstSet;
959                     m_params.binding + 1,                   // uint32_t dstBinding;
960                     0u,                                     // uint32_t dstArrayElement;
961                     1u,                                     // uint32_t descriptorCount;
962                     VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,      // VkDescriptorType descriptorType;
963                     DE_NULL,                                // const VkDescriptorImageInfo* pImageInfo;
964                     &descriptorBufferInfoOutput,            // const VkDescriptorBufferInfo* pBufferInfo;
965                     DE_NULL                                 // const VkBufferView* pTexelBufferView;
966                 }};
967 
968             m_vkd.cmdPushDescriptorSetKHR(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipelineLayout, 0, 2,
969                                           writeDescriptorSets);
970             m_vkd.cmdDispatch(*m_cmdBuffer, 1, 1, 1);
971         }
972 
973         endCommandBuffer(m_vkd, *m_cmdBuffer);
974     }
975 }
976 
~PushDescriptorBufferComputeTestInstance(void)977 PushDescriptorBufferComputeTestInstance::~PushDescriptorBufferComputeTestInstance(void)
978 {
979 }
980 
iterate(void)981 tcu::TestStatus PushDescriptorBufferComputeTestInstance::iterate(void)
982 {
983     init();
984 
985     submitCommandsAndWait(m_vkd, *m_device, m_queue, m_cmdBuffer.get());
986 
987     return verifyOutput();
988 }
989 
verifyOutput(void)990 tcu::TestStatus PushDescriptorBufferComputeTestInstance::verifyOutput(void)
991 {
992     invalidateAlloc(m_vkd, *m_device, *m_outputBufferAlloc);
993 
994     // Verify result
995     auto bufferPtr = reinterpret_cast<const char *>(m_outputBufferAlloc->getHostPtr());
996     for (uint32_t i = 0; i < m_params.numCalls; ++i)
997     {
998         if (deMemCmp(&m_testColors[i], bufferPtr + (i * m_itemSize), static_cast<size_t>(kSizeofVec4)) != 0)
999             TCU_FAIL("Output mismatch at output item " + de::toString(i));
1000     }
1001 
1002     return tcu::TestStatus::pass("Output matches expected values");
1003 }
1004 
1005 class PushDescriptorBufferComputeTest : public vkt::TestCase
1006 {
1007 public:
1008     PushDescriptorBufferComputeTest(tcu::TestContext &testContext, const string &name, const TestParams &params);
1009     ~PushDescriptorBufferComputeTest(void);
1010     void initPrograms(SourceCollections &sourceCollections) const;
1011     TestInstance *createInstance(Context &context) const;
1012 
1013 protected:
1014     const TestParams m_params;
1015 };
1016 
PushDescriptorBufferComputeTest(tcu::TestContext & testContext,const string & name,const TestParams & params)1017 PushDescriptorBufferComputeTest::PushDescriptorBufferComputeTest(tcu::TestContext &testContext, const string &name,
1018                                                                  const TestParams &params)
1019     : vkt::TestCase(testContext, name)
1020     , m_params(params)
1021 {
1022 }
1023 
~PushDescriptorBufferComputeTest(void)1024 PushDescriptorBufferComputeTest::~PushDescriptorBufferComputeTest(void)
1025 {
1026 }
1027 
createInstance(Context & context) const1028 TestInstance *PushDescriptorBufferComputeTest::createInstance(Context &context) const
1029 {
1030     return new PushDescriptorBufferComputeTestInstance(context, m_params);
1031 }
1032 
initPrograms(SourceCollections & sourceCollections) const1033 void PushDescriptorBufferComputeTest::initPrograms(SourceCollections &sourceCollections) const
1034 {
1035     const string bufferType = m_params.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ? "uniform" : "buffer";
1036     const string computeSrc = "#version 450\n"
1037                               "layout(set = 0, binding = " +
1038                               de::toString(m_params.binding) + ") " + bufferType +
1039                               " Block\n"
1040                               "{\n"
1041                               "    vec4 color;\n"
1042                               "} inputData;\n"
1043                               "\n"
1044                               "layout(set = 0, binding = " +
1045                               de::toString(m_params.binding + 1) +
1046                               ") writeonly buffer Output\n"
1047                               "{\n"
1048                               "    vec4 color;\n"
1049                               "} outData;\n"
1050                               "\n"
1051                               "void main()\n"
1052                               "{\n"
1053                               "    outData.color = inputData.color;\n"
1054                               "}\n";
1055 
1056     sourceCollections.glslSources.add("compute") << glu::ComputeSource(computeSrc);
1057 }
1058 
1059 class PushDescriptorImageGraphicsTestInstance : public vkt::TestInstance
1060 {
1061 public:
1062     PushDescriptorImageGraphicsTestInstance(Context &context, const TestParams &params);
1063     virtual ~PushDescriptorImageGraphicsTestInstance(void);
1064     void init(void);
1065     virtual tcu::TestStatus iterate(void);
1066     tcu::TestStatus verifyImage(void);
1067 
1068 private:
1069     const TestParams m_params;
1070     const PlatformInterface &m_vkp;
1071     const Extensions m_instanceExtensions;
1072     const CustomInstance m_instance;
1073     const InstanceDriver &m_vki;
1074     const VkPhysicalDevice m_physicalDevice;
1075     const uint32_t m_queueFamilyIndex;
1076     const Extensions m_deviceExtensions;
1077     std::vector<std::string> m_deviceEnabledExtensions;
1078     const Unique<VkDevice> m_device;
1079     const DeviceDriver m_vkd;
1080     const VkQueue m_queue;
1081     SimpleAllocator m_allocator;
1082     const tcu::UVec2 m_renderSize;
1083     const tcu::UVec2 m_textureSize;
1084     const VkFormat m_colorFormat;
1085     Move<VkImage> m_colorImage;
1086     de::MovePtr<Allocation> m_colorImageAlloc;
1087     Move<VkImageView> m_colorAttachmentView;
1088     vector<VkImageSp> m_textureImages;
1089     vector<AllocationSp> m_textureImageAllocs;
1090     vector<VkImageViewSp> m_textureViews;
1091     Move<VkSampler> m_whiteBorderSampler;
1092     Move<VkSampler> m_blackBorderSampler;
1093     RenderPassWrapper m_renderPass;
1094     Move<VkFramebuffer> m_framebuffer;
1095     ShaderWrapper m_vertexShaderModule;
1096     ShaderWrapper m_fragmentShaderModule;
1097     Move<VkBuffer> m_vertexBuffer;
1098     de::MovePtr<Allocation> m_vertexBufferAlloc;
1099     Move<VkDescriptorSetLayout> m_descriptorSetLayout;
1100     PipelineLayoutWrapper m_preRasterizationStatePipelineLayout;
1101     PipelineLayoutWrapper m_fragmentStatePipelineLayout;
1102     GraphicsPipelineWrapper m_graphicsPipeline;
1103     Move<VkCommandPool> m_cmdPool;
1104     Move<VkCommandBuffer> m_cmdBuffer;
1105     vector<Vertex4Tex4> m_vertices;
1106 };
1107 
PushDescriptorImageGraphicsTestInstance(Context & context,const TestParams & params)1108 PushDescriptorImageGraphicsTestInstance::PushDescriptorImageGraphicsTestInstance(Context &context,
1109                                                                                  const TestParams &params)
1110     : vkt::TestInstance(context)
1111     , m_params(params)
1112     , m_vkp(context.getPlatformInterface())
1113     , m_instanceExtensions(enumerateInstanceExtensionProperties(m_vkp, DE_NULL))
1114     , m_instance(createInstanceWithGetPhysicalDeviceProperties2(context, m_instanceExtensions))
1115     , m_vki(m_instance.getDriver())
1116     , m_physicalDevice(chooseDevice(m_vki, m_instance, context.getTestContext().getCommandLine()))
1117     , m_queueFamilyIndex(findQueueFamilyIndexWithCaps(m_vki, m_physicalDevice, VK_QUEUE_GRAPHICS_BIT))
1118     , m_deviceExtensions(enumerateDeviceExtensionProperties(m_vki, m_physicalDevice, DE_NULL))
1119     , m_device(createDeviceWithPushDescriptor(context, m_vkp, m_instance, m_vki, m_physicalDevice, m_deviceExtensions,
1120                                               m_queueFamilyIndex, params, m_deviceEnabledExtensions))
1121     , m_vkd(m_vkp, m_instance, *m_device, context.getUsedApiVersion(), context.getTestContext().getCommandLine())
1122     , m_queue(getDeviceQueue(m_vkd, *m_device, m_queueFamilyIndex, 0u))
1123     , m_allocator(m_vkd, *m_device, getPhysicalDeviceMemoryProperties(m_vki, m_physicalDevice))
1124     , m_renderSize(32, 32)
1125     , m_textureSize(32, 32)
1126     , m_colorFormat(VK_FORMAT_R8G8B8A8_UNORM)
1127     , m_graphicsPipeline(m_vki, m_vkd, m_physicalDevice, *m_device, m_deviceEnabledExtensions,
1128                          params.pipelineConstructionType)
1129     , m_vertices(createTexQuads(params.numCalls, 0.25f))
1130 {
1131 }
1132 
init(void)1133 void PushDescriptorImageGraphicsTestInstance::init(void)
1134 {
1135     const VkComponentMapping componentMappingRGBA = {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G,
1136                                                      VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A};
1137 
1138     // Create color image
1139     {
1140 
1141         const VkImageCreateInfo colorImageParams = {
1142             VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                                   // VkStructureType sType;
1143             DE_NULL,                                                               // const void* pNext;
1144             0u,                                                                    // VkImageCreateFlags flags;
1145             VK_IMAGE_TYPE_2D,                                                      // VkImageType imageType;
1146             m_colorFormat,                                                         // VkFormat format;
1147             {m_renderSize.x(), m_renderSize.y(), 1u},                              // VkExtent3D extent;
1148             1u,                                                                    // uint32_t mipLevels;
1149             1u,                                                                    // uint32_t arrayLayers;
1150             VK_SAMPLE_COUNT_1_BIT,                                                 // VkSampleCountFlagBits samples;
1151             VK_IMAGE_TILING_OPTIMAL,                                               // VkImageTiling tiling;
1152             VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
1153             VK_SHARING_MODE_EXCLUSIVE,                                             // VkSharingMode sharingMode;
1154             1u,                                                                    // uint32_t queueFamilyIndexCount;
1155             &m_queueFamilyIndex,      // const uint32_t* pQueueFamilyIndices;
1156             VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
1157         };
1158 
1159         m_colorImage = createImage(m_vkd, *m_device, &colorImageParams);
1160 
1161         // Allocate and bind color image memory
1162         m_colorImageAlloc =
1163             m_allocator.allocate(getImageMemoryRequirements(m_vkd, *m_device, *m_colorImage), MemoryRequirement::Any);
1164         VK_CHECK(m_vkd.bindImageMemory(*m_device, *m_colorImage, m_colorImageAlloc->getMemory(),
1165                                        m_colorImageAlloc->getOffset()));
1166     }
1167 
1168     // Create color attachment view
1169     {
1170         const VkImageViewCreateInfo colorAttachmentViewParams = {
1171             VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,   // VkStructureType sType;
1172             DE_NULL,                                    // const void* pNext;
1173             0u,                                         // VkImageViewCreateFlags flags;
1174             *m_colorImage,                              // VkImage image;
1175             VK_IMAGE_VIEW_TYPE_2D,                      // VkImageViewType viewType;
1176             m_colorFormat,                              // VkFormat format;
1177             componentMappingRGBA,                       // VkChannelMapping channels;
1178             {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u} // VkImageSubresourceRange subresourceRange;
1179         };
1180 
1181         m_colorAttachmentView = createImageView(m_vkd, *m_device, &colorAttachmentViewParams);
1182     }
1183 
1184     // Create texture images
1185     for (uint32_t texIdx = 0; texIdx < 2; texIdx++)
1186     {
1187         VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_TRANSFER_DST_BIT;
1188         if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER ||
1189             m_params.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||
1190             m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
1191             usageFlags |= VK_IMAGE_USAGE_SAMPLED_BIT;
1192         if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
1193             usageFlags |= VK_IMAGE_USAGE_STORAGE_BIT;
1194 
1195         const VkImageCreateInfo textureImageParams = {
1196             VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,        // VkStructureType sType;
1197             DE_NULL,                                    // const void* pNext;
1198             0u,                                         // VkImageCreateFlags flags;
1199             VK_IMAGE_TYPE_2D,                           // VkImageType imageType;
1200             m_colorFormat,                              // VkFormat format;
1201             {m_textureSize.x(), m_textureSize.y(), 1u}, // VkExtent3D extent;
1202             1u,                                         // uint32_t mipLevels;
1203             1u,                                         // uint32_t arrayLayers;
1204             VK_SAMPLE_COUNT_1_BIT,                      // VkSampleCountFlagBits samples;
1205             VK_IMAGE_TILING_OPTIMAL,                    // VkImageTiling tiling;
1206             usageFlags,                                 // VkImageUsageFlags usage;
1207             VK_SHARING_MODE_EXCLUSIVE,                  // VkSharingMode sharingMode;
1208             1u,                                         // uint32_t queueFamilyIndexCount;
1209             &m_queueFamilyIndex,                        // const uint32_t* pQueueFamilyIndices;
1210             VK_IMAGE_LAYOUT_UNDEFINED                   // VkImageLayout initialLayout;
1211         };
1212 
1213         m_textureImages.push_back(VkImageSp(new Unique<VkImage>(createImage(m_vkd, *m_device, &textureImageParams))));
1214 
1215         // Allocate and bind texture image memory
1216         m_textureImageAllocs.push_back(
1217             AllocationSp(m_allocator
1218                              .allocate(getImageMemoryRequirements(m_vkd, *m_device, **m_textureImages.back()),
1219                                        MemoryRequirement::Any)
1220                              .release()));
1221         VK_CHECK(m_vkd.bindImageMemory(*m_device, **m_textureImages.back(), m_textureImageAllocs.back()->getMemory(),
1222                                        m_textureImageAllocs.back()->getOffset()));
1223     }
1224 
1225     // Create texture image views
1226     for (uint32_t texIdx = 0; texIdx < 2; texIdx++)
1227     {
1228         const VkImageViewCreateInfo textureViewParams = {
1229             VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,   // VkStructureType sType;
1230             DE_NULL,                                    // const void* pNext;
1231             0u,                                         // VkImageViewCreateFlags flags;
1232             **m_textureImages[texIdx],                  // VkImage image;
1233             VK_IMAGE_VIEW_TYPE_2D,                      // VkImageViewType viewType;
1234             m_colorFormat,                              // VkFormat format;
1235             componentMappingRGBA,                       // VkChannelMapping channels;
1236             {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u} // VkImageSubresourceRange subresourceRange;
1237         };
1238 
1239         m_textureViews.push_back(
1240             VkImageViewSp(new Unique<VkImageView>(createImageView(m_vkd, *m_device, &textureViewParams))));
1241     }
1242 
1243     VkClearValue clearValues[2];
1244     clearValues[0].color.float32[0] = 0.0f;
1245     clearValues[0].color.float32[1] = 1.0f;
1246     clearValues[0].color.float32[2] = 0.0f;
1247     clearValues[0].color.float32[3] = 1.0f;
1248     clearValues[1].color.float32[0] = 1.0f;
1249     clearValues[1].color.float32[1] = 0.0f;
1250     clearValues[1].color.float32[2] = 0.0f;
1251     clearValues[1].color.float32[3] = 1.0f;
1252 
1253     const VkImageLayout textureImageLayout = (m_params.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) ?
1254                                                  VK_IMAGE_LAYOUT_GENERAL :
1255                                                  VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
1256 
1257     // Clear textures
1258     for (uint32_t texIdx = 0; texIdx < 2; texIdx++)
1259     {
1260         const VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1261         Move<VkCommandPool> cmdPool;
1262         Move<VkCommandBuffer> cmdBuffer;
1263 
1264         cmdPool   = createCommandPool(m_vkd, *m_device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, m_queueFamilyIndex);
1265         cmdBuffer = allocateCommandBuffer(m_vkd, *m_device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1266 
1267         const VkImageMemoryBarrier preImageBarrier = {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1268                                                       DE_NULL,                                // const void* pNext;
1269                                                       0u,                           // VkAccessFlags srcAccessMask;
1270                                                       VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask;
1271                                                       VK_IMAGE_LAYOUT_UNDEFINED,    // VkImageLayout oldLayout;
1272                                                       VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout;
1273                                                       VK_QUEUE_FAMILY_IGNORED,   // uint32_t srcQueueFamilyIndex;
1274                                                       VK_QUEUE_FAMILY_IGNORED,   // uint32_t dstQueueFamilyIndex;
1275                                                       **m_textureImages[texIdx], // VkImage image;
1276                                                       {
1277                                                           // VkImageSubresourceRange subresourceRange;
1278                                                           aspectMask, // VkImageAspect aspect;
1279                                                           0u,         // uint32_t baseMipLevel;
1280                                                           1u,         // uint32_t mipLevels;
1281                                                           0u,         // uint32_t baseArraySlice;
1282                                                           1u          // uint32_t arraySize;
1283                                                       }};
1284 
1285         const VkImageMemoryBarrier postImageBarrier = {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1286                                                        DE_NULL,                                // const void* pNext;
1287                                                        VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
1288                                                        VK_ACCESS_SHADER_READ_BIT,    // VkAccessFlags dstAccessMask;
1289                                                        VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout;
1290                                                        textureImageLayout,                   // VkImageLayout newLayout;
1291                                                        VK_QUEUE_FAMILY_IGNORED,   // uint32_t srcQueueFamilyIndex;
1292                                                        VK_QUEUE_FAMILY_IGNORED,   // uint32_t dstQueueFamilyIndex;
1293                                                        **m_textureImages[texIdx], // VkImage image;
1294                                                        {
1295                                                            // VkImageSubresourceRange subresourceRange;
1296                                                            aspectMask, // VkImageAspect aspect;
1297                                                            0u,         // uint32_t baseMipLevel;
1298                                                            1u,         // uint32_t mipLevels;
1299                                                            0u,         // uint32_t baseArraySlice;
1300                                                            1u          // uint32_t arraySize;
1301                                                        }};
1302 
1303         const VkImageSubresourceRange clearRange = {
1304             aspectMask, // VkImageAspectFlags aspectMask;
1305             0u,         // uint32_t baseMipLevel;
1306             1u,         // uint32_t levelCount;
1307             0u,         // uint32_t baseArrayLayer;
1308             1u          // uint32_t layerCount;
1309         };
1310 
1311         beginCommandBuffer(m_vkd, *cmdBuffer);
1312         m_vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
1313                                  (VkDependencyFlags)0, 0, (const VkMemoryBarrier *)DE_NULL, 0,
1314                                  (const VkBufferMemoryBarrier *)DE_NULL, 1, &preImageBarrier);
1315         m_vkd.cmdClearColorImage(*cmdBuffer, **m_textureImages[texIdx], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1316                                  &clearValues[texIdx].color, 1, &clearRange);
1317         m_vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
1318                                  (VkDependencyFlags)0, 0, (const VkMemoryBarrier *)DE_NULL, 0,
1319                                  (const VkBufferMemoryBarrier *)DE_NULL, 1, &postImageBarrier);
1320         endCommandBuffer(m_vkd, *cmdBuffer);
1321 
1322         submitCommandsAndWait(m_vkd, *m_device, m_queue, cmdBuffer.get());
1323     }
1324 
1325     // Create samplers: one with white and one with black border color to have a visible effect on switching the sampler
1326     {
1327         VkSamplerCreateInfo samplerParams = {
1328             VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,   // VkStructureType sType;
1329             DE_NULL,                                 // const void* pNext;
1330             0u,                                      // VkSamplerCreateFlags flags;
1331             VK_FILTER_NEAREST,                       // VkFilter magFilter;
1332             VK_FILTER_NEAREST,                       // VkFilter minFilter;
1333             VK_SAMPLER_MIPMAP_MODE_NEAREST,          // VkSamplerMipmapMode mipmapMode;
1334             VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, // VkSamplerAddressMode addressModeU;
1335             VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, // VkSamplerAddressMode addressModeV;
1336             VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, // VkSamplerAddressMode addressModeW;
1337             0.0f,                                    // float mipLodBias;
1338             VK_FALSE,                                // VkBool32 anisotropyEnable;
1339             0.0f,                                    // float maxAnisotropy;
1340             VK_FALSE,                                // VkBool32 compareEnable;
1341             VK_COMPARE_OP_NEVER,                     // VkCompareOp compareOp;
1342             0.0f,                                    // float minLod;
1343             0.0f,                                    // float maxLod;
1344             VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE,      // VkBorderColor borderColor;
1345             VK_FALSE                                 // VkBool32 unnormalizedCoordinates;
1346         };
1347 
1348         m_whiteBorderSampler      = createSampler(m_vkd, *m_device, &samplerParams);
1349         samplerParams.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK;
1350         m_blackBorderSampler      = createSampler(m_vkd, *m_device, &samplerParams);
1351     }
1352 
1353     // Create render pass
1354     {
1355         const VkAttachmentDescription attachmentDescription = {
1356             (VkAttachmentDescriptionFlags)0,         // VkAttachmentDescriptionFlags    flags
1357             VK_FORMAT_R8G8B8A8_UNORM,                // VkFormat                        format
1358             VK_SAMPLE_COUNT_1_BIT,                   // VkSampleCountFlagBits        samples
1359             VK_ATTACHMENT_LOAD_OP_CLEAR,             // VkAttachmentLoadOp            loadOp
1360             VK_ATTACHMENT_STORE_OP_STORE,            // VkAttachmentStoreOp            storeOp
1361             VK_ATTACHMENT_LOAD_OP_DONT_CARE,         // VkAttachmentLoadOp            stencilLoadOp
1362             VK_ATTACHMENT_STORE_OP_DONT_CARE,        // VkAttachmentStoreOp            stencilStoreOp
1363             VK_IMAGE_LAYOUT_UNDEFINED,               // VkImageLayout                initialLayout
1364             VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout                finalLayout
1365         };
1366 
1367         const VkAttachmentReference resultAttachmentRef = {
1368             0u,                                      // uint32_t            attachment
1369             VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout    layout
1370         };
1371 
1372         const VkSubpassDescription subpassDescription = {
1373             (VkSubpassDescriptionFlags)0,    // VkSubpassDescriptionFlags    flags
1374             VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint            pipelineBindPoint
1375             0u,                              // uint32_t                        inputAttachmentCount
1376             DE_NULL,                         // const VkAttachmentReference*    pInputAttachments
1377             1u,                              // uint32_t                        colorAttachmentCount
1378             &resultAttachmentRef,            // const VkAttachmentReference*    pColorAttachments
1379             DE_NULL,                         // const VkAttachmentReference*    pResolveAttachments
1380             DE_NULL,                         // const VkAttachmentReference*    pDepthStencilAttachment
1381             0u,                              // uint32_t                        preserveAttachmentCount
1382             DE_NULL                          // const uint32_t*                pPreserveAttachments
1383         };
1384 
1385         const VkRenderPassCreateInfo renderPassInfo = {
1386             VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureTypei                    sType
1387             DE_NULL,                                   // const void*                        pNext
1388             (VkRenderPassCreateFlags)0,                // VkRenderPassCreateFlags            flags
1389             1u,                                        // uint32_t                            attachmentCount
1390             &attachmentDescription,                    // const VkAttachmentDescription*    pAttachments
1391             1u,                                        // uint32_t                            subpassCount
1392             &subpassDescription,                       // const VkSubpassDescription*        pSubpasses
1393             0u,                                        // uint32_t                            dependencyCount
1394             DE_NULL                                    // const VkSubpassDependency*        pDependencies
1395         };
1396 
1397         m_renderPass = RenderPassWrapper(m_params.pipelineConstructionType, m_vkd, *m_device, &renderPassInfo);
1398     }
1399 
1400     // Create framebuffer
1401     {
1402         const VkImageView attachmentBindInfos[] = {*m_colorAttachmentView};
1403 
1404         const VkFramebufferCreateInfo framebufferParams = {
1405             VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
1406             DE_NULL,                                   // const void* pNext;
1407             0u,                                        // VkFramebufferCreateFlags flags;
1408             *m_renderPass,                             // VkRenderPass renderPass;
1409             1u,                                        // uint32_t attachmentCount;
1410             attachmentBindInfos,                       // const VkImageView* pAttachments;
1411             (uint32_t)m_renderSize.x(),                // uint32_t width;
1412             (uint32_t)m_renderSize.y(),                // uint32_t height;
1413             1u                                         // uint32_t layers;
1414         };
1415 
1416         m_renderPass.createFramebuffer(m_vkd, *m_device, &framebufferParams, *m_colorImage);
1417     }
1418 
1419     // Create pipeline layout
1420     {
1421         // Create descriptor set layout
1422         vector<VkDescriptorSetLayoutBinding> layoutBindings;
1423 
1424         switch (m_params.descriptorType)
1425         {
1426         case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
1427         {
1428             const VkDescriptorSetLayoutBinding descriptorSetLayoutBinding = {
1429                 m_params.binding,                          // uint32_t binding;
1430                 VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, // VkDescriptorType descriptorType;
1431                 1u,                                        // uint32_t descriptorCount;
1432                 VK_SHADER_STAGE_FRAGMENT_BIT,              // VkShaderStageFlags stageFlags;
1433                 DE_NULL                                    // const VkSampler* pImmutableSamplers;
1434             };
1435             layoutBindings.push_back(descriptorSetLayoutBinding);
1436         }
1437         break;
1438 
1439         case VK_DESCRIPTOR_TYPE_SAMPLER:
1440         {
1441             const VkDescriptorSetLayoutBinding descriptorSetLayoutBindingSampler = {
1442                 m_params.binding,             // uint32_t binding;
1443                 VK_DESCRIPTOR_TYPE_SAMPLER,   // VkDescriptorType descriptorType;
1444                 1u,                           // uint32_t descriptorCount;
1445                 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlags stageFlags;
1446                 DE_NULL                       // const VkSampler* pImmutableSamplers;
1447             };
1448             const VkDescriptorSetLayoutBinding descriptorSetLayoutBindingTex = {
1449                 m_params.binding + 1,             // uint32_t binding;
1450                 VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, // VkDescriptorType descriptorType;
1451                 1u,                               // uint32_t descriptorCount;
1452                 VK_SHADER_STAGE_FRAGMENT_BIT,     // VkShaderStageFlags stageFlags;
1453                 DE_NULL                           // const VkSampler* pImmutableSamplers;
1454             };
1455             layoutBindings.push_back(descriptorSetLayoutBindingSampler);
1456             layoutBindings.push_back(descriptorSetLayoutBindingTex);
1457         }
1458         break;
1459 
1460         case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
1461         {
1462             const VkDescriptorSetLayoutBinding descriptorSetLayoutBindingSampler = {
1463                 m_params.binding + 1,         // uint32_t binding;
1464                 VK_DESCRIPTOR_TYPE_SAMPLER,   // VkDescriptorType descriptorType;
1465                 1u,                           // uint32_t descriptorCount;
1466                 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlags stageFlags;
1467                 DE_NULL                       // const VkSampler* pImmutableSamplers;
1468             };
1469             const VkDescriptorSetLayoutBinding descriptorSetLayoutBindingTex = {
1470                 m_params.binding,                 // uint32_t binding;
1471                 VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, // VkDescriptorType descriptorType;
1472                 1u,                               // uint32_t descriptorCount;
1473                 VK_SHADER_STAGE_FRAGMENT_BIT,     // VkShaderStageFlags stageFlags;
1474                 DE_NULL                           // const VkSampler* pImmutableSamplers;
1475             };
1476             layoutBindings.push_back(descriptorSetLayoutBindingSampler);
1477             layoutBindings.push_back(descriptorSetLayoutBindingTex);
1478         }
1479         break;
1480 
1481         case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
1482         {
1483             const VkDescriptorSetLayoutBinding descriptorSetLayoutBinding = {
1484                 m_params.binding,                 // uint32_t binding;
1485                 VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, // VkDescriptorType descriptorType;
1486                 1u,                               // uint32_t descriptorCount;
1487                 VK_SHADER_STAGE_FRAGMENT_BIT,     // VkShaderStageFlags stageFlags;
1488                 DE_NULL                           // const VkSampler* pImmutableSamplers;
1489             };
1490             layoutBindings.push_back(descriptorSetLayoutBinding);
1491         }
1492         break;
1493 
1494         default:
1495             DE_FATAL("unexpected descriptor type");
1496             break;
1497         }
1498 
1499         const VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {
1500             VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,     // VkStructureType sType;
1501             DE_NULL,                                                 // const void* pNext;
1502             VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR, // VkDescriptorSetLayoutCreateFlags flags;
1503             (uint32_t)layoutBindings.size(),                         // uint32_t bindingCount;
1504             layoutBindings.data()                                    // const VkDescriptorSetLayoutBinding* pBindings;
1505         };
1506 
1507         m_descriptorSetLayout = createDescriptorSetLayout(m_vkd, *m_device, &descriptorSetLayoutCreateInfo, DE_NULL);
1508 
1509         // Create pipeline layout
1510         VkPipelineLayoutCreateFlags pipelineLayoutFlags =
1511             (m_params.pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC) ?
1512                 0u :
1513                 uint32_t(VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT);
1514         VkPipelineLayoutCreateInfo pipelineLayoutParams{
1515             VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
1516             DE_NULL,                                       // const void* pNext;
1517             pipelineLayoutFlags,                           // VkPipelineLayoutCreateFlags flags;
1518             0u,                                            // uint32_t setLayoutCount;
1519             DE_NULL,                                       // const VkDescriptorSetLayout* pSetLayouts;
1520             0u,                                            // uint32_t pushConstantRangeCount;
1521             DE_NULL                                        // const VkPushDescriptorRange* pPushDescriptorRanges;
1522         };
1523 
1524         m_preRasterizationStatePipelineLayout =
1525             PipelineLayoutWrapper(m_params.pipelineConstructionType, m_vkd, *m_device, &pipelineLayoutParams);
1526         pipelineLayoutParams.setLayoutCount = 1u;
1527         pipelineLayoutParams.pSetLayouts    = &(*m_descriptorSetLayout);
1528         m_fragmentStatePipelineLayout =
1529             PipelineLayoutWrapper(m_params.pipelineConstructionType, m_vkd, *m_device, &pipelineLayoutParams);
1530     }
1531 
1532     // Create shaders
1533     {
1534         m_vertexShaderModule   = ShaderWrapper(m_vkd, *m_device, m_context.getBinaryCollection().get("vert"), 0u);
1535         m_fragmentShaderModule = ShaderWrapper(m_vkd, *m_device, m_context.getBinaryCollection().get("frag"), 0u);
1536     }
1537 
1538     // Create pipeline
1539     {
1540         const VkVertexInputBindingDescription vertexInputBindingDescription = {
1541             0u,                         // uint32_t binding;
1542             sizeof(Vertex4Tex4),        // uint32_t strideInBytes;
1543             VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate stepRate;
1544         };
1545 
1546         const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] = {
1547             {
1548                 0u,                            // uint32_t location;
1549                 0u,                            // uint32_t binding;
1550                 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
1551                 0u                             // uint32_t offsetInBytes;
1552             },
1553             {
1554                 1u,                              // uint32_t location;
1555                 0u,                              // uint32_t binding;
1556                 VK_FORMAT_R32G32B32A32_SFLOAT,   // VkFormat format;
1557                 offsetof(Vertex4Tex4, texCoord), // uint32_t offset;
1558             }};
1559 
1560         const VkPipelineVertexInputStateCreateInfo vertexInputStateParams = {
1561             VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
1562             DE_NULL,                                                   // const void* pNext;
1563             0u,                                                        // vkPipelineVertexInputStateCreateFlags flags;
1564             1u,                                                        // uint32_t bindingCount;
1565             &vertexInputBindingDescription,  // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
1566             2u,                              // uint32_t attributeCount;
1567             vertexInputAttributeDescriptions // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
1568         };
1569 
1570         const vector<VkViewport> viewports{makeViewport(m_renderSize)};
1571         const vector<VkRect2D> scissors{makeRect2D(m_renderSize)};
1572 
1573         m_graphicsPipeline.setMonolithicPipelineLayout(m_fragmentStatePipelineLayout)
1574             .setDefaultRasterizationState()
1575             .setDefaultDepthStencilState()
1576             .setDefaultMultisampleState()
1577             .setDefaultColorBlendState()
1578             .setupVertexInputState(&vertexInputStateParams)
1579             .setupPreRasterizationShaderState(viewports, scissors, m_preRasterizationStatePipelineLayout, *m_renderPass,
1580                                               0u, m_vertexShaderModule)
1581             .setupFragmentShaderState(m_fragmentStatePipelineLayout, *m_renderPass, 0u, m_fragmentShaderModule)
1582             .setupFragmentOutputState(*m_renderPass)
1583             .buildPipeline();
1584     }
1585 
1586     // Create vertex buffer
1587     {
1588         const VkBufferCreateInfo vertexBufferParams = {
1589             VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,                    // VkStructureType sType;
1590             DE_NULL,                                                 // const void* pNext;
1591             0u,                                                      // VkBufferCreateFlags flags;
1592             (VkDeviceSize)(sizeof(Vertex4RGBA) * m_vertices.size()), // VkDeviceSize size;
1593             VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,                       // VkBufferUsageFlags usage;
1594             VK_SHARING_MODE_EXCLUSIVE,                               // VkSharingMode sharingMode;
1595             1u,                                                      // uint32_t queueFamilyCount;
1596             &m_queueFamilyIndex                                      // const uint32_t* pQueueFamilyIndices;
1597         };
1598 
1599         m_vertexBuffer      = createBuffer(m_vkd, *m_device, &vertexBufferParams);
1600         m_vertexBufferAlloc = m_allocator.allocate(getBufferMemoryRequirements(m_vkd, *m_device, *m_vertexBuffer),
1601                                                    MemoryRequirement::HostVisible);
1602 
1603         VK_CHECK(m_vkd.bindBufferMemory(*m_device, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(),
1604                                         m_vertexBufferAlloc->getOffset()));
1605 
1606         // Load vertices into vertex buffer
1607         deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4Tex4));
1608         flushAlloc(m_vkd, *m_device, *m_vertexBufferAlloc);
1609     }
1610 
1611     // Create command pool
1612     m_cmdPool = createCommandPool(m_vkd, *m_device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, m_queueFamilyIndex);
1613 
1614     // Create command buffer
1615     {
1616         const VkClearValue attachmentClearValue = defaultClearValue(m_colorFormat);
1617         const VkDeviceSize vertexBufferOffset   = 0;
1618 
1619         m_cmdBuffer = allocateCommandBuffer(m_vkd, *m_device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1620         beginCommandBuffer(m_vkd, *m_cmdBuffer, 0u);
1621         m_renderPass.begin(m_vkd, *m_cmdBuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()),
1622                            attachmentClearValue);
1623         m_graphicsPipeline.bind(*m_cmdBuffer);
1624         m_vkd.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
1625 
1626         // Draw quads. Switch sampler or image view depending on the test.
1627         vector<VkSampler> samplers;
1628         vector<VkImageView> imageViews;
1629 
1630         samplers.push_back(*m_whiteBorderSampler);
1631         if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER ||
1632             m_params.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
1633         {
1634             // Vary sampler between draws
1635             samplers.push_back(*m_blackBorderSampler);
1636         }
1637         else
1638         {
1639             // Usa a single sampler
1640             samplers.push_back(*m_whiteBorderSampler);
1641         }
1642 
1643         imageViews.push_back(**m_textureViews[0]);
1644         if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ||
1645             m_params.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||
1646             m_params.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
1647         {
1648             // Vary image view between draws
1649             imageViews.push_back(**m_textureViews[1]);
1650         }
1651         else
1652         {
1653             // Usa a single image view
1654             imageViews.push_back(**m_textureViews[0]);
1655         }
1656 
1657         for (uint32_t quadNdx = 0; quadNdx < m_params.numCalls; quadNdx++)
1658         {
1659             VkDescriptorImageInfo descriptorImageInfo = {
1660                 samplers[quadNdx],   // VkSampler sampler;
1661                 imageViews[quadNdx], // VkImageView imageView;
1662                 textureImageLayout   // VkImageLayout imageLayout;
1663             };
1664 
1665             VkWriteDescriptorSet writeDescriptorSet = {
1666                 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // VkStructureType sType;
1667                 DE_NULL,                                // const void* pNext;
1668                 0u,                                     // VkDescriptorSet dstSet;
1669                 m_params.binding,                       // uint32_t dstBinding;
1670                 0u,                                     // uint32_t dstArrayElement;
1671                 1u,                                     // uint32_t descriptorCount;
1672                 m_params.descriptorType,                // VkDescriptorType descriptorType;
1673                 &descriptorImageInfo,                   // const VkDescriptorImageInfo* pImageInfo;
1674                 DE_NULL,                                // const VkDescriptorBufferInfo* pBufferInfo;
1675                 DE_NULL                                 // const VkBufferView* pTexelBufferView;
1676             };
1677 
1678             vector<VkWriteDescriptorSet> writeDescriptorSets;
1679             writeDescriptorSets.push_back(writeDescriptorSet);
1680 
1681             if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER)
1682             {
1683                 // Sampler also needs an image.
1684                 writeDescriptorSet.dstBinding++;
1685                 writeDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
1686                 writeDescriptorSets.push_back(writeDescriptorSet);
1687             }
1688             else if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
1689             {
1690                 // Image also needs a sampler.
1691                 writeDescriptorSet.dstBinding++;
1692                 writeDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
1693                 writeDescriptorSets.push_back(writeDescriptorSet);
1694             }
1695 
1696             m_vkd.cmdPushDescriptorSetKHR(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_fragmentStatePipelineLayout,
1697                                           0, (uint32_t)writeDescriptorSets.size(), writeDescriptorSets.data());
1698             m_vkd.cmdDraw(*m_cmdBuffer, 6, 1, 6 * quadNdx, 0);
1699         }
1700 
1701         m_renderPass.end(m_vkd, *m_cmdBuffer);
1702         endCommandBuffer(m_vkd, *m_cmdBuffer);
1703     }
1704 }
1705 
~PushDescriptorImageGraphicsTestInstance(void)1706 PushDescriptorImageGraphicsTestInstance::~PushDescriptorImageGraphicsTestInstance(void)
1707 {
1708 }
1709 
iterate(void)1710 tcu::TestStatus PushDescriptorImageGraphicsTestInstance::iterate(void)
1711 {
1712     init();
1713 
1714     submitCommandsAndWait(m_vkd, *m_device, m_queue, m_cmdBuffer.get());
1715 
1716     return verifyImage();
1717 }
1718 
verifyImage(void)1719 tcu::TestStatus PushDescriptorImageGraphicsTestInstance::verifyImage(void)
1720 {
1721     const tcu::TextureFormat tcuColorFormat = mapVkFormat(m_colorFormat);
1722     const tcu::TextureFormat tcuDepthFormat = tcu::TextureFormat();
1723     const ColorVertexShader vertexShader;
1724     const ColorFragmentShader fragmentShader(tcuColorFormat, tcuDepthFormat);
1725     const rr::Program program(&vertexShader, &fragmentShader);
1726     ReferenceRenderer refRenderer(m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuDepthFormat, &program);
1727     bool compareOk = false;
1728 
1729     // Render reference image
1730     {
1731         vector<Vertex4RGBA> refQuadsOuter = createQuads(m_params.numCalls, 0.25f);
1732         vector<Vertex4RGBA> refQuadsInner = createQuads(m_params.numCalls, 0.25f * 0.8f);
1733         tcu::Vec4 outerColor[2];
1734         tcu::Vec4 innerColor[2];
1735         const bool hasBorder = m_params.descriptorType != VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
1736 
1737         if (hasBorder)
1738         {
1739             outerColor[0] = tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f);
1740             innerColor[0] = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
1741             if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
1742                 outerColor[1] = tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f);
1743             else
1744                 outerColor[1] = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
1745             if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER)
1746                 innerColor[1] = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
1747             else
1748                 innerColor[1] = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
1749         }
1750         else
1751         {
1752             outerColor[0] = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
1753             outerColor[1] = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
1754         }
1755 
1756         for (uint32_t quadIdx = 0; quadIdx < m_params.numCalls; quadIdx++)
1757             for (uint32_t vertexIdx = 0; vertexIdx < 6; vertexIdx++)
1758             {
1759                 const uint32_t idx              = quadIdx * 6 + vertexIdx;
1760                 refQuadsOuter[idx].color.xyzw() = outerColor[quadIdx];
1761                 refQuadsInner[idx].color.xyzw() = innerColor[quadIdx];
1762             }
1763 
1764         if (hasBorder)
1765             refQuadsOuter.insert(refQuadsOuter.end(), refQuadsInner.begin(), refQuadsInner.end());
1766 
1767         refRenderer.draw(rr::RenderState(refRenderer.getViewportState(),
1768                                          m_context.getDeviceProperties().limits.subPixelPrecisionBits),
1769                          rr::PRIMITIVETYPE_TRIANGLES, refQuadsOuter);
1770     }
1771 
1772     // Compare result with reference image
1773     {
1774         de::MovePtr<tcu::TextureLevel> result = readColorAttachment(
1775             m_vkd, *m_device, m_queue, m_queueFamilyIndex, m_allocator, *m_colorImage, m_colorFormat, m_renderSize);
1776 
1777         compareOk = tcu::intThresholdPositionDeviationCompare(
1778             m_context.getTestContext().getLog(), "IntImageCompare", "Image comparison", refRenderer.getAccess(),
1779             result->getAccess(), tcu::UVec4(2, 2, 2, 2), tcu::IVec3(1, 1, 0), true, tcu::COMPARE_LOG_RESULT);
1780     }
1781 
1782     if (compareOk)
1783         return tcu::TestStatus::pass("Result image matches reference");
1784     else
1785         return tcu::TestStatus::fail("Image mismatch");
1786 }
1787 
1788 class PushDescriptorImageGraphicsTest : public vkt::TestCase
1789 {
1790 public:
1791     PushDescriptorImageGraphicsTest(tcu::TestContext &testContext, const string &name, const TestParams &params);
1792     ~PushDescriptorImageGraphicsTest(void);
1793 
1794     void checkSupport(Context &context) const;
1795     void initPrograms(SourceCollections &sourceCollections) const;
1796     TestInstance *createInstance(Context &context) const;
1797 
1798 protected:
1799     const TestParams m_params;
1800 };
1801 
PushDescriptorImageGraphicsTest(tcu::TestContext & testContext,const string & name,const TestParams & params)1802 PushDescriptorImageGraphicsTest::PushDescriptorImageGraphicsTest(tcu::TestContext &testContext, const string &name,
1803                                                                  const TestParams &params)
1804     : vkt::TestCase(testContext, name)
1805     , m_params(params)
1806 {
1807 }
1808 
~PushDescriptorImageGraphicsTest(void)1809 PushDescriptorImageGraphicsTest::~PushDescriptorImageGraphicsTest(void)
1810 {
1811 }
1812 
createInstance(Context & context) const1813 TestInstance *PushDescriptorImageGraphicsTest::createInstance(Context &context) const
1814 {
1815     return new PushDescriptorImageGraphicsTestInstance(context, m_params);
1816 }
1817 
checkSupport(Context & context) const1818 void PushDescriptorImageGraphicsTest::checkSupport(Context &context) const
1819 {
1820     checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(),
1821                                           m_params.pipelineConstructionType);
1822 }
1823 
initPrograms(SourceCollections & sourceCollections) const1824 void PushDescriptorImageGraphicsTest::initPrograms(SourceCollections &sourceCollections) const
1825 {
1826     const string vertexSrc = "#version 450\n"
1827                              "layout(location = 0) in highp vec4 position;\n"
1828                              "layout(location = 1) in highp vec4 texcoordVtx;\n"
1829                              "layout(location = 0) out highp vec2 texcoordFrag;\n"
1830                              "\n"
1831                              "out gl_PerVertex { vec4 gl_Position; };\n"
1832                              "\n"
1833                              "void main()\n"
1834                              "{\n"
1835                              "    gl_Position = position;\n"
1836                              "    texcoordFrag = texcoordVtx.xy;\n"
1837                              "}\n";
1838 
1839     sourceCollections.glslSources.add("vert") << glu::VertexSource(vertexSrc);
1840 
1841     if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
1842     {
1843         const string fragmentSrc = "#version 450\n"
1844                                    "layout(location = 0) in highp vec2 texcoordFrag;\n"
1845                                    "layout(location = 0) out highp vec4 fragColor;\n"
1846                                    "layout(set = 0, binding = " +
1847                                    de::toString(m_params.binding) +
1848                                    ") uniform sampler2D combinedSampler;\n"
1849                                    "\n"
1850                                    "void main (void)\n"
1851                                    "{\n"
1852                                    "    fragColor = texture(combinedSampler, texcoordFrag);\n"
1853                                    "}\n";
1854 
1855         sourceCollections.glslSources.add("frag") << glu::FragmentSource(fragmentSrc);
1856     }
1857     else if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER)
1858     {
1859         const string fragmentSrc = "#version 450\n"
1860                                    "layout(location = 0) in highp vec2 texcoordFrag;\n"
1861                                    "layout(location = 0) out highp vec4 fragColor;\n"
1862                                    "layout(set = 0, binding = " +
1863                                    de::toString(m_params.binding) +
1864                                    ") uniform sampler texSampler;\n"
1865                                    "layout(set = 0, binding = " +
1866                                    de::toString(m_params.binding + 1) +
1867                                    ") uniform texture2D texImage;\n"
1868                                    "\n"
1869                                    "void main (void)\n"
1870                                    "{\n"
1871                                    "    fragColor = texture(sampler2D(texImage, texSampler), texcoordFrag);\n"
1872                                    "}\n";
1873 
1874         sourceCollections.glslSources.add("frag") << glu::FragmentSource(fragmentSrc);
1875     }
1876     else if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
1877     {
1878         const string fragmentSrc = "#version 450\n"
1879                                    "layout(location = 0) in highp vec2 texcoordFrag;\n"
1880                                    "layout(location = 0) out highp vec4 fragColor;\n"
1881                                    "layout(set = 0, binding = " +
1882                                    de::toString(m_params.binding + 1) +
1883                                    ") uniform sampler texSampler;\n"
1884                                    "layout(set = 0, binding = " +
1885                                    de::toString(m_params.binding) +
1886                                    ") uniform texture2D texImage;\n"
1887                                    "\n"
1888                                    "void main (void)\n"
1889                                    "{\n"
1890                                    "    fragColor = texture(sampler2D(texImage, texSampler), texcoordFrag);\n"
1891                                    "}\n";
1892 
1893         sourceCollections.glslSources.add("frag") << glu::FragmentSource(fragmentSrc);
1894     }
1895     else if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
1896     {
1897         const string fragmentSrc = "#version 450\n"
1898                                    "layout(location = 0) in highp vec2 texcoordFrag;\n"
1899                                    "layout(location = 0) out highp vec4 fragColor;\n"
1900                                    "layout(set = 0, binding = " +
1901                                    de::toString(m_params.binding) +
1902                                    ", rgba8) uniform readonly image2D storageImage;\n"
1903                                    "\n"
1904                                    "void main (void)\n"
1905                                    "{\n"
1906                                    "    fragColor = imageLoad(storageImage, ivec2(0));\n"
1907                                    "}\n";
1908 
1909         sourceCollections.glslSources.add("frag") << glu::FragmentSource(fragmentSrc);
1910     }
1911     else
1912     {
1913         DE_FATAL("Unexpected descriptor type");
1914     }
1915 }
1916 
1917 class PushDescriptorImageComputeTestInstance : public vkt::TestInstance
1918 {
1919 public:
1920     PushDescriptorImageComputeTestInstance(Context &context, const TestParams &params);
1921     virtual ~PushDescriptorImageComputeTestInstance(void);
1922     void init(void);
1923     virtual tcu::TestStatus iterate(void);
1924     tcu::TestStatus verifyOutput(void);
1925 
1926 private:
1927     const TestParams m_params;
1928     const PlatformInterface &m_vkp;
1929     const Extensions m_instanceExtensions;
1930     const CustomInstance m_instance;
1931     const InstanceDriver &m_vki;
1932     const VkPhysicalDevice m_physicalDevice;
1933     const uint32_t m_queueFamilyIndex;
1934     const Extensions m_deviceExtensions;
1935     std::vector<std::string> m_deviceEnabledExtensions;
1936     const Unique<VkDevice> m_device;
1937     const DeviceDriver m_vkd;
1938     const VkQueue m_queue;
1939     const VkDeviceSize m_itemSize;
1940     const VkDeviceSize m_blockSize;
1941     SimpleAllocator m_allocator;
1942     const tcu::UVec2 m_textureSize;
1943     const VkFormat m_colorFormat;
1944     Move<VkShaderModule> m_computeShaderModule;
1945     vector<VkImageSp> m_textureImages;
1946     vector<AllocationSp> m_textureImageAllocs;
1947     vector<VkImageViewSp> m_textureViews;
1948     Move<VkSampler> m_whiteBorderSampler;
1949     Move<VkSampler> m_blackBorderSampler;
1950     Move<VkBuffer> m_outputBuffer;
1951     de::MovePtr<Allocation> m_outputBufferAlloc;
1952     Move<VkDescriptorSetLayout> m_descriptorSetLayout;
1953     Move<VkPipelineLayout> m_pipelineLayout;
1954     Move<VkPipeline> m_computePipeline;
1955     Move<VkCommandPool> m_cmdPool;
1956     Move<VkCommandBuffer> m_cmdBuffer;
1957     uint32_t m_outputBufferBinding;
1958 };
1959 
PushDescriptorImageComputeTestInstance(Context & context,const TestParams & params)1960 PushDescriptorImageComputeTestInstance::PushDescriptorImageComputeTestInstance(Context &context,
1961                                                                                const TestParams &params)
1962     : vkt::TestInstance(context)
1963     , m_params(params)
1964     , m_vkp(context.getPlatformInterface())
1965     , m_instanceExtensions(enumerateInstanceExtensionProperties(m_vkp, DE_NULL))
1966     , m_instance(createInstanceWithGetPhysicalDeviceProperties2(context, m_instanceExtensions))
1967     , m_vki(m_instance.getDriver())
1968     , m_physicalDevice(chooseDevice(m_vki, m_instance, context.getTestContext().getCommandLine()))
1969     , m_queueFamilyIndex(
1970           findQueueFamilyIndexWithCaps(m_vki, m_physicalDevice, VK_QUEUE_COMPUTE_BIT | VK_QUEUE_GRAPHICS_BIT))
1971     , m_deviceExtensions(enumerateDeviceExtensionProperties(m_vki, m_physicalDevice, DE_NULL))
1972     , m_device(createDeviceWithPushDescriptor(context, m_vkp, m_instance, m_vki, m_physicalDevice, m_deviceExtensions,
1973                                               m_queueFamilyIndex, params, m_deviceEnabledExtensions))
1974     , m_vkd(m_vkp, m_instance, *m_device, context.getUsedApiVersion(), context.getTestContext().getCommandLine())
1975     , m_queue(getDeviceQueue(m_vkd, *m_device, m_queueFamilyIndex, 0u))
1976     , m_itemSize(calcItemSize(m_vki, m_physicalDevice, 2u))
1977     , m_blockSize(kSizeofVec4 * 2u)
1978     , m_allocator(m_vkd, *m_device, getPhysicalDeviceMemoryProperties(m_vki, m_physicalDevice))
1979     , m_textureSize(32, 32)
1980     , m_colorFormat(VK_FORMAT_R8G8B8A8_UNORM)
1981     , m_outputBufferBinding(0)
1982 {
1983 }
1984 
init(void)1985 void PushDescriptorImageComputeTestInstance::init(void)
1986 {
1987     const VkComponentMapping componentMappingRGBA = {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G,
1988                                                      VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A};
1989 
1990     // Create texture images
1991     for (uint32_t texIdx = 0; texIdx < 2; texIdx++)
1992     {
1993         VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_TRANSFER_DST_BIT;
1994         if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER ||
1995             m_params.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||
1996             m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
1997             usageFlags |= VK_IMAGE_USAGE_SAMPLED_BIT;
1998         if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
1999             usageFlags |= VK_IMAGE_USAGE_STORAGE_BIT;
2000 
2001         const VkImageCreateInfo textureImageParams = {
2002             VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,        // VkStructureType sType;
2003             DE_NULL,                                    // const void* pNext;
2004             0u,                                         // VkImageCreateFlags flags;
2005             VK_IMAGE_TYPE_2D,                           // VkImageType imageType;
2006             m_colorFormat,                              // VkFormat format;
2007             {m_textureSize.x(), m_textureSize.y(), 1u}, // VkExtent3D extent;
2008             1u,                                         // uint32_t mipLevels;
2009             1u,                                         // uint32_t arrayLayers;
2010             VK_SAMPLE_COUNT_1_BIT,                      // VkSampleCountFlagBits samples;
2011             VK_IMAGE_TILING_OPTIMAL,                    // VkImageTiling tiling;
2012             usageFlags,                                 // VkImageUsageFlags usage;
2013             VK_SHARING_MODE_EXCLUSIVE,                  // VkSharingMode sharingMode;
2014             1u,                                         // uint32_t queueFamilyIndexCount;
2015             &m_queueFamilyIndex,                        // const uint32_t* pQueueFamilyIndices;
2016             VK_IMAGE_LAYOUT_UNDEFINED                   // VkImageLayout initialLayout;
2017         };
2018 
2019         m_textureImages.push_back(VkImageSp(new Unique<VkImage>(createImage(m_vkd, *m_device, &textureImageParams))));
2020 
2021         // Allocate and bind texture image memory
2022         m_textureImageAllocs.push_back(
2023             AllocationSp(m_allocator
2024                              .allocate(getImageMemoryRequirements(m_vkd, *m_device, **m_textureImages.back()),
2025                                        MemoryRequirement::Any)
2026                              .release()));
2027         VK_CHECK(m_vkd.bindImageMemory(*m_device, **m_textureImages.back(), m_textureImageAllocs.back()->getMemory(),
2028                                        m_textureImageAllocs.back()->getOffset()));
2029     }
2030 
2031     // Create texture image views
2032     for (uint32_t texIdx = 0; texIdx < 2; texIdx++)
2033     {
2034         const VkImageViewCreateInfo textureViewParams = {
2035             VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,   // VkStructureType sType;
2036             DE_NULL,                                    // const void* pNext;
2037             0u,                                         // VkImageViewCreateFlags flags;
2038             **m_textureImages[texIdx],                  // VkImage image;
2039             VK_IMAGE_VIEW_TYPE_2D,                      // VkImageViewType viewType;
2040             m_colorFormat,                              // VkFormat format;
2041             componentMappingRGBA,                       // VkChannelMapping channels;
2042             {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u} // VkImageSubresourceRange subresourceRange;
2043         };
2044 
2045         m_textureViews.push_back(
2046             VkImageViewSp(new Unique<VkImageView>(createImageView(m_vkd, *m_device, &textureViewParams))));
2047     }
2048 
2049     VkClearValue clearValues[2];
2050     clearValues[0].color.float32[0] = 0.0f;
2051     clearValues[0].color.float32[1] = 1.0f;
2052     clearValues[0].color.float32[2] = 0.0f;
2053     clearValues[0].color.float32[3] = 1.0f;
2054     clearValues[1].color.float32[0] = 1.0f;
2055     clearValues[1].color.float32[1] = 0.0f;
2056     clearValues[1].color.float32[2] = 0.0f;
2057     clearValues[1].color.float32[3] = 1.0f;
2058 
2059     const VkImageLayout textureImageLayout = (m_params.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) ?
2060                                                  VK_IMAGE_LAYOUT_GENERAL :
2061                                                  VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
2062 
2063     // Clear textures
2064     for (uint32_t texIdx = 0; texIdx < 2; texIdx++)
2065     {
2066         const VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
2067         Move<VkCommandPool> cmdPool;
2068         Move<VkCommandBuffer> cmdBuffer;
2069 
2070         cmdPool   = createCommandPool(m_vkd, *m_device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, m_queueFamilyIndex);
2071         cmdBuffer = allocateCommandBuffer(m_vkd, *m_device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2072 
2073         const VkImageMemoryBarrier preImageBarrier = {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
2074                                                       DE_NULL,                                // const void* pNext;
2075                                                       0u,                           // VkAccessFlags srcAccessMask;
2076                                                       VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask;
2077                                                       VK_IMAGE_LAYOUT_UNDEFINED,    // VkImageLayout oldLayout;
2078                                                       VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout;
2079                                                       VK_QUEUE_FAMILY_IGNORED,   // uint32_t srcQueueFamilyIndex;
2080                                                       VK_QUEUE_FAMILY_IGNORED,   // uint32_t dstQueueFamilyIndex;
2081                                                       **m_textureImages[texIdx], // VkImage image;
2082                                                       {
2083                                                           // VkImageSubresourceRange subresourceRange;
2084                                                           aspectMask, // VkImageAspect aspect;
2085                                                           0u,         // uint32_t baseMipLevel;
2086                                                           1u,         // uint32_t mipLevels;
2087                                                           0u,         // uint32_t baseArraySlice;
2088                                                           1u          // uint32_t arraySize;
2089                                                       }};
2090 
2091         const VkImageMemoryBarrier postImageBarrier = {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
2092                                                        DE_NULL,                                // const void* pNext;
2093                                                        VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
2094                                                        VK_ACCESS_SHADER_READ_BIT,    // VkAccessFlags dstAccessMask;
2095                                                        VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout;
2096                                                        textureImageLayout,                   // VkImageLayout newLayout;
2097                                                        VK_QUEUE_FAMILY_IGNORED,   // uint32_t srcQueueFamilyIndex;
2098                                                        VK_QUEUE_FAMILY_IGNORED,   // uint32_t dstQueueFamilyIndex;
2099                                                        **m_textureImages[texIdx], // VkImage image;
2100                                                        {
2101                                                            // VkImageSubresourceRange subresourceRange;
2102                                                            aspectMask, // VkImageAspect aspect;
2103                                                            0u,         // uint32_t baseMipLevel;
2104                                                            1u,         // uint32_t mipLevels;
2105                                                            0u,         // uint32_t baseArraySlice;
2106                                                            1u          // uint32_t arraySize;
2107                                                        }};
2108 
2109         const VkImageSubresourceRange clearRange = {
2110             aspectMask, // VkImageAspectFlags aspectMask;
2111             0u,         // uint32_t baseMipLevel;
2112             1u,         // uint32_t levelCount;
2113             0u,         // uint32_t baseArrayLayer;
2114             1u          // uint32_t layerCount;
2115         };
2116 
2117         beginCommandBuffer(m_vkd, *cmdBuffer);
2118         m_vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
2119                                  (VkDependencyFlags)0, 0, (const VkMemoryBarrier *)DE_NULL, 0,
2120                                  (const VkBufferMemoryBarrier *)DE_NULL, 1, &preImageBarrier);
2121         m_vkd.cmdClearColorImage(*cmdBuffer, **m_textureImages[texIdx], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
2122                                  &clearValues[texIdx].color, 1, &clearRange);
2123         m_vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
2124                                  (VkDependencyFlags)0, 0, (const VkMemoryBarrier *)DE_NULL, 0,
2125                                  (const VkBufferMemoryBarrier *)DE_NULL, 1, &postImageBarrier);
2126         endCommandBuffer(m_vkd, *cmdBuffer);
2127 
2128         submitCommandsAndWait(m_vkd, *m_device, m_queue, cmdBuffer.get());
2129     }
2130 
2131     // Create samplers: one with white and one with black border color to have a visible effect on switching the sampler
2132     {
2133         VkSamplerCreateInfo samplerParams = {
2134             VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,   // VkStructureType sType;
2135             DE_NULL,                                 // const void* pNext;
2136             0u,                                      // VkSamplerCreateFlags flags;
2137             VK_FILTER_NEAREST,                       // VkFilter magFilter;
2138             VK_FILTER_NEAREST,                       // VkFilter minFilter;
2139             VK_SAMPLER_MIPMAP_MODE_NEAREST,          // VkSamplerMipmapMode mipmapMode;
2140             VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, // VkSamplerAddressMode addressModeU;
2141             VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, // VkSamplerAddressMode addressModeV;
2142             VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, // VkSamplerAddressMode addressModeW;
2143             0.0f,                                    // float mipLodBias;
2144             VK_FALSE,                                // VkBool32 anisotropyEnable;
2145             0.0f,                                    // float maxAnisotropy;
2146             VK_FALSE,                                // VkBool32 compareEnable;
2147             VK_COMPARE_OP_NEVER,                     // VkCompareOp compareOp;
2148             0.0f,                                    // float minLod;
2149             0.0f,                                    // float maxLod;
2150             VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE,      // VkBorderColor borderColor;
2151             VK_FALSE                                 // VkBool32 unnormalizedCoordinates;
2152         };
2153 
2154         m_whiteBorderSampler      = createSampler(m_vkd, *m_device, &samplerParams);
2155         samplerParams.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK;
2156         m_blackBorderSampler      = createSampler(m_vkd, *m_device, &samplerParams);
2157     }
2158 
2159     // Create pipeline layout
2160     {
2161         // Create descriptor set layout
2162         vector<VkDescriptorSetLayoutBinding> layoutBindings;
2163 
2164         switch (m_params.descriptorType)
2165         {
2166         case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
2167         {
2168             const VkDescriptorSetLayoutBinding descriptorSetLayoutBinding = {
2169                 m_params.binding,                          // uint32_t binding;
2170                 VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, // VkDescriptorType descriptorType;
2171                 1u,                                        // uint32_t descriptorCount;
2172                 VK_SHADER_STAGE_COMPUTE_BIT,               // VkShaderStageFlags stageFlags;
2173                 DE_NULL                                    // const VkSampler* pImmutableSamplers;
2174             };
2175             layoutBindings.push_back(descriptorSetLayoutBinding);
2176             m_outputBufferBinding = m_params.binding + 1;
2177         }
2178         break;
2179 
2180         case VK_DESCRIPTOR_TYPE_SAMPLER:
2181         {
2182             const VkDescriptorSetLayoutBinding descriptorSetLayoutBindingSampler = {
2183                 m_params.binding,            // uint32_t binding;
2184                 VK_DESCRIPTOR_TYPE_SAMPLER,  // VkDescriptorType descriptorType;
2185                 1u,                          // uint32_t descriptorCount;
2186                 VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlags stageFlags;
2187                 DE_NULL                      // const VkSampler* pImmutableSamplers;
2188             };
2189             const VkDescriptorSetLayoutBinding descriptorSetLayoutBindingTex = {
2190                 m_params.binding + 1,             // uint32_t binding;
2191                 VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, // VkDescriptorType descriptorType;
2192                 1u,                               // uint32_t descriptorCount;
2193                 VK_SHADER_STAGE_COMPUTE_BIT,      // VkShaderStageFlags stageFlags;
2194                 DE_NULL                           // const VkSampler* pImmutableSamplers;
2195             };
2196             layoutBindings.push_back(descriptorSetLayoutBindingSampler);
2197             layoutBindings.push_back(descriptorSetLayoutBindingTex);
2198             m_outputBufferBinding = m_params.binding + 2;
2199         }
2200         break;
2201 
2202         case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
2203         {
2204             const VkDescriptorSetLayoutBinding descriptorSetLayoutBindingSampler = {
2205                 m_params.binding + 1,        // uint32_t binding;
2206                 VK_DESCRIPTOR_TYPE_SAMPLER,  // VkDescriptorType descriptorType;
2207                 1u,                          // uint32_t descriptorCount;
2208                 VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlags stageFlags;
2209                 DE_NULL                      // const VkSampler* pImmutableSamplers;
2210             };
2211             const VkDescriptorSetLayoutBinding descriptorSetLayoutBindingTex = {
2212                 m_params.binding,                 // uint32_t binding;
2213                 VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, // VkDescriptorType descriptorType;
2214                 1u,                               // uint32_t descriptorCount;
2215                 VK_SHADER_STAGE_COMPUTE_BIT,      // VkShaderStageFlags stageFlags;
2216                 DE_NULL                           // const VkSampler* pImmutableSamplers;
2217             };
2218             layoutBindings.push_back(descriptorSetLayoutBindingSampler);
2219             layoutBindings.push_back(descriptorSetLayoutBindingTex);
2220             m_outputBufferBinding = m_params.binding + 2;
2221         }
2222         break;
2223 
2224         case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
2225         {
2226             const VkDescriptorSetLayoutBinding descriptorSetLayoutBinding = {
2227                 m_params.binding,                 // uint32_t binding;
2228                 VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, // VkDescriptorType descriptorType;
2229                 1u,                               // uint32_t descriptorCount;
2230                 VK_SHADER_STAGE_COMPUTE_BIT,      // VkShaderStageFlags stageFlags;
2231                 DE_NULL                           // const VkSampler* pImmutableSamplers;
2232             };
2233             layoutBindings.push_back(descriptorSetLayoutBinding);
2234             m_outputBufferBinding = m_params.binding + 1;
2235         }
2236         break;
2237 
2238         default:
2239             DE_FATAL("unexpected descriptor type");
2240             break;
2241         }
2242 
2243         const VkDescriptorSetLayoutBinding descriptorSetLayoutBindingOutputBuffer = {
2244             m_outputBufferBinding,             // uint32_t binding;
2245             VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, // VkDescriptorType descriptorType;
2246             1u,                                // uint32_t descriptorCount;
2247             VK_SHADER_STAGE_COMPUTE_BIT,       // VkShaderStageFlags stageFlags;
2248             DE_NULL                            // const VkSampler* pImmutableSamplers;
2249         };
2250 
2251         layoutBindings.push_back(descriptorSetLayoutBindingOutputBuffer);
2252 
2253         const VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {
2254             VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,     // VkStructureType sType;
2255             DE_NULL,                                                 // const void* pNext;
2256             VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR, // VkDescriptorSetLayoutCreateFlags flags;
2257             (uint32_t)layoutBindings.size(),                         // uint32_t bindingCount;
2258             layoutBindings.data()                                    // const VkDescriptorSetLayoutBinding* pBindings;
2259         };
2260 
2261         m_descriptorSetLayout = createDescriptorSetLayout(m_vkd, *m_device, &descriptorSetLayoutCreateInfo, DE_NULL);
2262 
2263         // Create pipeline layout
2264         const VkPipelineLayoutCreateInfo pipelineLayoutParams = {
2265             VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
2266             DE_NULL,                                       // const void* pNext;
2267             0u,                                            // VkPipelineLayoutCreateFlags flags;
2268             1u,                                            // uint32_t descriptorSetCount;
2269             &(*m_descriptorSetLayout),                     // const VkDescriptorSetLayout* pSetLayouts;
2270             0u,                                            // uint32_t pushConstantRangeCount;
2271             DE_NULL                                        // const VkPushDescriptorRange* pPushDescriptorRanges;
2272         };
2273 
2274         m_pipelineLayout = createPipelineLayout(m_vkd, *m_device, &pipelineLayoutParams);
2275     }
2276 
2277     // Create output buffer
2278     {
2279         DE_ASSERT(m_params.numCalls <= 2u);
2280 
2281         const VkBufferCreateInfo bufferCreateInfo = {
2282             VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
2283             DE_NULL,                              // const void* pNext;
2284             0u,                                   // VkBufferCreateFlags    flags
2285             m_itemSize * 2u,                      // VkDeviceSize size;
2286             VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,   // VkBufferUsageFlags usage;
2287             VK_SHARING_MODE_EXCLUSIVE,            // VkSharingMode sharingMode;
2288             1u,                                   // uint32_t queueFamilyCount;
2289             &m_queueFamilyIndex                   // const uint32_t* pQueueFamilyIndices;
2290         };
2291 
2292         m_outputBuffer      = createBuffer(m_vkd, *m_device, &bufferCreateInfo);
2293         m_outputBufferAlloc = m_allocator.allocate(getBufferMemoryRequirements(m_vkd, *m_device, *m_outputBuffer),
2294                                                    MemoryRequirement::HostVisible);
2295         VK_CHECK(m_vkd.bindBufferMemory(*m_device, *m_outputBuffer, m_outputBufferAlloc->getMemory(),
2296                                         m_outputBufferAlloc->getOffset()));
2297     }
2298 
2299     // Create shader
2300     {
2301         m_computeShaderModule =
2302             createShaderModule(m_vkd, *m_device, m_context.getBinaryCollection().get("compute"), 0u);
2303     }
2304 
2305     // Create pipeline
2306     {
2307         const VkPipelineShaderStageCreateInfo stageCreateInfo = {
2308             VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
2309             DE_NULL,                                             // const void* pNext;
2310             0u,                                                  // VkPipelineShaderStageCreateFlags flags;
2311             VK_SHADER_STAGE_COMPUTE_BIT,                         // VkShaderStageFlagBits stage;
2312             *m_computeShaderModule,                              // VkShaderModule module;
2313             "main",                                              // const char* pName;
2314             DE_NULL                                              // const VkSpecializationInfo* pSpecializationInfo;
2315         };
2316 
2317         const VkComputePipelineCreateInfo createInfo = {
2318             VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // VkStructureType sType;
2319             DE_NULL,                                        // const void* pNext;
2320             0u,                                             // VkPipelineCreateFlags flags;
2321             stageCreateInfo,                                // VkPipelineShaderStageCreateInfo stage;
2322             *m_pipelineLayout,                              // VkPipelineLayout layout;
2323             (VkPipeline)0,                                  // VkPipeline basePipelineHandle;
2324             0u,                                             // int32_t basePipelineIndex;
2325         };
2326 
2327         m_computePipeline = createComputePipeline(m_vkd, *m_device, (vk::VkPipelineCache)0u, &createInfo);
2328     }
2329 
2330     // Create command pool
2331     m_cmdPool = createCommandPool(m_vkd, *m_device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, m_queueFamilyIndex);
2332 
2333     // Create command buffer
2334     {
2335         m_cmdBuffer = allocateCommandBuffer(m_vkd, *m_device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2336         beginCommandBuffer(m_vkd, *m_cmdBuffer, 0u);
2337         m_vkd.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_computePipeline);
2338 
2339         // Dispatch: Each dispatch switches the input image.
2340         // Output buffer is exposed as a 2 x vec4 sized window.
2341         for (uint32_t dispatchNdx = 0; dispatchNdx < m_params.numCalls; dispatchNdx++)
2342         {
2343             vector<VkSampler> samplers;
2344             vector<VkImageView> imageViews;
2345 
2346             samplers.push_back(*m_whiteBorderSampler);
2347             if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER ||
2348                 m_params.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
2349             {
2350                 // Vary sampler between draws
2351                 samplers.push_back(*m_blackBorderSampler);
2352             }
2353             else
2354             {
2355                 // Usa a single sampler
2356                 samplers.push_back(*m_whiteBorderSampler);
2357             }
2358 
2359             imageViews.push_back(**m_textureViews[0]);
2360             if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ||
2361                 m_params.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||
2362                 m_params.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
2363             {
2364                 // Vary image view between draws
2365                 imageViews.push_back(**m_textureViews[1]);
2366             }
2367             else
2368             {
2369                 // Usa a single image view
2370                 imageViews.push_back(**m_textureViews[0]);
2371             }
2372 
2373             const VkDescriptorImageInfo descriptorImageInfo = {
2374                 samplers[dispatchNdx],   // VkSampler sampler;
2375                 imageViews[dispatchNdx], // VkImageView imageView;
2376                 textureImageLayout       // VkImageLayout imageLayout;
2377             };
2378 
2379             VkWriteDescriptorSet writeDescriptorSet = {
2380                 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // VkStructureType sType;
2381                 DE_NULL,                                // const void* pNext;
2382                 0u,                                     // VkDescriptorSet dstSet;
2383                 m_params.binding,                       // uint32_t dstBinding;
2384                 0u,                                     // uint32_t dstArrayElement;
2385                 1u,                                     // uint32_t descriptorCount;
2386                 m_params.descriptorType,                // VkDescriptorType descriptorType;
2387                 &descriptorImageInfo,                   // const VkDescriptorImageInfo* pImageInfo;
2388                 DE_NULL,                                // const VkDescriptorBufferInfo* pBufferInfo;
2389                 DE_NULL                                 // const VkBufferView* pTexelBufferView;
2390             };
2391 
2392             vector<VkWriteDescriptorSet> writeDescriptorSets;
2393             writeDescriptorSets.push_back(writeDescriptorSet);
2394 
2395             if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER)
2396             {
2397                 // Sampler also needs an image.
2398                 writeDescriptorSet.dstBinding++;
2399                 writeDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
2400                 writeDescriptorSets.push_back(writeDescriptorSet);
2401             }
2402             else if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
2403             {
2404                 // Image also needs a sampler.
2405                 writeDescriptorSet.dstBinding++;
2406                 writeDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
2407                 writeDescriptorSets.push_back(writeDescriptorSet);
2408             }
2409 
2410             const VkDescriptorBufferInfo descriptorBufferInfoOutput = {
2411                 *m_outputBuffer,          // VkBuffer buffer;
2412                 m_itemSize * dispatchNdx, // VkDeviceSize offset;
2413                 m_blockSize,              // VkDeviceSize range;
2414             };
2415 
2416             // Write output buffer descriptor set
2417             const VkWriteDescriptorSet writeDescriptorSetOutput = {
2418                 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // VkStructureType sType;
2419                 DE_NULL,                                // const void* pNext;
2420                 0u,                                     // VkDescriptorSet dstSet;
2421                 m_outputBufferBinding,                  // uint32_t dstBinding;
2422                 0u,                                     // uint32_t dstArrayElement;
2423                 1u,                                     // uint32_t descriptorCount;
2424                 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,      // VkDescriptorType descriptorType;
2425                 DE_NULL,                                // const VkDescriptorImageInfo* pImageInfo;
2426                 &descriptorBufferInfoOutput,            // const VkDescriptorBufferInfo* pBufferInfo;
2427                 DE_NULL                                 // const VkBufferView* pTexelBufferView;
2428             };
2429 
2430             writeDescriptorSets.push_back(writeDescriptorSetOutput);
2431 
2432             m_vkd.cmdPushDescriptorSetKHR(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipelineLayout, 0,
2433                                           (uint32_t)writeDescriptorSets.size(), writeDescriptorSets.data());
2434             m_vkd.cmdDispatch(*m_cmdBuffer, 1, 1, 1);
2435         }
2436 
2437         endCommandBuffer(m_vkd, *m_cmdBuffer);
2438     }
2439 }
2440 
~PushDescriptorImageComputeTestInstance(void)2441 PushDescriptorImageComputeTestInstance::~PushDescriptorImageComputeTestInstance(void)
2442 {
2443 }
2444 
iterate(void)2445 tcu::TestStatus PushDescriptorImageComputeTestInstance::iterate(void)
2446 {
2447     init();
2448 
2449     submitCommandsAndWait(m_vkd, *m_device, m_queue, m_cmdBuffer.get());
2450 
2451     return verifyOutput();
2452 }
2453 
verifyOutput(void)2454 tcu::TestStatus PushDescriptorImageComputeTestInstance::verifyOutput(void)
2455 {
2456     const auto floatsPerDispatch = 8u; // 8 floats (2 vec4s) per dispatch.
2457     std::vector<float> ref(floatsPerDispatch * 2u);
2458 
2459     invalidateAlloc(m_vkd, *m_device, *m_outputBufferAlloc);
2460 
2461     switch (m_params.descriptorType)
2462     {
2463     case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
2464         // Dispatch 1: inner & outer = green
2465         ref[0] = ref[4] = 0.0f;
2466         ref[1] = ref[5] = 1.0f;
2467         ref[2] = ref[6] = 0.0f;
2468         ref[3] = ref[7] = 1.0f;
2469 
2470         // Dispatch 2: inner & outer = red
2471         ref[8] = ref[12] = 1.0f;
2472         ref[9] = ref[13] = 0.0f;
2473         ref[10] = ref[14] = 0.0f;
2474         ref[11] = ref[15] = 1.0f;
2475         break;
2476 
2477     case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
2478         // Dispatch 1: inner = green, outer = white
2479         ref[0] = 0.0f;
2480         ref[1] = 1.0f;
2481         ref[2] = 0.0f;
2482         ref[3] = 1.0f;
2483 
2484         ref[4] = 1.0f;
2485         ref[5] = 1.0f;
2486         ref[6] = 1.0f;
2487         ref[7] = 1.0f;
2488 
2489         // Dispatch 2: inner = red, outer = black
2490         ref[8]  = 1.0f;
2491         ref[9]  = 0.0f;
2492         ref[10] = 0.0f;
2493         ref[11] = 1.0f;
2494 
2495         ref[12] = 0.0f;
2496         ref[13] = 0.0f;
2497         ref[14] = 0.0f;
2498         ref[15] = 1.0f;
2499         break;
2500 
2501     case VK_DESCRIPTOR_TYPE_SAMPLER:
2502         // Dispatch 1: inner = green, outer = white
2503         ref[0] = 0.0f;
2504         ref[1] = 1.0f;
2505         ref[2] = 0.0f;
2506         ref[3] = 1.0f;
2507 
2508         ref[4] = 1.0f;
2509         ref[5] = 1.0f;
2510         ref[6] = 1.0f;
2511         ref[7] = 1.0f;
2512 
2513         // Dispatch 2: inner = green, outer = black
2514         ref[8]  = 0.0f;
2515         ref[9]  = 1.0f;
2516         ref[10] = 0.0f;
2517         ref[11] = 1.0f;
2518 
2519         ref[12] = 0.0f;
2520         ref[13] = 0.0f;
2521         ref[14] = 0.0f;
2522         ref[15] = 1.0f;
2523         break;
2524 
2525     case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
2526         // Dispatch 1: inner = green, outer = white
2527         ref[0] = 0.0f;
2528         ref[1] = 1.0f;
2529         ref[2] = 0.0f;
2530         ref[3] = 1.0f;
2531 
2532         ref[4] = 1.0f;
2533         ref[5] = 1.0f;
2534         ref[6] = 1.0f;
2535         ref[7] = 1.0f;
2536 
2537         // Dispatch 2: inner = red, outer = white
2538         ref[8]  = 1.0f;
2539         ref[9]  = 0.0f;
2540         ref[10] = 0.0f;
2541         ref[11] = 1.0f;
2542 
2543         ref[12] = 1.0f;
2544         ref[13] = 1.0f;
2545         ref[14] = 1.0f;
2546         ref[15] = 1.0f;
2547         break;
2548 
2549     default:
2550         DE_FATAL("unexpected descriptor type");
2551         break;
2552     }
2553 
2554     // Verify result
2555     const auto bufferDataPtr = reinterpret_cast<const char *>(m_outputBufferAlloc->getHostPtr());
2556     const auto blockSize     = static_cast<size_t>(m_blockSize);
2557 
2558     for (uint32_t dispatchNdx = 0u; dispatchNdx < m_params.numCalls; ++dispatchNdx)
2559     {
2560         const auto refIdx = floatsPerDispatch * dispatchNdx;
2561         const auto bufferOffset =
2562             m_itemSize * dispatchNdx; // Each dispatch uses m_itemSize bytes in the buffer to meet alignment reqs.
2563 
2564         if (deMemCmp(&ref[refIdx], bufferDataPtr + bufferOffset, blockSize) != 0)
2565         {
2566             std::vector<float> buffferValues(floatsPerDispatch);
2567             std::vector<float> refValues(floatsPerDispatch);
2568 
2569             deMemcpy(refValues.data(), &ref[refIdx], blockSize);
2570             deMemcpy(buffferValues.data(), bufferDataPtr + bufferOffset, blockSize);
2571 
2572             std::ostringstream msg;
2573             msg << "Output mismatch at dispatch " << dispatchNdx << ": Reference ";
2574             for (uint32_t i = 0; i < floatsPerDispatch; ++i)
2575                 msg << ((i == 0) ? "[" : ", ") << refValues[i];
2576             msg << "]; Buffer ";
2577             for (uint32_t i = 0; i < floatsPerDispatch; ++i)
2578                 msg << ((i == 0) ? "[" : ", ") << buffferValues[i];
2579             msg << "]";
2580 
2581             m_context.getTestContext().getLog() << tcu::TestLog::Message << msg.str() << tcu::TestLog::EndMessage;
2582             return tcu::TestStatus::fail("Output mismatch");
2583         }
2584     }
2585 
2586     return tcu::TestStatus::pass("Output matches expected values");
2587 }
2588 
2589 class PushDescriptorImageComputeTest : public vkt::TestCase
2590 {
2591 public:
2592     PushDescriptorImageComputeTest(tcu::TestContext &testContext, const string &name, const TestParams &params);
2593     ~PushDescriptorImageComputeTest(void);
2594     void initPrograms(SourceCollections &sourceCollections) const;
2595     TestInstance *createInstance(Context &context) const;
2596 
2597 protected:
2598     const TestParams m_params;
2599 };
2600 
PushDescriptorImageComputeTest(tcu::TestContext & testContext,const string & name,const TestParams & params)2601 PushDescriptorImageComputeTest::PushDescriptorImageComputeTest(tcu::TestContext &testContext, const string &name,
2602                                                                const TestParams &params)
2603     : vkt::TestCase(testContext, name)
2604     , m_params(params)
2605 {
2606 }
2607 
~PushDescriptorImageComputeTest(void)2608 PushDescriptorImageComputeTest::~PushDescriptorImageComputeTest(void)
2609 {
2610 }
2611 
createInstance(Context & context) const2612 TestInstance *PushDescriptorImageComputeTest::createInstance(Context &context) const
2613 {
2614     return new PushDescriptorImageComputeTestInstance(context, m_params);
2615 }
2616 
initPrograms(SourceCollections & sourceCollections) const2617 void PushDescriptorImageComputeTest::initPrograms(SourceCollections &sourceCollections) const
2618 {
2619     if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
2620     {
2621         const string computeSrc = "#version 450\n"
2622                                   "layout(set = 0, binding = " +
2623                                   de::toString(m_params.binding) +
2624                                   ") uniform sampler2D combinedSampler;\n"
2625                                   "layout(set = 0, binding = " +
2626                                   de::toString(m_params.binding + 1) +
2627                                   ") writeonly buffer Output\n"
2628                                   "{\n"
2629                                   "    vec4 innerColor;\n"
2630                                   "    vec4 outerColor;\n"
2631                                   "} outData;\n"
2632                                   "\n"
2633                                   "void main()\n"
2634                                   "{\n"
2635                                   "    outData.innerColor = texture(combinedSampler, vec2(0.5));\n"
2636                                   "    outData.outerColor = texture(combinedSampler, vec2(-0.1));\n"
2637                                   "}\n";
2638 
2639         sourceCollections.glslSources.add("compute") << glu::ComputeSource(computeSrc);
2640     }
2641     else if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER)
2642     {
2643         const string computeSrc = "#version 450\n"
2644                                   "layout(set = 0, binding = " +
2645                                   de::toString(m_params.binding) +
2646                                   ") uniform sampler texSampler;\n"
2647                                   "layout(set = 0, binding = " +
2648                                   de::toString(m_params.binding + 1) +
2649                                   ") uniform texture2D texImage;\n"
2650                                   "layout(set = 0, binding = " +
2651                                   de::toString(m_params.binding + 2) +
2652                                   ") writeonly buffer Output\n"
2653                                   "{\n"
2654                                   "    vec4 innerColor;\n"
2655                                   "    vec4 outerColor;\n"
2656                                   "} outData;\n"
2657                                   "\n"
2658                                   "void main()\n"
2659                                   "{\n"
2660                                   "    outData.innerColor = texture(sampler2D(texImage, texSampler), vec2(0.5));\n"
2661                                   "    outData.outerColor = texture(sampler2D(texImage, texSampler), vec2(-0.1));\n"
2662                                   "}\n";
2663 
2664         sourceCollections.glslSources.add("compute") << glu::ComputeSource(computeSrc);
2665     }
2666     else if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
2667     {
2668         const string computeSrc = "#version 450\n"
2669                                   "layout(set = 0, binding = " +
2670                                   de::toString(m_params.binding + 1) +
2671                                   ") uniform sampler texSampler;\n"
2672                                   "layout(set = 0, binding = " +
2673                                   de::toString(m_params.binding) +
2674                                   ") uniform texture2D texImage;\n"
2675                                   "layout(set = 0, binding = " +
2676                                   de::toString(m_params.binding + 2) +
2677                                   ") writeonly buffer Output\n"
2678                                   "{\n"
2679                                   "    vec4 innerColor;\n"
2680                                   "    vec4 outerColor;\n"
2681                                   "} outData;\n"
2682                                   "\n"
2683                                   "void main()\n"
2684                                   "{\n"
2685                                   "    outData.innerColor = texture(sampler2D(texImage, texSampler), vec2(0.5));\n"
2686                                   "    outData.outerColor = texture(sampler2D(texImage, texSampler), vec2(-0.1));\n"
2687                                   "}\n";
2688 
2689         sourceCollections.glslSources.add("compute") << glu::ComputeSource(computeSrc);
2690     }
2691     else if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
2692     {
2693         const string computeSrc = "#version 450\n"
2694                                   "layout(set = 0, binding = " +
2695                                   de::toString(m_params.binding) +
2696                                   ", rgba8) uniform readonly image2D storageImage;\n"
2697                                   "layout(set = 0, binding = " +
2698                                   de::toString(m_params.binding + 1) +
2699                                   ") writeonly buffer Output\n"
2700                                   "{\n"
2701                                   "    vec4 innerColor;\n"
2702                                   "    vec4 outerColor;\n"
2703                                   "} outData;\n"
2704                                   "\n"
2705                                   "void main()\n"
2706                                   "{\n"
2707                                   "    outData.innerColor = imageLoad(storageImage, ivec2(0));\n"
2708                                   "    outData.outerColor = imageLoad(storageImage, ivec2(0));\n"
2709                                   "}\n";
2710 
2711         sourceCollections.glslSources.add("compute") << glu::ComputeSource(computeSrc);
2712     }
2713     else
2714     {
2715         DE_FATAL("Unexpected descriptor type");
2716     }
2717 }
2718 
2719 class PushDescriptorTexelBufferGraphicsTestInstance : public vkt::TestInstance
2720 {
2721 public:
2722     PushDescriptorTexelBufferGraphicsTestInstance(Context &context, const TestParams &params);
2723     virtual ~PushDescriptorTexelBufferGraphicsTestInstance(void);
2724     void init(void);
2725     virtual tcu::TestStatus iterate(void);
2726     tcu::TestStatus verifyImage(void);
2727 
2728 private:
2729     const TestParams m_params;
2730     const PlatformInterface &m_vkp;
2731     const Extensions m_instanceExtensions;
2732     const CustomInstance m_instance;
2733     const InstanceDriver &m_vki;
2734     const VkPhysicalDevice m_physicalDevice;
2735     const uint32_t m_queueFamilyIndex;
2736     const Extensions m_deviceExtensions;
2737     std::vector<std::string> m_deviceEnabledExtensions;
2738     const Unique<VkDevice> m_device;
2739     const DeviceDriver m_vkd;
2740     const VkQueue m_queue;
2741     SimpleAllocator m_allocator;
2742     const tcu::UVec2 m_renderSize;
2743     const VkFormat m_colorFormat;
2744     Move<VkImage> m_colorImage;
2745     de::MovePtr<Allocation> m_colorImageAlloc;
2746     Move<VkImageView> m_colorAttachmentView;
2747     vector<VkBufferSp> m_buffers;
2748     vector<AllocationSp> m_bufferAllocs;
2749     vector<VkBufferViewSp> m_bufferViews;
2750     const VkFormat m_bufferFormat;
2751     RenderPassWrapper m_renderPass;
2752     Move<VkFramebuffer> m_framebuffer;
2753     ShaderWrapper m_vertexShaderModule;
2754     ShaderWrapper m_fragmentShaderModule;
2755     Move<VkBuffer> m_vertexBuffer;
2756     de::MovePtr<Allocation> m_vertexBufferAlloc;
2757     Move<VkDescriptorSetLayout> m_descriptorSetLayout;
2758     PipelineLayoutWrapper m_preRasterizationStatePipelineLayout;
2759     PipelineLayoutWrapper m_fragmentStatePipelineLayout;
2760     GraphicsPipelineWrapper m_graphicsPipeline;
2761     Move<VkCommandPool> m_cmdPool;
2762     Move<VkCommandBuffer> m_cmdBuffer;
2763     vector<Vertex4RGBA> m_vertices;
2764 };
2765 
PushDescriptorTexelBufferGraphicsTestInstance(Context & context,const TestParams & params)2766 PushDescriptorTexelBufferGraphicsTestInstance::PushDescriptorTexelBufferGraphicsTestInstance(Context &context,
2767                                                                                              const TestParams &params)
2768     : vkt::TestInstance(context)
2769     , m_params(params)
2770     , m_vkp(context.getPlatformInterface())
2771     , m_instanceExtensions(enumerateInstanceExtensionProperties(m_vkp, DE_NULL))
2772     , m_instance(createInstanceWithGetPhysicalDeviceProperties2(context, m_instanceExtensions))
2773     , m_vki(m_instance.getDriver())
2774     , m_physicalDevice(chooseDevice(m_vki, m_instance, context.getTestContext().getCommandLine()))
2775     , m_queueFamilyIndex(findQueueFamilyIndexWithCaps(m_vki, m_physicalDevice, VK_QUEUE_GRAPHICS_BIT))
2776     , m_deviceExtensions(enumerateDeviceExtensionProperties(m_vki, m_physicalDevice, DE_NULL))
2777     , m_device(createDeviceWithPushDescriptor(context, m_vkp, m_instance, m_vki, m_physicalDevice, m_deviceExtensions,
2778                                               m_queueFamilyIndex, params, m_deviceEnabledExtensions))
2779     , m_vkd(m_vkp, m_instance, *m_device, context.getUsedApiVersion(), context.getTestContext().getCommandLine())
2780     , m_queue(getDeviceQueue(m_vkd, *m_device, m_queueFamilyIndex, 0u))
2781     , m_allocator(m_vkd, *m_device, getPhysicalDeviceMemoryProperties(m_vki, m_physicalDevice))
2782     , m_renderSize(32, 32)
2783     , m_colorFormat(VK_FORMAT_R8G8B8A8_UNORM)
2784     , m_bufferFormat(VK_FORMAT_R32G32B32A32_SFLOAT)
2785     , m_graphicsPipeline(m_vki, m_vkd, m_physicalDevice, *m_device, m_deviceEnabledExtensions,
2786                          params.pipelineConstructionType)
2787     , m_vertices(createQuads(params.numCalls, 0.25f))
2788 {
2789 }
2790 
init(void)2791 void PushDescriptorTexelBufferGraphicsTestInstance::init(void)
2792 {
2793     const VkComponentMapping componentMappingRGBA = {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G,
2794                                                      VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A};
2795 
2796     // Create color image
2797     {
2798 
2799         const VkImageCreateInfo colorImageParams = {
2800             VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                                   // VkStructureType sType;
2801             DE_NULL,                                                               // const void* pNext;
2802             0u,                                                                    // VkImageCreateFlags flags;
2803             VK_IMAGE_TYPE_2D,                                                      // VkImageType imageType;
2804             m_colorFormat,                                                         // VkFormat format;
2805             {m_renderSize.x(), m_renderSize.y(), 1u},                              // VkExtent3D extent;
2806             1u,                                                                    // uint32_t mipLevels;
2807             1u,                                                                    // uint32_t arrayLayers;
2808             VK_SAMPLE_COUNT_1_BIT,                                                 // VkSampleCountFlagBits samples;
2809             VK_IMAGE_TILING_OPTIMAL,                                               // VkImageTiling tiling;
2810             VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
2811             VK_SHARING_MODE_EXCLUSIVE,                                             // VkSharingMode sharingMode;
2812             1u,                                                                    // uint32_t queueFamilyIndexCount;
2813             &m_queueFamilyIndex,      // const uint32_t* pQueueFamilyIndices;
2814             VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
2815         };
2816 
2817         m_colorImage = createImage(m_vkd, *m_device, &colorImageParams);
2818 
2819         // Allocate and bind color image memory
2820         m_colorImageAlloc =
2821             m_allocator.allocate(getImageMemoryRequirements(m_vkd, *m_device, *m_colorImage), MemoryRequirement::Any);
2822         VK_CHECK(m_vkd.bindImageMemory(*m_device, *m_colorImage, m_colorImageAlloc->getMemory(),
2823                                        m_colorImageAlloc->getOffset()));
2824     }
2825 
2826     // Create color attachment view
2827     {
2828         const VkImageViewCreateInfo colorAttachmentViewParams = {
2829             VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,   // VkStructureType sType;
2830             DE_NULL,                                    // const void* pNext;
2831             0u,                                         // VkImageViewCreateFlags flags;
2832             *m_colorImage,                              // VkImage image;
2833             VK_IMAGE_VIEW_TYPE_2D,                      // VkImageViewType viewType;
2834             m_colorFormat,                              // VkFormat format;
2835             componentMappingRGBA,                       // VkChannelMapping channels;
2836             {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u} // VkImageSubresourceRange subresourceRange;
2837         };
2838 
2839         m_colorAttachmentView = createImageView(m_vkd, *m_device, &colorAttachmentViewParams);
2840     }
2841 
2842     // Create buffers
2843     VkBufferUsageFlags2CreateInfoKHR bufferUsageFlags2 = vk::initVulkanStructure();
2844     for (uint32_t bufIdx = 0; bufIdx < DE_LENGTH_OF_ARRAY(defaultTestColors); bufIdx++)
2845     {
2846         const VkBufferUsageFlags usageFlags = m_params.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER ?
2847                                                   VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT :
2848                                                   VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
2849 
2850         VkBufferCreateInfo bufferCreateInfo{
2851             VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
2852             DE_NULL,                              // const void* pNext;
2853             0u,                                   // VkBufferCreateFlags    flags
2854             kSizeofVec4,                          // VkDeviceSize size;
2855             usageFlags,                           // VkBufferUsageFlags usage;
2856             VK_SHARING_MODE_EXCLUSIVE,            // VkSharingMode sharingMode;
2857             1u,                                   // uint32_t queueFamilyCount;
2858             &m_queueFamilyIndex                   // const uint32_t* pQueueFamilyIndices;
2859         };
2860 
2861         if (m_params.useMaintenance5)
2862         {
2863             bufferUsageFlags2.usage = (VkBufferUsageFlagBits2KHR)usageFlags;
2864             bufferCreateInfo.pNext  = &bufferUsageFlags2;
2865             bufferCreateInfo.usage  = 0;
2866         }
2867 
2868         m_buffers.push_back(VkBufferSp(new Unique<VkBuffer>(createBuffer(m_vkd, *m_device, &bufferCreateInfo))));
2869         m_bufferAllocs.push_back(
2870             AllocationSp(m_allocator
2871                              .allocate(getBufferMemoryRequirements(m_vkd, *m_device, **m_buffers[bufIdx]),
2872                                        MemoryRequirement::HostVisible)
2873                              .release()));
2874         VK_CHECK(m_vkd.bindBufferMemory(*m_device, **m_buffers[bufIdx], m_bufferAllocs[bufIdx]->getMemory(),
2875                                         m_bufferAllocs[bufIdx]->getOffset()));
2876 
2877         deMemcpy(m_bufferAllocs[bufIdx]->getHostPtr(), &defaultTestColors[bufIdx], static_cast<size_t>(kSizeofVec4));
2878         flushAlloc(m_vkd, *m_device, *m_bufferAllocs[bufIdx]);
2879     }
2880 
2881     // Create buffer views
2882     for (uint32_t bufIdx = 0; bufIdx < DE_LENGTH_OF_ARRAY(defaultTestColors); bufIdx++)
2883     {
2884         const VkBufferViewCreateInfo bufferViewParams = {
2885             VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO, // VkStructureType sType;
2886             DE_NULL,                                   // const void* pNext;
2887             0u,                                        // VkBufferViewCreateFlags flags;
2888             **m_buffers[bufIdx],                       // VkBuffer buffer;
2889             m_bufferFormat,                            // VkFormat format;
2890             0u,                                        // VkDeviceSize offset;
2891             VK_WHOLE_SIZE                              // VkDeviceSize range;
2892         };
2893 
2894         m_bufferViews.push_back(
2895             VkBufferViewSp(new Unique<VkBufferView>(createBufferView(m_vkd, *m_device, &bufferViewParams))));
2896     }
2897 
2898     // Create render pass
2899     m_renderPass = RenderPassWrapper(m_params.pipelineConstructionType, m_vkd, *m_device, m_colorFormat);
2900 
2901     // Create framebuffer
2902     {
2903         const VkImageView attachmentBindInfos[] = {*m_colorAttachmentView};
2904 
2905         const VkFramebufferCreateInfo framebufferParams = {
2906             VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
2907             DE_NULL,                                   // const void* pNext;
2908             0u,                                        // VkFramebufferCreateFlags flags;
2909             *m_renderPass,                             // VkRenderPass renderPass;
2910             1u,                                        // uint32_t attachmentCount;
2911             attachmentBindInfos,                       // const VkImageView* pAttachments;
2912             (uint32_t)m_renderSize.x(),                // uint32_t width;
2913             (uint32_t)m_renderSize.y(),                // uint32_t height;
2914             1u                                         // uint32_t layers;
2915         };
2916 
2917         m_renderPass.createFramebuffer(m_vkd, *m_device, &framebufferParams, *m_colorImage);
2918     }
2919 
2920     // Create pipeline layout
2921     {
2922         const VkDescriptorSetLayoutBinding descriptorSetLayoutBinding = {
2923             m_params.binding,             // uint32_t binding;
2924             m_params.descriptorType,      // VkDescriptorType descriptorType;
2925             1u,                           // uint32_t descriptorCount;
2926             VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlags stageFlags;
2927             DE_NULL                       // const VkSampler* pImmutableSamplers;
2928         };
2929 
2930         const VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {
2931             VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,     // VkStructureType sType;
2932             DE_NULL,                                                 // const void* pNext;
2933             VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR, // VkDescriptorSetLayoutCreateFlags flags;
2934             1u,                                                      // uint32_t bindingCount;
2935             &descriptorSetLayoutBinding                              // const VkDescriptorSetLayoutBinding* pBindings;
2936         };
2937 
2938         m_descriptorSetLayout = createDescriptorSetLayout(m_vkd, *m_device, &descriptorSetLayoutCreateInfo, DE_NULL);
2939 
2940         VkPipelineLayoutCreateFlags pipelineLayoutFlags =
2941             (m_params.pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC) ?
2942                 0u :
2943                 uint32_t(VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT);
2944         VkPipelineLayoutCreateInfo pipelineLayoutParams{
2945             VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
2946             DE_NULL,                                       // const void* pNext;
2947             pipelineLayoutFlags,                           // VkPipelineLayoutCreateFlags flags;
2948             0u,                                            // uint32_t setLayoutCount;
2949             DE_NULL,                                       // const VkDescriptorSetLayout* pSetLayouts;
2950             0u,                                            // uint32_t pushConstantRangeCount;
2951             DE_NULL                                        // const VkPushDescriptorRange* pPushDescriptorRanges;
2952         };
2953 
2954         m_preRasterizationStatePipelineLayout =
2955             PipelineLayoutWrapper(m_params.pipelineConstructionType, m_vkd, *m_device, &pipelineLayoutParams);
2956         pipelineLayoutParams.setLayoutCount = 1u;
2957         pipelineLayoutParams.pSetLayouts    = &(*m_descriptorSetLayout);
2958         m_fragmentStatePipelineLayout =
2959             PipelineLayoutWrapper(m_params.pipelineConstructionType, m_vkd, *m_device, &pipelineLayoutParams);
2960     }
2961 
2962     // Create shaders
2963     {
2964         m_vertexShaderModule   = ShaderWrapper(m_vkd, *m_device, m_context.getBinaryCollection().get("vert"), 0u);
2965         m_fragmentShaderModule = ShaderWrapper(m_vkd, *m_device, m_context.getBinaryCollection().get("frag"), 0u);
2966     }
2967 
2968     // Create pipeline
2969     {
2970         const VkVertexInputBindingDescription vertexInputBindingDescription = {
2971             0u,                         // uint32_t binding;
2972             sizeof(Vertex4RGBA),        // uint32_t strideInBytes;
2973             VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate stepRate;
2974         };
2975 
2976         const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] = {
2977             {
2978                 0u,                            // uint32_t location;
2979                 0u,                            // uint32_t binding;
2980                 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
2981                 0u                             // uint32_t offsetInBytes;
2982             },
2983             {
2984                 1u,                            // uint32_t location;
2985                 0u,                            // uint32_t binding;
2986                 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
2987                 offsetof(Vertex4RGBA, color)   // uint32_t offset;
2988             }};
2989 
2990         const VkPipelineVertexInputStateCreateInfo vertexInputStateParams = {
2991             VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
2992             DE_NULL,                                                   // const void* pNext;
2993             0u,                                                        // vkPipelineVertexInputStateCreateFlags flags;
2994             1u,                                                        // uint32_t bindingCount;
2995             &vertexInputBindingDescription,  // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
2996             2u,                              // uint32_t attributeCount;
2997             vertexInputAttributeDescriptions // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
2998         };
2999 
3000         const vector<VkViewport> viewports{makeViewport(m_renderSize)};
3001         const vector<VkRect2D> scissors{makeRect2D(m_renderSize)};
3002 
3003         m_graphicsPipeline.setMonolithicPipelineLayout(m_fragmentStatePipelineLayout)
3004             .setDefaultRasterizationState()
3005             .setDefaultDepthStencilState()
3006             .setDefaultMultisampleState()
3007             .setDefaultColorBlendState()
3008             .setupVertexInputState(&vertexInputStateParams)
3009             .setupPreRasterizationShaderState(viewports, scissors, m_preRasterizationStatePipelineLayout, *m_renderPass,
3010                                               0u, m_vertexShaderModule)
3011             .setupFragmentShaderState(m_fragmentStatePipelineLayout, *m_renderPass, 0u, m_fragmentShaderModule)
3012             .setupFragmentOutputState(*m_renderPass)
3013             .buildPipeline();
3014     }
3015 
3016     // Create vertex buffer
3017     {
3018         const VkBufferCreateInfo vertexBufferParams = {
3019             VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,                    // VkStructureType sType;
3020             DE_NULL,                                                 // const void* pNext;
3021             0u,                                                      // VkBufferCreateFlags flags;
3022             (VkDeviceSize)(sizeof(Vertex4RGBA) * m_vertices.size()), // VkDeviceSize size;
3023             VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,                       // VkBufferUsageFlags usage;
3024             VK_SHARING_MODE_EXCLUSIVE,                               // VkSharingMode sharingMode;
3025             1u,                                                      // uint32_t queueFamilyCount;
3026             &m_queueFamilyIndex                                      // const uint32_t* pQueueFamilyIndices;
3027         };
3028 
3029         m_vertexBuffer      = createBuffer(m_vkd, *m_device, &vertexBufferParams);
3030         m_vertexBufferAlloc = m_allocator.allocate(getBufferMemoryRequirements(m_vkd, *m_device, *m_vertexBuffer),
3031                                                    MemoryRequirement::HostVisible);
3032 
3033         VK_CHECK(m_vkd.bindBufferMemory(*m_device, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(),
3034                                         m_vertexBufferAlloc->getOffset()));
3035 
3036         // Load vertices into vertex buffer
3037         deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA));
3038         flushAlloc(m_vkd, *m_device, *m_vertexBufferAlloc);
3039     }
3040 
3041     // Create command pool
3042     m_cmdPool = createCommandPool(m_vkd, *m_device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, m_queueFamilyIndex);
3043 
3044     // Create command buffer
3045     {
3046         const VkClearValue attachmentClearValue = defaultClearValue(m_colorFormat);
3047         const VkDeviceSize vertexBufferOffset   = 0;
3048 
3049         m_cmdBuffer = allocateCommandBuffer(m_vkd, *m_device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
3050         beginCommandBuffer(m_vkd, *m_cmdBuffer, 0u);
3051         m_renderPass.begin(m_vkd, *m_cmdBuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()),
3052                            attachmentClearValue);
3053         m_graphicsPipeline.bind(*m_cmdBuffer);
3054         m_vkd.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
3055 
3056         // Draw quads. Switch buffer view between draws.
3057         for (uint32_t quadNdx = 0; quadNdx < m_params.numCalls; quadNdx++)
3058         {
3059             VkWriteDescriptorSet writeDescriptorSet = {
3060                 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // VkStructureType sType;
3061                 DE_NULL,                                // const void* pNext;
3062                 0u,                                     // VkDescriptorSet dstSet;
3063                 m_params.binding,                       // uint32_t dstBinding;
3064                 0u,                                     // uint32_t dstArrayElement;
3065                 1u,                                     // uint32_t descriptorCount;
3066                 m_params.descriptorType,                // VkDescriptorType descriptorType;
3067                 DE_NULL,                                // const VkDescriptorImageInfo* pImageInfo;
3068                 DE_NULL,                                // const VkDescriptorBufferInfo* pBufferInfo;
3069                 &m_bufferViews[quadNdx]->get()          // const VkBufferView* pTexelBufferView;
3070             };
3071 
3072             m_vkd.cmdPushDescriptorSetKHR(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_fragmentStatePipelineLayout,
3073                                           0, 1u, &writeDescriptorSet);
3074             m_vkd.cmdDraw(*m_cmdBuffer, 6, 1, 6 * quadNdx, 0);
3075         }
3076 
3077         m_renderPass.end(m_vkd, *m_cmdBuffer);
3078         endCommandBuffer(m_vkd, *m_cmdBuffer);
3079     }
3080 }
3081 
~PushDescriptorTexelBufferGraphicsTestInstance(void)3082 PushDescriptorTexelBufferGraphicsTestInstance::~PushDescriptorTexelBufferGraphicsTestInstance(void)
3083 {
3084 }
3085 
iterate(void)3086 tcu::TestStatus PushDescriptorTexelBufferGraphicsTestInstance::iterate(void)
3087 {
3088     init();
3089 
3090     submitCommandsAndWait(m_vkd, *m_device, m_queue, m_cmdBuffer.get());
3091 
3092     return verifyImage();
3093 }
3094 
verifyImage(void)3095 tcu::TestStatus PushDescriptorTexelBufferGraphicsTestInstance::verifyImage(void)
3096 {
3097     const tcu::TextureFormat tcuColorFormat = mapVkFormat(m_colorFormat);
3098     const tcu::TextureFormat tcuDepthFormat = tcu::TextureFormat();
3099     const ColorVertexShader vertexShader;
3100     const ColorFragmentShader fragmentShader(tcuColorFormat, tcuDepthFormat);
3101     const rr::Program program(&vertexShader, &fragmentShader);
3102     ReferenceRenderer refRenderer(m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuDepthFormat, &program);
3103     bool compareOk = false;
3104 
3105     // Render reference image
3106     {
3107         for (uint32_t quadIdx = 0; quadIdx < m_params.numCalls; quadIdx++)
3108             for (uint32_t vertexIdx = 0; vertexIdx < 6; vertexIdx++)
3109                 m_vertices[quadIdx * 6 + vertexIdx].color.xyzw() = defaultTestColors[quadIdx];
3110 
3111         refRenderer.draw(rr::RenderState(refRenderer.getViewportState(),
3112                                          m_context.getDeviceProperties().limits.subPixelPrecisionBits),
3113                          rr::PRIMITIVETYPE_TRIANGLES, m_vertices);
3114     }
3115 
3116     // Compare result with reference image
3117     {
3118         de::MovePtr<tcu::TextureLevel> result = readColorAttachment(
3119             m_vkd, *m_device, m_queue, m_queueFamilyIndex, m_allocator, *m_colorImage, m_colorFormat, m_renderSize);
3120 
3121         compareOk = tcu::intThresholdPositionDeviationCompare(
3122             m_context.getTestContext().getLog(), "IntImageCompare", "Image comparison", refRenderer.getAccess(),
3123             result->getAccess(), tcu::UVec4(2, 2, 2, 2), tcu::IVec3(1, 1, 0), true, tcu::COMPARE_LOG_RESULT);
3124     }
3125 
3126     if (compareOk)
3127         return tcu::TestStatus::pass("Result image matches reference");
3128     else
3129         return tcu::TestStatus::fail("Image mismatch");
3130 }
3131 
3132 class PushDescriptorTexelBufferGraphicsTest : public vkt::TestCase
3133 {
3134 public:
3135     PushDescriptorTexelBufferGraphicsTest(tcu::TestContext &testContext, const string &name, const TestParams &params);
3136     ~PushDescriptorTexelBufferGraphicsTest(void);
3137 
3138     void checkSupport(Context &context) const;
3139     void initPrograms(SourceCollections &sourceCollections) const;
3140     TestInstance *createInstance(Context &context) const;
3141 
3142 protected:
3143     const TestParams m_params;
3144 };
3145 
PushDescriptorTexelBufferGraphicsTest(tcu::TestContext & testContext,const string & name,const TestParams & params)3146 PushDescriptorTexelBufferGraphicsTest::PushDescriptorTexelBufferGraphicsTest(tcu::TestContext &testContext,
3147                                                                              const string &name,
3148                                                                              const TestParams &params)
3149     : vkt::TestCase(testContext, name)
3150     , m_params(params)
3151 {
3152 }
3153 
~PushDescriptorTexelBufferGraphicsTest(void)3154 PushDescriptorTexelBufferGraphicsTest::~PushDescriptorTexelBufferGraphicsTest(void)
3155 {
3156 }
3157 
createInstance(Context & context) const3158 TestInstance *PushDescriptorTexelBufferGraphicsTest::createInstance(Context &context) const
3159 {
3160     return new PushDescriptorTexelBufferGraphicsTestInstance(context, m_params);
3161 }
3162 
checkSupport(Context & context) const3163 void PushDescriptorTexelBufferGraphicsTest::checkSupport(Context &context) const
3164 {
3165     if (m_params.useMaintenance5)
3166         context.requireDeviceFunctionality("VK_KHR_maintenance5");
3167 
3168     checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(),
3169                                           m_params.pipelineConstructionType);
3170 }
3171 
initPrograms(SourceCollections & sourceCollections) const3172 void PushDescriptorTexelBufferGraphicsTest::initPrograms(SourceCollections &sourceCollections) const
3173 {
3174     const string vertexSrc = "#version 450\n"
3175                              "layout(location = 0) in highp vec4 position;\n"
3176                              "layout(location = 1) in highp vec4 texcoordVtx;\n"
3177                              "layout(location = 0) out highp vec2 texcoordFrag;\n"
3178                              "\n"
3179                              "out gl_PerVertex { vec4 gl_Position; };\n"
3180                              "\n"
3181                              "void main()\n"
3182                              "{\n"
3183                              "    gl_Position = position;\n"
3184                              "    texcoordFrag = texcoordVtx.xy;\n"
3185                              "}\n";
3186 
3187     sourceCollections.glslSources.add("vert") << glu::VertexSource(vertexSrc);
3188 
3189     if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER)
3190     {
3191         const string fragmentSrc = "#version 450\n"
3192                                    "layout(location = 0) in highp vec2 texcoordFrag;\n"
3193                                    "layout(location = 0) out highp vec4 fragColor;\n"
3194                                    "layout(set = 0, binding = " +
3195                                    de::toString(m_params.binding) +
3196                                    ") uniform textureBuffer texelBuffer;\n"
3197                                    "\n"
3198                                    "void main (void)\n"
3199                                    "{\n"
3200                                    "    fragColor = texelFetch(texelBuffer, 0);\n"
3201                                    "}\n";
3202 
3203         sourceCollections.glslSources.add("frag") << glu::FragmentSource(fragmentSrc);
3204     }
3205     else
3206     {
3207         DE_ASSERT(m_params.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER);
3208         const string fragmentSrc = "#version 450\n"
3209                                    "layout(location = 0) in highp vec2 texcoordFrag;\n"
3210                                    "layout(location = 0) out highp vec4 fragColor;\n"
3211                                    "layout(set = 0, binding = " +
3212                                    de::toString(m_params.binding) +
3213                                    ", rgba32f) uniform readonly imageBuffer texelBuffer;\n"
3214                                    "\n"
3215                                    "void main (void)\n"
3216                                    "{\n"
3217                                    "    fragColor = imageLoad(texelBuffer, 0);\n"
3218                                    "}\n";
3219 
3220         sourceCollections.glslSources.add("frag") << glu::FragmentSource(fragmentSrc);
3221     }
3222 }
3223 
3224 class PushDescriptorTexelBufferComputeTestInstance : public vkt::TestInstance
3225 {
3226 public:
3227     PushDescriptorTexelBufferComputeTestInstance(Context &context, const TestParams &params);
3228     virtual ~PushDescriptorTexelBufferComputeTestInstance(void);
3229     void init(void);
3230     virtual tcu::TestStatus iterate(void);
3231     tcu::TestStatus verifyOutput(void);
3232 
3233 private:
3234     const TestParams m_params;
3235     const PlatformInterface &m_vkp;
3236     const Extensions m_instanceExtensions;
3237     const CustomInstance m_instance;
3238     const InstanceDriver &m_vki;
3239     const VkPhysicalDevice m_physicalDevice;
3240     const uint32_t m_queueFamilyIndex;
3241     const Extensions m_deviceExtensions;
3242     std::vector<std::string> m_deviceEnabledExtensions;
3243     const Unique<VkDevice> m_device;
3244     const DeviceDriver m_vkd;
3245     const VkQueue m_queue;
3246     const VkDeviceSize m_itemSize;
3247     SimpleAllocator m_allocator;
3248     vector<VkBufferSp> m_buffers;
3249     vector<AllocationSp> m_bufferAllocs;
3250     vector<VkBufferViewSp> m_bufferViews;
3251     const VkFormat m_bufferFormat;
3252     Move<VkShaderModule> m_computeShaderModule;
3253     Move<VkBuffer> m_outputBuffer;
3254     de::MovePtr<Allocation> m_outputBufferAlloc;
3255     Move<VkDescriptorSetLayout> m_descriptorSetLayout;
3256     Move<VkPipelineLayout> m_pipelineLayout;
3257     Move<VkPipeline> m_computePipeline;
3258     Move<VkCommandPool> m_cmdPool;
3259     Move<VkCommandBuffer> m_cmdBuffer;
3260 };
3261 
PushDescriptorTexelBufferComputeTestInstance(Context & context,const TestParams & params)3262 PushDescriptorTexelBufferComputeTestInstance::PushDescriptorTexelBufferComputeTestInstance(Context &context,
3263                                                                                            const TestParams &params)
3264     : vkt::TestInstance(context)
3265     , m_params(params)
3266     , m_vkp(context.getPlatformInterface())
3267     , m_instanceExtensions(enumerateInstanceExtensionProperties(m_vkp, DE_NULL))
3268     , m_instance(createInstanceWithGetPhysicalDeviceProperties2(context, m_instanceExtensions))
3269     , m_vki(m_instance.getDriver())
3270     , m_physicalDevice(chooseDevice(m_vki, m_instance, context.getTestContext().getCommandLine()))
3271     , m_queueFamilyIndex(findQueueFamilyIndexWithCaps(m_vki, m_physicalDevice, VK_QUEUE_COMPUTE_BIT))
3272     , m_deviceExtensions(enumerateDeviceExtensionProperties(m_vki, m_physicalDevice, DE_NULL))
3273     , m_device(createDeviceWithPushDescriptor(context, m_vkp, m_instance, m_vki, m_physicalDevice, m_deviceExtensions,
3274                                               m_queueFamilyIndex, params, m_deviceEnabledExtensions))
3275     , m_vkd(m_vkp, m_instance, *m_device, context.getUsedApiVersion(), context.getTestContext().getCommandLine())
3276     , m_queue(getDeviceQueue(m_vkd, *m_device, m_queueFamilyIndex, 0u))
3277     , m_itemSize(calcItemSize(m_vki, m_physicalDevice))
3278     , m_allocator(m_vkd, *m_device, getPhysicalDeviceMemoryProperties(m_vki, m_physicalDevice))
3279     , m_bufferFormat(VK_FORMAT_R32G32B32A32_SFLOAT)
3280 {
3281 }
3282 
init(void)3283 void PushDescriptorTexelBufferComputeTestInstance::init(void)
3284 {
3285     // Create buffers
3286     for (uint32_t bufIdx = 0; bufIdx < DE_LENGTH_OF_ARRAY(defaultTestColors); bufIdx++)
3287     {
3288         const VkBufferUsageFlags usageFlags = m_params.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER ?
3289                                                   VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT :
3290                                                   VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
3291 
3292         const VkBufferCreateInfo bufferCreateInfo = {
3293             VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
3294             DE_NULL,                              // const void* pNext;
3295             0u,                                   // VkBufferCreateFlags    flags
3296             kSizeofVec4,                          // VkDeviceSize size;
3297             usageFlags,                           // VkBufferUsageFlags usage;
3298             VK_SHARING_MODE_EXCLUSIVE,            // VkSharingMode sharingMode;
3299             1u,                                   // uint32_t queueFamilyCount;
3300             &m_queueFamilyIndex                   // const uint32_t* pQueueFamilyIndices;
3301         };
3302 
3303         m_buffers.push_back(VkBufferSp(new Unique<VkBuffer>(createBuffer(m_vkd, *m_device, &bufferCreateInfo))));
3304         m_bufferAllocs.push_back(
3305             AllocationSp(m_allocator
3306                              .allocate(getBufferMemoryRequirements(m_vkd, *m_device, **m_buffers[bufIdx]),
3307                                        MemoryRequirement::HostVisible)
3308                              .release()));
3309         VK_CHECK(m_vkd.bindBufferMemory(*m_device, **m_buffers[bufIdx], m_bufferAllocs[bufIdx]->getMemory(),
3310                                         m_bufferAllocs[bufIdx]->getOffset()));
3311 
3312         deMemcpy(m_bufferAllocs[bufIdx]->getHostPtr(), &defaultTestColors[bufIdx], static_cast<size_t>(kSizeofVec4));
3313         flushAlloc(m_vkd, *m_device, *m_bufferAllocs[bufIdx]);
3314     }
3315 
3316     // Create buffer views
3317     for (uint32_t bufIdx = 0; bufIdx < DE_LENGTH_OF_ARRAY(defaultTestColors); bufIdx++)
3318     {
3319         const VkBufferViewCreateInfo bufferViewParams = {
3320             VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO, // VkStructureType sType;
3321             DE_NULL,                                   // const void* pNext;
3322             0u,                                        // VkBufferViewCreateFlags flags;
3323             **m_buffers[bufIdx],                       // VkBuffer buffer;
3324             m_bufferFormat,                            // VkFormat format;
3325             0u,                                        // VkDeviceSize offset;
3326             VK_WHOLE_SIZE                              // VkDeviceSize range;
3327         };
3328 
3329         m_bufferViews.push_back(
3330             VkBufferViewSp(new Unique<VkBufferView>(createBufferView(m_vkd, *m_device, &bufferViewParams))));
3331     }
3332 
3333     // Create pipeline layout
3334     {
3335         vector<VkDescriptorSetLayoutBinding> layoutBindings;
3336 
3337         const VkDescriptorSetLayoutBinding descriptorSetLayoutBindings[] = {
3338             {
3339                 m_params.binding,            // uint32_t binding;
3340                 m_params.descriptorType,     // VkDescriptorType descriptorType;
3341                 1u,                          // uint32_t descriptorCount;
3342                 VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlags stageFlags;
3343                 DE_NULL                      // const VkSampler* pImmutableSamplers;
3344             },
3345             {
3346                 m_params.binding + 1,              // uint32_t binding;
3347                 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, // VkDescriptorType descriptorType;
3348                 1u,                                // uint32_t descriptorCount;
3349                 VK_SHADER_STAGE_COMPUTE_BIT,       // VkShaderStageFlags stageFlags;
3350                 DE_NULL                            // const VkSampler* pImmutableSamplers;
3351             }};
3352 
3353         const VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {
3354             VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,     // VkStructureType sType;
3355             DE_NULL,                                                 // const void* pNext;
3356             VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR, // VkDescriptorSetLayoutCreateFlags flags;
3357             2u,                                                      // uint32_t bindingCount;
3358             descriptorSetLayoutBindings                              // const VkDescriptorSetLayoutBinding* pBindings;
3359         };
3360 
3361         m_descriptorSetLayout = createDescriptorSetLayout(m_vkd, *m_device, &descriptorSetLayoutCreateInfo, DE_NULL);
3362 
3363         const VkPipelineLayoutCreateInfo pipelineLayoutParams = {
3364             VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
3365             DE_NULL,                                       // const void* pNext;
3366             0u,                                            // VkPipelineLayoutCreateFlags flags;
3367             1u,                                            // uint32_t descriptorSetCount;
3368             &(*m_descriptorSetLayout),                     // const VkDescriptorSetLayout* pSetLayouts;
3369             0u,                                            // uint32_t pushConstantRangeCount;
3370             DE_NULL                                        // const VkPushDescriptorRange* pPushDescriptorRanges;
3371         };
3372 
3373         m_pipelineLayout = createPipelineLayout(m_vkd, *m_device, &pipelineLayoutParams);
3374     }
3375 
3376     // Create output buffer
3377     {
3378         DE_ASSERT(m_params.numCalls <= 2u);
3379 
3380         const VkBufferCreateInfo bufferCreateInfo = {
3381             VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
3382             DE_NULL,                              // const void* pNext;
3383             0u,                                   // VkBufferCreateFlags    flags
3384             m_itemSize * m_params.numCalls,       // VkDeviceSize size;
3385             VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,   // VkBufferUsageFlags usage;
3386             VK_SHARING_MODE_EXCLUSIVE,            // VkSharingMode sharingMode;
3387             1u,                                   // uint32_t queueFamilyCount;
3388             &m_queueFamilyIndex                   // const uint32_t* pQueueFamilyIndices;
3389         };
3390 
3391         m_outputBuffer      = createBuffer(m_vkd, *m_device, &bufferCreateInfo);
3392         m_outputBufferAlloc = m_allocator.allocate(getBufferMemoryRequirements(m_vkd, *m_device, *m_outputBuffer),
3393                                                    MemoryRequirement::HostVisible);
3394         VK_CHECK(m_vkd.bindBufferMemory(*m_device, *m_outputBuffer, m_outputBufferAlloc->getMemory(),
3395                                         m_outputBufferAlloc->getOffset()));
3396     }
3397 
3398     // Create shader
3399     {
3400         m_computeShaderModule =
3401             createShaderModule(m_vkd, *m_device, m_context.getBinaryCollection().get("compute"), 0u);
3402     }
3403 
3404     // Create pipeline
3405     {
3406         const VkPipelineShaderStageCreateInfo stageCreateInfo = {
3407             VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
3408             DE_NULL,                                             // const void* pNext;
3409             0u,                                                  // VkPipelineShaderStageCreateFlags flags;
3410             VK_SHADER_STAGE_COMPUTE_BIT,                         // VkShaderStageFlagBits stage;
3411             *m_computeShaderModule,                              // VkShaderModule module;
3412             "main",                                              // const char* pName;
3413             DE_NULL                                              // const VkSpecializationInfo* pSpecializationInfo;
3414         };
3415 
3416         const VkComputePipelineCreateInfo createInfo = {
3417             VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // VkStructureType sType;
3418             DE_NULL,                                        // const void* pNext;
3419             0u,                                             // VkPipelineCreateFlags flags;
3420             stageCreateInfo,                                // VkPipelineShaderStageCreateInfo stage;
3421             *m_pipelineLayout,                              // VkPipelineLayout layout;
3422             (VkPipeline)0,                                  // VkPipeline basePipelineHandle;
3423             0u,                                             // int32_t basePipelineIndex;
3424         };
3425 
3426         m_computePipeline = createComputePipeline(m_vkd, *m_device, (vk::VkPipelineCache)0u, &createInfo);
3427     }
3428 
3429     // Create command pool
3430     m_cmdPool = createCommandPool(m_vkd, *m_device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, m_queueFamilyIndex);
3431 
3432     // Create command buffer
3433     {
3434         m_cmdBuffer = allocateCommandBuffer(m_vkd, *m_device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
3435         beginCommandBuffer(m_vkd, *m_cmdBuffer, 0u);
3436         m_vkd.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_computePipeline);
3437 
3438         // Dispatch: Each dispatch switches the input image.
3439         // Output buffer is exposed as a vec4 sized window.
3440         for (uint32_t dispatchNdx = 0; dispatchNdx < m_params.numCalls; dispatchNdx++)
3441         {
3442             VkWriteDescriptorSet writeDescriptorSet = {
3443                 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // VkStructureType sType;
3444                 DE_NULL,                                // const void* pNext;
3445                 0u,                                     // VkDescriptorSet dstSet;
3446                 m_params.binding,                       // uint32_t dstBinding;
3447                 0u,                                     // uint32_t dstArrayElement;
3448                 1u,                                     // uint32_t descriptorCount;
3449                 m_params.descriptorType,                // VkDescriptorType descriptorType;
3450                 DE_NULL,                                // const VkDescriptorImageInfo* pImageInfo;
3451                 DE_NULL,                                // const VkDescriptorBufferInfo* pBufferInfo;
3452                 &m_bufferViews[dispatchNdx]->get()      // const VkBufferView* pTexelBufferView;
3453             };
3454 
3455             vector<VkWriteDescriptorSet> writeDescriptorSets;
3456             writeDescriptorSets.push_back(writeDescriptorSet);
3457 
3458             const VkDescriptorBufferInfo descriptorBufferInfoOutput = {
3459                 *m_outputBuffer,          // VkBuffer buffer;
3460                 m_itemSize * dispatchNdx, // VkDeviceSize offset;
3461                 kSizeofVec4,              // VkDeviceSize range;
3462             };
3463 
3464             // Write output buffer descriptor set
3465             const VkWriteDescriptorSet writeDescriptorSetOutput = {
3466                 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // VkStructureType sType;
3467                 DE_NULL,                                // const void* pNext;
3468                 0u,                                     // VkDescriptorSet dstSet;
3469                 m_params.binding + 1,                   // uint32_t dstBinding;
3470                 0u,                                     // uint32_t dstArrayElement;
3471                 1u,                                     // uint32_t descriptorCount;
3472                 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,      // VkDescriptorType descriptorType;
3473                 DE_NULL,                                // const VkDescriptorImageInfo* pImageInfo;
3474                 &descriptorBufferInfoOutput,            // const VkDescriptorBufferInfo* pBufferInfo;
3475                 DE_NULL                                 // const VkBufferView* pTexelBufferView;
3476             };
3477 
3478             writeDescriptorSets.push_back(writeDescriptorSetOutput);
3479 
3480             m_vkd.cmdPushDescriptorSetKHR(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipelineLayout, 0,
3481                                           (uint32_t)writeDescriptorSets.size(), writeDescriptorSets.data());
3482             m_vkd.cmdDispatch(*m_cmdBuffer, 1, 1, 1);
3483         }
3484 
3485         endCommandBuffer(m_vkd, *m_cmdBuffer);
3486     }
3487 }
3488 
~PushDescriptorTexelBufferComputeTestInstance(void)3489 PushDescriptorTexelBufferComputeTestInstance::~PushDescriptorTexelBufferComputeTestInstance(void)
3490 {
3491 }
3492 
iterate(void)3493 tcu::TestStatus PushDescriptorTexelBufferComputeTestInstance::iterate(void)
3494 {
3495     init();
3496 
3497     submitCommandsAndWait(m_vkd, *m_device, m_queue, m_cmdBuffer.get());
3498 
3499     return verifyOutput();
3500 }
3501 
verifyOutput(void)3502 tcu::TestStatus PushDescriptorTexelBufferComputeTestInstance::verifyOutput(void)
3503 {
3504     const tcu::Vec4 ref[2] = {{1.0f, 0.0f, 0.0f, 1.0f}, {0.0f, 1.0f, 0.0f, 1.0f}};
3505     invalidateAlloc(m_vkd, *m_device, *m_outputBufferAlloc);
3506 
3507     // Verify result
3508     DE_ASSERT(m_params.numCalls <= 2u);
3509 
3510     auto bufferPtr = reinterpret_cast<const char *>(m_outputBufferAlloc->getHostPtr());
3511     for (uint32_t i = 0; i < m_params.numCalls; ++i)
3512     {
3513         tcu::Vec4 bufferColor;
3514         deMemcpy(&bufferColor, bufferPtr + (i * m_itemSize), static_cast<size_t>(kSizeofVec4));
3515 
3516         if (bufferColor != ref[i])
3517         {
3518             std::ostringstream msg;
3519             msg << "Output mismatch at item " << i << ": expected " << ref[i] << " but found " << bufferColor;
3520             TCU_FAIL(msg.str());
3521         }
3522     }
3523 
3524     return tcu::TestStatus::pass("Output matches expected values");
3525 }
3526 
3527 class PushDescriptorTexelBufferComputeTest : public vkt::TestCase
3528 {
3529 public:
3530     PushDescriptorTexelBufferComputeTest(tcu::TestContext &testContext, const string &name, const TestParams &params);
3531     ~PushDescriptorTexelBufferComputeTest(void);
3532     void initPrograms(SourceCollections &sourceCollections) const;
3533     TestInstance *createInstance(Context &context) const;
3534 
3535 protected:
3536     const TestParams m_params;
3537 };
3538 
PushDescriptorTexelBufferComputeTest(tcu::TestContext & testContext,const string & name,const TestParams & params)3539 PushDescriptorTexelBufferComputeTest::PushDescriptorTexelBufferComputeTest(tcu::TestContext &testContext,
3540                                                                            const string &name, const TestParams &params)
3541     : vkt::TestCase(testContext, name)
3542     , m_params(params)
3543 {
3544 }
3545 
~PushDescriptorTexelBufferComputeTest(void)3546 PushDescriptorTexelBufferComputeTest::~PushDescriptorTexelBufferComputeTest(void)
3547 {
3548 }
3549 
createInstance(Context & context) const3550 TestInstance *PushDescriptorTexelBufferComputeTest::createInstance(Context &context) const
3551 {
3552     return new PushDescriptorTexelBufferComputeTestInstance(context, m_params);
3553 }
3554 
initPrograms(SourceCollections & sourceCollections) const3555 void PushDescriptorTexelBufferComputeTest::initPrograms(SourceCollections &sourceCollections) const
3556 {
3557     if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER)
3558     {
3559         const string computeSrc = "#version 450\n"
3560                                   "layout(set = 0, binding = " +
3561                                   de::toString(m_params.binding) +
3562                                   ") uniform textureBuffer texelBuffer;\n"
3563                                   "layout(set = 0, binding = " +
3564                                   de::toString(m_params.binding + 1) +
3565                                   ") writeonly buffer Output\n"
3566                                   "{\n"
3567                                   "    vec4 color;\n"
3568                                   "} outData;\n"
3569                                   "\n"
3570                                   "void main()\n"
3571                                   "{\n"
3572                                   "    outData.color = texelFetch(texelBuffer, 0);\n"
3573                                   "}\n";
3574 
3575         sourceCollections.glslSources.add("compute") << glu::ComputeSource(computeSrc);
3576     }
3577     else
3578     {
3579         DE_ASSERT(m_params.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER);
3580 
3581         const string computeSrc = "#version 450\n"
3582                                   "layout(set = 0, binding = " +
3583                                   de::toString(m_params.binding) +
3584                                   ", rgba32f) uniform readonly imageBuffer texelBuffer;\n"
3585                                   "layout(set = 0, binding = " +
3586                                   de::toString(m_params.binding + 1) +
3587                                   ") writeonly buffer Output\n"
3588                                   "{\n"
3589                                   "    vec4 color;\n"
3590                                   "} outData;\n"
3591                                   "\n"
3592                                   "void main()\n"
3593                                   "{\n"
3594                                   "    outData.color = imageLoad(texelBuffer, 0);\n"
3595                                   "}\n";
3596 
3597         sourceCollections.glslSources.add("compute") << glu::ComputeSource(computeSrc);
3598     }
3599 }
3600 
3601 class PushDescriptorInputAttachmentGraphicsTestInstance : public vkt::TestInstance
3602 {
3603 public:
3604     PushDescriptorInputAttachmentGraphicsTestInstance(Context &context, const TestParams &params);
3605     virtual ~PushDescriptorInputAttachmentGraphicsTestInstance(void);
3606     void init(void);
3607     virtual tcu::TestStatus iterate(void);
3608     tcu::TestStatus verifyImage(void);
3609 
3610 private:
3611     const TestParams m_params;
3612     const PlatformInterface &m_vkp;
3613     const Extensions m_instanceExtensions;
3614     const CustomInstance m_instance;
3615     const InstanceDriver &m_vki;
3616     const VkPhysicalDevice m_physicalDevice;
3617     const uint32_t m_queueFamilyIndex;
3618     const Extensions m_deviceExtensions;
3619     std::vector<std::string> m_deviceEnabledExtensions;
3620     const Unique<VkDevice> m_device;
3621     const DeviceDriver m_vkd;
3622     const VkQueue m_queue;
3623     SimpleAllocator m_allocator;
3624     const tcu::UVec2 m_renderSize;
3625     const tcu::UVec2 m_textureSize;
3626     const VkFormat m_colorFormat;
3627     Move<VkImage> m_colorImage;
3628     de::MovePtr<Allocation> m_colorImageAlloc;
3629     Move<VkImageView> m_colorAttachmentView;
3630     vector<VkImageSp> m_inputImages;
3631     vector<AllocationSp> m_inputImageAllocs;
3632     vector<VkImageViewSp> m_inputImageViews;
3633     vector<VkRenderPassSp> m_renderPasses;
3634     ShaderWrapper m_vertexShaderModule;
3635     ShaderWrapper m_fragmentShaderModule;
3636     Move<VkBuffer> m_vertexBuffer;
3637     de::MovePtr<Allocation> m_vertexBufferAlloc;
3638     Move<VkDescriptorSetLayout> m_descriptorSetLayout;
3639     PipelineLayoutWrapper m_preRasterizationStatePipelineLayout;
3640     PipelineLayoutWrapper m_fragmentStatePipelineLayout;
3641     vector<GraphicsPipelineWrapper> m_graphicsPipelines;
3642     Move<VkCommandPool> m_cmdPool;
3643     Move<VkCommandBuffer> m_cmdBuffer;
3644     vector<Vertex4Tex4> m_vertices;
3645 };
3646 
PushDescriptorInputAttachmentGraphicsTestInstance(Context & context,const TestParams & params)3647 PushDescriptorInputAttachmentGraphicsTestInstance::PushDescriptorInputAttachmentGraphicsTestInstance(
3648     Context &context, const TestParams &params)
3649     : vkt::TestInstance(context)
3650     , m_params(params)
3651     , m_vkp(context.getPlatformInterface())
3652     , m_instanceExtensions(enumerateInstanceExtensionProperties(m_vkp, DE_NULL))
3653     , m_instance(createInstanceWithGetPhysicalDeviceProperties2(context, m_instanceExtensions))
3654     , m_vki(m_instance.getDriver())
3655     , m_physicalDevice(chooseDevice(m_vki, m_instance, context.getTestContext().getCommandLine()))
3656     , m_queueFamilyIndex(findQueueFamilyIndexWithCaps(m_vki, m_physicalDevice, VK_QUEUE_GRAPHICS_BIT))
3657     , m_deviceExtensions(enumerateDeviceExtensionProperties(m_vki, m_physicalDevice, DE_NULL))
3658     , m_device(createDeviceWithPushDescriptor(context, m_vkp, m_instance, m_vki, m_physicalDevice, m_deviceExtensions,
3659                                               m_queueFamilyIndex, params, m_deviceEnabledExtensions))
3660     , m_vkd(m_vkp, m_instance, *m_device, context.getUsedApiVersion(), context.getTestContext().getCommandLine())
3661     , m_queue(getDeviceQueue(m_vkd, *m_device, m_queueFamilyIndex, 0u))
3662     , m_allocator(m_vkd, *m_device, getPhysicalDeviceMemoryProperties(m_vki, m_physicalDevice))
3663     , m_renderSize(32, 32)
3664     , m_textureSize(32, 32)
3665     , m_colorFormat(VK_FORMAT_R8G8B8A8_UNORM)
3666     , m_vertices(createTexQuads(params.numCalls, 0.25f))
3667 {
3668 }
3669 
init(void)3670 void PushDescriptorInputAttachmentGraphicsTestInstance::init(void)
3671 {
3672     const VkComponentMapping componentMappingRGBA = {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G,
3673                                                      VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A};
3674 
3675     // Create color image
3676     {
3677 
3678         const VkImageCreateInfo colorImageParams = {
3679             VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                                   // VkStructureType sType;
3680             DE_NULL,                                                               // const void* pNext;
3681             0u,                                                                    // VkImageCreateFlags flags;
3682             VK_IMAGE_TYPE_2D,                                                      // VkImageType imageType;
3683             m_colorFormat,                                                         // VkFormat format;
3684             {m_renderSize.x(), m_renderSize.y(), 1u},                              // VkExtent3D extent;
3685             1u,                                                                    // uint32_t mipLevels;
3686             1u,                                                                    // uint32_t arrayLayers;
3687             VK_SAMPLE_COUNT_1_BIT,                                                 // VkSampleCountFlagBits samples;
3688             VK_IMAGE_TILING_OPTIMAL,                                               // VkImageTiling tiling;
3689             VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
3690             VK_SHARING_MODE_EXCLUSIVE,                                             // VkSharingMode sharingMode;
3691             1u,                                                                    // uint32_t queueFamilyIndexCount;
3692             &m_queueFamilyIndex,      // const uint32_t* pQueueFamilyIndices;
3693             VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
3694         };
3695 
3696         m_colorImage = createImage(m_vkd, *m_device, &colorImageParams);
3697 
3698         // Allocate and bind color image memory
3699         m_colorImageAlloc =
3700             m_allocator.allocate(getImageMemoryRequirements(m_vkd, *m_device, *m_colorImage), MemoryRequirement::Any);
3701         VK_CHECK(m_vkd.bindImageMemory(*m_device, *m_colorImage, m_colorImageAlloc->getMemory(),
3702                                        m_colorImageAlloc->getOffset()));
3703     }
3704 
3705     // Create color attachment view
3706     {
3707         const VkImageViewCreateInfo colorAttachmentViewParams = {
3708             VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,   // VkStructureType sType;
3709             DE_NULL,                                    // const void* pNext;
3710             0u,                                         // VkImageViewCreateFlags flags;
3711             *m_colorImage,                              // VkImage image;
3712             VK_IMAGE_VIEW_TYPE_2D,                      // VkImageViewType viewType;
3713             m_colorFormat,                              // VkFormat format;
3714             componentMappingRGBA,                       // VkChannelMapping channels;
3715             {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u} // VkImageSubresourceRange subresourceRange;
3716         };
3717 
3718         m_colorAttachmentView = createImageView(m_vkd, *m_device, &colorAttachmentViewParams);
3719     }
3720 
3721     // Create input images
3722     for (uint32_t imageIdx = 0; imageIdx < 2; imageIdx++)
3723     {
3724         const VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
3725 
3726         const VkImageCreateInfo inputImageParams = {
3727             VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,        // VkStructureType sType;
3728             DE_NULL,                                    // const void* pNext;
3729             0u,                                         // VkImageCreateFlags flags;
3730             VK_IMAGE_TYPE_2D,                           // VkImageType imageType;
3731             m_colorFormat,                              // VkFormat format;
3732             {m_textureSize.x(), m_textureSize.y(), 1u}, // VkExtent3D extent;
3733             1u,                                         // uint32_t mipLevels;
3734             1u,                                         // uint32_t arrayLayers;
3735             VK_SAMPLE_COUNT_1_BIT,                      // VkSampleCountFlagBits samples;
3736             VK_IMAGE_TILING_OPTIMAL,                    // VkImageTiling tiling;
3737             usageFlags,                                 // VkImageUsageFlags usage;
3738             VK_SHARING_MODE_EXCLUSIVE,                  // VkSharingMode sharingMode;
3739             1u,                                         // uint32_t queueFamilyIndexCount;
3740             &m_queueFamilyIndex,                        // const uint32_t* pQueueFamilyIndices;
3741             VK_IMAGE_LAYOUT_UNDEFINED                   // VkImageLayout initialLayout;
3742         };
3743 
3744         m_inputImages.push_back(VkImageSp(new Unique<VkImage>(createImage(m_vkd, *m_device, &inputImageParams))));
3745 
3746         // Allocate and bind image memory
3747         m_inputImageAllocs.push_back(AllocationSp(
3748             m_allocator
3749                 .allocate(getImageMemoryRequirements(m_vkd, *m_device, **m_inputImages.back()), MemoryRequirement::Any)
3750                 .release()));
3751         VK_CHECK(m_vkd.bindImageMemory(*m_device, **m_inputImages.back(), m_inputImageAllocs.back()->getMemory(),
3752                                        m_inputImageAllocs.back()->getOffset()));
3753     }
3754 
3755     // Create texture image views
3756     for (uint32_t imageIdx = 0; imageIdx < 2; imageIdx++)
3757     {
3758         const VkImageViewCreateInfo textureViewParams = {
3759             VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,   // VkStructureType sType;
3760             DE_NULL,                                    // const void* pNext;
3761             0u,                                         // VkImageViewCreateFlags flags;
3762             **m_inputImages[imageIdx],                  // VkImage image;
3763             VK_IMAGE_VIEW_TYPE_2D,                      // VkImageViewType viewType;
3764             m_colorFormat,                              // VkFormat format;
3765             componentMappingRGBA,                       // VkChannelMapping channels;
3766             {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u} // VkImageSubresourceRange subresourceRange;
3767         };
3768 
3769         m_inputImageViews.push_back(
3770             VkImageViewSp(new Unique<VkImageView>(createImageView(m_vkd, *m_device, &textureViewParams))));
3771     }
3772 
3773     VkClearValue clearValues[2];
3774     clearValues[0].color.float32[0] = 0.0f;
3775     clearValues[0].color.float32[1] = 1.0f;
3776     clearValues[0].color.float32[2] = 0.0f;
3777     clearValues[0].color.float32[3] = 1.0f;
3778     clearValues[1].color.float32[0] = 1.0f;
3779     clearValues[1].color.float32[1] = 0.0f;
3780     clearValues[1].color.float32[2] = 0.0f;
3781     clearValues[1].color.float32[3] = 1.0f;
3782 
3783     // Clear input images
3784     for (uint32_t imageIdx = 0; imageIdx < 2; imageIdx++)
3785     {
3786         const VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
3787         Move<VkCommandPool> cmdPool;
3788         Move<VkCommandBuffer> cmdBuffer;
3789         const VkAccessFlags accessFlags = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
3790 
3791         cmdPool   = createCommandPool(m_vkd, *m_device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, m_queueFamilyIndex);
3792         cmdBuffer = allocateCommandBuffer(m_vkd, *m_device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
3793 
3794         const VkImageMemoryBarrier preImageBarrier = {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
3795                                                       DE_NULL,                                // const void* pNext;
3796                                                       0u,                           // VkAccessFlags srcAccessMask;
3797                                                       VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask;
3798                                                       VK_IMAGE_LAYOUT_UNDEFINED,    // VkImageLayout oldLayout;
3799                                                       VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout;
3800                                                       VK_QUEUE_FAMILY_IGNORED,   // uint32_t srcQueueFamilyIndex;
3801                                                       VK_QUEUE_FAMILY_IGNORED,   // uint32_t dstQueueFamilyIndex;
3802                                                       **m_inputImages[imageIdx], // VkImage image;
3803                                                       {
3804                                                           // VkImageSubresourceRange subresourceRange;
3805                                                           aspectMask, // VkImageAspect aspect;
3806                                                           0u,         // uint32_t baseMipLevel;
3807                                                           1u,         // uint32_t mipLevels;
3808                                                           0u,         // uint32_t baseArraySlice;
3809                                                           1u          // uint32_t arraySize;
3810                                                       }};
3811 
3812         const VkImageMemoryBarrier postImageBarrier = {
3813             VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,   // VkStructureType sType;
3814             DE_NULL,                                  // const void* pNext;
3815             VK_ACCESS_TRANSFER_WRITE_BIT,             // VkAccessFlags srcAccessMask;
3816             accessFlags,                              // VkAccessFlags dstAccessMask;
3817             VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,     // VkImageLayout oldLayout;
3818             VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // VkImageLayout newLayout;
3819             VK_QUEUE_FAMILY_IGNORED,                  // uint32_t srcQueueFamilyIndex;
3820             VK_QUEUE_FAMILY_IGNORED,                  // uint32_t dstQueueFamilyIndex;
3821             **m_inputImages[imageIdx],                // VkImage image;
3822             {
3823                 // VkImageSubresourceRange subresourceRange;
3824                 aspectMask, // VkImageAspect aspect;
3825                 0u,         // uint32_t baseMipLevel;
3826                 1u,         // uint32_t mipLevels;
3827                 0u,         // uint32_t baseArraySlice;
3828                 1u          // uint32_t arraySize;
3829             }};
3830 
3831         const VkImageSubresourceRange clearRange = {
3832             aspectMask, // VkImageAspectFlags aspectMask;
3833             0u,         // uint32_t baseMipLevel;
3834             1u,         // uint32_t levelCount;
3835             0u,         // uint32_t baseArrayLayer;
3836             1u          // uint32_t layerCount;
3837         };
3838 
3839         beginCommandBuffer(m_vkd, *cmdBuffer);
3840         m_vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
3841                                  (VkDependencyFlags)0, 0, (const VkMemoryBarrier *)DE_NULL, 0,
3842                                  (const VkBufferMemoryBarrier *)DE_NULL, 1, &preImageBarrier);
3843         m_vkd.cmdClearColorImage(*cmdBuffer, **m_inputImages[imageIdx], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
3844                                  &clearValues[imageIdx].color, 1, &clearRange);
3845         m_vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
3846                                  (VkDependencyFlags)0, 0, (const VkMemoryBarrier *)DE_NULL, 0,
3847                                  (const VkBufferMemoryBarrier *)DE_NULL, 1, &postImageBarrier);
3848         endCommandBuffer(m_vkd, *cmdBuffer);
3849 
3850         submitCommandsAndWait(m_vkd, *m_device, m_queue, cmdBuffer.get());
3851     }
3852 
3853     // Create render passes
3854     for (uint32_t renderPassIdx = 0; renderPassIdx < 2; renderPassIdx++)
3855     {
3856         // The first pass clears the output image, and the second one draws on top of the first pass.
3857         const VkAttachmentLoadOp loadOps[] = {VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_LOAD_OP_LOAD};
3858 
3859         const VkImageLayout initialLayouts[] = {VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
3860 
3861         const VkAttachmentDescription attachmentDescriptions[] = {
3862             // Result attachment
3863             {
3864                 (VkAttachmentDescriptionFlags)0,         // VkAttachmentDescriptionFlags    flags
3865                 VK_FORMAT_R8G8B8A8_UNORM,                // VkFormat                        format
3866                 VK_SAMPLE_COUNT_1_BIT,                   // VkSampleCountFlagBits        samples
3867                 loadOps[renderPassIdx],                  // VkAttachmentLoadOp            loadOp
3868                 VK_ATTACHMENT_STORE_OP_STORE,            // VkAttachmentStoreOp            storeOp
3869                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,         // VkAttachmentLoadOp            stencilLoadOp
3870                 VK_ATTACHMENT_STORE_OP_DONT_CARE,        // VkAttachmentStoreOp            stencilStoreOp
3871                 initialLayouts[renderPassIdx],           // VkImageLayout                initialLayout
3872                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout                finalLayout
3873             },
3874             // Input attachment
3875             {
3876                 (VkAttachmentDescriptionFlags)0,          // VkAttachmentDescriptionFlags    flags
3877                 VK_FORMAT_R8G8B8A8_UNORM,                 // VkFormat                        format
3878                 VK_SAMPLE_COUNT_1_BIT,                    // VkSampleCountFlagBits        samples
3879                 VK_ATTACHMENT_LOAD_OP_LOAD,               // VkAttachmentLoadOp            loadOp
3880                 VK_ATTACHMENT_STORE_OP_STORE,             // VkAttachmentStoreOp            storeOp
3881                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,          // VkAttachmentLoadOp            stencilLoadOp
3882                 VK_ATTACHMENT_STORE_OP_DONT_CARE,         // VkAttachmentStoreOp            stencilStoreOp
3883                 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // VkImageLayout                initialLayout
3884                 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL  // VkImageLayout                finalLayout
3885             }};
3886 
3887         const VkAttachmentReference resultAttachmentRef = {
3888             0u,                                      // uint32_t            attachment
3889             VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout    layout
3890         };
3891 
3892         const VkAttachmentReference inputAttachmentRef = {
3893             1u,                                      // uint32_t            attachment
3894             VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL // VkImageLayout    layout
3895         };
3896 
3897         const VkSubpassDescription subpassDescription = {
3898             (VkSubpassDescriptionFlags)0,    // VkSubpassDescriptionFlags    flags
3899             VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint            pipelineBindPoint
3900             1u,                              // uint32_t                        inputAttachmentCount
3901             &inputAttachmentRef,             // const VkAttachmentReference*    pInputAttachments
3902             1u,                              // uint32_t                        colorAttachmentCount
3903             &resultAttachmentRef,            // const VkAttachmentReference*    pColorAttachments
3904             DE_NULL,                         // const VkAttachmentReference*    pResolveAttachments
3905             DE_NULL,                         // const VkAttachmentReference*    pDepthStencilAttachment
3906             0u,                              // uint32_t                        preserveAttachmentCount
3907             DE_NULL                          // const uint32_t*                pPreserveAttachments
3908         };
3909 
3910         const VkSubpassDependency subpassDependency = {
3911             VK_SUBPASS_EXTERNAL,                                             // uint32_t                srcSubpass
3912             0,                                                               // uint32_t                dstSubpass
3913             VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,                   // VkPipelineStageFlags    srcStageMask
3914             VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,                           // VkPipelineStageFlags    dstStageMask
3915             VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,                            // VkAccessFlags        srcAccessMask
3916             VK_ACCESS_INPUT_ATTACHMENT_READ_BIT | VK_ACCESS_SHADER_READ_BIT, //    dstAccessMask
3917             VK_DEPENDENCY_BY_REGION_BIT                                      // VkDependencyFlags    dependencyFlags
3918         };
3919 
3920         const VkRenderPassCreateInfo renderPassInfo = {
3921             VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureTypei                    sType
3922             DE_NULL,                                   // const void*                        pNext
3923             (VkRenderPassCreateFlags)0,                // VkRenderPassCreateFlags            flags
3924             2u,                                        // uint32_t                            attachmentCount
3925             attachmentDescriptions,                    // const VkAttachmentDescription*    pAttachments
3926             1u,                                        // uint32_t                            subpassCount
3927             &subpassDescription,                       // const VkSubpassDescription*        pSubpasses
3928             1u,                                        // uint32_t                            dependencyCount
3929             &subpassDependency                         // const VkSubpassDependency*        pDependencies
3930         };
3931 
3932         m_renderPasses.push_back(VkRenderPassSp(
3933             new RenderPassWrapper(m_params.pipelineConstructionType, m_vkd, *m_device, &renderPassInfo)));
3934 
3935         std::vector<VkImage> images = {
3936             *m_colorImage,
3937             **m_inputImages[renderPassIdx],
3938         };
3939 
3940         const VkImageView attachmentBindInfos[] = {
3941             *m_colorAttachmentView,
3942             **m_inputImageViews[renderPassIdx],
3943         };
3944 
3945         const VkFramebufferCreateInfo framebufferParams = {
3946             VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
3947             DE_NULL,                                   // const void* pNext;
3948             0u,                                        // VkFramebufferCreateFlags flags;
3949             **m_renderPasses[renderPassIdx],           // VkRenderPass renderPass;
3950             2u,                                        // uint32_t attachmentCount;
3951             attachmentBindInfos,                       // const VkImageView* pAttachments;
3952             (uint32_t)m_renderSize.x(),                // uint32_t width;
3953             (uint32_t)m_renderSize.y(),                // uint32_t height;
3954             1u                                         // uint32_t layers;
3955         };
3956 
3957         m_renderPasses[renderPassIdx]->createFramebuffer(m_vkd, *m_device, &framebufferParams, images);
3958     }
3959 
3960     // Create pipeline layout
3961     {
3962         // Create descriptor set layout
3963         const VkDescriptorSetLayoutBinding descriptorSetLayoutBinding = {
3964             m_params.binding,                    // uint32_t binding;
3965             VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, // VkDescriptorType descriptorType;
3966             1u,                                  // uint32_t descriptorCount;
3967             VK_SHADER_STAGE_FRAGMENT_BIT,        // VkShaderStageFlags stageFlags;
3968             DE_NULL                              // const VkSampler* pImmutableSamplers;
3969         };
3970 
3971         const VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {
3972             VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,     // VkStructureType sType;
3973             DE_NULL,                                                 // const void* pNext;
3974             VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR, // VkDescriptorSetLayoutCreateFlags flags;
3975             1u,                                                      // uint32_t bindingCount;
3976             &descriptorSetLayoutBinding                              // const VkDescriptorSetLayoutBinding* pBindings;
3977         };
3978 
3979         m_descriptorSetLayout = createDescriptorSetLayout(m_vkd, *m_device, &descriptorSetLayoutCreateInfo, DE_NULL);
3980 
3981         // Create pipeline layout
3982         VkPipelineLayoutCreateFlags pipelineLayoutFlags =
3983             (m_params.pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC) ?
3984                 0u :
3985                 uint32_t(VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT);
3986         VkPipelineLayoutCreateInfo pipelineLayoutParams{
3987             VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
3988             DE_NULL,                                       // const void* pNext;
3989             pipelineLayoutFlags,                           // VkPipelineLayoutCreateFlags flags;
3990             0u,                                            // uint32_t setLayoutCount;
3991             DE_NULL,                                       // const VkDescriptorSetLayout* pSetLayouts;
3992             0u,                                            // uint32_t pushConstantRangeCount;
3993             DE_NULL                                        // const VkPushDescriptorRange* pPushDescriptorRanges;
3994         };
3995 
3996         m_preRasterizationStatePipelineLayout =
3997             PipelineLayoutWrapper(m_params.pipelineConstructionType, m_vkd, *m_device, &pipelineLayoutParams);
3998         pipelineLayoutParams.setLayoutCount = 1u;
3999         pipelineLayoutParams.pSetLayouts    = &(*m_descriptorSetLayout);
4000         m_fragmentStatePipelineLayout =
4001             PipelineLayoutWrapper(m_params.pipelineConstructionType, m_vkd, *m_device, &pipelineLayoutParams);
4002     }
4003 
4004     // Create shaders
4005     {
4006         m_vertexShaderModule   = ShaderWrapper(m_vkd, *m_device, m_context.getBinaryCollection().get("vert"), 0u);
4007         m_fragmentShaderModule = ShaderWrapper(m_vkd, *m_device, m_context.getBinaryCollection().get("frag"), 0u);
4008     }
4009 
4010     m_graphicsPipelines.reserve(2);
4011 
4012     // Create pipelines
4013     for (uint32_t pipelineIdx = 0; pipelineIdx < 2; pipelineIdx++)
4014     {
4015         const VkVertexInputBindingDescription vertexInputBindingDescription = {
4016             0u,                         // uint32_t binding;
4017             sizeof(Vertex4Tex4),        // uint32_t strideInBytes;
4018             VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate stepRate;
4019         };
4020 
4021         const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] = {
4022             {
4023                 0u,                            // uint32_t location;
4024                 0u,                            // uint32_t binding;
4025                 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
4026                 0u                             // uint32_t offsetInBytes;
4027             },
4028             {
4029                 1u,                              // uint32_t location;
4030                 0u,                              // uint32_t binding;
4031                 VK_FORMAT_R32G32B32A32_SFLOAT,   // VkFormat format;
4032                 offsetof(Vertex4Tex4, texCoord), // uint32_t offset;
4033             }};
4034 
4035         const VkPipelineVertexInputStateCreateInfo vertexInputStateParams = {
4036             VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
4037             DE_NULL,                                                   // const void* pNext;
4038             0u,                                                        // vkPipelineVertexInputStateCreateFlags flags;
4039             1u,                                                        // uint32_t bindingCount;
4040             &vertexInputBindingDescription,  // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
4041             2u,                              // uint32_t attributeCount;
4042             vertexInputAttributeDescriptions // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
4043         };
4044 
4045         const vector<VkViewport> viewports{makeViewport(m_renderSize)};
4046         const vector<VkRect2D> scissors{makeRect2D(m_renderSize)};
4047 
4048         m_graphicsPipelines.emplace_back(m_vki, m_vkd, m_physicalDevice, *m_device, m_deviceEnabledExtensions,
4049                                          m_params.pipelineConstructionType);
4050         m_graphicsPipelines.back()
4051             .setMonolithicPipelineLayout(m_fragmentStatePipelineLayout)
4052             .setDefaultRasterizationState()
4053             .setDefaultDepthStencilState()
4054             .setDefaultMultisampleState()
4055             .setDefaultColorBlendState()
4056             .setupVertexInputState(&vertexInputStateParams)
4057             .setupPreRasterizationShaderState(viewports, scissors, m_preRasterizationStatePipelineLayout,
4058                                               **m_renderPasses[pipelineIdx], 0u, m_vertexShaderModule)
4059             .setupFragmentShaderState(m_fragmentStatePipelineLayout, **m_renderPasses[pipelineIdx], 0u,
4060                                       m_fragmentShaderModule)
4061             .setupFragmentOutputState(**m_renderPasses[pipelineIdx])
4062             .buildPipeline();
4063     }
4064 
4065     // Create vertex buffer
4066     {
4067         const VkBufferCreateInfo vertexBufferParams = {
4068             VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,                    // VkStructureType sType;
4069             DE_NULL,                                                 // const void* pNext;
4070             0u,                                                      // VkBufferCreateFlags flags;
4071             (VkDeviceSize)(sizeof(Vertex4RGBA) * m_vertices.size()), // VkDeviceSize size;
4072             VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,                       // VkBufferUsageFlags usage;
4073             VK_SHARING_MODE_EXCLUSIVE,                               // VkSharingMode sharingMode;
4074             1u,                                                      // uint32_t queueFamilyCount;
4075             &m_queueFamilyIndex                                      // const uint32_t* pQueueFamilyIndices;
4076         };
4077 
4078         m_vertexBuffer      = createBuffer(m_vkd, *m_device, &vertexBufferParams);
4079         m_vertexBufferAlloc = m_allocator.allocate(getBufferMemoryRequirements(m_vkd, *m_device, *m_vertexBuffer),
4080                                                    MemoryRequirement::HostVisible);
4081 
4082         VK_CHECK(m_vkd.bindBufferMemory(*m_device, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(),
4083                                         m_vertexBufferAlloc->getOffset()));
4084 
4085         // Load vertices into vertex buffer
4086         deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4Tex4));
4087         flushAlloc(m_vkd, *m_device, *m_vertexBufferAlloc);
4088     }
4089 
4090     // Create command pool
4091     m_cmdPool = createCommandPool(m_vkd, *m_device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, m_queueFamilyIndex);
4092 
4093     // Create command buffer
4094     {
4095         const VkClearValue attachmentClearValue = defaultClearValue(m_colorFormat);
4096         const VkDeviceSize vertexBufferOffset   = 0;
4097 
4098         m_cmdBuffer = allocateCommandBuffer(m_vkd, *m_device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
4099         beginCommandBuffer(m_vkd, *m_cmdBuffer, 0u);
4100         for (uint32_t quadNdx = 0; quadNdx < m_params.numCalls; quadNdx++)
4101         {
4102             (*m_renderPasses[quadNdx])
4103                 .begin(m_vkd, *m_cmdBuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), attachmentClearValue);
4104             m_graphicsPipelines[quadNdx].bind(*m_cmdBuffer);
4105             m_vkd.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
4106 
4107             VkDescriptorImageInfo descriptorImageInfo = {
4108                 0,                                       // VkSampler sampler;
4109                 **m_inputImageViews[quadNdx],            // VkImageView imageView;
4110                 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL // VkImageLayout imageLayout;
4111             };
4112 
4113             VkWriteDescriptorSet writeDescriptorSet = {
4114                 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // VkStructureType sType;
4115                 DE_NULL,                                // const void* pNext;
4116                 0u,                                     // VkDescriptorSet dstSet;
4117                 m_params.binding,                       // uint32_t dstBinding;
4118                 0u,                                     // uint32_t dstArrayElement;
4119                 1u,                                     // uint32_t descriptorCount;
4120                 m_params.descriptorType,                // VkDescriptorType descriptorType;
4121                 &descriptorImageInfo,                   // const VkDescriptorImageInfo* pImageInfo;
4122                 DE_NULL,                                // const VkDescriptorBufferInfo* pBufferInfo;
4123                 DE_NULL                                 // const VkBufferView* pTexelBufferView;
4124             };
4125 
4126             m_vkd.cmdPushDescriptorSetKHR(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_fragmentStatePipelineLayout,
4127                                           0, 1, &writeDescriptorSet);
4128             m_vkd.cmdDraw(*m_cmdBuffer, 6, 1, 6 * quadNdx, 0);
4129 
4130             (*m_renderPasses[quadNdx]).end(m_vkd, *m_cmdBuffer);
4131         }
4132 
4133         endCommandBuffer(m_vkd, *m_cmdBuffer);
4134     }
4135 }
4136 
~PushDescriptorInputAttachmentGraphicsTestInstance(void)4137 PushDescriptorInputAttachmentGraphicsTestInstance::~PushDescriptorInputAttachmentGraphicsTestInstance(void)
4138 {
4139 }
4140 
iterate(void)4141 tcu::TestStatus PushDescriptorInputAttachmentGraphicsTestInstance::iterate(void)
4142 {
4143     init();
4144 
4145     submitCommandsAndWait(m_vkd, *m_device, m_queue, m_cmdBuffer.get());
4146 
4147     return verifyImage();
4148 }
4149 
verifyImage(void)4150 tcu::TestStatus PushDescriptorInputAttachmentGraphicsTestInstance::verifyImage(void)
4151 {
4152     const tcu::TextureFormat tcuColorFormat = mapVkFormat(m_colorFormat);
4153     const tcu::TextureFormat tcuDepthFormat = tcu::TextureFormat();
4154     const ColorVertexShader vertexShader;
4155     const ColorFragmentShader fragmentShader(tcuColorFormat, tcuDepthFormat);
4156     const rr::Program program(&vertexShader, &fragmentShader);
4157     ReferenceRenderer refRenderer(m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuDepthFormat, &program);
4158     bool compareOk = false;
4159 
4160     // Render reference image
4161     {
4162         vector<Vertex4RGBA> refQuads = createQuads(m_params.numCalls, 0.25f);
4163         tcu::Vec4 colors[2];
4164 
4165         colors[0] = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
4166         colors[1] = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
4167 
4168         for (uint32_t quadIdx = 0; quadIdx < m_params.numCalls; quadIdx++)
4169             for (uint32_t vertexIdx = 0; vertexIdx < 6; vertexIdx++)
4170             {
4171                 const uint32_t idx         = quadIdx * 6 + vertexIdx;
4172                 refQuads[idx].color.xyzw() = colors[quadIdx];
4173             }
4174 
4175         refRenderer.draw(rr::RenderState(refRenderer.getViewportState(),
4176                                          m_context.getDeviceProperties().limits.subPixelPrecisionBits),
4177                          rr::PRIMITIVETYPE_TRIANGLES, refQuads);
4178     }
4179 
4180     // Compare result with reference image
4181     {
4182         de::MovePtr<tcu::TextureLevel> result = readColorAttachment(
4183             m_vkd, *m_device, m_queue, m_queueFamilyIndex, m_allocator, *m_colorImage, m_colorFormat, m_renderSize);
4184 
4185         compareOk = tcu::intThresholdPositionDeviationCompare(
4186             m_context.getTestContext().getLog(), "IntImageCompare", "Image comparison", refRenderer.getAccess(),
4187             result->getAccess(), tcu::UVec4(2, 2, 2, 2), tcu::IVec3(1, 1, 0), true, tcu::COMPARE_LOG_RESULT);
4188     }
4189 
4190     if (compareOk)
4191         return tcu::TestStatus::pass("Result image matches reference");
4192     else
4193         return tcu::TestStatus::fail("Image mismatch");
4194 }
4195 
4196 class PushDescriptorInputAttachmentGraphicsTest : public vkt::TestCase
4197 {
4198 public:
4199     PushDescriptorInputAttachmentGraphicsTest(tcu::TestContext &testContext, const string &name,
4200                                               const TestParams &params);
4201     ~PushDescriptorInputAttachmentGraphicsTest(void);
4202 
4203     void checkSupport(Context &context) const;
4204     void initPrograms(SourceCollections &sourceCollections) const;
4205     TestInstance *createInstance(Context &context) const;
4206 
4207 protected:
4208     const TestParams m_params;
4209 };
4210 
PushDescriptorInputAttachmentGraphicsTest(tcu::TestContext & testContext,const string & name,const TestParams & params)4211 PushDescriptorInputAttachmentGraphicsTest::PushDescriptorInputAttachmentGraphicsTest(tcu::TestContext &testContext,
4212                                                                                      const string &name,
4213                                                                                      const TestParams &params)
4214     : vkt::TestCase(testContext, name)
4215     , m_params(params)
4216 {
4217 }
4218 
~PushDescriptorInputAttachmentGraphicsTest(void)4219 PushDescriptorInputAttachmentGraphicsTest::~PushDescriptorInputAttachmentGraphicsTest(void)
4220 {
4221 }
4222 
createInstance(Context & context) const4223 TestInstance *PushDescriptorInputAttachmentGraphicsTest::createInstance(Context &context) const
4224 {
4225     return new PushDescriptorInputAttachmentGraphicsTestInstance(context, m_params);
4226 }
4227 
checkSupport(Context & context) const4228 void PushDescriptorInputAttachmentGraphicsTest::checkSupport(Context &context) const
4229 {
4230     checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(),
4231                                           m_params.pipelineConstructionType);
4232 }
4233 
initPrograms(SourceCollections & sourceCollections) const4234 void PushDescriptorInputAttachmentGraphicsTest::initPrograms(SourceCollections &sourceCollections) const
4235 {
4236     const string vertexSrc = "#version 450\n"
4237                              "layout(location = 0) in highp vec4 position;\n"
4238                              "layout(location = 1) in highp vec4 texcoordVtx;\n"
4239                              "layout(location = 0) out highp vec2 texcoordFrag;\n"
4240                              "\n"
4241                              "out gl_PerVertex { vec4 gl_Position; };\n"
4242                              "\n"
4243                              "void main()\n"
4244                              "{\n"
4245                              "    gl_Position = position;\n"
4246                              "    texcoordFrag = texcoordVtx.xy;\n"
4247                              "}\n";
4248 
4249     sourceCollections.glslSources.add("vert") << glu::VertexSource(vertexSrc);
4250 
4251     const string fragmentSrc = "#version 450\n"
4252                                "layout(location = 0) in highp vec2 texcoordFrag;\n"
4253                                "layout(location = 0) out highp vec4 fragColor;\n"
4254                                "layout(input_attachment_index = 0, set = 0, binding = " +
4255                                de::toString(m_params.binding) +
4256                                ") uniform subpassInput inputColor;\n"
4257                                "\n"
4258                                "void main (void)\n"
4259                                "{\n"
4260                                "    fragColor = subpassLoad(inputColor);\n"
4261                                "}\n";
4262 
4263     sourceCollections.glslSources.add("frag") << glu::FragmentSource(fragmentSrc);
4264 }
4265 
4266 } // namespace
4267 
createPushDescriptorTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineType)4268 tcu::TestCaseGroup *createPushDescriptorTests(tcu::TestContext &testCtx, PipelineConstructionType pipelineType)
4269 {
4270     const TestParams params[]{{pipelineType, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0u, 1u, false},
4271                               {pipelineType, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0u, 2u, false},
4272                               {pipelineType, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u, 2u, false},
4273                               {pipelineType, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 3u, 2u, false},
4274                               {pipelineType, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 0u, 1u, false},
4275                               {pipelineType, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 0u, 2u, false},
4276                               {pipelineType, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u, 2u, false},
4277                               {pipelineType, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 3u, 2u, false},
4278                               {pipelineType, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u, 128u, false},
4279                               {pipelineType, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0u, 1u, false},
4280                               {pipelineType, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0u, 2u, false},
4281                               {pipelineType, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1u, 2u, false},
4282                               {pipelineType, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 3u, 2u, false},
4283                               {pipelineType, VK_DESCRIPTOR_TYPE_SAMPLER, 0u, 1u, false},
4284                               {pipelineType, VK_DESCRIPTOR_TYPE_SAMPLER, 0u, 2u, false},
4285                               {pipelineType, VK_DESCRIPTOR_TYPE_SAMPLER, 1u, 2u, false},
4286                               {pipelineType, VK_DESCRIPTOR_TYPE_SAMPLER, 3u, 2u, false},
4287                               {pipelineType, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 0u, 1u, false},
4288                               {pipelineType, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 0u, 2u, false},
4289                               {pipelineType, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1u, 2u, false},
4290                               {pipelineType, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 3u, 2u, false},
4291                               {pipelineType, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 0u, 1u, false},
4292                               {pipelineType, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 0u, 2u, false},
4293                               {pipelineType, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1u, 2u, false},
4294                               {pipelineType, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 3u, 2u, false},
4295                               {pipelineType, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 0u, 1u, false},
4296                               {pipelineType, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 0u, 2u, false},
4297                               {pipelineType, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1u, 2u, false},
4298                               {pipelineType, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 3u, 2u, false},
4299                               {pipelineType, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 0u, 1u, false},
4300                               {pipelineType, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 0u, 2u, false},
4301                               {pipelineType, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1u, 2u, false},
4302                               {pipelineType, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 3u, 2u, false},
4303                               {pipelineType, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 0u, 1u, false},
4304                               {pipelineType, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 0u, 2u, false},
4305                               {pipelineType, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1u, 2u, false},
4306                               {pipelineType, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 3u, 2u, false}};
4307 
4308     de::MovePtr<tcu::TestCaseGroup> pushDescriptorTests(new tcu::TestCaseGroup(testCtx, "push_descriptor"));
4309 
4310     de::MovePtr<tcu::TestCaseGroup> graphicsTests(new tcu::TestCaseGroup(testCtx, "graphics"));
4311     de::MovePtr<tcu::TestCaseGroup> computeTests(new tcu::TestCaseGroup(testCtx, "compute"));
4312 
4313     for (uint32_t testIdx = 0; testIdx < DE_LENGTH_OF_ARRAY(params); testIdx++)
4314     {
4315         string testName;
4316         testName +=
4317             "binding" + de::toString(params[testIdx].binding) + "_numcalls" + de::toString(params[testIdx].numCalls);
4318         switch (params[testIdx].descriptorType)
4319         {
4320         case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
4321             testName += "_uniform_buffer";
4322             if (params[testIdx].numCalls <= 2)
4323                 graphicsTests->addChild(
4324                     new PushDescriptorBufferGraphicsTest(testCtx, testName.c_str(), params[testIdx]));
4325             if (pipelineType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
4326                 computeTests->addChild(new PushDescriptorBufferComputeTest(testCtx, testName.c_str(), params[testIdx]));
4327             break;
4328 
4329         case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
4330             testName += "_storage_buffer";
4331             if (params[testIdx].numCalls <= 2)
4332                 graphicsTests->addChild(
4333                     new PushDescriptorBufferGraphicsTest(testCtx, testName.c_str(), params[testIdx]));
4334             if (pipelineType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
4335                 computeTests->addChild(new PushDescriptorBufferComputeTest(testCtx, testName.c_str(), params[testIdx]));
4336             break;
4337 
4338         case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
4339             testName += "_combined_image_sampler";
4340             graphicsTests->addChild(new PushDescriptorImageGraphicsTest(testCtx, testName.c_str(), params[testIdx]));
4341             if (pipelineType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
4342                 computeTests->addChild(new PushDescriptorImageComputeTest(testCtx, testName.c_str(), params[testIdx]));
4343             break;
4344 
4345         case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
4346             testName += "_sampled_image";
4347             graphicsTests->addChild(new PushDescriptorImageGraphicsTest(testCtx, testName.c_str(), params[testIdx]));
4348             if (pipelineType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
4349                 computeTests->addChild(new PushDescriptorImageComputeTest(testCtx, testName.c_str(), params[testIdx]));
4350             break;
4351 
4352         case VK_DESCRIPTOR_TYPE_SAMPLER:
4353             testName += "_sampler";
4354             graphicsTests->addChild(new PushDescriptorImageGraphicsTest(testCtx, testName.c_str(), params[testIdx]));
4355             if (pipelineType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
4356                 computeTests->addChild(new PushDescriptorImageComputeTest(testCtx, testName.c_str(), params[testIdx]));
4357             break;
4358 
4359         case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
4360             testName += "_storage_image";
4361             graphicsTests->addChild(new PushDescriptorImageGraphicsTest(testCtx, testName.c_str(), params[testIdx]));
4362             if (pipelineType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
4363                 computeTests->addChild(new PushDescriptorImageComputeTest(testCtx, testName.c_str(), params[testIdx]));
4364             break;
4365 
4366         case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
4367             testName += "_uniform_texel_buffer";
4368             graphicsTests->addChild(
4369                 new PushDescriptorTexelBufferGraphicsTest(testCtx, testName.c_str(), params[testIdx]));
4370             if (pipelineType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
4371                 computeTests->addChild(
4372                     new PushDescriptorTexelBufferComputeTest(testCtx, testName.c_str(), params[testIdx]));
4373             break;
4374 
4375         case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
4376             testName += "_storage_texel_buffer";
4377             graphicsTests->addChild(
4378                 new PushDescriptorTexelBufferGraphicsTest(testCtx, testName.c_str(), params[testIdx]));
4379             if (pipelineType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
4380                 computeTests->addChild(
4381                     new PushDescriptorTexelBufferComputeTest(testCtx, testName.c_str(), params[testIdx]));
4382             break;
4383 
4384         case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
4385             // Input attachments are not supported with dynamic rendering
4386             if (!vk::isConstructionTypeShaderObject(pipelineType))
4387             {
4388                 testName += "_input_attachment";
4389                 graphicsTests->addChild(
4390                     new PushDescriptorInputAttachmentGraphicsTest(testCtx, testName.c_str(), params[testIdx]));
4391             }
4392             break;
4393 
4394         default:
4395             DE_FATAL("Unexpected descriptor type");
4396             break;
4397         }
4398     }
4399 
4400     if (pipelineType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
4401     {
4402         TestParams testParams = {pipelineType, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 0u, 1u, true};
4403         graphicsTests->addChild(
4404             new PushDescriptorTexelBufferGraphicsTest(testCtx, "maintenance5_uniform_texel_buffer", testParams));
4405         testParams.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
4406         graphicsTests->addChild(
4407             new PushDescriptorTexelBufferGraphicsTest(testCtx, "maintenance5_storage_texel_buffer", testParams));
4408         testParams.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
4409         graphicsTests->addChild(
4410             new PushDescriptorBufferGraphicsTest(testCtx, "maintenance5_uniform_buffer", testParams));
4411     }
4412 
4413     pushDescriptorTests->addChild(graphicsTests.release());
4414     if (pipelineType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
4415         pushDescriptorTests->addChild(computeTests.release());
4416 
4417     return pushDescriptorTests.release();
4418 }
4419 
4420 } // namespace pipeline
4421 } // namespace vkt
4422