Add Vulkan DrawContext utility class
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / vktDrawUtil.cpp
1 /*-------------------------------------------------------------------------
2  * Vulkan CTS Framework
3  * --------------------
4  *
5  * Copyright (c) 2016 The Khronos Group Inc.
6  * Copyright (c) 2016 Google Inc.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22  * \brief Utility for generating simple work
23  *//*--------------------------------------------------------------------*/
24
25 #include "vktDrawUtil.hpp"
26 #include "vkBufferWithMemory.hpp"
27 #include "vkImageWithMemory.hpp"
28 #include "vkTypeUtil.hpp"
29 #include "tcuTestLog.hpp"
30
31 namespace vkt
32 {
33 namespace drawutil
34 {
35
36 using namespace de;
37 using namespace tcu;
38 using namespace vk;
39
40 VkBufferCreateInfo makeBufferCreateInfo (const VkDeviceSize                     bufferSize,
41                                                                                  const VkBufferUsageFlags       usage)
42 {
43         const VkBufferCreateInfo bufferCreateInfo =
44         {
45                 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,   // VkStructureType              sType;
46                 DE_NULL,                                                                // const void*                  pNext;
47                 (VkBufferCreateFlags)0,                                 // VkBufferCreateFlags  flags;
48                 bufferSize,                                                             // VkDeviceSize                 size;
49                 usage,                                                                  // VkBufferUsageFlags   usage;
50                 VK_SHARING_MODE_EXCLUSIVE,                              // VkSharingMode                sharingMode;
51                 0u,                                                                             // deUint32                             queueFamilyIndexCount;
52                 DE_NULL,                                                                // const deUint32*              pQueueFamilyIndices;
53         };
54         return bufferCreateInfo;
55 }
56
57 VkBufferMemoryBarrier makeBufferMemoryBarrier (const VkAccessFlags      srcAccessMask,
58                                                                                            const VkAccessFlags  dstAccessMask,
59                                                                                            const VkBuffer               buffer,
60                                                                                            const VkDeviceSize   offset,
61                                                                                            const VkDeviceSize   bufferSizeBytes)
62 {
63         const VkBufferMemoryBarrier barrier =
64         {
65                 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,        // VkStructureType      sType;
66                 DE_NULL,                                                                        // const void*          pNext;
67                 srcAccessMask,                                                          // VkAccessFlags        srcAccessMask;
68                 dstAccessMask,                                                          // VkAccessFlags        dstAccessMask;
69                 VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                     srcQueueFamilyIndex;
70                 VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                     destQueueFamilyIndex;
71                 buffer,                                                                         // VkBuffer                     buffer;
72                 offset,                                                                         // VkDeviceSize         offset;
73                 bufferSizeBytes,                                                        // VkDeviceSize         size;
74         };
75         return barrier;
76 }
77
78 VkImageMemoryBarrier makeImageMemoryBarrier     (const VkAccessFlags                    srcAccessMask,
79                                                                                          const VkAccessFlags                    dstAccessMask,
80                                                                                          const VkImageLayout                    oldLayout,
81                                                                                          const VkImageLayout                    newLayout,
82                                                                                          const VkImage                                  image,
83                                                                                          const VkImageSubresourceRange  subresourceRange)
84 {
85         const VkImageMemoryBarrier barrier =
86         {
87                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                 // VkStructureType                      sType;
88                 DE_NULL,                                                                                // const void*                          pNext;
89                 srcAccessMask,                                                                  // VkAccessFlags                        outputMask;
90                 dstAccessMask,                                                                  // VkAccessFlags                        inputMask;
91                 oldLayout,                                                                              // VkImageLayout                        oldLayout;
92                 newLayout,                                                                              // VkImageLayout                        newLayout;
93                 VK_QUEUE_FAMILY_IGNORED,                                                // deUint32                                     srcQueueFamilyIndex;
94                 VK_QUEUE_FAMILY_IGNORED,                                                // deUint32                                     destQueueFamilyIndex;
95                 image,                                                                                  // VkImage                                      image;
96                 subresourceRange,                                                               // VkImageSubresourceRange      subresourceRange;
97         };
98         return barrier;
99 }
100
101 Move<VkCommandPool> makeCommandPool (const DeviceInterface& vk, const VkDevice device, const deUint32 queueFamilyIndex)
102 {
103         const VkCommandPoolCreateInfo info =
104         {
105                 VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,                     // VkStructureType                      sType;
106                 DE_NULL,                                                                                        // const void*                          pNext;
107                 VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,        // VkCommandPoolCreateFlags     flags;
108                 queueFamilyIndex,                                                                       // deUint32                                     queueFamilyIndex;
109         };
110         return createCommandPool(vk, device, &info);
111 }
112
113 Move<VkCommandBuffer> makeCommandBuffer (const DeviceInterface& vk, const VkDevice device, const VkCommandPool commandPool)
114 {
115         const VkCommandBufferAllocateInfo info =
116         {
117                 VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,         // VkStructureType              sType;
118                 DE_NULL,                                                                                        // const void*                  pNext;
119                 commandPool,                                                                            // VkCommandPool                commandPool;
120                 VK_COMMAND_BUFFER_LEVEL_PRIMARY,                                        // VkCommandBufferLevel level;
121                 1u,                                                                                                     // deUint32                             commandBufferCount;
122         };
123         return allocateCommandBuffer(vk, device, &info);
124 }
125
126 Move<VkDescriptorSet> makeDescriptorSet (const DeviceInterface&                 vk,
127                                                                                  const VkDevice                                 device,
128                                                                                  const VkDescriptorPool                 descriptorPool,
129                                                                                  const VkDescriptorSetLayout    setLayout)
130 {
131         const VkDescriptorSetAllocateInfo info =
132         {
133                 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,         // VkStructureType                              sType;
134                 DE_NULL,                                                                                        // const void*                                  pNext;
135                 descriptorPool,                                                                         // VkDescriptorPool                             descriptorPool;
136                 1u,                                                                                                     // deUint32                                             descriptorSetCount;
137                 &setLayout,                                                                                     // const VkDescriptorSetLayout* pSetLayouts;
138         };
139         return allocateDescriptorSet(vk, device, &info);
140 }
141
142 Move<VkPipelineLayout> makePipelineLayout (const DeviceInterface&               vk,
143                                                                                    const VkDevice                               device,
144                                                                                    const VkDescriptorSetLayout  descriptorSetLayout)
145 {
146         const VkPipelineLayoutCreateInfo info =
147         {
148                 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,          // VkStructureType                              sType;
149                 DE_NULL,                                                                                        // const void*                                  pNext;
150                 (VkPipelineLayoutCreateFlags)0,                                         // VkPipelineLayoutCreateFlags  flags;
151                 1u,                                                                                                     // deUint32                                             setLayoutCount;
152                 &descriptorSetLayout,                                                           // const VkDescriptorSetLayout* pSetLayouts;
153                 0u,                                                                                                     // deUint32                                             pushConstantRangeCount;
154                 DE_NULL,                                                                                        // const VkPushConstantRange*   pPushConstantRanges;
155         };
156         return createPipelineLayout(vk, device, &info);
157 }
158
159 Move<VkPipelineLayout> makePipelineLayoutWithoutDescriptors (const DeviceInterface&             vk,
160                                                                                                                          const VkDevice                         device)
161 {
162         const VkPipelineLayoutCreateInfo info =
163         {
164                 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,          // VkStructureType                              sType;
165                 DE_NULL,                                                                                        // const void*                                  pNext;
166                 (VkPipelineLayoutCreateFlags)0,                                         // VkPipelineLayoutCreateFlags  flags;
167                 0u,                                                                                                     // deUint32                                             setLayoutCount;
168                 DE_NULL,                                                                                        // const VkDescriptorSetLayout* pSetLayouts;
169                 0u,                                                                                                     // deUint32                                             pushConstantRangeCount;
170                 DE_NULL,                                                                                        // const VkPushConstantRange*   pPushConstantRanges;
171         };
172         return createPipelineLayout(vk, device, &info);
173 }
174
175 Move<VkImageView> makeImageView (const DeviceInterface&                 vk,
176                                                                  const VkDevice                                 device,
177                                                                  const VkImage                                  image,
178                                                                  const VkImageViewType                  viewType,
179                                                                  const VkFormat                                 format,
180                                                                  const VkImageSubresourceRange  subresourceRange)
181 {
182         const VkImageViewCreateInfo imageViewParams =
183         {
184                 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,               // VkStructureType                      sType;
185                 DE_NULL,                                                                                // const void*                          pNext;
186                 (VkImageViewCreateFlags)0,                                              // VkImageViewCreateFlags       flags;
187                 image,                                                                                  // VkImage                                      image;
188                 viewType,                                                                               // VkImageViewType                      viewType;
189                 format,                                                                                 // VkFormat                                     format;
190                 makeComponentMappingRGBA(),                                             // VkComponentMapping           components;
191                 subresourceRange,                                                               // VkImageSubresourceRange      subresourceRange;
192         };
193         return createImageView(vk, device, &imageViewParams);
194 }
195
196 VkBufferImageCopy makeBufferImageCopy (const VkImageSubresourceLayers   subresourceLayers,
197                                                                            const VkExtent3D                                     extent)
198 {
199         const VkBufferImageCopy copyParams =
200         {
201                 0ull,                                                                           //      VkDeviceSize                            bufferOffset;
202                 0u,                                                                                     //      deUint32                                        bufferRowLength;
203                 0u,                                                                                     //      deUint32                                        bufferImageHeight;
204                 subresourceLayers,                                                      //      VkImageSubresourceLayers        imageSubresource;
205                 makeOffset3D(0, 0, 0),                                          //      VkOffset3D                                      imageOffset;
206                 extent,                                                                         //      VkExtent3D                                      imageExtent;
207         };
208         return copyParams;
209 }
210
211 void beginCommandBuffer (const DeviceInterface& vk, const VkCommandBuffer commandBuffer)
212 {
213         const VkCommandBufferBeginInfo info =
214         {
215                 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,    // VkStructureType                          sType;
216                 DE_NULL,                                                                                // const void*                              pNext;
217                 VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,    // VkCommandBufferUsageFlags                flags;
218                 DE_NULL,                                                                                // const VkCommandBufferInheritanceInfo*    pInheritanceInfo;
219         };
220         VK_CHECK(vk.beginCommandBuffer(commandBuffer, &info));
221 }
222
223 void endCommandBuffer (const DeviceInterface& vk, const VkCommandBuffer commandBuffer)
224 {
225         VK_CHECK(vk.endCommandBuffer(commandBuffer));
226 }
227
228 void submitCommandsAndWait (const DeviceInterface&      vk,
229                                                         const VkDevice                  device,
230                                                         const VkQueue                   queue,
231                                                         const VkCommandBuffer   commandBuffer)
232 {
233         const VkFenceCreateInfo fenceInfo =
234         {
235                 VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,    // VkStructureType              sType;
236                 DE_NULL,                                                                // const void*                  pNext;
237                 (VkFenceCreateFlags)0,                                  // VkFenceCreateFlags   flags;
238         };
239         const Unique<VkFence> fence(createFence(vk, device, &fenceInfo));
240
241         const VkSubmitInfo submitInfo =
242         {
243                 VK_STRUCTURE_TYPE_SUBMIT_INFO,          // VkStructureType                sType;
244                 DE_NULL,                                                        // const void*                    pNext;
245                 0u,                                                                     // uint32_t                       waitSemaphoreCount;
246                 DE_NULL,                                                        // const VkSemaphore*             pWaitSemaphores;
247                 DE_NULL,                                                        // const VkPipelineStageFlags*    pWaitDstStageMask;
248                 1u,                                                                     // uint32_t                       commandBufferCount;
249                 &commandBuffer,                                         // const VkCommandBuffer*         pCommandBuffers;
250                 0u,                                                                     // uint32_t                       signalSemaphoreCount;
251                 DE_NULL,                                                        // const VkSemaphore*             pSignalSemaphores;
252         };
253         VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence));
254         VK_CHECK(vk.waitForFences(device, 1u, &fence.get(), DE_TRUE, ~0ull));
255 }
256
257 std::string getPrimitiveTopologyShortName (const VkPrimitiveTopology topology)
258 {
259         std::string name(getPrimitiveTopologyName(topology));
260         return de::toLower(name.substr(22));
261 }
262 DrawContext::DrawContext (Context&                                              context,
263                                                   const std::vector<Shader>&    shaders,
264                                                   const std::vector<Vec4>&              vertices,
265                                                   const VkPrimitiveTopology             primitiveTopology,
266                                                   const deUint32                                renderSize,
267                                                   const bool                                    depthClampEnable,
268                                                   const bool                                    blendEnable,
269                                                   const float                                   lineWidth)
270         : m_context                                     (context)
271         , m_colorFormat                         (VK_FORMAT_R8G8B8A8_UNORM)
272         , m_depthFormat                         (VK_FORMAT_D32_SFLOAT)
273         , m_colorSubresourceRange       (makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u))
274         , m_depthSubresourceRange       (makeImageSubresourceRange(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 1u, 0u, 1u))
275         , m_renderSize                          (renderSize, renderSize)
276         , m_imageExtent                         (makeExtent3D(m_renderSize.x(), m_renderSize.y(), 1u))
277         , m_primitiveTopology           (primitiveTopology)
278         , m_depthClampEnable            (depthClampEnable)
279         , m_blendEnable                         (blendEnable)
280         , m_numVertices                         (static_cast<deUint32>(vertices.size()))
281         , m_lineWidth                           (lineWidth)
282         , m_numPatchControlPoints       (NUM_PATCH_CONTROL_POINTS)              // we're treating patches as triangles
283 {
284         const DeviceInterface&  vk                      = m_context.getDeviceInterface();
285         const VkDevice                  device          = m_context.getDevice();
286         Allocator&                              allocator       = m_context.getDefaultAllocator();
287
288         // Command buffer
289         {
290                 m_cmdPool       = makeCommandPool(vk, device, m_context.getUniversalQueueFamilyIndex());
291                 m_cmdBuffer     = makeCommandBuffer(vk, device, *m_cmdPool);
292         }
293
294         // Color attachment image
295         {
296                 const VkImageUsageFlags usage                   = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
297                 const VkImageCreateInfo imageCreateInfo =
298                 {
299                         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,            // VkStructureType          sType;
300                         DE_NULL,                                                                        // const void*              pNext;
301                         (VkImageCreateFlags)0,                                          // VkImageCreateFlags       flags;
302                         VK_IMAGE_TYPE_2D,                                                       // VkImageType              imageType;
303                         m_colorFormat,                                                          // VkFormat                 format;
304                         m_imageExtent,                                                          // VkExtent3D               extent;
305                         1u,                                                                                     // uint32_t                 mipLevels;
306                         1u,                                                                                     // uint32_t                 arrayLayers;
307                         VK_SAMPLE_COUNT_1_BIT,                                          // VkSampleCountFlagBits    samples;
308                         VK_IMAGE_TILING_OPTIMAL,                                        // VkImageTiling            tiling;
309                         usage,                                                                          // VkImageUsageFlags        usage;
310                         VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode            sharingMode;
311                         VK_QUEUE_FAMILY_IGNORED,                                        // uint32_t                 queueFamilyIndexCount;
312                         DE_NULL,                                                                        // const uint32_t*          pQueueFamilyIndices;
313                         VK_IMAGE_LAYOUT_UNDEFINED,                                      // VkImageLayout            initialLayout;
314                 };
315
316                 m_colorImage = MovePtr<ImageWithMemory>(new ImageWithMemory(vk, device, allocator, imageCreateInfo, MemoryRequirement::Any));
317                 m_colorImageView = makeImageView(vk, device, **m_colorImage, VK_IMAGE_VIEW_TYPE_2D, m_colorFormat, m_colorSubresourceRange);
318
319                 // Buffer to copy attachment data after rendering
320
321                 const VkDeviceSize bitmapSize = tcu::getPixelSize(mapVkFormat(m_colorFormat)) * m_renderSize.x() * m_renderSize.y();
322                 m_colorAttachmentBuffer = MovePtr<BufferWithMemory>(new BufferWithMemory(
323                         vk, device, allocator, makeBufferCreateInfo(bitmapSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT), MemoryRequirement::HostVisible));
324
325                 {
326                         const Allocation& alloc = m_colorAttachmentBuffer->getAllocation();
327                         deMemset(alloc.getHostPtr(), 0, (size_t)bitmapSize);
328                         flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), bitmapSize);
329                 }
330         }
331
332         // Depth attachment image
333         {
334                 const VkImageCreateInfo imageCreateInfo =
335                 {
336                         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                    // VkStructureType                      sType
337                         DE_NULL,                                                                                // const void*                          pNext
338                         0u,                                                                                             // VkImageCreateFlags           flags
339                         VK_IMAGE_TYPE_2D,                                                               // VkImageType                          imageType
340                         m_depthFormat,                                                                  // VkFormat                                     depthFormat
341                         { m_renderSize.x(), m_renderSize.y(), 1u },             // VkExtent3D                           externt
342                         1u,                                                                                             // deUint32                                     mipLevels
343                         1u,                                                                                             // deUint32                                     arrayLayers
344                         VK_SAMPLE_COUNT_1_BIT,                                                  // VkSampleCountFlagBits        samples
345                         VK_IMAGE_TILING_OPTIMAL,                                                // VkImageTiling                        tiling
346                         VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,    // VkImageUsageFlags            usage
347                         VK_SHARING_MODE_EXCLUSIVE,                                              // VkSharingMode                        sharingMode
348                         0u,                                                                                             // deUint32                                     queueFamilyIndexCount
349                         DE_NULL,                                                                                // const deUint32*                      pQueueFamilyIndices
350                         VK_IMAGE_LAYOUT_UNDEFINED                                               // VkImageLayout                        initialLayout
351                 };
352
353                 m_depthImage = MovePtr<ImageWithMemory>(new ImageWithMemory(vk, device, allocator, imageCreateInfo, MemoryRequirement::HostVisible));
354                 m_depthImageView = makeImageView(vk, device, **m_depthImage, VK_IMAGE_VIEW_TYPE_2D, m_depthFormat, m_depthSubresourceRange);
355         }
356
357         // Vertex buffer
358         {
359                 const VkDeviceSize bufferSize = vertices.size() * sizeof(vertices[0]);
360                 m_vertexBuffer = MovePtr<BufferWithMemory>(new BufferWithMemory(
361                         vk, device, allocator, makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), MemoryRequirement::HostVisible));
362
363                 const Allocation& alloc = m_vertexBuffer->getAllocation();
364                 deMemcpy(alloc.getHostPtr(), &vertices[0], (size_t)bufferSize);
365                 flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), bufferSize);
366         }
367
368         // Pipeline layout
369         {
370                 m_pipelineLayout = makePipelineLayoutWithoutDescriptors(vk, device);
371         }
372
373         // Renderpass
374         {
375                 const VkAttachmentDescription colorAttachmentDescription =
376                 {
377                         (VkAttachmentDescriptionFlags)0,                                        // VkAttachmentDescriptionFlags         flags;
378                         m_colorFormat,                                                                          // VkFormat                                                     format;
379                         VK_SAMPLE_COUNT_1_BIT,                                                          // VkSampleCountFlagBits                        samples;
380                         VK_ATTACHMENT_LOAD_OP_CLEAR,                                            // VkAttachmentLoadOp                           loadOp;
381                         VK_ATTACHMENT_STORE_OP_STORE,                                           // VkAttachmentStoreOp                          storeOp;
382                         VK_ATTACHMENT_LOAD_OP_DONT_CARE,                                        // VkAttachmentLoadOp                           stencilLoadOp;
383                         VK_ATTACHMENT_STORE_OP_DONT_CARE,                                       // VkAttachmentStoreOp                          stencilStoreOp;
384                         VK_IMAGE_LAYOUT_UNDEFINED,                                                      // VkImageLayout                                        initialLayout;
385                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                       // VkImageLayout                                        finalLayout;
386                 };
387
388                 const VkAttachmentReference colorAttachmentReference =
389                 {
390                         0u,                                                                                                     // deUint32                     attachment;
391                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL                        // VkImageLayout        layout;
392                 };
393
394                 const VkAttachmentReference depthAttachmentReference =
395                 {
396                         VK_ATTACHMENT_UNUSED,                                                           // deUint32                     attachment;
397                         VK_IMAGE_LAYOUT_UNDEFINED                                                       // VkImageLayout        layout;
398                 };
399
400                 const VkSubpassDescription subpassDescription =
401                 {
402                         (VkSubpassDescriptionFlags)0,                                           // VkSubpassDescriptionFlags            flags;
403                         VK_PIPELINE_BIND_POINT_GRAPHICS,                                        // VkPipelineBindPoint                          pipelineBindPoint;
404                         0u,                                                                                                     // deUint32                                                     inputAttachmentCount;
405                         DE_NULL,                                                                                        // const VkAttachmentReference*         pInputAttachments;
406                         1u,                                                                                                     // deUint32                                                     colorAttachmentCount;
407                         &colorAttachmentReference,                                                      // const VkAttachmentReference*         pColorAttachments;
408                         DE_NULL,                                                                                        // const VkAttachmentReference*         pResolveAttachments;
409                         &depthAttachmentReference,                                                      // const VkAttachmentReference*         pDepthStencilAttachment;
410                         0u,                                                                                                     // deUint32                                                     preserveAttachmentCount;
411                         DE_NULL                                                                                         // const deUint32*                                      pPreserveAttachments;
412                 };
413
414                 const VkRenderPassCreateInfo renderPassInfo =
415                 {
416                         VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,                      // VkStructureType                                      sType;
417                         DE_NULL,                                                                                        // const void*                                          pNext;
418                         (VkRenderPassCreateFlags)0,                                                     // VkRenderPassCreateFlags                      flags;
419                         1u,                                                                                                     // deUint32                                                     attachmentCount;
420                         &colorAttachmentDescription,                                            // const VkAttachmentDescription*       pAttachments;
421                         1u,                                                                                                     // deUint32                                                     subpassCount;
422                         &subpassDescription,                                                            // const VkSubpassDescription*          pSubpasses;
423                         0u,                                                                                                     // deUint32                                                     dependencyCount;
424                         DE_NULL                                                                                         // const VkSubpassDependency*           pDependencies;
425                 };
426
427                 m_renderPass = createRenderPass(vk, device, &renderPassInfo);
428         }
429
430         // Framebuffer
431         {
432                 const VkImageView attachmentBindInfos[] =
433                 {
434                         m_colorImageView.get(),
435                         m_depthImageView.get()
436                 };
437
438                 const VkFramebufferCreateInfo framebufferInfo = {
439                         VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,              // VkStructureType                             sType;
440                         DE_NULL,                                                                                // const void*                                 pNext;
441                         (VkFramebufferCreateFlags)0,                                    // VkFramebufferCreateFlags                    flags;
442                         *m_renderPass,                                                                  // VkRenderPass                                renderPass;
443                         DE_LENGTH_OF_ARRAY(attachmentBindInfos),                // uint32_t                                    attachmentCount;
444                         attachmentBindInfos,                                                    // const VkImageView*                          pAttachments;
445                         m_renderSize.x(),                                                               // uint32_t                                    width;
446                         m_renderSize.y(),                                                               // uint32_t                                    height;
447                         1u,                                                                                             // uint32_t                                    layers;
448                 };
449
450                 m_framebuffer = createFramebuffer(vk, device, &framebufferInfo);
451         }
452
453         // Graphics pipeline
454         {
455                 const deUint32  vertexStride    = sizeof(Vec4);
456                 const VkFormat  vertexFormat    = VK_FORMAT_R32G32B32A32_SFLOAT;
457
458                 const VkVertexInputBindingDescription bindingDesc =
459                 {
460                         0u,                                                                     // uint32_t                             binding;
461                         vertexStride,                                           // uint32_t                             stride;
462                         VK_VERTEX_INPUT_RATE_VERTEX,            // VkVertexInputRate    inputRate;
463                 };
464                 const VkVertexInputAttributeDescription attributeDesc =
465                 {
466                         0u,                                                                     // uint32_t                     location;
467                         0u,                                                                     // uint32_t                     binding;
468                         vertexFormat,                                           // VkFormat                     format;
469                         0u,                                                                     // uint32_t                     offset;
470                 };
471
472                 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
473                 {
474                         VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,              // VkStructureType                             sType;
475                         DE_NULL,                                                                                                                // const void*                                 pNext;
476                         (VkPipelineVertexInputStateCreateFlags)0,                                               // VkPipelineVertexInputStateCreateFlags       flags;
477                         1u,                                                                                                                             // uint32_t                                    vertexBindingDescriptionCount;
478                         &bindingDesc,                                                                                                   // const VkVertexInputBindingDescription*      pVertexBindingDescriptions;
479                         1u,                                                                                                                             // uint32_t                                    vertexAttributeDescriptionCount;
480                         &attributeDesc,                                                                                                 // const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions;
481                 };
482
483                 const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
484                 {
485                         VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,    // VkStructureType                             sType;
486                         DE_NULL,                                                                                                                // const void*                                 pNext;
487                         (VkPipelineInputAssemblyStateCreateFlags)0,                                             // VkPipelineInputAssemblyStateCreateFlags     flags;
488                         m_primitiveTopology,                                                                                    // VkPrimitiveTopology                         topology;
489                         VK_FALSE,                                                                                                               // VkBool32                                    primitiveRestartEnable;
490                 };
491
492                 const VkPipelineTessellationStateCreateInfo pipelineTessellationStateInfo =
493                 {
494                         VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,              // VkStructureType                             sType;
495                         DE_NULL,                                                                                                                // const void*                                 pNext;
496                         (VkPipelineTessellationStateCreateFlags)0,                                              // VkPipelineTessellationStateCreateFlags      flags;
497                         m_numPatchControlPoints,                                                                                // uint32_t                                    patchControlPoints;
498                 };
499
500                 const VkViewport viewport = makeViewport(
501                         0.0f, 0.0f,
502                         static_cast<float>(m_renderSize.x()), static_cast<float>(m_renderSize.y()),
503                         0.0f, 1.0f);
504
505                 const VkRect2D scissor = {
506                         makeOffset2D(0, 0),
507                         makeExtent2D(m_renderSize.x(), m_renderSize.y()),
508                 };
509
510                 const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
511                 {
512                         VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,  // VkStructureType                             sType;
513                         DE_NULL,                                                                                                // const void*                                 pNext;
514                         (VkPipelineViewportStateCreateFlags)0,                                  // VkPipelineViewportStateCreateFlags          flags;
515                         1u,                                                                                                             // uint32_t                                    viewportCount;
516                         &viewport,                                                                                              // const VkViewport*                           pViewports;
517                         1u,                                                                                                             // uint32_t                                    scissorCount;
518                         &scissor,                                                                                               // const VkRect2D*                             pScissors;
519                 };
520
521                 const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
522                 {
523                         VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,             // VkStructureType                          sType;
524                         DE_NULL,                                                                                                                // const void*                              pNext;
525                         (VkPipelineRasterizationStateCreateFlags)0,                                             // VkPipelineRasterizationStateCreateFlags  flags;
526                         m_depthClampEnable,                                                                                             // VkBool32                                 depthClampEnable;
527                         VK_FALSE,                                                                                                               // VkBool32                                 rasterizerDiscardEnable;
528                         VK_POLYGON_MODE_FILL,                                                                                   // VkPolygonMode                                                        polygonMode;
529                         VK_CULL_MODE_NONE,                                                                                              // VkCullModeFlags                                                      cullMode;
530                         VK_FRONT_FACE_COUNTER_CLOCKWISE,                                                                // VkFrontFace                                                          frontFace;
531                         VK_FALSE,                                                                                                               // VkBool32                                                                     depthBiasEnable;
532                         0.0f,                                                                                                                   // float                                                                        depthBiasConstantFactor;
533                         0.0f,                                                                                                                   // float                                                                        depthBiasClamp;
534                         0.0f,                                                                                                                   // float                                                                        depthBiasSlopeFactor;
535                         m_lineWidth,                                                                                                    // float                                                                        lineWidth;
536                 };
537
538                 const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
539                 {
540                         VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,       // VkStructureType                                                      sType;
541                         DE_NULL,                                                                                                        // const void*                                                          pNext;
542                         (VkPipelineMultisampleStateCreateFlags)0,                                       // VkPipelineMultisampleStateCreateFlags        flags;
543                         VK_SAMPLE_COUNT_1_BIT,                                                                          // VkSampleCountFlagBits                                        rasterizationSamples;
544                         VK_FALSE,                                                                                                       // VkBool32                                                                     sampleShadingEnable;
545                         0.0f,                                                                                                           // float                                                                        minSampleShading;
546                         DE_NULL,                                                                                                        // const VkSampleMask*                                          pSampleMask;
547                         VK_FALSE,                                                                                                       // VkBool32                                                                     alphaToCoverageEnable;
548                         VK_FALSE                                                                                                        // VkBool32                                                                     alphaToOneEnable;
549                 };
550
551                 const VkStencilOpState stencilOpState = makeStencilOpState(
552                         VK_STENCIL_OP_KEEP,             // stencil fail
553                         VK_STENCIL_OP_KEEP,             // depth & stencil pass
554                         VK_STENCIL_OP_KEEP,             // depth only fail
555                         VK_COMPARE_OP_NEVER,    // compare op
556                         0u,                                             // compare mask
557                         0u,                                             // write mask
558                         0u);                                    // reference
559
560                 const VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
561                 {
562                         VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,     // VkStructureType                                                      sType;
563                         DE_NULL,                                                                                                        // const void*                                                          pNext;
564                         (VkPipelineDepthStencilStateCreateFlags)0,                                      // VkPipelineDepthStencilStateCreateFlags       flags;
565                         VK_FALSE,                                                                                                       // VkBool32                                                                     depthTestEnable;
566                         VK_FALSE,                                                                                                       // VkBool32                                                                     depthWriteEnable;
567                         VK_COMPARE_OP_LESS,                                                                                     // VkCompareOp                                                          depthCompareOp;
568                         VK_FALSE,                                                                                                       // VkBool32                                                                     depthBoundsTestEnable;
569                         VK_FALSE,                                                                                                       // VkBool32                                                                     stencilTestEnable;
570                         stencilOpState,                                                                                         // VkStencilOpState                                                     front;
571                         stencilOpState,                                                                                         // VkStencilOpState                                                     back;
572                         0.0f,                                                                                                           // float                                                                        minDepthBounds;
573                         1.0f,                                                                                                           // float                                                                        maxDepthBounds;
574                 };
575
576                 const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
577                 const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState =
578                 {
579                         m_blendEnable,                                          // VkBool32                                     blendEnable;
580                         VK_BLEND_FACTOR_SRC_ALPHA,                      // VkBlendFactor                        srcColorBlendFactor;
581                         VK_BLEND_FACTOR_ONE,                            // VkBlendFactor                        dstColorBlendFactor;
582                         VK_BLEND_OP_ADD,                                        // VkBlendOp                            colorBlendOp;
583                         VK_BLEND_FACTOR_SRC_ALPHA,                      // VkBlendFactor                        srcAlphaBlendFactor;
584                         VK_BLEND_FACTOR_ONE,                            // VkBlendFactor                        dstAlphaBlendFactor;
585                         VK_BLEND_OP_ADD,                                        // VkBlendOp                            alphaBlendOp;
586                         colorComponentsAll,                                     // VkColorComponentFlags        colorWriteMask;
587                 };
588
589                 const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
590                 {
591                         VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,       // VkStructureType                                                              sType;
592                         DE_NULL,                                                                                                        // const void*                                                                  pNext;
593                         (VkPipelineColorBlendStateCreateFlags)0,                                        // VkPipelineColorBlendStateCreateFlags                 flags;
594                         VK_FALSE,                                                                                                       // VkBool32                                                                             logicOpEnable;
595                         VK_LOGIC_OP_COPY,                                                                                       // VkLogicOp                                                                    logicOp;
596                         1u,                                                                                                                     // deUint32                                                                             attachmentCount;
597                         &pipelineColorBlendAttachmentState,                                                     // const VkPipelineColorBlendAttachmentState*   pAttachments;
598                         { 0.0f, 0.0f, 0.0f, 0.0f },                                                                     // float                                                                                blendConstants[4];
599                 };
600
601                 // Create shader stages
602
603                 std::vector<VkPipelineShaderStageCreateInfo>    shaderStages;
604                 VkShaderStageFlags                                                              stageFlags = (VkShaderStageFlags)0;
605
606                 DE_ASSERT(shaders.size() <= MAX_NUM_SHADER_MODULES);
607                 for (deUint32 shaderNdx = 0; shaderNdx < shaders.size(); ++shaderNdx)
608                 {
609                         m_shaderModules[shaderNdx] = createShaderModule(vk, device, *shaders[shaderNdx].binary, (VkShaderModuleCreateFlags)0);
610
611                         const VkPipelineShaderStageCreateInfo pipelineShaderStageInfo =
612                         {
613                                 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,    // VkStructureType                                              sType;
614                                 DE_NULL,                                                                                                // const void*                                                  pNext;
615                                 (VkPipelineShaderStageCreateFlags)0,                                    // VkPipelineShaderStageCreateFlags             flags;
616                                 shaders[shaderNdx].stage,                                                               // VkShaderStageFlagBits                                stage;
617                                 *m_shaderModules[shaderNdx],                                                    // VkShaderModule                                               module;
618                                 "main",                                                                                                 // const char*                                                  pName;
619                                 DE_NULL,                                                                                                // const VkSpecializationInfo*                  pSpecializationInfo;
620                         };
621
622                         shaderStages.push_back(pipelineShaderStageInfo);
623                         stageFlags |= shaders[shaderNdx].stage;
624                 }
625
626                 DE_ASSERT(
627                         (m_primitiveTopology != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST) ||
628                         (stageFlags & (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)));
629
630                 const bool tessellationEnabled = (m_primitiveTopology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST);
631                 const VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
632                 {
633                         VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,                                                // VkStructureType                                                                      sType;
634                         DE_NULL,                                                                                                                                // const void*                                                                          pNext;
635                         (VkPipelineCreateFlags)0,                                                                                               // VkPipelineCreateFlags                                                        flags;
636                         static_cast<deUint32>(shaderStages.size()),                                                             // deUint32                                                                                     stageCount;
637                         &shaderStages[0],                                                                                                               // const VkPipelineShaderStageCreateInfo*                       pStages;
638                         &vertexInputStateInfo,                                                                                                  // const VkPipelineVertexInputStateCreateInfo*          pVertexInputState;
639                         &pipelineInputAssemblyStateInfo,                                                                                // const VkPipelineInputAssemblyStateCreateInfo*        pInputAssemblyState;
640                         (tessellationEnabled ? &pipelineTessellationStateInfo : DE_NULL),               // const VkPipelineTessellationStateCreateInfo*         pTessellationState;
641                         &pipelineViewportStateInfo,                                                                                             // const VkPipelineViewportStateCreateInfo*                     pViewportState;
642                         &pipelineRasterizationStateInfo,                                                                                // const VkPipelineRasterizationStateCreateInfo*        pRasterizationState;
643                         &pipelineMultisampleStateInfo,                                                                                  // const VkPipelineMultisampleStateCreateInfo*          pMultisampleState;
644                         &pipelineDepthStencilStateInfo,                                                                                 // const VkPipelineDepthStencilStateCreateInfo*         pDepthStencilState;
645                         &pipelineColorBlendStateInfo,                                                                                   // const VkPipelineColorBlendStateCreateInfo*           pColorBlendState;
646                         DE_NULL,                                                                                                                                // const VkPipelineDynamicStateCreateInfo*                      pDynamicState;
647                         *m_pipelineLayout,                                                                                                              // VkPipelineLayout                                                                     layout;
648                         *m_renderPass,                                                                                                                  // VkRenderPass                                                                         renderPass;
649                         0u,                                                                                                                                             // deUint32                                                                                     subpass;
650                         DE_NULL,                                                                                                                                // VkPipeline                                                                           basePipelineHandle;
651                         0,                                                                                                                                              // deInt32                                                                                      basePipelineIndex;
652                 };
653
654                 m_pipeline = createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
655         }
656
657         // Record commands
658         {
659                 const VkDeviceSize zeroOffset = 0ull;
660
661                 beginCommandBuffer(vk, *m_cmdBuffer);
662
663                 // Begin render pass
664                 {
665                         const VkClearValue      clearValue = makeClearValueColor(Vec4(0.0f, 0.0f, 0.0f, 1.0f));
666                         const VkRect2D          renderArea =
667                         {
668                                 makeOffset2D(0, 0),
669                                 makeExtent2D(m_renderSize.x(), m_renderSize.y())
670                         };
671
672                         const VkRenderPassBeginInfo renderPassBeginInfo = {
673                                 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,               // VkStructureType         sType;
674                                 DE_NULL,                                                                                // const void*             pNext;
675                                 *m_renderPass,                                                                  // VkRenderPass            renderPass;
676                                 *m_framebuffer,                                                                 // VkFramebuffer           framebuffer;
677                                 renderArea,                                                                             // VkRect2D                renderArea;
678                                 1u,                                                                                             // uint32_t                clearValueCount;
679                                 &clearValue,                                                                    // const VkClearValue*     pClearValues;
680                         };
681
682                         vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
683                 }
684
685                 vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
686                 vk.cmdBindVertexBuffers(*m_cmdBuffer, 0u, 1u, &(**m_vertexBuffer), &zeroOffset);
687
688                 vk.cmdDraw(*m_cmdBuffer, m_numVertices, 1u, 0u, 1u);
689                 vk.cmdEndRenderPass(*m_cmdBuffer);
690
691                 // Barrier: draw -> copy from image
692                 {
693                         const VkImageMemoryBarrier barrier = makeImageMemoryBarrier(
694                                 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
695                                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
696                                 **m_colorImage, m_colorSubresourceRange);
697
698                         vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0,
699                                 0u, DE_NULL, 0u, DE_NULL, 1u, &barrier);
700                 }
701
702                 {
703                         const VkBufferImageCopy copyRegion = makeBufferImageCopy(makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u), m_imageExtent);
704                         vk.cmdCopyImageToBuffer(*m_cmdBuffer, **m_colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_colorAttachmentBuffer, 1u, &copyRegion);
705                 }
706
707                 // Barrier: copy to buffer -> host read
708                 {
709                         const VkBufferMemoryBarrier barrier = makeBufferMemoryBarrier(
710                                 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT,
711                                 **m_colorAttachmentBuffer, 0ull, VK_WHOLE_SIZE);
712
713                         vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0,
714                                 0u, DE_NULL, 1u, &barrier, 0u, DE_NULL);
715                 }
716
717                 endCommandBuffer(vk, *m_cmdBuffer);
718         }
719 }
720
721 void DrawContext::draw (void)
722 {
723         const DeviceInterface&  vk                      = m_context.getDeviceInterface();
724         const VkDevice                  device          = m_context.getDevice();
725         const VkQueue                   queue           = m_context.getUniversalQueue();
726         tcu::TestLog&                   log                     = m_context.getTestContext().getLog();
727
728         submitCommandsAndWait(vk, device, queue, *m_cmdBuffer);
729
730         log << tcu::LogImageSet("attachments", "") << tcu::LogImage("color0", "", getColorPixels()) << tcu::TestLog::EndImageSet;
731 }
732
733 tcu::ConstPixelBufferAccess DrawContext::getColorPixels (void) const
734 {
735         const DeviceInterface&  vk                      = m_context.getDeviceInterface();
736         const VkDevice                  device          = m_context.getDevice();
737
738         const Allocation& alloc = m_colorAttachmentBuffer->getAllocation();
739         invalidateMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), VK_WHOLE_SIZE);
740
741         return tcu::ConstPixelBufferAccess(mapVkFormat(m_colorFormat), m_imageExtent.width, m_imageExtent.height, m_imageExtent.depth, alloc.getHostPtr());
742 }
743 } // drawutil
744 } // vkt