1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2016 The Khronos Group Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Synchronization operation abstraction
22 *//*--------------------------------------------------------------------*/
23
24 #include "vktSynchronizationOperation.hpp"
25 #include "vkDefs.hpp"
26 #include "vktTestCase.hpp"
27 #include "vktTestCaseUtil.hpp"
28 #include "vkRef.hpp"
29 #include "vkRefUtil.hpp"
30 #include "vkMemUtil.hpp"
31 #include "vkBarrierUtil.hpp"
32 #include "vkQueryUtil.hpp"
33 #include "vkTypeUtil.hpp"
34 #include "vkImageUtil.hpp"
35 #include "vkBuilderUtil.hpp"
36 #include "vkCmdUtil.hpp"
37 #include "vkObjUtil.hpp"
38 #include "deUniquePtr.hpp"
39 #include "tcuTestLog.hpp"
40 #include "tcuTextureUtil.hpp"
41 #include <vector>
42 #include <sstream>
43
44 namespace vkt
45 {
46 namespace synchronization
47 {
48 namespace
49 {
50 using namespace vk;
51
52 enum Constants
53 {
54 MAX_IMAGE_DIMENSION_2D = 0x1000u,
55 MAX_UBO_RANGE = 0x4000u,
56 MAX_UPDATE_BUFFER_SIZE = 0x10000u,
57 };
58
59 enum BufferType
60 {
61 BUFFER_TYPE_UNIFORM,
62 BUFFER_TYPE_STORAGE,
63 };
64
65 enum AccessMode
66 {
67 ACCESS_MODE_READ,
68 ACCESS_MODE_WRITE,
69 };
70
71 enum PipelineType
72 {
73 PIPELINE_TYPE_GRAPHICS,
74 PIPELINE_TYPE_COMPUTE,
75 };
76
77 static const char* const s_perVertexBlock = "gl_PerVertex {\n"
78 " vec4 gl_Position;\n"
79 "}";
80
81 static const SyncInfo emptySyncInfo =
82 {
83 0, // VkPipelineStageFlags stageMask;
84 0, // VkAccessFlags accessMask;
85 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout imageLayout;
86 };
87
getShaderStageName(VkShaderStageFlagBits stage)88 std::string getShaderStageName(VkShaderStageFlagBits stage)
89 {
90 switch (stage)
91 {
92 default:
93 DE_FATAL("Unhandled stage!");
94 return "";
95 case VK_SHADER_STAGE_COMPUTE_BIT:
96 return "compute";
97 case VK_SHADER_STAGE_FRAGMENT_BIT:
98 return "fragment";
99 case VK_SHADER_STAGE_VERTEX_BIT:
100 return "vertex";
101 case VK_SHADER_STAGE_GEOMETRY_BIT:
102 return "geometry";
103 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
104 return "tess_control";
105 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
106 return "tess_eval";
107 }
108 }
109
110 //! A pipeline that can be embedded inside an operation.
111 class Pipeline
112 {
113 public:
~Pipeline(void)114 virtual ~Pipeline (void) {}
115 virtual void recordCommands (OperationContext& context, const VkCommandBuffer cmdBuffer, const VkDescriptorSet descriptorSet) = 0;
116 };
117
118 //! Vertex data that covers the whole viewport with two triangles.
119 class VertexGrid
120 {
121 public:
VertexGrid(OperationContext & context)122 VertexGrid (OperationContext& context)
123 : m_vertexFormat (VK_FORMAT_R32G32B32A32_SFLOAT)
124 , m_vertexStride (tcu::getPixelSize(mapVkFormat(m_vertexFormat)))
125 {
126 const DeviceInterface& vk = context.getDeviceInterface();
127 const VkDevice device = context.getDevice();
128 Allocator& allocator = context.getAllocator();
129
130 // Vertex positions
131 {
132 m_vertexData.push_back(tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f));
133 m_vertexData.push_back(tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f));
134 m_vertexData.push_back(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
135
136 m_vertexData.push_back(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
137 m_vertexData.push_back(tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f));
138 m_vertexData.push_back(tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f));
139 }
140
141 {
142 const VkDeviceSize vertexDataSizeBytes = m_vertexData.size() * sizeof(m_vertexData[0]);
143
144 m_vertexBuffer = de::MovePtr<Buffer>(new Buffer(vk, device, allocator, makeBufferCreateInfo(vertexDataSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), MemoryRequirement::HostVisible));
145 DE_ASSERT(sizeof(m_vertexData[0]) == m_vertexStride);
146
147 {
148 const Allocation& alloc = m_vertexBuffer->getAllocation();
149
150 deMemcpy(alloc.getHostPtr(), &m_vertexData[0], static_cast<std::size_t>(vertexDataSizeBytes));
151 flushAlloc(vk, device, alloc);
152 }
153 }
154
155 // Indices
156 {
157 const VkDeviceSize indexBufferSizeBytes = sizeof(deUint32) * m_vertexData.size();
158 const deUint32 numIndices = static_cast<deUint32>(m_vertexData.size());
159
160 m_indexBuffer = de::MovePtr<Buffer>(new Buffer(vk, device, allocator, makeBufferCreateInfo(indexBufferSizeBytes, VK_BUFFER_USAGE_INDEX_BUFFER_BIT), MemoryRequirement::HostVisible));
161
162 {
163 const Allocation& alloc = m_indexBuffer->getAllocation();
164 deUint32* const pData = static_cast<deUint32*>(alloc.getHostPtr());
165
166 for (deUint32 i = 0; i < numIndices; ++i)
167 pData[i] = i;
168
169 flushAlloc(vk, device, alloc);
170 }
171 }
172 }
173
getVertexFormat(void) const174 VkFormat getVertexFormat (void) const { return m_vertexFormat; }
getVertexStride(void) const175 deUint32 getVertexStride (void) const { return m_vertexStride; }
getIndexType(void) const176 VkIndexType getIndexType (void) const { return VK_INDEX_TYPE_UINT32; }
getNumVertices(void) const177 deUint32 getNumVertices (void) const { return static_cast<deUint32>(m_vertexData.size()); }
getNumIndices(void) const178 deUint32 getNumIndices (void) const { return getNumVertices(); }
getVertexBuffer(void) const179 VkBuffer getVertexBuffer (void) const { return **m_vertexBuffer; }
getIndexBuffer(void) const180 VkBuffer getIndexBuffer (void) const { return **m_indexBuffer; }
181
182 private:
183 const VkFormat m_vertexFormat;
184 const deUint32 m_vertexStride;
185 std::vector<tcu::Vec4> m_vertexData;
186 de::MovePtr<Buffer> m_vertexBuffer;
187 de::MovePtr<Buffer> m_indexBuffer;
188 };
189
190 //! Add flags for all shader stages required to support a particular stage (e.g. fragment requires vertex as well).
getRequiredStages(const VkShaderStageFlagBits stage)191 VkShaderStageFlags getRequiredStages (const VkShaderStageFlagBits stage)
192 {
193 VkShaderStageFlags flags = 0;
194
195 DE_ASSERT(stage == VK_SHADER_STAGE_COMPUTE_BIT || (stage & VK_SHADER_STAGE_COMPUTE_BIT) == 0);
196
197 if (stage & VK_SHADER_STAGE_ALL_GRAPHICS)
198 flags |= VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
199
200 if (stage & (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT))
201 flags |= VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
202
203 if (stage & VK_SHADER_STAGE_GEOMETRY_BIT)
204 flags |= VK_SHADER_STAGE_GEOMETRY_BIT;
205
206 if (stage & VK_SHADER_STAGE_COMPUTE_BIT)
207 flags |= VK_SHADER_STAGE_COMPUTE_BIT;
208
209 return flags;
210 }
211
212 //! Check that SSBO read/write is available and that all shader stages are supported.
requireFeaturesForSSBOAccess(OperationContext & context,const VkShaderStageFlags usedStages)213 void requireFeaturesForSSBOAccess (OperationContext& context, const VkShaderStageFlags usedStages)
214 {
215 const InstanceInterface& vki = context.getInstanceInterface();
216 const VkPhysicalDevice physDevice = context.getPhysicalDevice();
217 FeatureFlags flags = (FeatureFlags)0;
218
219 if (usedStages & VK_SHADER_STAGE_FRAGMENT_BIT)
220 flags |= FEATURE_FRAGMENT_STORES_AND_ATOMICS;
221
222 if (usedStages & (VK_SHADER_STAGE_ALL_GRAPHICS & (~VK_SHADER_STAGE_FRAGMENT_BIT)))
223 flags |= FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS;
224
225 if (usedStages & VK_SHADER_STAGE_GEOMETRY_BIT)
226 flags |= FEATURE_GEOMETRY_SHADER;
227
228 if (usedStages & (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT))
229 flags |= FEATURE_TESSELLATION_SHADER;
230
231 requireFeatures(vki, physDevice, flags);
232 }
233
getHostBufferData(const OperationContext & context,const Buffer & hostBuffer,const VkDeviceSize size)234 Data getHostBufferData (const OperationContext& context, const Buffer& hostBuffer, const VkDeviceSize size)
235 {
236 const DeviceInterface& vk = context.getDeviceInterface();
237 const VkDevice device = context.getDevice();
238 const Allocation& alloc = hostBuffer.getAllocation();
239 const Data data =
240 {
241 static_cast<std::size_t>(size), // std::size_t size;
242 static_cast<deUint8*>(alloc.getHostPtr()), // const deUint8* data;
243 };
244
245 invalidateAlloc(vk, device, alloc);
246
247 return data;
248 }
249
setHostBufferData(const OperationContext & context,const Buffer & hostBuffer,const Data & data)250 void setHostBufferData (const OperationContext& context, const Buffer& hostBuffer, const Data& data)
251 {
252 const DeviceInterface& vk = context.getDeviceInterface();
253 const VkDevice device = context.getDevice();
254 const Allocation& alloc = hostBuffer.getAllocation();
255
256 deMemcpy(alloc.getHostPtr(), data.data, data.size);
257 flushAlloc(vk, device, alloc);
258 }
259
assertValidShaderStage(const VkShaderStageFlagBits stage)260 void assertValidShaderStage (const VkShaderStageFlagBits stage)
261 {
262 switch (stage)
263 {
264 case VK_SHADER_STAGE_VERTEX_BIT:
265 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
266 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
267 case VK_SHADER_STAGE_GEOMETRY_BIT:
268 case VK_SHADER_STAGE_FRAGMENT_BIT:
269 case VK_SHADER_STAGE_COMPUTE_BIT:
270 // OK
271 break;
272
273 default:
274 DE_FATAL("Invalid shader stage");
275 break;
276 }
277 }
278
pipelineStageFlagsFromShaderStageFlagBits(const VkShaderStageFlagBits shaderStage)279 VkPipelineStageFlags pipelineStageFlagsFromShaderStageFlagBits (const VkShaderStageFlagBits shaderStage)
280 {
281 switch (shaderStage)
282 {
283 case VK_SHADER_STAGE_VERTEX_BIT: return VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT_KHR;
284 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: return VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT_KHR;
285 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: return VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT_KHR;
286 case VK_SHADER_STAGE_GEOMETRY_BIT: return VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT_KHR;
287 case VK_SHADER_STAGE_FRAGMENT_BIT: return VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT_KHR;
288 case VK_SHADER_STAGE_COMPUTE_BIT: return VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT_KHR;
289
290 // Other usages are probably an error, so flag that.
291 default:
292 DE_FATAL("Invalid shader stage");
293 return (VkPipelineStageFlags)0;
294 }
295 }
296
297 //! Fill destination buffer with a repeating pattern.
fillPattern(void * const pData,const VkDeviceSize size,bool useIndexPattern=false)298 void fillPattern (void* const pData, const VkDeviceSize size, bool useIndexPattern = false)
299 {
300 // There are two pattern options - most operations use primePattern,
301 // indexPattern is only needed for testing vertex index bufffer.
302 static const deUint8 primePattern[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31 };
303 static const deUint32 indexPattern[] = { 0, 1, 2, 3, 4 };
304
305 const deUint8* pattern = (useIndexPattern ? reinterpret_cast<const deUint8*>(indexPattern)
306 : primePattern);
307 const deUint32 patternSize = static_cast<deUint32>(useIndexPattern
308 ? DE_LENGTH_OF_ARRAY(indexPattern)*sizeof(deUint32)
309 : DE_LENGTH_OF_ARRAY(primePattern));
310 deUint8* const pBytes = static_cast<deUint8*>(pData);
311
312 for (deUint32 i = 0; i < size; ++i)
313 pBytes[i] = pattern[i % patternSize];
314 }
315
316 //! Get size in bytes of a pixel buffer with given extent.
getPixelBufferSize(const VkFormat format,const VkExtent3D & extent)317 VkDeviceSize getPixelBufferSize (const VkFormat format, const VkExtent3D& extent)
318 {
319 const int pixelSize = tcu::getPixelSize(mapVkFormat(format));
320 return (pixelSize * extent.width * extent.height * extent.depth);
321 }
322
323 //! Determine the size of a 2D image that can hold sizeBytes data.
get2DImageExtentWithSize(const VkDeviceSize sizeBytes,const deUint32 pixelSize)324 VkExtent3D get2DImageExtentWithSize (const VkDeviceSize sizeBytes, const deUint32 pixelSize)
325 {
326 const deUint32 size = static_cast<deUint32>(sizeBytes / pixelSize);
327
328 DE_ASSERT(size <= MAX_IMAGE_DIMENSION_2D * MAX_IMAGE_DIMENSION_2D);
329
330 return makeExtent3D(
331 std::min(size, static_cast<deUint32>(MAX_IMAGE_DIMENSION_2D)),
332 (size / MAX_IMAGE_DIMENSION_2D) + (size % MAX_IMAGE_DIMENSION_2D != 0 ? 1u : 0u),
333 1u);
334 }
335
makeClearValue(const VkFormat format)336 VkClearValue makeClearValue (const VkFormat format)
337 {
338 if (isDepthStencilFormat(format))
339 return makeClearValueDepthStencil(0.4f, 21u);
340 else
341 {
342 if (isIntFormat(format) || isUintFormat(format))
343 return makeClearValueColorU32(8u, 16u, 24u, 32u);
344 else
345 return makeClearValueColorF32(0.25f, 0.49f, 0.75f, 1.0f);
346 }
347 }
348
clearPixelBuffer(tcu::PixelBufferAccess & pixels,const VkClearValue & clearValue)349 void clearPixelBuffer (tcu::PixelBufferAccess& pixels, const VkClearValue& clearValue)
350 {
351 const tcu::TextureFormat format = pixels.getFormat();
352 const tcu::TextureChannelClass channelClass = tcu::getTextureChannelClass(format.type);
353
354 if (format.order == tcu::TextureFormat::D)
355 {
356 for (int z = 0; z < pixels.getDepth(); z++)
357 for (int y = 0; y < pixels.getHeight(); y++)
358 for (int x = 0; x < pixels.getWidth(); x++)
359 pixels.setPixDepth(clearValue.depthStencil.depth, x, y, z);
360 }
361 else if (format.order == tcu::TextureFormat::S)
362 {
363 for (int z = 0; z < pixels.getDepth(); z++)
364 for (int y = 0; y < pixels.getHeight(); y++)
365 for (int x = 0; x < pixels.getWidth(); x++)
366 pixels.setPixStencil(clearValue.depthStencil.stencil, x, y, z);
367 }
368 else if (format.order == tcu::TextureFormat::DS)
369 {
370 for (int z = 0; z < pixels.getDepth(); z++)
371 for (int y = 0; y < pixels.getHeight(); y++)
372 for (int x = 0; x < pixels.getWidth(); x++)
373 {
374 pixels.setPixDepth(clearValue.depthStencil.depth, x, y, z);
375 pixels.setPixStencil(clearValue.depthStencil.stencil, x, y, z);
376 }
377 }
378 else if (channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER || channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
379 {
380 const tcu::UVec4 color (clearValue.color.uint32);
381
382 for (int z = 0; z < pixels.getDepth(); z++)
383 for (int y = 0; y < pixels.getHeight(); y++)
384 for (int x = 0; x < pixels.getWidth(); x++)
385 pixels.setPixel(color, x, y, z);
386 }
387 else
388 {
389 const tcu::Vec4 color (clearValue.color.float32);
390
391 for (int z = 0; z < pixels.getDepth(); z++)
392 for (int y = 0; y < pixels.getHeight(); y++)
393 for (int x = 0; x < pixels.getWidth(); x++)
394 pixels.setPixel(color, x, y, z);
395 }
396 }
397
getImageViewType(const VkImageType imageType)398 VkImageViewType getImageViewType (const VkImageType imageType)
399 {
400 switch (imageType)
401 {
402 case VK_IMAGE_TYPE_1D: return VK_IMAGE_VIEW_TYPE_1D;
403 case VK_IMAGE_TYPE_2D: return VK_IMAGE_VIEW_TYPE_2D;
404 case VK_IMAGE_TYPE_3D: return VK_IMAGE_VIEW_TYPE_3D;
405
406 default:
407 DE_FATAL("Unknown image type");
408 return VK_IMAGE_VIEW_TYPE_LAST;
409 }
410 }
411
getShaderImageType(const VkFormat format,const VkImageType imageType)412 std::string getShaderImageType (const VkFormat format, const VkImageType imageType)
413 {
414 const tcu::TextureFormat texFormat = mapVkFormat(format);
415 const std::string formatPart = tcu::getTextureChannelClass(texFormat.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER ? "u" :
416 tcu::getTextureChannelClass(texFormat.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER ? "i" : "";
417 switch (imageType)
418 {
419 case VK_IMAGE_TYPE_1D: return formatPart + "image1D";
420 case VK_IMAGE_TYPE_2D: return formatPart + "image2D";
421 case VK_IMAGE_TYPE_3D: return formatPart + "image3D";
422
423 default:
424 DE_FATAL("Unknown image type");
425 return "";
426 }
427 }
428
getShaderImageFormatQualifier(const VkFormat format)429 std::string getShaderImageFormatQualifier (const VkFormat format)
430 {
431 const tcu::TextureFormat texFormat = mapVkFormat(format);
432 const char* orderPart = DE_NULL;
433 const char* typePart = DE_NULL;
434
435 switch (texFormat.order)
436 {
437 case tcu::TextureFormat::R: orderPart = "r"; break;
438 case tcu::TextureFormat::RG: orderPart = "rg"; break;
439 case tcu::TextureFormat::RGB: orderPart = "rgb"; break;
440 case tcu::TextureFormat::RGBA: orderPart = "rgba"; break;
441
442 default:
443 DE_FATAL("Unksupported texture channel order");
444 break;
445 }
446
447 switch (texFormat.type)
448 {
449 case tcu::TextureFormat::FLOAT: typePart = "32f"; break;
450 case tcu::TextureFormat::HALF_FLOAT: typePart = "16f"; break;
451
452 case tcu::TextureFormat::UNSIGNED_INT32: typePart = "32ui"; break;
453 case tcu::TextureFormat::UNSIGNED_INT16: typePart = "16ui"; break;
454 case tcu::TextureFormat::UNSIGNED_INT8: typePart = "8ui"; break;
455
456 case tcu::TextureFormat::SIGNED_INT32: typePart = "32i"; break;
457 case tcu::TextureFormat::SIGNED_INT16: typePart = "16i"; break;
458 case tcu::TextureFormat::SIGNED_INT8: typePart = "8i"; break;
459
460 case tcu::TextureFormat::UNORM_INT16: typePart = "16"; break;
461 case tcu::TextureFormat::UNORM_INT8: typePart = "8"; break;
462
463 case tcu::TextureFormat::SNORM_INT16: typePart = "16_snorm"; break;
464 case tcu::TextureFormat::SNORM_INT8: typePart = "8_snorm"; break;
465
466 default:
467 DE_FATAL("Unksupported texture channel type");
468 break;
469 }
470
471 return std::string(orderPart) + typePart;
472 }
473
474 namespace FillUpdateBuffer
475 {
476
477 enum BufferOp
478 {
479 BUFFER_OP_FILL,
480 BUFFER_OP_UPDATE,
481 BUFFER_OP_UPDATE_WITH_INDEX_PATTERN,
482 };
483
484 class Implementation : public Operation
485 {
486 public:
Implementation(OperationContext & context,Resource & resource,const BufferOp bufferOp)487 Implementation (OperationContext& context, Resource& resource, const BufferOp bufferOp)
488 : m_context (context)
489 , m_resource (resource)
490 , m_fillValue (0x13)
491 , m_bufferOp (bufferOp)
492 {
493 DE_ASSERT((m_resource.getBuffer().size % sizeof(deUint32)) == 0);
494 DE_ASSERT(m_bufferOp == BUFFER_OP_FILL || m_resource.getBuffer().size <= MAX_UPDATE_BUFFER_SIZE);
495
496 m_data.resize(static_cast<size_t>(m_resource.getBuffer().size));
497
498 if (m_bufferOp == BUFFER_OP_FILL)
499 {
500 const std::size_t size = m_data.size() / sizeof(m_fillValue);
501 deUint32* const pData = reinterpret_cast<deUint32*>(&m_data[0]);
502
503 for (deUint32 i = 0; i < size; ++i)
504 pData[i] = m_fillValue;
505 }
506 else if (m_bufferOp == BUFFER_OP_UPDATE)
507 {
508 fillPattern(&m_data[0], m_data.size());
509 }
510 else if(m_bufferOp == BUFFER_OP_UPDATE_WITH_INDEX_PATTERN)
511 {
512 fillPattern(&m_data[0], m_data.size(), true);
513 }
514 }
515
recordCommands(const VkCommandBuffer cmdBuffer)516 void recordCommands (const VkCommandBuffer cmdBuffer)
517 {
518 const DeviceInterface& vk = m_context.getDeviceInterface();
519
520 if (m_bufferOp == BUFFER_OP_FILL)
521 {
522 vk.cmdFillBuffer(cmdBuffer, m_resource.getBuffer().handle, m_resource.getBuffer().offset, m_resource.getBuffer().size, m_fillValue);
523
524 SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
525 const VkBufferMemoryBarrier2KHR bufferMemoryBarrier2 = makeBufferMemoryBarrier2(
526 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags2KHR srcStageMask
527 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR, // VkAccessFlags2KHR srcAccessMask
528 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags2KHR dstStageMask
529 VK_ACCESS_2_TRANSFER_READ_BIT_KHR, // VkAccessFlags2KHR dstAccessMask
530 m_resource.getBuffer().handle, // VkBuffer buffer
531 0u, // VkDeviceSize offset
532 m_resource.getBuffer().size // VkDeviceSize size
533 );
534 VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, &bufferMemoryBarrier2);
535 synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
536 }
537 else
538 vk.cmdUpdateBuffer(cmdBuffer, m_resource.getBuffer().handle, m_resource.getBuffer().offset, m_resource.getBuffer().size, reinterpret_cast<deUint32*>(&m_data[0]));
539 }
540
getInSyncInfo(void) const541 SyncInfo getInSyncInfo (void) const
542 {
543 return emptySyncInfo;
544 }
545
getOutSyncInfo(void) const546 SyncInfo getOutSyncInfo (void) const
547 {
548 const SyncInfo syncInfo =
549 {
550 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags stageMask;
551 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR, // VkAccessFlags accessMask;
552 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout imageLayout;
553 };
554
555 return syncInfo;
556 }
557
getData(void) const558 Data getData (void) const
559 {
560 const Data data =
561 {
562 m_data.size(), // std::size_t size;
563 &m_data[0], // const deUint8* data;
564 };
565 return data;
566 }
567
setData(const Data & data)568 void setData (const Data& data)
569 {
570 deMemcpy(&m_data[0], data.data, data.size);
571 }
572
573 private:
574 OperationContext& m_context;
575 Resource& m_resource;
576 std::vector<deUint8> m_data;
577 const deUint32 m_fillValue;
578 const BufferOp m_bufferOp;
579 };
580
581 class Support : public OperationSupport
582 {
583 public:
Support(const ResourceDescription & resourceDesc,const BufferOp bufferOp)584 Support (const ResourceDescription& resourceDesc, const BufferOp bufferOp)
585 : m_resourceDesc (resourceDesc)
586 , m_bufferOp (bufferOp)
587 {
588 DE_ASSERT(m_bufferOp == BUFFER_OP_FILL || m_bufferOp == BUFFER_OP_UPDATE || m_bufferOp == BUFFER_OP_UPDATE_WITH_INDEX_PATTERN);
589 DE_ASSERT(m_resourceDesc.type == RESOURCE_TYPE_BUFFER || m_resourceDesc.type == RESOURCE_TYPE_INDEX_BUFFER);
590 }
591
getInResourceUsageFlags(void) const592 deUint32 getInResourceUsageFlags (void) const
593 {
594 return 0;
595 }
596
getOutResourceUsageFlags(void) const597 deUint32 getOutResourceUsageFlags (void) const
598 {
599 return VK_BUFFER_USAGE_TRANSFER_DST_BIT;
600 }
601
getQueueFlags(const OperationContext & context) const602 VkQueueFlags getQueueFlags (const OperationContext& context) const
603 {
604 if (m_bufferOp == BUFFER_OP_FILL && !context.isDeviceFunctionalitySupported("VK_KHR_maintenance1"))
605 {
606 return VK_QUEUE_COMPUTE_BIT | VK_QUEUE_GRAPHICS_BIT;
607 }
608
609 return VK_QUEUE_TRANSFER_BIT;
610 }
611
build(OperationContext & context,Resource & resource) const612 de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
613 {
614 return de::MovePtr<Operation>(new Implementation(context, resource, m_bufferOp));
615 }
616
build(OperationContext &,Resource &,Resource &) const617 de::MovePtr<Operation> build (OperationContext&, Resource&, Resource&) const
618 {
619 DE_ASSERT(0);
620 return de::MovePtr<Operation>();
621 }
622
623 private:
624 const ResourceDescription m_resourceDesc;
625 const BufferOp m_bufferOp;
626 };
627
628 } // FillUpdateBuffer ns
629
630 namespace CopyBuffer
631 {
632
633 class Implementation : public Operation
634 {
635 public:
Implementation(OperationContext & context,Resource & resource,const AccessMode mode)636 Implementation (OperationContext& context, Resource& resource, const AccessMode mode)
637 : m_context (context)
638 , m_resource (resource)
639 , m_mode (mode)
640 {
641 const DeviceInterface& vk = m_context.getDeviceInterface();
642 const VkDevice device = m_context.getDevice();
643 Allocator& allocator = m_context.getAllocator();
644 const VkBufferUsageFlags hostBufferUsage = (m_mode == ACCESS_MODE_READ ? VK_BUFFER_USAGE_TRANSFER_DST_BIT : VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
645
646 m_hostBuffer = de::MovePtr<Buffer>(new Buffer(vk, device, allocator, makeBufferCreateInfo(m_resource.getBuffer().size, hostBufferUsage), MemoryRequirement::HostVisible));
647
648 const Allocation& alloc = m_hostBuffer->getAllocation();
649
650 if (m_mode == ACCESS_MODE_READ)
651 deMemset(alloc.getHostPtr(), 0, static_cast<size_t>(m_resource.getBuffer().size));
652 else
653 fillPattern(alloc.getHostPtr(), m_resource.getBuffer().size);
654
655 flushAlloc(vk, device, alloc);
656 }
657
recordCommands(const VkCommandBuffer cmdBuffer)658 void recordCommands (const VkCommandBuffer cmdBuffer)
659 {
660 const DeviceInterface& vk = m_context.getDeviceInterface();
661 const VkBufferCopy copyRegion = makeBufferCopy(0u, 0u, m_resource.getBuffer().size);
662 SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
663
664 if (m_mode == ACCESS_MODE_READ)
665 {
666 vk.cmdCopyBuffer(cmdBuffer, m_resource.getBuffer().handle, **m_hostBuffer, 1u, ©Region);
667
668 // Insert a barrier so copied data is available to the host
669 const VkBufferMemoryBarrier2KHR bufferMemoryBarrier2 = makeBufferMemoryBarrier2(
670 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags2KHR srcStageMask
671 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR, // VkAccessFlags2KHR srcAccessMask
672 VK_PIPELINE_STAGE_2_HOST_BIT_KHR, // VkPipelineStageFlags2KHR dstStageMask
673 VK_ACCESS_2_HOST_READ_BIT_KHR, // VkAccessFlags2KHR dstAccessMask
674 **m_hostBuffer, // VkBuffer buffer
675 0u, // VkDeviceSize offset
676 m_resource.getBuffer().size // VkDeviceSize size
677 );
678 VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, &bufferMemoryBarrier2);
679 synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
680 }
681 else
682 {
683 // Insert a barrier so buffer data is available to the device
684 //const VkBufferMemoryBarrier2KHR bufferMemoryBarrier2 = makeBufferMemoryBarrier2(
685 // VK_PIPELINE_STAGE_2_HOST_BIT_KHR, // VkPipelineStageFlags2KHR srcStageMask
686 // VK_ACCESS_2_HOST_WRITE_BIT_KHR, // VkAccessFlags2KHR srcAccessMask
687 // VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags2KHR dstStageMask
688 // VK_ACCESS_2_TRANSFER_READ_BIT_KHR, // VkAccessFlags2KHR dstAccessMask
689 // **m_hostBuffer, // VkBuffer buffer
690 // 0u, // VkDeviceSize offset
691 // m_resource.getBuffer().size // VkDeviceSize size
692 //);
693 //VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, &bufferMemoryBarrier2);
694 //synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
695
696 vk.cmdCopyBuffer(cmdBuffer, **m_hostBuffer, m_resource.getBuffer().handle, 1u, ©Region);
697 }
698 }
699
getInSyncInfo(void) const700 SyncInfo getInSyncInfo (void) const
701 {
702 const VkAccessFlags access = (m_mode == ACCESS_MODE_READ ? VK_ACCESS_2_TRANSFER_READ_BIT_KHR : 0);
703 const SyncInfo syncInfo =
704 {
705 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags stageMask;
706 access, // VkAccessFlags accessMask;
707 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout imageLayout;
708 };
709 return syncInfo;
710 }
711
getOutSyncInfo(void) const712 SyncInfo getOutSyncInfo (void) const
713 {
714 const VkAccessFlags access = (m_mode == ACCESS_MODE_WRITE ? VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR : 0);
715 const SyncInfo syncInfo =
716 {
717 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags stageMask;
718 access, // VkAccessFlags accessMask;
719 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout imageLayout;
720 };
721 return syncInfo;
722 }
723
getData(void) const724 Data getData (void) const
725 {
726 return getHostBufferData(m_context, *m_hostBuffer, m_resource.getBuffer().size);
727 }
728
setData(const Data & data)729 void setData (const Data& data)
730 {
731 DE_ASSERT(m_mode == ACCESS_MODE_WRITE);
732 setHostBufferData(m_context, *m_hostBuffer, data);
733 }
734
735 private:
736 OperationContext& m_context;
737 Resource& m_resource;
738 const AccessMode m_mode;
739 de::MovePtr<Buffer> m_hostBuffer;
740 };
741
742 class Support : public OperationSupport
743 {
744 public:
Support(const ResourceDescription & resourceDesc,const AccessMode mode)745 Support (const ResourceDescription& resourceDesc, const AccessMode mode)
746 : m_mode (mode)
747 {
748 DE_ASSERT(resourceDesc.type == RESOURCE_TYPE_BUFFER);
749 DE_UNREF(resourceDesc);
750 }
751
getInResourceUsageFlags(void) const752 deUint32 getInResourceUsageFlags (void) const
753 {
754 return m_mode == ACCESS_MODE_READ ? VK_BUFFER_USAGE_TRANSFER_SRC_BIT : 0;
755 }
756
getOutResourceUsageFlags(void) const757 deUint32 getOutResourceUsageFlags (void) const
758 {
759 return m_mode == ACCESS_MODE_WRITE ? VK_BUFFER_USAGE_TRANSFER_DST_BIT : 0;
760 }
761
getQueueFlags(const OperationContext & context) const762 VkQueueFlags getQueueFlags (const OperationContext& context) const
763 {
764 DE_UNREF(context);
765 return VK_QUEUE_TRANSFER_BIT;
766 }
767
build(OperationContext & context,Resource & resource) const768 de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
769 {
770 return de::MovePtr<Operation>(new Implementation(context, resource, m_mode));
771 }
772
build(OperationContext &,Resource &,Resource &) const773 de::MovePtr<Operation> build (OperationContext&, Resource&, Resource&) const
774 {
775 DE_ASSERT(0);
776 return de::MovePtr<Operation>();
777 }
778
779 private:
780 const AccessMode m_mode;
781 };
782
783 class CopyImplementation : public Operation
784 {
785 public:
CopyImplementation(OperationContext & context,Resource & inResource,Resource & outResource)786 CopyImplementation (OperationContext& context, Resource& inResource, Resource& outResource)
787 : m_context (context)
788 , m_inResource (inResource)
789 , m_outResource (outResource)
790 {
791 }
792
recordCommands(const VkCommandBuffer cmdBuffer)793 void recordCommands (const VkCommandBuffer cmdBuffer)
794 {
795 const DeviceInterface& vk = m_context.getDeviceInterface();
796 const VkBufferCopy copyRegion = makeBufferCopy(0u, 0u, m_inResource.getBuffer().size);
797
798 vk.cmdCopyBuffer(cmdBuffer, m_inResource.getBuffer().handle, m_outResource.getBuffer().handle, 1u, ©Region);
799 }
800
getInSyncInfo(void) const801 SyncInfo getInSyncInfo (void) const
802 {
803 const SyncInfo syncInfo =
804 {
805 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags stageMask;
806 VK_ACCESS_2_TRANSFER_READ_BIT_KHR, // VkAccessFlags accessMask;
807 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout imageLayout;
808 };
809 return syncInfo;
810 }
811
getOutSyncInfo(void) const812 SyncInfo getOutSyncInfo (void) const
813 {
814 const SyncInfo syncInfo =
815 {
816 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags stageMask;
817 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR, // VkAccessFlags accessMask;
818 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout imageLayout;
819 };
820 return syncInfo;
821 }
822
getData(void) const823 Data getData (void) const
824 {
825 Data data = { 0, DE_NULL };
826 return data;
827 }
828
setData(const Data &)829 void setData (const Data&)
830 {
831 DE_ASSERT(0);
832 }
833
834 private:
835 OperationContext& m_context;
836 Resource& m_inResource;
837 Resource& m_outResource;
838 de::MovePtr<Buffer> m_hostBuffer;
839 };
840
841 class CopySupport : public OperationSupport
842 {
843 public:
CopySupport(const ResourceDescription & resourceDesc)844 CopySupport (const ResourceDescription& resourceDesc)
845 {
846 DE_ASSERT(resourceDesc.type == RESOURCE_TYPE_BUFFER);
847 DE_UNREF(resourceDesc);
848 }
849
getInResourceUsageFlags(void) const850 deUint32 getInResourceUsageFlags (void) const
851 {
852 return VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
853 }
854
getOutResourceUsageFlags(void) const855 deUint32 getOutResourceUsageFlags (void) const
856 {
857 return VK_BUFFER_USAGE_TRANSFER_DST_BIT;
858 }
859
getQueueFlags(const OperationContext & context) const860 VkQueueFlags getQueueFlags (const OperationContext& context) const
861 {
862 DE_UNREF(context);
863 return VK_QUEUE_TRANSFER_BIT;
864 }
865
build(OperationContext &,Resource &) const866 de::MovePtr<Operation> build (OperationContext&, Resource&) const
867 {
868 DE_ASSERT(0);
869 return de::MovePtr<Operation>();
870 }
871
build(OperationContext & context,Resource & inResource,Resource & outResource) const872 de::MovePtr<Operation> build (OperationContext& context, Resource& inResource, Resource& outResource) const
873 {
874 return de::MovePtr<Operation>(new CopyImplementation(context, inResource, outResource));
875 }
876 };
877
878 } // CopyBuffer ns
879
880 namespace CopyBlitResolveImage
881 {
882
883 class ImplementationBase : public Operation
884 {
885 public:
886 //! Copy/Blit/Resolve etc. operation
887 virtual void recordCopyCommand (const VkCommandBuffer cmdBuffer) = 0;
888
889 //! Get source stage mask that is used during read - added to test synchronization2 new stage masks
890 virtual VkPipelineStageFlags2KHR getReadSrcStageMask() const = 0;
891
ImplementationBase(OperationContext & context,Resource & resource,const AccessMode mode)892 ImplementationBase (OperationContext& context, Resource& resource, const AccessMode mode)
893 : m_context (context)
894 , m_resource (resource)
895 , m_mode (mode)
896 , m_bufferSize (getPixelBufferSize(m_resource.getImage().format, m_resource.getImage().extent))
897 {
898 const DeviceInterface& vk = m_context.getDeviceInterface();
899 const VkDevice device = m_context.getDevice();
900 Allocator& allocator = m_context.getAllocator();
901
902 m_hostBuffer = de::MovePtr<Buffer>(new Buffer(
903 vk, device, allocator, makeBufferCreateInfo(m_bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT),
904 MemoryRequirement::HostVisible));
905
906 const Allocation& alloc = m_hostBuffer->getAllocation();
907 if (m_mode == ACCESS_MODE_READ)
908 deMemset(alloc.getHostPtr(), 0, static_cast<size_t>(m_bufferSize));
909 else
910 fillPattern(alloc.getHostPtr(), m_bufferSize);
911 flushAlloc(vk, device, alloc);
912
913 // Staging image
914 const auto& imgResource = m_resource.getImage();
915 m_image = de::MovePtr<Image>(new Image(
916 vk, device, allocator,
917 makeImageCreateInfo(imgResource.imageType, imgResource.extent, imgResource.format,
918 (VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT), VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL),
919 MemoryRequirement::Any));
920 }
921
recordCommands(const VkCommandBuffer cmdBuffer)922 void recordCommands (const VkCommandBuffer cmdBuffer)
923 {
924 const DeviceInterface& vk = m_context.getDeviceInterface();
925 const VkBufferImageCopy bufferCopyRegion = makeBufferImageCopy(m_resource.getImage().extent, m_resource.getImage().subresourceLayers);
926 SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
927
928 // Staging image layout
929 {
930 const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
931 VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR, // VkPipelineStageFlags2KHR srcStageMask
932 (VkAccessFlags)0, // VkAccessFlags2KHR srcAccessMask
933 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags2KHR dstStageMask
934 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR, // VkAccessFlags2KHR dstAccessMask
935 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout
936 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout
937 **m_image, // VkImage image
938 m_resource.getImage().subresourceRange // VkImageSubresourceRange subresourceRange
939 );
940 VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
941 synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
942 }
943
944 if (m_mode == ACCESS_MODE_READ)
945 {
946 // Resource Image -> Staging image
947 recordCopyCommand(cmdBuffer);
948
949 // Staging image layout
950 const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
951 getReadSrcStageMask(), // VkPipelineStageFlags2KHR srcStageMask
952 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR, // VkAccessFlags2KHR srcAccessMask
953 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags2KHR dstStageMask
954 VK_ACCESS_2_TRANSFER_READ_BIT_KHR, // VkAccessFlags2KHR dstAccessMask
955 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout
956 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout
957 **m_image, // VkImage image
958 m_resource.getImage().subresourceRange // VkImageSubresourceRange subresourceRange
959 );
960 VkDependencyInfoKHR imageDependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
961 synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &imageDependencyInfo);
962
963 // Image -> Host buffer
964 vk.cmdCopyImageToBuffer(cmdBuffer, **m_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_hostBuffer, 1u, &bufferCopyRegion);
965
966 // Insert a barrier so copied data is available to the host
967 const VkBufferMemoryBarrier2KHR bufferMemoryBarrier2 = makeBufferMemoryBarrier2(
968 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags2KHR srcStageMask
969 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR, // VkAccessFlags2KHR srcAccessMask
970 VK_PIPELINE_STAGE_2_HOST_BIT_KHR, // VkPipelineStageFlags2KHR dstStageMask
971 VK_ACCESS_2_HOST_READ_BIT_KHR, // VkAccessFlags2KHR dstAccessMask
972 **m_hostBuffer, // VkBuffer buffer
973 0u, // VkDeviceSize offset
974 m_bufferSize // VkDeviceSize size
975 );
976 VkDependencyInfoKHR bufferDependencyInfo = makeCommonDependencyInfo(DE_NULL, &bufferMemoryBarrier2);
977 synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &bufferDependencyInfo);
978 }
979 else
980 {
981 // Host buffer -> Staging image
982 vk.cmdCopyBufferToImage(cmdBuffer, **m_hostBuffer, **m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &bufferCopyRegion);
983
984 // Staging image layout
985 {
986 const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
987 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags2KHR srcStageMask
988 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR, // VkAccessFlags2KHR srcAccessMask
989 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags2KHR dstStageMask
990 VK_ACCESS_2_TRANSFER_READ_BIT_KHR, // VkAccessFlags2KHR dstAccessMask
991 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout
992 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout
993 **m_image, // VkImage image
994 m_resource.getImage().subresourceRange // VkImageSubresourceRange subresourceRange
995 );
996 VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
997 synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
998 }
999
1000 // Resource image layout
1001 {
1002 const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
1003 VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR, // VkPipelineStageFlags2KHR srcStageMask
1004 (VkAccessFlags2KHR)0, // VkAccessFlags2KHR srcAccessMask
1005 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags2KHR dstStageMask
1006 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR, // VkAccessFlags2KHR dstAccessMask
1007 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout
1008 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout
1009 m_resource.getImage().handle, // VkImage image
1010 m_resource.getImage().subresourceRange // VkImageSubresourceRange subresourceRange
1011 );
1012 VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
1013 synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
1014 }
1015
1016 // Staging image -> Resource Image
1017 recordCopyCommand(cmdBuffer);
1018 }
1019 }
1020
getInSyncInfo(void) const1021 SyncInfo getInSyncInfo (void) const
1022 {
1023 const VkAccessFlags2KHR access = (m_mode == ACCESS_MODE_READ ? VK_ACCESS_2_TRANSFER_READ_BIT_KHR : VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR);
1024 const VkImageLayout layout = (m_mode == ACCESS_MODE_READ ? VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL : VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
1025 const SyncInfo syncInfo =
1026 {
1027 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags stageMask;
1028 access, // VkAccessFlags accessMask;
1029 layout, // VkImageLayout imageLayout;
1030 };
1031 return syncInfo;
1032 }
1033
getOutSyncInfo(void) const1034 SyncInfo getOutSyncInfo (void) const
1035 {
1036 const VkAccessFlags2KHR access = (m_mode == ACCESS_MODE_READ ? VK_ACCESS_2_TRANSFER_READ_BIT_KHR : VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR);
1037 const VkImageLayout layout = (m_mode == ACCESS_MODE_READ ? VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL : VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
1038 const SyncInfo syncInfo =
1039 {
1040 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags stageMask;
1041 access, // VkAccessFlags accessMask;
1042 layout, // VkImageLayout imageLayout;
1043 };
1044 return syncInfo;
1045 }
1046
getData(void) const1047 Data getData (void) const
1048 {
1049 return getHostBufferData(m_context, *m_hostBuffer, m_bufferSize);
1050 }
1051
setData(const Data & data)1052 void setData (const Data& data)
1053 {
1054 DE_ASSERT(m_mode == ACCESS_MODE_WRITE);
1055 setHostBufferData(m_context, *m_hostBuffer, data);
1056 }
1057
1058 protected:
1059 OperationContext& m_context;
1060 Resource& m_resource;
1061 const AccessMode m_mode;
1062 const VkDeviceSize m_bufferSize;
1063 de::MovePtr<Buffer> m_hostBuffer;
1064 de::MovePtr<Image> m_image;
1065 };
1066
makeExtentOffset(const Resource & resource)1067 VkOffset3D makeExtentOffset (const Resource& resource)
1068 {
1069 DE_ASSERT(resource.getType() == RESOURCE_TYPE_IMAGE);
1070 const VkExtent3D extent = resource.getImage().extent;
1071
1072 switch (resource.getImage().imageType)
1073 {
1074 case VK_IMAGE_TYPE_1D: return makeOffset3D(extent.width, 1, 1);
1075 case VK_IMAGE_TYPE_2D: return makeOffset3D(extent.width, extent.height, 1);
1076 case VK_IMAGE_TYPE_3D: return makeOffset3D(extent.width, extent.height, extent.depth);
1077 default:
1078 DE_ASSERT(0);
1079 return VkOffset3D();
1080 }
1081 }
1082
makeBlitRegion(const Resource & resource)1083 VkImageBlit makeBlitRegion (const Resource& resource)
1084 {
1085 const VkImageBlit blitRegion =
1086 {
1087 resource.getImage().subresourceLayers, // VkImageSubresourceLayers srcSubresource;
1088 { makeOffset3D(0, 0, 0), makeExtentOffset(resource) }, // VkOffset3D srcOffsets[2];
1089 resource.getImage().subresourceLayers, // VkImageSubresourceLayers dstSubresource;
1090 { makeOffset3D(0, 0, 0), makeExtentOffset(resource) }, // VkOffset3D dstOffsets[2];
1091 };
1092 return blitRegion;
1093 }
1094
1095 class BlitImplementation : public ImplementationBase
1096 {
1097 public:
BlitImplementation(OperationContext & context,Resource & resource,const AccessMode mode)1098 BlitImplementation (OperationContext& context, Resource& resource, const AccessMode mode)
1099 : ImplementationBase (context, resource, mode)
1100 , m_blitRegion (makeBlitRegion(m_resource))
1101 {
1102 const InstanceInterface& vki = m_context.getInstanceInterface();
1103 const VkPhysicalDevice physDevice = m_context.getPhysicalDevice();
1104 const auto& imgResource = m_resource.getImage();
1105 const VkFormatProperties formatProps = getPhysicalDeviceFormatProperties(vki, physDevice, imgResource.format);
1106 const auto& features = ((imgResource.tiling == VK_IMAGE_TILING_LINEAR) ? formatProps.linearTilingFeatures : formatProps.optimalTilingFeatures);
1107 const VkFormatFeatureFlags requiredFlags = (VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT);
1108
1109 // SRC and DST blit is required because both images are using the same format.
1110 if ((features & requiredFlags) != requiredFlags)
1111 TCU_THROW(NotSupportedError, "Format doesn't support blits");
1112 }
1113
recordCopyCommand(const VkCommandBuffer cmdBuffer)1114 void recordCopyCommand (const VkCommandBuffer cmdBuffer)
1115 {
1116 const DeviceInterface& vk = m_context.getDeviceInterface();
1117
1118 if (m_mode == ACCESS_MODE_READ)
1119 {
1120 // Resource Image -> Staging image
1121 vk.cmdBlitImage(cmdBuffer, m_resource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1122 1u, &m_blitRegion, VK_FILTER_NEAREST);
1123 }
1124 else
1125 {
1126 // Staging image -> Resource Image
1127 vk.cmdBlitImage(cmdBuffer, **m_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, m_resource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1128 1u, &m_blitRegion, VK_FILTER_NEAREST);
1129 }
1130 }
1131
getReadSrcStageMask() const1132 VkPipelineStageFlags2KHR getReadSrcStageMask() const
1133 {
1134 return (m_context.getSynchronizationType() == SynchronizationType::LEGACY) ? VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR : VK_PIPELINE_STAGE_2_BLIT_BIT_KHR;
1135 }
1136
1137
1138 private:
1139 const VkImageBlit m_blitRegion;
1140 };
1141
1142 template <typename ImageCopyOrResolve>
makeImageRegion(const Resource & resource)1143 ImageCopyOrResolve makeImageRegion (const Resource& resource)
1144 {
1145 return
1146 {
1147 resource.getImage().subresourceLayers, // VkImageSubresourceLayers srcSubresource;
1148 makeOffset3D(0, 0, 0), // VkOffset3D srcOffset;
1149 resource.getImage().subresourceLayers, // VkImageSubresourceLayers dstSubresource;
1150 makeOffset3D(0, 0, 0), // VkOffset3D dstOffset;
1151 resource.getImage().extent, // VkExtent3D extent;
1152 };
1153 }
1154
1155 class CopyImplementation : public ImplementationBase
1156 {
1157 public:
CopyImplementation(OperationContext & context,Resource & resource,const AccessMode mode)1158 CopyImplementation (OperationContext& context, Resource& resource, const AccessMode mode)
1159 : ImplementationBase (context, resource, mode)
1160 , m_imageCopyRegion (makeImageRegion<VkImageCopy>(m_resource))
1161 {
1162 }
1163
recordCopyCommand(const VkCommandBuffer cmdBuffer)1164 void recordCopyCommand (const VkCommandBuffer cmdBuffer)
1165 {
1166 const DeviceInterface& vk = m_context.getDeviceInterface();
1167
1168 if (m_mode == ACCESS_MODE_READ)
1169 {
1170 // Resource Image -> Staging image
1171 vk.cmdCopyImage(cmdBuffer, m_resource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &m_imageCopyRegion);
1172 }
1173 else
1174 {
1175 // Staging image -> Resource Image
1176 vk.cmdCopyImage(cmdBuffer, **m_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, m_resource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &m_imageCopyRegion);
1177 }
1178 }
1179
getReadSrcStageMask() const1180 VkPipelineStageFlags2KHR getReadSrcStageMask() const
1181 {
1182 return (m_context.getSynchronizationType() == SynchronizationType::LEGACY) ? VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR : VK_PIPELINE_STAGE_2_COPY_BIT_KHR;
1183 }
1184
1185 private:
1186 const VkImageCopy m_imageCopyRegion;
1187 };
1188
1189 class ResolveImplementation : public ImplementationBase
1190 {
1191 public:
ResolveImplementation(OperationContext & context,Resource & resource,const AccessMode mode)1192 ResolveImplementation(OperationContext& context, Resource& resource, const AccessMode mode)
1193 : ImplementationBase (context, resource, mode)
1194 , m_imageResolveRegion (makeImageRegion<VkImageResolve>(resource))
1195 {
1196 DE_ASSERT(m_mode == ACCESS_MODE_READ);
1197 }
1198
recordCopyCommand(const VkCommandBuffer cmdBuffer)1199 void recordCopyCommand(const VkCommandBuffer cmdBuffer)
1200 {
1201 const DeviceInterface& vk = m_context.getDeviceInterface();
1202
1203 // Resource Image -> Staging image
1204 vk.cmdResolveImage(cmdBuffer, m_resource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &m_imageResolveRegion);
1205 }
1206
getReadSrcStageMask() const1207 VkPipelineStageFlags2KHR getReadSrcStageMask() const
1208 {
1209 return (m_context.getSynchronizationType() == SynchronizationType::LEGACY) ? VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR : VK_PIPELINE_STAGE_2_RESOLVE_BIT_KHR;
1210 }
1211
1212 private:
1213 VkImageResolve m_imageResolveRegion;
1214 };
1215
1216 enum Type
1217 {
1218 TYPE_COPY,
1219 TYPE_BLIT,
1220 TYPE_RESOLVE,
1221 };
1222
1223 class Support : public OperationSupport
1224 {
1225 public:
Support(const ResourceDescription & resourceDesc,const Type type,const AccessMode mode)1226 Support (const ResourceDescription& resourceDesc, const Type type, const AccessMode mode)
1227 : m_type (type)
1228 , m_mode (mode)
1229 {
1230 DE_ASSERT(resourceDesc.type == RESOURCE_TYPE_IMAGE);
1231
1232 const bool isDepthStencil = isDepthStencilFormat(resourceDesc.imageFormat);
1233 m_requiredQueueFlags = (isDepthStencil || m_type != TYPE_COPY ? VK_QUEUE_GRAPHICS_BIT : VK_QUEUE_TRANSFER_BIT);
1234
1235 // Don't blit depth/stencil images.
1236 DE_ASSERT(m_type != TYPE_BLIT || !isDepthStencil);
1237 }
1238
getInResourceUsageFlags(void) const1239 deUint32 getInResourceUsageFlags (void) const
1240 {
1241 return (m_mode == ACCESS_MODE_READ ? VK_IMAGE_USAGE_TRANSFER_SRC_BIT : 0);
1242 }
1243
getOutResourceUsageFlags(void) const1244 deUint32 getOutResourceUsageFlags (void) const
1245 {
1246 return (m_mode == ACCESS_MODE_WRITE ? VK_IMAGE_USAGE_TRANSFER_DST_BIT : 0);
1247 }
1248
getQueueFlags(const OperationContext & context) const1249 VkQueueFlags getQueueFlags (const OperationContext& context) const
1250 {
1251 DE_UNREF(context);
1252 return m_requiredQueueFlags;
1253 }
1254
build(OperationContext & context,Resource & resource) const1255 de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
1256 {
1257 if (m_type == TYPE_COPY)
1258 return de::MovePtr<Operation>(new CopyImplementation(context, resource, m_mode));
1259 else if (m_type == TYPE_BLIT)
1260 return de::MovePtr<Operation>(new BlitImplementation(context, resource, m_mode));
1261 else
1262 return de::MovePtr<Operation>(new ResolveImplementation(context, resource, m_mode));
1263 }
1264
build(OperationContext &,Resource &,Resource &) const1265 de::MovePtr<Operation> build (OperationContext&, Resource&, Resource&) const
1266 {
1267 DE_ASSERT(0);
1268 return de::MovePtr<Operation>();
1269 }
1270
1271 private:
1272 const Type m_type;
1273 const AccessMode m_mode;
1274 VkQueueFlags m_requiredQueueFlags;
1275 };
1276
1277 class BlitCopyImplementation : public Operation
1278 {
1279 public:
BlitCopyImplementation(OperationContext & context,Resource & inResource,Resource & outResource)1280 BlitCopyImplementation (OperationContext& context, Resource& inResource, Resource& outResource)
1281 : m_context (context)
1282 , m_inResource (inResource)
1283 , m_outResource (outResource)
1284 , m_blitRegion (makeBlitRegion(m_inResource))
1285 {
1286 DE_ASSERT(m_inResource.getType() == RESOURCE_TYPE_IMAGE);
1287 DE_ASSERT(m_outResource.getType() == RESOURCE_TYPE_IMAGE);
1288
1289 const InstanceInterface& vki = m_context.getInstanceInterface();
1290 const VkPhysicalDevice physDevice = m_context.getPhysicalDevice();
1291 const auto& imgResource = m_inResource.getImage();
1292 const VkFormatProperties formatProps = getPhysicalDeviceFormatProperties(vki, physDevice, imgResource.format);
1293 const auto& features = ((imgResource.tiling == VK_IMAGE_TILING_LINEAR) ? formatProps.linearTilingFeatures : formatProps.optimalTilingFeatures);
1294 const VkFormatFeatureFlags requiredFlags = (VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT);
1295
1296 // SRC and DST blit is required because both images are using the same format.
1297 if ((features & requiredFlags) != requiredFlags)
1298 TCU_THROW(NotSupportedError, "Format doesn't support blits");
1299 }
1300
recordCommands(const VkCommandBuffer cmdBuffer)1301 void recordCommands (const VkCommandBuffer cmdBuffer)
1302 {
1303 const DeviceInterface& vk = m_context.getDeviceInterface();
1304 SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
1305
1306 {
1307 const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
1308 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, // VkPipelineStageFlags2KHR srcStageMask
1309 (VkAccessFlags2KHR)0, // VkAccessFlags2KHR srcAccessMask
1310 VK_PIPELINE_STAGE_TRANSFER_BIT, // VkPipelineStageFlags2KHR dstStageMask
1311 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR, // VkAccessFlags2KHR dstAccessMask
1312 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout
1313 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout
1314 m_outResource.getImage().handle, // VkImage image
1315 m_outResource.getImage().subresourceRange // VkImageSubresourceRange subresourceRange
1316 );
1317 VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
1318 synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
1319 }
1320
1321 vk.cmdBlitImage(cmdBuffer,
1322 m_inResource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1323 m_outResource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1324 1u, &m_blitRegion, VK_FILTER_NEAREST);
1325 }
1326
getInSyncInfo(void) const1327 SyncInfo getInSyncInfo (void) const
1328 {
1329 const SyncInfo syncInfo =
1330 {
1331 VK_PIPELINE_STAGE_TRANSFER_BIT, // VkPipelineStageFlags stageMask;
1332 VK_ACCESS_2_TRANSFER_READ_BIT_KHR, // VkAccessFlags accessMask;
1333 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout imageLayout;
1334 };
1335 return syncInfo;
1336 }
1337
getOutSyncInfo(void) const1338 SyncInfo getOutSyncInfo (void) const
1339 {
1340 const SyncInfo syncInfo =
1341 {
1342 VK_PIPELINE_STAGE_TRANSFER_BIT, // VkPipelineStageFlags stageMask;
1343 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR, // VkAccessFlags accessMask;
1344 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout imageLayout;
1345 };
1346 return syncInfo;
1347 }
1348
getData(void) const1349 Data getData (void) const
1350 {
1351 Data data = { 0, DE_NULL };
1352 return data;
1353 }
1354
setData(const Data &)1355 void setData (const Data&)
1356 {
1357 DE_ASSERT(0);
1358 }
1359
1360 private:
1361 OperationContext& m_context;
1362 Resource& m_inResource;
1363 Resource& m_outResource;
1364 const VkImageBlit m_blitRegion;
1365 };
1366
1367 class CopyCopyImplementation : public Operation
1368 {
1369 public:
CopyCopyImplementation(OperationContext & context,Resource & inResource,Resource & outResource)1370 CopyCopyImplementation (OperationContext& context, Resource& inResource, Resource& outResource)
1371 : m_context (context)
1372 , m_inResource (inResource)
1373 , m_outResource (outResource)
1374 , m_imageCopyRegion (makeImageRegion<VkImageCopy>(m_inResource))
1375 {
1376 DE_ASSERT(m_inResource.getType() == RESOURCE_TYPE_IMAGE);
1377 DE_ASSERT(m_outResource.getType() == RESOURCE_TYPE_IMAGE);
1378 }
1379
recordCommands(const VkCommandBuffer cmdBuffer)1380 void recordCommands (const VkCommandBuffer cmdBuffer)
1381 {
1382 const DeviceInterface& vk = m_context.getDeviceInterface();
1383 SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
1384
1385 {
1386 const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
1387 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, // VkPipelineStageFlags2KHR srcStageMask
1388 (VkAccessFlags)0, // VkAccessFlags2KHR srcAccessMask
1389 VK_PIPELINE_STAGE_TRANSFER_BIT, // VkPipelineStageFlags2KHR dstStageMask
1390 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR, // VkAccessFlags2KHR dstAccessMask
1391 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout
1392 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout
1393 m_outResource.getImage().handle, // VkImage image
1394 m_outResource.getImage().subresourceRange // VkImageSubresourceRange subresourceRange
1395 );
1396 VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
1397 synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
1398 }
1399
1400 vk.cmdCopyImage(cmdBuffer,
1401 m_inResource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1402 m_outResource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1403 1u, &m_imageCopyRegion);
1404 }
1405
getInSyncInfo(void) const1406 SyncInfo getInSyncInfo (void) const
1407 {
1408 const SyncInfo syncInfo =
1409 {
1410 VK_PIPELINE_STAGE_TRANSFER_BIT, // VkPipelineStageFlags stageMask;
1411 VK_ACCESS_2_TRANSFER_READ_BIT_KHR, // VkAccessFlags accessMask;
1412 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout imageLayout;
1413 };
1414 return syncInfo;
1415 }
1416
getOutSyncInfo(void) const1417 SyncInfo getOutSyncInfo (void) const
1418 {
1419 const SyncInfo syncInfo =
1420 {
1421 VK_PIPELINE_STAGE_TRANSFER_BIT, // VkPipelineStageFlags stageMask;
1422 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR, // VkAccessFlags accessMask;
1423 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout imageLayout;
1424 };
1425 return syncInfo;
1426 }
1427
getData(void) const1428 Data getData (void) const
1429 {
1430 Data data = { 0, DE_NULL };
1431 return data;
1432 }
1433
setData(const Data &)1434 void setData (const Data&)
1435 {
1436 DE_ASSERT(0);
1437 }
1438
1439 private:
1440 OperationContext& m_context;
1441 Resource& m_inResource;
1442 Resource& m_outResource;
1443 const VkImageCopy m_imageCopyRegion;
1444 };
1445
1446 class CopySupport : public OperationSupport
1447 {
1448 public:
CopySupport(const ResourceDescription & resourceDesc,const Type type)1449 CopySupport (const ResourceDescription& resourceDesc, const Type type)
1450 : m_type (type)
1451 {
1452 DE_ASSERT(resourceDesc.type == RESOURCE_TYPE_IMAGE);
1453
1454 const bool isDepthStencil = isDepthStencilFormat(resourceDesc.imageFormat);
1455 m_requiredQueueFlags = (isDepthStencil || m_type == TYPE_BLIT ? VK_QUEUE_GRAPHICS_BIT : VK_QUEUE_TRANSFER_BIT);
1456
1457 // Don't blit depth/stencil images.
1458 DE_ASSERT(m_type != TYPE_BLIT || !isDepthStencil);
1459 }
1460
getInResourceUsageFlags(void) const1461 deUint32 getInResourceUsageFlags (void) const
1462 {
1463 return VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1464 }
1465
getOutResourceUsageFlags(void) const1466 deUint32 getOutResourceUsageFlags (void) const
1467 {
1468 return VK_IMAGE_USAGE_TRANSFER_DST_BIT;
1469 }
1470
getQueueFlags(const OperationContext & context) const1471 VkQueueFlags getQueueFlags (const OperationContext& context) const
1472 {
1473 DE_UNREF(context);
1474 return m_requiredQueueFlags;
1475 }
1476
build(OperationContext &,Resource &) const1477 de::MovePtr<Operation> build (OperationContext&, Resource&) const
1478 {
1479 DE_ASSERT(0);
1480 return de::MovePtr<Operation>();
1481 }
1482
build(OperationContext & context,Resource & inResource,Resource & outResource) const1483 de::MovePtr<Operation> build (OperationContext& context, Resource& inResource, Resource& outResource) const
1484 {
1485 if (m_type == TYPE_COPY)
1486 return de::MovePtr<Operation>(new CopyCopyImplementation(context, inResource, outResource));
1487 else
1488 return de::MovePtr<Operation>(new BlitCopyImplementation(context, inResource, outResource));
1489 }
1490
1491 private:
1492 const Type m_type;
1493 VkQueueFlags m_requiredQueueFlags;
1494 };
1495
1496 } // CopyBlitImage ns
1497
1498 namespace ShaderAccess
1499 {
1500
1501 enum DispatchCall
1502 {
1503 DISPATCH_CALL_DISPATCH,
1504 DISPATCH_CALL_DISPATCH_INDIRECT,
1505 };
1506
1507 class GraphicsPipeline : public Pipeline
1508 {
1509 public:
GraphicsPipeline(OperationContext & context,const VkShaderStageFlagBits stage,const std::string & shaderPrefix,const VkDescriptorSetLayout descriptorSetLayout)1510 GraphicsPipeline (OperationContext& context, const VkShaderStageFlagBits stage, const std::string& shaderPrefix, const VkDescriptorSetLayout descriptorSetLayout)
1511 : m_vertices (context)
1512 {
1513 const DeviceInterface& vk = context.getDeviceInterface();
1514 const VkDevice device = context.getDevice();
1515 Allocator& allocator = context.getAllocator();
1516 const VkShaderStageFlags requiredStages = getRequiredStages(stage);
1517
1518 // Color attachment
1519
1520 m_colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
1521 m_colorImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
1522 m_colorImageExtent = makeExtent3D(16u, 16u, 1u);
1523 m_colorAttachmentImage = de::MovePtr<Image>(new Image(vk, device, allocator,
1524 makeImageCreateInfo(VK_IMAGE_TYPE_2D, m_colorImageExtent, m_colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
1525 VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL),
1526 MemoryRequirement::Any));
1527
1528 // Pipeline
1529
1530 m_colorAttachmentView = makeImageView (vk, device, **m_colorAttachmentImage, VK_IMAGE_VIEW_TYPE_2D, m_colorFormat, m_colorImageSubresourceRange);
1531 m_renderPass = makeRenderPass (vk, device, m_colorFormat);
1532 m_framebuffer = makeFramebuffer (vk, device, *m_renderPass, *m_colorAttachmentView, m_colorImageExtent.width, m_colorImageExtent.height);
1533 m_pipelineLayout = makePipelineLayout(vk, device, descriptorSetLayout);
1534
1535 GraphicsPipelineBuilder pipelineBuilder;
1536 pipelineBuilder
1537 .setRenderSize (tcu::IVec2(m_colorImageExtent.width, m_colorImageExtent.height))
1538 .setVertexInputSingleAttribute (m_vertices.getVertexFormat(), m_vertices.getVertexStride())
1539 .setShader (vk, device, VK_SHADER_STAGE_VERTEX_BIT, context.getBinaryCollection().get(shaderPrefix + "vert"), DE_NULL)
1540 .setShader (vk, device, VK_SHADER_STAGE_FRAGMENT_BIT, context.getBinaryCollection().get(shaderPrefix + "frag"), DE_NULL);
1541
1542 if (requiredStages & (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT))
1543 pipelineBuilder
1544 .setPatchControlPoints (m_vertices.getNumVertices())
1545 .setShader (vk, device, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, context.getBinaryCollection().get(shaderPrefix + "tesc"), DE_NULL)
1546 .setShader (vk, device, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, context.getBinaryCollection().get(shaderPrefix + "tese"), DE_NULL);
1547
1548 if (requiredStages & VK_SHADER_STAGE_GEOMETRY_BIT)
1549 pipelineBuilder
1550 .setShader (vk, device, VK_SHADER_STAGE_GEOMETRY_BIT, context.getBinaryCollection().get(shaderPrefix + "geom"), DE_NULL);
1551
1552 m_pipeline = pipelineBuilder.build(vk, device, *m_pipelineLayout, *m_renderPass, context.getPipelineCacheData(), context.getResourceInterface());
1553 }
1554
recordCommands(OperationContext & context,const VkCommandBuffer cmdBuffer,const VkDescriptorSet descriptorSet)1555 void recordCommands (OperationContext& context, const VkCommandBuffer cmdBuffer, const VkDescriptorSet descriptorSet)
1556 {
1557 const DeviceInterface& vk = context.getDeviceInterface();
1558 SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(context.getSynchronizationType(), vk, DE_FALSE);
1559
1560 // Change color attachment image layout
1561 {
1562 const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
1563 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, // VkPipelineStageFlags2KHR srcStageMask
1564 (VkAccessFlags)0, // VkAccessFlags2KHR srcAccessMask
1565 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // VkPipelineStageFlags2KHR dstStageMask
1566 VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR, // VkAccessFlags2KHR dstAccessMask
1567 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout
1568 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout
1569 **m_colorAttachmentImage, // VkImage image
1570 m_colorImageSubresourceRange // VkImageSubresourceRange subresourceRange
1571 );
1572 VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
1573 synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
1574 }
1575
1576 {
1577 const VkRect2D renderArea = makeRect2D(m_colorImageExtent);
1578 const tcu::Vec4 clearColor = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
1579
1580 beginRenderPass(vk, cmdBuffer, *m_renderPass, *m_framebuffer, renderArea, clearColor);
1581 }
1582
1583 vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
1584 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
1585 {
1586 const VkDeviceSize vertexBufferOffset = 0ull;
1587 const VkBuffer vertexBuffer = m_vertices.getVertexBuffer();
1588 vk.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer, &vertexBufferOffset);
1589 }
1590
1591 vk.cmdDraw(cmdBuffer, m_vertices.getNumVertices(), 1u, 0u, 0u);
1592 endRenderPass(vk, cmdBuffer);
1593 }
1594
1595 private:
1596 const VertexGrid m_vertices;
1597 VkFormat m_colorFormat;
1598 de::MovePtr<Image> m_colorAttachmentImage;
1599 Move<VkImageView> m_colorAttachmentView;
1600 VkExtent3D m_colorImageExtent;
1601 VkImageSubresourceRange m_colorImageSubresourceRange;
1602 Move<VkRenderPass> m_renderPass;
1603 Move<VkFramebuffer> m_framebuffer;
1604 Move<VkPipelineLayout> m_pipelineLayout;
1605 Move<VkPipeline> m_pipeline;
1606 };
1607
1608 class ComputePipeline : public Pipeline
1609 {
1610 public:
ComputePipeline(OperationContext & context,const DispatchCall dispatchCall,const std::string & shaderPrefix,const VkDescriptorSetLayout descriptorSetLayout)1611 ComputePipeline (OperationContext& context, const DispatchCall dispatchCall, const std::string& shaderPrefix, const VkDescriptorSetLayout descriptorSetLayout)
1612 : m_dispatchCall (dispatchCall)
1613 {
1614 const DeviceInterface& vk = context.getDeviceInterface();
1615 const VkDevice device = context.getDevice();
1616 Allocator& allocator = context.getAllocator();
1617
1618 if (m_dispatchCall == DISPATCH_CALL_DISPATCH_INDIRECT)
1619 {
1620 m_indirectBuffer = de::MovePtr<Buffer>(new Buffer(vk, device, allocator,
1621 makeBufferCreateInfo(sizeof(VkDispatchIndirectCommand), VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT), MemoryRequirement::HostVisible));
1622
1623 const Allocation& alloc = m_indirectBuffer->getAllocation();
1624 VkDispatchIndirectCommand* const pIndirectCommand = static_cast<VkDispatchIndirectCommand*>(alloc.getHostPtr());
1625
1626 pIndirectCommand->x = 1u;
1627 pIndirectCommand->y = 1u;
1628 pIndirectCommand->z = 1u;
1629
1630 flushAlloc(vk, device, alloc);
1631 }
1632
1633 const Unique<VkShaderModule> shaderModule(createShaderModule(vk, device, context.getBinaryCollection().get(shaderPrefix + "comp"), (VkShaderModuleCreateFlags)0));
1634
1635 m_pipelineLayout = makePipelineLayout(vk, device, descriptorSetLayout);
1636 m_pipeline = makeComputePipeline(vk, device, *m_pipelineLayout, *shaderModule, DE_NULL, context.getPipelineCacheData(), context.getResourceInterface());
1637 }
1638
recordCommands(OperationContext & context,const VkCommandBuffer cmdBuffer,const VkDescriptorSet descriptorSet)1639 void recordCommands (OperationContext& context, const VkCommandBuffer cmdBuffer, const VkDescriptorSet descriptorSet)
1640 {
1641 const DeviceInterface& vk = context.getDeviceInterface();
1642
1643 vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipeline);
1644 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
1645
1646 if (m_dispatchCall == DISPATCH_CALL_DISPATCH_INDIRECT)
1647 vk.cmdDispatchIndirect(cmdBuffer, **m_indirectBuffer, 0u);
1648 else
1649 vk.cmdDispatch(cmdBuffer, 1u, 1u, 1u);
1650 }
1651
1652 private:
1653 const DispatchCall m_dispatchCall;
1654 de::MovePtr<Buffer> m_indirectBuffer;
1655 Move<VkPipelineLayout> m_pipelineLayout;
1656 Move<VkPipeline> m_pipeline;
1657 };
1658
1659 //! Read/write operation on a UBO/SSBO in graphics/compute pipeline.
1660 class BufferImplementation : public Operation
1661 {
1662 public:
BufferImplementation(OperationContext & context,Resource & resource,const VkShaderStageFlagBits stage,const BufferType bufferType,const std::string & shaderPrefix,const AccessMode mode,const PipelineType pipelineType,const DispatchCall dispatchCall)1663 BufferImplementation (OperationContext& context,
1664 Resource& resource,
1665 const VkShaderStageFlagBits stage,
1666 const BufferType bufferType,
1667 const std::string& shaderPrefix,
1668 const AccessMode mode,
1669 const PipelineType pipelineType,
1670 const DispatchCall dispatchCall)
1671 : m_context (context)
1672 , m_resource (resource)
1673 , m_stage (stage)
1674 , m_pipelineStage (pipelineStageFlagsFromShaderStageFlagBits(m_stage))
1675 , m_bufferType (bufferType)
1676 , m_mode (mode)
1677 , m_dispatchCall (dispatchCall)
1678 {
1679 requireFeaturesForSSBOAccess (m_context, m_stage);
1680
1681 const DeviceInterface& vk = m_context.getDeviceInterface();
1682 const VkDevice device = m_context.getDevice();
1683 Allocator& allocator = m_context.getAllocator();
1684
1685 m_hostBuffer = de::MovePtr<Buffer>(new Buffer(
1686 vk, device, allocator, makeBufferCreateInfo(m_resource.getBuffer().size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), MemoryRequirement::HostVisible));
1687
1688 // Init host buffer data
1689 {
1690 const Allocation& alloc = m_hostBuffer->getAllocation();
1691 if (m_mode == ACCESS_MODE_READ)
1692 deMemset(alloc.getHostPtr(), 0, static_cast<size_t>(m_resource.getBuffer().size));
1693 else
1694 fillPattern(alloc.getHostPtr(), m_resource.getBuffer().size);
1695 flushAlloc(vk, device, alloc);
1696 }
1697
1698 // Prepare descriptors
1699 {
1700 const VkDescriptorType bufferDescriptorType = (m_bufferType == BUFFER_TYPE_UNIFORM ? VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER : VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
1701
1702 m_descriptorSetLayout = DescriptorSetLayoutBuilder()
1703 .addSingleBinding(bufferDescriptorType, m_stage)
1704 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, m_stage)
1705 .build(vk, device);
1706
1707 m_descriptorPool = DescriptorPoolBuilder()
1708 .addType(bufferDescriptorType)
1709 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
1710 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1711
1712 m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
1713
1714 const VkDescriptorBufferInfo bufferInfo = makeDescriptorBufferInfo(m_resource.getBuffer().handle, m_resource.getBuffer().offset, m_resource.getBuffer().size);
1715 const VkDescriptorBufferInfo hostBufferInfo = makeDescriptorBufferInfo(**m_hostBuffer, 0u, m_resource.getBuffer().size);
1716
1717 if (m_mode == ACCESS_MODE_READ)
1718 {
1719 DescriptorSetUpdateBuilder()
1720 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), bufferDescriptorType, &bufferInfo)
1721 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &hostBufferInfo)
1722 .update(vk, device);
1723 }
1724 else
1725 {
1726 DescriptorSetUpdateBuilder()
1727 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &hostBufferInfo)
1728 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &bufferInfo)
1729 .update(vk, device);
1730 }
1731 }
1732
1733 // Create pipeline
1734 m_pipeline = (pipelineType == PIPELINE_TYPE_GRAPHICS ? de::MovePtr<Pipeline>(new GraphicsPipeline(context, stage, shaderPrefix, *m_descriptorSetLayout))
1735 : de::MovePtr<Pipeline>(new ComputePipeline(context, m_dispatchCall, shaderPrefix, *m_descriptorSetLayout)));
1736 }
1737
recordCommands(const VkCommandBuffer cmdBuffer)1738 void recordCommands (const VkCommandBuffer cmdBuffer)
1739 {
1740 m_pipeline->recordCommands(m_context, cmdBuffer, *m_descriptorSet);
1741
1742 // Post draw/dispatch commands
1743
1744 if (m_mode == ACCESS_MODE_READ)
1745 {
1746 const DeviceInterface& vk = m_context.getDeviceInterface();
1747 SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
1748
1749 // Insert a barrier so data written by the shader is available to the host
1750 const VkBufferMemoryBarrier2KHR bufferMemoryBarrier2 = makeBufferMemoryBarrier2(
1751 m_pipelineStage, // VkPipelineStageFlags2KHR srcStageMask
1752 VK_ACCESS_2_SHADER_WRITE_BIT_KHR, // VkAccessFlags2KHR srcAccessMask
1753 VK_PIPELINE_STAGE_HOST_BIT, // VkPipelineStageFlags2KHR dstStageMask
1754 VK_ACCESS_2_HOST_READ_BIT_KHR, // VkAccessFlags2KHR dstAccessMask
1755 **m_hostBuffer, // VkBuffer buffer
1756 0u, // VkDeviceSize offset
1757 m_resource.getBuffer().size // VkDeviceSize size
1758 );
1759 VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, &bufferMemoryBarrier2);
1760 synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
1761 }
1762 }
1763
getInSyncInfo(void) const1764 SyncInfo getInSyncInfo (void) const
1765 {
1766 const VkAccessFlags2KHR accessFlags = (m_mode == ACCESS_MODE_READ ? (m_bufferType == BUFFER_TYPE_UNIFORM ? VK_ACCESS_2_UNIFORM_READ_BIT_KHR
1767 : VK_ACCESS_2_SHADER_READ_BIT_KHR)
1768 : VK_ACCESS_2_SHADER_WRITE_BIT_KHR);
1769 const SyncInfo syncInfo =
1770 {
1771 m_pipelineStage, // VkPipelineStageFlags stageMask;
1772 accessFlags, // VkAccessFlags accessMask;
1773 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout imageLayout;
1774 };
1775 return syncInfo;
1776 }
1777
getOutSyncInfo(void) const1778 SyncInfo getOutSyncInfo (void) const
1779 {
1780 const VkAccessFlags accessFlags = m_mode == ACCESS_MODE_WRITE ? VK_ACCESS_2_SHADER_WRITE_BIT_KHR : 0;
1781 const SyncInfo syncInfo =
1782 {
1783 m_pipelineStage, // VkPipelineStageFlags stageMask;
1784 accessFlags, // VkAccessFlags accessMask;
1785 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout imageLayout;
1786 };
1787 return syncInfo;
1788 }
1789
getData(void) const1790 Data getData (void) const
1791 {
1792 return getHostBufferData(m_context, *m_hostBuffer, m_resource.getBuffer().size);
1793 }
1794
setData(const Data & data)1795 void setData (const Data& data)
1796 {
1797 DE_ASSERT(m_mode == ACCESS_MODE_WRITE);
1798 setHostBufferData(m_context, *m_hostBuffer, data);
1799 }
1800
1801 private:
1802 OperationContext& m_context;
1803 Resource& m_resource;
1804 const VkShaderStageFlagBits m_stage;
1805 const VkPipelineStageFlags m_pipelineStage;
1806 const BufferType m_bufferType;
1807 const AccessMode m_mode;
1808 const DispatchCall m_dispatchCall;
1809 de::MovePtr<Buffer> m_hostBuffer;
1810 Move<VkDescriptorPool> m_descriptorPool;
1811 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
1812 Move<VkDescriptorSet> m_descriptorSet;
1813 de::MovePtr<Pipeline> m_pipeline;
1814 };
1815
1816 class ImageImplementation : public Operation
1817 {
1818 public:
ImageImplementation(OperationContext & context,Resource & resource,const VkShaderStageFlagBits stage,const std::string & shaderPrefix,const AccessMode mode,const PipelineType pipelineType,const DispatchCall dispatchCall)1819 ImageImplementation (OperationContext& context,
1820 Resource& resource,
1821 const VkShaderStageFlagBits stage,
1822 const std::string& shaderPrefix,
1823 const AccessMode mode,
1824 const PipelineType pipelineType,
1825 const DispatchCall dispatchCall)
1826 : m_context (context)
1827 , m_resource (resource)
1828 , m_stage (stage)
1829 , m_pipelineStage (pipelineStageFlagsFromShaderStageFlagBits(m_stage))
1830 , m_mode (mode)
1831 , m_dispatchCall (dispatchCall)
1832 , m_hostBufferSizeBytes (getPixelBufferSize(m_resource.getImage().format, m_resource.getImage().extent))
1833 {
1834 const DeviceInterface& vk = m_context.getDeviceInterface();
1835 const InstanceInterface& vki = m_context.getInstanceInterface();
1836 const VkDevice device = m_context.getDevice();
1837 const VkPhysicalDevice physDevice = m_context.getPhysicalDevice();
1838 Allocator& allocator = m_context.getAllocator();
1839
1840 // Image stores are always required, in either access mode.
1841 requireFeaturesForSSBOAccess(m_context, m_stage);
1842
1843 // Some storage image formats may not be supported
1844 const auto& imgResource = m_resource.getImage();
1845 requireStorageImageSupport(vki, physDevice, imgResource.format, imgResource.tiling);
1846
1847 m_hostBuffer = de::MovePtr<Buffer>(new Buffer(
1848 vk, device, allocator, makeBufferCreateInfo(m_hostBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT),
1849 MemoryRequirement::HostVisible));
1850
1851 // Init host buffer data
1852 {
1853 const Allocation& alloc = m_hostBuffer->getAllocation();
1854 if (m_mode == ACCESS_MODE_READ)
1855 deMemset(alloc.getHostPtr(), 0, static_cast<size_t>(m_hostBufferSizeBytes));
1856 else
1857 fillPattern(alloc.getHostPtr(), m_hostBufferSizeBytes);
1858 flushAlloc(vk, device, alloc);
1859 }
1860
1861 // Image resources
1862 {
1863 m_image = de::MovePtr<Image>(new Image(vk, device, allocator,
1864 makeImageCreateInfo(m_resource.getImage().imageType, m_resource.getImage().extent, m_resource.getImage().format,
1865 (VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_STORAGE_BIT),
1866 VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL),
1867 MemoryRequirement::Any));
1868
1869 if (m_mode == ACCESS_MODE_READ)
1870 {
1871 m_srcImage = &m_resource.getImage().handle;
1872 m_dstImage = &(**m_image);
1873 }
1874 else
1875 {
1876 m_srcImage = &(**m_image);
1877 m_dstImage = &m_resource.getImage().handle;
1878 }
1879
1880 const VkImageViewType viewType = getImageViewType(m_resource.getImage().imageType);
1881
1882 m_srcImageView = makeImageView(vk, device, *m_srcImage, viewType, m_resource.getImage().format, m_resource.getImage().subresourceRange);
1883 m_dstImageView = makeImageView(vk, device, *m_dstImage, viewType, m_resource.getImage().format, m_resource.getImage().subresourceRange);
1884 }
1885
1886 // Prepare descriptors
1887 {
1888 m_descriptorSetLayout = DescriptorSetLayoutBuilder()
1889 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, m_stage)
1890 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, m_stage)
1891 .build(vk, device);
1892
1893 m_descriptorPool = DescriptorPoolBuilder()
1894 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
1895 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
1896 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1897
1898 m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
1899
1900 const VkDescriptorImageInfo srcImageInfo = makeDescriptorImageInfo(DE_NULL, *m_srcImageView, VK_IMAGE_LAYOUT_GENERAL);
1901 const VkDescriptorImageInfo dstImageInfo = makeDescriptorImageInfo(DE_NULL, *m_dstImageView, VK_IMAGE_LAYOUT_GENERAL);
1902
1903 DescriptorSetUpdateBuilder()
1904 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &srcImageInfo)
1905 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &dstImageInfo)
1906 .update(vk, device);
1907 }
1908
1909 // Create pipeline
1910 m_pipeline = (pipelineType == PIPELINE_TYPE_GRAPHICS ? de::MovePtr<Pipeline>(new GraphicsPipeline(context, stage, shaderPrefix, *m_descriptorSetLayout))
1911 : de::MovePtr<Pipeline>(new ComputePipeline(context, m_dispatchCall, shaderPrefix, *m_descriptorSetLayout)));
1912 }
1913
recordCommands(const VkCommandBuffer cmdBuffer)1914 void recordCommands (const VkCommandBuffer cmdBuffer)
1915 {
1916 const DeviceInterface& vk = m_context.getDeviceInterface();
1917 const VkBufferImageCopy bufferCopyRegion = makeBufferImageCopy(m_resource.getImage().extent, m_resource.getImage().subresourceLayers);
1918 SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
1919
1920 // Destination image layout
1921 {
1922 const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
1923 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, // VkPipelineStageFlags2KHR srcStageMask
1924 (VkAccessFlags)0, // VkAccessFlags2KHR srcAccessMask
1925 m_pipelineStage, // VkPipelineStageFlags2KHR dstStageMask
1926 VK_ACCESS_2_SHADER_WRITE_BIT_KHR, // VkAccessFlags2KHR dstAccessMask
1927 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout
1928 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout
1929 *m_dstImage, // VkImage image
1930 m_resource.getImage().subresourceRange // VkImageSubresourceRange subresourceRange
1931 );
1932 VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
1933 synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
1934 }
1935
1936 // In write mode, source image must be filled with data.
1937 if (m_mode == ACCESS_MODE_WRITE)
1938 {
1939 // Layout for transfer
1940 {
1941 const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
1942 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, // VkPipelineStageFlags2KHR srcStageMask
1943 (VkAccessFlags)0, // VkAccessFlags2KHR srcAccessMask
1944 VK_PIPELINE_STAGE_TRANSFER_BIT, // VkPipelineStageFlags2KHR dstStageMask
1945 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR, // VkAccessFlags2KHR dstAccessMask
1946 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout
1947 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout
1948 *m_srcImage, // VkImage image
1949 m_resource.getImage().subresourceRange // VkImageSubresourceRange subresourceRange
1950 );
1951 VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
1952 synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
1953 }
1954
1955 // Host buffer -> Src image
1956 vk.cmdCopyBufferToImage(cmdBuffer, **m_hostBuffer, *m_srcImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &bufferCopyRegion);
1957
1958 // Layout for shader reading
1959 {
1960 const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
1961 VK_PIPELINE_STAGE_TRANSFER_BIT, // VkPipelineStageFlags2KHR srcStageMask
1962 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR, // VkAccessFlags2KHR srcAccessMask
1963 m_pipelineStage, // VkPipelineStageFlags2KHR dstStageMask
1964 VK_ACCESS_2_SHADER_READ_BIT_KHR, // VkAccessFlags2KHR dstAccessMask
1965 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout
1966 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout
1967 *m_srcImage, // VkImage image
1968 m_resource.getImage().subresourceRange // VkImageSubresourceRange subresourceRange
1969 );
1970 VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
1971 synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
1972 }
1973 }
1974
1975 // Execute shaders
1976
1977 m_pipeline->recordCommands(m_context, cmdBuffer, *m_descriptorSet);
1978
1979 // Post draw/dispatch commands
1980
1981 if (m_mode == ACCESS_MODE_READ)
1982 {
1983 // Layout for transfer
1984 {
1985 const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
1986 m_pipelineStage, // VkPipelineStageFlags2KHR srcStageMask
1987 VK_ACCESS_2_SHADER_WRITE_BIT_KHR, // VkAccessFlags2KHR srcAccessMask
1988 VK_PIPELINE_STAGE_TRANSFER_BIT, // VkPipelineStageFlags2KHR dstStageMask
1989 VK_ACCESS_2_TRANSFER_READ_BIT_KHR, // VkAccessFlags2KHR dstAccessMask
1990 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout oldLayout
1991 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout
1992 *m_dstImage, // VkImage image
1993 m_resource.getImage().subresourceRange // VkImageSubresourceRange subresourceRange
1994 );
1995 VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
1996 synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
1997 }
1998
1999 // Dst image -> Host buffer
2000 vk.cmdCopyImageToBuffer(cmdBuffer, *m_dstImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_hostBuffer, 1u, &bufferCopyRegion);
2001
2002 // Insert a barrier so data written by the shader is available to the host
2003 {
2004 const VkBufferMemoryBarrier2KHR bufferMemoryBarrier2 = makeBufferMemoryBarrier2(
2005 VK_PIPELINE_STAGE_TRANSFER_BIT, // VkPipelineStageFlags2KHR srcStageMask
2006 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR, // VkAccessFlags2KHR srcAccessMask
2007 VK_PIPELINE_STAGE_HOST_BIT, // VkPipelineStageFlags2KHR dstStageMask
2008 VK_ACCESS_2_HOST_READ_BIT_KHR, // VkAccessFlags2KHR dstAccessMask
2009 **m_hostBuffer, // VkBuffer buffer
2010 0u, // VkDeviceSize offset
2011 m_hostBufferSizeBytes // VkDeviceSize size
2012 );
2013 VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, &bufferMemoryBarrier2);
2014 synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
2015 }
2016 }
2017 }
2018
getInSyncInfo(void) const2019 SyncInfo getInSyncInfo (void) const
2020 {
2021 const VkAccessFlags accessFlags = (m_mode == ACCESS_MODE_READ ? VK_ACCESS_2_SHADER_READ_BIT_KHR : 0);
2022 const SyncInfo syncInfo =
2023 {
2024 m_pipelineStage, // VkPipelineStageFlags stageMask;
2025 accessFlags, // VkAccessFlags accessMask;
2026 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout imageLayout;
2027 };
2028 return syncInfo;
2029 }
2030
getOutSyncInfo(void) const2031 SyncInfo getOutSyncInfo (void) const
2032 {
2033 const VkAccessFlags accessFlags = (m_mode == ACCESS_MODE_WRITE ? VK_ACCESS_2_SHADER_WRITE_BIT_KHR : 0);
2034 const SyncInfo syncInfo =
2035 {
2036 m_pipelineStage, // VkPipelineStageFlags stageMask;
2037 accessFlags, // VkAccessFlags accessMask;
2038 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout imageLayout;
2039 };
2040 return syncInfo;
2041 }
2042
getData(void) const2043 Data getData (void) const
2044 {
2045 return getHostBufferData(m_context, *m_hostBuffer, m_hostBufferSizeBytes);
2046 }
2047
setData(const Data & data)2048 void setData (const Data& data)
2049 {
2050 DE_ASSERT(m_mode == ACCESS_MODE_WRITE);
2051 setHostBufferData(m_context, *m_hostBuffer, data);
2052 }
2053
2054 private:
2055 OperationContext& m_context;
2056 Resource& m_resource;
2057 const VkShaderStageFlagBits m_stage;
2058 const VkPipelineStageFlags m_pipelineStage;
2059 const AccessMode m_mode;
2060 const DispatchCall m_dispatchCall;
2061 const VkDeviceSize m_hostBufferSizeBytes;
2062 de::MovePtr<Buffer> m_hostBuffer;
2063 de::MovePtr<Image> m_image; //! Additional image used as src or dst depending on operation mode.
2064 const VkImage* m_srcImage;
2065 const VkImage* m_dstImage;
2066 Move<VkImageView> m_srcImageView;
2067 Move<VkImageView> m_dstImageView;
2068 Move<VkDescriptorPool> m_descriptorPool;
2069 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
2070 Move<VkDescriptorSet> m_descriptorSet;
2071 de::MovePtr<Pipeline> m_pipeline;
2072 };
2073
2074 //! Create generic passthrough shaders with bits of custom code inserted in a specific shader stage.
initPassthroughPrograms(SourceCollections & programCollection,const std::string & shaderPrefix,const std::string & declCode,const std::string & mainCode,const VkShaderStageFlagBits stage)2075 void initPassthroughPrograms (SourceCollections& programCollection,
2076 const std::string& shaderPrefix,
2077 const std::string& declCode,
2078 const std::string& mainCode,
2079 const VkShaderStageFlagBits stage)
2080 {
2081 const VkShaderStageFlags requiredStages = getRequiredStages(stage);
2082
2083 if (requiredStages & VK_SHADER_STAGE_VERTEX_BIT)
2084 {
2085 std::ostringstream src;
2086 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
2087 << "\n"
2088 << "layout(location = 0) in vec4 v_in_position;\n"
2089 << "\n"
2090 << "out " << s_perVertexBlock << ";\n"
2091 << "\n"
2092 << (stage & VK_SHADER_STAGE_VERTEX_BIT ? declCode + "\n" : "")
2093 << "void main (void)\n"
2094 << "{\n"
2095 << " gl_Position = v_in_position;\n"
2096 << (stage & VK_SHADER_STAGE_VERTEX_BIT ? mainCode : "")
2097 << "}\n";
2098
2099 if (!programCollection.glslSources.contains(shaderPrefix + "vert"))
2100 programCollection.glslSources.add(shaderPrefix + "vert") << glu::VertexSource(src.str());
2101 }
2102
2103 if (requiredStages & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
2104 {
2105 std::ostringstream src;
2106 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
2107 << "\n"
2108 << "layout(vertices = 3) out;\n"
2109 << "\n"
2110 << "in " << s_perVertexBlock << " gl_in[gl_MaxPatchVertices];\n"
2111 << "\n"
2112 << "out " << s_perVertexBlock << " gl_out[];\n"
2113 << "\n"
2114 << (stage & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT ? declCode + "\n" : "")
2115 << "void main (void)\n"
2116 << "{\n"
2117 << " gl_TessLevelInner[0] = 1.0;\n"
2118 << " gl_TessLevelInner[1] = 1.0;\n"
2119 << "\n"
2120 << " gl_TessLevelOuter[0] = 1.0;\n"
2121 << " gl_TessLevelOuter[1] = 1.0;\n"
2122 << " gl_TessLevelOuter[2] = 1.0;\n"
2123 << " gl_TessLevelOuter[3] = 1.0;\n"
2124 << "\n"
2125 << " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
2126 << (stage & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT ? "\n" + mainCode : "")
2127 << "}\n";
2128
2129 if (!programCollection.glslSources.contains(shaderPrefix + "tesc"))
2130 programCollection.glslSources.add(shaderPrefix + "tesc") << glu::TessellationControlSource(src.str());
2131 }
2132
2133 if (requiredStages & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
2134 {
2135 std::ostringstream src;
2136 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
2137 << "\n"
2138 << "layout(triangles, equal_spacing, ccw) in;\n"
2139 << "\n"
2140 << "in " << s_perVertexBlock << " gl_in[gl_MaxPatchVertices];\n"
2141 << "\n"
2142 << "out " << s_perVertexBlock << ";\n"
2143 << "\n"
2144 << (stage & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT ? declCode + "\n" : "")
2145 << "void main (void)\n"
2146 << "{\n"
2147 << " vec3 px = gl_TessCoord.x * gl_in[0].gl_Position.xyz;\n"
2148 << " vec3 py = gl_TessCoord.y * gl_in[1].gl_Position.xyz;\n"
2149 << " vec3 pz = gl_TessCoord.z * gl_in[2].gl_Position.xyz;\n"
2150 << " gl_Position = vec4(px + py + pz, 1.0);\n"
2151 << (stage & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT ? mainCode : "")
2152 << "}\n";
2153
2154 if (!programCollection.glslSources.contains(shaderPrefix + "tese"))
2155 programCollection.glslSources.add(shaderPrefix + "tese") << glu::TessellationEvaluationSource(src.str());
2156 }
2157
2158 if (requiredStages & VK_SHADER_STAGE_GEOMETRY_BIT)
2159 {
2160 std::ostringstream src;
2161 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
2162 << "\n"
2163 << "layout(triangles) in;\n"
2164 << "layout(triangle_strip, max_vertices = 3) out;\n"
2165 << "\n"
2166 << "in " << s_perVertexBlock << " gl_in[];\n"
2167 << "\n"
2168 << "out " << s_perVertexBlock << ";\n"
2169 << "\n"
2170 << (stage & VK_SHADER_STAGE_GEOMETRY_BIT ? declCode + "\n" : "")
2171 << "void main (void)\n"
2172 << "{\n"
2173 << " gl_Position = gl_in[0].gl_Position;\n"
2174 << " EmitVertex();\n"
2175 << "\n"
2176 << " gl_Position = gl_in[1].gl_Position;\n"
2177 << " EmitVertex();\n"
2178 << "\n"
2179 << " gl_Position = gl_in[2].gl_Position;\n"
2180 << " EmitVertex();\n"
2181 << (stage & VK_SHADER_STAGE_GEOMETRY_BIT ? "\n" + mainCode : "")
2182 << "}\n";
2183
2184 if (!programCollection.glslSources.contains(shaderPrefix + "geom"))
2185 programCollection.glslSources.add(shaderPrefix + "geom") << glu::GeometrySource(src.str());
2186 }
2187
2188 if (requiredStages & VK_SHADER_STAGE_FRAGMENT_BIT)
2189 {
2190 std::ostringstream src;
2191 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
2192 << "\n"
2193 << "layout(location = 0) out vec4 o_color;\n"
2194 << "\n"
2195 << (stage & VK_SHADER_STAGE_FRAGMENT_BIT ? declCode + "\n" : "")
2196 << "void main (void)\n"
2197 << "{\n"
2198 << " o_color = vec4(1.0);\n"
2199 << (stage & VK_SHADER_STAGE_FRAGMENT_BIT ? "\n" + mainCode : "")
2200 << "}\n";
2201
2202 if (!programCollection.glslSources.contains(shaderPrefix + "frag"))
2203 programCollection.glslSources.add(shaderPrefix + "frag") << glu::FragmentSource(src.str());
2204 }
2205
2206 if (requiredStages & VK_SHADER_STAGE_COMPUTE_BIT)
2207 {
2208 std::ostringstream src;
2209 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
2210 << "\n"
2211 << "layout(local_size_x = 1) in;\n"
2212 << "\n"
2213 << (stage & VK_SHADER_STAGE_COMPUTE_BIT ? declCode + "\n" : "")
2214 << "void main (void)\n"
2215 << "{\n"
2216 << (stage & VK_SHADER_STAGE_COMPUTE_BIT ? mainCode : "")
2217 << "}\n";
2218
2219 if (!programCollection.glslSources.contains(shaderPrefix + "comp"))
2220 programCollection.glslSources.add(shaderPrefix + "comp") << glu::ComputeSource(src.str());
2221 }
2222 }
2223
2224 class BufferSupport : public OperationSupport
2225 {
2226 public:
BufferSupport(const ResourceDescription & resourceDesc,const BufferType bufferType,const AccessMode mode,const VkShaderStageFlagBits stage,const DispatchCall dispatchCall=DISPATCH_CALL_DISPATCH)2227 BufferSupport (const ResourceDescription& resourceDesc,
2228 const BufferType bufferType,
2229 const AccessMode mode,
2230 const VkShaderStageFlagBits stage,
2231 const DispatchCall dispatchCall = DISPATCH_CALL_DISPATCH)
2232 : m_resourceDesc (resourceDesc)
2233 , m_bufferType (bufferType)
2234 , m_mode (mode)
2235 , m_stage (stage)
2236 , m_shaderPrefix (std::string(m_mode == ACCESS_MODE_READ ? "read_" : "write_") + (m_bufferType == BUFFER_TYPE_UNIFORM ? "ubo_" : "ssbo_"))
2237 , m_dispatchCall (dispatchCall)
2238 {
2239 DE_ASSERT(m_resourceDesc.type == RESOURCE_TYPE_BUFFER);
2240 DE_ASSERT(m_bufferType == BUFFER_TYPE_UNIFORM || m_bufferType == BUFFER_TYPE_STORAGE);
2241 DE_ASSERT(m_mode == ACCESS_MODE_READ || m_mode == ACCESS_MODE_WRITE);
2242 DE_ASSERT(m_mode == ACCESS_MODE_READ || m_bufferType == BUFFER_TYPE_STORAGE);
2243 DE_ASSERT(m_bufferType != BUFFER_TYPE_UNIFORM || m_resourceDesc.size.x() <= MAX_UBO_RANGE);
2244 DE_ASSERT(m_dispatchCall == DISPATCH_CALL_DISPATCH || m_dispatchCall == DISPATCH_CALL_DISPATCH_INDIRECT);
2245
2246 assertValidShaderStage(m_stage);
2247 }
2248
initPrograms(SourceCollections & programCollection) const2249 void initPrograms (SourceCollections& programCollection) const
2250 {
2251 DE_ASSERT((m_resourceDesc.size.x() % sizeof(tcu::UVec4)) == 0);
2252
2253 const std::string bufferTypeStr = (m_bufferType == BUFFER_TYPE_UNIFORM ? "uniform" : "buffer");
2254 const int numVecElements = static_cast<int>(m_resourceDesc.size.x() / sizeof(tcu::UVec4)); // std140 must be aligned to a multiple of 16
2255
2256 std::ostringstream declSrc;
2257 declSrc << "layout(set = 0, binding = 0, std140) readonly " << bufferTypeStr << " Input {\n"
2258 << " uvec4 data[" << numVecElements << "];\n"
2259 << "} b_in;\n"
2260 << "\n"
2261 << "layout(set = 0, binding = 1, std140) writeonly buffer Output {\n"
2262 << " uvec4 data[" << numVecElements << "];\n"
2263 << "} b_out;\n";
2264
2265 std::ostringstream copySrc;
2266 copySrc << " for (int i = 0; i < " << numVecElements << "; ++i) {\n"
2267 << " b_out.data[i] = b_in.data[i];\n"
2268 << " }\n";
2269
2270 initPassthroughPrograms(programCollection, m_shaderPrefix, declSrc.str(), copySrc.str(), m_stage);
2271 }
2272
getInResourceUsageFlags(void) const2273 deUint32 getInResourceUsageFlags (void) const
2274 {
2275 if (m_bufferType == BUFFER_TYPE_UNIFORM)
2276 return m_mode == ACCESS_MODE_READ ? VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT : 0;
2277 else
2278 return m_mode == ACCESS_MODE_READ ? VK_BUFFER_USAGE_STORAGE_BUFFER_BIT : 0;
2279 }
2280
getOutResourceUsageFlags(void) const2281 deUint32 getOutResourceUsageFlags (void) const
2282 {
2283 if (m_bufferType == BUFFER_TYPE_UNIFORM)
2284 return m_mode == ACCESS_MODE_WRITE ? VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT : 0;
2285 else
2286 return m_mode == ACCESS_MODE_WRITE ? VK_BUFFER_USAGE_STORAGE_BUFFER_BIT : 0;
2287 }
2288
getQueueFlags(const OperationContext & context) const2289 VkQueueFlags getQueueFlags (const OperationContext& context) const
2290 {
2291 DE_UNREF(context);
2292 return (m_stage == VK_SHADER_STAGE_COMPUTE_BIT ? VK_QUEUE_COMPUTE_BIT : VK_QUEUE_GRAPHICS_BIT);
2293 }
2294
build(OperationContext & context,Resource & resource) const2295 de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
2296 {
2297 if (m_stage & VK_SHADER_STAGE_COMPUTE_BIT)
2298 return de::MovePtr<Operation>(new BufferImplementation(context, resource, m_stage, m_bufferType, m_shaderPrefix, m_mode, PIPELINE_TYPE_COMPUTE, m_dispatchCall));
2299 else
2300 return de::MovePtr<Operation>(new BufferImplementation(context, resource, m_stage, m_bufferType, m_shaderPrefix, m_mode, PIPELINE_TYPE_GRAPHICS, m_dispatchCall));
2301 }
2302
build(OperationContext &,Resource &,Resource &) const2303 de::MovePtr<Operation> build (OperationContext&, Resource&, Resource&) const
2304 {
2305 DE_ASSERT(0);
2306 return de::MovePtr<Operation>();
2307 }
2308
2309 private:
2310 const ResourceDescription m_resourceDesc;
2311 const BufferType m_bufferType;
2312 const AccessMode m_mode;
2313 const VkShaderStageFlagBits m_stage;
2314 const std::string m_shaderPrefix;
2315 const DispatchCall m_dispatchCall;
2316 };
2317
2318 class ImageSupport : public OperationSupport
2319 {
2320 public:
ImageSupport(const ResourceDescription & resourceDesc,const AccessMode mode,const VkShaderStageFlagBits stage,const DispatchCall dispatchCall=DISPATCH_CALL_DISPATCH)2321 ImageSupport (const ResourceDescription& resourceDesc,
2322 const AccessMode mode,
2323 const VkShaderStageFlagBits stage,
2324 const DispatchCall dispatchCall = DISPATCH_CALL_DISPATCH)
2325 : m_resourceDesc (resourceDesc)
2326 , m_mode (mode)
2327 , m_stage (stage)
2328 , m_shaderPrefix (m_mode == ACCESS_MODE_READ ? "read_image_" : "write_image_")
2329 , m_dispatchCall (dispatchCall)
2330 {
2331 DE_ASSERT(m_resourceDesc.type == RESOURCE_TYPE_IMAGE);
2332 DE_ASSERT(m_mode == ACCESS_MODE_READ || m_mode == ACCESS_MODE_WRITE);
2333 DE_ASSERT(m_dispatchCall == DISPATCH_CALL_DISPATCH || m_dispatchCall == DISPATCH_CALL_DISPATCH_INDIRECT);
2334
2335 assertValidShaderStage(m_stage);
2336 }
2337
initPrograms(SourceCollections & programCollection) const2338 void initPrograms (SourceCollections& programCollection) const
2339 {
2340 const std::string imageFormat = getShaderImageFormatQualifier(m_resourceDesc.imageFormat);
2341 const std::string imageType = getShaderImageType(m_resourceDesc.imageFormat, m_resourceDesc.imageType);
2342
2343 std::ostringstream declSrc;
2344 declSrc << "layout(set = 0, binding = 0, " << imageFormat << ") readonly uniform " << imageType << " srcImg;\n"
2345 << "layout(set = 0, binding = 1, " << imageFormat << ") writeonly uniform " << imageType << " dstImg;\n";
2346
2347 std::ostringstream mainSrc;
2348 if (m_resourceDesc.imageType == VK_IMAGE_TYPE_1D)
2349 mainSrc << " for (int x = 0; x < " << m_resourceDesc.size.x() << "; ++x)\n"
2350 << " imageStore(dstImg, x, imageLoad(srcImg, x));\n";
2351 else if (m_resourceDesc.imageType == VK_IMAGE_TYPE_2D)
2352 mainSrc << " for (int y = 0; y < " << m_resourceDesc.size.y() << "; ++y)\n"
2353 << " for (int x = 0; x < " << m_resourceDesc.size.x() << "; ++x)\n"
2354 << " imageStore(dstImg, ivec2(x, y), imageLoad(srcImg, ivec2(x, y)));\n";
2355 else if (m_resourceDesc.imageType == VK_IMAGE_TYPE_3D)
2356 mainSrc << " for (int z = 0; z < " << m_resourceDesc.size.z() << "; ++z)\n"
2357 << " for (int y = 0; y < " << m_resourceDesc.size.y() << "; ++y)\n"
2358 << " for (int x = 0; x < " << m_resourceDesc.size.x() << "; ++x)\n"
2359 << " imageStore(dstImg, ivec3(x, y, z), imageLoad(srcImg, ivec3(x, y, z)));\n";
2360 else
2361 DE_ASSERT(0);
2362
2363 initPassthroughPrograms(programCollection, m_shaderPrefix, declSrc.str(), mainSrc.str(), m_stage);
2364 }
2365
getInResourceUsageFlags(void) const2366 deUint32 getInResourceUsageFlags (void) const
2367 {
2368 return VK_IMAGE_USAGE_STORAGE_BIT;
2369 }
2370
getOutResourceUsageFlags(void) const2371 deUint32 getOutResourceUsageFlags (void) const
2372 {
2373 return VK_IMAGE_USAGE_STORAGE_BIT;
2374 }
2375
getQueueFlags(const OperationContext & context) const2376 VkQueueFlags getQueueFlags (const OperationContext& context) const
2377 {
2378 DE_UNREF(context);
2379 return (m_stage == VK_SHADER_STAGE_COMPUTE_BIT ? VK_QUEUE_COMPUTE_BIT : VK_QUEUE_GRAPHICS_BIT);
2380 }
2381
build(OperationContext & context,Resource & resource) const2382 de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
2383 {
2384 if (m_stage & VK_SHADER_STAGE_COMPUTE_BIT)
2385 return de::MovePtr<Operation>(new ImageImplementation(context, resource, m_stage, m_shaderPrefix, m_mode, PIPELINE_TYPE_COMPUTE, m_dispatchCall));
2386 else
2387 return de::MovePtr<Operation>(new ImageImplementation(context, resource, m_stage, m_shaderPrefix, m_mode, PIPELINE_TYPE_GRAPHICS, m_dispatchCall));
2388 }
2389
build(OperationContext &,Resource &,Resource &) const2390 de::MovePtr<Operation> build (OperationContext&, Resource&, Resource&) const
2391 {
2392 DE_ASSERT(0);
2393 return de::MovePtr<Operation>();
2394 }
2395
2396 private:
2397 const ResourceDescription m_resourceDesc;
2398 const AccessMode m_mode;
2399 const VkShaderStageFlagBits m_stage;
2400 const std::string m_shaderPrefix;
2401 const DispatchCall m_dispatchCall;
2402 };
2403
2404 //! Copy operation on a UBO/SSBO in graphics/compute pipeline.
2405 class BufferCopyImplementation : public Operation
2406 {
2407 public:
BufferCopyImplementation(OperationContext & context,Resource & inResource,Resource & outResource,const VkShaderStageFlagBits stage,const BufferType bufferType,const std::string & shaderPrefix,const PipelineType pipelineType,const DispatchCall dispatchCall)2408 BufferCopyImplementation (OperationContext& context,
2409 Resource& inResource,
2410 Resource& outResource,
2411 const VkShaderStageFlagBits stage,
2412 const BufferType bufferType,
2413 const std::string& shaderPrefix,
2414 const PipelineType pipelineType,
2415 const DispatchCall dispatchCall)
2416 : m_context (context)
2417 , m_inResource (inResource)
2418 , m_outResource (outResource)
2419 , m_stage (stage)
2420 , m_pipelineStage (pipelineStageFlagsFromShaderStageFlagBits(m_stage))
2421 , m_bufferType (bufferType)
2422 , m_dispatchCall (dispatchCall)
2423 {
2424 requireFeaturesForSSBOAccess (m_context, m_stage);
2425
2426 const DeviceInterface& vk = m_context.getDeviceInterface();
2427 const VkDevice device = m_context.getDevice();
2428
2429 // Prepare descriptors
2430 {
2431 const VkDescriptorType bufferDescriptorType = (m_bufferType == BUFFER_TYPE_UNIFORM ? VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER : VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
2432
2433 m_descriptorSetLayout = DescriptorSetLayoutBuilder()
2434 .addSingleBinding(bufferDescriptorType, m_stage)
2435 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, m_stage)
2436 .build(vk, device);
2437
2438 m_descriptorPool = DescriptorPoolBuilder()
2439 .addType(bufferDescriptorType)
2440 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
2441 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
2442
2443 m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
2444
2445 const VkDescriptorBufferInfo inBufferInfo = makeDescriptorBufferInfo(m_inResource.getBuffer().handle, m_inResource.getBuffer().offset, m_inResource.getBuffer().size);
2446 const VkDescriptorBufferInfo outBufferInfo = makeDescriptorBufferInfo(m_outResource.getBuffer().handle, m_outResource.getBuffer().offset, m_outResource.getBuffer().size);
2447
2448 DescriptorSetUpdateBuilder()
2449 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &inBufferInfo)
2450 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &outBufferInfo)
2451 .update(vk, device);
2452 }
2453
2454 // Create pipeline
2455 m_pipeline = (pipelineType == PIPELINE_TYPE_GRAPHICS ? de::MovePtr<Pipeline>(new GraphicsPipeline(context, stage, shaderPrefix, *m_descriptorSetLayout))
2456 : de::MovePtr<Pipeline>(new ComputePipeline(context, m_dispatchCall, shaderPrefix, *m_descriptorSetLayout)));
2457 }
2458
recordCommands(const VkCommandBuffer cmdBuffer)2459 void recordCommands (const VkCommandBuffer cmdBuffer)
2460 {
2461 m_pipeline->recordCommands(m_context, cmdBuffer, *m_descriptorSet);
2462 }
2463
getInSyncInfo(void) const2464 SyncInfo getInSyncInfo (void) const
2465 {
2466 const SyncInfo syncInfo =
2467 {
2468 m_pipelineStage, // VkPipelineStageFlags stageMask;
2469 VK_ACCESS_2_SHADER_READ_BIT_KHR, // VkAccessFlags accessMask;
2470 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout imageLayout;
2471 };
2472 return syncInfo;
2473 }
2474
getOutSyncInfo(void) const2475 SyncInfo getOutSyncInfo (void) const
2476 {
2477 const SyncInfo syncInfo =
2478 {
2479 m_pipelineStage, // VkPipelineStageFlags stageMask;
2480 VK_ACCESS_2_SHADER_WRITE_BIT_KHR, // VkAccessFlags accessMask;
2481 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout imageLayout;
2482 };
2483 return syncInfo;
2484 }
2485
getData(void) const2486 Data getData (void) const
2487 {
2488 Data data = { 0, DE_NULL };
2489 return data;
2490 }
2491
setData(const Data &)2492 void setData (const Data&)
2493 {
2494 DE_ASSERT(0);
2495 }
2496
2497 private:
2498 OperationContext& m_context;
2499 Resource& m_inResource;
2500 Resource& m_outResource;
2501 const VkShaderStageFlagBits m_stage;
2502 const VkPipelineStageFlags m_pipelineStage;
2503 const BufferType m_bufferType;
2504 const DispatchCall m_dispatchCall;
2505 Move<VkDescriptorPool> m_descriptorPool;
2506 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
2507 Move<VkDescriptorSet> m_descriptorSet;
2508 de::MovePtr<Pipeline> m_pipeline;
2509 };
2510
2511 class CopyBufferSupport : public OperationSupport
2512 {
2513 public:
CopyBufferSupport(const ResourceDescription & resourceDesc,const BufferType bufferType,const VkShaderStageFlagBits stage,const DispatchCall dispatchCall=DISPATCH_CALL_DISPATCH)2514 CopyBufferSupport (const ResourceDescription& resourceDesc,
2515 const BufferType bufferType,
2516 const VkShaderStageFlagBits stage,
2517 const DispatchCall dispatchCall = DISPATCH_CALL_DISPATCH)
2518 : m_resourceDesc (resourceDesc)
2519 , m_bufferType (bufferType)
2520 , m_stage (stage)
2521 , m_shaderPrefix (std::string("copy_") + getShaderStageName(stage) + (m_bufferType == BUFFER_TYPE_UNIFORM ? "_ubo_" : "_ssbo_"))
2522 , m_dispatchCall (dispatchCall)
2523 {
2524 DE_ASSERT(m_resourceDesc.type == RESOURCE_TYPE_BUFFER);
2525 DE_ASSERT(m_bufferType == BUFFER_TYPE_UNIFORM || m_bufferType == BUFFER_TYPE_STORAGE);
2526 DE_ASSERT(m_bufferType != BUFFER_TYPE_UNIFORM || m_resourceDesc.size.x() <= MAX_UBO_RANGE);
2527 DE_ASSERT(m_dispatchCall == DISPATCH_CALL_DISPATCH || m_dispatchCall == DISPATCH_CALL_DISPATCH_INDIRECT);
2528
2529 assertValidShaderStage(m_stage);
2530 }
2531
initPrograms(SourceCollections & programCollection) const2532 void initPrograms (SourceCollections& programCollection) const
2533 {
2534 DE_ASSERT((m_resourceDesc.size.x() % sizeof(tcu::UVec4)) == 0);
2535
2536 const std::string bufferTypeStr = (m_bufferType == BUFFER_TYPE_UNIFORM ? "uniform" : "buffer");
2537 const int numVecElements = static_cast<int>(m_resourceDesc.size.x() / sizeof(tcu::UVec4)); // std140 must be aligned to a multiple of 16
2538
2539 std::ostringstream declSrc;
2540 declSrc << "layout(set = 0, binding = 0, std140) readonly " << bufferTypeStr << " Input {\n"
2541 << " uvec4 data[" << numVecElements << "];\n"
2542 << "} b_in;\n"
2543 << "\n"
2544 << "layout(set = 0, binding = 1, std140) writeonly buffer Output {\n"
2545 << " uvec4 data[" << numVecElements << "];\n"
2546 << "} b_out;\n";
2547
2548 std::ostringstream copySrc;
2549 copySrc << " for (int i = 0; i < " << numVecElements << "; ++i) {\n"
2550 << " b_out.data[i] = b_in.data[i];\n"
2551 << " }\n";
2552
2553 initPassthroughPrograms(programCollection, m_shaderPrefix, declSrc.str(), copySrc.str(), m_stage);
2554 }
2555
getInResourceUsageFlags(void) const2556 deUint32 getInResourceUsageFlags (void) const
2557 {
2558 return (m_bufferType == BUFFER_TYPE_UNIFORM ? VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT : VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
2559 }
2560
getOutResourceUsageFlags(void) const2561 deUint32 getOutResourceUsageFlags (void) const
2562 {
2563 return VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
2564 }
2565
getQueueFlags(const OperationContext & context) const2566 VkQueueFlags getQueueFlags (const OperationContext& context) const
2567 {
2568 DE_UNREF(context);
2569 return (m_stage == VK_SHADER_STAGE_COMPUTE_BIT ? VK_QUEUE_COMPUTE_BIT : VK_QUEUE_GRAPHICS_BIT);
2570 }
2571
build(OperationContext &,Resource &) const2572 de::MovePtr<Operation> build (OperationContext&, Resource&) const
2573 {
2574 DE_ASSERT(0);
2575 return de::MovePtr<Operation>();
2576 }
2577
build(OperationContext & context,Resource & inResource,Resource & outResource) const2578 de::MovePtr<Operation> build (OperationContext& context, Resource& inResource, Resource& outResource) const
2579 {
2580 if (m_stage & VK_SHADER_STAGE_COMPUTE_BIT)
2581 return de::MovePtr<Operation>(new BufferCopyImplementation(context, inResource, outResource, m_stage, m_bufferType, m_shaderPrefix, PIPELINE_TYPE_COMPUTE, m_dispatchCall));
2582 else
2583 return de::MovePtr<Operation>(new BufferCopyImplementation(context, inResource, outResource, m_stage, m_bufferType, m_shaderPrefix, PIPELINE_TYPE_GRAPHICS, m_dispatchCall));
2584 }
2585
2586 private:
2587 const ResourceDescription m_resourceDesc;
2588 const BufferType m_bufferType;
2589 const VkShaderStageFlagBits m_stage;
2590 const std::string m_shaderPrefix;
2591 const DispatchCall m_dispatchCall;
2592 };
2593
2594 class CopyImageImplementation : public Operation
2595 {
2596 public:
CopyImageImplementation(OperationContext & context,Resource & inResource,Resource & outResource,const VkShaderStageFlagBits stage,const std::string & shaderPrefix,const PipelineType pipelineType,const DispatchCall dispatchCall)2597 CopyImageImplementation (OperationContext& context,
2598 Resource& inResource,
2599 Resource& outResource,
2600 const VkShaderStageFlagBits stage,
2601 const std::string& shaderPrefix,
2602 const PipelineType pipelineType,
2603 const DispatchCall dispatchCall)
2604 : m_context (context)
2605 , m_inResource (inResource)
2606 , m_outResource (outResource)
2607 , m_stage (stage)
2608 , m_pipelineStage (pipelineStageFlagsFromShaderStageFlagBits(m_stage))
2609 , m_dispatchCall (dispatchCall)
2610 {
2611 const DeviceInterface& vk = m_context.getDeviceInterface();
2612 const InstanceInterface& vki = m_context.getInstanceInterface();
2613 const VkDevice device = m_context.getDevice();
2614 const VkPhysicalDevice physDevice = m_context.getPhysicalDevice();
2615
2616 // Image stores are always required, in either access mode.
2617 requireFeaturesForSSBOAccess(m_context, m_stage);
2618
2619 // Some storage image formats may not be supported
2620 const auto& imgResource = m_inResource.getImage();
2621 requireStorageImageSupport(vki, physDevice, imgResource.format, imgResource.tiling);
2622
2623 // Image resources
2624 {
2625 const VkImageViewType viewType = getImageViewType(m_inResource.getImage().imageType);
2626
2627 m_srcImageView = makeImageView(vk, device, m_inResource.getImage().handle, viewType, m_inResource.getImage().format, m_inResource.getImage().subresourceRange);
2628 m_dstImageView = makeImageView(vk, device, m_outResource.getImage().handle, viewType, m_outResource.getImage().format, m_outResource.getImage().subresourceRange);
2629 }
2630
2631 // Prepare descriptors
2632 {
2633 m_descriptorSetLayout = DescriptorSetLayoutBuilder()
2634 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, m_stage)
2635 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, m_stage)
2636 .build(vk, device);
2637
2638 m_descriptorPool = DescriptorPoolBuilder()
2639 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
2640 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
2641 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
2642
2643 m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
2644
2645 const VkDescriptorImageInfo srcImageInfo = makeDescriptorImageInfo(DE_NULL, *m_srcImageView, VK_IMAGE_LAYOUT_GENERAL);
2646 const VkDescriptorImageInfo dstImageInfo = makeDescriptorImageInfo(DE_NULL, *m_dstImageView, VK_IMAGE_LAYOUT_GENERAL);
2647
2648 DescriptorSetUpdateBuilder()
2649 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &srcImageInfo)
2650 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &dstImageInfo)
2651 .update(vk, device);
2652 }
2653
2654 // Create pipeline
2655 m_pipeline = (pipelineType == PIPELINE_TYPE_GRAPHICS ? de::MovePtr<Pipeline>(new GraphicsPipeline(context, stage, shaderPrefix, *m_descriptorSetLayout))
2656 : de::MovePtr<Pipeline>(new ComputePipeline(context, m_dispatchCall, shaderPrefix, *m_descriptorSetLayout)));
2657 }
2658
recordCommands(const VkCommandBuffer cmdBuffer)2659 void recordCommands (const VkCommandBuffer cmdBuffer)
2660 {
2661 {
2662 const DeviceInterface& vk = m_context.getDeviceInterface();
2663 SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
2664
2665 const VkImageMemoryBarrier2KHR imageMemoryBarriers2 = makeImageMemoryBarrier2(
2666 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, // VkPipelineStageFlags2KHR srcStageMask
2667 (VkAccessFlags)0, // VkAccessFlags2KHR srcAccessMask
2668 m_pipelineStage, // VkPipelineStageFlags2KHR dstStageMask
2669 VK_ACCESS_2_SHADER_WRITE_BIT_KHR, // VkAccessFlags2KHR dstAccessMask
2670 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout
2671 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout
2672 m_outResource.getImage().handle, // VkImage image
2673 m_outResource.getImage().subresourceRange // VkImageSubresourceRange subresourceRange
2674 );
2675 VkDependencyInfoKHR dependencyInfo
2676 {
2677 VK_STRUCTURE_TYPE_DEPENDENCY_INFO_KHR, // VkStructureType sType
2678 DE_NULL, // const void* pNext
2679 VK_DEPENDENCY_BY_REGION_BIT, // VkDependencyFlags dependencyFlags
2680 0u, // deUint32 memoryBarrierCount
2681 DE_NULL, // const VkMemoryBarrier2KHR* pMemoryBarriers
2682 0u, // deUint32 bufferMemoryBarrierCount
2683 DE_NULL, // const VkBufferMemoryBarrier2KHR* pBufferMemoryBarriers
2684 1, // deUint32 imageMemoryBarrierCount
2685 &imageMemoryBarriers2 // const VkImageMemoryBarrier2KHR* pImageMemoryBarriers
2686 };
2687 synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
2688 }
2689
2690 // Execute shaders
2691 m_pipeline->recordCommands(m_context, cmdBuffer, *m_descriptorSet);
2692 }
2693
getInSyncInfo(void) const2694 SyncInfo getInSyncInfo (void) const
2695 {
2696 const SyncInfo syncInfo =
2697 {
2698 m_pipelineStage, // VkPipelineStageFlags stageMask;
2699 VK_ACCESS_2_SHADER_READ_BIT_KHR, // VkAccessFlags accessMask;
2700 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout imageLayout;
2701 };
2702 return syncInfo;
2703 }
2704
getOutSyncInfo(void) const2705 SyncInfo getOutSyncInfo (void) const
2706 {
2707 const SyncInfo syncInfo =
2708 {
2709 m_pipelineStage, // VkPipelineStageFlags stageMask;
2710 VK_ACCESS_2_SHADER_WRITE_BIT_KHR, // VkAccessFlags accessMask;
2711 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout imageLayout;
2712 };
2713 return syncInfo;
2714 }
2715
getData(void) const2716 Data getData (void) const
2717 {
2718 Data data = { 0, DE_NULL };
2719 return data;
2720 }
2721
setData(const Data &)2722 void setData (const Data&)
2723 {
2724 DE_ASSERT(0);
2725 }
2726
2727 private:
2728 OperationContext& m_context;
2729 Resource& m_inResource;
2730 Resource& m_outResource;
2731 const VkShaderStageFlagBits m_stage;
2732 const VkPipelineStageFlags m_pipelineStage;
2733 const DispatchCall m_dispatchCall;
2734 Move<VkImageView> m_srcImageView;
2735 Move<VkImageView> m_dstImageView;
2736 Move<VkDescriptorPool> m_descriptorPool;
2737 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
2738 Move<VkDescriptorSet> m_descriptorSet;
2739 de::MovePtr<Pipeline> m_pipeline;
2740 };
2741
2742 class CopyImageSupport : public OperationSupport
2743 {
2744 public:
CopyImageSupport(const ResourceDescription & resourceDesc,const VkShaderStageFlagBits stage,const DispatchCall dispatchCall=DISPATCH_CALL_DISPATCH)2745 CopyImageSupport (const ResourceDescription& resourceDesc,
2746 const VkShaderStageFlagBits stage,
2747 const DispatchCall dispatchCall = DISPATCH_CALL_DISPATCH)
2748 : m_resourceDesc (resourceDesc)
2749 , m_stage (stage)
2750 , m_shaderPrefix (std::string("copy_image_") + getShaderStageName(stage) + "_")
2751 , m_dispatchCall (dispatchCall)
2752 {
2753 DE_ASSERT(m_resourceDesc.type == RESOURCE_TYPE_IMAGE);
2754 DE_ASSERT(m_dispatchCall == DISPATCH_CALL_DISPATCH || m_dispatchCall == DISPATCH_CALL_DISPATCH_INDIRECT);
2755
2756 assertValidShaderStage(m_stage);
2757 }
2758
initPrograms(SourceCollections & programCollection) const2759 void initPrograms (SourceCollections& programCollection) const
2760 {
2761 const std::string imageFormat = getShaderImageFormatQualifier(m_resourceDesc.imageFormat);
2762 const std::string imageType = getShaderImageType(m_resourceDesc.imageFormat, m_resourceDesc.imageType);
2763
2764 std::ostringstream declSrc;
2765 declSrc << "layout(set = 0, binding = 0, " << imageFormat << ") readonly uniform " << imageType << " srcImg;\n"
2766 << "layout(set = 0, binding = 1, " << imageFormat << ") writeonly uniform " << imageType << " dstImg;\n";
2767
2768 std::ostringstream mainSrc;
2769 if (m_resourceDesc.imageType == VK_IMAGE_TYPE_1D)
2770 mainSrc << " for (int x = 0; x < " << m_resourceDesc.size.x() << "; ++x)\n"
2771 << " imageStore(dstImg, x, imageLoad(srcImg, x));\n";
2772 else if (m_resourceDesc.imageType == VK_IMAGE_TYPE_2D)
2773 mainSrc << " for (int y = 0; y < " << m_resourceDesc.size.y() << "; ++y)\n"
2774 << " for (int x = 0; x < " << m_resourceDesc.size.x() << "; ++x)\n"
2775 << " imageStore(dstImg, ivec2(x, y), imageLoad(srcImg, ivec2(x, y)));\n";
2776 else if (m_resourceDesc.imageType == VK_IMAGE_TYPE_3D)
2777 mainSrc << " for (int z = 0; z < " << m_resourceDesc.size.z() << "; ++z)\n"
2778 << " for (int y = 0; y < " << m_resourceDesc.size.y() << "; ++y)\n"
2779 << " for (int x = 0; x < " << m_resourceDesc.size.x() << "; ++x)\n"
2780 << " imageStore(dstImg, ivec3(x, y, z), imageLoad(srcImg, ivec3(x, y, z)));\n";
2781 else
2782 DE_ASSERT(0);
2783
2784 initPassthroughPrograms(programCollection, m_shaderPrefix, declSrc.str(), mainSrc.str(), m_stage);
2785 }
2786
getInResourceUsageFlags(void) const2787 deUint32 getInResourceUsageFlags (void) const
2788 {
2789 return VK_IMAGE_USAGE_STORAGE_BIT;
2790 }
2791
getOutResourceUsageFlags(void) const2792 deUint32 getOutResourceUsageFlags (void) const
2793 {
2794 return VK_IMAGE_USAGE_STORAGE_BIT;
2795 }
2796
getQueueFlags(const OperationContext & context) const2797 VkQueueFlags getQueueFlags (const OperationContext& context) const
2798 {
2799 DE_UNREF(context);
2800 return (m_stage == VK_SHADER_STAGE_COMPUTE_BIT ? VK_QUEUE_COMPUTE_BIT : VK_QUEUE_GRAPHICS_BIT);
2801 }
2802
build(OperationContext &,Resource &) const2803 de::MovePtr<Operation> build (OperationContext&, Resource&) const
2804 {
2805 DE_ASSERT(0);
2806 return de::MovePtr<Operation>();
2807 }
2808
build(OperationContext & context,Resource & inResource,Resource & outResource) const2809 de::MovePtr<Operation> build (OperationContext& context, Resource& inResource, Resource& outResource) const
2810 {
2811 if (m_stage & VK_SHADER_STAGE_COMPUTE_BIT)
2812 return de::MovePtr<Operation>(new CopyImageImplementation(context, inResource, outResource, m_stage, m_shaderPrefix, PIPELINE_TYPE_COMPUTE, m_dispatchCall));
2813 else
2814 return de::MovePtr<Operation>(new CopyImageImplementation(context, inResource, outResource, m_stage, m_shaderPrefix, PIPELINE_TYPE_GRAPHICS, m_dispatchCall));
2815 }
2816
2817 private:
2818 const ResourceDescription m_resourceDesc;
2819 const VkShaderStageFlagBits m_stage;
2820 const std::string m_shaderPrefix;
2821 const DispatchCall m_dispatchCall;
2822 };
2823
2824 class MSImageImplementation : public Operation
2825 {
2826 public:
MSImageImplementation(OperationContext & context,Resource & resource)2827 MSImageImplementation(OperationContext& context,
2828 Resource& resource)
2829 : m_context (context)
2830 , m_resource (resource)
2831 , m_hostBufferSizeBytes(getPixelBufferSize(m_resource.getImage().format, m_resource.getImage().extent))
2832 {
2833 const DeviceInterface& vk = m_context.getDeviceInterface();
2834 const InstanceInterface& vki = m_context.getInstanceInterface();
2835 const VkDevice device = m_context.getDevice();
2836 const VkPhysicalDevice physDevice = m_context.getPhysicalDevice();
2837 const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(vki, physDevice);
2838 Allocator& allocator = m_context.getAllocator();
2839
2840 const auto& imgResource = m_resource.getImage();
2841 requireStorageImageSupport(vki, physDevice, imgResource.format, imgResource.tiling);
2842 if (!features.shaderStorageImageMultisample)
2843 TCU_THROW(NotSupportedError, "Using multisample images as storage is not supported");
2844
2845 VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(m_hostBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
2846 m_hostBuffer = de::MovePtr<Buffer>(new Buffer(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible));
2847 const Allocation& alloc = m_hostBuffer->getAllocation();
2848 fillPattern(alloc.getHostPtr(), m_hostBufferSizeBytes);
2849 flushAlloc(vk, device, alloc);
2850
2851 const ImageResource& image = m_resource.getImage();
2852 const VkImageViewType viewType = getImageViewType(image.imageType);
2853 m_imageView = makeImageView(vk, device, image.handle, viewType, image.format, image.subresourceRange);
2854
2855 // Prepare descriptors
2856 {
2857 m_descriptorSetLayout = DescriptorSetLayoutBuilder()
2858 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
2859 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
2860 .build(vk, device);
2861
2862 m_descriptorPool = DescriptorPoolBuilder()
2863 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
2864 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
2865 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
2866
2867 m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
2868
2869 const VkDescriptorBufferInfo bufferInfo = makeDescriptorBufferInfo(**m_hostBuffer, 0u, m_hostBufferSizeBytes);
2870 const VkDescriptorImageInfo imageInfo = makeDescriptorImageInfo(DE_NULL, *m_imageView, VK_IMAGE_LAYOUT_GENERAL);
2871
2872 DescriptorSetUpdateBuilder()
2873 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &bufferInfo)
2874 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &imageInfo)
2875 .update(vk, device);
2876 }
2877
2878 // Create pipeline
2879 const Unique<VkShaderModule> shaderModule(createShaderModule(vk, device, context.getBinaryCollection().get("comp"), (VkShaderModuleCreateFlags)0));
2880 m_pipelineLayout = makePipelineLayout (vk, device, *m_descriptorSetLayout);
2881 m_pipeline = makeComputePipeline(vk, device, *m_pipelineLayout, *shaderModule, DE_NULL, context.getPipelineCacheData(), context.getResourceInterface());
2882 }
2883
recordCommands(const VkCommandBuffer cmdBuffer)2884 void recordCommands(const VkCommandBuffer cmdBuffer)
2885 {
2886 const DeviceInterface& vk = m_context.getDeviceInterface();
2887 SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
2888
2889 // change image layout
2890 {
2891 const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
2892 VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR, // VkPipelineStageFlags2KHR srcStageMask
2893 (VkAccessFlags)0, // VkAccessFlags2KHR srcAccessMask
2894 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT_KHR, // VkPipelineStageFlags2KHR dstStageMask
2895 VK_ACCESS_2_SHADER_WRITE_BIT_KHR, // VkAccessFlags2KHR dstAccessMask
2896 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout
2897 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout
2898 m_resource.getImage().handle, // VkImage image
2899 m_resource.getImage().subresourceRange // VkImageSubresourceRange subresourceRange
2900 );
2901 VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
2902 synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
2903 }
2904
2905 // execute shader
2906 vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipeline);
2907 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipelineLayout, 0u, 1u, &*m_descriptorSet, 0u, DE_NULL);
2908 vk.cmdDispatch(cmdBuffer, m_resource.getImage().extent.width, m_resource.getImage().extent.height, 1u);
2909 }
2910
getInSyncInfo(void) const2911 SyncInfo getInSyncInfo(void) const
2912 {
2913 DE_ASSERT(false);
2914 return emptySyncInfo;
2915 }
2916
getOutSyncInfo(void) const2917 SyncInfo getOutSyncInfo(void) const
2918 {
2919 return
2920 {
2921 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT_KHR, // VkPipelineStageFlags stageMask;
2922 VK_ACCESS_2_SHADER_WRITE_BIT_KHR, // VkAccessFlags accessMask;
2923 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout imageLayout;
2924 };
2925 }
2926
getData(void) const2927 Data getData(void) const
2928 {
2929 return getHostBufferData(m_context, *m_hostBuffer, m_hostBufferSizeBytes);
2930 }
2931
setData(const Data &)2932 void setData(const Data&)
2933 {
2934 DE_ASSERT(false);
2935 }
2936
2937 private:
2938 OperationContext& m_context;
2939 Resource& m_resource;
2940 Move<VkImageView> m_imageView;
2941
2942 const VkDeviceSize m_hostBufferSizeBytes;
2943 de::MovePtr<Buffer> m_hostBuffer;
2944
2945 Move<VkDescriptorPool> m_descriptorPool;
2946 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
2947 Move<VkDescriptorSet> m_descriptorSet;
2948 Move<VkPipelineLayout> m_pipelineLayout;
2949 Move<VkPipeline> m_pipeline;
2950 };
2951
2952 class MSImageSupport : public OperationSupport
2953 {
2954 public:
MSImageSupport(const ResourceDescription & resourceDesc)2955 MSImageSupport(const ResourceDescription& resourceDesc)
2956 : m_resourceDesc (resourceDesc)
2957 {
2958 DE_ASSERT(m_resourceDesc.type == RESOURCE_TYPE_IMAGE);
2959 }
2960
initPrograms(SourceCollections & programCollection) const2961 void initPrograms (SourceCollections& programCollection) const
2962 {
2963 std::stringstream source;
2964 source <<
2965 "#version 440\n"
2966 "\n"
2967 "layout(local_size_x = 1) in;\n"
2968 "layout(set = 0, binding = 0, std430) readonly buffer Input {\n"
2969 " uint data[];\n"
2970 "} inData;\n"
2971 "layout(set = 0, binding = 1, r32ui) writeonly uniform uimage2DMS msImage;\n"
2972 "\n"
2973 "void main (void)\n"
2974 "{\n"
2975 " int gx = int(gl_GlobalInvocationID.x);\n"
2976 " int gy = int(gl_GlobalInvocationID.y);\n"
2977 " uint value = inData.data[gy * " << m_resourceDesc.size.x() << " + gx];\n"
2978 " for (int sampleNdx = 0; sampleNdx < " << m_resourceDesc.imageSamples << "; ++sampleNdx)\n"
2979 " imageStore(msImage, ivec2(gx, gy), sampleNdx, uvec4(value));\n"
2980 "}\n";
2981 programCollection.glslSources.add("comp") << glu::ComputeSource(source.str().c_str());
2982 }
2983
getInResourceUsageFlags(void) const2984 deUint32 getInResourceUsageFlags (void) const
2985 {
2986 return 0;
2987 }
2988
getOutResourceUsageFlags(void) const2989 deUint32 getOutResourceUsageFlags (void) const
2990 {
2991 return VK_IMAGE_USAGE_STORAGE_BIT;
2992 }
2993
getQueueFlags(const OperationContext &) const2994 VkQueueFlags getQueueFlags (const OperationContext&) const
2995 {
2996 return VK_QUEUE_COMPUTE_BIT;
2997 }
2998
build(OperationContext & context,Resource & resource) const2999 de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
3000 {
3001 return de::MovePtr<Operation>(new MSImageImplementation(context, resource));
3002 }
3003
build(OperationContext &,Resource &,Resource &) const3004 de::MovePtr<Operation> build (OperationContext&, Resource&, Resource&) const
3005 {
3006 DE_ASSERT(0);
3007 return de::MovePtr<Operation>();
3008 }
3009
3010 private:
3011 const ResourceDescription m_resourceDesc;
3012 };
3013
3014 } // ShaderAccess ns
3015
3016 namespace CopyBufferToImage
3017 {
3018
3019 class WriteImplementation : public Operation
3020 {
3021 public:
WriteImplementation(OperationContext & context,Resource & resource)3022 WriteImplementation (OperationContext& context, Resource& resource)
3023 : m_context (context)
3024 , m_resource (resource)
3025 , m_bufferSize (getPixelBufferSize(m_resource.getImage().format, m_resource.getImage().extent))
3026 {
3027 DE_ASSERT(m_resource.getType() == RESOURCE_TYPE_IMAGE);
3028
3029 const DeviceInterface& vk = m_context.getDeviceInterface();
3030 const VkDevice device = m_context.getDevice();
3031 Allocator& allocator = m_context.getAllocator();
3032
3033 m_hostBuffer = de::MovePtr<Buffer>(new Buffer(
3034 vk, device, allocator, makeBufferCreateInfo(m_bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT), MemoryRequirement::HostVisible));
3035
3036 const Allocation& alloc = m_hostBuffer->getAllocation();
3037 fillPattern(alloc.getHostPtr(), m_bufferSize);
3038 flushAlloc(vk, device, alloc);
3039 }
3040
recordCommands(const VkCommandBuffer cmdBuffer)3041 void recordCommands (const VkCommandBuffer cmdBuffer)
3042 {
3043 const DeviceInterface& vk = m_context.getDeviceInterface();
3044 const VkBufferImageCopy copyRegion = makeBufferImageCopy(m_resource.getImage().extent, m_resource.getImage().subresourceLayers);
3045 SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
3046
3047 const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
3048 VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR, // VkPipelineStageFlags2KHR srcStageMask
3049 (VkAccessFlags)0, // VkAccessFlags2KHR srcAccessMask
3050 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags2KHR dstStageMask
3051 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR, // VkAccessFlags2KHR dstAccessMask
3052 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout
3053 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout
3054 m_resource.getImage().handle, // VkImage image
3055 m_resource.getImage().subresourceRange // VkImageSubresourceRange subresourceRange
3056 );
3057 VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
3058 synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
3059
3060 vk.cmdCopyBufferToImage(cmdBuffer, **m_hostBuffer, m_resource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, ©Region);
3061 }
3062
getInSyncInfo(void) const3063 SyncInfo getInSyncInfo (void) const
3064 {
3065 return emptySyncInfo;
3066 }
3067
getOutSyncInfo(void) const3068 SyncInfo getOutSyncInfo (void) const
3069 {
3070 const SyncInfo syncInfo =
3071 {
3072 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags stageMask;
3073 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR, // VkAccessFlags accessMask;
3074 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout imageLayout;
3075 };
3076 return syncInfo;
3077 }
3078
getData(void) const3079 Data getData (void) const
3080 {
3081 return getHostBufferData(m_context, *m_hostBuffer, m_bufferSize);
3082 }
3083
setData(const Data & data)3084 void setData (const Data& data)
3085 {
3086 setHostBufferData(m_context, *m_hostBuffer, data);
3087 }
3088
3089 private:
3090 OperationContext& m_context;
3091 Resource& m_resource;
3092 de::MovePtr<Buffer> m_hostBuffer;
3093 const VkDeviceSize m_bufferSize;
3094 };
3095
3096 class ReadImplementation : public Operation
3097 {
3098 public:
ReadImplementation(OperationContext & context,Resource & resource)3099 ReadImplementation (OperationContext& context, Resource& resource)
3100 : m_context (context)
3101 , m_resource (resource)
3102 , m_subresourceRange (makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u))
3103 , m_subresourceLayers (makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u))
3104 {
3105 DE_ASSERT(m_resource.getType() == RESOURCE_TYPE_BUFFER);
3106
3107 const DeviceInterface& vk = m_context.getDeviceInterface();
3108 const VkDevice device = m_context.getDevice();
3109 Allocator& allocator = m_context.getAllocator();
3110 const VkFormat format = VK_FORMAT_R8G8B8A8_UNORM;
3111 const deUint32 pixelSize = tcu::getPixelSize(mapVkFormat(format));
3112
3113 DE_ASSERT((m_resource.getBuffer().size % pixelSize) == 0);
3114 m_imageExtent = get2DImageExtentWithSize(m_resource.getBuffer().size, pixelSize); // there may be some unused space at the end
3115
3116 // Copy destination image.
3117 m_image = de::MovePtr<Image>(new Image(
3118 vk, device, allocator,
3119 makeImageCreateInfo(VK_IMAGE_TYPE_2D, m_imageExtent, format,
3120 (VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT),
3121 VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL),
3122 MemoryRequirement::Any));
3123
3124 // Image data will be copied here, so it can be read on the host.
3125 m_hostBuffer = de::MovePtr<Buffer>(new Buffer(
3126 vk, device, allocator, makeBufferCreateInfo(m_resource.getBuffer().size, VK_BUFFER_USAGE_TRANSFER_DST_BIT), MemoryRequirement::HostVisible));
3127 }
3128
recordCommands(const VkCommandBuffer cmdBuffer)3129 void recordCommands (const VkCommandBuffer cmdBuffer)
3130 {
3131 const DeviceInterface& vk = m_context.getDeviceInterface();
3132 const VkBufferImageCopy copyRegion = makeBufferImageCopy(m_imageExtent, m_subresourceLayers);
3133 SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
3134
3135 // Resource -> Image
3136 {
3137 const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
3138 VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR, // VkPipelineStageFlags2KHR srcStageMask
3139 (VkAccessFlags)0, // VkAccessFlags2KHR srcAccessMask
3140 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags2KHR dstStageMask
3141 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR, // VkAccessFlags2KHR dstAccessMask
3142 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout
3143 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout
3144 **m_image, // VkImage image
3145 m_subresourceRange // VkImageSubresourceRange subresourceRange
3146 );
3147 VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
3148 synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
3149
3150 vk.cmdCopyBufferToImage(cmdBuffer, m_resource.getBuffer().handle, **m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, ©Region);
3151 }
3152 // Image -> Host buffer
3153 {
3154 const VkImageMemoryBarrier2KHR imageLayoutBarrier2 = makeImageMemoryBarrier2(
3155 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags2KHR srcStageMask
3156 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR, // VkAccessFlags2KHR srcAccessMask
3157 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags2KHR dstStageMask
3158 VK_ACCESS_2_TRANSFER_READ_BIT_KHR, // VkAccessFlags2KHR dstAccessMask
3159 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout
3160 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout
3161 **m_image, // VkImage image
3162 m_subresourceRange // VkImageSubresourceRange subresourceRange
3163 );
3164 VkDependencyInfoKHR layoutDependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageLayoutBarrier2);
3165 synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &layoutDependencyInfo);
3166
3167 vk.cmdCopyImageToBuffer(cmdBuffer, **m_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_hostBuffer, 1u, ©Region);
3168
3169 const VkBufferMemoryBarrier2KHR bufferMemoryBarrier2 = makeBufferMemoryBarrier2(
3170 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags2KHR srcStageMask
3171 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR, // VkAccessFlags2KHR srcAccessMask
3172 VK_PIPELINE_STAGE_2_HOST_BIT_KHR, // VkPipelineStageFlags2KHR dstStageMask
3173 VK_ACCESS_2_HOST_READ_BIT_KHR, // VkAccessFlags2KHR dstAccessMask
3174 **m_hostBuffer, // VkBuffer buffer
3175 0u, // VkDeviceSize offset
3176 m_resource.getBuffer().size // VkDeviceSize size
3177 );
3178 VkDependencyInfoKHR bufferDependencyInfo = makeCommonDependencyInfo(DE_NULL, &bufferMemoryBarrier2);
3179 synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &bufferDependencyInfo);
3180 }
3181 }
3182
getInSyncInfo(void) const3183 SyncInfo getInSyncInfo (void) const
3184 {
3185 const SyncInfo syncInfo =
3186 {
3187 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags stageMask;
3188 VK_ACCESS_2_TRANSFER_READ_BIT_KHR, // VkAccessFlags accessMask;
3189 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout imageLayout;
3190 };
3191 return syncInfo;
3192 }
3193
getOutSyncInfo(void) const3194 SyncInfo getOutSyncInfo (void) const
3195 {
3196 return emptySyncInfo;
3197 }
3198
getData(void) const3199 Data getData (void) const
3200 {
3201 return getHostBufferData(m_context, *m_hostBuffer, m_resource.getBuffer().size);
3202 }
3203
setData(const Data & data)3204 void setData (const Data& data)
3205 {
3206 setHostBufferData(m_context, *m_hostBuffer, data);
3207 }
3208
3209 private:
3210 OperationContext& m_context;
3211 Resource& m_resource;
3212 const VkImageSubresourceRange m_subresourceRange;
3213 const VkImageSubresourceLayers m_subresourceLayers;
3214 de::MovePtr<Buffer> m_hostBuffer;
3215 de::MovePtr<Image> m_image;
3216 VkExtent3D m_imageExtent;
3217 };
3218
3219 class Support : public OperationSupport
3220 {
3221 public:
Support(const ResourceDescription & resourceDesc,const AccessMode mode)3222 Support (const ResourceDescription& resourceDesc, const AccessMode mode)
3223 : m_mode (mode)
3224 , m_resourceType (resourceDesc.type)
3225 , m_requiredQueueFlags (resourceDesc.type == RESOURCE_TYPE_IMAGE && isDepthStencilFormat(resourceDesc.imageFormat) ? VK_QUEUE_GRAPHICS_BIT : VK_QUEUE_TRANSFER_BIT)
3226 {
3227 // From spec:
3228 // Because depth or stencil aspect buffer to image copies may require format conversions on some implementations,
3229 // they are not supported on queues that do not support graphics.
3230
3231 DE_ASSERT(m_mode == ACCESS_MODE_READ || m_mode == ACCESS_MODE_WRITE);
3232 DE_ASSERT(m_mode == ACCESS_MODE_READ || resourceDesc.type != RESOURCE_TYPE_BUFFER);
3233 DE_ASSERT(m_mode == ACCESS_MODE_WRITE || resourceDesc.type != RESOURCE_TYPE_IMAGE);
3234 }
3235
getInResourceUsageFlags(void) const3236 deUint32 getInResourceUsageFlags (void) const
3237 {
3238 if (m_resourceType == RESOURCE_TYPE_IMAGE)
3239 return m_mode == ACCESS_MODE_READ ? VK_IMAGE_USAGE_TRANSFER_SRC_BIT : 0;
3240 else
3241 return m_mode == ACCESS_MODE_READ ? VK_BUFFER_USAGE_TRANSFER_SRC_BIT : 0;
3242 }
3243
getOutResourceUsageFlags(void) const3244 deUint32 getOutResourceUsageFlags (void) const
3245 {
3246 if (m_resourceType == RESOURCE_TYPE_IMAGE)
3247 return m_mode == ACCESS_MODE_WRITE ? VK_IMAGE_USAGE_TRANSFER_DST_BIT : 0;
3248 else
3249 return m_mode == ACCESS_MODE_WRITE ? VK_BUFFER_USAGE_TRANSFER_DST_BIT : 0;
3250 }
3251
getQueueFlags(const OperationContext & context) const3252 VkQueueFlags getQueueFlags (const OperationContext& context) const
3253 {
3254 DE_UNREF(context);
3255 return m_requiredQueueFlags;
3256 }
3257
build(OperationContext & context,Resource & resource) const3258 de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
3259 {
3260 if (m_mode == ACCESS_MODE_READ)
3261 return de::MovePtr<Operation>(new ReadImplementation(context, resource));
3262 else
3263 return de::MovePtr<Operation>(new WriteImplementation(context, resource));
3264 }
3265
build(OperationContext &,Resource &,Resource &) const3266 de::MovePtr<Operation> build (OperationContext&, Resource&, Resource&) const
3267 {
3268 DE_ASSERT(0);
3269 return de::MovePtr<Operation>();
3270 }
3271
3272 private:
3273 const AccessMode m_mode;
3274 const enum ResourceType m_resourceType;
3275 const VkQueueFlags m_requiredQueueFlags;
3276 };
3277
3278 class CopyImplementation : public Operation
3279 {
3280 public:
CopyImplementation(OperationContext & context,Resource & inResource,Resource & outResource)3281 CopyImplementation (OperationContext& context, Resource& inResource, Resource& outResource)
3282 : m_context (context)
3283 , m_inResource (inResource)
3284 , m_outResource (outResource)
3285 {
3286 DE_ASSERT(m_inResource.getType() == RESOURCE_TYPE_BUFFER);
3287 DE_ASSERT(m_outResource.getType() == RESOURCE_TYPE_IMAGE);
3288 }
3289
recordCommands(const VkCommandBuffer cmdBuffer)3290 void recordCommands (const VkCommandBuffer cmdBuffer)
3291 {
3292 const DeviceInterface& vk = m_context.getDeviceInterface();
3293 const VkBufferImageCopy copyRegion = makeBufferImageCopy(m_outResource.getImage().extent, m_outResource.getImage().subresourceLayers);
3294 SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
3295
3296 const VkBufferMemoryBarrier2KHR bufferMemoryBarrier2 = makeBufferMemoryBarrier2(
3297 VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR, // VkPipelineStageFlags2KHR srcStageMask
3298 (VkAccessFlags)0, // VkAccessFlags2KHR srcAccessMask
3299 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags2KHR dstStageMask
3300 VK_ACCESS_2_TRANSFER_READ_BIT_KHR, // VkAccessFlags2KHR dstAccessMask
3301 m_inResource.getBuffer().handle, // VkBuffer buffer
3302 0u, // VkDeviceSize offset
3303 m_inResource.getBuffer().size // VkDeviceSize size
3304 );
3305 const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
3306 VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR, // VkPipelineStageFlags2KHR srcStageMask
3307 (VkAccessFlags)0, // VkAccessFlags2KHR srcAccessMask
3308 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags2KHR dstStageMask
3309 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR, // VkAccessFlags2KHR dstAccessMask
3310 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout
3311 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout
3312 m_outResource.getImage().handle, // VkImage image
3313 m_outResource.getImage().subresourceRange // VkImageSubresourceRange subresourceRange
3314 );
3315 VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, &bufferMemoryBarrier2, &imageMemoryBarrier2);
3316 synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
3317
3318 vk.cmdCopyBufferToImage(cmdBuffer, m_inResource.getBuffer().handle, m_outResource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, ©Region);
3319 }
3320
getInSyncInfo(void) const3321 SyncInfo getInSyncInfo (void) const
3322 {
3323 const SyncInfo syncInfo =
3324 {
3325 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags stageMask;
3326 VK_ACCESS_2_TRANSFER_READ_BIT_KHR, // VkAccessFlags accessMask;
3327 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout imageLayout;
3328 };
3329 return syncInfo;
3330 }
3331
getOutSyncInfo(void) const3332 SyncInfo getOutSyncInfo (void) const
3333 {
3334 const SyncInfo syncInfo =
3335 {
3336 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags stageMask;
3337 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR, // VkAccessFlags accessMask;
3338 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout imageLayout;
3339 };
3340 return syncInfo;
3341 }
3342
getData(void) const3343 Data getData (void) const
3344 {
3345 Data data = { 0, DE_NULL };
3346 return data;
3347 }
3348
setData(const Data &)3349 void setData (const Data&)
3350 {
3351 DE_ASSERT(0);
3352 }
3353
3354 private:
3355 OperationContext& m_context;
3356 Resource& m_inResource;
3357 Resource& m_outResource;
3358 };
3359
3360 class CopySupport : public OperationSupport
3361 {
3362 public:
CopySupport(const ResourceDescription & resourceDesc)3363 CopySupport (const ResourceDescription& resourceDesc)
3364 : m_resourceType (resourceDesc.type)
3365 , m_requiredQueueFlags (resourceDesc.type == RESOURCE_TYPE_IMAGE && isDepthStencilFormat(resourceDesc.imageFormat) ? VK_QUEUE_GRAPHICS_BIT : VK_QUEUE_TRANSFER_BIT)
3366 {
3367 }
3368
getInResourceUsageFlags(void) const3369 deUint32 getInResourceUsageFlags (void) const
3370 {
3371 if (m_resourceType == RESOURCE_TYPE_IMAGE)
3372 return VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
3373 else
3374 return VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
3375 }
3376
getOutResourceUsageFlags(void) const3377 deUint32 getOutResourceUsageFlags (void) const
3378 {
3379 if (m_resourceType == RESOURCE_TYPE_IMAGE)
3380 return VK_IMAGE_USAGE_TRANSFER_DST_BIT;
3381 else
3382 return VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3383 }
3384
getQueueFlags(const OperationContext & context) const3385 VkQueueFlags getQueueFlags (const OperationContext& context) const
3386 {
3387 DE_UNREF(context);
3388 return m_requiredQueueFlags;
3389 }
3390
build(OperationContext &,Resource &) const3391 de::MovePtr<Operation> build (OperationContext&, Resource&) const
3392 {
3393 DE_ASSERT(0);
3394 return de::MovePtr<Operation>();
3395 }
3396
build(OperationContext & context,Resource & inResource,Resource & outResource) const3397 de::MovePtr<Operation> build (OperationContext& context, Resource& inResource, Resource& outResource) const
3398 {
3399 return de::MovePtr<Operation>(new CopyImplementation(context, inResource, outResource));
3400 }
3401
3402 private:
3403 const enum ResourceType m_resourceType;
3404 const VkQueueFlags m_requiredQueueFlags;
3405 };
3406
3407 } // CopyBufferToImage ns
3408
3409 namespace CopyImageToBuffer
3410 {
3411
3412 class WriteImplementation : public Operation
3413 {
3414 public:
WriteImplementation(OperationContext & context,Resource & resource)3415 WriteImplementation (OperationContext& context, Resource& resource)
3416 : m_context (context)
3417 , m_resource (resource)
3418 , m_subresourceRange (makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u))
3419 , m_subresourceLayers (makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u))
3420 {
3421 DE_ASSERT(m_resource.getType() == RESOURCE_TYPE_BUFFER);
3422
3423 const DeviceInterface& vk = m_context.getDeviceInterface();
3424 const VkDevice device = m_context.getDevice();
3425 Allocator& allocator = m_context.getAllocator();
3426 const VkFormat format = VK_FORMAT_R8G8B8A8_UNORM;
3427 const deUint32 pixelSize = tcu::getPixelSize(mapVkFormat(format));
3428
3429 DE_ASSERT((m_resource.getBuffer().size % pixelSize) == 0);
3430 m_imageExtent = get2DImageExtentWithSize(m_resource.getBuffer().size, pixelSize);
3431
3432 // Source data staging buffer
3433 m_hostBuffer = de::MovePtr<Buffer>(new Buffer(
3434 vk, device, allocator, makeBufferCreateInfo(m_resource.getBuffer().size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT), MemoryRequirement::HostVisible));
3435
3436 const Allocation& alloc = m_hostBuffer->getAllocation();
3437 fillPattern(alloc.getHostPtr(), m_resource.getBuffer().size);
3438 flushAlloc(vk, device, alloc);
3439
3440 // Source data image
3441 m_image = de::MovePtr<Image>(new Image(
3442 vk, device, allocator,
3443 makeImageCreateInfo(VK_IMAGE_TYPE_2D, m_imageExtent, format, (VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT),
3444 VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL),
3445 MemoryRequirement::Any));
3446 }
3447
recordCommands(const VkCommandBuffer cmdBuffer)3448 void recordCommands (const VkCommandBuffer cmdBuffer)
3449 {
3450 const DeviceInterface& vk = m_context.getDeviceInterface();
3451 const VkBufferImageCopy copyRegion = makeBufferImageCopy(m_imageExtent, m_subresourceLayers);
3452 SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
3453
3454 // Host buffer -> Image
3455 {
3456 const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
3457 VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR, // VkPipelineStageFlags2KHR srcStageMask
3458 (VkAccessFlags)0, // VkAccessFlags2KHR srcAccessMask
3459 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags2KHR dstStageMask
3460 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR, // VkAccessFlags2KHR dstAccessMask
3461 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout
3462 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout
3463 **m_image, // VkImage image
3464 m_subresourceRange // VkImageSubresourceRange subresourceRange
3465 );
3466 VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
3467 synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
3468
3469 vk.cmdCopyBufferToImage(cmdBuffer, **m_hostBuffer, **m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, ©Region);
3470 }
3471 // Image -> Resource
3472 {
3473 const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
3474 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags2KHR srcStageMask
3475 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR, // VkAccessFlags2KHR srcAccessMask
3476 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags2KHR dstStageMask
3477 VK_ACCESS_2_TRANSFER_READ_BIT_KHR, // VkAccessFlags2KHR dstAccessMask
3478 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout
3479 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout
3480 **m_image, // VkImage image
3481 m_subresourceRange // VkImageSubresourceRange subresourceRange
3482 );
3483 VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
3484 synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
3485
3486 vk.cmdCopyImageToBuffer(cmdBuffer, **m_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, m_resource.getBuffer().handle, 1u, ©Region);
3487 }
3488 }
3489
getInSyncInfo(void) const3490 SyncInfo getInSyncInfo (void) const
3491 {
3492 return emptySyncInfo;
3493 }
3494
getOutSyncInfo(void) const3495 SyncInfo getOutSyncInfo (void) const
3496 {
3497 const SyncInfo syncInfo =
3498 {
3499 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags stageMask;
3500 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR, // VkAccessFlags accessMask;
3501 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout imageLayout;
3502 };
3503 return syncInfo;
3504 }
3505
getData(void) const3506 Data getData (void) const
3507 {
3508 return getHostBufferData(m_context, *m_hostBuffer, m_resource.getBuffer().size);
3509 }
3510
setData(const Data & data)3511 void setData (const Data& data)
3512 {
3513 setHostBufferData(m_context, *m_hostBuffer, data);
3514 }
3515
3516 private:
3517 OperationContext& m_context;
3518 Resource& m_resource;
3519 const VkImageSubresourceRange m_subresourceRange;
3520 const VkImageSubresourceLayers m_subresourceLayers;
3521 de::MovePtr<Buffer> m_hostBuffer;
3522 de::MovePtr<Image> m_image;
3523 VkExtent3D m_imageExtent;
3524 };
3525
3526 class ReadImplementation : public Operation
3527 {
3528 public:
ReadImplementation(OperationContext & context,Resource & resource)3529 ReadImplementation (OperationContext& context, Resource& resource)
3530 : m_context (context)
3531 , m_resource (resource)
3532 , m_bufferSize (getPixelBufferSize(m_resource.getImage().format, m_resource.getImage().extent))
3533 {
3534 DE_ASSERT(m_resource.getType() == RESOURCE_TYPE_IMAGE);
3535
3536 const DeviceInterface& vk = m_context.getDeviceInterface();
3537 const VkDevice device = m_context.getDevice();
3538 Allocator& allocator = m_context.getAllocator();
3539
3540 m_hostBuffer = de::MovePtr<Buffer>(new Buffer(
3541 vk, device, allocator, makeBufferCreateInfo(m_bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT), MemoryRequirement::HostVisible));
3542
3543 const Allocation& alloc = m_hostBuffer->getAllocation();
3544 deMemset(alloc.getHostPtr(), 0, static_cast<size_t>(m_bufferSize));
3545 flushAlloc(vk, device, alloc);
3546 }
3547
recordCommands(const VkCommandBuffer cmdBuffer)3548 void recordCommands (const VkCommandBuffer cmdBuffer)
3549 {
3550 const DeviceInterface& vk = m_context.getDeviceInterface();
3551 const VkBufferImageCopy copyRegion = makeBufferImageCopy(m_resource.getImage().extent, m_resource.getImage().subresourceLayers);
3552 SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
3553
3554 vk.cmdCopyImageToBuffer(cmdBuffer, m_resource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_hostBuffer, 1u, ©Region);
3555
3556 // Insert a barrier so data written by the transfer is available to the host
3557 {
3558 const VkBufferMemoryBarrier2KHR bufferMemoryBarrier2 = makeBufferMemoryBarrier2(
3559 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags2KHR srcStageMask
3560 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR, // VkAccessFlags2KHR srcAccessMask
3561 VK_PIPELINE_STAGE_2_HOST_BIT_KHR, // VkPipelineStageFlags2KHR dstStageMask
3562 VK_ACCESS_2_HOST_READ_BIT_KHR, // VkAccessFlags2KHR dstAccessMask
3563 **m_hostBuffer, // VkBuffer buffer
3564 0u, // VkDeviceSize offset
3565 VK_WHOLE_SIZE // VkDeviceSize size
3566 );
3567 VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, &bufferMemoryBarrier2);
3568 synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
3569 }
3570 }
3571
getInSyncInfo(void) const3572 SyncInfo getInSyncInfo (void) const
3573 {
3574 const SyncInfo syncInfo =
3575 {
3576 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags stageMask;
3577 VK_ACCESS_2_TRANSFER_READ_BIT_KHR, // VkAccessFlags accessMask;
3578 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout imageLayout;
3579 };
3580 return syncInfo;
3581 }
3582
getOutSyncInfo(void) const3583 SyncInfo getOutSyncInfo (void) const
3584 {
3585 return emptySyncInfo;
3586 }
3587
getData(void) const3588 Data getData (void) const
3589 {
3590 return getHostBufferData(m_context, *m_hostBuffer, m_bufferSize);
3591 }
3592
setData(const Data &)3593 void setData (const Data&)
3594 {
3595 DE_ASSERT(0);
3596 }
3597
3598 private:
3599 OperationContext& m_context;
3600 Resource& m_resource;
3601 de::MovePtr<Buffer> m_hostBuffer;
3602 const VkDeviceSize m_bufferSize;
3603 };
3604
3605 class CopyImplementation : public Operation
3606 {
3607 public:
CopyImplementation(OperationContext & context,Resource & inResource,Resource & outResource)3608 CopyImplementation (OperationContext& context, Resource& inResource, Resource& outResource)
3609 : m_context (context)
3610 , m_inResource (inResource)
3611 , m_outResource (outResource)
3612 , m_subresourceRange (makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u))
3613 , m_subresourceLayers (makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u))
3614 {
3615 DE_ASSERT(m_inResource.getType() == RESOURCE_TYPE_IMAGE);
3616 DE_ASSERT(m_outResource.getType() == RESOURCE_TYPE_BUFFER);
3617 }
3618
recordCommands(const VkCommandBuffer cmdBuffer)3619 void recordCommands (const VkCommandBuffer cmdBuffer)
3620 {
3621 const DeviceInterface& vk = m_context.getDeviceInterface();
3622 const VkBufferImageCopy copyRegion = makeBufferImageCopy(m_inResource.getImage().extent, m_subresourceLayers);
3623 SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
3624
3625 {
3626 const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
3627 VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR, // VkPipelineStageFlags2KHR srcStageMask
3628 (VkAccessFlags)0, // VkAccessFlags2KHR srcAccessMask
3629 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags2KHR dstStageMask
3630 VK_ACCESS_2_TRANSFER_READ_BIT_KHR, // VkAccessFlags2KHR dstAccessMask
3631 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout
3632 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout
3633 m_inResource.getImage().handle, // VkImage image
3634 m_inResource.getImage().subresourceRange // VkImageSubresourceRange subresourceRange
3635 );
3636 const VkBufferMemoryBarrier2KHR bufferMemoryBarrier2 = makeBufferMemoryBarrier2(
3637 VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR, // VkPipelineStageFlags2KHR srcStageMask
3638 (VkAccessFlags)0, // VkAccessFlags2KHR srcAccessMask
3639 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags2KHR dstStageMask
3640 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR, // VkAccessFlags2KHR dstAccessMask
3641 m_outResource.getBuffer().handle, // VkBuffer buffer
3642 0u, // VkDeviceSize offset
3643 m_outResource.getBuffer().size // VkDeviceSize size
3644 );
3645 VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, &bufferMemoryBarrier2, &imageMemoryBarrier2);
3646 synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
3647 }
3648
3649 vk.cmdCopyImageToBuffer(cmdBuffer, m_inResource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, m_outResource.getBuffer().handle, 1u, ©Region);
3650 }
3651
getInSyncInfo(void) const3652 SyncInfo getInSyncInfo (void) const
3653 {
3654 const SyncInfo syncInfo =
3655 {
3656 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags stageMask;
3657 VK_ACCESS_2_TRANSFER_READ_BIT_KHR, // VkAccessFlags accessMask;
3658 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout imageLayout;
3659 };
3660 return syncInfo;
3661 }
3662
getOutSyncInfo(void) const3663 SyncInfo getOutSyncInfo (void) const
3664 {
3665 const SyncInfo syncInfo =
3666 {
3667 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags stageMask;
3668 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR, // VkAccessFlags accessMask;
3669 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout imageLayout;
3670 };
3671 return syncInfo;
3672 }
3673
getData(void) const3674 Data getData (void) const
3675 {
3676 Data data = { 0, DE_NULL };
3677 return data;
3678 }
3679
setData(const Data &)3680 void setData (const Data&)
3681 {
3682 DE_ASSERT(0);
3683 }
3684
3685 private:
3686 OperationContext& m_context;
3687 Resource& m_inResource;
3688 Resource& m_outResource;
3689 const VkImageSubresourceRange m_subresourceRange;
3690 const VkImageSubresourceLayers m_subresourceLayers;
3691 };
3692
3693 class Support : public OperationSupport
3694 {
3695 public:
Support(const ResourceDescription & resourceDesc,const AccessMode mode)3696 Support (const ResourceDescription& resourceDesc, const AccessMode mode)
3697 : m_mode (mode)
3698 , m_requiredQueueFlags (resourceDesc.type == RESOURCE_TYPE_IMAGE && isDepthStencilFormat(resourceDesc.imageFormat) ? VK_QUEUE_GRAPHICS_BIT : VK_QUEUE_TRANSFER_BIT)
3699 {
3700 DE_ASSERT(m_mode == ACCESS_MODE_READ || m_mode == ACCESS_MODE_WRITE);
3701 DE_ASSERT(m_mode == ACCESS_MODE_READ || resourceDesc.type != RESOURCE_TYPE_IMAGE);
3702 DE_ASSERT(m_mode == ACCESS_MODE_WRITE || resourceDesc.type != RESOURCE_TYPE_BUFFER);
3703 }
3704
getInResourceUsageFlags(void) const3705 deUint32 getInResourceUsageFlags (void) const
3706 {
3707 return m_mode == ACCESS_MODE_READ ? VK_BUFFER_USAGE_TRANSFER_SRC_BIT : 0;
3708 }
3709
getOutResourceUsageFlags(void) const3710 deUint32 getOutResourceUsageFlags (void) const
3711 {
3712 return m_mode == ACCESS_MODE_WRITE ? VK_BUFFER_USAGE_TRANSFER_DST_BIT : 0;
3713 }
3714
getQueueFlags(const OperationContext & context) const3715 VkQueueFlags getQueueFlags (const OperationContext& context) const
3716 {
3717 DE_UNREF(context);
3718 return m_requiredQueueFlags;
3719 }
3720
build(OperationContext & context,Resource & resource) const3721 de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
3722 {
3723 if (m_mode == ACCESS_MODE_READ)
3724 return de::MovePtr<Operation>(new ReadImplementation(context, resource));
3725 else
3726 return de::MovePtr<Operation>(new WriteImplementation(context, resource));
3727 }
3728
build(OperationContext &,Resource &,Resource &) const3729 de::MovePtr<Operation> build (OperationContext&, Resource&, Resource&) const
3730 {
3731 DE_ASSERT(0);
3732 return de::MovePtr<Operation>();
3733 }
3734
3735 private:
3736 const AccessMode m_mode;
3737 const VkQueueFlags m_requiredQueueFlags;
3738 };
3739
3740 } // CopyImageToBuffer ns
3741
3742 namespace ClearImage
3743 {
3744
3745 enum ClearMode
3746 {
3747 CLEAR_MODE_COLOR,
3748 CLEAR_MODE_DEPTH_STENCIL,
3749 };
3750
3751 class Implementation : public Operation
3752 {
3753 public:
Implementation(OperationContext & context,Resource & resource,const ClearMode mode)3754 Implementation (OperationContext& context, Resource& resource, const ClearMode mode)
3755 : m_context (context)
3756 , m_resource (resource)
3757 , m_clearValue (makeClearValue(m_resource.getImage().format))
3758 , m_mode (mode)
3759 {
3760 const VkDeviceSize size = getPixelBufferSize(m_resource.getImage().format, m_resource.getImage().extent);
3761 const VkExtent3D& extent = m_resource.getImage().extent;
3762 const VkFormat format = m_resource.getImage().format;
3763 const tcu::TextureFormat texFormat = mapVkFormat(format);
3764
3765 m_data.resize(static_cast<std::size_t>(size));
3766 tcu::PixelBufferAccess imagePixels(texFormat, extent.width, extent.height, extent.depth, &m_data[0]);
3767 clearPixelBuffer(imagePixels, m_clearValue);
3768 }
3769
recordCommands(const VkCommandBuffer cmdBuffer)3770 void recordCommands (const VkCommandBuffer cmdBuffer)
3771 {
3772 const DeviceInterface& vk = m_context.getDeviceInterface();
3773 SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
3774
3775 VkPipelineStageFlags2KHR dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR;
3776 if (m_context.getSynchronizationType() == SynchronizationType::SYNCHRONIZATION2)
3777 dstStageMask = VK_PIPELINE_STAGE_2_CLEAR_BIT_KHR;
3778
3779 const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
3780 VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR, // VkPipelineStageFlags2KHR srcStageMask
3781 (VkAccessFlags)0, // VkAccessFlags2KHR srcAccessMask
3782 dstStageMask, // VkPipelineStageFlags2KHR dstStageMask
3783 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR, // VkAccessFlags2KHR dstAccessMask
3784 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout
3785 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout
3786 m_resource.getImage().handle, // VkImage image
3787 m_resource.getImage().subresourceRange // VkImageSubresourceRange subresourceRange
3788 );
3789 VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
3790 synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
3791
3792 if (m_mode == CLEAR_MODE_COLOR)
3793 vk.cmdClearColorImage(cmdBuffer, m_resource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &m_clearValue.color, 1u, &m_resource.getImage().subresourceRange);
3794 else
3795 vk.cmdClearDepthStencilImage(cmdBuffer, m_resource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &m_clearValue.depthStencil, 1u, &m_resource.getImage().subresourceRange);
3796 }
3797
getInSyncInfo(void) const3798 SyncInfo getInSyncInfo (void) const
3799 {
3800 return emptySyncInfo;
3801 }
3802
getOutSyncInfo(void) const3803 SyncInfo getOutSyncInfo (void) const
3804 {
3805 VkPipelineStageFlags2KHR stageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR;
3806 if (m_context.getSynchronizationType() == SynchronizationType::SYNCHRONIZATION2)
3807 stageMask = VK_PIPELINE_STAGE_2_CLEAR_BIT_KHR;
3808
3809 return
3810 {
3811 stageMask, // VkPipelineStageFlags stageMask;
3812 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR, // VkAccessFlags accessMask;
3813 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout imageLayout;
3814 };
3815 }
3816
getData(void) const3817 Data getData (void) const
3818 {
3819 const Data data =
3820 {
3821 m_data.size(), // std::size_t size;
3822 &m_data[0], // const deUint8* data;
3823 };
3824 return data;
3825 }
3826
setData(const Data &)3827 void setData (const Data&)
3828 {
3829 DE_ASSERT(0);
3830 }
3831
3832 private:
3833 OperationContext& m_context;
3834 Resource& m_resource;
3835 std::vector<deUint8> m_data;
3836 const VkClearValue m_clearValue;
3837 const ClearMode m_mode;
3838 };
3839
3840 class Support : public OperationSupport
3841 {
3842 public:
Support(const ResourceDescription & resourceDesc,const ClearMode mode)3843 Support (const ResourceDescription& resourceDesc, const ClearMode mode)
3844 : m_resourceDesc (resourceDesc)
3845 , m_mode (mode)
3846 {
3847 DE_ASSERT(m_mode == CLEAR_MODE_COLOR || m_mode == CLEAR_MODE_DEPTH_STENCIL);
3848 DE_ASSERT(m_resourceDesc.type == RESOURCE_TYPE_IMAGE);
3849 DE_ASSERT(m_resourceDesc.imageAspect == VK_IMAGE_ASPECT_COLOR_BIT || (m_mode != CLEAR_MODE_COLOR));
3850 DE_ASSERT((m_resourceDesc.imageAspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) || (m_mode != CLEAR_MODE_DEPTH_STENCIL));
3851 }
3852
getInResourceUsageFlags(void) const3853 deUint32 getInResourceUsageFlags (void) const
3854 {
3855 return 0;
3856 }
3857
getOutResourceUsageFlags(void) const3858 deUint32 getOutResourceUsageFlags (void) const
3859 {
3860 return VK_IMAGE_USAGE_TRANSFER_DST_BIT;
3861 }
3862
getQueueFlags(const OperationContext & context) const3863 VkQueueFlags getQueueFlags (const OperationContext& context) const
3864 {
3865 DE_UNREF(context);
3866 if (m_mode == CLEAR_MODE_COLOR)
3867 return VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT;
3868 else
3869 return VK_QUEUE_GRAPHICS_BIT;
3870 }
3871
build(OperationContext & context,Resource & resource) const3872 de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
3873 {
3874 return de::MovePtr<Operation>(new Implementation(context, resource, m_mode));
3875 }
3876
build(OperationContext &,Resource &,Resource &) const3877 de::MovePtr<Operation> build (OperationContext&, Resource&, Resource&) const
3878 {
3879 DE_ASSERT(0);
3880 return de::MovePtr<Operation>();
3881 }
3882
3883 private:
3884 const ResourceDescription m_resourceDesc;
3885 const ClearMode m_mode;
3886 };
3887
3888 } // ClearImage ns
3889
3890 namespace Draw
3891 {
3892
3893 enum DrawCall
3894 {
3895 DRAW_CALL_DRAW,
3896 DRAW_CALL_DRAW_INDEXED,
3897 DRAW_CALL_DRAW_INDIRECT,
3898 DRAW_CALL_DRAW_INDEXED_INDIRECT,
3899 };
3900
3901 //! A write operation that is a result of drawing to an image.
3902 //! \todo Add support for depth/stencil too?
3903 class Implementation : public Operation
3904 {
3905 public:
Implementation(OperationContext & context,Resource & resource,const DrawCall drawCall)3906 Implementation (OperationContext& context, Resource& resource, const DrawCall drawCall)
3907 : m_context (context)
3908 , m_resource (resource)
3909 , m_drawCall (drawCall)
3910 , m_vertices (context)
3911 {
3912 const DeviceInterface& vk = context.getDeviceInterface();
3913 const VkDevice device = context.getDevice();
3914 Allocator& allocator = context.getAllocator();
3915
3916 // Indirect buffer
3917
3918 if (m_drawCall == DRAW_CALL_DRAW_INDIRECT)
3919 {
3920 m_indirectBuffer = de::MovePtr<Buffer>(new Buffer(vk, device, allocator,
3921 makeBufferCreateInfo(sizeof(VkDrawIndirectCommand), VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT), MemoryRequirement::HostVisible));
3922
3923 const Allocation& alloc = m_indirectBuffer->getAllocation();
3924 VkDrawIndirectCommand* const pIndirectCommand = static_cast<VkDrawIndirectCommand*>(alloc.getHostPtr());
3925
3926 pIndirectCommand->vertexCount = m_vertices.getNumVertices();
3927 pIndirectCommand->instanceCount = 1u;
3928 pIndirectCommand->firstVertex = 0u;
3929 pIndirectCommand->firstInstance = 0u;
3930
3931 flushAlloc(vk, device, alloc);
3932 }
3933 else if (m_drawCall == DRAW_CALL_DRAW_INDEXED_INDIRECT)
3934 {
3935 m_indirectBuffer = de::MovePtr<Buffer>(new Buffer(vk, device, allocator,
3936 makeBufferCreateInfo(sizeof(VkDrawIndexedIndirectCommand), VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT), MemoryRequirement::HostVisible));
3937
3938 const Allocation& alloc = m_indirectBuffer->getAllocation();
3939 VkDrawIndexedIndirectCommand* const pIndirectCommand = static_cast<VkDrawIndexedIndirectCommand*>(alloc.getHostPtr());
3940
3941 pIndirectCommand->indexCount = m_vertices.getNumIndices();
3942 pIndirectCommand->instanceCount = 1u;
3943 pIndirectCommand->firstIndex = 0u;
3944 pIndirectCommand->vertexOffset = 0u;
3945 pIndirectCommand->firstInstance = 0u;
3946
3947 flushAlloc(vk, device, alloc);
3948 }
3949
3950 // Resource image is the color attachment
3951
3952 m_colorFormat = m_resource.getImage().format;
3953 m_colorSubresourceRange = m_resource.getImage().subresourceRange;
3954 m_colorImage = m_resource.getImage().handle;
3955 m_attachmentExtent = m_resource.getImage().extent;
3956
3957 // Pipeline
3958
3959 m_colorAttachmentView = makeImageView (vk, device, m_colorImage, VK_IMAGE_VIEW_TYPE_2D, m_colorFormat, m_colorSubresourceRange);
3960 m_renderPass = makeRenderPass (vk, device, m_colorFormat);
3961 m_framebuffer = makeFramebuffer (vk, device, *m_renderPass, *m_colorAttachmentView, m_attachmentExtent.width, m_attachmentExtent.height);
3962 m_pipelineLayout = makePipelineLayout(vk, device);
3963
3964 GraphicsPipelineBuilder pipelineBuilder;
3965 pipelineBuilder
3966 .setRenderSize (tcu::IVec2(m_attachmentExtent.width, m_attachmentExtent.height))
3967 .setVertexInputSingleAttribute (m_vertices.getVertexFormat(), m_vertices.getVertexStride())
3968 .setShader (vk, device, VK_SHADER_STAGE_VERTEX_BIT, context.getBinaryCollection().get("draw_vert"), DE_NULL)
3969 .setShader (vk, device, VK_SHADER_STAGE_FRAGMENT_BIT, context.getBinaryCollection().get("draw_frag"), DE_NULL);
3970
3971 m_pipeline = pipelineBuilder.build(vk, device, *m_pipelineLayout, *m_renderPass, context.getPipelineCacheData(), context.getResourceInterface() );
3972
3973 // Set expected draw values
3974
3975 m_expectedData.resize(static_cast<size_t>(getPixelBufferSize(m_resource.getImage().format, m_resource.getImage().extent)));
3976 tcu::PixelBufferAccess imagePixels(mapVkFormat(m_colorFormat), m_attachmentExtent.width, m_attachmentExtent.height, m_attachmentExtent.depth, &m_expectedData[0]);
3977 clearPixelBuffer(imagePixels, makeClearValue(m_colorFormat));
3978 }
3979
recordCommands(const VkCommandBuffer cmdBuffer)3980 void recordCommands (const VkCommandBuffer cmdBuffer)
3981 {
3982 const DeviceInterface& vk = m_context.getDeviceInterface();
3983 SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
3984
3985 // Change color attachment image layout
3986 {
3987 const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
3988 VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR, // VkPipelineStageFlags2KHR srcStageMask
3989 (VkAccessFlags)0, // VkAccessFlags2KHR srcAccessMask
3990 VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR, // VkPipelineStageFlags2KHR dstStageMask
3991 VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR, // VkAccessFlags2KHR dstAccessMask
3992 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout
3993 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout
3994 m_colorImage, // VkImage image
3995 m_colorSubresourceRange // VkImageSubresourceRange subresourceRange
3996 );
3997 VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
3998 synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
3999 }
4000
4001 {
4002 const VkRect2D renderArea = makeRect2D(m_attachmentExtent);
4003 const tcu::Vec4 clearColor = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
4004
4005 beginRenderPass(vk, cmdBuffer, *m_renderPass, *m_framebuffer, renderArea, clearColor);
4006 }
4007
4008 vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
4009 {
4010 const VkDeviceSize vertexBufferOffset = 0ull;
4011 const VkBuffer vertexBuffer = m_vertices.getVertexBuffer();
4012 vk.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer, &vertexBufferOffset);
4013 }
4014
4015 if (m_drawCall == DRAW_CALL_DRAW_INDEXED || m_drawCall == DRAW_CALL_DRAW_INDEXED_INDIRECT)
4016 vk.cmdBindIndexBuffer(cmdBuffer, m_vertices.getIndexBuffer(), 0u, m_vertices.getIndexType());
4017
4018 switch (m_drawCall)
4019 {
4020 case DRAW_CALL_DRAW:
4021 vk.cmdDraw(cmdBuffer, m_vertices.getNumVertices(), 1u, 0u, 0u);
4022 break;
4023
4024 case DRAW_CALL_DRAW_INDEXED:
4025 vk.cmdDrawIndexed(cmdBuffer, m_vertices.getNumIndices(), 1u, 0u, 0, 0u);
4026 break;
4027
4028 case DRAW_CALL_DRAW_INDIRECT:
4029 vk.cmdDrawIndirect(cmdBuffer, **m_indirectBuffer, 0u, 1u, 0u);
4030 break;
4031
4032 case DRAW_CALL_DRAW_INDEXED_INDIRECT:
4033 vk.cmdDrawIndexedIndirect(cmdBuffer, **m_indirectBuffer, 0u, 1u, 0u);
4034 break;
4035 }
4036
4037 endRenderPass(vk, cmdBuffer);
4038 }
4039
getInSyncInfo(void) const4040 SyncInfo getInSyncInfo (void) const
4041 {
4042 return emptySyncInfo;
4043 }
4044
getOutSyncInfo(void) const4045 SyncInfo getOutSyncInfo (void) const
4046 {
4047 const SyncInfo syncInfo =
4048 {
4049 VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR, // VkPipelineStageFlags stageMask;
4050 VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR, // VkAccessFlags accessMask;
4051 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout imageLayout;
4052 };
4053 return syncInfo;
4054 }
4055
getData(void) const4056 Data getData (void) const
4057 {
4058 const Data data =
4059 {
4060 m_expectedData.size(), // std::size_t size;
4061 &m_expectedData[0], // const deUint8* data;
4062 };
4063 return data;
4064 }
4065
setData(const Data & data)4066 void setData (const Data& data)
4067 {
4068 DE_ASSERT(m_expectedData.size() == data.size);
4069 deMemcpy(&m_expectedData[0], data.data, data.size);
4070 }
4071
4072 private:
4073 OperationContext& m_context;
4074 Resource& m_resource;
4075 const DrawCall m_drawCall;
4076 const VertexGrid m_vertices;
4077 std::vector<deUint8> m_expectedData;
4078 de::MovePtr<Buffer> m_indirectBuffer;
4079 VkFormat m_colorFormat;
4080 VkImage m_colorImage;
4081 Move<VkImageView> m_colorAttachmentView;
4082 VkImageSubresourceRange m_colorSubresourceRange;
4083 VkExtent3D m_attachmentExtent;
4084 Move<VkRenderPass> m_renderPass;
4085 Move<VkFramebuffer> m_framebuffer;
4086 Move<VkPipelineLayout> m_pipelineLayout;
4087 Move<VkPipeline> m_pipeline;
4088 };
4089
4090 template<typename T, std::size_t N>
toString(const T (& values)[N])4091 std::string toString (const T (&values)[N])
4092 {
4093 std::ostringstream str;
4094 for (std::size_t i = 0; i < N; ++i)
4095 str << (i != 0 ? ", " : "") << values[i];
4096 return str.str();
4097 }
4098
4099 class Support : public OperationSupport
4100 {
4101 public:
Support(const ResourceDescription & resourceDesc,const DrawCall drawCall)4102 Support (const ResourceDescription& resourceDesc, const DrawCall drawCall)
4103 : m_resourceDesc (resourceDesc)
4104 , m_drawCall (drawCall)
4105 {
4106 DE_ASSERT(m_resourceDesc.type == RESOURCE_TYPE_IMAGE && m_resourceDesc.imageType == VK_IMAGE_TYPE_2D);
4107 DE_ASSERT(!isDepthStencilFormat(m_resourceDesc.imageFormat));
4108 }
4109
initPrograms(SourceCollections & programCollection) const4110 void initPrograms (SourceCollections& programCollection) const
4111 {
4112 // Vertex
4113 {
4114 std::ostringstream src;
4115 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
4116 << "\n"
4117 << "layout(location = 0) in vec4 v_in_position;\n"
4118 << "\n"
4119 << "out " << s_perVertexBlock << ";\n"
4120 << "\n"
4121 << "void main (void)\n"
4122 << "{\n"
4123 << " gl_Position = v_in_position;\n"
4124 << "}\n";
4125
4126 programCollection.glslSources.add("draw_vert") << glu::VertexSource(src.str());
4127 }
4128
4129 // Fragment
4130 {
4131 const VkClearValue clearValue = makeClearValue(m_resourceDesc.imageFormat);
4132 const bool isIntegerFormat = isIntFormat(m_resourceDesc.imageFormat) || isUintFormat(m_resourceDesc.imageFormat);
4133 const std::string colorType = (isIntegerFormat ? "uvec4" : "vec4");
4134
4135 std::ostringstream src;
4136 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
4137 << "\n"
4138 << "layout(location = 0) out " << colorType << " o_color;\n"
4139 << "\n"
4140 << "void main (void)\n"
4141 << "{\n"
4142 << " o_color = " << colorType << "(" << (isIntegerFormat ? toString(clearValue.color.uint32) : toString(clearValue.color.float32)) << ");\n"
4143 << "}\n";
4144
4145 programCollection.glslSources.add("draw_frag") << glu::FragmentSource(src.str());
4146 }
4147 }
4148
getInResourceUsageFlags(void) const4149 deUint32 getInResourceUsageFlags (void) const
4150 {
4151 return 0;
4152 }
4153
getOutResourceUsageFlags(void) const4154 deUint32 getOutResourceUsageFlags (void) const
4155 {
4156 return VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
4157 }
4158
getQueueFlags(const OperationContext & context) const4159 VkQueueFlags getQueueFlags (const OperationContext& context) const
4160 {
4161 DE_UNREF(context);
4162 return VK_QUEUE_GRAPHICS_BIT;
4163 }
4164
build(OperationContext & context,Resource & resource) const4165 de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
4166 {
4167 return de::MovePtr<Operation>(new Implementation(context, resource, m_drawCall));
4168 }
4169
build(OperationContext &,Resource &,Resource &) const4170 de::MovePtr<Operation> build (OperationContext&, Resource&, Resource&) const
4171 {
4172 DE_ASSERT(0);
4173 return de::MovePtr<Operation>();
4174 }
4175
4176 private:
4177 const ResourceDescription m_resourceDesc;
4178 const DrawCall m_drawCall;
4179 };
4180
4181 } // Draw ns
4182
4183 namespace ClearAttachments
4184 {
4185
4186 class Implementation : public Operation
4187 {
4188 public:
Implementation(OperationContext & context,Resource & resource)4189 Implementation (OperationContext& context, Resource& resource)
4190 : m_context (context)
4191 , m_resource (resource)
4192 , m_clearValue (makeClearValue(m_resource.getImage().format))
4193 {
4194 const DeviceInterface& vk = context.getDeviceInterface();
4195 const VkDevice device = context.getDevice();
4196
4197 const VkDeviceSize size = getPixelBufferSize(m_resource.getImage().format, m_resource.getImage().extent);
4198 const VkExtent3D& extent = m_resource.getImage().extent;
4199 const VkFormat format = m_resource.getImage().format;
4200 const tcu::TextureFormat texFormat = mapVkFormat(format);
4201 const SyncInfo syncInfo = getOutSyncInfo();
4202
4203 m_data.resize(static_cast<std::size_t>(size));
4204 tcu::PixelBufferAccess imagePixels(texFormat, extent.width, extent.height, extent.depth, &m_data[0]);
4205 clearPixelBuffer(imagePixels, m_clearValue);
4206
4207 m_attachmentView = makeImageView(vk, device, m_resource.getImage().handle, getImageViewType(m_resource.getImage().imageType), m_resource.getImage().format, m_resource.getImage().subresourceRange);
4208
4209 switch (m_resource.getImage().subresourceRange.aspectMask)
4210 {
4211 case VK_IMAGE_ASPECT_COLOR_BIT:
4212 m_renderPass = makeRenderPass(vk, device, m_resource.getImage().format, VK_FORMAT_UNDEFINED, VK_ATTACHMENT_LOAD_OP_DONT_CARE, syncInfo.imageLayout);
4213 break;
4214 case VK_IMAGE_ASPECT_STENCIL_BIT:
4215 case VK_IMAGE_ASPECT_DEPTH_BIT:
4216 m_renderPass = makeRenderPass(vk, device, VK_FORMAT_UNDEFINED, m_resource.getImage().format, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, syncInfo.imageLayout);
4217 break;
4218 default:
4219 DE_ASSERT(0);
4220 break;
4221 }
4222
4223 m_frameBuffer = makeFramebuffer(vk, device, *m_renderPass, *m_attachmentView, m_resource.getImage().extent.width, m_resource.getImage().extent.height);
4224 }
4225
recordCommands(const VkCommandBuffer cmdBuffer)4226 void recordCommands (const VkCommandBuffer cmdBuffer)
4227 {
4228 const DeviceInterface& vk = m_context.getDeviceInterface();
4229 if ((m_resource.getImage().subresourceRange.aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) != 0)
4230 {
4231 const VkImageMemoryBarrier imageBarrier =
4232 {
4233 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
4234 DE_NULL, // pNext
4235 0u, // srcAccessMask
4236 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, // dstAccessMask
4237 VK_IMAGE_LAYOUT_UNDEFINED, // oldLayout
4238 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // newLayout
4239 VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex
4240 VK_QUEUE_FAMILY_IGNORED, // dstQueueFamilyIndex
4241 m_resource.getImage().handle, // image
4242 m_resource.getImage().subresourceRange // subresourceRange
4243 };
4244 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &imageBarrier);
4245 }
4246 beginRenderPass(vk, cmdBuffer, *m_renderPass, *m_frameBuffer, makeRect2D(0 ,0, m_resource.getImage().extent.width, m_resource.getImage().extent.height), m_clearValue);
4247
4248 const VkClearAttachment clearAttachment =
4249 {
4250 m_resource.getImage().subresourceRange.aspectMask, // VkImageAspectFlags aspectMask;
4251 0, // deUint32 colorAttachment;
4252 m_clearValue // VkClearValue clearValue;
4253 };
4254
4255 const VkRect2D rect2D = makeRect2D(m_resource.getImage().extent);
4256
4257 const VkClearRect clearRect =
4258 {
4259 rect2D, // VkRect2D rect;
4260 0u, // deUint32 baseArrayLayer;
4261 m_resource.getImage().subresourceLayers.layerCount // deUint32 layerCount;
4262 };
4263
4264 vk.cmdClearAttachments(cmdBuffer, 1, &clearAttachment, 1, &clearRect);
4265
4266 endRenderPass(vk, cmdBuffer);
4267 }
4268
getInSyncInfo(void) const4269 SyncInfo getInSyncInfo (void) const
4270 {
4271 return emptySyncInfo;
4272 }
4273
getOutSyncInfo(void) const4274 SyncInfo getOutSyncInfo (void) const
4275 {
4276 SyncInfo syncInfo;
4277 syncInfo.stageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT_KHR;
4278
4279 switch (m_resource.getImage().subresourceRange.aspectMask)
4280 {
4281 case VK_IMAGE_ASPECT_COLOR_BIT:
4282 syncInfo.accessMask = VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR;
4283 syncInfo.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
4284 break;
4285 case VK_IMAGE_ASPECT_STENCIL_BIT:
4286 case VK_IMAGE_ASPECT_DEPTH_BIT:
4287 syncInfo.accessMask = VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT_KHR;
4288 syncInfo.imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
4289 break;
4290 default:
4291 DE_ASSERT(0);
4292 break;
4293 }
4294
4295 return syncInfo;
4296 }
4297
getData(void) const4298 Data getData (void) const
4299 {
4300 const Data data =
4301 {
4302 m_data.size(), // std::size_t size;
4303 &m_data[0], // const deUint8* data;
4304 };
4305 return data;
4306 }
4307
setData(const Data &)4308 void setData (const Data&)
4309 {
4310 DE_ASSERT(0);
4311 }
4312
4313 private:
4314 OperationContext& m_context;
4315 Resource& m_resource;
4316 std::vector<deUint8> m_data;
4317 const VkClearValue m_clearValue;
4318 Move<VkImageView> m_attachmentView;
4319 Move<VkRenderPass> m_renderPass;
4320 Move<VkFramebuffer> m_frameBuffer;
4321 };
4322
4323 class Support : public OperationSupport
4324 {
4325 public:
Support(const ResourceDescription & resourceDesc)4326 Support (const ResourceDescription& resourceDesc)
4327 : m_resourceDesc (resourceDesc)
4328 {
4329 DE_ASSERT(m_resourceDesc.type == RESOURCE_TYPE_IMAGE);
4330 }
4331
getInResourceUsageFlags(void) const4332 deUint32 getInResourceUsageFlags (void) const
4333 {
4334 return 0;
4335 }
4336
getOutResourceUsageFlags(void) const4337 deUint32 getOutResourceUsageFlags (void) const
4338 {
4339 switch (m_resourceDesc.imageAspect)
4340 {
4341 case VK_IMAGE_ASPECT_COLOR_BIT:
4342 return VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
4343 case VK_IMAGE_ASPECT_STENCIL_BIT:
4344 case VK_IMAGE_ASPECT_DEPTH_BIT:
4345 return VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
4346 default:
4347 DE_ASSERT(0);
4348 }
4349 return 0u;
4350 }
4351
getQueueFlags(const OperationContext & context) const4352 VkQueueFlags getQueueFlags (const OperationContext& context) const
4353 {
4354 DE_UNREF(context);
4355 return VK_QUEUE_GRAPHICS_BIT;
4356 }
4357
build(OperationContext & context,Resource & resource) const4358 de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
4359 {
4360 return de::MovePtr<Operation>(new Implementation(context, resource));
4361 }
4362
build(OperationContext &,Resource &,Resource &) const4363 de::MovePtr<Operation> build (OperationContext&, Resource&, Resource&) const
4364 {
4365 DE_ASSERT(0);
4366 return de::MovePtr<Operation>();
4367 }
4368
4369 private:
4370 const ResourceDescription m_resourceDesc;
4371 };
4372
4373 } // ClearAttachments
4374
4375 namespace IndirectBuffer
4376 {
4377
4378 class GraphicsPipeline : public Pipeline
4379 {
4380 public:
GraphicsPipeline(OperationContext & context,const ResourceType resourceType,const VkBuffer indirectBuffer,const std::string & shaderPrefix,const VkDescriptorSetLayout descriptorSetLayout)4381 GraphicsPipeline (OperationContext& context,
4382 const ResourceType resourceType,
4383 const VkBuffer indirectBuffer,
4384 const std::string& shaderPrefix,
4385 const VkDescriptorSetLayout descriptorSetLayout)
4386 : m_resourceType (resourceType)
4387 , m_indirectBuffer (indirectBuffer)
4388 , m_vertices (context)
4389 {
4390 const DeviceInterface& vk = context.getDeviceInterface();
4391 const VkDevice device = context.getDevice();
4392 Allocator& allocator = context.getAllocator();
4393
4394 // Color attachment
4395
4396 m_colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
4397 m_colorImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
4398 m_colorImageExtent = makeExtent3D(16u, 16u, 1u);
4399 m_colorAttachmentImage = de::MovePtr<Image>(new Image(vk, device, allocator,
4400 makeImageCreateInfo(VK_IMAGE_TYPE_2D, m_colorImageExtent, m_colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
4401 VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL),
4402 MemoryRequirement::Any));
4403
4404 // Pipeline
4405
4406 m_colorAttachmentView = makeImageView (vk, device, **m_colorAttachmentImage, VK_IMAGE_VIEW_TYPE_2D, m_colorFormat, m_colorImageSubresourceRange);
4407 m_renderPass = makeRenderPass (vk, device, m_colorFormat);
4408 m_framebuffer = makeFramebuffer (vk, device, *m_renderPass, *m_colorAttachmentView, m_colorImageExtent.width, m_colorImageExtent.height);
4409 m_pipelineLayout = makePipelineLayout(vk, device, descriptorSetLayout);
4410
4411 GraphicsPipelineBuilder pipelineBuilder;
4412 pipelineBuilder
4413 .setRenderSize (tcu::IVec2(m_colorImageExtent.width, m_colorImageExtent.height))
4414 .setVertexInputSingleAttribute (m_vertices.getVertexFormat(), m_vertices.getVertexStride())
4415 .setShader (vk, device, VK_SHADER_STAGE_VERTEX_BIT, context.getBinaryCollection().get(shaderPrefix + "vert"), DE_NULL)
4416 .setShader (vk, device, VK_SHADER_STAGE_FRAGMENT_BIT, context.getBinaryCollection().get(shaderPrefix + "frag"), DE_NULL);
4417
4418 m_pipeline = pipelineBuilder.build(vk, device, *m_pipelineLayout, *m_renderPass, context.getPipelineCacheData(), context.getResourceInterface());
4419 }
4420
recordCommands(OperationContext & context,const VkCommandBuffer cmdBuffer,const VkDescriptorSet descriptorSet)4421 void recordCommands (OperationContext& context, const VkCommandBuffer cmdBuffer, const VkDescriptorSet descriptorSet)
4422 {
4423 const DeviceInterface& vk = context.getDeviceInterface();
4424 SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(context.getSynchronizationType(), vk, DE_FALSE);
4425
4426 // Change color attachment image layout
4427 {
4428 const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
4429 VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR, // VkPipelineStageFlags2KHR srcStageMask
4430 (VkAccessFlags)0, // VkAccessFlags2KHR srcAccessMask
4431 VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR, // VkPipelineStageFlags2KHR dstStageMask
4432 VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR, // VkAccessFlags2KHR dstAccessMask
4433 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout
4434 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout
4435 **m_colorAttachmentImage, // VkImage image
4436 m_colorImageSubresourceRange // VkImageSubresourceRange subresourceRange
4437 );
4438 VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
4439 synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
4440 }
4441
4442 {
4443 const VkRect2D renderArea = makeRect2D(m_colorImageExtent);
4444 const tcu::Vec4 clearColor = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
4445
4446 beginRenderPass(vk, cmdBuffer, *m_renderPass, *m_framebuffer, renderArea, clearColor);
4447 }
4448
4449 vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
4450 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
4451 {
4452 const VkDeviceSize vertexBufferOffset = 0ull;
4453 const VkBuffer vertexBuffer = m_vertices.getVertexBuffer();
4454 vk.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer, &vertexBufferOffset);
4455 }
4456
4457 switch (m_resourceType)
4458 {
4459 case RESOURCE_TYPE_INDIRECT_BUFFER_DRAW:
4460 vk.cmdDrawIndirect(cmdBuffer, m_indirectBuffer, 0u, 1u, 0u);
4461 break;
4462
4463 case RESOURCE_TYPE_INDIRECT_BUFFER_DRAW_INDEXED:
4464 vk.cmdBindIndexBuffer(cmdBuffer, m_vertices.getIndexBuffer(), 0u, m_vertices.getIndexType());
4465 vk.cmdDrawIndexedIndirect(cmdBuffer, m_indirectBuffer, 0u, 1u, 0u);
4466 break;
4467
4468 default:
4469 DE_ASSERT(0);
4470 break;
4471 }
4472 endRenderPass(vk, cmdBuffer);
4473 }
4474
4475 private:
4476 const ResourceType m_resourceType;
4477 const VkBuffer m_indirectBuffer;
4478 const VertexGrid m_vertices;
4479 VkFormat m_colorFormat;
4480 de::MovePtr<Image> m_colorAttachmentImage;
4481 Move<VkImageView> m_colorAttachmentView;
4482 VkExtent3D m_colorImageExtent;
4483 VkImageSubresourceRange m_colorImageSubresourceRange;
4484 Move<VkRenderPass> m_renderPass;
4485 Move<VkFramebuffer> m_framebuffer;
4486 Move<VkPipelineLayout> m_pipelineLayout;
4487 Move<VkPipeline> m_pipeline;
4488 };
4489
4490 class ComputePipeline : public Pipeline
4491 {
4492 public:
ComputePipeline(OperationContext & context,const VkBuffer indirectBuffer,const std::string & shaderPrefix,const VkDescriptorSetLayout descriptorSetLayout)4493 ComputePipeline (OperationContext& context,
4494 const VkBuffer indirectBuffer,
4495 const std::string& shaderPrefix,
4496 const VkDescriptorSetLayout descriptorSetLayout)
4497 : m_indirectBuffer (indirectBuffer)
4498 {
4499 const DeviceInterface& vk = context.getDeviceInterface();
4500 const VkDevice device = context.getDevice();
4501
4502 const Unique<VkShaderModule> shaderModule(createShaderModule(vk, device, context.getBinaryCollection().get(shaderPrefix + "comp"), (VkShaderModuleCreateFlags)0));
4503
4504 m_pipelineLayout = makePipelineLayout(vk, device, descriptorSetLayout);
4505 m_pipeline = makeComputePipeline(vk, device, *m_pipelineLayout, *shaderModule, DE_NULL, context.getPipelineCacheData(), context.getResourceInterface());
4506 }
4507
recordCommands(OperationContext & context,const VkCommandBuffer cmdBuffer,const VkDescriptorSet descriptorSet)4508 void recordCommands (OperationContext& context, const VkCommandBuffer cmdBuffer, const VkDescriptorSet descriptorSet)
4509 {
4510 const DeviceInterface& vk = context.getDeviceInterface();
4511
4512 vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipeline);
4513 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
4514 vk.cmdDispatchIndirect(cmdBuffer, m_indirectBuffer, 0u);
4515 }
4516
4517 private:
4518 const VkBuffer m_indirectBuffer;
4519 Move<VkPipelineLayout> m_pipelineLayout;
4520 Move<VkPipeline> m_pipeline;
4521 };
4522
4523 //! Read indirect buffer by executing an indirect draw or dispatch command.
4524 class ReadImplementation : public Operation
4525 {
4526 public:
ReadImplementation(OperationContext & context,Resource & resource)4527 ReadImplementation (OperationContext& context, Resource& resource)
4528 : m_context (context)
4529 , m_resource (resource)
4530 , m_stage (resource.getType() == RESOURCE_TYPE_INDIRECT_BUFFER_DISPATCH ? VK_SHADER_STAGE_COMPUTE_BIT : VK_SHADER_STAGE_VERTEX_BIT)
4531 , m_pipelineStage (pipelineStageFlagsFromShaderStageFlagBits(m_stage))
4532 , m_hostBufferSizeBytes (sizeof(deUint32))
4533 {
4534 requireFeaturesForSSBOAccess (m_context, m_stage);
4535
4536 const DeviceInterface& vk = m_context.getDeviceInterface();
4537 const VkDevice device = m_context.getDevice();
4538 Allocator& allocator = m_context.getAllocator();
4539
4540 m_hostBuffer = de::MovePtr<Buffer>(new Buffer(
4541 vk, device, allocator, makeBufferCreateInfo(m_hostBufferSizeBytes, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), MemoryRequirement::HostVisible));
4542
4543 // Init host buffer data
4544 {
4545 const Allocation& alloc = m_hostBuffer->getAllocation();
4546 deMemset(alloc.getHostPtr(), 0, static_cast<size_t>(m_hostBufferSizeBytes));
4547 flushAlloc(vk, device, alloc);
4548 }
4549
4550 // Prepare descriptors
4551 {
4552 m_descriptorSetLayout = DescriptorSetLayoutBuilder()
4553 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, m_stage)
4554 .build(vk, device);
4555
4556 m_descriptorPool = DescriptorPoolBuilder()
4557 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
4558 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
4559
4560 m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
4561
4562 const VkDescriptorBufferInfo hostBufferInfo = makeDescriptorBufferInfo(**m_hostBuffer, 0u, m_hostBufferSizeBytes);
4563
4564 DescriptorSetUpdateBuilder()
4565 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &hostBufferInfo)
4566 .update(vk, device);
4567 }
4568
4569 // Create pipeline
4570 m_pipeline = (m_resource.getType() == RESOURCE_TYPE_INDIRECT_BUFFER_DISPATCH
4571 ? de::MovePtr<Pipeline>(new ComputePipeline(context, m_resource.getBuffer().handle, "read_ib_", *m_descriptorSetLayout))
4572 : de::MovePtr<Pipeline>(new GraphicsPipeline(context, m_resource.getType(), m_resource.getBuffer().handle, "read_ib_", *m_descriptorSetLayout)));
4573 }
4574
recordCommands(const VkCommandBuffer cmdBuffer)4575 void recordCommands (const VkCommandBuffer cmdBuffer)
4576 {
4577 const DeviceInterface& vk = m_context.getDeviceInterface();
4578 SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
4579
4580 m_pipeline->recordCommands(m_context, cmdBuffer, *m_descriptorSet);
4581
4582 // Insert a barrier so data written by the shader is available to the host
4583 const VkBufferMemoryBarrier2KHR bufferMemoryBarrier2 = makeBufferMemoryBarrier2(
4584 m_pipelineStage, // VkPipelineStageFlags2KHR srcStageMask
4585 VK_ACCESS_2_SHADER_WRITE_BIT_KHR, // VkAccessFlags2KHR srcAccessMask
4586 VK_PIPELINE_STAGE_2_HOST_BIT_KHR, // VkPipelineStageFlags2KHR dstStageMask
4587 VK_ACCESS_2_HOST_READ_BIT_KHR, // VkAccessFlags2KHR dstAccessMask
4588 **m_hostBuffer, // VkBuffer buffer
4589 0u, // VkDeviceSize offset
4590 m_hostBufferSizeBytes // VkDeviceSize size
4591 );
4592 VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, &bufferMemoryBarrier2);
4593 synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
4594 }
4595
getInSyncInfo(void) const4596 SyncInfo getInSyncInfo (void) const
4597 {
4598 const SyncInfo syncInfo =
4599 {
4600 VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT_KHR, // VkPipelineStageFlags stageMask;
4601 VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT_KHR, // VkAccessFlags accessMask;
4602 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout imageLayout;
4603 };
4604 return syncInfo;
4605 }
4606
getOutSyncInfo(void) const4607 SyncInfo getOutSyncInfo (void) const
4608 {
4609 return emptySyncInfo;
4610 }
4611
getData(void) const4612 Data getData (void) const
4613 {
4614 return getHostBufferData(m_context, *m_hostBuffer, m_hostBufferSizeBytes);
4615 }
4616
setData(const Data &)4617 void setData (const Data&)
4618 {
4619 DE_ASSERT(0);
4620 }
4621
4622 private:
4623 OperationContext& m_context;
4624 Resource& m_resource;
4625 const VkShaderStageFlagBits m_stage;
4626 const VkPipelineStageFlags m_pipelineStage;
4627 const VkDeviceSize m_hostBufferSizeBytes;
4628 de::MovePtr<Buffer> m_hostBuffer;
4629 Move<VkDescriptorPool> m_descriptorPool;
4630 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
4631 Move<VkDescriptorSet> m_descriptorSet;
4632 de::MovePtr<Pipeline> m_pipeline;
4633 };
4634
4635 //! Prepare indirect buffer for a draw/dispatch call.
4636 class WriteImplementation : public Operation
4637 {
4638 public:
WriteImplementation(OperationContext & context,Resource & resource)4639 WriteImplementation (OperationContext& context, Resource& resource)
4640 : m_context (context)
4641 , m_resource (resource)
4642 {
4643 switch (m_resource.getType())
4644 {
4645 case RESOURCE_TYPE_INDIRECT_BUFFER_DRAW:
4646 {
4647 m_drawIndirect.vertexCount = 6u;
4648 m_drawIndirect.instanceCount = 1u;
4649 m_drawIndirect.firstVertex = 0u;
4650 m_drawIndirect.firstInstance = 0u;
4651
4652 m_indirectData = reinterpret_cast<deUint32*>(&m_drawIndirect);
4653 m_expectedValue = 6u;
4654 }
4655 break;
4656
4657 case RESOURCE_TYPE_INDIRECT_BUFFER_DRAW_INDEXED:
4658 {
4659 m_drawIndexedIndirect.indexCount = 6u;
4660 m_drawIndexedIndirect.instanceCount = 1u;
4661 m_drawIndexedIndirect.firstIndex = 0u;
4662 m_drawIndexedIndirect.vertexOffset = 0u;
4663 m_drawIndexedIndirect.firstInstance = 0u;
4664
4665 m_indirectData = reinterpret_cast<deUint32*>(&m_drawIndexedIndirect);
4666 m_expectedValue = 6u;
4667 }
4668 break;
4669
4670 case RESOURCE_TYPE_INDIRECT_BUFFER_DISPATCH:
4671 {
4672 m_dispatchIndirect.x = 7u;
4673 m_dispatchIndirect.y = 2u;
4674 m_dispatchIndirect.z = 1u;
4675
4676 m_indirectData = reinterpret_cast<deUint32*>(&m_dispatchIndirect);
4677 m_expectedValue = 14u;
4678 }
4679 break;
4680
4681 default:
4682 DE_ASSERT(0);
4683 break;
4684 }
4685 }
4686
recordCommands(const VkCommandBuffer cmdBuffer)4687 void recordCommands (const VkCommandBuffer cmdBuffer)
4688 {
4689 const DeviceInterface& vk = m_context.getDeviceInterface();
4690
4691 vk.cmdUpdateBuffer(cmdBuffer, m_resource.getBuffer().handle, m_resource.getBuffer().offset, m_resource.getBuffer().size, m_indirectData);
4692 }
4693
getInSyncInfo(void) const4694 SyncInfo getInSyncInfo (void) const
4695 {
4696 return emptySyncInfo;
4697 }
4698
getOutSyncInfo(void) const4699 SyncInfo getOutSyncInfo (void) const
4700 {
4701 const SyncInfo syncInfo =
4702 {
4703 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags stageMask;
4704 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR, // VkAccessFlags accessMask;
4705 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout imageLayout;
4706 };
4707 return syncInfo;
4708 }
4709
getData(void) const4710 Data getData (void) const
4711 {
4712 const Data data =
4713 {
4714 sizeof(deUint32), // std::size_t size;
4715 reinterpret_cast<const deUint8*>(&m_expectedValue), // const deUint8* data;
4716 };
4717 return data;
4718 }
4719
setData(const Data &)4720 void setData (const Data&)
4721 {
4722 DE_ASSERT(0);
4723 }
4724
4725 private:
4726 OperationContext& m_context;
4727 Resource& m_resource;
4728 VkDrawIndirectCommand m_drawIndirect;
4729 VkDrawIndexedIndirectCommand m_drawIndexedIndirect;
4730 VkDispatchIndirectCommand m_dispatchIndirect;
4731 deUint32* m_indirectData;
4732 deUint32 m_expectedValue; //! Side-effect value expected to be computed by a read (draw/dispatch) command.
4733 };
4734
4735 class ReadSupport : public OperationSupport
4736 {
4737 public:
ReadSupport(const ResourceDescription & resourceDesc)4738 ReadSupport (const ResourceDescription& resourceDesc)
4739 : m_resourceDesc (resourceDesc)
4740 {
4741 DE_ASSERT(isIndirectBuffer(m_resourceDesc.type));
4742 }
4743
initPrograms(SourceCollections & programCollection) const4744 void initPrograms (SourceCollections& programCollection) const
4745 {
4746 std::ostringstream decl;
4747 decl << "layout(set = 0, binding = 0, std140) coherent buffer Data {\n"
4748 << " uint value;\n"
4749 << "} sb_out;\n";
4750
4751 std::ostringstream main;
4752 main << " atomicAdd(sb_out.value, 1u);\n";
4753
4754 // Vertex
4755 {
4756 std::ostringstream src;
4757 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
4758 << "\n"
4759 << "layout(location = 0) in vec4 v_in_position;\n"
4760 << "\n"
4761 << "out " << s_perVertexBlock << ";\n"
4762 << "\n"
4763 << decl.str()
4764 << "\n"
4765 << "void main (void)\n"
4766 << "{\n"
4767 << " gl_Position = v_in_position;\n"
4768 << main.str()
4769 << "}\n";
4770
4771 programCollection.glslSources.add("read_ib_vert") << glu::VertexSource(src.str());
4772 }
4773
4774 // Fragment
4775 {
4776 std::ostringstream src;
4777 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
4778 << "\n"
4779 << "layout(location = 0) out vec4 o_color;\n"
4780 << "\n"
4781 << "void main (void)\n"
4782 << "{\n"
4783 << " o_color = vec4(1.0);\n"
4784 << "}\n";
4785
4786 programCollection.glslSources.add("read_ib_frag") << glu::FragmentSource(src.str());
4787 }
4788
4789 // Compute
4790 {
4791 std::ostringstream src;
4792 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
4793 << "\n"
4794 << "layout(local_size_x = 1) in;\n"
4795 << "\n"
4796 << decl.str()
4797 << "\n"
4798 << "void main (void)\n"
4799 << "{\n"
4800 << main.str()
4801 << "}\n";
4802
4803 programCollection.glslSources.add("read_ib_comp") << glu::ComputeSource(src.str());
4804 }
4805 }
4806
getInResourceUsageFlags(void) const4807 deUint32 getInResourceUsageFlags (void) const
4808 {
4809 return VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT;
4810 }
4811
getOutResourceUsageFlags(void) const4812 deUint32 getOutResourceUsageFlags (void) const
4813 {
4814 return 0;
4815 }
4816
getQueueFlags(const OperationContext & context) const4817 VkQueueFlags getQueueFlags (const OperationContext& context) const
4818 {
4819 DE_UNREF(context);
4820 return (m_resourceDesc.type == RESOURCE_TYPE_INDIRECT_BUFFER_DISPATCH ? VK_QUEUE_COMPUTE_BIT : VK_QUEUE_GRAPHICS_BIT);
4821 }
4822
build(OperationContext & context,Resource & resource) const4823 de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
4824 {
4825 return de::MovePtr<Operation>(new ReadImplementation(context, resource));
4826 }
4827
build(OperationContext &,Resource &,Resource &) const4828 de::MovePtr<Operation> build (OperationContext&, Resource&, Resource&) const
4829 {
4830 DE_ASSERT(0);
4831 return de::MovePtr<Operation>();
4832 }
4833
4834 private:
4835 const ResourceDescription m_resourceDesc;
4836 };
4837
4838
4839 class WriteSupport : public OperationSupport
4840 {
4841 public:
WriteSupport(const ResourceDescription & resourceDesc)4842 WriteSupport (const ResourceDescription& resourceDesc)
4843 {
4844 DE_ASSERT(isIndirectBuffer(resourceDesc.type));
4845 DE_UNREF(resourceDesc);
4846 }
4847
getInResourceUsageFlags(void) const4848 deUint32 getInResourceUsageFlags (void) const
4849 {
4850 return 0;
4851 }
4852
getOutResourceUsageFlags(void) const4853 deUint32 getOutResourceUsageFlags (void) const
4854 {
4855 return VK_BUFFER_USAGE_TRANSFER_DST_BIT;
4856 }
4857
getQueueFlags(const OperationContext & context) const4858 VkQueueFlags getQueueFlags (const OperationContext& context) const
4859 {
4860 DE_UNREF(context);
4861 return VK_QUEUE_TRANSFER_BIT;
4862 }
4863
build(OperationContext & context,Resource & resource) const4864 de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
4865 {
4866 return de::MovePtr<Operation>(new WriteImplementation(context, resource));
4867 }
4868
build(OperationContext &,Resource &,Resource &) const4869 de::MovePtr<Operation> build (OperationContext&, Resource&, Resource&) const
4870 {
4871 DE_ASSERT(0);
4872 return de::MovePtr<Operation>();
4873 }
4874 };
4875
4876 } // IndirectBuffer ns
4877
4878 namespace VertexInput
4879 {
4880
4881 enum DrawMode
4882 {
4883 DRAW_MODE_VERTEX = 0,
4884 DRAW_MODE_INDEXED,
4885 };
4886
4887 class Implementation : public Operation
4888 {
4889 public:
Implementation(OperationContext & context,Resource & resource,DrawMode drawMode)4890 Implementation (OperationContext& context, Resource& resource, DrawMode drawMode)
4891 : m_context (context)
4892 , m_resource (resource)
4893 , m_drawMode (drawMode)
4894 {
4895 requireFeaturesForSSBOAccess (m_context, VK_SHADER_STAGE_VERTEX_BIT);
4896
4897 const DeviceInterface& vk = context.getDeviceInterface();
4898 const VkDevice device = context.getDevice();
4899 Allocator& allocator = context.getAllocator();
4900 VkFormat attributeFormat = VK_FORMAT_R32G32B32A32_UINT;
4901 const VkDeviceSize dataSizeBytes = m_resource.getBuffer().size;
4902
4903 // allocate ssbo that will store data used for verification
4904 {
4905 m_outputBuffer = de::MovePtr<Buffer>(new Buffer(vk, device, allocator,
4906 makeBufferCreateInfo(dataSizeBytes, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), MemoryRequirement::HostVisible));
4907
4908 const Allocation& alloc = m_outputBuffer->getAllocation();
4909 deMemset(alloc.getHostPtr(), 0, static_cast<size_t>(dataSizeBytes));
4910 flushAlloc(vk, device, alloc);
4911 }
4912
4913 // allocate buffer that will be used for vertex attributes when we use resource for indices
4914 if (m_drawMode == DRAW_MODE_INDEXED)
4915 {
4916 attributeFormat = VK_FORMAT_R32_UINT;
4917
4918 m_inputBuffer = de::MovePtr<Buffer>(new Buffer(vk, device, allocator,
4919 makeBufferCreateInfo(dataSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), MemoryRequirement::HostVisible));
4920
4921 const Allocation& alloc = m_inputBuffer->getAllocation();
4922 fillPattern(alloc.getHostPtr(), dataSizeBytes, true);
4923 flushAlloc(vk, device, alloc);
4924 }
4925
4926 m_descriptorSetLayout = DescriptorSetLayoutBuilder()
4927 .addSingleBinding (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_VERTEX_BIT)
4928 .build (vk, device);
4929
4930 m_descriptorPool = DescriptorPoolBuilder()
4931 .addType (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
4932 .build (vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
4933
4934 m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
4935
4936 const VkDescriptorBufferInfo outputBufferDescriptorInfo = makeDescriptorBufferInfo(m_outputBuffer->get(), 0ull, dataSizeBytes);
4937 DescriptorSetUpdateBuilder()
4938 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &outputBufferDescriptorInfo)
4939 .update (vk, device);
4940
4941 // Color attachment
4942 m_colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
4943 m_colorImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
4944 m_colorImageExtent = makeExtent3D(16u, 16u, 1u);
4945 m_colorAttachmentImage = de::MovePtr<Image>(new Image(vk, device, allocator,
4946 makeImageCreateInfo(VK_IMAGE_TYPE_2D, m_colorImageExtent, m_colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
4947 VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL),
4948 MemoryRequirement::Any));
4949
4950 // Pipeline
4951 m_colorAttachmentView = makeImageView (vk, device, **m_colorAttachmentImage, VK_IMAGE_VIEW_TYPE_2D, m_colorFormat, m_colorImageSubresourceRange);
4952 m_renderPass = makeRenderPass (vk, device, m_colorFormat);
4953 m_framebuffer = makeFramebuffer (vk, device, *m_renderPass, *m_colorAttachmentView, m_colorImageExtent.width, m_colorImageExtent.height);
4954 m_pipelineLayout = makePipelineLayout(vk, device, *m_descriptorSetLayout);
4955
4956 m_pipeline = GraphicsPipelineBuilder()
4957 .setPrimitiveTopology (VK_PRIMITIVE_TOPOLOGY_POINT_LIST)
4958 .setRenderSize (tcu::IVec2(static_cast<int>(m_colorImageExtent.width), static_cast<int>(m_colorImageExtent.height)))
4959 .setVertexInputSingleAttribute (attributeFormat, tcu::getPixelSize(mapVkFormat(attributeFormat)))
4960 .setShader (vk, device, VK_SHADER_STAGE_VERTEX_BIT, context.getBinaryCollection().get("input_vert"), DE_NULL)
4961 .setShader (vk, device, VK_SHADER_STAGE_FRAGMENT_BIT, context.getBinaryCollection().get("input_frag"), DE_NULL)
4962 .build (vk, device, *m_pipelineLayout, *m_renderPass, context.getPipelineCacheData(), context.getResourceInterface());
4963 }
4964
recordCommands(const VkCommandBuffer cmdBuffer)4965 void recordCommands (const VkCommandBuffer cmdBuffer)
4966 {
4967 const DeviceInterface& vk = m_context.getDeviceInterface();
4968 const VkDeviceSize dataSizeBytes = m_resource.getBuffer().size;
4969 SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
4970
4971 // Change color attachment image layout
4972 {
4973 const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
4974 VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR, // VkPipelineStageFlags2KHR srcStageMask
4975 (VkAccessFlags)0, // VkAccessFlags2KHR srcAccessMask
4976 VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR, // VkPipelineStageFlags2KHR dstStageMask
4977 VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR, // VkAccessFlags2KHR dstAccessMask
4978 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout
4979 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout
4980 **m_colorAttachmentImage, // VkImage image
4981 m_colorImageSubresourceRange // VkImageSubresourceRange subresourceRange
4982 );
4983 VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
4984 synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
4985 }
4986
4987 {
4988 const VkRect2D renderArea = makeRect2D(m_colorImageExtent);
4989 const tcu::Vec4 clearColor = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
4990
4991 beginRenderPass(vk, cmdBuffer, *m_renderPass, *m_framebuffer, renderArea, clearColor);
4992 }
4993
4994 vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
4995 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1u, &m_descriptorSet.get(), 0u, DE_NULL);
4996
4997 const VkDeviceSize vertexBufferOffset = 0ull;
4998 if (m_drawMode == DRAW_MODE_VERTEX)
4999 {
5000 const deUint32 count = static_cast<deUint32>(dataSizeBytes / sizeof(tcu::UVec4));
5001 vk.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &m_resource.getBuffer().handle, &vertexBufferOffset);
5002 vk.cmdDraw(cmdBuffer, count, 1u, 0u, 0u);
5003 }
5004 else // (m_drawMode == DRAW_MODE_INDEXED)
5005 {
5006 const deUint32 count = static_cast<deUint32>(dataSizeBytes / sizeof(deUint32));
5007 vk.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &**m_inputBuffer, &vertexBufferOffset);
5008 vk.cmdBindIndexBuffer(cmdBuffer, m_resource.getBuffer().handle, 0u, VK_INDEX_TYPE_UINT32);
5009 vk.cmdDrawIndexed(cmdBuffer, count, 1, 0, 0, 0);
5010 }
5011
5012 endRenderPass(vk, cmdBuffer);
5013
5014 // Insert a barrier so data written by the shader is available to the host
5015 {
5016 const VkBufferMemoryBarrier2KHR bufferMemoryBarrier2 = makeBufferMemoryBarrier2(
5017 VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT_KHR, // VkPipelineStageFlags2KHR srcStageMask
5018 VK_ACCESS_2_SHADER_WRITE_BIT_KHR, // VkAccessFlags2KHR srcAccessMask
5019 VK_PIPELINE_STAGE_2_HOST_BIT_KHR, // VkPipelineStageFlags2KHR dstStageMask
5020 VK_ACCESS_2_HOST_READ_BIT_KHR, // VkAccessFlags2KHR dstAccessMask
5021 **m_outputBuffer, // VkBuffer buffer
5022 0u, // VkDeviceSize offset
5023 m_resource.getBuffer().size // VkDeviceSize size
5024 );
5025 VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, &bufferMemoryBarrier2);
5026 synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
5027 }
5028 }
5029
getInSyncInfo(void) const5030 SyncInfo getInSyncInfo (void) const
5031 {
5032 const bool usingIndexedDraw = (m_drawMode == DRAW_MODE_INDEXED);
5033 VkPipelineStageFlags2KHR stageMask = VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT_KHR;
5034 VkAccessFlags2KHR accessMask = usingIndexedDraw ? VK_ACCESS_2_INDEX_READ_BIT_KHR
5035 : VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT_KHR;
5036
5037 if (m_context.getSynchronizationType() == SynchronizationType::SYNCHRONIZATION2)
5038 {
5039 // test new stages added with VK_KHR_synchronization2 (no need to further duplicate those tests);
5040 // with this operation we can test pre_rasterization, index_input and attribute_input flags;
5041 // since this operation is executed for three buffers of different size we use diferent flags depending on the size
5042 if (m_resource.getBuffer().size > MAX_UPDATE_BUFFER_SIZE)
5043 stageMask = VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT_KHR;
5044 else
5045 stageMask = usingIndexedDraw ? VK_PIPELINE_STAGE_2_INDEX_INPUT_BIT_KHR
5046 : VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT_KHR;
5047 }
5048
5049 const SyncInfo syncInfo =
5050 {
5051 stageMask, // VkPipelineStageFlags stageMask;
5052 accessMask, // VkAccessFlags accessMask;
5053 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout imageLayout;
5054 };
5055 return syncInfo;
5056 }
5057
getOutSyncInfo(void) const5058 SyncInfo getOutSyncInfo (void) const
5059 {
5060 return emptySyncInfo;
5061 }
5062
getData(void) const5063 Data getData (void) const
5064 {
5065 return getHostBufferData(m_context, *m_outputBuffer, m_resource.getBuffer().size);
5066 }
5067
setData(const Data & data)5068 void setData (const Data& data)
5069 {
5070 setHostBufferData(m_context, *m_outputBuffer, data);
5071 }
5072
5073 private:
5074 OperationContext& m_context;
5075 Resource& m_resource;
5076 DrawMode m_drawMode;
5077 de::MovePtr<Buffer> m_inputBuffer;
5078 de::MovePtr<Buffer> m_outputBuffer;
5079 Move<VkRenderPass> m_renderPass;
5080 Move<VkFramebuffer> m_framebuffer;
5081 Move<VkPipelineLayout> m_pipelineLayout;
5082 Move<VkPipeline> m_pipeline;
5083 VkFormat m_colorFormat;
5084 de::MovePtr<Image> m_colorAttachmentImage;
5085 Move<VkImageView> m_colorAttachmentView;
5086 VkExtent3D m_colorImageExtent;
5087 VkImageSubresourceRange m_colorImageSubresourceRange;
5088 Move<VkDescriptorPool> m_descriptorPool;
5089 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
5090 Move<VkDescriptorSet> m_descriptorSet;
5091 };
5092
5093 class Support : public OperationSupport
5094 {
5095 public:
Support(const ResourceDescription & resourceDesc,DrawMode drawMode)5096 Support(const ResourceDescription& resourceDesc, DrawMode drawMode)
5097 : m_resourceDesc (resourceDesc)
5098 , m_drawMode (drawMode)
5099 {
5100 DE_ASSERT(m_resourceDesc.type == RESOURCE_TYPE_BUFFER || m_resourceDesc.type == RESOURCE_TYPE_INDEX_BUFFER);
5101 }
5102
initPrograms(SourceCollections & programCollection) const5103 void initPrograms (SourceCollections& programCollection) const
5104 {
5105 // Vertex
5106 {
5107 std::ostringstream src;
5108 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n";
5109 if (m_drawMode == DRAW_MODE_VERTEX)
5110 {
5111 src << "layout(location = 0) in uvec4 v_in_data;\n"
5112 << "layout(set = 0, binding = 0, std140) writeonly buffer Output {\n"
5113 << " uvec4 data[" << m_resourceDesc.size.x() / sizeof(tcu::UVec4) << "];\n"
5114 << "} b_out;\n"
5115 << "\n"
5116 << "void main (void)\n"
5117 << "{\n"
5118 << " b_out.data[gl_VertexIndex] = v_in_data;\n"
5119 << " gl_PointSize = 1.0f;\n"
5120 << "}\n";
5121 }
5122 else // DRAW_MODE_INDEXED
5123 {
5124 src << "layout(location = 0) in uint v_in_data;\n"
5125 << "layout(set = 0, binding = 0, std430) writeonly buffer Output {\n"
5126 << " uint data[" << m_resourceDesc.size.x() / sizeof(deUint32) << "];\n"
5127 << "} b_out;\n"
5128 << "\n"
5129 << "void main (void)\n"
5130 << "{\n"
5131 << " b_out.data[gl_VertexIndex] = v_in_data;\n"
5132 << " gl_PointSize = 1.0f;\n"
5133 << "}\n";
5134 }
5135 programCollection.glslSources.add("input_vert") << glu::VertexSource(src.str());
5136 }
5137
5138 // Fragment
5139 {
5140 std::ostringstream src;
5141 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
5142 << "\n"
5143 << "layout(location = 0) out vec4 o_color;\n"
5144 << "\n"
5145 << "void main (void)\n"
5146 << "{\n"
5147 << " o_color = vec4(1.0);\n"
5148 << "}\n";
5149 programCollection.glslSources.add("input_frag") << glu::FragmentSource(src.str());
5150 }
5151 }
5152
getInResourceUsageFlags(void) const5153 deUint32 getInResourceUsageFlags (void) const
5154 {
5155 return (m_drawMode == DRAW_MODE_VERTEX) ? VK_BUFFER_USAGE_VERTEX_BUFFER_BIT : VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
5156 }
5157
getOutResourceUsageFlags(void) const5158 deUint32 getOutResourceUsageFlags (void) const
5159 {
5160 return VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
5161 }
5162
getQueueFlags(const OperationContext &) const5163 VkQueueFlags getQueueFlags (const OperationContext&) const
5164 {
5165 return VK_QUEUE_GRAPHICS_BIT;
5166 }
5167
build(OperationContext & context,Resource & resource) const5168 de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
5169 {
5170 return de::MovePtr<Operation>(new Implementation(context, resource, m_drawMode));
5171 }
5172
build(OperationContext &,Resource &,Resource &) const5173 de::MovePtr<Operation> build (OperationContext&, Resource&, Resource&) const
5174 {
5175 DE_ASSERT(0);
5176 return de::MovePtr<Operation>();
5177 }
5178
5179 private:
5180 const ResourceDescription m_resourceDesc;
5181 const DrawMode m_drawMode;
5182 };
5183
5184 } // VertexInput
5185
5186 } // anonymous ns
5187
OperationContext(Context & context,SynchronizationType syncType,PipelineCacheData & pipelineCacheData)5188 OperationContext::OperationContext (Context& context, SynchronizationType syncType, PipelineCacheData& pipelineCacheData)
5189 : m_context (context)
5190 , m_syncType (syncType)
5191 , m_vki (context.getInstanceInterface())
5192 , m_vk (context.getDeviceInterface())
5193 , m_physicalDevice (context.getPhysicalDevice())
5194 , m_device (context.getDevice())
5195 , m_allocator (context.getDefaultAllocator())
5196 , m_progCollection (context.getBinaryCollection())
5197 , m_pipelineCacheData (pipelineCacheData)
5198 {
5199 }
5200
OperationContext(Context & context,SynchronizationType syncType,const DeviceInterface & vk,const VkDevice device,vk::Allocator & allocator,PipelineCacheData & pipelineCacheData)5201 OperationContext::OperationContext (Context& context,
5202 SynchronizationType syncType,
5203 const DeviceInterface& vk,
5204 const VkDevice device,
5205 vk::Allocator& allocator,
5206 PipelineCacheData& pipelineCacheData)
5207 : m_context (context)
5208 , m_syncType (syncType)
5209 , m_vki (context.getInstanceInterface())
5210 , m_vk (vk)
5211 , m_physicalDevice (context.getPhysicalDevice())
5212 , m_device (device)
5213 , m_allocator (allocator)
5214 , m_progCollection (context.getBinaryCollection())
5215 , m_pipelineCacheData (pipelineCacheData)
5216 {
5217 }
5218
OperationContext(Context & context,SynchronizationType syncType,const vk::InstanceInterface & vki,const vk::DeviceInterface & vkd,vk::VkPhysicalDevice physicalDevice,vk::VkDevice device,vk::Allocator & allocator,vk::BinaryCollection & programCollection,PipelineCacheData & pipelineCacheData)5219 OperationContext::OperationContext (Context& context,
5220 SynchronizationType syncType,
5221 const vk::InstanceInterface& vki,
5222 const vk::DeviceInterface& vkd,
5223 vk::VkPhysicalDevice physicalDevice,
5224 vk::VkDevice device,
5225 vk::Allocator& allocator,
5226 vk::BinaryCollection& programCollection,
5227 PipelineCacheData& pipelineCacheData)
5228 : m_context (context)
5229 , m_syncType (syncType)
5230 , m_vki (vki)
5231 , m_vk (vkd)
5232 , m_physicalDevice (physicalDevice)
5233 , m_device (device)
5234 , m_allocator (allocator)
5235 , m_progCollection (programCollection)
5236 , m_pipelineCacheData (pipelineCacheData)
5237 {
5238 }
5239
Resource(OperationContext & context,const ResourceDescription & desc,const deUint32 usage,const vk::VkSharingMode sharingMode,const std::vector<deUint32> & queueFamilyIndex)5240 Resource::Resource (OperationContext& context, const ResourceDescription& desc, const deUint32 usage, const vk::VkSharingMode sharingMode, const std::vector<deUint32>& queueFamilyIndex)
5241 : m_type (desc.type)
5242 {
5243 const DeviceInterface& vk = context.getDeviceInterface();
5244 const InstanceInterface& vki = context.getInstanceInterface();
5245 const VkDevice device = context.getDevice();
5246 const VkPhysicalDevice physDevice = context.getPhysicalDevice();
5247 Allocator& allocator = context.getAllocator();
5248
5249 if (m_type == RESOURCE_TYPE_BUFFER || m_type == RESOURCE_TYPE_INDEX_BUFFER || isIndirectBuffer(m_type))
5250 {
5251 m_bufferData = de::MovePtr<BufferResource>(new BufferResource(DE_NULL, 0u, static_cast<VkDeviceSize>(desc.size.x())));
5252 VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(m_bufferData->size, usage);
5253 bufferCreateInfo.sharingMode = sharingMode;
5254 if (queueFamilyIndex.size() > 0)
5255 {
5256 bufferCreateInfo.queueFamilyIndexCount = static_cast<deUint32>(queueFamilyIndex.size());
5257 bufferCreateInfo.pQueueFamilyIndices = &queueFamilyIndex[0];
5258 }
5259 m_buffer = de::MovePtr<Buffer>(new Buffer(vk, device, allocator, bufferCreateInfo, MemoryRequirement::Any));
5260 m_bufferData->handle = **m_buffer;
5261 }
5262 else if (m_type == RESOURCE_TYPE_IMAGE)
5263 {
5264 m_imageData = de::MovePtr<ImageResource>(new ImageResource(
5265 DE_NULL,
5266 makeExtent3D(desc.size.x(), std::max(1, desc.size.y()), std::max(1, desc.size.z())),
5267 desc.imageType,
5268 desc.imageFormat,
5269 makeImageSubresourceRange(desc.imageAspect, 0u, 1u, 0u, 1u),
5270 makeImageSubresourceLayers(desc.imageAspect, 0u, 0u, 1u),
5271 vk::VK_IMAGE_TILING_OPTIMAL
5272 ));
5273 VkImageCreateInfo imageInfo = makeImageCreateInfo(m_imageData->imageType, m_imageData->extent, m_imageData->format, usage, desc.imageSamples, m_imageData->tiling);
5274 imageInfo.sharingMode = sharingMode;
5275 if (queueFamilyIndex.size() > 0)
5276 {
5277 imageInfo.queueFamilyIndexCount = static_cast<deUint32>(queueFamilyIndex.size());
5278 imageInfo.pQueueFamilyIndices = &queueFamilyIndex[0];
5279 }
5280
5281 VkImageFormatProperties imageFormatProperties;
5282 const VkResult formatResult = vki.getPhysicalDeviceImageFormatProperties(physDevice, imageInfo.format, imageInfo.imageType, imageInfo.tiling, imageInfo.usage, imageInfo.flags, &imageFormatProperties);
5283
5284 if (formatResult != VK_SUCCESS)
5285 TCU_THROW(NotSupportedError, "Image format is not supported");
5286
5287 if ((imageFormatProperties.sampleCounts & desc.imageSamples) != desc.imageSamples)
5288 TCU_THROW(NotSupportedError, "Requested sample count is not supported");
5289
5290 m_image = de::MovePtr<Image>(new Image(vk, device, allocator, imageInfo, MemoryRequirement::Any));
5291 m_imageData->handle = **m_image;
5292 }
5293 else
5294 DE_ASSERT(0);
5295 }
5296
Resource(ResourceType type,vk::Move<vk::VkBuffer> buffer,de::MovePtr<vk::Allocation> allocation,vk::VkDeviceSize offset,vk::VkDeviceSize size)5297 Resource::Resource (ResourceType type,
5298 vk::Move<vk::VkBuffer> buffer,
5299 de::MovePtr<vk::Allocation> allocation,
5300 vk::VkDeviceSize offset,
5301 vk::VkDeviceSize size)
5302 : m_type (type)
5303 , m_buffer (new Buffer(buffer, allocation))
5304 , m_bufferData (de::MovePtr<BufferResource>(new BufferResource(m_buffer->get(), offset, size)))
5305 {
5306 DE_ASSERT(type != RESOURCE_TYPE_IMAGE);
5307 }
5308
Resource(vk::Move<vk::VkImage> image,de::MovePtr<vk::Allocation> allocation,const vk::VkExtent3D & extent,vk::VkImageType imageType,vk::VkFormat format,vk::VkImageSubresourceRange subresourceRange,vk::VkImageSubresourceLayers subresourceLayers,vk::VkImageTiling tiling)5309 Resource::Resource (vk::Move<vk::VkImage> image,
5310 de::MovePtr<vk::Allocation> allocation,
5311 const vk::VkExtent3D& extent,
5312 vk::VkImageType imageType,
5313 vk::VkFormat format,
5314 vk::VkImageSubresourceRange subresourceRange,
5315 vk::VkImageSubresourceLayers subresourceLayers,
5316 vk::VkImageTiling tiling)
5317 : m_type (RESOURCE_TYPE_IMAGE)
5318 , m_image (new Image(image, allocation))
5319 , m_imageData (de::MovePtr<ImageResource>(new ImageResource(m_image->get(), extent, imageType, format, subresourceRange, subresourceLayers, tiling)))
5320 {
5321 }
5322
getMemory(void) const5323 vk::VkDeviceMemory Resource::getMemory (void) const
5324 {
5325 if (m_type == RESOURCE_TYPE_IMAGE)
5326 return m_image->getAllocation().getMemory();
5327 else
5328 return m_buffer->getAllocation().getMemory();
5329 }
5330
5331 //! \note This function exists for performance reasons. We're creating a lot of tests and checking requirements here
5332 //! before creating an OperationSupport object is faster.
isResourceSupported(const OperationName opName,const ResourceDescription & resourceDesc)5333 bool isResourceSupported (const OperationName opName, const ResourceDescription& resourceDesc)
5334 {
5335 switch (opName)
5336 {
5337 case OPERATION_NAME_WRITE_FILL_BUFFER:
5338 case OPERATION_NAME_WRITE_COPY_BUFFER:
5339 case OPERATION_NAME_WRITE_COPY_IMAGE_TO_BUFFER:
5340 case OPERATION_NAME_WRITE_SSBO_VERTEX:
5341 case OPERATION_NAME_WRITE_SSBO_TESSELLATION_CONTROL:
5342 case OPERATION_NAME_WRITE_SSBO_TESSELLATION_EVALUATION:
5343 case OPERATION_NAME_WRITE_SSBO_GEOMETRY:
5344 case OPERATION_NAME_WRITE_SSBO_FRAGMENT:
5345 case OPERATION_NAME_WRITE_SSBO_COMPUTE:
5346 case OPERATION_NAME_WRITE_SSBO_COMPUTE_INDIRECT:
5347 case OPERATION_NAME_READ_COPY_BUFFER:
5348 case OPERATION_NAME_READ_COPY_BUFFER_TO_IMAGE:
5349 case OPERATION_NAME_READ_SSBO_VERTEX:
5350 case OPERATION_NAME_READ_SSBO_TESSELLATION_CONTROL:
5351 case OPERATION_NAME_READ_SSBO_TESSELLATION_EVALUATION:
5352 case OPERATION_NAME_READ_SSBO_GEOMETRY:
5353 case OPERATION_NAME_READ_SSBO_FRAGMENT:
5354 case OPERATION_NAME_READ_SSBO_COMPUTE:
5355 case OPERATION_NAME_READ_SSBO_COMPUTE_INDIRECT:
5356 case OPERATION_NAME_READ_VERTEX_INPUT:
5357 return resourceDesc.type == RESOURCE_TYPE_BUFFER;
5358
5359 case OPERATION_NAME_WRITE_INDIRECT_BUFFER_DRAW:
5360 case OPERATION_NAME_READ_INDIRECT_BUFFER_DRAW:
5361 return resourceDesc.type == RESOURCE_TYPE_INDIRECT_BUFFER_DRAW;
5362
5363 case OPERATION_NAME_WRITE_INDIRECT_BUFFER_DRAW_INDEXED:
5364 case OPERATION_NAME_READ_INDIRECT_BUFFER_DRAW_INDEXED:
5365 return resourceDesc.type == RESOURCE_TYPE_INDIRECT_BUFFER_DRAW_INDEXED;
5366
5367 case OPERATION_NAME_WRITE_INDIRECT_BUFFER_DISPATCH:
5368 case OPERATION_NAME_READ_INDIRECT_BUFFER_DISPATCH:
5369 return resourceDesc.type == RESOURCE_TYPE_INDIRECT_BUFFER_DISPATCH;
5370
5371 case OPERATION_NAME_WRITE_UPDATE_INDEX_BUFFER:
5372 case OPERATION_NAME_READ_INDEX_INPUT:
5373 return resourceDesc.type == RESOURCE_TYPE_INDEX_BUFFER;
5374
5375 case OPERATION_NAME_WRITE_UPDATE_BUFFER:
5376 return resourceDesc.type == RESOURCE_TYPE_BUFFER && resourceDesc.size.x() <= MAX_UPDATE_BUFFER_SIZE;
5377
5378 case OPERATION_NAME_WRITE_COPY_IMAGE:
5379 case OPERATION_NAME_WRITE_COPY_BUFFER_TO_IMAGE:
5380 case OPERATION_NAME_READ_COPY_IMAGE:
5381 case OPERATION_NAME_READ_COPY_IMAGE_TO_BUFFER:
5382 return resourceDesc.type == RESOURCE_TYPE_IMAGE && resourceDesc.imageSamples == VK_SAMPLE_COUNT_1_BIT;
5383
5384 case OPERATION_NAME_WRITE_CLEAR_ATTACHMENTS:
5385 return resourceDesc.type == RESOURCE_TYPE_IMAGE && resourceDesc.imageType != VK_IMAGE_TYPE_3D
5386 && resourceDesc.imageSamples == VK_SAMPLE_COUNT_1_BIT;
5387
5388 case OPERATION_NAME_WRITE_IMAGE_COMPUTE_MULTISAMPLE:
5389 case OPERATION_NAME_READ_RESOLVE_IMAGE:
5390 return resourceDesc.type == RESOURCE_TYPE_IMAGE && resourceDesc.imageAspect == VK_IMAGE_ASPECT_COLOR_BIT
5391 && resourceDesc.imageSamples != VK_SAMPLE_COUNT_1_BIT;
5392
5393 case OPERATION_NAME_WRITE_BLIT_IMAGE:
5394 case OPERATION_NAME_READ_BLIT_IMAGE:
5395 case OPERATION_NAME_WRITE_IMAGE_VERTEX:
5396 case OPERATION_NAME_WRITE_IMAGE_TESSELLATION_CONTROL:
5397 case OPERATION_NAME_WRITE_IMAGE_TESSELLATION_EVALUATION:
5398 case OPERATION_NAME_WRITE_IMAGE_GEOMETRY:
5399 case OPERATION_NAME_WRITE_IMAGE_FRAGMENT:
5400 case OPERATION_NAME_WRITE_IMAGE_COMPUTE:
5401 case OPERATION_NAME_WRITE_IMAGE_COMPUTE_INDIRECT:
5402 case OPERATION_NAME_READ_IMAGE_VERTEX:
5403 case OPERATION_NAME_READ_IMAGE_TESSELLATION_CONTROL:
5404 case OPERATION_NAME_READ_IMAGE_TESSELLATION_EVALUATION:
5405 case OPERATION_NAME_READ_IMAGE_GEOMETRY:
5406 case OPERATION_NAME_READ_IMAGE_FRAGMENT:
5407 case OPERATION_NAME_READ_IMAGE_COMPUTE:
5408 case OPERATION_NAME_READ_IMAGE_COMPUTE_INDIRECT:
5409 return resourceDesc.type == RESOURCE_TYPE_IMAGE && resourceDesc.imageAspect == VK_IMAGE_ASPECT_COLOR_BIT
5410 && resourceDesc.imageSamples == VK_SAMPLE_COUNT_1_BIT;
5411
5412 case OPERATION_NAME_READ_UBO_VERTEX:
5413 case OPERATION_NAME_READ_UBO_TESSELLATION_CONTROL:
5414 case OPERATION_NAME_READ_UBO_TESSELLATION_EVALUATION:
5415 case OPERATION_NAME_READ_UBO_GEOMETRY:
5416 case OPERATION_NAME_READ_UBO_FRAGMENT:
5417 case OPERATION_NAME_READ_UBO_COMPUTE:
5418 case OPERATION_NAME_READ_UBO_COMPUTE_INDIRECT:
5419 return resourceDesc.type == RESOURCE_TYPE_BUFFER && resourceDesc.size.x() <= MAX_UBO_RANGE;
5420
5421 case OPERATION_NAME_WRITE_CLEAR_COLOR_IMAGE:
5422 return resourceDesc.type == RESOURCE_TYPE_IMAGE && resourceDesc.imageAspect == VK_IMAGE_ASPECT_COLOR_BIT
5423 && resourceDesc.imageSamples == VK_SAMPLE_COUNT_1_BIT;
5424
5425 case OPERATION_NAME_WRITE_CLEAR_DEPTH_STENCIL_IMAGE:
5426 return resourceDesc.type == RESOURCE_TYPE_IMAGE && (resourceDesc.imageAspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))
5427 && resourceDesc.imageSamples == VK_SAMPLE_COUNT_1_BIT;
5428
5429 case OPERATION_NAME_WRITE_DRAW:
5430 case OPERATION_NAME_WRITE_DRAW_INDEXED:
5431 case OPERATION_NAME_WRITE_DRAW_INDIRECT:
5432 case OPERATION_NAME_WRITE_DRAW_INDEXED_INDIRECT:
5433 return resourceDesc.type == RESOURCE_TYPE_IMAGE && resourceDesc.imageType == VK_IMAGE_TYPE_2D
5434 && (resourceDesc.imageAspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) == 0
5435 && resourceDesc.imageSamples == VK_SAMPLE_COUNT_1_BIT;
5436
5437 case OPERATION_NAME_COPY_BUFFER:
5438 case OPERATION_NAME_COPY_SSBO_VERTEX:
5439 case OPERATION_NAME_COPY_SSBO_TESSELLATION_CONTROL:
5440 case OPERATION_NAME_COPY_SSBO_TESSELLATION_EVALUATION:
5441 case OPERATION_NAME_COPY_SSBO_GEOMETRY:
5442 case OPERATION_NAME_COPY_SSBO_FRAGMENT:
5443 case OPERATION_NAME_COPY_SSBO_COMPUTE:
5444 case OPERATION_NAME_COPY_SSBO_COMPUTE_INDIRECT:
5445 return resourceDesc.type == RESOURCE_TYPE_BUFFER;
5446
5447 case OPERATION_NAME_COPY_IMAGE:
5448 case OPERATION_NAME_BLIT_IMAGE:
5449 case OPERATION_NAME_COPY_IMAGE_VERTEX:
5450 case OPERATION_NAME_COPY_IMAGE_TESSELLATION_CONTROL:
5451 case OPERATION_NAME_COPY_IMAGE_TESSELLATION_EVALUATION:
5452 case OPERATION_NAME_COPY_IMAGE_GEOMETRY:
5453 case OPERATION_NAME_COPY_IMAGE_FRAGMENT:
5454 case OPERATION_NAME_COPY_IMAGE_COMPUTE:
5455 case OPERATION_NAME_COPY_IMAGE_COMPUTE_INDIRECT:
5456 return resourceDesc.type == RESOURCE_TYPE_IMAGE && resourceDesc.imageAspect == VK_IMAGE_ASPECT_COLOR_BIT
5457 && resourceDesc.imageSamples == VK_SAMPLE_COUNT_1_BIT;
5458
5459 default:
5460 DE_ASSERT(0);
5461 return false;
5462 }
5463 }
5464
getOperationName(const OperationName opName)5465 std::string getOperationName (const OperationName opName)
5466 {
5467 switch (opName)
5468 {
5469 case OPERATION_NAME_WRITE_FILL_BUFFER: return "write_fill_buffer";
5470 case OPERATION_NAME_WRITE_UPDATE_BUFFER: return "write_update_buffer";
5471 case OPERATION_NAME_WRITE_COPY_BUFFER: return "write_copy_buffer";
5472 case OPERATION_NAME_WRITE_COPY_BUFFER_TO_IMAGE: return "write_copy_buffer_to_image";
5473 case OPERATION_NAME_WRITE_COPY_IMAGE_TO_BUFFER: return "write_copy_image_to_buffer";
5474 case OPERATION_NAME_WRITE_COPY_IMAGE: return "write_copy_image";
5475 case OPERATION_NAME_WRITE_BLIT_IMAGE: return "write_blit_image";
5476 case OPERATION_NAME_WRITE_SSBO_VERTEX: return "write_ssbo_vertex";
5477 case OPERATION_NAME_WRITE_SSBO_TESSELLATION_CONTROL: return "write_ssbo_tess_control";
5478 case OPERATION_NAME_WRITE_SSBO_TESSELLATION_EVALUATION: return "write_ssbo_tess_eval";
5479 case OPERATION_NAME_WRITE_SSBO_GEOMETRY: return "write_ssbo_geometry";
5480 case OPERATION_NAME_WRITE_SSBO_FRAGMENT: return "write_ssbo_fragment";
5481 case OPERATION_NAME_WRITE_SSBO_COMPUTE: return "write_ssbo_compute";
5482 case OPERATION_NAME_WRITE_SSBO_COMPUTE_INDIRECT: return "write_ssbo_compute_indirect";
5483 case OPERATION_NAME_WRITE_IMAGE_VERTEX: return "write_image_vertex";
5484 case OPERATION_NAME_WRITE_IMAGE_TESSELLATION_CONTROL: return "write_image_tess_control";
5485 case OPERATION_NAME_WRITE_IMAGE_TESSELLATION_EVALUATION: return "write_image_tess_eval";
5486 case OPERATION_NAME_WRITE_IMAGE_GEOMETRY: return "write_image_geometry";
5487 case OPERATION_NAME_WRITE_IMAGE_FRAGMENT: return "write_image_fragment";
5488 case OPERATION_NAME_WRITE_IMAGE_COMPUTE: return "write_image_compute";
5489 case OPERATION_NAME_WRITE_IMAGE_COMPUTE_MULTISAMPLE: return "write_image_compute_multisample";
5490 case OPERATION_NAME_WRITE_IMAGE_COMPUTE_INDIRECT: return "write_image_compute_indirect";
5491 case OPERATION_NAME_WRITE_CLEAR_COLOR_IMAGE: return "write_clear_color_image";
5492 case OPERATION_NAME_WRITE_CLEAR_DEPTH_STENCIL_IMAGE: return "write_clear_depth_stencil_image";
5493 case OPERATION_NAME_WRITE_DRAW: return "write_draw";
5494 case OPERATION_NAME_WRITE_DRAW_INDEXED: return "write_draw_indexed";
5495 case OPERATION_NAME_WRITE_DRAW_INDIRECT: return "write_draw_indirect";
5496 case OPERATION_NAME_WRITE_DRAW_INDEXED_INDIRECT: return "write_draw_indexed_indirect";
5497 case OPERATION_NAME_WRITE_CLEAR_ATTACHMENTS: return "write_clear_attachments";
5498 case OPERATION_NAME_WRITE_INDIRECT_BUFFER_DRAW: return "write_indirect_buffer_draw";
5499 case OPERATION_NAME_WRITE_INDIRECT_BUFFER_DRAW_INDEXED: return "write_indirect_buffer_draw_indexed";
5500 case OPERATION_NAME_WRITE_INDIRECT_BUFFER_DISPATCH: return "write_indirect_buffer_dispatch";
5501 case OPERATION_NAME_WRITE_UPDATE_INDEX_BUFFER: return "write_update_index_buffer";
5502
5503 case OPERATION_NAME_READ_COPY_BUFFER: return "read_copy_buffer";
5504 case OPERATION_NAME_READ_COPY_BUFFER_TO_IMAGE: return "read_copy_buffer_to_image";
5505 case OPERATION_NAME_READ_COPY_IMAGE_TO_BUFFER: return "read_copy_image_to_buffer";
5506 case OPERATION_NAME_READ_COPY_IMAGE: return "read_copy_image";
5507 case OPERATION_NAME_READ_BLIT_IMAGE: return "read_blit_image";
5508 case OPERATION_NAME_READ_RESOLVE_IMAGE: return "read_resolve_image";
5509 case OPERATION_NAME_READ_UBO_VERTEX: return "read_ubo_vertex";
5510 case OPERATION_NAME_READ_UBO_TESSELLATION_CONTROL: return "read_ubo_tess_control";
5511 case OPERATION_NAME_READ_UBO_TESSELLATION_EVALUATION: return "read_ubo_tess_eval";
5512 case OPERATION_NAME_READ_UBO_GEOMETRY: return "read_ubo_geometry";
5513 case OPERATION_NAME_READ_UBO_FRAGMENT: return "read_ubo_fragment";
5514 case OPERATION_NAME_READ_UBO_COMPUTE: return "read_ubo_compute";
5515 case OPERATION_NAME_READ_UBO_COMPUTE_INDIRECT: return "read_ubo_compute_indirect";
5516 case OPERATION_NAME_READ_SSBO_VERTEX: return "read_ssbo_vertex";
5517 case OPERATION_NAME_READ_SSBO_TESSELLATION_CONTROL: return "read_ssbo_tess_control";
5518 case OPERATION_NAME_READ_SSBO_TESSELLATION_EVALUATION: return "read_ssbo_tess_eval";
5519 case OPERATION_NAME_READ_SSBO_GEOMETRY: return "read_ssbo_geometry";
5520 case OPERATION_NAME_READ_SSBO_FRAGMENT: return "read_ssbo_fragment";
5521 case OPERATION_NAME_READ_SSBO_COMPUTE: return "read_ssbo_compute";
5522 case OPERATION_NAME_READ_SSBO_COMPUTE_INDIRECT: return "read_ssbo_compute_indirect";
5523 case OPERATION_NAME_READ_IMAGE_VERTEX: return "read_image_vertex";
5524 case OPERATION_NAME_READ_IMAGE_TESSELLATION_CONTROL: return "read_image_tess_control";
5525 case OPERATION_NAME_READ_IMAGE_TESSELLATION_EVALUATION: return "read_image_tess_eval";
5526 case OPERATION_NAME_READ_IMAGE_GEOMETRY: return "read_image_geometry";
5527 case OPERATION_NAME_READ_IMAGE_FRAGMENT: return "read_image_fragment";
5528 case OPERATION_NAME_READ_IMAGE_COMPUTE: return "read_image_compute";
5529 case OPERATION_NAME_READ_IMAGE_COMPUTE_INDIRECT: return "read_image_compute_indirect";
5530 case OPERATION_NAME_READ_INDIRECT_BUFFER_DRAW: return "read_indirect_buffer_draw";
5531 case OPERATION_NAME_READ_INDIRECT_BUFFER_DRAW_INDEXED: return "read_indirect_buffer_draw_indexed";
5532 case OPERATION_NAME_READ_INDIRECT_BUFFER_DISPATCH: return "read_indirect_buffer_dispatch";
5533 case OPERATION_NAME_READ_VERTEX_INPUT: return "read_vertex_input";
5534 case OPERATION_NAME_READ_INDEX_INPUT: return "read_index_input";
5535
5536 case OPERATION_NAME_COPY_BUFFER: return "copy_buffer";
5537 case OPERATION_NAME_COPY_IMAGE: return "copy_image";
5538 case OPERATION_NAME_BLIT_IMAGE: return "blit_image";
5539 case OPERATION_NAME_COPY_SSBO_VERTEX: return "copy_buffer_vertex";
5540 case OPERATION_NAME_COPY_SSBO_TESSELLATION_CONTROL: return "copy_ssbo_tess_control";
5541 case OPERATION_NAME_COPY_SSBO_TESSELLATION_EVALUATION: return "copy_ssbo_tess_eval";
5542 case OPERATION_NAME_COPY_SSBO_GEOMETRY: return "copy_ssbo_geometry";
5543 case OPERATION_NAME_COPY_SSBO_FRAGMENT: return "copy_ssbo_fragment";
5544 case OPERATION_NAME_COPY_SSBO_COMPUTE: return "copy_ssbo_compute";
5545 case OPERATION_NAME_COPY_SSBO_COMPUTE_INDIRECT: return "copy_ssbo_compute_indirect";
5546 case OPERATION_NAME_COPY_IMAGE_VERTEX: return "copy_image_vertex";
5547 case OPERATION_NAME_COPY_IMAGE_TESSELLATION_CONTROL: return "copy_image_tess_control";
5548 case OPERATION_NAME_COPY_IMAGE_TESSELLATION_EVALUATION: return "copy_image_tess_eval";
5549 case OPERATION_NAME_COPY_IMAGE_GEOMETRY: return "copy_image_geometry";
5550 case OPERATION_NAME_COPY_IMAGE_FRAGMENT: return "copy_image_fragment";
5551 case OPERATION_NAME_COPY_IMAGE_COMPUTE: return "copy_image_compute";
5552 case OPERATION_NAME_COPY_IMAGE_COMPUTE_INDIRECT: return "copy_image_compute_indirect";
5553 default:
5554 DE_ASSERT(0);
5555 return "";
5556 }
5557 }
5558
makeOperationSupport(const OperationName opName,const ResourceDescription & resourceDesc)5559 de::MovePtr<OperationSupport> makeOperationSupport (const OperationName opName, const ResourceDescription& resourceDesc)
5560 {
5561 switch (opName)
5562 {
5563 case OPERATION_NAME_WRITE_FILL_BUFFER: return de::MovePtr<OperationSupport>(new FillUpdateBuffer ::Support (resourceDesc, FillUpdateBuffer::BUFFER_OP_FILL));
5564 case OPERATION_NAME_WRITE_UPDATE_BUFFER: return de::MovePtr<OperationSupport>(new FillUpdateBuffer ::Support (resourceDesc, FillUpdateBuffer::BUFFER_OP_UPDATE));
5565 case OPERATION_NAME_WRITE_COPY_BUFFER: return de::MovePtr<OperationSupport>(new CopyBuffer ::Support (resourceDesc, ACCESS_MODE_WRITE));
5566 case OPERATION_NAME_WRITE_COPY_BUFFER_TO_IMAGE: return de::MovePtr<OperationSupport>(new CopyBufferToImage ::Support (resourceDesc, ACCESS_MODE_WRITE));
5567 case OPERATION_NAME_WRITE_COPY_IMAGE_TO_BUFFER: return de::MovePtr<OperationSupport>(new CopyImageToBuffer ::Support (resourceDesc, ACCESS_MODE_WRITE));
5568 case OPERATION_NAME_WRITE_COPY_IMAGE: return de::MovePtr<OperationSupport>(new CopyBlitResolveImage ::Support (resourceDesc, CopyBlitResolveImage::TYPE_COPY, ACCESS_MODE_WRITE));
5569 case OPERATION_NAME_WRITE_BLIT_IMAGE: return de::MovePtr<OperationSupport>(new CopyBlitResolveImage ::Support (resourceDesc, CopyBlitResolveImage::TYPE_BLIT, ACCESS_MODE_WRITE));
5570 case OPERATION_NAME_WRITE_SSBO_VERTEX: return de::MovePtr<OperationSupport>(new ShaderAccess ::BufferSupport (resourceDesc, BUFFER_TYPE_STORAGE, ACCESS_MODE_WRITE, VK_SHADER_STAGE_VERTEX_BIT));
5571 case OPERATION_NAME_WRITE_SSBO_TESSELLATION_CONTROL: return de::MovePtr<OperationSupport>(new ShaderAccess ::BufferSupport (resourceDesc, BUFFER_TYPE_STORAGE, ACCESS_MODE_WRITE, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT));
5572 case OPERATION_NAME_WRITE_SSBO_TESSELLATION_EVALUATION: return de::MovePtr<OperationSupport>(new ShaderAccess ::BufferSupport (resourceDesc, BUFFER_TYPE_STORAGE, ACCESS_MODE_WRITE, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT));
5573 case OPERATION_NAME_WRITE_SSBO_GEOMETRY: return de::MovePtr<OperationSupport>(new ShaderAccess ::BufferSupport (resourceDesc, BUFFER_TYPE_STORAGE, ACCESS_MODE_WRITE, VK_SHADER_STAGE_GEOMETRY_BIT));
5574 case OPERATION_NAME_WRITE_SSBO_FRAGMENT: return de::MovePtr<OperationSupport>(new ShaderAccess ::BufferSupport (resourceDesc, BUFFER_TYPE_STORAGE, ACCESS_MODE_WRITE, VK_SHADER_STAGE_FRAGMENT_BIT));
5575 case OPERATION_NAME_WRITE_SSBO_COMPUTE: return de::MovePtr<OperationSupport>(new ShaderAccess ::BufferSupport (resourceDesc, BUFFER_TYPE_STORAGE, ACCESS_MODE_WRITE, VK_SHADER_STAGE_COMPUTE_BIT));
5576 case OPERATION_NAME_WRITE_SSBO_COMPUTE_INDIRECT: return de::MovePtr<OperationSupport>(new ShaderAccess ::BufferSupport (resourceDesc, BUFFER_TYPE_STORAGE, ACCESS_MODE_WRITE, VK_SHADER_STAGE_COMPUTE_BIT, ShaderAccess::DISPATCH_CALL_DISPATCH_INDIRECT));
5577 case OPERATION_NAME_WRITE_IMAGE_VERTEX: return de::MovePtr<OperationSupport>(new ShaderAccess ::ImageSupport (resourceDesc, ACCESS_MODE_WRITE, VK_SHADER_STAGE_VERTEX_BIT));
5578 case OPERATION_NAME_WRITE_IMAGE_TESSELLATION_CONTROL: return de::MovePtr<OperationSupport>(new ShaderAccess ::ImageSupport (resourceDesc, ACCESS_MODE_WRITE, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT));
5579 case OPERATION_NAME_WRITE_IMAGE_TESSELLATION_EVALUATION: return de::MovePtr<OperationSupport>(new ShaderAccess ::ImageSupport (resourceDesc, ACCESS_MODE_WRITE, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT));
5580 case OPERATION_NAME_WRITE_IMAGE_GEOMETRY: return de::MovePtr<OperationSupport>(new ShaderAccess ::ImageSupport (resourceDesc, ACCESS_MODE_WRITE, VK_SHADER_STAGE_GEOMETRY_BIT));
5581 case OPERATION_NAME_WRITE_IMAGE_FRAGMENT: return de::MovePtr<OperationSupport>(new ShaderAccess ::ImageSupport (resourceDesc, ACCESS_MODE_WRITE, VK_SHADER_STAGE_FRAGMENT_BIT));
5582 case OPERATION_NAME_WRITE_IMAGE_COMPUTE: return de::MovePtr<OperationSupport>(new ShaderAccess ::ImageSupport (resourceDesc, ACCESS_MODE_WRITE, VK_SHADER_STAGE_COMPUTE_BIT));
5583 case OPERATION_NAME_WRITE_IMAGE_COMPUTE_INDIRECT: return de::MovePtr<OperationSupport>(new ShaderAccess ::ImageSupport (resourceDesc, ACCESS_MODE_WRITE, VK_SHADER_STAGE_COMPUTE_BIT, ShaderAccess::DISPATCH_CALL_DISPATCH_INDIRECT));
5584 case OPERATION_NAME_WRITE_IMAGE_COMPUTE_MULTISAMPLE: return de::MovePtr<OperationSupport>(new ShaderAccess ::MSImageSupport(resourceDesc));
5585 case OPERATION_NAME_WRITE_CLEAR_COLOR_IMAGE: return de::MovePtr<OperationSupport>(new ClearImage ::Support (resourceDesc, ClearImage::CLEAR_MODE_COLOR));
5586 case OPERATION_NAME_WRITE_CLEAR_DEPTH_STENCIL_IMAGE: return de::MovePtr<OperationSupport>(new ClearImage ::Support (resourceDesc, ClearImage::CLEAR_MODE_DEPTH_STENCIL));
5587 case OPERATION_NAME_WRITE_DRAW: return de::MovePtr<OperationSupport>(new Draw ::Support (resourceDesc, Draw::DRAW_CALL_DRAW));
5588 case OPERATION_NAME_WRITE_DRAW_INDEXED: return de::MovePtr<OperationSupport>(new Draw ::Support (resourceDesc, Draw::DRAW_CALL_DRAW_INDEXED));
5589 case OPERATION_NAME_WRITE_DRAW_INDIRECT: return de::MovePtr<OperationSupport>(new Draw ::Support (resourceDesc, Draw::DRAW_CALL_DRAW_INDIRECT));
5590 case OPERATION_NAME_WRITE_DRAW_INDEXED_INDIRECT: return de::MovePtr<OperationSupport>(new Draw ::Support (resourceDesc, Draw::DRAW_CALL_DRAW_INDEXED_INDIRECT));
5591 case OPERATION_NAME_WRITE_CLEAR_ATTACHMENTS: return de::MovePtr<OperationSupport>(new ClearAttachments ::Support (resourceDesc));
5592 case OPERATION_NAME_WRITE_INDIRECT_BUFFER_DRAW: return de::MovePtr<OperationSupport>(new IndirectBuffer ::WriteSupport (resourceDesc));
5593 case OPERATION_NAME_WRITE_INDIRECT_BUFFER_DRAW_INDEXED: return de::MovePtr<OperationSupport>(new IndirectBuffer ::WriteSupport (resourceDesc));
5594 case OPERATION_NAME_WRITE_INDIRECT_BUFFER_DISPATCH: return de::MovePtr<OperationSupport>(new IndirectBuffer ::WriteSupport (resourceDesc));
5595 case OPERATION_NAME_WRITE_UPDATE_INDEX_BUFFER: return de::MovePtr<OperationSupport>(new FillUpdateBuffer ::Support (resourceDesc, FillUpdateBuffer::BUFFER_OP_UPDATE_WITH_INDEX_PATTERN));
5596
5597 case OPERATION_NAME_READ_COPY_BUFFER: return de::MovePtr<OperationSupport>(new CopyBuffer ::Support (resourceDesc, ACCESS_MODE_READ));
5598 case OPERATION_NAME_READ_COPY_BUFFER_TO_IMAGE: return de::MovePtr<OperationSupport>(new CopyBufferToImage ::Support (resourceDesc, ACCESS_MODE_READ));
5599 case OPERATION_NAME_READ_COPY_IMAGE_TO_BUFFER: return de::MovePtr<OperationSupport>(new CopyImageToBuffer ::Support (resourceDesc, ACCESS_MODE_READ));
5600 case OPERATION_NAME_READ_COPY_IMAGE: return de::MovePtr<OperationSupport>(new CopyBlitResolveImage::Support (resourceDesc, CopyBlitResolveImage::TYPE_COPY, ACCESS_MODE_READ));
5601 case OPERATION_NAME_READ_BLIT_IMAGE: return de::MovePtr<OperationSupport>(new CopyBlitResolveImage::Support (resourceDesc, CopyBlitResolveImage::TYPE_BLIT, ACCESS_MODE_READ));
5602 case OPERATION_NAME_READ_RESOLVE_IMAGE: return de::MovePtr<OperationSupport>(new CopyBlitResolveImage::Support (resourceDesc, CopyBlitResolveImage::TYPE_RESOLVE, ACCESS_MODE_READ));
5603 case OPERATION_NAME_READ_UBO_VERTEX: return de::MovePtr<OperationSupport>(new ShaderAccess ::BufferSupport (resourceDesc, BUFFER_TYPE_UNIFORM, ACCESS_MODE_READ, VK_SHADER_STAGE_VERTEX_BIT));
5604 case OPERATION_NAME_READ_UBO_TESSELLATION_CONTROL: return de::MovePtr<OperationSupport>(new ShaderAccess ::BufferSupport (resourceDesc, BUFFER_TYPE_UNIFORM, ACCESS_MODE_READ, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT));
5605 case OPERATION_NAME_READ_UBO_TESSELLATION_EVALUATION: return de::MovePtr<OperationSupport>(new ShaderAccess ::BufferSupport (resourceDesc, BUFFER_TYPE_UNIFORM, ACCESS_MODE_READ, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT));
5606 case OPERATION_NAME_READ_UBO_GEOMETRY: return de::MovePtr<OperationSupport>(new ShaderAccess ::BufferSupport (resourceDesc, BUFFER_TYPE_UNIFORM, ACCESS_MODE_READ, VK_SHADER_STAGE_GEOMETRY_BIT));
5607 case OPERATION_NAME_READ_UBO_FRAGMENT: return de::MovePtr<OperationSupport>(new ShaderAccess ::BufferSupport (resourceDesc, BUFFER_TYPE_UNIFORM, ACCESS_MODE_READ, VK_SHADER_STAGE_FRAGMENT_BIT));
5608 case OPERATION_NAME_READ_UBO_COMPUTE: return de::MovePtr<OperationSupport>(new ShaderAccess ::BufferSupport (resourceDesc, BUFFER_TYPE_UNIFORM, ACCESS_MODE_READ, VK_SHADER_STAGE_COMPUTE_BIT));
5609 case OPERATION_NAME_READ_UBO_COMPUTE_INDIRECT: return de::MovePtr<OperationSupport>(new ShaderAccess ::BufferSupport (resourceDesc, BUFFER_TYPE_UNIFORM, ACCESS_MODE_READ, VK_SHADER_STAGE_COMPUTE_BIT, ShaderAccess::DISPATCH_CALL_DISPATCH_INDIRECT));
5610 case OPERATION_NAME_READ_SSBO_VERTEX: return de::MovePtr<OperationSupport>(new ShaderAccess ::BufferSupport (resourceDesc, BUFFER_TYPE_STORAGE, ACCESS_MODE_READ, VK_SHADER_STAGE_VERTEX_BIT));
5611 case OPERATION_NAME_READ_SSBO_TESSELLATION_CONTROL: return de::MovePtr<OperationSupport>(new ShaderAccess ::BufferSupport (resourceDesc, BUFFER_TYPE_STORAGE, ACCESS_MODE_READ, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT));
5612 case OPERATION_NAME_READ_SSBO_TESSELLATION_EVALUATION: return de::MovePtr<OperationSupport>(new ShaderAccess ::BufferSupport (resourceDesc, BUFFER_TYPE_STORAGE, ACCESS_MODE_READ, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT));
5613 case OPERATION_NAME_READ_SSBO_GEOMETRY: return de::MovePtr<OperationSupport>(new ShaderAccess ::BufferSupport (resourceDesc, BUFFER_TYPE_STORAGE, ACCESS_MODE_READ, VK_SHADER_STAGE_GEOMETRY_BIT));
5614 case OPERATION_NAME_READ_SSBO_FRAGMENT: return de::MovePtr<OperationSupport>(new ShaderAccess ::BufferSupport (resourceDesc, BUFFER_TYPE_STORAGE, ACCESS_MODE_READ, VK_SHADER_STAGE_FRAGMENT_BIT));
5615 case OPERATION_NAME_READ_SSBO_COMPUTE: return de::MovePtr<OperationSupport>(new ShaderAccess ::BufferSupport (resourceDesc, BUFFER_TYPE_STORAGE, ACCESS_MODE_READ, VK_SHADER_STAGE_COMPUTE_BIT));
5616 case OPERATION_NAME_READ_SSBO_COMPUTE_INDIRECT: return de::MovePtr<OperationSupport>(new ShaderAccess ::BufferSupport (resourceDesc, BUFFER_TYPE_STORAGE, ACCESS_MODE_READ, VK_SHADER_STAGE_COMPUTE_BIT, ShaderAccess::DISPATCH_CALL_DISPATCH_INDIRECT));
5617 case OPERATION_NAME_READ_IMAGE_VERTEX: return de::MovePtr<OperationSupport>(new ShaderAccess ::ImageSupport (resourceDesc, ACCESS_MODE_READ, VK_SHADER_STAGE_VERTEX_BIT));
5618 case OPERATION_NAME_READ_IMAGE_TESSELLATION_CONTROL: return de::MovePtr<OperationSupport>(new ShaderAccess ::ImageSupport (resourceDesc, ACCESS_MODE_READ, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT));
5619 case OPERATION_NAME_READ_IMAGE_TESSELLATION_EVALUATION: return de::MovePtr<OperationSupport>(new ShaderAccess ::ImageSupport (resourceDesc, ACCESS_MODE_READ, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT));
5620 case OPERATION_NAME_READ_IMAGE_GEOMETRY: return de::MovePtr<OperationSupport>(new ShaderAccess ::ImageSupport (resourceDesc, ACCESS_MODE_READ, VK_SHADER_STAGE_GEOMETRY_BIT));
5621 case OPERATION_NAME_READ_IMAGE_FRAGMENT: return de::MovePtr<OperationSupport>(new ShaderAccess ::ImageSupport (resourceDesc, ACCESS_MODE_READ, VK_SHADER_STAGE_FRAGMENT_BIT));
5622 case OPERATION_NAME_READ_IMAGE_COMPUTE: return de::MovePtr<OperationSupport>(new ShaderAccess ::ImageSupport (resourceDesc, ACCESS_MODE_READ, VK_SHADER_STAGE_COMPUTE_BIT));
5623 case OPERATION_NAME_READ_IMAGE_COMPUTE_INDIRECT: return de::MovePtr<OperationSupport>(new ShaderAccess ::ImageSupport (resourceDesc, ACCESS_MODE_READ, VK_SHADER_STAGE_COMPUTE_BIT, ShaderAccess::DISPATCH_CALL_DISPATCH_INDIRECT));
5624 case OPERATION_NAME_READ_INDIRECT_BUFFER_DRAW: return de::MovePtr<OperationSupport>(new IndirectBuffer ::ReadSupport (resourceDesc));
5625 case OPERATION_NAME_READ_INDIRECT_BUFFER_DRAW_INDEXED: return de::MovePtr<OperationSupport>(new IndirectBuffer ::ReadSupport (resourceDesc));
5626 case OPERATION_NAME_READ_INDIRECT_BUFFER_DISPATCH: return de::MovePtr<OperationSupport>(new IndirectBuffer ::ReadSupport (resourceDesc));
5627 case OPERATION_NAME_READ_VERTEX_INPUT: return de::MovePtr<OperationSupport>(new VertexInput ::Support (resourceDesc, VertexInput::DRAW_MODE_VERTEX));
5628 case OPERATION_NAME_READ_INDEX_INPUT: return de::MovePtr<OperationSupport>(new VertexInput ::Support (resourceDesc, VertexInput::DRAW_MODE_INDEXED));
5629
5630 case OPERATION_NAME_COPY_BUFFER: return de::MovePtr<OperationSupport>(new CopyBuffer ::CopySupport (resourceDesc));
5631 case OPERATION_NAME_COPY_IMAGE: return de::MovePtr<OperationSupport>(new CopyBlitResolveImage::CopySupport (resourceDesc, CopyBlitResolveImage::TYPE_COPY));
5632 case OPERATION_NAME_BLIT_IMAGE: return de::MovePtr<OperationSupport>(new CopyBlitResolveImage::CopySupport (resourceDesc, CopyBlitResolveImage::TYPE_BLIT));
5633 case OPERATION_NAME_COPY_SSBO_VERTEX: return de::MovePtr<OperationSupport>(new ShaderAccess ::CopyBufferSupport (resourceDesc, BUFFER_TYPE_STORAGE, VK_SHADER_STAGE_VERTEX_BIT));
5634 case OPERATION_NAME_COPY_SSBO_TESSELLATION_CONTROL: return de::MovePtr<OperationSupport>(new ShaderAccess ::CopyBufferSupport (resourceDesc, BUFFER_TYPE_STORAGE, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT));
5635 case OPERATION_NAME_COPY_SSBO_TESSELLATION_EVALUATION: return de::MovePtr<OperationSupport>(new ShaderAccess ::CopyBufferSupport (resourceDesc, BUFFER_TYPE_STORAGE, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT));
5636 case OPERATION_NAME_COPY_SSBO_GEOMETRY: return de::MovePtr<OperationSupport>(new ShaderAccess ::CopyBufferSupport (resourceDesc, BUFFER_TYPE_STORAGE, VK_SHADER_STAGE_GEOMETRY_BIT));
5637 case OPERATION_NAME_COPY_SSBO_FRAGMENT: return de::MovePtr<OperationSupport>(new ShaderAccess ::CopyBufferSupport (resourceDesc, BUFFER_TYPE_STORAGE, VK_SHADER_STAGE_FRAGMENT_BIT));
5638 case OPERATION_NAME_COPY_SSBO_COMPUTE: return de::MovePtr<OperationSupport>(new ShaderAccess ::CopyBufferSupport (resourceDesc, BUFFER_TYPE_STORAGE, VK_SHADER_STAGE_COMPUTE_BIT));
5639 case OPERATION_NAME_COPY_SSBO_COMPUTE_INDIRECT: return de::MovePtr<OperationSupport>(new ShaderAccess ::CopyBufferSupport (resourceDesc, BUFFER_TYPE_STORAGE, VK_SHADER_STAGE_COMPUTE_BIT, ShaderAccess::DISPATCH_CALL_DISPATCH_INDIRECT));
5640 case OPERATION_NAME_COPY_IMAGE_VERTEX: return de::MovePtr<OperationSupport>(new ShaderAccess ::CopyImageSupport (resourceDesc, VK_SHADER_STAGE_VERTEX_BIT));
5641 case OPERATION_NAME_COPY_IMAGE_TESSELLATION_CONTROL: return de::MovePtr<OperationSupport>(new ShaderAccess ::CopyImageSupport (resourceDesc, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT));
5642 case OPERATION_NAME_COPY_IMAGE_TESSELLATION_EVALUATION: return de::MovePtr<OperationSupport>(new ShaderAccess ::CopyImageSupport (resourceDesc, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT));
5643 case OPERATION_NAME_COPY_IMAGE_GEOMETRY: return de::MovePtr<OperationSupport>(new ShaderAccess ::CopyImageSupport (resourceDesc, VK_SHADER_STAGE_GEOMETRY_BIT));
5644 case OPERATION_NAME_COPY_IMAGE_FRAGMENT: return de::MovePtr<OperationSupport>(new ShaderAccess ::CopyImageSupport (resourceDesc, VK_SHADER_STAGE_FRAGMENT_BIT));
5645 case OPERATION_NAME_COPY_IMAGE_COMPUTE: return de::MovePtr<OperationSupport>(new ShaderAccess ::CopyImageSupport (resourceDesc, VK_SHADER_STAGE_COMPUTE_BIT));
5646 case OPERATION_NAME_COPY_IMAGE_COMPUTE_INDIRECT: return de::MovePtr<OperationSupport>(new ShaderAccess ::CopyImageSupport (resourceDesc, VK_SHADER_STAGE_COMPUTE_BIT, ShaderAccess::DISPATCH_CALL_DISPATCH_INDIRECT));
5647
5648 default:
5649 DE_ASSERT(0);
5650 return de::MovePtr<OperationSupport>();
5651 }
5652 }
5653
5654 } // synchronization
5655 } // vkt
5656