Added test to stress semaphore chains
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / synchronization / vktSynchronizationUtil.cpp
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2016 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Synchronization tests utilities
22  *//*--------------------------------------------------------------------*/
23
24 #include "vktSynchronizationUtil.hpp"
25 #include "vkTypeUtil.hpp"
26 #include "deStringUtil.hpp"
27
28 namespace vkt
29 {
30 namespace synchronization
31 {
32 using namespace vk;
33
34 VkBufferCreateInfo makeBufferCreateInfo (const VkDeviceSize                     bufferSize,
35                                                                                  const VkBufferUsageFlags       usage)
36 {
37         const VkBufferCreateInfo bufferCreateInfo =
38         {
39                 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,   // VkStructureType              sType;
40                 DE_NULL,                                                                // const void*                  pNext;
41                 (VkBufferCreateFlags)0,                                 // VkBufferCreateFlags  flags;
42                 bufferSize,                                                             // VkDeviceSize                 size;
43                 usage,                                                                  // VkBufferUsageFlags   usage;
44                 VK_SHARING_MODE_EXCLUSIVE,                              // VkSharingMode                sharingMode;
45                 0u,                                                                             // deUint32                             queueFamilyIndexCount;
46                 DE_NULL,                                                                // const deUint32*              pQueueFamilyIndices;
47         };
48         return bufferCreateInfo;
49 }
50
51 VkMemoryBarrier makeMemoryBarrier (const VkAccessFlags  srcAccessMask,
52                                                                    const VkAccessFlags  dstAccessMask)
53 {
54         const VkMemoryBarrier barrier =
55         {
56                 VK_STRUCTURE_TYPE_MEMORY_BARRIER,       // VkStructureType    sType;
57                 DE_NULL,                                                        // const void*        pNext;
58                 srcAccessMask,                                          // VkAccessFlags      srcAccessMask;
59                 dstAccessMask,                                          // VkAccessFlags      dstAccessMask;
60         };
61         return barrier;
62 }
63
64 VkBufferMemoryBarrier makeBufferMemoryBarrier (const VkAccessFlags      srcAccessMask,
65                                                                                            const VkAccessFlags  dstAccessMask,
66                                                                                            const VkBuffer               buffer,
67                                                                                            const VkDeviceSize   offset,
68                                                                                            const VkDeviceSize   bufferSizeBytes)
69 {
70         const VkBufferMemoryBarrier barrier =
71         {
72                 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,        // VkStructureType      sType;
73                 DE_NULL,                                                                        // const void*          pNext;
74                 srcAccessMask,                                                          // VkAccessFlags        srcAccessMask;
75                 dstAccessMask,                                                          // VkAccessFlags        dstAccessMask;
76                 VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                     srcQueueFamilyIndex;
77                 VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                     destQueueFamilyIndex;
78                 buffer,                                                                         // VkBuffer                     buffer;
79                 offset,                                                                         // VkDeviceSize         offset;
80                 bufferSizeBytes,                                                        // VkDeviceSize         size;
81         };
82         return barrier;
83 }
84
85 VkImageMemoryBarrier makeImageMemoryBarrier     (const VkAccessFlags                    srcAccessMask,
86                                                                                          const VkAccessFlags                    dstAccessMask,
87                                                                                          const VkImageLayout                    oldLayout,
88                                                                                          const VkImageLayout                    newLayout,
89                                                                                          const VkImage                                  image,
90                                                                                          const VkImageSubresourceRange  subresourceRange)
91 {
92         const VkImageMemoryBarrier barrier =
93         {
94                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                 // VkStructureType                      sType;
95                 DE_NULL,                                                                                // const void*                          pNext;
96                 srcAccessMask,                                                                  // VkAccessFlags                        outputMask;
97                 dstAccessMask,                                                                  // VkAccessFlags                        inputMask;
98                 oldLayout,                                                                              // VkImageLayout                        oldLayout;
99                 newLayout,                                                                              // VkImageLayout                        newLayout;
100                 VK_QUEUE_FAMILY_IGNORED,                                                // deUint32                                     srcQueueFamilyIndex;
101                 VK_QUEUE_FAMILY_IGNORED,                                                // deUint32                                     destQueueFamilyIndex;
102                 image,                                                                                  // VkImage                                      image;
103                 subresourceRange,                                                               // VkImageSubresourceRange      subresourceRange;
104         };
105         return barrier;
106 }
107
108 Move<VkCommandBuffer> makeCommandBuffer (const DeviceInterface& vk, const VkDevice device, const VkCommandPool commandPool)
109 {
110         const VkCommandBufferAllocateInfo info =
111         {
112                 VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,         // VkStructureType              sType;
113                 DE_NULL,                                                                                        // const void*                  pNext;
114                 commandPool,                                                                            // VkCommandPool                commandPool;
115                 VK_COMMAND_BUFFER_LEVEL_PRIMARY,                                        // VkCommandBufferLevel level;
116                 1u,                                                                                                     // deUint32                             commandBufferCount;
117         };
118         return allocateCommandBuffer(vk, device, &info);
119 }
120
121 Move<VkDescriptorSet> makeDescriptorSet (const DeviceInterface&                 vk,
122                                                                                  const VkDevice                                 device,
123                                                                                  const VkDescriptorPool                 descriptorPool,
124                                                                                  const VkDescriptorSetLayout    setLayout)
125 {
126         const VkDescriptorSetAllocateInfo info =
127         {
128                 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,         // VkStructureType                              sType;
129                 DE_NULL,                                                                                        // const void*                                  pNext;
130                 descriptorPool,                                                                         // VkDescriptorPool                             descriptorPool;
131                 1u,                                                                                                     // deUint32                                             descriptorSetCount;
132                 &setLayout,                                                                                     // const VkDescriptorSetLayout* pSetLayouts;
133         };
134         return allocateDescriptorSet(vk, device, &info);
135 }
136
137 Move<VkPipelineLayout> makePipelineLayout (const DeviceInterface&               vk,
138                                                                                    const VkDevice                               device,
139                                                                                    const VkDescriptorSetLayout  descriptorSetLayout)
140 {
141         const VkPipelineLayoutCreateInfo info =
142         {
143                 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,          // VkStructureType                              sType;
144                 DE_NULL,                                                                                        // const void*                                  pNext;
145                 (VkPipelineLayoutCreateFlags)0,                                         // VkPipelineLayoutCreateFlags  flags;
146                 1u,                                                                                                     // deUint32                                             setLayoutCount;
147                 &descriptorSetLayout,                                                           // const VkDescriptorSetLayout* pSetLayouts;
148                 0u,                                                                                                     // deUint32                                             pushConstantRangeCount;
149                 DE_NULL,                                                                                        // const VkPushConstantRange*   pPushConstantRanges;
150         };
151         return createPipelineLayout(vk, device, &info);
152 }
153
154 Move<VkPipelineLayout> makePipelineLayoutWithoutDescriptors (const DeviceInterface&             vk,
155                                                                                                                          const VkDevice                         device)
156 {
157         const VkPipelineLayoutCreateInfo info =
158         {
159                 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,          // VkStructureType                              sType;
160                 DE_NULL,                                                                                        // const void*                                  pNext;
161                 (VkPipelineLayoutCreateFlags)0,                                         // VkPipelineLayoutCreateFlags  flags;
162                 0u,                                                                                                     // deUint32                                             setLayoutCount;
163                 DE_NULL,                                                                                        // const VkDescriptorSetLayout* pSetLayouts;
164                 0u,                                                                                                     // deUint32                                             pushConstantRangeCount;
165                 DE_NULL,                                                                                        // const VkPushConstantRange*   pPushConstantRanges;
166         };
167         return createPipelineLayout(vk, device, &info);
168 }
169
170 Move<VkPipeline> makeComputePipeline (const DeviceInterface&            vk,
171                                                                           const VkDevice                                device,
172                                                                           const VkPipelineLayout                pipelineLayout,
173                                                                           const VkShaderModule                  shaderModule,
174                                                                           const VkSpecializationInfo*   specInfo,
175                                                                           PipelineCacheData&                    pipelineCacheData)
176 {
177         const VkPipelineShaderStageCreateInfo shaderStageInfo =
178         {
179                 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,    // VkStructureType                                      sType;
180                 DE_NULL,                                                                                                // const void*                                          pNext;
181                 (VkPipelineShaderStageCreateFlags)0,                                    // VkPipelineShaderStageCreateFlags     flags;
182                 VK_SHADER_STAGE_COMPUTE_BIT,                                                    // VkShaderStageFlagBits                        stage;
183                 shaderModule,                                                                                   // VkShaderModule                                       module;
184                 "main",                                                                                                 // const char*                                          pName;
185                 specInfo,                                                                                               // const VkSpecializationInfo*          pSpecializationInfo;
186         };
187         const VkComputePipelineCreateInfo pipelineInfo =
188         {
189                 VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,         // VkStructureType                                      sType;
190                 DE_NULL,                                                                                        // const void*                                          pNext;
191                 (VkPipelineCreateFlags)0,                                                       // VkPipelineCreateFlags                        flags;
192                 shaderStageInfo,                                                                        // VkPipelineShaderStageCreateInfo      stage;
193                 pipelineLayout,                                                                         // VkPipelineLayout                                     layout;
194                 DE_NULL,                                                                                        // VkPipeline                                           basePipelineHandle;
195                 0,                                                                                                      // deInt32                                                      basePipelineIndex;
196         };
197
198         {
199                 const vk::Unique<vk::VkPipelineCache>   pipelineCache   (pipelineCacheData.createPipelineCache(vk, device));
200                 vk::Move<vk::VkPipeline>                                pipeline                (createComputePipeline(vk, device, *pipelineCache, &pipelineInfo));
201
202                 // Refresh data from cache
203                 pipelineCacheData.setFromPipelineCache(vk, device, *pipelineCache);
204
205                 return pipeline;
206         }
207 }
208
209 VkImageCreateInfo makeImageCreateInfo (const VkImageType imageType, const VkExtent3D& extent, const VkFormat format, const VkImageUsageFlags usage)
210 {
211         const VkImageCreateInfo imageInfo =
212         {
213                 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,            // VkStructureType          sType;
214                 DE_NULL,                                                                        // const void*              pNext;
215                 (VkImageCreateFlags)0,                                          // VkImageCreateFlags       flags;
216                 imageType,                                                                      // VkImageType              imageType;
217                 format,                                                                         // VkFormat                 format;
218                 extent,                                                                         // VkExtent3D               extent;
219                 1u,                                                                                     // uint32_t                 mipLevels;
220                 1u,                                                                                     // uint32_t                 arrayLayers;
221                 VK_SAMPLE_COUNT_1_BIT,                                          // VkSampleCountFlagBits    samples;
222                 VK_IMAGE_TILING_OPTIMAL,                                        // VkImageTiling            tiling;
223                 usage,                                                                          // VkImageUsageFlags        usage;
224                 VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode            sharingMode;
225                 0u,                                                                                     // uint32_t                 queueFamilyIndexCount;
226                 DE_NULL,                                                                        // const uint32_t*          pQueueFamilyIndices;
227                 VK_IMAGE_LAYOUT_UNDEFINED,                                      // VkImageLayout            initialLayout;
228         };
229         return imageInfo;
230 }
231
232 Move<VkImageView> makeImageView (const DeviceInterface&                 vk,
233                                                                  const VkDevice                                 device,
234                                                                  const VkImage                                  image,
235                                                                  const VkImageViewType                  viewType,
236                                                                  const VkFormat                                 format,
237                                                                  const VkImageSubresourceRange  subresourceRange)
238 {
239         const VkImageViewCreateInfo imageViewParams =
240         {
241                 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,               // VkStructureType                      sType;
242                 DE_NULL,                                                                                // const void*                          pNext;
243                 (VkImageViewCreateFlags)0,                                              // VkImageViewCreateFlags       flags;
244                 image,                                                                                  // VkImage                                      image;
245                 viewType,                                                                               // VkImageViewType                      viewType;
246                 format,                                                                                 // VkFormat                                     format;
247                 makeComponentMappingRGBA(),                                             // VkComponentMapping           components;
248                 subresourceRange,                                                               // VkImageSubresourceRange      subresourceRange;
249         };
250         return createImageView(vk, device, &imageViewParams);
251 }
252
253 VkBufferImageCopy makeBufferImageCopy (const VkImageSubresourceLayers   subresourceLayers,
254                                                                            const VkExtent3D                                     extent)
255 {
256         const VkBufferImageCopy copyParams =
257         {
258                 0ull,                                                                           //      VkDeviceSize                            bufferOffset;
259                 0u,                                                                                     //      deUint32                                        bufferRowLength;
260                 0u,                                                                                     //      deUint32                                        bufferImageHeight;
261                 subresourceLayers,                                                      //      VkImageSubresourceLayers        imageSubresource;
262                 makeOffset3D(0, 0, 0),                                          //      VkOffset3D                                      imageOffset;
263                 extent,                                                                         //      VkExtent3D                                      imageExtent;
264         };
265         return copyParams;
266 }
267
268 void beginCommandBuffer (const DeviceInterface& vk, const VkCommandBuffer commandBuffer)
269 {
270         const VkCommandBufferBeginInfo info =
271         {
272                 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,    // VkStructureType                          sType;
273                 DE_NULL,                                                                                // const void*                              pNext;
274                 VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,    // VkCommandBufferUsageFlags                flags;
275                 DE_NULL,                                                                                // const VkCommandBufferInheritanceInfo*    pInheritanceInfo;
276         };
277         VK_CHECK(vk.beginCommandBuffer(commandBuffer, &info));
278 }
279
280 void endCommandBuffer (const DeviceInterface& vk, const VkCommandBuffer commandBuffer)
281 {
282         VK_CHECK(vk.endCommandBuffer(commandBuffer));
283 }
284
285 void submitCommandsAndWait (const DeviceInterface&      vk,
286                                                         const VkDevice                  device,
287                                                         const VkQueue                   queue,
288                                                         const VkCommandBuffer   commandBuffer)
289 {
290         const Unique<VkFence> fence(createFence(vk, device));
291
292         const VkSubmitInfo submitInfo =
293         {
294                 VK_STRUCTURE_TYPE_SUBMIT_INFO,          // VkStructureType                sType;
295                 DE_NULL,                                                        // const void*                    pNext;
296                 0u,                                                                     // uint32_t                       waitSemaphoreCount;
297                 DE_NULL,                                                        // const VkSemaphore*             pWaitSemaphores;
298                 DE_NULL,                                                        // const VkPipelineStageFlags*    pWaitDstStageMask;
299                 1u,                                                                     // uint32_t                       commandBufferCount;
300                 &commandBuffer,                                         // const VkCommandBuffer*         pCommandBuffers;
301                 0u,                                                                     // uint32_t                       signalSemaphoreCount;
302                 DE_NULL,                                                        // const VkSemaphore*             pSignalSemaphores;
303         };
304         VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence));
305         VK_CHECK(vk.waitForFences(device, 1u, &fence.get(), DE_TRUE, ~0ull));
306 }
307
308 void beginRenderPass (const DeviceInterface&    vk,
309                                           const VkCommandBuffer         commandBuffer,
310                                           const VkRenderPass            renderPass,
311                                           const VkFramebuffer           framebuffer,
312                                           const VkRect2D&                       renderArea,
313                                           const tcu::Vec4&                      clearColor)
314 {
315         const VkClearValue clearValue = makeClearValueColor(clearColor);
316
317         const VkRenderPassBeginInfo renderPassBeginInfo = {
318                 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,               // VkStructureType         sType;
319                 DE_NULL,                                                                                // const void*             pNext;
320                 renderPass,                                                                             // VkRenderPass            renderPass;
321                 framebuffer,                                                                    // VkFramebuffer           framebuffer;
322                 renderArea,                                                                             // VkRect2D                renderArea;
323                 1u,                                                                                             // uint32_t                clearValueCount;
324                 &clearValue,                                                                    // const VkClearValue*     pClearValues;
325         };
326
327         vk.cmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
328 }
329
330 void beginRenderPassWithRasterizationDisabled (const DeviceInterface&   vk,
331                                                                                            const VkCommandBuffer        commandBuffer,
332                                                                                            const VkRenderPass           renderPass,
333                                                                                            const VkFramebuffer          framebuffer)
334 {
335         const VkRect2D renderArea = {{ 0, 0 }, { 0, 0 }};
336
337         const VkRenderPassBeginInfo renderPassBeginInfo = {
338                 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,               // VkStructureType         sType;
339                 DE_NULL,                                                                                // const void*             pNext;
340                 renderPass,                                                                             // VkRenderPass            renderPass;
341                 framebuffer,                                                                    // VkFramebuffer           framebuffer;
342                 renderArea,                                                                             // VkRect2D                renderArea;
343                 0u,                                                                                             // uint32_t                clearValueCount;
344                 DE_NULL,                                                                                // const VkClearValue*     pClearValues;
345         };
346
347         vk.cmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
348 }
349
350 void endRenderPass (const DeviceInterface&      vk,
351                                         const VkCommandBuffer   commandBuffer)
352 {
353         vk.cmdEndRenderPass(commandBuffer);
354 }
355
356 Move<VkRenderPass> makeRenderPass (const DeviceInterface&       vk,
357                                                                    const VkDevice                       device,
358                                                                    const VkFormat                       colorFormat)
359 {
360         const VkAttachmentDescription colorAttachmentDescription =
361         {
362                 (VkAttachmentDescriptionFlags)0,                                        // VkAttachmentDescriptionFlags         flags;
363                 colorFormat,                                                                            // VkFormat                                                     format;
364                 VK_SAMPLE_COUNT_1_BIT,                                                          // VkSampleCountFlagBits                        samples;
365                 VK_ATTACHMENT_LOAD_OP_CLEAR,                                            // VkAttachmentLoadOp                           loadOp;
366                 VK_ATTACHMENT_STORE_OP_STORE,                                           // VkAttachmentStoreOp                          storeOp;
367                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,                                        // VkAttachmentLoadOp                           stencilLoadOp;
368                 VK_ATTACHMENT_STORE_OP_DONT_CARE,                                       // VkAttachmentStoreOp                          stencilStoreOp;
369                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                       // VkImageLayout                                        initialLayout;
370                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL                        // VkImageLayout                                        finalLayout;
371         };
372
373         const VkAttachmentReference colorAttachmentReference =
374         {
375                 0u,                                                                                                     // deUint32                     attachment;
376                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL                        // VkImageLayout        layout;
377         };
378
379         const VkAttachmentReference depthAttachmentReference =
380         {
381                 VK_ATTACHMENT_UNUSED,                                                           // deUint32                     attachment;
382                 VK_IMAGE_LAYOUT_UNDEFINED                                                       // VkImageLayout        layout;
383         };
384
385         const VkSubpassDescription subpassDescription =
386         {
387                 (VkSubpassDescriptionFlags)0,                                           // VkSubpassDescriptionFlags            flags;
388                 VK_PIPELINE_BIND_POINT_GRAPHICS,                                        // VkPipelineBindPoint                          pipelineBindPoint;
389                 0u,                                                                                                     // deUint32                                                     inputAttachmentCount;
390                 DE_NULL,                                                                                        // const VkAttachmentReference*         pInputAttachments;
391                 1u,                                                                                                     // deUint32                                                     colorAttachmentCount;
392                 &colorAttachmentReference,                                                      // const VkAttachmentReference*         pColorAttachments;
393                 DE_NULL,                                                                                        // const VkAttachmentReference*         pResolveAttachments;
394                 &depthAttachmentReference,                                                      // const VkAttachmentReference*         pDepthStencilAttachment;
395                 0u,                                                                                                     // deUint32                                                     preserveAttachmentCount;
396                 DE_NULL                                                                                         // const deUint32*                                      pPreserveAttachments;
397         };
398
399         const VkRenderPassCreateInfo renderPassInfo =
400         {
401                 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,                      // VkStructureType                                      sType;
402                 DE_NULL,                                                                                        // const void*                                          pNext;
403                 (VkRenderPassCreateFlags)0,                                                     // VkRenderPassCreateFlags                      flags;
404                 1u,                                                                                                     // deUint32                                                     attachmentCount;
405                 &colorAttachmentDescription,                                            // const VkAttachmentDescription*       pAttachments;
406                 1u,                                                                                                     // deUint32                                                     subpassCount;
407                 &subpassDescription,                                                            // const VkSubpassDescription*          pSubpasses;
408                 0u,                                                                                                     // deUint32                                                     dependencyCount;
409                 DE_NULL                                                                                         // const VkSubpassDependency*           pDependencies;
410         };
411
412         return createRenderPass(vk, device, &renderPassInfo);
413 }
414
415 Move<VkFramebuffer> makeFramebuffer (const DeviceInterface&             vk,
416                                                                          const VkDevice                         device,
417                                                                          const VkRenderPass                     renderPass,
418                                                                          const VkImageView                      colorAttachment,
419                                                                          const deUint32                         width,
420                                                                          const deUint32                         height,
421                                                                          const deUint32                         layers)
422 {
423         const VkFramebufferCreateInfo framebufferInfo = {
424                 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,              // VkStructureType                             sType;
425                 DE_NULL,                                                                                // const void*                                 pNext;
426                 (VkFramebufferCreateFlags)0,                                    // VkFramebufferCreateFlags                    flags;
427                 renderPass,                                                                             // VkRenderPass                                renderPass;
428                 1u,                                                                                             // uint32_t                                    attachmentCount;
429                 &colorAttachment,                                                               // const VkImageView*                          pAttachments;
430                 width,                                                                                  // uint32_t                                    width;
431                 height,                                                                                 // uint32_t                                    height;
432                 layers,                                                                                 // uint32_t                                    layers;
433         };
434
435         return createFramebuffer(vk, device, &framebufferInfo);
436 }
437
438 GraphicsPipelineBuilder& GraphicsPipelineBuilder::setShader (const DeviceInterface&                     vk,
439                                                                                                                          const VkDevice                                 device,
440                                                                                                                          const VkShaderStageFlagBits    stage,
441                                                                                                                          const ProgramBinary&                   binary,
442                                                                                                                          const VkSpecializationInfo*    specInfo)
443 {
444         VkShaderModule module;
445         switch (stage)
446         {
447                 case (VK_SHADER_STAGE_VERTEX_BIT):
448                         DE_ASSERT(m_vertexShaderModule.get() == DE_NULL);
449                         m_vertexShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0);
450                         module = *m_vertexShaderModule;
451                         break;
452
453                 case (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT):
454                         DE_ASSERT(m_tessControlShaderModule.get() == DE_NULL);
455                         m_tessControlShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0);
456                         module = *m_tessControlShaderModule;
457                         break;
458
459                 case (VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT):
460                         DE_ASSERT(m_tessEvaluationShaderModule.get() == DE_NULL);
461                         m_tessEvaluationShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0);
462                         module = *m_tessEvaluationShaderModule;
463                         break;
464
465                 case (VK_SHADER_STAGE_GEOMETRY_BIT):
466                         DE_ASSERT(m_geometryShaderModule.get() == DE_NULL);
467                         m_geometryShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0);
468                         module = *m_geometryShaderModule;
469                         break;
470
471                 case (VK_SHADER_STAGE_FRAGMENT_BIT):
472                         DE_ASSERT(m_fragmentShaderModule.get() == DE_NULL);
473                         m_fragmentShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0);
474                         module = *m_fragmentShaderModule;
475                         break;
476
477                 default:
478                         DE_FATAL("Invalid shader stage");
479                         return *this;
480         }
481
482         const VkPipelineShaderStageCreateInfo pipelineShaderStageInfo =
483         {
484                 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,    // VkStructureType                                              sType;
485                 DE_NULL,                                                                                                // const void*                                                  pNext;
486                 (VkPipelineShaderStageCreateFlags)0,                                    // VkPipelineShaderStageCreateFlags             flags;
487                 stage,                                                                                                  // VkShaderStageFlagBits                                stage;
488                 module,                                                                                                 // VkShaderModule                                               module;
489                 "main",                                                                                                 // const char*                                                  pName;
490                 specInfo,                                                                                               // const VkSpecializationInfo*                  pSpecializationInfo;
491         };
492
493         m_shaderStageFlags |= stage;
494         m_shaderStages.push_back(pipelineShaderStageInfo);
495
496         return *this;
497 }
498
499 GraphicsPipelineBuilder& GraphicsPipelineBuilder::setVertexInputSingleAttribute (const VkFormat vertexFormat, const deUint32 stride)
500 {
501         const VkVertexInputBindingDescription bindingDesc =
502         {
503                 0u,                                                                     // uint32_t                             binding;
504                 stride,                                                         // uint32_t                             stride;
505                 VK_VERTEX_INPUT_RATE_VERTEX,            // VkVertexInputRate    inputRate;
506         };
507         const VkVertexInputAttributeDescription attributeDesc =
508         {
509                 0u,                                                                     // uint32_t                     location;
510                 0u,                                                                     // uint32_t                     binding;
511                 vertexFormat,                                           // VkFormat                     format;
512                 0u,                                                                     // uint32_t                     offset;
513         };
514
515         m_vertexInputBindings.clear();
516         m_vertexInputBindings.push_back(bindingDesc);
517
518         m_vertexInputAttributes.clear();
519         m_vertexInputAttributes.push_back(attributeDesc);
520
521         return *this;
522 }
523
524 template<typename T>
525 inline const T* dataPointer (const std::vector<T>& vec)
526 {
527         return (vec.size() != 0 ? &vec[0] : DE_NULL);
528 }
529
530 Move<VkPipeline> GraphicsPipelineBuilder::build (const DeviceInterface& vk,
531                                                                                                  const VkDevice                 device,
532                                                                                                  const VkPipelineLayout pipelineLayout,
533                                                                                                  const VkRenderPass             renderPass,
534                                                                                                  PipelineCacheData&             pipelineCacheData)
535 {
536         const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
537         {
538                 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,              // VkStructureType                             sType;
539                 DE_NULL,                                                                                                                // const void*                                 pNext;
540                 (VkPipelineVertexInputStateCreateFlags)0,                                               // VkPipelineVertexInputStateCreateFlags       flags;
541                 static_cast<deUint32>(m_vertexInputBindings.size()),                    // uint32_t                                    vertexBindingDescriptionCount;
542                 dataPointer(m_vertexInputBindings),                                                             // const VkVertexInputBindingDescription*      pVertexBindingDescriptions;
543                 static_cast<deUint32>(m_vertexInputAttributes.size()),                  // uint32_t                                    vertexAttributeDescriptionCount;
544                 dataPointer(m_vertexInputAttributes),                                                   // const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions;
545         };
546
547         const VkPrimitiveTopology topology = (m_shaderStageFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST
548                                                                                                                                                                                                                  : m_primitiveTopology;
549         const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
550         {
551                 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,    // VkStructureType                             sType;
552                 DE_NULL,                                                                                                                // const void*                                 pNext;
553                 (VkPipelineInputAssemblyStateCreateFlags)0,                                             // VkPipelineInputAssemblyStateCreateFlags     flags;
554                 topology,                                                                                                               // VkPrimitiveTopology                         topology;
555                 VK_FALSE,                                                                                                               // VkBool32                                    primitiveRestartEnable;
556         };
557
558         const VkPipelineTessellationStateCreateInfo pipelineTessellationStateInfo =
559         {
560                 VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,              // VkStructureType                             sType;
561                 DE_NULL,                                                                                                                // const void*                                 pNext;
562                 (VkPipelineTessellationStateCreateFlags)0,                                              // VkPipelineTessellationStateCreateFlags      flags;
563                 m_patchControlPoints,                                                                                   // uint32_t                                    patchControlPoints;
564         };
565
566         const VkViewport viewport = makeViewport(
567                 0.0f, 0.0f,
568                 static_cast<float>(m_renderSize.x()), static_cast<float>(m_renderSize.y()),
569                 0.0f, 1.0f);
570
571         const VkRect2D scissor = {
572                 makeOffset2D(0, 0),
573                 makeExtent2D(m_renderSize.x(), m_renderSize.y()),
574         };
575
576         const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
577         {
578                 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,  // VkStructureType                             sType;
579                 DE_NULL,                                                                                                // const void*                                 pNext;
580                 (VkPipelineViewportStateCreateFlags)0,                                  // VkPipelineViewportStateCreateFlags          flags;
581                 1u,                                                                                                             // uint32_t                                    viewportCount;
582                 &viewport,                                                                                              // const VkViewport*                           pViewports;
583                 1u,                                                                                                             // uint32_t                                    scissorCount;
584                 &scissor,                                                                                               // const VkRect2D*                             pScissors;
585         };
586
587         const bool isRasterizationDisabled = ((m_shaderStageFlags & VK_SHADER_STAGE_FRAGMENT_BIT) == 0);
588         const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
589         {
590                 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,             // VkStructureType                          sType;
591                 DE_NULL,                                                                                                                // const void*                              pNext;
592                 (VkPipelineRasterizationStateCreateFlags)0,                                             // VkPipelineRasterizationStateCreateFlags  flags;
593                 VK_FALSE,                                                                                                               // VkBool32                                 depthClampEnable;
594                 isRasterizationDisabled,                                                                                // VkBool32                                 rasterizerDiscardEnable;
595                 VK_POLYGON_MODE_FILL,                                                                                   // VkPolygonMode                                                        polygonMode;
596                 m_cullModeFlags,                                                                                                // VkCullModeFlags                                                      cullMode;
597                 m_frontFace,                                                                                                    // VkFrontFace                                                          frontFace;
598                 VK_FALSE,                                                                                                               // VkBool32                                                                     depthBiasEnable;
599                 0.0f,                                                                                                                   // float                                                                        depthBiasConstantFactor;
600                 0.0f,                                                                                                                   // float                                                                        depthBiasClamp;
601                 0.0f,                                                                                                                   // float                                                                        depthBiasSlopeFactor;
602                 1.0f,                                                                                                                   // float                                                                        lineWidth;
603         };
604
605         const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
606         {
607                 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,       // VkStructureType                                                      sType;
608                 DE_NULL,                                                                                                        // const void*                                                          pNext;
609                 (VkPipelineMultisampleStateCreateFlags)0,                                       // VkPipelineMultisampleStateCreateFlags        flags;
610                 VK_SAMPLE_COUNT_1_BIT,                                                                          // VkSampleCountFlagBits                                        rasterizationSamples;
611                 VK_FALSE,                                                                                                       // VkBool32                                                                     sampleShadingEnable;
612                 0.0f,                                                                                                           // float                                                                        minSampleShading;
613                 DE_NULL,                                                                                                        // const VkSampleMask*                                          pSampleMask;
614                 VK_FALSE,                                                                                                       // VkBool32                                                                     alphaToCoverageEnable;
615                 VK_FALSE                                                                                                        // VkBool32                                                                     alphaToOneEnable;
616         };
617
618         const VkStencilOpState stencilOpState = makeStencilOpState(
619                 VK_STENCIL_OP_KEEP,             // stencil fail
620                 VK_STENCIL_OP_KEEP,             // depth & stencil pass
621                 VK_STENCIL_OP_KEEP,             // depth only fail
622                 VK_COMPARE_OP_NEVER,    // compare op
623                 0u,                                             // compare mask
624                 0u,                                             // write mask
625                 0u);                                    // reference
626
627         const VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
628         {
629                 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,     // VkStructureType                                                      sType;
630                 DE_NULL,                                                                                                        // const void*                                                          pNext;
631                 (VkPipelineDepthStencilStateCreateFlags)0,                                      // VkPipelineDepthStencilStateCreateFlags       flags;
632                 VK_FALSE,                                                                                                       // VkBool32                                                                     depthTestEnable;
633                 VK_FALSE,                                                                                                       // VkBool32                                                                     depthWriteEnable;
634                 VK_COMPARE_OP_LESS,                                                                                     // VkCompareOp                                                          depthCompareOp;
635                 VK_FALSE,                                                                                                       // VkBool32                                                                     depthBoundsTestEnable;
636                 VK_FALSE,                                                                                                       // VkBool32                                                                     stencilTestEnable;
637                 stencilOpState,                                                                                         // VkStencilOpState                                                     front;
638                 stencilOpState,                                                                                         // VkStencilOpState                                                     back;
639                 0.0f,                                                                                                           // float                                                                        minDepthBounds;
640                 1.0f,                                                                                                           // float                                                                        maxDepthBounds;
641         };
642
643         const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
644         const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState =
645         {
646                 m_blendEnable,                                          // VkBool32                                     blendEnable;
647                 VK_BLEND_FACTOR_SRC_ALPHA,                      // VkBlendFactor                        srcColorBlendFactor;
648                 VK_BLEND_FACTOR_ONE,                            // VkBlendFactor                        dstColorBlendFactor;
649                 VK_BLEND_OP_ADD,                                        // VkBlendOp                            colorBlendOp;
650                 VK_BLEND_FACTOR_SRC_ALPHA,                      // VkBlendFactor                        srcAlphaBlendFactor;
651                 VK_BLEND_FACTOR_ONE,                            // VkBlendFactor                        dstAlphaBlendFactor;
652                 VK_BLEND_OP_ADD,                                        // VkBlendOp                            alphaBlendOp;
653                 colorComponentsAll,                                     // VkColorComponentFlags        colorWriteMask;
654         };
655
656         const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
657         {
658                 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,       // VkStructureType                                                              sType;
659                 DE_NULL,                                                                                                        // const void*                                                                  pNext;
660                 (VkPipelineColorBlendStateCreateFlags)0,                                        // VkPipelineColorBlendStateCreateFlags                 flags;
661                 VK_FALSE,                                                                                                       // VkBool32                                                                             logicOpEnable;
662                 VK_LOGIC_OP_COPY,                                                                                       // VkLogicOp                                                                    logicOp;
663                 1u,                                                                                                                     // deUint32                                                                             attachmentCount;
664                 &pipelineColorBlendAttachmentState,                                                     // const VkPipelineColorBlendAttachmentState*   pAttachments;
665                 { 0.0f, 0.0f, 0.0f, 0.0f },                                                                     // float                                                                                blendConstants[4];
666         };
667
668         const VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
669         {
670                 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,                                                // VkStructureType                                                                      sType;
671                 DE_NULL,                                                                                                                                // const void*                                                                          pNext;
672                 (VkPipelineCreateFlags)0,                                                                                               // VkPipelineCreateFlags                                                        flags;
673                 static_cast<deUint32>(m_shaderStages.size()),                                                   // deUint32                                                                                     stageCount;
674                 &m_shaderStages[0],                                                                                                             // const VkPipelineShaderStageCreateInfo*                       pStages;
675                 &vertexInputStateInfo,                                                                                                  // const VkPipelineVertexInputStateCreateInfo*          pVertexInputState;
676                 &pipelineInputAssemblyStateInfo,                                                                                // const VkPipelineInputAssemblyStateCreateInfo*        pInputAssemblyState;
677                 (m_shaderStageFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT ? &pipelineTessellationStateInfo : DE_NULL), // const VkPipelineTessellationStateCreateInfo*             pTessellationState;
678                 (isRasterizationDisabled ? DE_NULL : &pipelineViewportStateInfo),               // const VkPipelineViewportStateCreateInfo*                     pViewportState;
679                 &pipelineRasterizationStateInfo,                                                                                // const VkPipelineRasterizationStateCreateInfo*        pRasterizationState;
680                 (isRasterizationDisabled ? DE_NULL : &pipelineMultisampleStateInfo),    // const VkPipelineMultisampleStateCreateInfo*          pMultisampleState;
681                 (isRasterizationDisabled ? DE_NULL : &pipelineDepthStencilStateInfo),   // const VkPipelineDepthStencilStateCreateInfo*         pDepthStencilState;
682                 (isRasterizationDisabled ? DE_NULL : &pipelineColorBlendStateInfo),             // const VkPipelineColorBlendStateCreateInfo*           pColorBlendState;
683                 DE_NULL,                                                                                                                                // const VkPipelineDynamicStateCreateInfo*                      pDynamicState;
684                 pipelineLayout,                                                                                                                 // VkPipelineLayout                                                                     layout;
685                 renderPass,                                                                                                                             // VkRenderPass                                                                         renderPass;
686                 0u,                                                                                                                                             // deUint32                                                                                     subpass;
687                 DE_NULL,                                                                                                                                // VkPipeline                                                                           basePipelineHandle;
688                 0,                                                                                                                                              // deInt32                                                                                      basePipelineIndex;
689         };
690
691         {
692                 const vk::Unique<vk::VkPipelineCache>   pipelineCache   (pipelineCacheData.createPipelineCache(vk, device));
693                 vk::Move<vk::VkPipeline>                                pipeline                (createGraphicsPipeline(vk, device, *pipelineCache, &graphicsPipelineInfo));
694
695                 // Refresh data from cache
696                 pipelineCacheData.setFromPipelineCache(vk, device, *pipelineCache);
697
698                 return pipeline;
699         }
700 }
701
702 void requireFeatures (const InstanceInterface& vki, const VkPhysicalDevice physDevice, const FeatureFlags flags)
703 {
704         const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(vki, physDevice);
705
706         if (((flags & FEATURE_TESSELLATION_SHADER) != 0) && !features.tessellationShader)
707                 throw tcu::NotSupportedError("Tessellation shader not supported");
708
709         if (((flags & FEATURE_GEOMETRY_SHADER) != 0) && !features.geometryShader)
710                 throw tcu::NotSupportedError("Geometry shader not supported");
711
712         if (((flags & FEATURE_SHADER_FLOAT_64) != 0) && !features.shaderFloat64)
713                 throw tcu::NotSupportedError("Double-precision floats not supported");
714
715         if (((flags & FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS) != 0) && !features.vertexPipelineStoresAndAtomics)
716                 throw tcu::NotSupportedError("SSBO and image writes not supported in vertex pipeline");
717
718         if (((flags & FEATURE_FRAGMENT_STORES_AND_ATOMICS) != 0) && !features.fragmentStoresAndAtomics)
719                 throw tcu::NotSupportedError("SSBO and image writes not supported in fragment shader");
720
721         if (((flags & FEATURE_SHADER_TESSELLATION_AND_GEOMETRY_POINT_SIZE) != 0) && !features.shaderTessellationAndGeometryPointSize)
722                 throw tcu::NotSupportedError("Tessellation and geometry shaders don't support PointSize built-in");
723
724         if (((flags & FEATURE_SHADER_STORAGE_IMAGE_EXTENDED_FORMATS) != 0) && !features.shaderStorageImageExtendedFormats)
725                 throw tcu::NotSupportedError("Storage image extended formats not supported");
726 }
727
728 std::string getResourceName (const ResourceDescription& resource)
729 {
730         std::ostringstream str;
731
732         if (resource.type == RESOURCE_TYPE_BUFFER)
733                 str << "buffer_" << resource.size.x();
734         else if (resource.type == RESOURCE_TYPE_IMAGE)
735         {
736                 str << "image_" << resource.size.x()
737                                                 << (resource.size.y() > 0 ? "x" + de::toString(resource.size.y()) : "")
738                                                 << (resource.size.z() > 0 ? "x" + de::toString(resource.size.z()) : "")
739                         << "_" << de::toLower(getFormatName(resource.imageFormat)).substr(10);
740         }
741         else if (isIndirectBuffer(resource.type))
742                 str << "indirect_buffer";
743         else
744                 DE_ASSERT(0);
745
746         return str.str();
747 }
748
749 bool isIndirectBuffer (const ResourceType type)
750 {
751         switch (type)
752         {
753                 case RESOURCE_TYPE_INDIRECT_BUFFER_DRAW:
754                 case RESOURCE_TYPE_INDIRECT_BUFFER_DRAW_INDEXED:
755                 case RESOURCE_TYPE_INDIRECT_BUFFER_DISPATCH:
756                         return true;
757
758                 default:
759                         return false;
760         }
761 }
762
763 PipelineCacheData::PipelineCacheData (void)
764 {
765 }
766
767 PipelineCacheData::~PipelineCacheData (void)
768 {
769 }
770
771 vk::Move<VkPipelineCache> PipelineCacheData::createPipelineCache (const vk::DeviceInterface& vk, const vk::VkDevice device) const
772 {
773         const de::ScopedLock                                            dataLock        (m_lock);
774         const struct vk::VkPipelineCacheCreateInfo      params  =
775         {
776                 vk::VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO,
777                 DE_NULL,
778                 (vk::VkPipelineCacheCreateFlags)0,
779                 (deUintptr)m_data.size(),
780                 (m_data.empty() ? DE_NULL : &m_data[0])
781         };
782
783         return vk::createPipelineCache(vk, device, &params);
784 }
785
786 void PipelineCacheData::setFromPipelineCache (const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkPipelineCache pipelineCache)
787 {
788         const de::ScopedLock            dataLock                (m_lock);
789         deUintptr                                       dataSize                = 0;
790
791         VK_CHECK(vk.getPipelineCacheData(device, pipelineCache, &dataSize, DE_NULL));
792
793         m_data.resize(dataSize);
794
795         if (dataSize > 0)
796                 VK_CHECK(vk.getPipelineCacheData(device, pipelineCache, &dataSize, &m_data[0]));
797 }
798
799 } // synchronization
800 } // vkt