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