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