Merge "Fix missing SSBO binding in EGL robustness tests"
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / draw / vktDrawImageObjectUtil.cpp
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 The Khronos Group Inc.
6  * Copyright (c) 2015 Intel Corporation
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 Image Object Util
23  *//*--------------------------------------------------------------------*/
24
25 #include "vktDrawImageObjectUtil.hpp"
26
27 #include "tcuSurface.hpp"
28 #include "tcuVectorUtil.hpp"
29
30 #include "vkRefUtil.hpp"
31 #include "vkQueryUtil.hpp"
32 #include "vkImageUtil.hpp"
33 #include "vktDrawCreateInfoUtil.hpp"
34 #include "vktDrawBufferObjectUtil.hpp"
35
36 #include "tcuTextureUtil.hpp"
37
38 namespace vkt
39 {
40 namespace Draw
41 {
42
43 void MemoryOp::pack (int                                pixelSize,
44                                          int                            width,
45                                          int                            height,
46                                          int                            depth,
47                                          vk::VkDeviceSize       rowPitchOrZero,
48                                          vk::VkDeviceSize       depthPitchOrZero,
49                                          const void *           srcBuffer,
50                                          void *                         destBuffer)
51 {
52         vk::VkDeviceSize rowPitch       = rowPitchOrZero;
53         vk::VkDeviceSize depthPitch     = depthPitchOrZero;
54
55         if (rowPitch == 0)
56                 rowPitch = width * pixelSize;
57
58         if (depthPitch == 0)
59                 depthPitch = rowPitch * height;
60
61         const vk::VkDeviceSize size = depthPitch * depth;
62
63         const deUint8 *srcRow = reinterpret_cast<const deUint8 *>(srcBuffer);
64         const deUint8 *srcStart;
65         srcStart = srcRow;
66         deUint8 *dstRow = reinterpret_cast<deUint8 *>(destBuffer);
67         deUint8 *dstStart;
68         dstStart = dstRow;
69
70         if (rowPitch == static_cast<vk::VkDeviceSize>(width * pixelSize) &&
71                 depthPitch == static_cast<vk::VkDeviceSize>(rowPitch * height))
72         {
73                 // fast path
74                 deMemcpy(dstRow, srcRow, static_cast<size_t>(size));
75         }
76         else
77         {
78                 // slower, per row path
79                 for (int d = 0; d < depth; d++)
80                 {
81                         vk::VkDeviceSize offsetDepthDst = d * depthPitch;
82                         vk::VkDeviceSize offsetDepthSrc = d * (pixelSize * width * height);
83                         srcRow = srcStart + offsetDepthSrc;
84                         dstRow = dstStart + offsetDepthDst;
85                         for (int r = 0; r < height; ++r)
86                         {
87                                 deMemcpy(dstRow, srcRow, static_cast<size_t>(rowPitch));
88                                 srcRow += pixelSize * width;
89                                 dstRow += rowPitch;
90                         }
91                 }
92         }
93 }
94
95 void MemoryOp::unpack (int                                      pixelSize,
96                                            int                                  width,
97                                            int                                  height,
98                                            int                                  depth,
99                                            vk::VkDeviceSize             rowPitchOrZero,
100                                            vk::VkDeviceSize             depthPitchOrZero,
101                                            const void *                 srcBuffer,
102                                            void *                               destBuffer)
103 {
104         vk::VkDeviceSize rowPitch       = rowPitchOrZero;
105         vk::VkDeviceSize depthPitch = depthPitchOrZero;
106
107         if (rowPitch == 0)
108                 rowPitch = width * pixelSize;
109
110         if (depthPitch == 0)
111                 depthPitch = rowPitch * height;
112
113         const vk::VkDeviceSize size = depthPitch * depth;
114
115         const deUint8 *srcRow = reinterpret_cast<const deUint8 *>(srcBuffer);
116         const deUint8 *srcStart;
117         srcStart = srcRow;
118         deUint8 *dstRow = reinterpret_cast<deUint8 *>(destBuffer);
119         deUint8 *dstStart;
120         dstStart = dstRow;
121
122         if (rowPitch == static_cast<vk::VkDeviceSize>(width * pixelSize) &&
123                 depthPitch == static_cast<vk::VkDeviceSize>(rowPitch * height))
124         {
125                 // fast path
126                 deMemcpy(dstRow, srcRow, static_cast<size_t>(size));
127         }
128         else {
129                 // slower, per row path
130                 for (size_t d = 0; d < (size_t)depth; d++)
131                 {
132                         vk::VkDeviceSize offsetDepthDst = d * (pixelSize * width * height);
133                         vk::VkDeviceSize offsetDepthSrc = d * depthPitch;
134                         srcRow = srcStart + offsetDepthSrc;
135                         dstRow = dstStart + offsetDepthDst;
136                         for (int r = 0; r < height; ++r)
137                         {
138                                 deMemcpy(dstRow, srcRow, static_cast<size_t>(pixelSize * width));
139                                 srcRow += rowPitch;
140                                 dstRow += pixelSize * width;
141                         }
142                 }
143         }
144 }
145
146 Image::Image (const vk::DeviceInterface& vk,
147                           vk::VkDevice                          device,
148                           vk::VkFormat                          format,
149                           const vk::VkExtent3D&         extend,
150                           deUint32                                      levelCount,
151                           deUint32                                      layerCount,
152                           vk::Move<vk::VkImage>         object_)
153         : m_allocation          (DE_NULL)
154         , m_object                      (object_)
155         , m_format                      (format)
156         , m_extent                      (extend)
157         , m_levelCount          (levelCount)
158         , m_layerCount          (layerCount)
159         , m_vk(vk)
160         , m_device(device)
161 {
162 }
163
164 tcu::ConstPixelBufferAccess Image::readSurface (vk::VkQueue                                     queue,
165                                                                                                 vk::Allocator&                          allocator,
166                                                                                                 vk::VkImageLayout                       layout,
167                                                                                                 vk::VkOffset3D                          offset,
168                                                                                                 int                                                     width,
169                                                                                                 int                                                     height,
170                                                                                                 vk::VkImageAspectFlagBits       aspect,
171                                                                                                 unsigned int                            mipLevel,
172                                                                                                 unsigned int                            arrayElement)
173 {
174         m_pixelAccessData.resize(width * height * vk::mapVkFormat(m_format).getPixelSize());
175         deMemset(m_pixelAccessData.data(), 0, m_pixelAccessData.size());
176         if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
177         {
178                 read(queue, allocator, layout, offset, width, height, 1, mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_2D,
179                 m_pixelAccessData.data());
180         }
181         if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
182         {
183                 readUsingBuffer(queue, allocator, layout, offset, width, height, 1, mipLevel, arrayElement, aspect, m_pixelAccessData.data());
184         }
185         return tcu::ConstPixelBufferAccess(vk::mapVkFormat(m_format), width, height, 1, m_pixelAccessData.data());
186 }
187
188 tcu::ConstPixelBufferAccess Image::readVolume (vk::VkQueue                                      queue,
189                                                                                            vk::Allocator&                               allocator,
190                                                                                            vk::VkImageLayout                    layout,
191                                                                                            vk::VkOffset3D                               offset,
192                                                                                            int                                                  width,
193                                                                                            int                                                  height,
194                                                                                            int                                                  depth,
195                                                                                            vk::VkImageAspectFlagBits    aspect,
196                                                                                            unsigned int                                 mipLevel,
197                                                                                            unsigned int                                 arrayElement)
198 {
199         m_pixelAccessData.resize(width * height * depth * vk::mapVkFormat(m_format).getPixelSize());
200         deMemset(m_pixelAccessData.data(), 0, m_pixelAccessData.size());
201         if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
202         {
203                 read(queue, allocator, layout, offset, width, height, depth, mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_3D,
204                 m_pixelAccessData.data());
205         }
206         if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
207         {
208                 readUsingBuffer(queue, allocator, layout, offset, width, height, depth, mipLevel, arrayElement, aspect, m_pixelAccessData.data());
209         }
210         return tcu::ConstPixelBufferAccess(vk::mapVkFormat(m_format), width, height, depth, m_pixelAccessData.data());
211 }
212
213 tcu::ConstPixelBufferAccess Image::readSurface1D(vk::VkQueue                            queue,
214                                                                                                  vk::Allocator&                         allocator,
215                                                                                                  vk::VkImageLayout                      layout,
216                                                                                                  vk::VkOffset3D                         offset,
217                                                                                                  int                                            width,
218                                                                                                  vk::VkImageAspectFlagBits      aspect,
219                                                                                                  unsigned int                           mipLevel,
220                                                                                                  unsigned int                           arrayElement)
221 {
222         m_pixelAccessData.resize(width * vk::mapVkFormat(m_format).getPixelSize());
223         deMemset(m_pixelAccessData.data(), 0, m_pixelAccessData.size());
224         if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
225         {
226                 read(queue, allocator, layout, offset, width, 1, 1, mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_1D,
227                 m_pixelAccessData.data());
228         }
229         if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
230         {
231                 readUsingBuffer(queue, allocator, layout, offset, width, 1, 1, mipLevel, arrayElement, aspect,
232                 m_pixelAccessData.data());
233         }
234         return tcu::ConstPixelBufferAccess(vk::mapVkFormat(m_format), width, 1, 1, m_pixelAccessData.data());
235 }
236
237 void Image::read (vk::VkQueue                                   queue,
238                                   vk::Allocator&                                allocator,
239                                   vk::VkImageLayout                             layout,
240                                   vk::VkOffset3D                                offset,
241                                   int                                                   width,
242                                   int                                                   height,
243                                   int                                                   depth,
244                                   unsigned int                                  mipLevel,
245                                   unsigned int                                  arrayElement,
246                                   vk::VkImageAspectFlagBits             aspect,
247                                   vk::VkImageType                               type,
248                                   void *                                                data)
249 {
250         DE_ASSERT(layout == vk::VK_IMAGE_LAYOUT_GENERAL || layout == vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
251
252         de::SharedPtr<Image> stagingResource = copyToLinearImage(queue, allocator, layout, offset, width,
253                                                                                                                          height, depth, mipLevel, arrayElement, aspect, type);
254         const vk::VkOffset3D zeroOffset = {0, 0, 0};
255         stagingResource->readLinear(zeroOffset, width, height, depth, 0, 0, aspect, data);
256 }
257
258 void Image::readUsingBuffer (vk::VkQueue                                queue,
259                                                          vk::Allocator&                         allocator,
260                                                          vk::VkImageLayout                      layout,
261                                                          vk::VkOffset3D                         offset,
262                                                          int                                            width,
263                                                          int                                            height,
264                                                          int                                            depth,
265                                                          unsigned int                           mipLevel,
266                                                          unsigned int                           arrayElement,
267                                                          vk::VkImageAspectFlagBits      aspect,
268                                                          void *                                         data)
269 {
270         DE_ASSERT(layout == vk::VK_IMAGE_LAYOUT_GENERAL || layout == vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);;
271
272         de::SharedPtr<Buffer> stagingResource;
273
274         bool isCombinedType = isCombinedDepthStencilType(vk::mapVkFormat(m_format).type);
275         vk::VkDeviceSize bufferSize = 0;
276
277         if (!isCombinedType)
278                 bufferSize = vk::mapVkFormat(m_format).getPixelSize() * width * height * depth;
279
280         if (isCombinedType)
281         {
282                 int pixelSize = 0;
283                 switch (m_format)
284                 {
285                         case vk::VK_FORMAT_D16_UNORM_S8_UINT:
286                                 pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 2 : 1;
287                                 break;
288                         case  vk::VK_FORMAT_D32_SFLOAT_S8_UINT:
289                                 pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 4 : 1;
290                                 break;
291                         case vk::VK_FORMAT_X8_D24_UNORM_PACK32:
292                         case vk::VK_FORMAT_D24_UNORM_S8_UINT:
293                                 pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 3 : 1;
294                                 break;
295
296                         default:
297                                 DE_FATAL("Not implemented");
298                 }
299                 bufferSize = pixelSize*width*height*depth;
300         }
301
302         BufferCreateInfo stagingBufferResourceCreateInfo(bufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT | vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
303         stagingResource = Buffer::createAndAlloc(m_vk, m_device, stagingBufferResourceCreateInfo, allocator, vk::MemoryRequirement::HostVisible);
304
305         {
306                 //todo [scygan] get proper queueFamilyIndex
307                 CmdPoolCreateInfo copyCmdPoolCreateInfo(0);
308                 vk::Unique<vk::VkCommandPool> copyCmdPool(vk::createCommandPool(m_vk, m_device, &copyCmdPoolCreateInfo));
309                 vk::Unique<vk::VkCommandBuffer> copyCmdBuffer(vk::allocateCommandBuffer(m_vk, m_device, *copyCmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
310
311                 CmdBufferBeginInfo beginInfo;
312                 VK_CHECK(m_vk.beginCommandBuffer(*copyCmdBuffer, &beginInfo));
313
314                 if (layout == vk::VK_IMAGE_LAYOUT_UNDEFINED)
315                 {
316                         layout = vk::VK_IMAGE_LAYOUT_GENERAL;
317
318                         vk::VkImageMemoryBarrier barrier;
319                         barrier.sType = vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
320                         barrier.pNext = DE_NULL;
321                         barrier.srcAccessMask = 0;
322                         barrier.dstAccessMask = 0;
323                         barrier.oldLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
324                         barrier.newLayout = vk::VK_IMAGE_LAYOUT_GENERAL;
325                         barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
326                         barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
327                         barrier.image = object();
328
329                         barrier.subresourceRange.aspectMask = aspect;
330                         barrier.subresourceRange.baseMipLevel = 0;
331                         barrier.subresourceRange.levelCount = m_levelCount;
332                         barrier.subresourceRange.baseArrayLayer = 0;
333                         barrier.subresourceRange.layerCount = m_layerCount;
334
335                         m_vk.cmdPipelineBarrier(*copyCmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (vk::VkDependencyFlags)0,
336                                                                         0, (const vk::VkMemoryBarrier*)DE_NULL,
337                                                                         0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
338                                                                         1, &barrier);
339                 }
340
341                 vk::VkBufferImageCopy region =
342                 {
343                         0, 0, 0,
344                         { (vk::VkImageAspectFlags)aspect, mipLevel, arrayElement, 1 },
345                         offset,
346                         { (deUint32)width, (deUint32)height, (deUint32)depth }
347                 };
348
349                 m_vk.cmdCopyImageToBuffer(*copyCmdBuffer, object(), layout, stagingResource->object(), 1, &region);
350                 VK_CHECK(m_vk.endCommandBuffer(*copyCmdBuffer));
351
352                 vk::VkSubmitInfo submitInfo =
353                 {
354                         vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,      // VkStructureType                      sType;
355                         DE_NULL,                                                        // const void*                          pNext;
356                         0,                                                                      // deUint32                                     waitSemaphoreCount;
357                         DE_NULL,                                                        // const VkSemaphore*           pWaitSemaphores;
358                         (const vk::VkPipelineStageFlags*)DE_NULL,
359                         1,                                                                      // deUint32                                     commandBufferCount;
360                         &copyCmdBuffer.get(),                           // const VkCommandBuffer*       pCommandBuffers;
361                         0,                                                                      // deUint32                                     signalSemaphoreCount;
362                         DE_NULL                                                         // const VkSemaphore*           pSignalSemaphores;
363                 };
364                 m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
365
366                 // TODO: make this less intrusive
367                 VK_CHECK(m_vk.queueWaitIdle(queue));
368         }
369
370         deUint8* destPtr = reinterpret_cast<deUint8*>(stagingResource->getBoundMemory().getHostPtr());
371         deMemcpy(data, destPtr, static_cast<size_t>(bufferSize));
372 }
373
374 tcu::ConstPixelBufferAccess Image::readSurfaceLinear (vk::VkOffset3D                            offset,
375                                                                                                           int                                                   width,
376                                                                                                           int                                                   height,
377                                                                                                           int                                                   depth,
378                                                                                                           vk::VkImageAspectFlagBits             aspect,
379                                                                                                           unsigned int                                  mipLevel,
380                                                                                                           unsigned int                                  arrayElement)
381 {
382         m_pixelAccessData.resize(width * height * vk::mapVkFormat(m_format).getPixelSize());
383         readLinear(offset, width, height, depth, mipLevel, arrayElement, aspect, m_pixelAccessData.data());
384         return tcu::ConstPixelBufferAccess(vk::mapVkFormat(m_format), width, height, 1, m_pixelAccessData.data());
385 }
386
387 void Image::readLinear (vk::VkOffset3D                          offset,
388                                                 int                                                     width,
389                                                 int                                                     height,
390                                                 int                                                     depth,
391                                                 unsigned int                            mipLevel,
392                                                 unsigned int                            arrayElement,
393                                                 vk::VkImageAspectFlagBits       aspect,
394                                                 void *                                          data)
395 {
396         DE_ASSERT(mipLevel < m_levelCount);
397         DE_ASSERT(arrayElement < m_layerCount);
398
399         vk::VkImageSubresource imageSubResource = { (vk::VkImageAspectFlags)aspect, mipLevel, arrayElement };
400
401         vk::VkSubresourceLayout imageLayout;
402         deMemset(&imageLayout, 0, sizeof(imageLayout));
403
404         m_vk.getImageSubresourceLayout(m_device, object(), &imageSubResource, &imageLayout);
405
406         const deUint8* srcPtr = reinterpret_cast<const deUint8*>(getBoundMemory().getHostPtr());
407         srcPtr += imageLayout.offset;
408         srcPtr += offset.z * imageLayout.depthPitch;
409         srcPtr += offset.y * imageLayout.rowPitch;
410         srcPtr += offset.x;
411
412         MemoryOp::unpack(vk::mapVkFormat(m_format).getPixelSize(), width, height, depth,
413                 imageLayout.rowPitch, imageLayout.depthPitch, srcPtr, data);
414 }
415
416 de::SharedPtr<Image> Image::copyToLinearImage (vk::VkQueue                                      queue,
417                                                                                            vk::Allocator&                               allocator,
418                                                                                            vk::VkImageLayout                    layout,
419                                                                                            vk::VkOffset3D                               offset,
420                                                                                            int                                                  width,
421                                                                                            int                                                  height,
422                                                                                            int                                                  depth,
423                                                                                            unsigned int                                 mipLevel,
424                                                                                            unsigned int                                 arrayElement,
425                                                                                            vk::VkImageAspectFlagBits    aspect,
426                                                                                            vk::VkImageType                              type)
427 {
428         de::SharedPtr<Image> stagingResource;
429         {
430                 vk::VkExtent3D stagingExtent = {(deUint32)width, (deUint32)height, (deUint32)depth};
431                 ImageCreateInfo stagingResourceCreateInfo(type, m_format, stagingExtent, 1, 1, vk::VK_SAMPLE_COUNT_1_BIT,
432                                                                                                   vk::VK_IMAGE_TILING_LINEAR, vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT);
433
434                 stagingResource = Image::createAndAlloc(m_vk, m_device, stagingResourceCreateInfo, allocator,
435                                                                                                 vk::MemoryRequirement::HostVisible);
436
437                 //todo [scygan] get proper queueFamilyIndex
438                 CmdPoolCreateInfo copyCmdPoolCreateInfo(0);
439                 vk::Unique<vk::VkCommandPool> copyCmdPool(vk::createCommandPool(m_vk, m_device, &copyCmdPoolCreateInfo));
440                 vk::Unique<vk::VkCommandBuffer> copyCmdBuffer(vk::allocateCommandBuffer(m_vk, m_device, *copyCmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
441
442                 CmdBufferBeginInfo beginInfo;
443                 VK_CHECK(m_vk.beginCommandBuffer(*copyCmdBuffer, &beginInfo));
444
445                 transition2DImage(m_vk, *copyCmdBuffer, stagingResource->object(), aspect, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_GENERAL);
446
447                 const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
448                 vk::VkImageCopy region = { { (vk::VkImageAspectFlags)aspect, mipLevel, arrayElement, 1}, offset, { (vk::VkImageAspectFlags)aspect, 0, 0, 1}, zeroOffset, {(deUint32)width, (deUint32)height, (deUint32)depth} };
449
450                 m_vk.cmdCopyImage(*copyCmdBuffer, object(), layout, stagingResource->object(), vk::VK_IMAGE_LAYOUT_GENERAL, 1, &region);
451                 VK_CHECK(m_vk.endCommandBuffer(*copyCmdBuffer));
452
453                 vk::VkSubmitInfo submitInfo =
454                 {
455                         vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,      // VkStructureType                      sType;
456                         DE_NULL,                                                        // const void*                          pNext;
457                         0,                                                                      // deUint32                                     waitSemaphoreCount;
458                         DE_NULL,                                                        // const VkSemaphore*           pWaitSemaphores;
459                         (const vk::VkPipelineStageFlags*)DE_NULL,
460                         1,                                                                      // deUint32                                     commandBufferCount;
461                         &copyCmdBuffer.get(),                           // const VkCommandBuffer*       pCommandBuffers;
462                         0,                                                                      // deUint32                                     signalSemaphoreCount;
463                         DE_NULL                                                         // const VkSemaphore*           pSignalSemaphores;
464                 };
465                 m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
466
467                 // TODO: make this less intrusive
468                 VK_CHECK(m_vk.queueWaitIdle(queue));
469         }
470         return stagingResource;
471 }
472
473 void Image::uploadVolume(const tcu::ConstPixelBufferAccess&     access,
474                                                  vk::VkQueue                                            queue,
475                                                  vk::Allocator&                                         allocator,
476                                                  vk::VkImageLayout                                      layout,
477                                                  vk::VkOffset3D                                         offset,
478                                                  vk::VkImageAspectFlagBits                      aspect,
479                                                  unsigned int                                           mipLevel,
480                                                  unsigned int                                           arrayElement)
481 {
482         if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
483         {
484                 upload(queue, allocator, layout, offset, access.getWidth(),
485                 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_3D,
486                 access.getDataPtr());
487         }
488         if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
489         {
490                 uploadUsingBuffer(queue, allocator, layout, offset, access.getWidth(),
491                 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, access.getDataPtr());
492         }
493 }
494
495 void Image::uploadSurface (const tcu::ConstPixelBufferAccess&   access,
496                                                    vk::VkQueue                                                  queue,
497                                                    vk::Allocator&                                               allocator,
498                                                    vk::VkImageLayout                                    layout,
499                                                    vk::VkOffset3D                                               offset,
500                                                    vk::VkImageAspectFlagBits                    aspect,
501                                                    unsigned int                                                 mipLevel,
502                                                    unsigned int                                                 arrayElement)
503 {
504         if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
505         {
506                 upload(queue, allocator, layout, offset, access.getWidth(),
507                         access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_2D,
508                         access.getDataPtr());
509         }
510         if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
511         {
512                 uploadUsingBuffer(queue, allocator, layout, offset, access.getWidth(),
513                         access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, access.getDataPtr());
514         }
515 }
516
517 void Image::uploadSurface1D (const tcu::ConstPixelBufferAccess& access,
518                                                          vk::VkQueue                                            queue,
519                                                          vk::Allocator&                                         allocator,
520                                                          vk::VkImageLayout                                      layout,
521                                                          vk::VkOffset3D                                         offset,
522                                                          vk::VkImageAspectFlagBits                      aspect,
523                                                          unsigned int                                           mipLevel,
524                                                          unsigned int                                           arrayElement)
525 {
526         if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
527         {
528                 upload(queue, allocator, layout, offset, access.getWidth(),
529                         access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_1D,
530                         access.getDataPtr());
531         }
532         if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
533         {
534                 uploadUsingBuffer(queue, allocator, layout, offset, access.getWidth(),
535                         access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, access.getDataPtr());
536         }
537 }
538
539 void Image::uploadSurfaceLinear (const tcu::ConstPixelBufferAccess&     access,
540                                                                  vk::VkOffset3D                                         offset,
541                                                                  int                                                            width,
542                                                                  int                                                            height,
543                                                                  int                                                            depth,
544                                                                  vk::VkImageAspectFlagBits                      aspect,
545                                                                  unsigned int                                           mipLevel,
546                                                                  unsigned int                                           arrayElement)
547 {
548         uploadLinear(offset, width, height, depth, mipLevel, arrayElement, aspect, access.getDataPtr());
549 }
550
551 void Image::upload (vk::VkQueue                                 queue,
552                                         vk::Allocator&                          allocator,
553                                         vk::VkImageLayout                       layout,
554                                         vk::VkOffset3D                          offset,
555                                         int                                                     width,
556                                         int                                                     height,
557                                         int                                                     depth,
558                                         unsigned int                            mipLevel,
559                                         unsigned int                            arrayElement,
560                                         vk::VkImageAspectFlagBits       aspect,
561                                         vk::VkImageType                         type,
562                                         const void *                            data)
563 {
564         DE_ASSERT(layout == vk::VK_IMAGE_LAYOUT_GENERAL || layout == vk::VK_IMAGE_LAYOUT_UNDEFINED || layout == vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
565
566         de::SharedPtr<Image> stagingResource;
567         vk::VkExtent3D extent = {(deUint32)width, (deUint32)height, (deUint32)depth};
568         ImageCreateInfo stagingResourceCreateInfo(
569                 type, m_format, extent, 1, 1, vk::VK_SAMPLE_COUNT_1_BIT,
570                 vk::VK_IMAGE_TILING_LINEAR, vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
571
572         stagingResource = Image::createAndAlloc(m_vk, m_device, stagingResourceCreateInfo, allocator,
573                                                                 vk::MemoryRequirement::HostVisible);
574
575         const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
576         stagingResource->uploadLinear(zeroOffset, width, height, depth, 0, 0, aspect, data);
577
578         {
579                 //todo [scygan] get proper queueFamilyIndex
580                 CmdPoolCreateInfo copyCmdPoolCreateInfo(0);
581                 vk::Unique<vk::VkCommandPool> copyCmdPool(vk::createCommandPool(m_vk, m_device, &copyCmdPoolCreateInfo));
582                 vk::Unique<vk::VkCommandBuffer> copyCmdBuffer(vk::allocateCommandBuffer(m_vk, m_device, *copyCmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
583
584                 CmdBufferBeginInfo beginInfo;
585                 VK_CHECK(m_vk.beginCommandBuffer(*copyCmdBuffer, &beginInfo));
586
587                 if (layout == vk::VK_IMAGE_LAYOUT_UNDEFINED)
588                 {
589                         layout = vk::VK_IMAGE_LAYOUT_GENERAL;
590
591                         vk::VkImageMemoryBarrier barrier;
592                         barrier.sType = vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
593                         barrier.pNext = DE_NULL;
594                         barrier.srcAccessMask = 0;
595                         barrier.dstAccessMask = 0;
596                         barrier.oldLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
597                         barrier.newLayout = vk::VK_IMAGE_LAYOUT_GENERAL;
598                         barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
599                         barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
600                         barrier.image = object();
601
602                         barrier.subresourceRange.aspectMask = aspect;
603                         barrier.subresourceRange.baseMipLevel = 0;
604                         barrier.subresourceRange.levelCount = m_levelCount;
605                         barrier.subresourceRange.baseArrayLayer = 0;
606                         barrier.subresourceRange.layerCount = m_layerCount;
607
608                         m_vk.cmdPipelineBarrier(*copyCmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (vk::VkDependencyFlags)0,
609                                                                         0, (const vk::VkMemoryBarrier*)DE_NULL,
610                                                                         0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
611                                                                         1, &barrier);
612                 }
613
614                 transition2DImage(m_vk, *copyCmdBuffer, stagingResource->object(), aspect, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_GENERAL);
615
616                 vk::VkImageCopy region = {{ (vk::VkImageAspectFlags)aspect, 0, 0, 1},
617                                                                         zeroOffset,
618                                                                         { (vk::VkImageAspectFlags)aspect, mipLevel, arrayElement, 1},
619                                                                         offset,
620                                                                         {(deUint32)width, (deUint32)height, (deUint32)depth}};
621
622                 m_vk.cmdCopyImage(*copyCmdBuffer, stagingResource->object(),
623                                                                 vk::VK_IMAGE_LAYOUT_GENERAL, object(), layout, 1, &region);
624                 VK_CHECK(m_vk.endCommandBuffer(*copyCmdBuffer));
625
626                 vk::VkSubmitInfo submitInfo =
627                 {
628                         vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,      // VkStructureType                      sType;
629                         DE_NULL,                                                        // const void*                          pNext;
630                         0,                                                                      // deUint32                                     waitSemaphoreCount;
631                         DE_NULL,                                                        // const VkSemaphore*           pWaitSemaphores;
632                         (const vk::VkPipelineStageFlags*)DE_NULL,
633                         1,                                                                      // deUint32                                     commandBufferCount;
634                         &copyCmdBuffer.get(),                           // const VkCommandBuffer*       pCommandBuffers;
635                         0,                                                                      // deUint32                                     signalSemaphoreCount;
636                         DE_NULL                                                         // const VkSemaphore*           pSignalSemaphores;
637                 };
638                 m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
639
640                 // TODO: make this less intrusive
641                 VK_CHECK(m_vk.queueWaitIdle(queue));
642         }
643 }
644
645 void Image::uploadUsingBuffer (vk::VkQueue                                      queue,
646                                                            vk::Allocator&                               allocator,
647                                                            vk::VkImageLayout                    layout,
648                                                            vk::VkOffset3D                               offset,
649                                                            int                                                  width,
650                                                            int                                                  height,
651                                                            int                                                  depth,
652                                                            unsigned int                                 mipLevel,
653                                                            unsigned int                                 arrayElement,
654                                                            vk::VkImageAspectFlagBits    aspect,
655                                                            const void *                                 data)
656 {
657         DE_ASSERT(layout == vk::VK_IMAGE_LAYOUT_GENERAL || layout == vk::VK_IMAGE_LAYOUT_UNDEFINED || layout == vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
658
659         de::SharedPtr<Buffer> stagingResource;
660         bool isCombinedType = isCombinedDepthStencilType(vk::mapVkFormat(m_format).type);
661         vk::VkDeviceSize bufferSize = 0;
662         if (!isCombinedType)
663                 bufferSize = vk::mapVkFormat(m_format).getPixelSize() *width*height*depth;
664         if (isCombinedType)
665         {
666                 int pixelSize = 0;
667                 switch (m_format)
668                 {
669                         case vk::VK_FORMAT_D16_UNORM_S8_UINT:
670                                 pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 2 : 1;
671                                 break;
672                         case  vk::VK_FORMAT_D32_SFLOAT_S8_UINT:
673                                 pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 4 : 1;
674                                 break;
675                         case vk::VK_FORMAT_X8_D24_UNORM_PACK32:
676                         case vk::VK_FORMAT_D24_UNORM_S8_UINT:
677                                 pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 3 : 1;
678                                 break;
679
680                         default:
681                                 DE_FATAL("Not implemented");
682                 }
683                 bufferSize = pixelSize*width*height*depth;
684         }
685         BufferCreateInfo stagingBufferResourceCreateInfo(bufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT | vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
686         stagingResource = Buffer::createAndAlloc(m_vk, m_device, stagingBufferResourceCreateInfo, allocator, vk::MemoryRequirement::HostVisible);
687         deUint8* destPtr = reinterpret_cast<deUint8*>(stagingResource->getBoundMemory().getHostPtr());
688         deMemcpy(destPtr, data, static_cast<size_t>(bufferSize));
689         vk::flushMappedMemoryRange(m_vk, m_device, stagingResource->getBoundMemory().getMemory(), stagingResource->getBoundMemory().getOffset(), bufferSize);
690         {
691                 //todo [scygan] get proper queueFamilyIndex
692                 CmdPoolCreateInfo copyCmdPoolCreateInfo(0);
693                 vk::Unique<vk::VkCommandPool> copyCmdPool(vk::createCommandPool(m_vk, m_device, &copyCmdPoolCreateInfo));
694                 vk::Unique<vk::VkCommandBuffer> copyCmdBuffer(vk::allocateCommandBuffer(m_vk, m_device, *copyCmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
695
696                 CmdBufferBeginInfo beginInfo;
697                 VK_CHECK(m_vk.beginCommandBuffer(*copyCmdBuffer, &beginInfo));
698
699                 if (layout == vk::VK_IMAGE_LAYOUT_UNDEFINED)
700                 {
701                         layout = vk::VK_IMAGE_LAYOUT_GENERAL;
702
703                         vk::VkImageMemoryBarrier barrier;
704                         barrier.sType = vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
705                         barrier.pNext = DE_NULL;
706                         barrier.srcAccessMask = 0;
707                         barrier.dstAccessMask = 0;
708                         barrier.oldLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
709                         barrier.newLayout = vk::VK_IMAGE_LAYOUT_GENERAL;
710                         barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
711                         barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
712                         barrier.image = object();
713
714                         barrier.subresourceRange.aspectMask = aspect;
715                         barrier.subresourceRange.baseMipLevel = 0;
716                         barrier.subresourceRange.levelCount = m_levelCount;
717                         barrier.subresourceRange.baseArrayLayer = 0;
718                         barrier.subresourceRange.layerCount = m_layerCount;
719
720                         m_vk.cmdPipelineBarrier(*copyCmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (vk::VkDependencyFlags)0,
721                                                                         0, (const vk::VkMemoryBarrier*)DE_NULL,
722                                                                         0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
723                                                                         1, &barrier);
724                 }
725
726                 vk::VkBufferImageCopy region = {
727                         0, 0, 0,
728                         { (vk::VkImageAspectFlags)aspect, mipLevel, arrayElement, 1 },
729                         offset,
730                         { (deUint32)width, (deUint32)height, (deUint32)depth }
731                 };
732
733                 m_vk.cmdCopyBufferToImage(*copyCmdBuffer, stagingResource->object(),
734                         object(), layout, 1, &region);
735                 VK_CHECK(m_vk.endCommandBuffer(*copyCmdBuffer));
736
737                 vk::VkSubmitInfo submitInfo =
738                 {
739                         vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,      // VkStructureType                      sType;
740                         DE_NULL,                                                        // const void*                          pNext;
741                         0,                                                                      // deUint32                                     waitSemaphoreCount;
742                         DE_NULL,                                                        // const VkSemaphore*           pWaitSemaphores;
743                         (const vk::VkPipelineStageFlags*)DE_NULL,
744                         1,                                                                      // deUint32                                     commandBufferCount;
745                         &copyCmdBuffer.get(),                           // const VkCommandBuffer*       pCommandBuffers;
746                         0,                                                                      // deUint32                                     signalSemaphoreCount;
747                         DE_NULL                                                         // const VkSemaphore*           pSignalSemaphores;
748                 };
749                 m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
750
751                 // TODO: make this less intrusive
752                 VK_CHECK(m_vk.queueWaitIdle(queue));
753         }
754 }
755
756 void Image::uploadLinear (vk::VkOffset3D                        offset,
757                                                   int                                           width,
758                                                   int                                           height,
759                                                   int                                           depth,
760                                                   unsigned int                          mipLevel,
761                                                   unsigned int                          arrayElement,
762                                                   vk::VkImageAspectFlagBits     aspect,
763                                                   const void *                          data)
764 {
765         DE_ASSERT(mipLevel < m_levelCount);
766         DE_ASSERT(arrayElement < m_layerCount);
767
768         vk::VkSubresourceLayout imageLayout;
769
770         vk::VkImageSubresource imageSubResource = { (vk::VkImageAspectFlags)aspect, mipLevel, arrayElement};
771
772         m_vk.getImageSubresourceLayout(m_device, object(), &imageSubResource,
773                                                                                                         &imageLayout);
774
775         deUint8* destPtr = reinterpret_cast<deUint8*>(getBoundMemory().getHostPtr());
776         destPtr += imageLayout.offset;
777         destPtr += offset.z * imageLayout.depthPitch;
778         destPtr += offset.y * imageLayout.rowPitch;
779         destPtr += offset.x;
780
781         MemoryOp::pack(vk::mapVkFormat(m_format).getPixelSize(), width, height, depth,
782                 imageLayout.rowPitch, imageLayout.depthPitch, data, destPtr);
783 }
784
785 void Image::bindMemory (de::MovePtr<vk::Allocation> allocation)
786 {
787         DE_ASSERT(allocation);
788         VK_CHECK(m_vk.bindImageMemory(m_device, *m_object, allocation->getMemory(), allocation->getOffset()));
789
790         DE_ASSERT(!m_allocation);
791         m_allocation = allocation;
792 }
793
794 de::SharedPtr<Image> Image::createAndAlloc(const vk::DeviceInterface&   vk,
795                                                                                    vk::VkDevice                                 device,
796                                                                                    const vk::VkImageCreateInfo& createInfo,
797                                                                                    vk::Allocator&                               allocator,
798                                                                                    vk::MemoryRequirement                memoryRequirement)
799 {
800         de::SharedPtr<Image> ret = create(vk, device, createInfo);
801
802         vk::VkMemoryRequirements imageRequirements = vk::getImageMemoryRequirements(vk, device, ret->object());
803         ret->bindMemory(allocator.allocate(imageRequirements, memoryRequirement));
804         return ret;
805 }
806
807 de::SharedPtr<Image> Image::create(const vk::DeviceInterface&   vk,
808                                                                    vk::VkDevice                                 device,
809                                                                    const vk::VkImageCreateInfo  &createInfo)
810 {
811         return de::SharedPtr<Image>(new Image(vk, device, createInfo.format, createInfo.extent,
812                                                                 createInfo.mipLevels, createInfo.arrayLayers,
813                                                                 vk::createImage(vk, device, &createInfo)));
814 }
815
816 void transition2DImage (const vk::DeviceInterface&      vk,
817                                                 vk::VkCommandBuffer                     cmdBuffer,
818                                                 vk::VkImage                                     image,
819                                                 vk::VkImageAspectFlags          aspectMask,
820                                                 vk::VkImageLayout                       oldLayout,
821                                                 vk::VkImageLayout                       newLayout,
822                                                 vk::VkAccessFlags                       srcAccessMask,
823                                                 vk::VkAccessFlags                       dstAccessMask)
824 {
825         vk::VkImageMemoryBarrier barrier;
826         barrier.sType                                                   = vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
827         barrier.pNext                                                   = DE_NULL;
828         barrier.srcAccessMask                                   = srcAccessMask;
829         barrier.dstAccessMask                                   = dstAccessMask;
830         barrier.oldLayout                                               = oldLayout;
831         barrier.newLayout                                               = newLayout;
832         barrier.srcQueueFamilyIndex                             = VK_QUEUE_FAMILY_IGNORED;
833         barrier.dstQueueFamilyIndex                             = VK_QUEUE_FAMILY_IGNORED;
834         barrier.image                                                   = image;
835         barrier.subresourceRange.aspectMask             = aspectMask;
836         barrier.subresourceRange.baseMipLevel   = 0;
837         barrier.subresourceRange.levelCount             = 1;
838         barrier.subresourceRange.baseArrayLayer = 0;
839         barrier.subresourceRange.layerCount             = 1;
840
841         vk.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (vk::VkDependencyFlags)0,
842                                                   0, (const vk::VkMemoryBarrier*)DE_NULL,
843                                                   0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
844                                                   1, &barrier);
845 }
846
847 void initialTransitionColor2DImage (const vk::DeviceInterface &vk, vk::VkCommandBuffer cmdBuffer, vk::VkImage image, vk::VkImageLayout layout)
848 {
849         transition2DImage(vk, cmdBuffer, image, vk::VK_IMAGE_ASPECT_COLOR_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, layout);
850 }
851
852 void initialTransitionDepth2DImage (const vk::DeviceInterface &vk, vk::VkCommandBuffer cmdBuffer, vk::VkImage image, vk::VkImageLayout layout)
853 {
854         transition2DImage(vk, cmdBuffer, image, vk::VK_IMAGE_ASPECT_DEPTH_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, layout);
855 }
856
857 void initialTransitionStencil2DImage (const vk::DeviceInterface &vk, vk::VkCommandBuffer cmdBuffer, vk::VkImage image, vk::VkImageLayout layout)
858 {
859         transition2DImage(vk, cmdBuffer, image, vk::VK_IMAGE_ASPECT_STENCIL_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, layout);
860 }
861
862 void initialTransitionDepthStencil2DImage (const vk::DeviceInterface&   vk,
863                                                                                    vk::VkCommandBuffer                  cmdBuffer,
864                                                                                    vk::VkImage                                  image,
865                                                                                    vk::VkImageLayout                    layout,
866                                                                                    vk::VkAccessFlags                    srcAccessMask,
867                                                                                    vk::VkAccessFlags                    dstAccessMask)
868 {
869         transition2DImage(vk, cmdBuffer, image, vk::VK_IMAGE_ASPECT_DEPTH_BIT | vk::VK_IMAGE_ASPECT_STENCIL_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, layout, srcAccessMask, dstAccessMask);
870 }
871
872 } // Draw
873 } // vkt