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