1 /*-------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2015 Google 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 Pipeline barrier tests
22 *//*--------------------------------------------------------------------*/
23
24 #include "vktMemoryPipelineBarrierTests.hpp"
25
26 #include "vktTestCaseUtil.hpp"
27
28 #include "vkDefs.hpp"
29 #include "vkPlatform.hpp"
30 #include "vkRefUtil.hpp"
31 #include "vkQueryUtil.hpp"
32 #include "vkMemUtil.hpp"
33 #include "vkTypeUtil.hpp"
34 #include "vkPrograms.hpp"
35 #include "vkCmdUtil.hpp"
36 #include "vkObjUtil.hpp"
37
38 #include "tcuMaybe.hpp"
39 #include "tcuTextureUtil.hpp"
40 #include "tcuTestLog.hpp"
41 #include "tcuResultCollector.hpp"
42 #include "tcuTexture.hpp"
43 #include "tcuImageCompare.hpp"
44
45 #include "deUniquePtr.hpp"
46 #include "deStringUtil.hpp"
47 #include "deRandom.hpp"
48
49 #include "deInt32.h"
50 #include "deMath.h"
51 #include "deMemory.h"
52
53 #include <map>
54 #include <set>
55 #include <sstream>
56 #include <string>
57 #include <vector>
58
59 using tcu::TestLog;
60 using tcu::Maybe;
61
62 using de::MovePtr;
63
64 using std::string;
65 using std::vector;
66 using std::map;
67 using std::set;
68 using std::pair;
69
70 using tcu::IVec2;
71 using tcu::UVec2;
72 using tcu::UVec4;
73 using tcu::Vec4;
74 using tcu::ConstPixelBufferAccess;
75 using tcu::PixelBufferAccess;
76 using tcu::TextureFormat;
77 using tcu::TextureLevel;
78
79 namespace vkt
80 {
81 namespace memory
82 {
83 namespace
84 {
85
86 #define ONE_MEGABYTE 1024*1024
87 #define DEFAULT_VERTEX_BUFFER_STRIDE 2
88 #define ALTERNATIVE_VERTEX_BUFFER_STRIDE 4
89
90 enum
91 {
92 MAX_UNIFORM_BUFFER_SIZE = 1024,
93 MAX_STORAGE_BUFFER_SIZE = (1<<28),
94 MAX_SIZE = (128 * 1024)
95 };
96
97 // \todo [mika] Add to utilities
98 template<typename T>
divRoundUp(const T & a,const T & b)99 T divRoundUp (const T& a, const T& b)
100 {
101 return (a / b) + (a % b == 0 ? 0 : 1);
102 }
103
104 enum Usage
105 {
106 // Mapped host read and write
107 USAGE_HOST_READ = (0x1u<<0),
108 USAGE_HOST_WRITE = (0x1u<<1),
109
110 // Copy and other transfer operations
111 USAGE_TRANSFER_SRC = (0x1u<<2),
112 USAGE_TRANSFER_DST = (0x1u<<3),
113
114 // Buffer usage flags
115 USAGE_INDEX_BUFFER = (0x1u<<4),
116 USAGE_VERTEX_BUFFER = (0x1u<<5),
117
118 USAGE_UNIFORM_BUFFER = (0x1u<<6),
119 USAGE_STORAGE_BUFFER = (0x1u<<7),
120
121 USAGE_UNIFORM_TEXEL_BUFFER = (0x1u<<8),
122 USAGE_STORAGE_TEXEL_BUFFER = (0x1u<<9),
123
124 // \todo [2016-03-09 mika] This is probably almost impossible to do
125 USAGE_INDIRECT_BUFFER = (0x1u<<10),
126
127 // Texture usage flags
128 USAGE_SAMPLED_IMAGE = (0x1u<<11),
129 USAGE_STORAGE_IMAGE = (0x1u<<12),
130 USAGE_COLOR_ATTACHMENT = (0x1u<<13),
131 USAGE_INPUT_ATTACHMENT = (0x1u<<14),
132 USAGE_DEPTH_STENCIL_ATTACHMENT = (0x1u<<15),
133 };
134
supportsDeviceBufferWrites(Usage usage)135 bool supportsDeviceBufferWrites (Usage usage)
136 {
137 if (usage & USAGE_TRANSFER_DST)
138 return true;
139
140 if (usage & USAGE_STORAGE_BUFFER)
141 return true;
142
143 if (usage & USAGE_STORAGE_TEXEL_BUFFER)
144 return true;
145
146 return false;
147 }
148
supportsDeviceImageWrites(Usage usage)149 bool supportsDeviceImageWrites (Usage usage)
150 {
151 if (usage & USAGE_TRANSFER_DST)
152 return true;
153
154 if (usage & USAGE_STORAGE_IMAGE)
155 return true;
156
157 if (usage & USAGE_COLOR_ATTACHMENT)
158 return true;
159
160 return false;
161 }
162
163 // Sequential access enums
164 enum Access
165 {
166 ACCESS_INDIRECT_COMMAND_READ_BIT = 0,
167 ACCESS_INDEX_READ_BIT,
168 ACCESS_VERTEX_ATTRIBUTE_READ_BIT,
169 ACCESS_UNIFORM_READ_BIT,
170 ACCESS_INPUT_ATTACHMENT_READ_BIT,
171 ACCESS_SHADER_READ_BIT,
172 ACCESS_SHADER_WRITE_BIT,
173 ACCESS_COLOR_ATTACHMENT_READ_BIT,
174 ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
175 ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
176 ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
177 ACCESS_TRANSFER_READ_BIT,
178 ACCESS_TRANSFER_WRITE_BIT,
179 ACCESS_HOST_READ_BIT,
180 ACCESS_HOST_WRITE_BIT,
181 ACCESS_MEMORY_READ_BIT,
182 ACCESS_MEMORY_WRITE_BIT,
183
184 ACCESS_LAST
185 };
186
accessFlagToAccess(vk::VkAccessFlagBits flag)187 Access accessFlagToAccess (vk::VkAccessFlagBits flag)
188 {
189 switch (flag)
190 {
191 case vk::VK_ACCESS_INDIRECT_COMMAND_READ_BIT: return ACCESS_INDIRECT_COMMAND_READ_BIT;
192 case vk::VK_ACCESS_INDEX_READ_BIT: return ACCESS_INDEX_READ_BIT;
193 case vk::VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT: return ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
194 case vk::VK_ACCESS_UNIFORM_READ_BIT: return ACCESS_UNIFORM_READ_BIT;
195 case vk::VK_ACCESS_INPUT_ATTACHMENT_READ_BIT: return ACCESS_INPUT_ATTACHMENT_READ_BIT;
196 case vk::VK_ACCESS_SHADER_READ_BIT: return ACCESS_SHADER_READ_BIT;
197 case vk::VK_ACCESS_SHADER_WRITE_BIT: return ACCESS_SHADER_WRITE_BIT;
198 case vk::VK_ACCESS_COLOR_ATTACHMENT_READ_BIT: return ACCESS_COLOR_ATTACHMENT_READ_BIT;
199 case vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT: return ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
200 case vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT: return ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
201 case vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT: return ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
202 case vk::VK_ACCESS_TRANSFER_READ_BIT: return ACCESS_TRANSFER_READ_BIT;
203 case vk::VK_ACCESS_TRANSFER_WRITE_BIT: return ACCESS_TRANSFER_WRITE_BIT;
204 case vk::VK_ACCESS_HOST_READ_BIT: return ACCESS_HOST_READ_BIT;
205 case vk::VK_ACCESS_HOST_WRITE_BIT: return ACCESS_HOST_WRITE_BIT;
206 case vk::VK_ACCESS_MEMORY_READ_BIT: return ACCESS_MEMORY_READ_BIT;
207 case vk::VK_ACCESS_MEMORY_WRITE_BIT: return ACCESS_MEMORY_WRITE_BIT;
208
209 default:
210 DE_FATAL("Unknown access flags");
211 return ACCESS_LAST;
212 }
213 }
214
215 // Sequential stage enums
216 enum PipelineStage
217 {
218 PIPELINESTAGE_TOP_OF_PIPE_BIT = 0,
219 PIPELINESTAGE_BOTTOM_OF_PIPE_BIT,
220 PIPELINESTAGE_DRAW_INDIRECT_BIT,
221 PIPELINESTAGE_VERTEX_INPUT_BIT,
222 PIPELINESTAGE_VERTEX_SHADER_BIT,
223 PIPELINESTAGE_TESSELLATION_CONTROL_SHADER_BIT,
224 PIPELINESTAGE_TESSELLATION_EVALUATION_SHADER_BIT,
225 PIPELINESTAGE_GEOMETRY_SHADER_BIT,
226 PIPELINESTAGE_FRAGMENT_SHADER_BIT,
227 PIPELINESTAGE_EARLY_FRAGMENT_TESTS_BIT,
228 PIPELINESTAGE_LATE_FRAGMENT_TESTS_BIT,
229 PIPELINESTAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
230 PIPELINESTAGE_COMPUTE_SHADER_BIT,
231 PIPELINESTAGE_TRANSFER_BIT,
232 PIPELINESTAGE_HOST_BIT,
233
234 PIPELINESTAGE_LAST
235 };
236
pipelineStageFlagToPipelineStage(vk::VkPipelineStageFlagBits flag)237 PipelineStage pipelineStageFlagToPipelineStage (vk::VkPipelineStageFlagBits flag)
238 {
239 switch (flag)
240 {
241 case vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT: return PIPELINESTAGE_TOP_OF_PIPE_BIT;
242 case vk::VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT: return PIPELINESTAGE_BOTTOM_OF_PIPE_BIT;
243 case vk::VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT: return PIPELINESTAGE_DRAW_INDIRECT_BIT;
244 case vk::VK_PIPELINE_STAGE_VERTEX_INPUT_BIT: return PIPELINESTAGE_VERTEX_INPUT_BIT;
245 case vk::VK_PIPELINE_STAGE_VERTEX_SHADER_BIT: return PIPELINESTAGE_VERTEX_SHADER_BIT;
246 case vk::VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT: return PIPELINESTAGE_TESSELLATION_CONTROL_SHADER_BIT;
247 case vk::VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT: return PIPELINESTAGE_TESSELLATION_EVALUATION_SHADER_BIT;
248 case vk::VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT: return PIPELINESTAGE_GEOMETRY_SHADER_BIT;
249 case vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT: return PIPELINESTAGE_FRAGMENT_SHADER_BIT;
250 case vk::VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT: return PIPELINESTAGE_EARLY_FRAGMENT_TESTS_BIT;
251 case vk::VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT: return PIPELINESTAGE_LATE_FRAGMENT_TESTS_BIT;
252 case vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT: return PIPELINESTAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
253 case vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT: return PIPELINESTAGE_COMPUTE_SHADER_BIT;
254 case vk::VK_PIPELINE_STAGE_TRANSFER_BIT: return PIPELINESTAGE_TRANSFER_BIT;
255 case vk::VK_PIPELINE_STAGE_HOST_BIT: return PIPELINESTAGE_HOST_BIT;
256
257 default:
258 DE_FATAL("Unknown pipeline stage flags");
259 return PIPELINESTAGE_LAST;
260 }
261 }
262
operator |(Usage a,Usage b)263 Usage operator| (Usage a, Usage b)
264 {
265 return (Usage)((deUint32)a | (deUint32)b);
266 }
267
operator &(Usage a,Usage b)268 Usage operator& (Usage a, Usage b)
269 {
270 return (Usage)((deUint32)a & (deUint32)b);
271 }
272
usageToName(Usage usage)273 string usageToName (Usage usage)
274 {
275 const struct
276 {
277 Usage usage;
278 const char* const name;
279 } usageNames[] =
280 {
281 { USAGE_HOST_READ, "host_read" },
282 { USAGE_HOST_WRITE, "host_write" },
283
284 { USAGE_TRANSFER_SRC, "transfer_src" },
285 { USAGE_TRANSFER_DST, "transfer_dst" },
286
287 { USAGE_INDEX_BUFFER, "index_buffer" },
288 { USAGE_VERTEX_BUFFER, "vertex_buffer" },
289 { USAGE_UNIFORM_BUFFER, "uniform_buffer" },
290 { USAGE_STORAGE_BUFFER, "storage_buffer" },
291 { USAGE_UNIFORM_TEXEL_BUFFER, "uniform_texel_buffer" },
292 { USAGE_STORAGE_TEXEL_BUFFER, "storage_texel_buffer" },
293 { USAGE_INDIRECT_BUFFER, "indirect_buffer" },
294 { USAGE_SAMPLED_IMAGE, "image_sampled" },
295 { USAGE_STORAGE_IMAGE, "storage_image" },
296 { USAGE_COLOR_ATTACHMENT, "color_attachment" },
297 { USAGE_INPUT_ATTACHMENT, "input_attachment" },
298 { USAGE_DEPTH_STENCIL_ATTACHMENT, "depth_stencil_attachment" },
299 };
300
301 std::ostringstream stream;
302 bool first = true;
303
304 for (size_t usageNdx = 0; usageNdx < DE_LENGTH_OF_ARRAY(usageNames); usageNdx++)
305 {
306 if (usage & usageNames[usageNdx].usage)
307 {
308 if (!first)
309 stream << "_";
310 else
311 first = false;
312
313 stream << usageNames[usageNdx].name;
314 }
315 }
316
317 return stream.str();
318 }
319
usageToBufferUsageFlags(Usage usage)320 vk::VkBufferUsageFlags usageToBufferUsageFlags (Usage usage)
321 {
322 vk::VkBufferUsageFlags flags = 0;
323
324 if (usage & USAGE_TRANSFER_SRC)
325 flags |= vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
326
327 if (usage & USAGE_TRANSFER_DST)
328 flags |= vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
329
330 if (usage & USAGE_INDEX_BUFFER)
331 flags |= vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
332
333 if (usage & USAGE_VERTEX_BUFFER)
334 flags |= vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
335
336 if (usage & USAGE_INDIRECT_BUFFER)
337 flags |= vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT;
338
339 if (usage & USAGE_UNIFORM_BUFFER)
340 flags |= vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
341
342 if (usage & USAGE_STORAGE_BUFFER)
343 flags |= vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
344
345 if (usage & USAGE_UNIFORM_TEXEL_BUFFER)
346 flags |= vk::VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT;
347
348 if (usage & USAGE_STORAGE_TEXEL_BUFFER)
349 flags |= vk::VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
350
351 return flags;
352 }
353
usageToImageUsageFlags(Usage usage)354 vk::VkImageUsageFlags usageToImageUsageFlags (Usage usage)
355 {
356 vk::VkImageUsageFlags flags = 0;
357
358 if (usage & USAGE_TRANSFER_SRC)
359 flags |= vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
360
361 if (usage & USAGE_TRANSFER_DST)
362 flags |= vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT;
363
364 if (usage & USAGE_SAMPLED_IMAGE)
365 flags |= vk::VK_IMAGE_USAGE_SAMPLED_BIT;
366
367 if (usage & USAGE_STORAGE_IMAGE)
368 flags |= vk::VK_IMAGE_USAGE_STORAGE_BIT;
369
370 if (usage & USAGE_COLOR_ATTACHMENT)
371 flags |= vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
372
373 if (usage & USAGE_INPUT_ATTACHMENT)
374 flags |= vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
375
376 if (usage & USAGE_DEPTH_STENCIL_ATTACHMENT)
377 flags |= vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
378
379 return flags;
380 }
381
usageToStageFlags(Usage usage)382 vk::VkPipelineStageFlags usageToStageFlags (Usage usage)
383 {
384 vk::VkPipelineStageFlags flags = 0;
385
386 if (usage & (USAGE_HOST_READ|USAGE_HOST_WRITE))
387 flags |= vk::VK_PIPELINE_STAGE_HOST_BIT;
388
389 if (usage & (USAGE_TRANSFER_SRC|USAGE_TRANSFER_DST))
390 flags |= vk::VK_PIPELINE_STAGE_TRANSFER_BIT;
391
392 if (usage & (USAGE_VERTEX_BUFFER|USAGE_INDEX_BUFFER))
393 flags |= vk::VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
394
395 if (usage & USAGE_INDIRECT_BUFFER)
396 flags |= vk::VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT;
397
398 if (usage &
399 (USAGE_UNIFORM_BUFFER
400 | USAGE_STORAGE_BUFFER
401 | USAGE_UNIFORM_TEXEL_BUFFER
402 | USAGE_STORAGE_TEXEL_BUFFER
403 | USAGE_SAMPLED_IMAGE
404 | USAGE_STORAGE_IMAGE))
405 {
406 flags |= (vk::VK_PIPELINE_STAGE_VERTEX_SHADER_BIT
407 | vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
408 | vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
409 }
410
411 if (usage & USAGE_INPUT_ATTACHMENT)
412 flags |= vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
413
414 if (usage & USAGE_COLOR_ATTACHMENT)
415 flags |= vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
416
417 if (usage & USAGE_DEPTH_STENCIL_ATTACHMENT)
418 {
419 flags |= vk::VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
420 | vk::VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
421 }
422
423 return flags;
424 }
425
usageToAccessFlags(Usage usage)426 vk::VkAccessFlags usageToAccessFlags (Usage usage)
427 {
428 vk::VkAccessFlags flags = 0;
429
430 if (usage & USAGE_HOST_READ)
431 flags |= vk::VK_ACCESS_HOST_READ_BIT;
432
433 if (usage & USAGE_HOST_WRITE)
434 flags |= vk::VK_ACCESS_HOST_WRITE_BIT;
435
436 if (usage & USAGE_TRANSFER_SRC)
437 flags |= vk::VK_ACCESS_TRANSFER_READ_BIT;
438
439 if (usage & USAGE_TRANSFER_DST)
440 flags |= vk::VK_ACCESS_TRANSFER_WRITE_BIT;
441
442 if (usage & USAGE_INDEX_BUFFER)
443 flags |= vk::VK_ACCESS_INDEX_READ_BIT;
444
445 if (usage & USAGE_VERTEX_BUFFER)
446 flags |= vk::VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
447
448 if (usage & (USAGE_UNIFORM_BUFFER | USAGE_UNIFORM_TEXEL_BUFFER))
449 flags |= vk::VK_ACCESS_UNIFORM_READ_BIT;
450
451 if (usage & USAGE_SAMPLED_IMAGE)
452 flags |= vk::VK_ACCESS_SHADER_READ_BIT;
453
454 if (usage & (USAGE_STORAGE_BUFFER
455 | USAGE_STORAGE_TEXEL_BUFFER
456 | USAGE_STORAGE_IMAGE))
457 flags |= vk::VK_ACCESS_SHADER_READ_BIT | vk::VK_ACCESS_SHADER_WRITE_BIT;
458
459 if (usage & USAGE_INDIRECT_BUFFER)
460 flags |= vk::VK_ACCESS_INDIRECT_COMMAND_READ_BIT;
461
462 if (usage & USAGE_COLOR_ATTACHMENT)
463 flags |= vk::VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
464
465 if (usage & USAGE_INPUT_ATTACHMENT)
466 flags |= vk::VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
467
468 if (usage & USAGE_DEPTH_STENCIL_ATTACHMENT)
469 flags |= vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT
470 | vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
471
472 return flags;
473 }
474
475 struct TestConfig
476 {
477 Usage usage;
478 deUint32 vertexBufferStride;
479 vk::VkDeviceSize size;
480 vk::VkSharingMode sharing;
481 };
482
createBeginCommandBuffer(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkCommandPool pool,vk::VkCommandBufferLevel level)483 vk::Move<vk::VkCommandBuffer> createBeginCommandBuffer (const vk::DeviceInterface& vkd,
484 vk::VkDevice device,
485 vk::VkCommandPool pool,
486 vk::VkCommandBufferLevel level)
487 {
488 const vk::VkCommandBufferInheritanceInfo inheritInfo =
489 {
490 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
491 DE_NULL,
492 0,
493 0,
494 0,
495 VK_FALSE,
496 0u,
497 0u
498 };
499 const vk::VkCommandBufferBeginInfo beginInfo =
500 {
501 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
502 DE_NULL,
503 0u,
504 (level == vk::VK_COMMAND_BUFFER_LEVEL_SECONDARY ? &inheritInfo : (const vk::VkCommandBufferInheritanceInfo*)DE_NULL),
505 };
506
507 vk::Move<vk::VkCommandBuffer> commandBuffer (allocateCommandBuffer(vkd, device, pool, level));
508
509 vkd.beginCommandBuffer(*commandBuffer, &beginInfo);
510
511 return commandBuffer;
512 }
513
createBuffer(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkDeviceSize size,vk::VkBufferUsageFlags usage,vk::VkSharingMode sharingMode,const vector<deUint32> & queueFamilies)514 vk::Move<vk::VkBuffer> createBuffer (const vk::DeviceInterface& vkd,
515 vk::VkDevice device,
516 vk::VkDeviceSize size,
517 vk::VkBufferUsageFlags usage,
518 vk::VkSharingMode sharingMode,
519 const vector<deUint32>& queueFamilies)
520 {
521 const vk::VkBufferCreateInfo createInfo =
522 {
523 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
524 DE_NULL,
525
526 0, // flags
527 size,
528 usage,
529 sharingMode,
530 (deUint32)queueFamilies.size(),
531 &queueFamilies[0]
532 };
533
534 return vk::createBuffer(vkd, device, &createInfo);
535 }
536
allocMemory(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkDeviceSize size,deUint32 memoryTypeIndex)537 vk::Move<vk::VkDeviceMemory> allocMemory (const vk::DeviceInterface& vkd,
538 vk::VkDevice device,
539 vk::VkDeviceSize size,
540 deUint32 memoryTypeIndex)
541 {
542 const vk::VkMemoryAllocateInfo alloc =
543 {
544 vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // sType
545 DE_NULL, // pNext
546
547 size,
548 memoryTypeIndex
549 };
550
551 return vk::allocateMemory(vkd, device, &alloc);
552 }
553
bindBufferMemory(const vk::InstanceInterface & vki,const vk::DeviceInterface & vkd,vk::VkPhysicalDevice physicalDevice,vk::VkDevice device,vk::VkBuffer buffer,vk::VkMemoryPropertyFlags properties)554 vk::Move<vk::VkDeviceMemory> bindBufferMemory (const vk::InstanceInterface& vki,
555 const vk::DeviceInterface& vkd,
556 vk::VkPhysicalDevice physicalDevice,
557 vk::VkDevice device,
558 vk::VkBuffer buffer,
559 vk::VkMemoryPropertyFlags properties)
560 {
561 const vk::VkMemoryRequirements memoryRequirements = vk::getBufferMemoryRequirements(vkd, device, buffer);
562 const vk::VkPhysicalDeviceMemoryProperties memoryProperties = vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice);
563 deUint32 memoryTypeIndex;
564
565 for (memoryTypeIndex = 0; memoryTypeIndex < memoryProperties.memoryTypeCount; memoryTypeIndex++)
566 {
567 if ((memoryRequirements.memoryTypeBits & (0x1u << memoryTypeIndex))
568 && (memoryProperties.memoryTypes[memoryTypeIndex].propertyFlags & properties) == properties)
569 {
570 try
571 {
572 const vk::VkMemoryAllocateInfo allocationInfo =
573 {
574 vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
575 DE_NULL,
576 memoryRequirements.size,
577 memoryTypeIndex
578 };
579 vk::Move<vk::VkDeviceMemory> memory (vk::allocateMemory(vkd, device, &allocationInfo));
580
581 VK_CHECK(vkd.bindBufferMemory(device, buffer, *memory, 0));
582
583 return memory;
584 }
585 catch (const vk::Error& error)
586 {
587 if (error.getError() == vk::VK_ERROR_OUT_OF_DEVICE_MEMORY
588 || error.getError() == vk::VK_ERROR_OUT_OF_HOST_MEMORY)
589 {
590 // Try next memory type/heap if out of memory
591 }
592 else
593 {
594 // Throw all other errors forward
595 throw;
596 }
597 }
598 }
599 }
600
601 TCU_FAIL("Failed to allocate memory for buffer");
602 }
603
bindImageMemory(const vk::InstanceInterface & vki,const vk::DeviceInterface & vkd,vk::VkPhysicalDevice physicalDevice,vk::VkDevice device,vk::VkImage image,vk::VkMemoryPropertyFlags properties)604 vk::Move<vk::VkDeviceMemory> bindImageMemory (const vk::InstanceInterface& vki,
605 const vk::DeviceInterface& vkd,
606 vk::VkPhysicalDevice physicalDevice,
607 vk::VkDevice device,
608 vk::VkImage image,
609 vk::VkMemoryPropertyFlags properties)
610 {
611 const vk::VkMemoryRequirements memoryRequirements = vk::getImageMemoryRequirements(vkd, device, image);
612 const vk::VkPhysicalDeviceMemoryProperties memoryProperties = vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice);
613 deUint32 memoryTypeIndex;
614
615 for (memoryTypeIndex = 0; memoryTypeIndex < memoryProperties.memoryTypeCount; memoryTypeIndex++)
616 {
617 if ((memoryRequirements.memoryTypeBits & (0x1u << memoryTypeIndex))
618 && (memoryProperties.memoryTypes[memoryTypeIndex].propertyFlags & properties) == properties)
619 {
620 try
621 {
622 const vk::VkMemoryAllocateInfo allocationInfo =
623 {
624 vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
625 DE_NULL,
626 memoryRequirements.size,
627 memoryTypeIndex
628 };
629 vk::Move<vk::VkDeviceMemory> memory (vk::allocateMemory(vkd, device, &allocationInfo));
630
631 VK_CHECK(vkd.bindImageMemory(device, image, *memory, 0));
632
633 return memory;
634 }
635 catch (const vk::Error& error)
636 {
637 if (error.getError() == vk::VK_ERROR_OUT_OF_DEVICE_MEMORY
638 || error.getError() == vk::VK_ERROR_OUT_OF_HOST_MEMORY)
639 {
640 // Try next memory type/heap if out of memory
641 }
642 else
643 {
644 // Throw all other errors forward
645 throw;
646 }
647 }
648 }
649 }
650
651 TCU_FAIL("Failed to allocate memory for image");
652 }
653
mapMemory(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkDeviceMemory memory,vk::VkDeviceSize size)654 void* mapMemory (const vk::DeviceInterface& vkd,
655 vk::VkDevice device,
656 vk::VkDeviceMemory memory,
657 vk::VkDeviceSize size)
658 {
659 void* ptr;
660
661 VK_CHECK(vkd.mapMemory(device, memory, 0, size, 0, &ptr));
662
663 return ptr;
664 }
665
666 class ReferenceMemory
667 {
668 public:
669 ReferenceMemory (size_t size);
670
671 void set (size_t pos, deUint8 val);
672 deUint8 get (size_t pos) const;
673 bool isDefined (size_t pos) const;
674
675 void setDefined (size_t offset, size_t size, const void* data);
676 void setUndefined (size_t offset, size_t size);
677 void setData (size_t offset, size_t size, const void* data);
678
getSize(void) const679 size_t getSize (void) const { return m_data.size(); }
680
681 private:
682 vector<deUint8> m_data;
683 vector<deUint64> m_defined;
684 };
685
ReferenceMemory(size_t size)686 ReferenceMemory::ReferenceMemory (size_t size)
687 : m_data (size, 0)
688 , m_defined (size / 64 + (size % 64 == 0 ? 0 : 1), 0ull)
689 {
690 }
691
set(size_t pos,deUint8 val)692 void ReferenceMemory::set (size_t pos, deUint8 val)
693 {
694 DE_ASSERT(pos < m_data.size());
695
696 m_data[pos] = val;
697 m_defined[pos / 64] |= 0x1ull << (pos % 64);
698 }
699
setData(size_t offset,size_t size,const void * data_)700 void ReferenceMemory::setData (size_t offset, size_t size, const void* data_)
701 {
702 const deUint8* data = (const deUint8*)data_;
703
704 DE_ASSERT(offset < m_data.size());
705 DE_ASSERT(offset + size <= m_data.size());
706
707 // \todo [2016-03-09 mika] Optimize
708 for (size_t pos = 0; pos < size; pos++)
709 {
710 m_data[offset + pos] = data[pos];
711 m_defined[(offset + pos) / 64] |= 0x1ull << ((offset + pos) % 64);
712 }
713 }
714
setUndefined(size_t offset,size_t size)715 void ReferenceMemory::setUndefined (size_t offset, size_t size)
716 {
717 // \todo [2016-03-09 mika] Optimize
718 for (size_t pos = 0; pos < size; pos++)
719 m_defined[(offset + pos) / 64] |= 0x1ull << ((offset + pos) % 64);
720 }
721
get(size_t pos) const722 deUint8 ReferenceMemory::get (size_t pos) const
723 {
724 DE_ASSERT(pos < m_data.size());
725 DE_ASSERT(isDefined(pos));
726 return m_data[pos];
727 }
728
isDefined(size_t pos) const729 bool ReferenceMemory::isDefined (size_t pos) const
730 {
731 DE_ASSERT(pos < m_data.size());
732
733 return (m_defined[pos / 64] & (0x1ull << (pos % 64))) != 0;
734 }
735
736 class Memory
737 {
738 public:
739 Memory (const vk::InstanceInterface& vki,
740 const vk::DeviceInterface& vkd,
741 vk::VkPhysicalDevice physicalDevice,
742 vk::VkDevice device,
743 vk::VkDeviceSize size,
744 deUint32 memoryTypeIndex,
745 vk::VkDeviceSize maxBufferSize,
746 deInt32 maxImageWidth,
747 deInt32 maxImageHeight);
748
getSize(void) const749 vk::VkDeviceSize getSize (void) const { return m_size; }
getMaxBufferSize(void) const750 vk::VkDeviceSize getMaxBufferSize (void) const { return m_maxBufferSize; }
getSupportBuffers(void) const751 bool getSupportBuffers (void) const { return m_maxBufferSize > 0; }
752
getMaxImageWidth(void) const753 deInt32 getMaxImageWidth (void) const { return m_maxImageWidth; }
getMaxImageHeight(void) const754 deInt32 getMaxImageHeight (void) const { return m_maxImageHeight; }
getSupportImages(void) const755 bool getSupportImages (void) const { return m_maxImageWidth > 0; }
756
getMemoryType(void) const757 const vk::VkMemoryType& getMemoryType (void) const { return m_memoryType; }
getMemoryTypeIndex(void) const758 deUint32 getMemoryTypeIndex (void) const { return m_memoryTypeIndex; }
getMemory(void) const759 vk::VkDeviceMemory getMemory (void) const { return *m_memory; }
760
761 private:
762 const vk::VkDeviceSize m_size;
763 const deUint32 m_memoryTypeIndex;
764 const vk::VkMemoryType m_memoryType;
765 const vk::Unique<vk::VkDeviceMemory> m_memory;
766 const vk::VkDeviceSize m_maxBufferSize;
767 const deInt32 m_maxImageWidth;
768 const deInt32 m_maxImageHeight;
769 };
770
getMemoryTypeInfo(const vk::InstanceInterface & vki,vk::VkPhysicalDevice device,deUint32 memoryTypeIndex)771 vk::VkMemoryType getMemoryTypeInfo (const vk::InstanceInterface& vki,
772 vk::VkPhysicalDevice device,
773 deUint32 memoryTypeIndex)
774 {
775 const vk::VkPhysicalDeviceMemoryProperties memoryProperties = vk::getPhysicalDeviceMemoryProperties(vki, device);
776
777 DE_ASSERT(memoryTypeIndex < memoryProperties.memoryTypeCount);
778
779 return memoryProperties.memoryTypes[memoryTypeIndex];
780 }
781
findMaxBufferSize(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkBufferUsageFlags usage,vk::VkSharingMode sharingMode,const vector<deUint32> & queueFamilies,vk::VkDeviceSize memorySize,deUint32 memoryTypeIndex)782 vk::VkDeviceSize findMaxBufferSize (const vk::DeviceInterface& vkd,
783 vk::VkDevice device,
784
785 vk::VkBufferUsageFlags usage,
786 vk::VkSharingMode sharingMode,
787 const vector<deUint32>& queueFamilies,
788
789 vk::VkDeviceSize memorySize,
790 deUint32 memoryTypeIndex)
791 {
792 vk::VkDeviceSize lastSuccess = 0;
793 vk::VkDeviceSize currentSize = memorySize / 2;
794
795 {
796 const vk::Unique<vk::VkBuffer> buffer (createBuffer(vkd, device, memorySize, usage, sharingMode, queueFamilies));
797 const vk::VkMemoryRequirements requirements (vk::getBufferMemoryRequirements(vkd, device, *buffer));
798
799 if (requirements.size == memorySize && requirements.memoryTypeBits & (0x1u << memoryTypeIndex))
800 return memorySize;
801 }
802
803 for (vk::VkDeviceSize stepSize = memorySize / 4; currentSize > 0; stepSize /= 2)
804 {
805 const vk::Unique<vk::VkBuffer> buffer (createBuffer(vkd, device, currentSize, usage, sharingMode, queueFamilies));
806 const vk::VkMemoryRequirements requirements (vk::getBufferMemoryRequirements(vkd, device, *buffer));
807
808 if (requirements.size <= memorySize && requirements.memoryTypeBits & (0x1u << memoryTypeIndex))
809 {
810 lastSuccess = currentSize;
811 currentSize += stepSize;
812 }
813 else
814 currentSize -= stepSize;
815
816 if (stepSize == 0)
817 break;
818 }
819
820 return lastSuccess;
821 }
822
823 // Round size down maximum W * H * 4, where W and H < 4096
roundBufferSizeToWxHx4(vk::VkDeviceSize size)824 vk::VkDeviceSize roundBufferSizeToWxHx4 (vk::VkDeviceSize size)
825 {
826 const vk::VkDeviceSize maxTextureSize = 4096;
827 vk::VkDeviceSize maxTexelCount = size / 4;
828 vk::VkDeviceSize bestW = de::max(maxTexelCount, maxTextureSize);
829 vk::VkDeviceSize bestH = maxTexelCount / bestW;
830
831 // \todo [2016-03-09 mika] Could probably be faster?
832 for (vk::VkDeviceSize w = 1; w * w < maxTexelCount && w < maxTextureSize && bestW * bestH * 4 < size; w++)
833 {
834 const vk::VkDeviceSize h = maxTexelCount / w;
835
836 if (bestW * bestH < w * h)
837 {
838 bestW = w;
839 bestH = h;
840 }
841 }
842
843 return bestW * bestH * 4;
844 }
845
846 // Find RGBA8 image size that has exactly "size" of number of bytes.
847 // "size" must be W * H * 4 where W and H < 4096
findImageSizeWxHx4(vk::VkDeviceSize size)848 IVec2 findImageSizeWxHx4 (vk::VkDeviceSize size)
849 {
850 const vk::VkDeviceSize maxTextureSize = 4096;
851 vk::VkDeviceSize texelCount = size / 4;
852
853 DE_ASSERT((size % 4) == 0);
854
855 // \todo [2016-03-09 mika] Could probably be faster?
856 for (vk::VkDeviceSize w = 1; w < maxTextureSize && w < texelCount; w++)
857 {
858 const vk::VkDeviceSize h = texelCount / w;
859
860 if ((texelCount % w) == 0 && h < maxTextureSize)
861 return IVec2((int)w, (int)h);
862 }
863
864 DE_FATAL("Invalid size");
865 return IVec2(-1, -1);
866 }
867
findMaxRGBA8ImageSize(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkImageUsageFlags usage,vk::VkSharingMode sharingMode,const vector<deUint32> & queueFamilies,vk::VkDeviceSize memorySize,deUint32 memoryTypeIndex)868 IVec2 findMaxRGBA8ImageSize (const vk::DeviceInterface& vkd,
869 vk::VkDevice device,
870
871 vk::VkImageUsageFlags usage,
872 vk::VkSharingMode sharingMode,
873 const vector<deUint32>& queueFamilies,
874
875 vk::VkDeviceSize memorySize,
876 deUint32 memoryTypeIndex)
877 {
878 IVec2 lastSuccess (0);
879 IVec2 currentSize;
880
881 {
882 const deUint32 texelCount = (deUint32)(memorySize / 4);
883 const deUint32 width = (deUint32)deFloatSqrt((float)texelCount);
884 const deUint32 height = texelCount / width;
885
886 currentSize[0] = deMaxu32(width, height);
887 currentSize[1] = deMinu32(width, height);
888 }
889
890 for (deInt32 stepSize = currentSize[0] / 2; currentSize[0] > 0; stepSize /= 2)
891 {
892 const vk::VkImageCreateInfo createInfo =
893 {
894 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
895 DE_NULL,
896
897 0u,
898 vk::VK_IMAGE_TYPE_2D,
899 vk::VK_FORMAT_R8G8B8A8_UNORM,
900 {
901 (deUint32)currentSize[0],
902 (deUint32)currentSize[1],
903 1u,
904 },
905 1u, 1u,
906 vk::VK_SAMPLE_COUNT_1_BIT,
907 vk::VK_IMAGE_TILING_OPTIMAL,
908 usage,
909 sharingMode,
910 (deUint32)queueFamilies.size(),
911 &queueFamilies[0],
912 vk::VK_IMAGE_LAYOUT_UNDEFINED
913 };
914 const vk::Unique<vk::VkImage> image (vk::createImage(vkd, device, &createInfo));
915 const vk::VkMemoryRequirements requirements (vk::getImageMemoryRequirements(vkd, device, *image));
916
917 if (requirements.size <= memorySize && requirements.memoryTypeBits & (0x1u << memoryTypeIndex))
918 {
919 lastSuccess = currentSize;
920 currentSize[0] += stepSize;
921 currentSize[1] += stepSize;
922 }
923 else
924 {
925 currentSize[0] -= stepSize;
926 currentSize[1] -= stepSize;
927 }
928
929 if (stepSize == 0)
930 break;
931 }
932
933 return lastSuccess;
934 }
935
Memory(const vk::InstanceInterface & vki,const vk::DeviceInterface & vkd,vk::VkPhysicalDevice physicalDevice,vk::VkDevice device,vk::VkDeviceSize size,deUint32 memoryTypeIndex,vk::VkDeviceSize maxBufferSize,deInt32 maxImageWidth,deInt32 maxImageHeight)936 Memory::Memory (const vk::InstanceInterface& vki,
937 const vk::DeviceInterface& vkd,
938 vk::VkPhysicalDevice physicalDevice,
939 vk::VkDevice device,
940 vk::VkDeviceSize size,
941 deUint32 memoryTypeIndex,
942 vk::VkDeviceSize maxBufferSize,
943 deInt32 maxImageWidth,
944 deInt32 maxImageHeight)
945 : m_size (size)
946 , m_memoryTypeIndex (memoryTypeIndex)
947 , m_memoryType (getMemoryTypeInfo(vki, physicalDevice, memoryTypeIndex))
948 , m_memory (allocMemory(vkd, device, size, memoryTypeIndex))
949 , m_maxBufferSize (maxBufferSize)
950 , m_maxImageWidth (maxImageWidth)
951 , m_maxImageHeight (maxImageHeight)
952 {
953 }
954
955 class Context
956 {
957 public:
Context(const vk::InstanceInterface & vki,const vk::DeviceInterface & vkd,vk::VkPhysicalDevice physicalDevice,vk::VkDevice device,vk::VkQueue queue,deUint32 queueFamilyIndex,const vector<pair<deUint32,vk::VkQueue>> & queues,const vk::BinaryCollection & binaryCollection)958 Context (const vk::InstanceInterface& vki,
959 const vk::DeviceInterface& vkd,
960 vk::VkPhysicalDevice physicalDevice,
961 vk::VkDevice device,
962 vk::VkQueue queue,
963 deUint32 queueFamilyIndex,
964 const vector<pair<deUint32, vk::VkQueue> >& queues,
965 const vk::BinaryCollection& binaryCollection)
966 : m_vki (vki)
967 , m_vkd (vkd)
968 , m_physicalDevice (physicalDevice)
969 , m_device (device)
970 , m_queue (queue)
971 , m_queueFamilyIndex (queueFamilyIndex)
972 , m_queues (queues)
973 , m_commandPool (createCommandPool(vkd, device, vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex))
974 , m_binaryCollection (binaryCollection)
975 {
976 for (size_t queueNdx = 0; queueNdx < m_queues.size(); queueNdx++)
977 m_queueFamilies.push_back(m_queues[queueNdx].first);
978 }
979
getInstanceInterface(void) const980 const vk::InstanceInterface& getInstanceInterface (void) const { return m_vki; }
getPhysicalDevice(void) const981 vk::VkPhysicalDevice getPhysicalDevice (void) const { return m_physicalDevice; }
getDevice(void) const982 vk::VkDevice getDevice (void) const { return m_device; }
getDeviceInterface(void) const983 const vk::DeviceInterface& getDeviceInterface (void) const { return m_vkd; }
getQueue(void) const984 vk::VkQueue getQueue (void) const { return m_queue; }
getQueueFamily(void) const985 deUint32 getQueueFamily (void) const { return m_queueFamilyIndex; }
getQueues(void) const986 const vector<pair<deUint32, vk::VkQueue> >& getQueues (void) const { return m_queues; }
getQueueFamilies(void) const987 const vector<deUint32> getQueueFamilies (void) const { return m_queueFamilies; }
getCommandPool(void) const988 vk::VkCommandPool getCommandPool (void) const { return *m_commandPool; }
getBinaryCollection(void) const989 const vk::BinaryCollection& getBinaryCollection (void) const { return m_binaryCollection; }
990
991 private:
992 const vk::InstanceInterface& m_vki;
993 const vk::DeviceInterface& m_vkd;
994 const vk::VkPhysicalDevice m_physicalDevice;
995 const vk::VkDevice m_device;
996 const vk::VkQueue m_queue;
997 const deUint32 m_queueFamilyIndex;
998 const vector<pair<deUint32, vk::VkQueue> > m_queues;
999 const vk::Unique<vk::VkCommandPool> m_commandPool;
1000 const vk::BinaryCollection& m_binaryCollection;
1001 vector<deUint32> m_queueFamilies;
1002 };
1003
1004 class PrepareContext
1005 {
1006 public:
PrepareContext(const Context & context,const Memory & memory)1007 PrepareContext (const Context& context,
1008 const Memory& memory)
1009 : m_context (context)
1010 , m_memory (memory)
1011 {
1012 }
1013
getMemory(void) const1014 const Memory& getMemory (void) const { return m_memory; }
getContext(void) const1015 const Context& getContext (void) const { return m_context; }
getBinaryCollection(void) const1016 const vk::BinaryCollection& getBinaryCollection (void) const { return m_context.getBinaryCollection(); }
1017
setBuffer(vk::Move<vk::VkBuffer> buffer,vk::VkDeviceSize size)1018 void setBuffer (vk::Move<vk::VkBuffer> buffer,
1019 vk::VkDeviceSize size)
1020 {
1021 DE_ASSERT(!m_currentImage);
1022 DE_ASSERT(!m_currentBuffer);
1023
1024 m_currentBuffer = buffer;
1025 m_currentBufferSize = size;
1026 }
1027
getBuffer(void) const1028 vk::VkBuffer getBuffer (void) const { return *m_currentBuffer; }
getBufferSize(void) const1029 vk::VkDeviceSize getBufferSize (void) const
1030 {
1031 DE_ASSERT(m_currentBuffer);
1032 return m_currentBufferSize;
1033 }
1034
releaseBuffer(void)1035 void releaseBuffer (void) { m_currentBuffer.disown(); }
1036
setImage(vk::Move<vk::VkImage> image,vk::VkImageLayout layout,vk::VkDeviceSize memorySize,deInt32 width,deInt32 height)1037 void setImage (vk::Move<vk::VkImage> image,
1038 vk::VkImageLayout layout,
1039 vk::VkDeviceSize memorySize,
1040 deInt32 width,
1041 deInt32 height)
1042 {
1043 DE_ASSERT(!m_currentImage);
1044 DE_ASSERT(!m_currentBuffer);
1045
1046 m_currentImage = image;
1047 m_currentImageMemorySize = memorySize;
1048 m_currentImageLayout = layout;
1049 m_currentImageWidth = width;
1050 m_currentImageHeight = height;
1051 }
1052
setImageLayout(vk::VkImageLayout layout)1053 void setImageLayout (vk::VkImageLayout layout)
1054 {
1055 DE_ASSERT(m_currentImage);
1056 m_currentImageLayout = layout;
1057 }
1058
getImage(void) const1059 vk::VkImage getImage (void) const { return *m_currentImage; }
getImageWidth(void) const1060 deInt32 getImageWidth (void) const
1061 {
1062 DE_ASSERT(m_currentImage);
1063 return m_currentImageWidth;
1064 }
getImageHeight(void) const1065 deInt32 getImageHeight (void) const
1066 {
1067 DE_ASSERT(m_currentImage);
1068 return m_currentImageHeight;
1069 }
getImageMemorySize(void) const1070 vk::VkDeviceSize getImageMemorySize (void) const
1071 {
1072 DE_ASSERT(m_currentImage);
1073 return m_currentImageMemorySize;
1074 }
1075
releaseImage(void)1076 void releaseImage (void) { m_currentImage.disown(); }
1077
getImageLayout(void) const1078 vk::VkImageLayout getImageLayout (void) const
1079 {
1080 DE_ASSERT(m_currentImage);
1081 return m_currentImageLayout;
1082 }
1083
1084 private:
1085 const Context& m_context;
1086 const Memory& m_memory;
1087
1088 vk::Move<vk::VkBuffer> m_currentBuffer;
1089 vk::VkDeviceSize m_currentBufferSize;
1090
1091 vk::Move<vk::VkImage> m_currentImage;
1092 vk::VkDeviceSize m_currentImageMemorySize;
1093 vk::VkImageLayout m_currentImageLayout;
1094 deInt32 m_currentImageWidth;
1095 deInt32 m_currentImageHeight;
1096 };
1097
1098 class ExecuteContext
1099 {
1100 public:
ExecuteContext(const Context & context)1101 ExecuteContext (const Context& context)
1102 : m_context (context)
1103 {
1104 }
1105
getContext(void) const1106 const Context& getContext (void) const { return m_context; }
setMapping(void * ptr)1107 void setMapping (void* ptr) { m_mapping = ptr; }
getMapping(void) const1108 void* getMapping (void) const { return m_mapping; }
1109
1110 private:
1111 const Context& m_context;
1112 void* m_mapping;
1113 };
1114
1115 class VerifyContext
1116 {
1117 public:
VerifyContext(TestLog & log,tcu::ResultCollector & resultCollector,const Context & context,vk::VkDeviceSize size)1118 VerifyContext (TestLog& log,
1119 tcu::ResultCollector& resultCollector,
1120 const Context& context,
1121 vk::VkDeviceSize size)
1122 : m_log (log)
1123 , m_resultCollector (resultCollector)
1124 , m_context (context)
1125 , m_reference ((size_t)size)
1126 {
1127 }
1128
getContext(void) const1129 const Context& getContext (void) const { return m_context; }
getLog(void) const1130 TestLog& getLog (void) const { return m_log; }
getResultCollector(void) const1131 tcu::ResultCollector& getResultCollector (void) const { return m_resultCollector; }
1132
getReference(void)1133 ReferenceMemory& getReference (void) { return m_reference; }
getReferenceImage(void)1134 TextureLevel& getReferenceImage (void) { return m_referenceImage;}
1135
1136 private:
1137 TestLog& m_log;
1138 tcu::ResultCollector& m_resultCollector;
1139 const Context& m_context;
1140 ReferenceMemory m_reference;
1141 TextureLevel m_referenceImage;
1142 };
1143
1144 class Command
1145 {
1146 public:
1147 // Constructor should allocate all non-vulkan resources.
~Command(void)1148 virtual ~Command (void) {}
1149
1150 // Get name of the command
1151 virtual const char* getName (void) const = 0;
1152
1153 // Log prepare operations
logPrepare(TestLog &,size_t) const1154 virtual void logPrepare (TestLog&, size_t) const {}
1155 // Log executed operations
logExecute(TestLog &,size_t) const1156 virtual void logExecute (TestLog&, size_t) const {}
1157
1158 // Prepare should allocate all vulkan resources and resources that require
1159 // that buffer or memory has been already allocated. This should build all
1160 // command buffers etc.
prepare(PrepareContext &)1161 virtual void prepare (PrepareContext&) {}
1162
1163 // Execute command. Write or read mapped memory, submit commands to queue
1164 // etc.
execute(ExecuteContext &)1165 virtual void execute (ExecuteContext&) {}
1166
1167 // Verify that results are correct.
verify(VerifyContext &,size_t)1168 virtual void verify (VerifyContext&, size_t) {}
1169
1170 protected:
1171 // Allow only inheritance
Command(void)1172 Command (void) {}
1173
1174 private:
1175 // Disallow copying
1176 Command (const Command&);
1177 Command& operator& (const Command&);
1178 };
1179
1180 class Map : public Command
1181 {
1182 public:
Map(void)1183 Map (void) {}
~Map(void)1184 ~Map (void) {}
getName(void) const1185 const char* getName (void) const { return "Map"; }
1186
1187
logExecute(TestLog & log,size_t commandIndex) const1188 void logExecute (TestLog& log, size_t commandIndex) const
1189 {
1190 log << TestLog::Message << commandIndex << ":" << getName() << " Map memory" << TestLog::EndMessage;
1191 }
1192
prepare(PrepareContext & context)1193 void prepare (PrepareContext& context)
1194 {
1195 m_memory = context.getMemory().getMemory();
1196 m_size = context.getMemory().getSize();
1197 }
1198
execute(ExecuteContext & context)1199 void execute (ExecuteContext& context)
1200 {
1201 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
1202 const vk::VkDevice device = context.getContext().getDevice();
1203
1204 context.setMapping(mapMemory(vkd, device, m_memory, m_size));
1205 }
1206
1207 private:
1208 vk::VkDeviceMemory m_memory;
1209 vk::VkDeviceSize m_size;
1210 };
1211
1212 class UnMap : public Command
1213 {
1214 public:
UnMap(void)1215 UnMap (void) {}
~UnMap(void)1216 ~UnMap (void) {}
getName(void) const1217 const char* getName (void) const { return "UnMap"; }
1218
logExecute(TestLog & log,size_t commandIndex) const1219 void logExecute (TestLog& log, size_t commandIndex) const
1220 {
1221 log << TestLog::Message << commandIndex << ": Unmap memory" << TestLog::EndMessage;
1222 }
1223
prepare(PrepareContext & context)1224 void prepare (PrepareContext& context)
1225 {
1226 m_memory = context.getMemory().getMemory();
1227 }
1228
execute(ExecuteContext & context)1229 void execute (ExecuteContext& context)
1230 {
1231 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
1232 const vk::VkDevice device = context.getContext().getDevice();
1233
1234 vkd.unmapMemory(device, m_memory);
1235 context.setMapping(DE_NULL);
1236 }
1237
1238 private:
1239 vk::VkDeviceMemory m_memory;
1240 };
1241
1242 class Invalidate : public Command
1243 {
1244 public:
Invalidate(void)1245 Invalidate (void) {}
~Invalidate(void)1246 ~Invalidate (void) {}
getName(void) const1247 const char* getName (void) const { return "Invalidate"; }
1248
logExecute(TestLog & log,size_t commandIndex) const1249 void logExecute (TestLog& log, size_t commandIndex) const
1250 {
1251 log << TestLog::Message << commandIndex << ": Invalidate mapped memory" << TestLog::EndMessage;
1252 }
1253
prepare(PrepareContext & context)1254 void prepare (PrepareContext& context)
1255 {
1256 m_memory = context.getMemory().getMemory();
1257 m_size = context.getMemory().getSize();
1258 }
1259
execute(ExecuteContext & context)1260 void execute (ExecuteContext& context)
1261 {
1262 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
1263 const vk::VkDevice device = context.getContext().getDevice();
1264
1265 vk::invalidateMappedMemoryRange(vkd, device, m_memory, 0, VK_WHOLE_SIZE);
1266 }
1267
1268 private:
1269 vk::VkDeviceMemory m_memory;
1270 vk::VkDeviceSize m_size;
1271 };
1272
1273 class Flush : public Command
1274 {
1275 public:
Flush(void)1276 Flush (void) {}
~Flush(void)1277 ~Flush (void) {}
getName(void) const1278 const char* getName (void) const { return "Flush"; }
1279
logExecute(TestLog & log,size_t commandIndex) const1280 void logExecute (TestLog& log, size_t commandIndex) const
1281 {
1282 log << TestLog::Message << commandIndex << ": Flush mapped memory" << TestLog::EndMessage;
1283 }
1284
prepare(PrepareContext & context)1285 void prepare (PrepareContext& context)
1286 {
1287 m_memory = context.getMemory().getMemory();
1288 m_size = context.getMemory().getSize();
1289 }
1290
execute(ExecuteContext & context)1291 void execute (ExecuteContext& context)
1292 {
1293 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
1294 const vk::VkDevice device = context.getContext().getDevice();
1295
1296 vk::flushMappedMemoryRange(vkd, device, m_memory, 0, VK_WHOLE_SIZE);
1297 }
1298
1299 private:
1300 vk::VkDeviceMemory m_memory;
1301 vk::VkDeviceSize m_size;
1302 };
1303
1304 // Host memory reads and writes
1305 class HostMemoryAccess : public Command
1306 {
1307 public:
1308 HostMemoryAccess (bool read, bool write, deUint32 seed);
~HostMemoryAccess(void)1309 ~HostMemoryAccess (void) {}
getName(void) const1310 const char* getName (void) const { return "HostMemoryAccess"; }
1311
1312 void logExecute (TestLog& log, size_t commandIndex) const;
1313 void prepare (PrepareContext& context);
1314 void execute (ExecuteContext& context);
1315 void verify (VerifyContext& context, size_t commandIndex);
1316
1317 private:
1318 const bool m_read;
1319 const bool m_write;
1320 const deUint32 m_seed;
1321
1322 size_t m_size;
1323 vector<deUint8> m_readData;
1324 };
1325
HostMemoryAccess(bool read,bool write,deUint32 seed)1326 HostMemoryAccess::HostMemoryAccess (bool read, bool write, deUint32 seed)
1327 : m_read (read)
1328 , m_write (write)
1329 , m_seed (seed)
1330 {
1331 }
1332
logExecute(TestLog & log,size_t commandIndex) const1333 void HostMemoryAccess::logExecute (TestLog& log, size_t commandIndex) const
1334 {
1335 log << TestLog::Message << commandIndex << ": Host memory access:" << (m_read ? " read" : "") << (m_write ? " write" : "") << ", seed: " << m_seed << TestLog::EndMessage;
1336 }
1337
prepare(PrepareContext & context)1338 void HostMemoryAccess::prepare (PrepareContext& context)
1339 {
1340 m_size = (size_t)context.getMemory().getSize();
1341
1342 if (m_read)
1343 m_readData.resize(m_size, 0);
1344 }
1345
execute(ExecuteContext & context)1346 void HostMemoryAccess::execute (ExecuteContext& context)
1347 {
1348 if (m_read && m_write)
1349 {
1350 de::Random rng (m_seed);
1351 deUint8* const ptr = (deUint8*)context.getMapping();
1352 if (m_size >= ONE_MEGABYTE)
1353 {
1354 deMemcpy(&m_readData[0], ptr, m_size);
1355 for (size_t pos = 0; pos < m_size; ++pos)
1356 {
1357 ptr[pos] = m_readData[pos] ^ rng.getUint8();
1358 }
1359 }
1360 else
1361 {
1362 for (size_t pos = 0; pos < m_size; ++pos)
1363 {
1364 const deUint8 mask = rng.getUint8();
1365 const deUint8 value = ptr[pos];
1366
1367 m_readData[pos] = value;
1368 ptr[pos] = value ^ mask;
1369 }
1370 }
1371 }
1372 else if (m_read)
1373 {
1374 const deUint8* const ptr = (deUint8*)context.getMapping();
1375 if (m_size >= ONE_MEGABYTE)
1376 {
1377 deMemcpy(&m_readData[0], ptr, m_size);
1378 }
1379 else
1380 {
1381 for (size_t pos = 0; pos < m_size; ++pos)
1382 {
1383 m_readData[pos] = ptr[pos];
1384 }
1385 }
1386 }
1387 else if (m_write)
1388 {
1389 de::Random rng (m_seed);
1390 deUint8* const ptr = (deUint8*)context.getMapping();
1391 for (size_t pos = 0; pos < m_size; ++pos)
1392 {
1393 ptr[pos] = rng.getUint8();
1394 }
1395 }
1396 else
1397 DE_FATAL("Host memory access without read or write.");
1398 }
1399
verify(VerifyContext & context,size_t commandIndex)1400 void HostMemoryAccess::verify (VerifyContext& context, size_t commandIndex)
1401 {
1402 tcu::ResultCollector& resultCollector = context.getResultCollector();
1403 ReferenceMemory& reference = context.getReference();
1404 de::Random rng (m_seed);
1405
1406 if (m_read && m_write)
1407 {
1408 for (size_t pos = 0; pos < m_size; pos++)
1409 {
1410 const deUint8 mask = rng.getUint8();
1411 const deUint8 value = m_readData[pos];
1412
1413 if (reference.isDefined(pos))
1414 {
1415 if (value != reference.get(pos))
1416 {
1417 resultCollector.fail(
1418 de::toString(commandIndex) + ":" + getName()
1419 + " Result differs from reference, Expected: "
1420 + de::toString(tcu::toHex<8>(reference.get(pos)))
1421 + ", Got: "
1422 + de::toString(tcu::toHex<8>(value))
1423 + ", At offset: "
1424 + de::toString(pos));
1425 break;
1426 }
1427
1428 reference.set(pos, reference.get(pos) ^ mask);
1429 }
1430 }
1431 }
1432 else if (m_read)
1433 {
1434 for (size_t pos = 0; pos < m_size; pos++)
1435 {
1436 const deUint8 value = m_readData[pos];
1437
1438 if (reference.isDefined(pos))
1439 {
1440 if (value != reference.get(pos))
1441 {
1442 resultCollector.fail(
1443 de::toString(commandIndex) + ":" + getName()
1444 + " Result differs from reference, Expected: "
1445 + de::toString(tcu::toHex<8>(reference.get(pos)))
1446 + ", Got: "
1447 + de::toString(tcu::toHex<8>(value))
1448 + ", At offset: "
1449 + de::toString(pos));
1450 break;
1451 }
1452 }
1453 }
1454 }
1455 else if (m_write)
1456 {
1457 for (size_t pos = 0; pos < m_size; pos++)
1458 {
1459 const deUint8 value = rng.getUint8();
1460
1461 reference.set(pos, value);
1462 }
1463 }
1464 else
1465 DE_FATAL("Host memory access without read or write.");
1466 }
1467
1468 class CreateBuffer : public Command
1469 {
1470 public:
1471 CreateBuffer (vk::VkBufferUsageFlags usage,
1472 vk::VkSharingMode sharing);
~CreateBuffer(void)1473 ~CreateBuffer (void) {}
getName(void) const1474 const char* getName (void) const { return "CreateBuffer"; }
1475
1476 void logPrepare (TestLog& log, size_t commandIndex) const;
1477 void prepare (PrepareContext& context);
1478
1479 private:
1480 const vk::VkBufferUsageFlags m_usage;
1481 const vk::VkSharingMode m_sharing;
1482 };
1483
CreateBuffer(vk::VkBufferUsageFlags usage,vk::VkSharingMode sharing)1484 CreateBuffer::CreateBuffer (vk::VkBufferUsageFlags usage,
1485 vk::VkSharingMode sharing)
1486 : m_usage (usage)
1487 , m_sharing (sharing)
1488 {
1489 }
1490
logPrepare(TestLog & log,size_t commandIndex) const1491 void CreateBuffer::logPrepare (TestLog& log, size_t commandIndex) const
1492 {
1493 log << TestLog::Message << commandIndex << ":" << getName() << " Create buffer, Sharing mode: " << m_sharing << ", Usage: " << vk::getBufferUsageFlagsStr(m_usage) << TestLog::EndMessage;
1494 }
1495
prepare(PrepareContext & context)1496 void CreateBuffer::prepare (PrepareContext& context)
1497 {
1498 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
1499 const vk::VkDevice device = context.getContext().getDevice();
1500 const vk::VkDeviceSize bufferSize = context.getMemory().getMaxBufferSize();
1501 const vector<deUint32>& queueFamilies = context.getContext().getQueueFamilies();
1502
1503 context.setBuffer(createBuffer(vkd, device, bufferSize, m_usage, m_sharing, queueFamilies), bufferSize);
1504 }
1505
1506 class DestroyBuffer : public Command
1507 {
1508 public:
1509 DestroyBuffer (void);
~DestroyBuffer(void)1510 ~DestroyBuffer (void) {}
getName(void) const1511 const char* getName (void) const { return "DestroyBuffer"; }
1512
1513 void logExecute (TestLog& log, size_t commandIndex) const;
1514 void prepare (PrepareContext& context);
1515 void execute (ExecuteContext& context);
1516
1517 private:
1518 vk::Move<vk::VkBuffer> m_buffer;
1519 };
1520
DestroyBuffer(void)1521 DestroyBuffer::DestroyBuffer (void)
1522 {
1523 }
1524
prepare(PrepareContext & context)1525 void DestroyBuffer::prepare (PrepareContext& context)
1526 {
1527 m_buffer = vk::Move<vk::VkBuffer>(vk::check(context.getBuffer()), vk::Deleter<vk::VkBuffer>(context.getContext().getDeviceInterface(), context.getContext().getDevice(), DE_NULL));
1528 context.releaseBuffer();
1529 }
1530
logExecute(TestLog & log,size_t commandIndex) const1531 void DestroyBuffer::logExecute (TestLog& log, size_t commandIndex) const
1532 {
1533 log << TestLog::Message << commandIndex << ":" << getName() << " Destroy buffer" << TestLog::EndMessage;
1534 }
1535
execute(ExecuteContext & context)1536 void DestroyBuffer::execute (ExecuteContext& context)
1537 {
1538 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
1539 const vk::VkDevice device = context.getContext().getDevice();
1540
1541 vkd.destroyBuffer(device, m_buffer.disown(), DE_NULL);
1542 }
1543
1544 class BindBufferMemory : public Command
1545 {
1546 public:
BindBufferMemory(void)1547 BindBufferMemory (void) {}
~BindBufferMemory(void)1548 ~BindBufferMemory (void) {}
getName(void) const1549 const char* getName (void) const { return "BindBufferMemory"; }
1550
1551 void logPrepare (TestLog& log, size_t commandIndex) const;
1552 void prepare (PrepareContext& context);
1553 };
1554
logPrepare(TestLog & log,size_t commandIndex) const1555 void BindBufferMemory::logPrepare (TestLog& log, size_t commandIndex) const
1556 {
1557 log << TestLog::Message << commandIndex << ":" << getName() << " Bind memory to buffer" << TestLog::EndMessage;
1558 }
1559
prepare(PrepareContext & context)1560 void BindBufferMemory::prepare (PrepareContext& context)
1561 {
1562 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
1563 const vk::VkDevice device = context.getContext().getDevice();
1564
1565 VK_CHECK(vkd.bindBufferMemory(device, context.getBuffer(), context.getMemory().getMemory(), 0));
1566 }
1567
1568 class CreateImage : public Command
1569 {
1570 public:
1571 CreateImage (vk::VkImageUsageFlags usage,
1572 vk::VkSharingMode sharing);
~CreateImage(void)1573 ~CreateImage (void) {}
getName(void) const1574 const char* getName (void) const { return "CreateImage"; }
1575
1576 void logPrepare (TestLog& log, size_t commandIndex) const;
1577 void prepare (PrepareContext& context);
1578 void verify (VerifyContext& context, size_t commandIndex);
1579
1580 private:
1581 const vk::VkImageUsageFlags m_usage;
1582 const vk::VkSharingMode m_sharing;
1583 deInt32 m_imageWidth;
1584 deInt32 m_imageHeight;
1585 };
1586
CreateImage(vk::VkImageUsageFlags usage,vk::VkSharingMode sharing)1587 CreateImage::CreateImage (vk::VkImageUsageFlags usage,
1588 vk::VkSharingMode sharing)
1589 : m_usage (usage)
1590 , m_sharing (sharing)
1591 {
1592 }
1593
logPrepare(TestLog & log,size_t commandIndex) const1594 void CreateImage::logPrepare (TestLog& log, size_t commandIndex) const
1595 {
1596 log << TestLog::Message << commandIndex << ":" << getName() << " Create image, sharing: " << m_sharing << ", usage: " << vk::getImageUsageFlagsStr(m_usage) << TestLog::EndMessage;
1597 }
1598
prepare(PrepareContext & context)1599 void CreateImage::prepare (PrepareContext& context)
1600 {
1601 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
1602 const vk::VkDevice device = context.getContext().getDevice();
1603 const vector<deUint32>& queueFamilies = context.getContext().getQueueFamilies();
1604
1605 m_imageWidth = context.getMemory().getMaxImageWidth();
1606 m_imageHeight = context.getMemory().getMaxImageHeight();
1607
1608 {
1609 const vk::VkImageCreateInfo createInfo =
1610 {
1611 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
1612 DE_NULL,
1613
1614 0u,
1615 vk::VK_IMAGE_TYPE_2D,
1616 vk::VK_FORMAT_R8G8B8A8_UNORM,
1617 {
1618 (deUint32)m_imageWidth,
1619 (deUint32)m_imageHeight,
1620 1u,
1621 },
1622 1u, 1u,
1623 vk::VK_SAMPLE_COUNT_1_BIT,
1624 vk::VK_IMAGE_TILING_OPTIMAL,
1625 m_usage,
1626 m_sharing,
1627 (deUint32)queueFamilies.size(),
1628 &queueFamilies[0],
1629 vk::VK_IMAGE_LAYOUT_UNDEFINED
1630 };
1631 vk::Move<vk::VkImage> image (createImage(vkd, device, &createInfo));
1632 const vk::VkMemoryRequirements requirements = vk::getImageMemoryRequirements(vkd, device, *image);
1633
1634 context.setImage(image, vk::VK_IMAGE_LAYOUT_UNDEFINED, requirements.size, m_imageWidth, m_imageHeight);
1635 }
1636 }
1637
verify(VerifyContext & context,size_t)1638 void CreateImage::verify (VerifyContext& context, size_t)
1639 {
1640 context.getReferenceImage() = TextureLevel(TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8), m_imageWidth, m_imageHeight);
1641 }
1642
1643 class DestroyImage : public Command
1644 {
1645 public:
1646 DestroyImage (void);
~DestroyImage(void)1647 ~DestroyImage (void) {}
getName(void) const1648 const char* getName (void) const { return "DestroyImage"; }
1649
1650 void logExecute (TestLog& log, size_t commandIndex) const;
1651 void prepare (PrepareContext& context);
1652 void execute (ExecuteContext& context);
1653
1654 private:
1655 vk::Move<vk::VkImage> m_image;
1656 };
1657
DestroyImage(void)1658 DestroyImage::DestroyImage (void)
1659 {
1660 }
1661
prepare(PrepareContext & context)1662 void DestroyImage::prepare (PrepareContext& context)
1663 {
1664 m_image = vk::Move<vk::VkImage>(vk::check(context.getImage()), vk::Deleter<vk::VkImage>(context.getContext().getDeviceInterface(), context.getContext().getDevice(), DE_NULL));
1665 context.releaseImage();
1666 }
1667
1668
logExecute(TestLog & log,size_t commandIndex) const1669 void DestroyImage::logExecute (TestLog& log, size_t commandIndex) const
1670 {
1671 log << TestLog::Message << commandIndex << ":" << getName() << " Destroy image" << TestLog::EndMessage;
1672 }
1673
execute(ExecuteContext & context)1674 void DestroyImage::execute (ExecuteContext& context)
1675 {
1676 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
1677 const vk::VkDevice device = context.getContext().getDevice();
1678
1679 vkd.destroyImage(device, m_image.disown(), DE_NULL);
1680 }
1681
1682 class BindImageMemory : public Command
1683 {
1684 public:
BindImageMemory(void)1685 BindImageMemory (void) {}
~BindImageMemory(void)1686 ~BindImageMemory (void) {}
getName(void) const1687 const char* getName (void) const { return "BindImageMemory"; }
1688
1689 void logPrepare (TestLog& log, size_t commandIndex) const;
1690 void prepare (PrepareContext& context);
1691 };
1692
logPrepare(TestLog & log,size_t commandIndex) const1693 void BindImageMemory::logPrepare (TestLog& log, size_t commandIndex) const
1694 {
1695 log << TestLog::Message << commandIndex << ":" << getName() << " Bind memory to image" << TestLog::EndMessage;
1696 }
1697
prepare(PrepareContext & context)1698 void BindImageMemory::prepare (PrepareContext& context)
1699 {
1700 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
1701 const vk::VkDevice device = context.getContext().getDevice();
1702
1703 VK_CHECK(vkd.bindImageMemory(device, context.getImage(), context.getMemory().getMemory(), 0));
1704 }
1705
1706 class QueueWaitIdle : public Command
1707 {
1708 public:
QueueWaitIdle(void)1709 QueueWaitIdle (void) {}
~QueueWaitIdle(void)1710 ~QueueWaitIdle (void) {}
getName(void) const1711 const char* getName (void) const { return "QueuetWaitIdle"; }
1712
1713 void logExecute (TestLog& log, size_t commandIndex) const;
1714 void execute (ExecuteContext& context);
1715 };
1716
logExecute(TestLog & log,size_t commandIndex) const1717 void QueueWaitIdle::logExecute (TestLog& log, size_t commandIndex) const
1718 {
1719 log << TestLog::Message << commandIndex << ":" << getName() << " Queue wait idle" << TestLog::EndMessage;
1720 }
1721
execute(ExecuteContext & context)1722 void QueueWaitIdle::execute (ExecuteContext& context)
1723 {
1724 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
1725 const vk::VkQueue queue = context.getContext().getQueue();
1726
1727 VK_CHECK(vkd.queueWaitIdle(queue));
1728 }
1729
1730 class DeviceWaitIdle : public Command
1731 {
1732 public:
DeviceWaitIdle(void)1733 DeviceWaitIdle (void) {}
~DeviceWaitIdle(void)1734 ~DeviceWaitIdle (void) {}
getName(void) const1735 const char* getName (void) const { return "DeviceWaitIdle"; }
1736
1737 void logExecute (TestLog& log, size_t commandIndex) const;
1738 void execute (ExecuteContext& context);
1739 };
1740
logExecute(TestLog & log,size_t commandIndex) const1741 void DeviceWaitIdle::logExecute (TestLog& log, size_t commandIndex) const
1742 {
1743 log << TestLog::Message << commandIndex << ":" << getName() << " Device wait idle" << TestLog::EndMessage;
1744 }
1745
execute(ExecuteContext & context)1746 void DeviceWaitIdle::execute (ExecuteContext& context)
1747 {
1748 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
1749 const vk::VkDevice device = context.getContext().getDevice();
1750
1751 VK_CHECK(vkd.deviceWaitIdle(device));
1752 }
1753
1754 class SubmitContext
1755 {
1756 public:
SubmitContext(const PrepareContext & context,const vk::VkCommandBuffer commandBuffer)1757 SubmitContext (const PrepareContext& context,
1758 const vk::VkCommandBuffer commandBuffer)
1759 : m_context (context)
1760 , m_commandBuffer (commandBuffer)
1761 {
1762 }
1763
getMemory(void) const1764 const Memory& getMemory (void) const { return m_context.getMemory(); }
getContext(void) const1765 const Context& getContext (void) const { return m_context.getContext(); }
getCommandBuffer(void) const1766 vk::VkCommandBuffer getCommandBuffer (void) const { return m_commandBuffer; }
1767
getBuffer(void) const1768 vk::VkBuffer getBuffer (void) const { return m_context.getBuffer(); }
getBufferSize(void) const1769 vk::VkDeviceSize getBufferSize (void) const { return m_context.getBufferSize(); }
1770
getImage(void) const1771 vk::VkImage getImage (void) const { return m_context.getImage(); }
getImageWidth(void) const1772 deInt32 getImageWidth (void) const { return m_context.getImageWidth(); }
getImageHeight(void) const1773 deInt32 getImageHeight (void) const { return m_context.getImageHeight(); }
1774
1775 private:
1776 const PrepareContext& m_context;
1777 const vk::VkCommandBuffer m_commandBuffer;
1778 };
1779
1780 class CmdCommand
1781 {
1782 public:
~CmdCommand(void)1783 virtual ~CmdCommand (void) {}
1784 virtual const char* getName (void) const = 0;
1785
1786 // Log things that are done during prepare
logPrepare(TestLog &,size_t) const1787 virtual void logPrepare (TestLog&, size_t) const {}
1788 // Log submitted calls etc.
logSubmit(TestLog &,size_t) const1789 virtual void logSubmit (TestLog&, size_t) const {}
1790
1791 // Allocate vulkan resources and prepare for submit.
prepare(PrepareContext &)1792 virtual void prepare (PrepareContext&) {}
1793
1794 // Submit commands to command buffer.
submit(SubmitContext &)1795 virtual void submit (SubmitContext&) {}
1796
1797 // Verify results
verify(VerifyContext &,size_t)1798 virtual void verify (VerifyContext&, size_t) {}
1799 };
1800
1801 class SubmitCommandBuffer : public Command
1802 {
1803 public:
1804 SubmitCommandBuffer (const vector<CmdCommand*>& commands);
1805 ~SubmitCommandBuffer (void);
1806
getName(void) const1807 const char* getName (void) const { return "SubmitCommandBuffer"; }
1808 void logExecute (TestLog& log, size_t commandIndex) const;
1809 void logPrepare (TestLog& log, size_t commandIndex) const;
1810
1811 // Allocate command buffer and submit commands to command buffer
1812 void prepare (PrepareContext& context);
1813 void execute (ExecuteContext& context);
1814
1815 // Verify that results are correct.
1816 void verify (VerifyContext& context, size_t commandIndex);
1817
1818 private:
1819 vector<CmdCommand*> m_commands;
1820 vk::Move<vk::VkCommandBuffer> m_commandBuffer;
1821 };
1822
SubmitCommandBuffer(const vector<CmdCommand * > & commands)1823 SubmitCommandBuffer::SubmitCommandBuffer (const vector<CmdCommand*>& commands)
1824 : m_commands (commands)
1825 {
1826 }
1827
~SubmitCommandBuffer(void)1828 SubmitCommandBuffer::~SubmitCommandBuffer (void)
1829 {
1830 for (size_t cmdNdx = 0; cmdNdx < m_commands.size(); cmdNdx++)
1831 delete m_commands[cmdNdx];
1832 }
1833
prepare(PrepareContext & context)1834 void SubmitCommandBuffer::prepare (PrepareContext& context)
1835 {
1836 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
1837 const vk::VkDevice device = context.getContext().getDevice();
1838 const vk::VkCommandPool commandPool = context.getContext().getCommandPool();
1839
1840 m_commandBuffer = createBeginCommandBuffer(vkd, device, commandPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1841
1842 for (size_t cmdNdx = 0; cmdNdx < m_commands.size(); cmdNdx++)
1843 {
1844 CmdCommand& command = *m_commands[cmdNdx];
1845
1846 command.prepare(context);
1847 }
1848
1849 {
1850 SubmitContext submitContext (context, *m_commandBuffer);
1851
1852 for (size_t cmdNdx = 0; cmdNdx < m_commands.size(); cmdNdx++)
1853 {
1854 CmdCommand& command = *m_commands[cmdNdx];
1855
1856 command.submit(submitContext);
1857 }
1858
1859 endCommandBuffer(vkd, *m_commandBuffer);
1860 }
1861 }
1862
execute(ExecuteContext & context)1863 void SubmitCommandBuffer::execute (ExecuteContext& context)
1864 {
1865 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
1866 const vk::VkCommandBuffer cmd = *m_commandBuffer;
1867 const vk::VkQueue queue = context.getContext().getQueue();
1868 const vk::VkSubmitInfo submit =
1869 {
1870 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
1871 DE_NULL,
1872
1873 0,
1874 DE_NULL,
1875 (const vk::VkPipelineStageFlags*)DE_NULL,
1876
1877 1,
1878 &cmd,
1879
1880 0,
1881 DE_NULL
1882 };
1883
1884 vkd.queueSubmit(queue, 1, &submit, 0);
1885 }
1886
verify(VerifyContext & context,size_t commandIndex)1887 void SubmitCommandBuffer::verify (VerifyContext& context, size_t commandIndex)
1888 {
1889 const string sectionName (de::toString(commandIndex) + ":" + getName());
1890 const tcu::ScopedLogSection section (context.getLog(), sectionName, sectionName);
1891
1892 for (size_t cmdNdx = 0; cmdNdx < m_commands.size(); cmdNdx++)
1893 m_commands[cmdNdx]->verify(context, cmdNdx);
1894 }
1895
logPrepare(TestLog & log,size_t commandIndex) const1896 void SubmitCommandBuffer::logPrepare (TestLog& log, size_t commandIndex) const
1897 {
1898 const string sectionName (de::toString(commandIndex) + ":" + getName());
1899 const tcu::ScopedLogSection section (log, sectionName, sectionName);
1900
1901 for (size_t cmdNdx = 0; cmdNdx < m_commands.size(); cmdNdx++)
1902 m_commands[cmdNdx]->logPrepare(log, cmdNdx);
1903 }
1904
logExecute(TestLog & log,size_t commandIndex) const1905 void SubmitCommandBuffer::logExecute (TestLog& log, size_t commandIndex) const
1906 {
1907 const string sectionName (de::toString(commandIndex) + ":" + getName());
1908 const tcu::ScopedLogSection section (log, sectionName, sectionName);
1909
1910 for (size_t cmdNdx = 0; cmdNdx < m_commands.size(); cmdNdx++)
1911 m_commands[cmdNdx]->logSubmit(log, cmdNdx);
1912 }
1913
1914 class PipelineBarrier : public CmdCommand
1915 {
1916 public:
1917 enum Type
1918 {
1919 TYPE_GLOBAL = 0,
1920 TYPE_BUFFER,
1921 TYPE_IMAGE,
1922 TYPE_LAST
1923 };
1924 PipelineBarrier (const vk::VkPipelineStageFlags srcStages,
1925 const vk::VkAccessFlags srcAccesses,
1926 const vk::VkPipelineStageFlags dstStages,
1927 const vk::VkAccessFlags dstAccesses,
1928 Type type,
1929 const tcu::Maybe<vk::VkImageLayout> imageLayout);
~PipelineBarrier(void)1930 ~PipelineBarrier (void) {}
getName(void) const1931 const char* getName (void) const { return "PipelineBarrier"; }
1932
1933 void logSubmit (TestLog& log, size_t commandIndex) const;
1934 void submit (SubmitContext& context);
1935
1936 private:
1937 const vk::VkPipelineStageFlags m_srcStages;
1938 const vk::VkAccessFlags m_srcAccesses;
1939 const vk::VkPipelineStageFlags m_dstStages;
1940 const vk::VkAccessFlags m_dstAccesses;
1941 const Type m_type;
1942 const tcu::Maybe<vk::VkImageLayout> m_imageLayout;
1943 };
1944
PipelineBarrier(const vk::VkPipelineStageFlags srcStages,const vk::VkAccessFlags srcAccesses,const vk::VkPipelineStageFlags dstStages,const vk::VkAccessFlags dstAccesses,Type type,const tcu::Maybe<vk::VkImageLayout> imageLayout)1945 PipelineBarrier::PipelineBarrier (const vk::VkPipelineStageFlags srcStages,
1946 const vk::VkAccessFlags srcAccesses,
1947 const vk::VkPipelineStageFlags dstStages,
1948 const vk::VkAccessFlags dstAccesses,
1949 Type type,
1950 const tcu::Maybe<vk::VkImageLayout> imageLayout)
1951 : m_srcStages (srcStages)
1952 , m_srcAccesses (srcAccesses)
1953 , m_dstStages (dstStages)
1954 , m_dstAccesses (dstAccesses)
1955 , m_type (type)
1956 , m_imageLayout (imageLayout)
1957 {
1958 }
1959
logSubmit(TestLog & log,size_t commandIndex) const1960 void PipelineBarrier::logSubmit (TestLog& log, size_t commandIndex) const
1961 {
1962 log << TestLog::Message << commandIndex << ":" << getName()
1963 << " " << (m_type == TYPE_GLOBAL ? "Global pipeline barrier"
1964 : m_type == TYPE_BUFFER ? "Buffer pipeline barrier"
1965 : "Image pipeline barrier")
1966 << ", srcStages: " << vk::getPipelineStageFlagsStr(m_srcStages) << ", srcAccesses: " << vk::getAccessFlagsStr(m_srcAccesses)
1967 << ", dstStages: " << vk::getPipelineStageFlagsStr(m_dstStages) << ", dstAccesses: " << vk::getAccessFlagsStr(m_dstAccesses) << TestLog::EndMessage;
1968 }
1969
submit(SubmitContext & context)1970 void PipelineBarrier::submit (SubmitContext& context)
1971 {
1972 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
1973 const vk::VkCommandBuffer cmd = context.getCommandBuffer();
1974
1975 switch (m_type)
1976 {
1977 case TYPE_GLOBAL:
1978 {
1979 const vk::VkMemoryBarrier barrier =
1980 {
1981 vk::VK_STRUCTURE_TYPE_MEMORY_BARRIER,
1982 DE_NULL,
1983
1984 m_srcAccesses,
1985 m_dstAccesses
1986 };
1987
1988 vkd.cmdPipelineBarrier(cmd, m_srcStages, m_dstStages, (vk::VkDependencyFlags)0, 1, &barrier, 0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 0, (const vk::VkImageMemoryBarrier*)DE_NULL);
1989 break;
1990 }
1991
1992 case TYPE_BUFFER:
1993 {
1994 const vk::VkBufferMemoryBarrier barrier =
1995 {
1996 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
1997 DE_NULL,
1998
1999 m_srcAccesses,
2000 m_dstAccesses,
2001
2002 VK_QUEUE_FAMILY_IGNORED,
2003 VK_QUEUE_FAMILY_IGNORED,
2004
2005 context.getBuffer(),
2006 0,
2007 VK_WHOLE_SIZE
2008 };
2009
2010 vkd.cmdPipelineBarrier(cmd, m_srcStages, m_dstStages, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 1, &barrier, 0, (const vk::VkImageMemoryBarrier*)DE_NULL);
2011 break;
2012 }
2013
2014 case TYPE_IMAGE:
2015 {
2016 const vk::VkImageMemoryBarrier barrier =
2017 {
2018 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
2019 DE_NULL,
2020
2021 m_srcAccesses,
2022 m_dstAccesses,
2023
2024 *m_imageLayout,
2025 *m_imageLayout,
2026
2027 VK_QUEUE_FAMILY_IGNORED,
2028 VK_QUEUE_FAMILY_IGNORED,
2029
2030 context.getImage(),
2031 {
2032 vk::VK_IMAGE_ASPECT_COLOR_BIT,
2033 0, 1,
2034 0, 1
2035 }
2036 };
2037
2038 vkd.cmdPipelineBarrier(cmd, m_srcStages, m_dstStages, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1, &barrier);
2039 break;
2040 }
2041
2042 default:
2043 DE_FATAL("Unknown pipeline barrier type");
2044 }
2045 }
2046
2047 class ImageTransition : public CmdCommand
2048 {
2049 public:
2050 ImageTransition (vk::VkPipelineStageFlags srcStages,
2051 vk::VkAccessFlags srcAccesses,
2052
2053 vk::VkPipelineStageFlags dstStages,
2054 vk::VkAccessFlags dstAccesses,
2055
2056 vk::VkImageLayout srcLayout,
2057 vk::VkImageLayout dstLayout);
2058
~ImageTransition(void)2059 ~ImageTransition (void) {}
getName(void) const2060 const char* getName (void) const { return "ImageTransition"; }
2061
2062 void prepare (PrepareContext& context);
2063 void logSubmit (TestLog& log, size_t commandIndex) const;
2064 void submit (SubmitContext& context);
2065 void verify (VerifyContext& context, size_t);
2066
2067 private:
2068 const vk::VkPipelineStageFlags m_srcStages;
2069 const vk::VkAccessFlags m_srcAccesses;
2070 const vk::VkPipelineStageFlags m_dstStages;
2071 const vk::VkAccessFlags m_dstAccesses;
2072 const vk::VkImageLayout m_srcLayout;
2073 const vk::VkImageLayout m_dstLayout;
2074
2075 vk::VkDeviceSize m_imageMemorySize;
2076 };
2077
ImageTransition(vk::VkPipelineStageFlags srcStages,vk::VkAccessFlags srcAccesses,vk::VkPipelineStageFlags dstStages,vk::VkAccessFlags dstAccesses,vk::VkImageLayout srcLayout,vk::VkImageLayout dstLayout)2078 ImageTransition::ImageTransition (vk::VkPipelineStageFlags srcStages,
2079 vk::VkAccessFlags srcAccesses,
2080
2081 vk::VkPipelineStageFlags dstStages,
2082 vk::VkAccessFlags dstAccesses,
2083
2084 vk::VkImageLayout srcLayout,
2085 vk::VkImageLayout dstLayout)
2086 : m_srcStages (srcStages)
2087 , m_srcAccesses (srcAccesses)
2088 , m_dstStages (dstStages)
2089 , m_dstAccesses (dstAccesses)
2090 , m_srcLayout (srcLayout)
2091 , m_dstLayout (dstLayout)
2092 {
2093 }
2094
logSubmit(TestLog & log,size_t commandIndex) const2095 void ImageTransition::logSubmit (TestLog& log, size_t commandIndex) const
2096 {
2097 log << TestLog::Message << commandIndex << ":" << getName()
2098 << " Image transition pipeline barrier"
2099 << ", srcStages: " << vk::getPipelineStageFlagsStr(m_srcStages) << ", srcAccesses: " << vk::getAccessFlagsStr(m_srcAccesses)
2100 << ", dstStages: " << vk::getPipelineStageFlagsStr(m_dstStages) << ", dstAccesses: " << vk::getAccessFlagsStr(m_dstAccesses)
2101 << ", srcLayout: " << m_srcLayout << ", dstLayout: " << m_dstLayout << TestLog::EndMessage;
2102 }
2103
prepare(PrepareContext & context)2104 void ImageTransition::prepare (PrepareContext& context)
2105 {
2106 DE_ASSERT(context.getImageLayout() == vk::VK_IMAGE_LAYOUT_UNDEFINED || m_srcLayout == vk::VK_IMAGE_LAYOUT_UNDEFINED || context.getImageLayout() == m_srcLayout);
2107
2108 context.setImageLayout(m_dstLayout);
2109 m_imageMemorySize = context.getImageMemorySize();
2110 }
2111
submit(SubmitContext & context)2112 void ImageTransition::submit (SubmitContext& context)
2113 {
2114 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
2115 const vk::VkCommandBuffer cmd = context.getCommandBuffer();
2116 const vk::VkImageMemoryBarrier barrier =
2117 {
2118 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
2119 DE_NULL,
2120
2121 m_srcAccesses,
2122 m_dstAccesses,
2123
2124 m_srcLayout,
2125 m_dstLayout,
2126
2127 VK_QUEUE_FAMILY_IGNORED,
2128 VK_QUEUE_FAMILY_IGNORED,
2129
2130 context.getImage(),
2131 {
2132 vk::VK_IMAGE_ASPECT_COLOR_BIT,
2133 0u, 1u,
2134 0u, 1u
2135 }
2136 };
2137
2138 vkd.cmdPipelineBarrier(cmd, m_srcStages, m_dstStages, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1, &barrier);
2139 }
2140
verify(VerifyContext & context,size_t)2141 void ImageTransition::verify (VerifyContext& context, size_t)
2142 {
2143 context.getReference().setUndefined(0, (size_t)m_imageMemorySize);
2144 }
2145
2146 class FillBuffer : public CmdCommand
2147 {
2148 public:
FillBuffer(deUint32 value)2149 FillBuffer (deUint32 value) : m_value(value) {}
~FillBuffer(void)2150 ~FillBuffer (void) {}
getName(void) const2151 const char* getName (void) const { return "FillBuffer"; }
2152
2153 void logSubmit (TestLog& log, size_t commandIndex) const;
2154 void submit (SubmitContext& context);
2155 void verify (VerifyContext& context, size_t commandIndex);
2156
2157 private:
2158 const deUint32 m_value;
2159 vk::VkDeviceSize m_bufferSize;
2160 };
2161
logSubmit(TestLog & log,size_t commandIndex) const2162 void FillBuffer::logSubmit (TestLog& log, size_t commandIndex) const
2163 {
2164 log << TestLog::Message << commandIndex << ":" << getName() << " Fill value: " << m_value << TestLog::EndMessage;
2165 }
2166
submit(SubmitContext & context)2167 void FillBuffer::submit (SubmitContext& context)
2168 {
2169 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
2170 const vk::VkCommandBuffer cmd = context.getCommandBuffer();
2171 const vk::VkBuffer buffer = context.getBuffer();
2172 const vk::VkDeviceSize sizeMask = ~(0x3ull); // \note Round down to multiple of 4
2173
2174 m_bufferSize = sizeMask & context.getBufferSize();
2175 vkd.cmdFillBuffer(cmd, buffer, 0, m_bufferSize, m_value);
2176 }
2177
verify(VerifyContext & context,size_t)2178 void FillBuffer::verify (VerifyContext& context, size_t)
2179 {
2180 ReferenceMemory& reference = context.getReference();
2181
2182 for (size_t ndx = 0; ndx < m_bufferSize; ndx++)
2183 {
2184 #if (DE_ENDIANNESS == DE_LITTLE_ENDIAN)
2185 reference.set(ndx, (deUint8)(0xffu & (m_value >> (8*(ndx % 4)))));
2186 #else
2187 reference.set(ndx, (deUint8)(0xffu & (m_value >> (8*(3 - (ndx % 4))))));
2188 #endif
2189 }
2190 }
2191
2192 class UpdateBuffer : public CmdCommand
2193 {
2194 public:
UpdateBuffer(deUint32 seed)2195 UpdateBuffer (deUint32 seed) : m_seed(seed) {}
~UpdateBuffer(void)2196 ~UpdateBuffer (void) {}
getName(void) const2197 const char* getName (void) const { return "UpdateBuffer"; }
2198
2199 void logSubmit (TestLog& log, size_t commandIndex) const;
2200 void submit (SubmitContext& context);
2201 void verify (VerifyContext& context, size_t commandIndex);
2202
2203 private:
2204 const deUint32 m_seed;
2205 vk::VkDeviceSize m_bufferSize;
2206 };
2207
logSubmit(TestLog & log,size_t commandIndex) const2208 void UpdateBuffer::logSubmit (TestLog& log, size_t commandIndex) const
2209 {
2210 log << TestLog::Message << commandIndex << ":" << getName() << " Update buffer, seed: " << m_seed << TestLog::EndMessage;
2211 }
2212
submit(SubmitContext & context)2213 void UpdateBuffer::submit (SubmitContext& context)
2214 {
2215 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
2216 const vk::VkCommandBuffer cmd = context.getCommandBuffer();
2217 const vk::VkBuffer buffer = context.getBuffer();
2218 const size_t blockSize = 65536;
2219 std::vector<deUint8> data (blockSize, 0);
2220 de::Random rng (m_seed);
2221
2222 m_bufferSize = context.getBufferSize();
2223
2224 for (size_t updated = 0; updated < m_bufferSize; updated += blockSize)
2225 {
2226 for (size_t ndx = 0; ndx < data.size(); ndx++)
2227 data[ndx] = rng.getUint8();
2228
2229 if (m_bufferSize - updated > blockSize)
2230 vkd.cmdUpdateBuffer(cmd, buffer, updated, blockSize, (const deUint32*)(&data[0]));
2231 else
2232 vkd.cmdUpdateBuffer(cmd, buffer, updated, m_bufferSize - updated, (const deUint32*)(&data[0]));
2233 }
2234 }
2235
verify(VerifyContext & context,size_t)2236 void UpdateBuffer::verify (VerifyContext& context, size_t)
2237 {
2238 ReferenceMemory& reference = context.getReference();
2239 const size_t blockSize = 65536;
2240 vector<deUint8> data (blockSize, 0);
2241 de::Random rng (m_seed);
2242
2243 for (size_t updated = 0; updated < m_bufferSize; updated += blockSize)
2244 {
2245 for (size_t ndx = 0; ndx < data.size(); ndx++)
2246 data[ndx] = rng.getUint8();
2247
2248 if (m_bufferSize - updated > blockSize)
2249 reference.setData(updated, blockSize, &data[0]);
2250 else
2251 reference.setData(updated, (size_t)(m_bufferSize - updated), &data[0]);
2252 }
2253 }
2254
2255 class BufferCopyToBuffer : public CmdCommand
2256 {
2257 public:
BufferCopyToBuffer(void)2258 BufferCopyToBuffer (void) {}
~BufferCopyToBuffer(void)2259 ~BufferCopyToBuffer (void) {}
getName(void) const2260 const char* getName (void) const { return "BufferCopyToBuffer"; }
2261
2262 void logPrepare (TestLog& log, size_t commandIndex) const;
2263 void prepare (PrepareContext& context);
2264 void logSubmit (TestLog& log, size_t commandIndex) const;
2265 void submit (SubmitContext& context);
2266 void verify (VerifyContext& context, size_t commandIndex);
2267
2268 private:
2269 vk::VkDeviceSize m_bufferSize;
2270 vk::Move<vk::VkBuffer> m_dstBuffer;
2271 vk::Move<vk::VkDeviceMemory> m_memory;
2272 };
2273
logPrepare(TestLog & log,size_t commandIndex) const2274 void BufferCopyToBuffer::logPrepare (TestLog& log, size_t commandIndex) const
2275 {
2276 log << TestLog::Message << commandIndex << ":" << getName() << " Allocate destination buffer for buffer to buffer copy." << TestLog::EndMessage;
2277 }
2278
prepare(PrepareContext & context)2279 void BufferCopyToBuffer::prepare (PrepareContext& context)
2280 {
2281 const vk::InstanceInterface& vki = context.getContext().getInstanceInterface();
2282 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
2283 const vk::VkPhysicalDevice physicalDevice = context.getContext().getPhysicalDevice();
2284 const vk::VkDevice device = context.getContext().getDevice();
2285 const vector<deUint32>& queueFamilies = context.getContext().getQueueFamilies();
2286
2287 m_bufferSize = context.getBufferSize();
2288
2289 m_dstBuffer = createBuffer(vkd, device, m_bufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT, vk::VK_SHARING_MODE_EXCLUSIVE, queueFamilies);
2290 m_memory = bindBufferMemory(vki, vkd, physicalDevice, device, *m_dstBuffer, vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
2291 }
2292
logSubmit(TestLog & log,size_t commandIndex) const2293 void BufferCopyToBuffer::logSubmit (TestLog& log, size_t commandIndex) const
2294 {
2295 log << TestLog::Message << commandIndex << ":" << getName() << " Copy buffer to another buffer" << TestLog::EndMessage;
2296 }
2297
submit(SubmitContext & context)2298 void BufferCopyToBuffer::submit (SubmitContext& context)
2299 {
2300 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
2301 const vk::VkCommandBuffer commandBuffer = context.getCommandBuffer();
2302 const vk::VkBufferCopy range =
2303 {
2304 0, 0, // Offsets
2305 m_bufferSize
2306 };
2307
2308 vkd.cmdCopyBuffer(commandBuffer, context.getBuffer(), *m_dstBuffer, 1, &range);
2309 }
2310
verify(VerifyContext & context,size_t commandIndex)2311 void BufferCopyToBuffer::verify (VerifyContext& context, size_t commandIndex)
2312 {
2313 tcu::ResultCollector& resultCollector (context.getResultCollector());
2314 ReferenceMemory& reference (context.getReference());
2315 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
2316 const vk::VkDevice device = context.getContext().getDevice();
2317 const vk::VkQueue queue = context.getContext().getQueue();
2318 const vk::VkCommandPool commandPool = context.getContext().getCommandPool();
2319 const vk::Unique<vk::VkCommandBuffer> commandBuffer (createBeginCommandBuffer(vkd, device, commandPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
2320 const vk::VkBufferMemoryBarrier barrier =
2321 {
2322 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
2323 DE_NULL,
2324
2325 vk::VK_ACCESS_TRANSFER_WRITE_BIT,
2326 vk::VK_ACCESS_HOST_READ_BIT,
2327
2328 VK_QUEUE_FAMILY_IGNORED,
2329 VK_QUEUE_FAMILY_IGNORED,
2330 *m_dstBuffer,
2331 0,
2332 VK_WHOLE_SIZE
2333 };
2334
2335 vkd.cmdPipelineBarrier(*commandBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 1, &barrier, 0, (const vk::VkImageMemoryBarrier*)DE_NULL);
2336
2337 endCommandBuffer(vkd, *commandBuffer);
2338 submitCommandsAndWait(vkd, device, queue, *commandBuffer);
2339
2340 {
2341 void* const ptr = mapMemory(vkd, device, *m_memory, m_bufferSize);
2342 bool isOk = true;
2343
2344 vk::invalidateMappedMemoryRange(vkd, device, *m_memory, 0, VK_WHOLE_SIZE);
2345
2346 {
2347 const deUint8* const data = (const deUint8*)ptr;
2348
2349 for (size_t pos = 0; pos < (size_t)m_bufferSize; pos++)
2350 {
2351 if (reference.isDefined(pos))
2352 {
2353 if (data[pos] != reference.get(pos))
2354 {
2355 resultCollector.fail(
2356 de::toString(commandIndex) + ":" + getName()
2357 + " Result differs from reference, Expected: "
2358 + de::toString(tcu::toHex<8>(reference.get(pos)))
2359 + ", Got: "
2360 + de::toString(tcu::toHex<8>(data[pos]))
2361 + ", At offset: "
2362 + de::toString(pos));
2363 break;
2364 }
2365 }
2366 }
2367 }
2368
2369 vkd.unmapMemory(device, *m_memory);
2370
2371 if (!isOk)
2372 context.getLog() << TestLog::Message << commandIndex << ": Buffer copy to buffer verification failed" << TestLog::EndMessage;
2373 }
2374 }
2375
2376 class BufferCopyFromBuffer : public CmdCommand
2377 {
2378 public:
BufferCopyFromBuffer(deUint32 seed)2379 BufferCopyFromBuffer (deUint32 seed) : m_seed(seed) {}
~BufferCopyFromBuffer(void)2380 ~BufferCopyFromBuffer (void) {}
getName(void) const2381 const char* getName (void) const { return "BufferCopyFromBuffer"; }
2382
2383 void logPrepare (TestLog& log, size_t commandIndex) const;
2384 void prepare (PrepareContext& context);
2385 void logSubmit (TestLog& log, size_t commandIndex) const;
2386 void submit (SubmitContext& context);
2387 void verify (VerifyContext& context, size_t commandIndex);
2388
2389 private:
2390 const deUint32 m_seed;
2391 vk::VkDeviceSize m_bufferSize;
2392 vk::Move<vk::VkBuffer> m_srcBuffer;
2393 vk::Move<vk::VkDeviceMemory> m_memory;
2394 };
2395
logPrepare(TestLog & log,size_t commandIndex) const2396 void BufferCopyFromBuffer::logPrepare (TestLog& log, size_t commandIndex) const
2397 {
2398 log << TestLog::Message << commandIndex << ":" << getName() << " Allocate source buffer for buffer to buffer copy. Seed: " << m_seed << TestLog::EndMessage;
2399 }
2400
prepare(PrepareContext & context)2401 void BufferCopyFromBuffer::prepare (PrepareContext& context)
2402 {
2403 const vk::InstanceInterface& vki = context.getContext().getInstanceInterface();
2404 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
2405 const vk::VkPhysicalDevice physicalDevice = context.getContext().getPhysicalDevice();
2406 const vk::VkDevice device = context.getContext().getDevice();
2407 const vector<deUint32>& queueFamilies = context.getContext().getQueueFamilies();
2408
2409 m_bufferSize = context.getBufferSize();
2410 m_srcBuffer = createBuffer(vkd, device, m_bufferSize, vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT, vk::VK_SHARING_MODE_EXCLUSIVE, queueFamilies);
2411 m_memory = bindBufferMemory(vki, vkd, physicalDevice, device, *m_srcBuffer, vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
2412
2413 {
2414 void* const ptr = mapMemory(vkd, device, *m_memory, m_bufferSize);
2415 de::Random rng (m_seed);
2416
2417 {
2418 deUint8* const data = (deUint8*)ptr;
2419
2420 for (size_t ndx = 0; ndx < (size_t)m_bufferSize; ndx++)
2421 data[ndx] = rng.getUint8();
2422 }
2423
2424 vk::flushMappedMemoryRange(vkd, device, *m_memory, 0, VK_WHOLE_SIZE);
2425 vkd.unmapMemory(device, *m_memory);
2426 }
2427 }
2428
logSubmit(TestLog & log,size_t commandIndex) const2429 void BufferCopyFromBuffer::logSubmit (TestLog& log, size_t commandIndex) const
2430 {
2431 log << TestLog::Message << commandIndex << ":" << getName() << " Copy buffer data from another buffer" << TestLog::EndMessage;
2432 }
2433
submit(SubmitContext & context)2434 void BufferCopyFromBuffer::submit (SubmitContext& context)
2435 {
2436 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
2437 const vk::VkCommandBuffer commandBuffer = context.getCommandBuffer();
2438 const vk::VkBufferCopy range =
2439 {
2440 0, 0, // Offsets
2441 m_bufferSize
2442 };
2443
2444 vkd.cmdCopyBuffer(commandBuffer, *m_srcBuffer, context.getBuffer(), 1, &range);
2445 }
2446
verify(VerifyContext & context,size_t)2447 void BufferCopyFromBuffer::verify (VerifyContext& context, size_t)
2448 {
2449 ReferenceMemory& reference (context.getReference());
2450 de::Random rng (m_seed);
2451
2452 for (size_t ndx = 0; ndx < (size_t)m_bufferSize; ndx++)
2453 reference.set(ndx, rng.getUint8());
2454 }
2455
2456 class BufferCopyToImage : public CmdCommand
2457 {
2458 public:
BufferCopyToImage(void)2459 BufferCopyToImage (void) {}
~BufferCopyToImage(void)2460 ~BufferCopyToImage (void) {}
getName(void) const2461 const char* getName (void) const { return "BufferCopyToImage"; }
2462
2463 void logPrepare (TestLog& log, size_t commandIndex) const;
2464 void prepare (PrepareContext& context);
2465 void logSubmit (TestLog& log, size_t commandIndex) const;
2466 void submit (SubmitContext& context);
2467 void verify (VerifyContext& context, size_t commandIndex);
2468
2469 private:
2470 deInt32 m_imageWidth;
2471 deInt32 m_imageHeight;
2472 vk::Move<vk::VkImage> m_dstImage;
2473 vk::Move<vk::VkDeviceMemory> m_memory;
2474 };
2475
logPrepare(TestLog & log,size_t commandIndex) const2476 void BufferCopyToImage::logPrepare (TestLog& log, size_t commandIndex) const
2477 {
2478 log << TestLog::Message << commandIndex << ":" << getName() << " Allocate destination image for buffer to image copy." << TestLog::EndMessage;
2479 }
2480
prepare(PrepareContext & context)2481 void BufferCopyToImage::prepare (PrepareContext& context)
2482 {
2483 const vk::InstanceInterface& vki = context.getContext().getInstanceInterface();
2484 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
2485 const vk::VkPhysicalDevice physicalDevice = context.getContext().getPhysicalDevice();
2486 const vk::VkDevice device = context.getContext().getDevice();
2487 const vk::VkQueue queue = context.getContext().getQueue();
2488 const vk::VkCommandPool commandPool = context.getContext().getCommandPool();
2489 const vector<deUint32>& queueFamilies = context.getContext().getQueueFamilies();
2490 const IVec2 imageSize = findImageSizeWxHx4(context.getBufferSize());
2491
2492 m_imageWidth = imageSize[0];
2493 m_imageHeight = imageSize[1];
2494
2495 {
2496 const vk::VkImageCreateInfo createInfo =
2497 {
2498 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
2499 DE_NULL,
2500
2501 0,
2502 vk::VK_IMAGE_TYPE_2D,
2503 vk::VK_FORMAT_R8G8B8A8_UNORM,
2504 {
2505 (deUint32)m_imageWidth,
2506 (deUint32)m_imageHeight,
2507 1u,
2508 },
2509 1, 1, // mipLevels, arrayLayers
2510 vk::VK_SAMPLE_COUNT_1_BIT,
2511
2512 vk::VK_IMAGE_TILING_OPTIMAL,
2513 vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT|vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
2514 vk::VK_SHARING_MODE_EXCLUSIVE,
2515
2516 (deUint32)queueFamilies.size(),
2517 &queueFamilies[0],
2518 vk::VK_IMAGE_LAYOUT_UNDEFINED
2519 };
2520
2521 m_dstImage = vk::createImage(vkd, device, &createInfo);
2522 }
2523
2524 m_memory = bindImageMemory(vki, vkd, physicalDevice, device, *m_dstImage, 0);
2525
2526 {
2527 const vk::Unique<vk::VkCommandBuffer> commandBuffer (createBeginCommandBuffer(vkd, device, commandPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
2528 const vk::VkImageMemoryBarrier barrier =
2529 {
2530 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
2531 DE_NULL,
2532
2533 0,
2534 vk::VK_ACCESS_TRANSFER_WRITE_BIT,
2535
2536 vk::VK_IMAGE_LAYOUT_UNDEFINED,
2537 vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
2538
2539 VK_QUEUE_FAMILY_IGNORED,
2540 VK_QUEUE_FAMILY_IGNORED,
2541
2542 *m_dstImage,
2543 {
2544 vk::VK_IMAGE_ASPECT_COLOR_BIT,
2545 0, // Mip level
2546 1, // Mip level count
2547 0, // Layer
2548 1 // Layer count
2549 }
2550 };
2551
2552 vkd.cmdPipelineBarrier(*commandBuffer, vk::VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1, &barrier);
2553
2554 endCommandBuffer(vkd, *commandBuffer);
2555 submitCommandsAndWait(vkd, device, queue, *commandBuffer);
2556 }
2557 }
2558
logSubmit(TestLog & log,size_t commandIndex) const2559 void BufferCopyToImage::logSubmit (TestLog& log, size_t commandIndex) const
2560 {
2561 log << TestLog::Message << commandIndex << ":" << getName() << " Copy buffer to image" << TestLog::EndMessage;
2562 }
2563
submit(SubmitContext & context)2564 void BufferCopyToImage::submit (SubmitContext& context)
2565 {
2566 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
2567 const vk::VkCommandBuffer commandBuffer = context.getCommandBuffer();
2568 const vk::VkBufferImageCopy region =
2569 {
2570 0,
2571 0, 0,
2572 {
2573 vk::VK_IMAGE_ASPECT_COLOR_BIT,
2574 0, // mipLevel
2575 0, // arrayLayer
2576 1 // layerCount
2577 },
2578 { 0, 0, 0 },
2579 {
2580 (deUint32)m_imageWidth,
2581 (deUint32)m_imageHeight,
2582 1u
2583 }
2584 };
2585
2586 vkd.cmdCopyBufferToImage(commandBuffer, context.getBuffer(), *m_dstImage, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
2587 }
2588
verify(VerifyContext & context,size_t commandIndex)2589 void BufferCopyToImage::verify (VerifyContext& context, size_t commandIndex)
2590 {
2591 tcu::ResultCollector& resultCollector (context.getResultCollector());
2592 ReferenceMemory& reference (context.getReference());
2593 const vk::InstanceInterface& vki = context.getContext().getInstanceInterface();
2594 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
2595 const vk::VkPhysicalDevice physicalDevice = context.getContext().getPhysicalDevice();
2596 const vk::VkDevice device = context.getContext().getDevice();
2597 const vk::VkQueue queue = context.getContext().getQueue();
2598 const vk::VkCommandPool commandPool = context.getContext().getCommandPool();
2599 const vk::Unique<vk::VkCommandBuffer> commandBuffer (createBeginCommandBuffer(vkd, device, commandPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
2600 const vector<deUint32>& queueFamilies = context.getContext().getQueueFamilies();
2601 const vk::Unique<vk::VkBuffer> dstBuffer (createBuffer(vkd, device, 4 * m_imageWidth * m_imageHeight, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT, vk::VK_SHARING_MODE_EXCLUSIVE, queueFamilies));
2602 const vk::Unique<vk::VkDeviceMemory> memory (bindBufferMemory(vki, vkd, physicalDevice, device, *dstBuffer, vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));
2603 {
2604 const vk::VkImageMemoryBarrier imageBarrier =
2605 {
2606 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
2607 DE_NULL,
2608
2609 vk::VK_ACCESS_TRANSFER_WRITE_BIT,
2610 vk::VK_ACCESS_TRANSFER_READ_BIT,
2611
2612 vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
2613 vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
2614
2615 VK_QUEUE_FAMILY_IGNORED,
2616 VK_QUEUE_FAMILY_IGNORED,
2617
2618 *m_dstImage,
2619 {
2620 vk::VK_IMAGE_ASPECT_COLOR_BIT,
2621 0, // Mip level
2622 1, // Mip level count
2623 0, // Layer
2624 1 // Layer count
2625 }
2626 };
2627 const vk::VkBufferMemoryBarrier bufferBarrier =
2628 {
2629 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
2630 DE_NULL,
2631
2632 vk::VK_ACCESS_TRANSFER_WRITE_BIT,
2633 vk::VK_ACCESS_HOST_READ_BIT,
2634
2635 VK_QUEUE_FAMILY_IGNORED,
2636 VK_QUEUE_FAMILY_IGNORED,
2637 *dstBuffer,
2638 0,
2639 VK_WHOLE_SIZE
2640 };
2641
2642 const vk::VkBufferImageCopy region =
2643 {
2644 0,
2645 0, 0,
2646 {
2647 vk::VK_IMAGE_ASPECT_COLOR_BIT,
2648 0, // mipLevel
2649 0, // arrayLayer
2650 1 // layerCount
2651 },
2652 { 0, 0, 0 },
2653 {
2654 (deUint32)m_imageWidth,
2655 (deUint32)m_imageHeight,
2656 1u
2657 }
2658 };
2659
2660 vkd.cmdPipelineBarrier(*commandBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1, &imageBarrier);
2661 vkd.cmdCopyImageToBuffer(*commandBuffer, *m_dstImage, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *dstBuffer, 1, ®ion);
2662 vkd.cmdPipelineBarrier(*commandBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 1, &bufferBarrier, 0, (const vk::VkImageMemoryBarrier*)DE_NULL);
2663 }
2664
2665 endCommandBuffer(vkd, *commandBuffer);
2666 submitCommandsAndWait(vkd, device, queue, *commandBuffer);
2667
2668 {
2669 void* const ptr = mapMemory(vkd, device, *memory, 4 * m_imageWidth * m_imageHeight);
2670
2671 invalidateMappedMemoryRange(vkd, device, *memory, 0, VK_WHOLE_SIZE);
2672
2673 {
2674 const deUint8* const data = (const deUint8*)ptr;
2675
2676 for (size_t pos = 0; pos < (size_t)( 4 * m_imageWidth * m_imageHeight); pos++)
2677 {
2678 if (reference.isDefined(pos))
2679 {
2680 if (data[pos] != reference.get(pos))
2681 {
2682 resultCollector.fail(
2683 de::toString(commandIndex) + ":" + getName()
2684 + " Result differs from reference, Expected: "
2685 + de::toString(tcu::toHex<8>(reference.get(pos)))
2686 + ", Got: "
2687 + de::toString(tcu::toHex<8>(data[pos]))
2688 + ", At offset: "
2689 + de::toString(pos));
2690 break;
2691 }
2692 }
2693 }
2694 }
2695
2696 vkd.unmapMemory(device, *memory);
2697 }
2698 }
2699
2700 class BufferCopyFromImage : public CmdCommand
2701 {
2702 public:
BufferCopyFromImage(deUint32 seed)2703 BufferCopyFromImage (deUint32 seed) : m_seed(seed) {}
~BufferCopyFromImage(void)2704 ~BufferCopyFromImage (void) {}
getName(void) const2705 const char* getName (void) const { return "BufferCopyFromImage"; }
2706
2707 void logPrepare (TestLog& log, size_t commandIndex) const;
2708 void prepare (PrepareContext& context);
2709 void logSubmit (TestLog& log, size_t commandIndex) const;
2710 void submit (SubmitContext& context);
2711 void verify (VerifyContext& context, size_t commandIndex);
2712
2713 private:
2714 const deUint32 m_seed;
2715 deInt32 m_imageWidth;
2716 deInt32 m_imageHeight;
2717 vk::Move<vk::VkImage> m_srcImage;
2718 vk::Move<vk::VkDeviceMemory> m_memory;
2719 };
2720
logPrepare(TestLog & log,size_t commandIndex) const2721 void BufferCopyFromImage::logPrepare (TestLog& log, size_t commandIndex) const
2722 {
2723 log << TestLog::Message << commandIndex << ":" << getName() << " Allocate source image for image to buffer copy." << TestLog::EndMessage;
2724 }
2725
prepare(PrepareContext & context)2726 void BufferCopyFromImage::prepare (PrepareContext& context)
2727 {
2728 const vk::InstanceInterface& vki = context.getContext().getInstanceInterface();
2729 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
2730 const vk::VkPhysicalDevice physicalDevice = context.getContext().getPhysicalDevice();
2731 const vk::VkDevice device = context.getContext().getDevice();
2732 const vk::VkQueue queue = context.getContext().getQueue();
2733 const vk::VkCommandPool commandPool = context.getContext().getCommandPool();
2734 const vector<deUint32>& queueFamilies = context.getContext().getQueueFamilies();
2735 const IVec2 imageSize = findImageSizeWxHx4(context.getBufferSize());
2736
2737 m_imageWidth = imageSize[0];
2738 m_imageHeight = imageSize[1];
2739
2740 {
2741 const vk::VkImageCreateInfo createInfo =
2742 {
2743 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
2744 DE_NULL,
2745
2746 0,
2747 vk::VK_IMAGE_TYPE_2D,
2748 vk::VK_FORMAT_R8G8B8A8_UNORM,
2749 {
2750 (deUint32)m_imageWidth,
2751 (deUint32)m_imageHeight,
2752 1u,
2753 },
2754 1, 1, // mipLevels, arrayLayers
2755 vk::VK_SAMPLE_COUNT_1_BIT,
2756
2757 vk::VK_IMAGE_TILING_OPTIMAL,
2758 vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT|vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
2759 vk::VK_SHARING_MODE_EXCLUSIVE,
2760
2761 (deUint32)queueFamilies.size(),
2762 &queueFamilies[0],
2763 vk::VK_IMAGE_LAYOUT_UNDEFINED
2764 };
2765
2766 m_srcImage = vk::createImage(vkd, device, &createInfo);
2767 }
2768
2769 m_memory = bindImageMemory(vki, vkd, physicalDevice, device, *m_srcImage, 0);
2770
2771 {
2772 const vk::Unique<vk::VkBuffer> srcBuffer (createBuffer(vkd, device, 4 * m_imageWidth * m_imageHeight, vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT, vk::VK_SHARING_MODE_EXCLUSIVE, queueFamilies));
2773 const vk::Unique<vk::VkDeviceMemory> memory (bindBufferMemory(vki, vkd, physicalDevice, device, *srcBuffer, vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));
2774 const vk::Unique<vk::VkCommandBuffer> commandBuffer (createBeginCommandBuffer(vkd, device, commandPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
2775 const vk::VkImageMemoryBarrier preImageBarrier =
2776 {
2777 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
2778 DE_NULL,
2779
2780 0,
2781 vk::VK_ACCESS_TRANSFER_WRITE_BIT,
2782
2783 vk::VK_IMAGE_LAYOUT_UNDEFINED,
2784 vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
2785
2786 VK_QUEUE_FAMILY_IGNORED,
2787 VK_QUEUE_FAMILY_IGNORED,
2788
2789 *m_srcImage,
2790 {
2791 vk::VK_IMAGE_ASPECT_COLOR_BIT,
2792 0, // Mip level
2793 1, // Mip level count
2794 0, // Layer
2795 1 // Layer count
2796 }
2797 };
2798 const vk::VkImageMemoryBarrier postImageBarrier =
2799 {
2800 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
2801 DE_NULL,
2802
2803 vk::VK_ACCESS_TRANSFER_WRITE_BIT,
2804 0,
2805
2806 vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
2807 vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
2808
2809 VK_QUEUE_FAMILY_IGNORED,
2810 VK_QUEUE_FAMILY_IGNORED,
2811
2812 *m_srcImage,
2813 {
2814 vk::VK_IMAGE_ASPECT_COLOR_BIT,
2815 0, // Mip level
2816 1, // Mip level count
2817 0, // Layer
2818 1 // Layer count
2819 }
2820 };
2821 const vk::VkBufferImageCopy region =
2822 {
2823 0,
2824 0, 0,
2825 {
2826 vk::VK_IMAGE_ASPECT_COLOR_BIT,
2827 0, // mipLevel
2828 0, // arrayLayer
2829 1 // layerCount
2830 },
2831 { 0, 0, 0 },
2832 {
2833 (deUint32)m_imageWidth,
2834 (deUint32)m_imageHeight,
2835 1u
2836 }
2837 };
2838
2839 {
2840 void* const ptr = mapMemory(vkd, device, *memory, 4 * m_imageWidth * m_imageHeight);
2841 de::Random rng (m_seed);
2842
2843 {
2844 deUint8* const data = (deUint8*)ptr;
2845
2846 for (size_t ndx = 0; ndx < (size_t)(4 * m_imageWidth * m_imageHeight); ndx++)
2847 data[ndx] = rng.getUint8();
2848 }
2849
2850 vk::flushMappedMemoryRange(vkd, device, *memory, 0, VK_WHOLE_SIZE);
2851 vkd.unmapMemory(device, *memory);
2852 }
2853
2854 vkd.cmdPipelineBarrier(*commandBuffer, vk::VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1, &preImageBarrier);
2855 vkd.cmdCopyBufferToImage(*commandBuffer, *srcBuffer, *m_srcImage, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
2856 vkd.cmdPipelineBarrier(*commandBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1, &postImageBarrier);
2857
2858 endCommandBuffer(vkd, *commandBuffer);
2859 submitCommandsAndWait(vkd, device, queue, *commandBuffer);
2860 }
2861 }
2862
logSubmit(TestLog & log,size_t commandIndex) const2863 void BufferCopyFromImage::logSubmit (TestLog& log, size_t commandIndex) const
2864 {
2865 log << TestLog::Message << commandIndex << ":" << getName() << " Copy buffer data from image" << TestLog::EndMessage;
2866 }
2867
submit(SubmitContext & context)2868 void BufferCopyFromImage::submit (SubmitContext& context)
2869 {
2870 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
2871 const vk::VkCommandBuffer commandBuffer = context.getCommandBuffer();
2872 const vk::VkBufferImageCopy region =
2873 {
2874 0,
2875 0, 0,
2876 {
2877 vk::VK_IMAGE_ASPECT_COLOR_BIT,
2878 0, // mipLevel
2879 0, // arrayLayer
2880 1 // layerCount
2881 },
2882 { 0, 0, 0 },
2883 {
2884 (deUint32)m_imageWidth,
2885 (deUint32)m_imageHeight,
2886 1u
2887 }
2888 };
2889
2890 vkd.cmdCopyImageToBuffer(commandBuffer, *m_srcImage, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, context.getBuffer(), 1, ®ion);
2891 }
2892
verify(VerifyContext & context,size_t)2893 void BufferCopyFromImage::verify (VerifyContext& context, size_t)
2894 {
2895 ReferenceMemory& reference (context.getReference());
2896 de::Random rng (m_seed);
2897
2898 for (size_t ndx = 0; ndx < (size_t)(4 * m_imageWidth * m_imageHeight); ndx++)
2899 reference.set(ndx, rng.getUint8());
2900 }
2901
2902 class ImageCopyToBuffer : public CmdCommand
2903 {
2904 public:
ImageCopyToBuffer(vk::VkImageLayout imageLayout)2905 ImageCopyToBuffer (vk::VkImageLayout imageLayout) : m_imageLayout (imageLayout) {}
~ImageCopyToBuffer(void)2906 ~ImageCopyToBuffer (void) {}
getName(void) const2907 const char* getName (void) const { return "BufferCopyToImage"; }
2908
2909 void logPrepare (TestLog& log, size_t commandIndex) const;
2910 void prepare (PrepareContext& context);
2911 void logSubmit (TestLog& log, size_t commandIndex) const;
2912 void submit (SubmitContext& context);
2913 void verify (VerifyContext& context, size_t commandIndex);
2914
2915 private:
2916 vk::VkImageLayout m_imageLayout;
2917 vk::VkDeviceSize m_bufferSize;
2918 vk::Move<vk::VkBuffer> m_dstBuffer;
2919 vk::Move<vk::VkDeviceMemory> m_memory;
2920 vk::VkDeviceSize m_imageMemorySize;
2921 deInt32 m_imageWidth;
2922 deInt32 m_imageHeight;
2923 };
2924
logPrepare(TestLog & log,size_t commandIndex) const2925 void ImageCopyToBuffer::logPrepare (TestLog& log, size_t commandIndex) const
2926 {
2927 log << TestLog::Message << commandIndex << ":" << getName() << " Allocate destination buffer for image to buffer copy." << TestLog::EndMessage;
2928 }
2929
prepare(PrepareContext & context)2930 void ImageCopyToBuffer::prepare (PrepareContext& context)
2931 {
2932 const vk::InstanceInterface& vki = context.getContext().getInstanceInterface();
2933 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
2934 const vk::VkPhysicalDevice physicalDevice = context.getContext().getPhysicalDevice();
2935 const vk::VkDevice device = context.getContext().getDevice();
2936 const vector<deUint32>& queueFamilies = context.getContext().getQueueFamilies();
2937
2938 m_imageWidth = context.getImageWidth();
2939 m_imageHeight = context.getImageHeight();
2940 m_bufferSize = 4 * m_imageWidth * m_imageHeight;
2941 m_imageMemorySize = context.getImageMemorySize();
2942 m_dstBuffer = createBuffer(vkd, device, m_bufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT, vk::VK_SHARING_MODE_EXCLUSIVE, queueFamilies);
2943 m_memory = bindBufferMemory(vki, vkd, physicalDevice, device, *m_dstBuffer, vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
2944 }
2945
logSubmit(TestLog & log,size_t commandIndex) const2946 void ImageCopyToBuffer::logSubmit (TestLog& log, size_t commandIndex) const
2947 {
2948 log << TestLog::Message << commandIndex << ":" << getName() << " Copy image to buffer" << TestLog::EndMessage;
2949 }
2950
submit(SubmitContext & context)2951 void ImageCopyToBuffer::submit (SubmitContext& context)
2952 {
2953 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
2954 const vk::VkCommandBuffer commandBuffer = context.getCommandBuffer();
2955 const vk::VkBufferImageCopy region =
2956 {
2957 0,
2958 0, 0,
2959 {
2960 vk::VK_IMAGE_ASPECT_COLOR_BIT,
2961 0, // mipLevel
2962 0, // arrayLayer
2963 1 // layerCount
2964 },
2965 { 0, 0, 0 },
2966 {
2967 (deUint32)m_imageWidth,
2968 (deUint32)m_imageHeight,
2969 1u
2970 }
2971 };
2972
2973 vkd.cmdCopyImageToBuffer(commandBuffer, context.getImage(), m_imageLayout, *m_dstBuffer, 1, ®ion);
2974 }
2975
verify(VerifyContext & context,size_t commandIndex)2976 void ImageCopyToBuffer::verify (VerifyContext& context, size_t commandIndex)
2977 {
2978 tcu::ResultCollector& resultCollector (context.getResultCollector());
2979 ReferenceMemory& reference (context.getReference());
2980 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
2981 const vk::VkDevice device = context.getContext().getDevice();
2982 const vk::VkQueue queue = context.getContext().getQueue();
2983 const vk::VkCommandPool commandPool = context.getContext().getCommandPool();
2984 const vk::Unique<vk::VkCommandBuffer> commandBuffer (createBeginCommandBuffer(vkd, device, commandPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
2985 const vk::VkBufferMemoryBarrier barrier =
2986 {
2987 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
2988 DE_NULL,
2989
2990 vk::VK_ACCESS_TRANSFER_WRITE_BIT,
2991 vk::VK_ACCESS_HOST_READ_BIT,
2992
2993 VK_QUEUE_FAMILY_IGNORED,
2994 VK_QUEUE_FAMILY_IGNORED,
2995 *m_dstBuffer,
2996 0,
2997 VK_WHOLE_SIZE
2998 };
2999
3000 vkd.cmdPipelineBarrier(*commandBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 1, &barrier, 0, (const vk::VkImageMemoryBarrier*)DE_NULL);
3001
3002 endCommandBuffer(vkd, *commandBuffer);
3003 submitCommandsAndWait(vkd, device, queue, *commandBuffer);
3004
3005 reference.setUndefined(0, (size_t)m_imageMemorySize);
3006 {
3007 void* const ptr = mapMemory(vkd, device, *m_memory, m_bufferSize);
3008 const ConstPixelBufferAccess referenceImage (context.getReferenceImage().getAccess());
3009 const ConstPixelBufferAccess resultImage (TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8), m_imageWidth, m_imageHeight, 1, ptr);
3010
3011 vk::invalidateMappedMemoryRange(vkd, device, *m_memory, 0, VK_WHOLE_SIZE);
3012
3013 if (!tcu::intThresholdCompare(context.getLog(), (de::toString(commandIndex) + ":" + getName()).c_str(), (de::toString(commandIndex) + ":" + getName()).c_str(), referenceImage, resultImage, UVec4(0), tcu::COMPARE_LOG_ON_ERROR))
3014 resultCollector.fail(de::toString(commandIndex) + ":" + getName() + " Image comparison failed");
3015
3016 vkd.unmapMemory(device, *m_memory);
3017 }
3018 }
3019
3020 class ImageCopyFromBuffer : public CmdCommand
3021 {
3022 public:
ImageCopyFromBuffer(deUint32 seed,vk::VkImageLayout imageLayout)3023 ImageCopyFromBuffer (deUint32 seed, vk::VkImageLayout imageLayout) : m_seed(seed), m_imageLayout(imageLayout) {}
~ImageCopyFromBuffer(void)3024 ~ImageCopyFromBuffer (void) {}
getName(void) const3025 const char* getName (void) const { return "ImageCopyFromBuffer"; }
3026
3027 void logPrepare (TestLog& log, size_t commandIndex) const;
3028 void prepare (PrepareContext& context);
3029 void logSubmit (TestLog& log, size_t commandIndex) const;
3030 void submit (SubmitContext& context);
3031 void verify (VerifyContext& context, size_t commandIndex);
3032
3033 private:
3034 const deUint32 m_seed;
3035 const vk::VkImageLayout m_imageLayout;
3036 deInt32 m_imageWidth;
3037 deInt32 m_imageHeight;
3038 vk::VkDeviceSize m_imageMemorySize;
3039 vk::VkDeviceSize m_bufferSize;
3040 vk::Move<vk::VkBuffer> m_srcBuffer;
3041 vk::Move<vk::VkDeviceMemory> m_memory;
3042 };
3043
logPrepare(TestLog & log,size_t commandIndex) const3044 void ImageCopyFromBuffer::logPrepare (TestLog& log, size_t commandIndex) const
3045 {
3046 log << TestLog::Message << commandIndex << ":" << getName() << " Allocate source buffer for buffer to image copy. Seed: " << m_seed << TestLog::EndMessage;
3047 }
3048
prepare(PrepareContext & context)3049 void ImageCopyFromBuffer::prepare (PrepareContext& context)
3050 {
3051 const vk::InstanceInterface& vki = context.getContext().getInstanceInterface();
3052 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
3053 const vk::VkPhysicalDevice physicalDevice = context.getContext().getPhysicalDevice();
3054 const vk::VkDevice device = context.getContext().getDevice();
3055 const vector<deUint32>& queueFamilies = context.getContext().getQueueFamilies();
3056
3057 m_imageWidth = context.getImageHeight();
3058 m_imageHeight = context.getImageWidth();
3059 m_imageMemorySize = context.getImageMemorySize();
3060 m_bufferSize = m_imageWidth * m_imageHeight * 4;
3061 m_srcBuffer = createBuffer(vkd, device, m_bufferSize, vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT, vk::VK_SHARING_MODE_EXCLUSIVE, queueFamilies);
3062 m_memory = bindBufferMemory(vki, vkd, physicalDevice, device, *m_srcBuffer, vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
3063
3064 {
3065 void* const ptr = mapMemory(vkd, device, *m_memory, m_bufferSize);
3066 de::Random rng (m_seed);
3067
3068 {
3069 deUint8* const data = (deUint8*)ptr;
3070
3071 for (size_t ndx = 0; ndx < (size_t)m_bufferSize; ndx++)
3072 data[ndx] = rng.getUint8();
3073 }
3074
3075 vk::flushMappedMemoryRange(vkd, device, *m_memory, 0, VK_WHOLE_SIZE);
3076 vkd.unmapMemory(device, *m_memory);
3077 }
3078 }
3079
logSubmit(TestLog & log,size_t commandIndex) const3080 void ImageCopyFromBuffer::logSubmit (TestLog& log, size_t commandIndex) const
3081 {
3082 log << TestLog::Message << commandIndex << ":" << getName() << " Copy image data from buffer" << TestLog::EndMessage;
3083 }
3084
submit(SubmitContext & context)3085 void ImageCopyFromBuffer::submit (SubmitContext& context)
3086 {
3087 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
3088 const vk::VkCommandBuffer commandBuffer = context.getCommandBuffer();
3089 const vk::VkBufferImageCopy region =
3090 {
3091 0,
3092 0, 0,
3093 {
3094 vk::VK_IMAGE_ASPECT_COLOR_BIT,
3095 0, // mipLevel
3096 0, // arrayLayer
3097 1 // layerCount
3098 },
3099 { 0, 0, 0 },
3100 {
3101 (deUint32)m_imageWidth,
3102 (deUint32)m_imageHeight,
3103 1u
3104 }
3105 };
3106
3107 vkd.cmdCopyBufferToImage(commandBuffer, *m_srcBuffer, context.getImage(), m_imageLayout, 1, ®ion);
3108 }
3109
verify(VerifyContext & context,size_t)3110 void ImageCopyFromBuffer::verify (VerifyContext& context, size_t)
3111 {
3112 ReferenceMemory& reference (context.getReference());
3113 de::Random rng (m_seed);
3114
3115 reference.setUndefined(0, (size_t)m_imageMemorySize);
3116
3117 {
3118 const PixelBufferAccess& refAccess (context.getReferenceImage().getAccess());
3119
3120 for (deInt32 y = 0; y < m_imageHeight; y++)
3121 for (deInt32 x = 0; x < m_imageWidth; x++)
3122 {
3123 const deUint8 r8 = rng.getUint8();
3124 const deUint8 g8 = rng.getUint8();
3125 const deUint8 b8 = rng.getUint8();
3126 const deUint8 a8 = rng.getUint8();
3127
3128 refAccess.setPixel(UVec4(r8, g8, b8, a8), x, y);
3129 }
3130 }
3131 }
3132
3133 class ImageCopyFromImage : public CmdCommand
3134 {
3135 public:
ImageCopyFromImage(deUint32 seed,vk::VkImageLayout imageLayout)3136 ImageCopyFromImage (deUint32 seed, vk::VkImageLayout imageLayout) : m_seed(seed), m_imageLayout(imageLayout) {}
~ImageCopyFromImage(void)3137 ~ImageCopyFromImage (void) {}
getName(void) const3138 const char* getName (void) const { return "ImageCopyFromImage"; }
3139
3140 void logPrepare (TestLog& log, size_t commandIndex) const;
3141 void prepare (PrepareContext& context);
3142 void logSubmit (TestLog& log, size_t commandIndex) const;
3143 void submit (SubmitContext& context);
3144 void verify (VerifyContext& context, size_t commandIndex);
3145
3146 private:
3147 const deUint32 m_seed;
3148 const vk::VkImageLayout m_imageLayout;
3149 deInt32 m_imageWidth;
3150 deInt32 m_imageHeight;
3151 vk::VkDeviceSize m_imageMemorySize;
3152 vk::Move<vk::VkImage> m_srcImage;
3153 vk::Move<vk::VkDeviceMemory> m_memory;
3154 };
3155
logPrepare(TestLog & log,size_t commandIndex) const3156 void ImageCopyFromImage::logPrepare (TestLog& log, size_t commandIndex) const
3157 {
3158 log << TestLog::Message << commandIndex << ":" << getName() << " Allocate source image for image to image copy." << TestLog::EndMessage;
3159 }
3160
prepare(PrepareContext & context)3161 void ImageCopyFromImage::prepare (PrepareContext& context)
3162 {
3163 const vk::InstanceInterface& vki = context.getContext().getInstanceInterface();
3164 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
3165 const vk::VkPhysicalDevice physicalDevice = context.getContext().getPhysicalDevice();
3166 const vk::VkDevice device = context.getContext().getDevice();
3167 const vk::VkQueue queue = context.getContext().getQueue();
3168 const vk::VkCommandPool commandPool = context.getContext().getCommandPool();
3169 const vector<deUint32>& queueFamilies = context.getContext().getQueueFamilies();
3170
3171 m_imageWidth = context.getImageWidth();
3172 m_imageHeight = context.getImageHeight();
3173 m_imageMemorySize = context.getImageMemorySize();
3174
3175 {
3176 const vk::VkImageCreateInfo createInfo =
3177 {
3178 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
3179 DE_NULL,
3180
3181 0,
3182 vk::VK_IMAGE_TYPE_2D,
3183 vk::VK_FORMAT_R8G8B8A8_UNORM,
3184 {
3185 (deUint32)m_imageWidth,
3186 (deUint32)m_imageHeight,
3187 1u,
3188 },
3189 1, 1, // mipLevels, arrayLayers
3190 vk::VK_SAMPLE_COUNT_1_BIT,
3191
3192 vk::VK_IMAGE_TILING_OPTIMAL,
3193 vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT|vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
3194 vk::VK_SHARING_MODE_EXCLUSIVE,
3195
3196 (deUint32)queueFamilies.size(),
3197 &queueFamilies[0],
3198 vk::VK_IMAGE_LAYOUT_UNDEFINED
3199 };
3200
3201 m_srcImage = vk::createImage(vkd, device, &createInfo);
3202 }
3203
3204 m_memory = bindImageMemory(vki, vkd, physicalDevice, device, *m_srcImage, 0);
3205
3206 {
3207 const vk::Unique<vk::VkBuffer> srcBuffer (createBuffer(vkd, device, 4 * m_imageWidth * m_imageHeight, vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT, vk::VK_SHARING_MODE_EXCLUSIVE, queueFamilies));
3208 const vk::Unique<vk::VkDeviceMemory> memory (bindBufferMemory(vki, vkd, physicalDevice, device, *srcBuffer, vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));
3209 const vk::Unique<vk::VkCommandBuffer> commandBuffer (createBeginCommandBuffer(vkd, device, commandPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
3210 const vk::VkImageMemoryBarrier preImageBarrier =
3211 {
3212 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
3213 DE_NULL,
3214
3215 0,
3216 vk::VK_ACCESS_TRANSFER_WRITE_BIT,
3217
3218 vk::VK_IMAGE_LAYOUT_UNDEFINED,
3219 vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
3220
3221 VK_QUEUE_FAMILY_IGNORED,
3222 VK_QUEUE_FAMILY_IGNORED,
3223
3224 *m_srcImage,
3225 {
3226 vk::VK_IMAGE_ASPECT_COLOR_BIT,
3227 0, // Mip level
3228 1, // Mip level count
3229 0, // Layer
3230 1 // Layer count
3231 }
3232 };
3233 const vk::VkImageMemoryBarrier postImageBarrier =
3234 {
3235 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
3236 DE_NULL,
3237
3238 vk::VK_ACCESS_TRANSFER_WRITE_BIT,
3239 0,
3240
3241 vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
3242 vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
3243
3244 VK_QUEUE_FAMILY_IGNORED,
3245 VK_QUEUE_FAMILY_IGNORED,
3246
3247 *m_srcImage,
3248 {
3249 vk::VK_IMAGE_ASPECT_COLOR_BIT,
3250 0, // Mip level
3251 1, // Mip level count
3252 0, // Layer
3253 1 // Layer count
3254 }
3255 };
3256 const vk::VkBufferImageCopy region =
3257 {
3258 0,
3259 0, 0,
3260 {
3261 vk::VK_IMAGE_ASPECT_COLOR_BIT,
3262 0, // mipLevel
3263 0, // arrayLayer
3264 1 // layerCount
3265 },
3266 { 0, 0, 0 },
3267 {
3268 (deUint32)m_imageWidth,
3269 (deUint32)m_imageHeight,
3270 1u
3271 }
3272 };
3273
3274 {
3275 void* const ptr = mapMemory(vkd, device, *memory, 4 * m_imageWidth * m_imageHeight);
3276 de::Random rng (m_seed);
3277
3278 {
3279 deUint8* const data = (deUint8*)ptr;
3280
3281 for (size_t ndx = 0; ndx < (size_t)(4 * m_imageWidth * m_imageHeight); ndx++)
3282 data[ndx] = rng.getUint8();
3283 }
3284
3285 vk::flushMappedMemoryRange(vkd, device, *memory, 0, VK_WHOLE_SIZE);
3286 vkd.unmapMemory(device, *memory);
3287 }
3288
3289 vkd.cmdPipelineBarrier(*commandBuffer, vk::VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1, &preImageBarrier);
3290 vkd.cmdCopyBufferToImage(*commandBuffer, *srcBuffer, *m_srcImage, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
3291 vkd.cmdPipelineBarrier(*commandBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1, &postImageBarrier);
3292
3293 endCommandBuffer(vkd, *commandBuffer);
3294 submitCommandsAndWait(vkd, device, queue, *commandBuffer);
3295 }
3296 }
3297
logSubmit(TestLog & log,size_t commandIndex) const3298 void ImageCopyFromImage::logSubmit (TestLog& log, size_t commandIndex) const
3299 {
3300 log << TestLog::Message << commandIndex << ":" << getName() << " Copy image data from another image" << TestLog::EndMessage;
3301 }
3302
submit(SubmitContext & context)3303 void ImageCopyFromImage::submit (SubmitContext& context)
3304 {
3305 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
3306 const vk::VkCommandBuffer commandBuffer = context.getCommandBuffer();
3307 const vk::VkImageCopy region =
3308 {
3309 {
3310 vk::VK_IMAGE_ASPECT_COLOR_BIT,
3311 0, // mipLevel
3312 0, // arrayLayer
3313 1 // layerCount
3314 },
3315 { 0, 0, 0 },
3316
3317 {
3318 vk::VK_IMAGE_ASPECT_COLOR_BIT,
3319 0, // mipLevel
3320 0, // arrayLayer
3321 1 // layerCount
3322 },
3323 { 0, 0, 0 },
3324 {
3325 (deUint32)m_imageWidth,
3326 (deUint32)m_imageHeight,
3327 1u
3328 }
3329 };
3330
3331 vkd.cmdCopyImage(commandBuffer, *m_srcImage, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, context.getImage(), m_imageLayout, 1, ®ion);
3332 }
3333
verify(VerifyContext & context,size_t)3334 void ImageCopyFromImage::verify (VerifyContext& context, size_t)
3335 {
3336 ReferenceMemory& reference (context.getReference());
3337 de::Random rng (m_seed);
3338
3339 reference.setUndefined(0, (size_t)m_imageMemorySize);
3340
3341 {
3342 const PixelBufferAccess& refAccess (context.getReferenceImage().getAccess());
3343
3344 for (deInt32 y = 0; y < m_imageHeight; y++)
3345 for (deInt32 x = 0; x < m_imageWidth; x++)
3346 {
3347 const deUint8 r8 = rng.getUint8();
3348 const deUint8 g8 = rng.getUint8();
3349 const deUint8 b8 = rng.getUint8();
3350 const deUint8 a8 = rng.getUint8();
3351
3352 refAccess.setPixel(UVec4(r8, g8, b8, a8), x, y);
3353 }
3354 }
3355 }
3356
3357 class ImageCopyToImage : public CmdCommand
3358 {
3359 public:
ImageCopyToImage(vk::VkImageLayout imageLayout)3360 ImageCopyToImage (vk::VkImageLayout imageLayout) : m_imageLayout(imageLayout) {}
~ImageCopyToImage(void)3361 ~ImageCopyToImage (void) {}
getName(void) const3362 const char* getName (void) const { return "ImageCopyToImage"; }
3363
3364 void logPrepare (TestLog& log, size_t commandIndex) const;
3365 void prepare (PrepareContext& context);
3366 void logSubmit (TestLog& log, size_t commandIndex) const;
3367 void submit (SubmitContext& context);
3368 void verify (VerifyContext& context, size_t commandIndex);
3369
3370 private:
3371 const vk::VkImageLayout m_imageLayout;
3372 deInt32 m_imageWidth;
3373 deInt32 m_imageHeight;
3374 vk::VkDeviceSize m_imageMemorySize;
3375 vk::Move<vk::VkImage> m_dstImage;
3376 vk::Move<vk::VkDeviceMemory> m_memory;
3377 };
3378
logPrepare(TestLog & log,size_t commandIndex) const3379 void ImageCopyToImage::logPrepare (TestLog& log, size_t commandIndex) const
3380 {
3381 log << TestLog::Message << commandIndex << ":" << getName() << " Allocate destination image for image to image copy." << TestLog::EndMessage;
3382 }
3383
prepare(PrepareContext & context)3384 void ImageCopyToImage::prepare (PrepareContext& context)
3385 {
3386 const vk::InstanceInterface& vki = context.getContext().getInstanceInterface();
3387 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
3388 const vk::VkPhysicalDevice physicalDevice = context.getContext().getPhysicalDevice();
3389 const vk::VkDevice device = context.getContext().getDevice();
3390 const vk::VkQueue queue = context.getContext().getQueue();
3391 const vk::VkCommandPool commandPool = context.getContext().getCommandPool();
3392 const vector<deUint32>& queueFamilies = context.getContext().getQueueFamilies();
3393
3394 m_imageWidth = context.getImageWidth();
3395 m_imageHeight = context.getImageHeight();
3396 m_imageMemorySize = context.getImageMemorySize();
3397
3398 {
3399 const vk::VkImageCreateInfo createInfo =
3400 {
3401 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
3402 DE_NULL,
3403
3404 0,
3405 vk::VK_IMAGE_TYPE_2D,
3406 vk::VK_FORMAT_R8G8B8A8_UNORM,
3407 {
3408 (deUint32)m_imageWidth,
3409 (deUint32)m_imageHeight,
3410 1u,
3411 },
3412 1, 1, // mipLevels, arrayLayers
3413 vk::VK_SAMPLE_COUNT_1_BIT,
3414
3415 vk::VK_IMAGE_TILING_OPTIMAL,
3416 vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT|vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
3417 vk::VK_SHARING_MODE_EXCLUSIVE,
3418
3419 (deUint32)queueFamilies.size(),
3420 &queueFamilies[0],
3421 vk::VK_IMAGE_LAYOUT_UNDEFINED
3422 };
3423
3424 m_dstImage = vk::createImage(vkd, device, &createInfo);
3425 }
3426
3427 m_memory = bindImageMemory(vki, vkd, physicalDevice, device, *m_dstImage, 0);
3428
3429 {
3430 const vk::Unique<vk::VkCommandBuffer> commandBuffer (createBeginCommandBuffer(vkd, device, commandPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
3431 const vk::VkImageMemoryBarrier barrier =
3432 {
3433 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
3434 DE_NULL,
3435
3436 0,
3437 vk::VK_ACCESS_TRANSFER_WRITE_BIT,
3438
3439 vk::VK_IMAGE_LAYOUT_UNDEFINED,
3440 vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
3441
3442 VK_QUEUE_FAMILY_IGNORED,
3443 VK_QUEUE_FAMILY_IGNORED,
3444
3445 *m_dstImage,
3446 {
3447 vk::VK_IMAGE_ASPECT_COLOR_BIT,
3448 0, // Mip level
3449 1, // Mip level count
3450 0, // Layer
3451 1 // Layer count
3452 }
3453 };
3454
3455 vkd.cmdPipelineBarrier(*commandBuffer, vk::VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1, &barrier);
3456
3457 endCommandBuffer(vkd, *commandBuffer);
3458 submitCommandsAndWait(vkd, device, queue, *commandBuffer);
3459 }
3460 }
3461
logSubmit(TestLog & log,size_t commandIndex) const3462 void ImageCopyToImage::logSubmit (TestLog& log, size_t commandIndex) const
3463 {
3464 log << TestLog::Message << commandIndex << ":" << getName() << " Copy image to another image" << TestLog::EndMessage;
3465 }
3466
submit(SubmitContext & context)3467 void ImageCopyToImage::submit (SubmitContext& context)
3468 {
3469 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
3470 const vk::VkCommandBuffer commandBuffer = context.getCommandBuffer();
3471 const vk::VkImageCopy region =
3472 {
3473 {
3474 vk::VK_IMAGE_ASPECT_COLOR_BIT,
3475 0, // mipLevel
3476 0, // arrayLayer
3477 1 // layerCount
3478 },
3479 { 0, 0, 0 },
3480
3481 {
3482 vk::VK_IMAGE_ASPECT_COLOR_BIT,
3483 0, // mipLevel
3484 0, // arrayLayer
3485 1 // layerCount
3486 },
3487 { 0, 0, 0 },
3488 {
3489 (deUint32)m_imageWidth,
3490 (deUint32)m_imageHeight,
3491 1u
3492 }
3493 };
3494
3495 vkd.cmdCopyImage(commandBuffer, context.getImage(), m_imageLayout, *m_dstImage, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
3496 }
3497
verify(VerifyContext & context,size_t commandIndex)3498 void ImageCopyToImage::verify (VerifyContext& context, size_t commandIndex)
3499 {
3500 tcu::ResultCollector& resultCollector (context.getResultCollector());
3501 const vk::InstanceInterface& vki = context.getContext().getInstanceInterface();
3502 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
3503 const vk::VkPhysicalDevice physicalDevice = context.getContext().getPhysicalDevice();
3504 const vk::VkDevice device = context.getContext().getDevice();
3505 const vk::VkQueue queue = context.getContext().getQueue();
3506 const vk::VkCommandPool commandPool = context.getContext().getCommandPool();
3507 const vk::Unique<vk::VkCommandBuffer> commandBuffer (createBeginCommandBuffer(vkd, device, commandPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
3508 const vector<deUint32>& queueFamilies = context.getContext().getQueueFamilies();
3509 const vk::Unique<vk::VkBuffer> dstBuffer (createBuffer(vkd, device, 4 * m_imageWidth * m_imageHeight, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT, vk::VK_SHARING_MODE_EXCLUSIVE, queueFamilies));
3510 const vk::Unique<vk::VkDeviceMemory> memory (bindBufferMemory(vki, vkd, physicalDevice, device, *dstBuffer, vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));
3511 {
3512 const vk::VkImageMemoryBarrier imageBarrier =
3513 {
3514 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
3515 DE_NULL,
3516
3517 vk::VK_ACCESS_TRANSFER_WRITE_BIT,
3518 vk::VK_ACCESS_TRANSFER_READ_BIT,
3519
3520 vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
3521 vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
3522
3523 VK_QUEUE_FAMILY_IGNORED,
3524 VK_QUEUE_FAMILY_IGNORED,
3525
3526 *m_dstImage,
3527 {
3528 vk::VK_IMAGE_ASPECT_COLOR_BIT,
3529 0, // Mip level
3530 1, // Mip level count
3531 0, // Layer
3532 1 // Layer count
3533 }
3534 };
3535 const vk::VkBufferMemoryBarrier bufferBarrier =
3536 {
3537 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
3538 DE_NULL,
3539
3540 vk::VK_ACCESS_TRANSFER_WRITE_BIT,
3541 vk::VK_ACCESS_HOST_READ_BIT,
3542
3543 VK_QUEUE_FAMILY_IGNORED,
3544 VK_QUEUE_FAMILY_IGNORED,
3545 *dstBuffer,
3546 0,
3547 VK_WHOLE_SIZE
3548 };
3549 const vk::VkBufferImageCopy region =
3550 {
3551 0,
3552 0, 0,
3553 {
3554 vk::VK_IMAGE_ASPECT_COLOR_BIT,
3555 0, // mipLevel
3556 0, // arrayLayer
3557 1 // layerCount
3558 },
3559 { 0, 0, 0 },
3560 {
3561 (deUint32)m_imageWidth,
3562 (deUint32)m_imageHeight,
3563 1u
3564 }
3565 };
3566
3567 vkd.cmdPipelineBarrier(*commandBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1, &imageBarrier);
3568 vkd.cmdCopyImageToBuffer(*commandBuffer, *m_dstImage, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *dstBuffer, 1, ®ion);
3569 vkd.cmdPipelineBarrier(*commandBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 1, &bufferBarrier, 0, (const vk::VkImageMemoryBarrier*)DE_NULL);
3570 }
3571
3572 endCommandBuffer(vkd, *commandBuffer);
3573 submitCommandsAndWait(vkd, device, queue, *commandBuffer);
3574
3575 {
3576 void* const ptr = mapMemory(vkd, device, *memory, 4 * m_imageWidth * m_imageHeight);
3577
3578 vk::invalidateMappedMemoryRange(vkd, device, *memory, 0, VK_WHOLE_SIZE);
3579
3580 {
3581 const deUint8* const data = (const deUint8*)ptr;
3582 const ConstPixelBufferAccess resAccess (TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8), m_imageWidth, m_imageHeight, 1, data);
3583 const ConstPixelBufferAccess& refAccess (context.getReferenceImage().getAccess());
3584
3585 if (!tcu::intThresholdCompare(context.getLog(), (de::toString(commandIndex) + ":" + getName()).c_str(), (de::toString(commandIndex) + ":" + getName()).c_str(), refAccess, resAccess, UVec4(0), tcu::COMPARE_LOG_ON_ERROR))
3586 resultCollector.fail(de::toString(commandIndex) + ":" + getName() + " Image comparison failed");
3587 }
3588
3589 vkd.unmapMemory(device, *memory);
3590 }
3591 }
3592
3593 enum BlitScale
3594 {
3595 BLIT_SCALE_20,
3596 BLIT_SCALE_10,
3597 };
3598
3599 class ImageBlitFromImage : public CmdCommand
3600 {
3601 public:
ImageBlitFromImage(deUint32 seed,BlitScale scale,vk::VkImageLayout imageLayout)3602 ImageBlitFromImage (deUint32 seed, BlitScale scale, vk::VkImageLayout imageLayout) : m_seed(seed), m_scale(scale), m_imageLayout(imageLayout) {}
~ImageBlitFromImage(void)3603 ~ImageBlitFromImage (void) {}
getName(void) const3604 const char* getName (void) const { return "ImageBlitFromImage"; }
3605
3606 void logPrepare (TestLog& log, size_t commandIndex) const;
3607 void prepare (PrepareContext& context);
3608 void logSubmit (TestLog& log, size_t commandIndex) const;
3609 void submit (SubmitContext& context);
3610 void verify (VerifyContext& context, size_t commandIndex);
3611
3612 private:
3613 const deUint32 m_seed;
3614 const BlitScale m_scale;
3615 const vk::VkImageLayout m_imageLayout;
3616 deInt32 m_imageWidth;
3617 deInt32 m_imageHeight;
3618 vk::VkDeviceSize m_imageMemorySize;
3619 deInt32 m_srcImageWidth;
3620 deInt32 m_srcImageHeight;
3621 vk::Move<vk::VkImage> m_srcImage;
3622 vk::Move<vk::VkDeviceMemory> m_memory;
3623 };
3624
logPrepare(TestLog & log,size_t commandIndex) const3625 void ImageBlitFromImage::logPrepare (TestLog& log, size_t commandIndex) const
3626 {
3627 log << TestLog::Message << commandIndex << ":" << getName() << " Allocate source image for image to image blit." << TestLog::EndMessage;
3628 }
3629
prepare(PrepareContext & context)3630 void ImageBlitFromImage::prepare (PrepareContext& context)
3631 {
3632 const vk::InstanceInterface& vki = context.getContext().getInstanceInterface();
3633 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
3634 const vk::VkPhysicalDevice physicalDevice = context.getContext().getPhysicalDevice();
3635 const vk::VkDevice device = context.getContext().getDevice();
3636 const vk::VkQueue queue = context.getContext().getQueue();
3637 const vk::VkCommandPool commandPool = context.getContext().getCommandPool();
3638 const vector<deUint32>& queueFamilies = context.getContext().getQueueFamilies();
3639
3640 m_imageWidth = context.getImageWidth();
3641 m_imageHeight = context.getImageHeight();
3642 m_imageMemorySize = context.getImageMemorySize();
3643
3644 if (m_scale == BLIT_SCALE_10)
3645 {
3646 m_srcImageWidth = m_imageWidth;
3647 m_srcImageHeight = m_imageHeight;
3648 }
3649 else if (m_scale == BLIT_SCALE_20)
3650 {
3651 m_srcImageWidth = m_imageWidth == 1 ? 1 : m_imageWidth / 2;
3652 m_srcImageHeight = m_imageHeight == 1 ? 1 : m_imageHeight / 2;
3653 }
3654 else
3655 DE_FATAL("Unsupported scale");
3656
3657 {
3658 const vk::VkImageCreateInfo createInfo =
3659 {
3660 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
3661 DE_NULL,
3662
3663 0,
3664 vk::VK_IMAGE_TYPE_2D,
3665 vk::VK_FORMAT_R8G8B8A8_UNORM,
3666 {
3667 (deUint32)m_srcImageWidth,
3668 (deUint32)m_srcImageHeight,
3669 1u,
3670 },
3671 1, 1, // mipLevels, arrayLayers
3672 vk::VK_SAMPLE_COUNT_1_BIT,
3673
3674 vk::VK_IMAGE_TILING_OPTIMAL,
3675 vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT|vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
3676 vk::VK_SHARING_MODE_EXCLUSIVE,
3677
3678 (deUint32)queueFamilies.size(),
3679 &queueFamilies[0],
3680 vk::VK_IMAGE_LAYOUT_UNDEFINED
3681 };
3682
3683 m_srcImage = vk::createImage(vkd, device, &createInfo);
3684 }
3685
3686 m_memory = bindImageMemory(vki, vkd, physicalDevice, device, *m_srcImage, 0);
3687
3688 {
3689 const vk::Unique<vk::VkBuffer> srcBuffer (createBuffer(vkd, device, 4 * m_srcImageWidth * m_srcImageHeight, vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT, vk::VK_SHARING_MODE_EXCLUSIVE, queueFamilies));
3690 const vk::Unique<vk::VkDeviceMemory> memory (bindBufferMemory(vki, vkd, physicalDevice, device, *srcBuffer, vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));
3691 const vk::Unique<vk::VkCommandBuffer> commandBuffer (createBeginCommandBuffer(vkd, device, commandPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
3692 const vk::VkImageMemoryBarrier preImageBarrier =
3693 {
3694 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
3695 DE_NULL,
3696
3697 0,
3698 vk::VK_ACCESS_TRANSFER_WRITE_BIT,
3699
3700 vk::VK_IMAGE_LAYOUT_UNDEFINED,
3701 vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
3702
3703 VK_QUEUE_FAMILY_IGNORED,
3704 VK_QUEUE_FAMILY_IGNORED,
3705
3706 *m_srcImage,
3707 {
3708 vk::VK_IMAGE_ASPECT_COLOR_BIT,
3709 0, // Mip level
3710 1, // Mip level count
3711 0, // Layer
3712 1 // Layer count
3713 }
3714 };
3715 const vk::VkImageMemoryBarrier postImageBarrier =
3716 {
3717 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
3718 DE_NULL,
3719
3720 vk::VK_ACCESS_TRANSFER_WRITE_BIT,
3721 0,
3722
3723 vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
3724 vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
3725
3726 VK_QUEUE_FAMILY_IGNORED,
3727 VK_QUEUE_FAMILY_IGNORED,
3728
3729 *m_srcImage,
3730 {
3731 vk::VK_IMAGE_ASPECT_COLOR_BIT,
3732 0, // Mip level
3733 1, // Mip level count
3734 0, // Layer
3735 1 // Layer count
3736 }
3737 };
3738 const vk::VkBufferImageCopy region =
3739 {
3740 0,
3741 0, 0,
3742 {
3743 vk::VK_IMAGE_ASPECT_COLOR_BIT,
3744 0, // mipLevel
3745 0, // arrayLayer
3746 1 // layerCount
3747 },
3748 { 0, 0, 0 },
3749 {
3750 (deUint32)m_srcImageWidth,
3751 (deUint32)m_srcImageHeight,
3752 1u
3753 }
3754 };
3755
3756 {
3757 void* const ptr = mapMemory(vkd, device, *memory, 4 * m_srcImageWidth * m_srcImageHeight);
3758 de::Random rng (m_seed);
3759
3760 {
3761 deUint8* const data = (deUint8*)ptr;
3762
3763 for (size_t ndx = 0; ndx < (size_t)(4 * m_srcImageWidth * m_srcImageHeight); ndx++)
3764 data[ndx] = rng.getUint8();
3765 }
3766
3767 vk::flushMappedMemoryRange(vkd, device, *memory, 0, VK_WHOLE_SIZE);
3768 vkd.unmapMemory(device, *memory);
3769 }
3770
3771 vkd.cmdPipelineBarrier(*commandBuffer, vk::VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1, &preImageBarrier);
3772 vkd.cmdCopyBufferToImage(*commandBuffer, *srcBuffer, *m_srcImage, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
3773 vkd.cmdPipelineBarrier(*commandBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1, &postImageBarrier);
3774
3775 endCommandBuffer(vkd, *commandBuffer);
3776 submitCommandsAndWait(vkd, device, queue, *commandBuffer);
3777 }
3778 }
3779
logSubmit(TestLog & log,size_t commandIndex) const3780 void ImageBlitFromImage::logSubmit (TestLog& log, size_t commandIndex) const
3781 {
3782 log << TestLog::Message << commandIndex << ":" << getName() << " Blit from another image" << (m_scale == BLIT_SCALE_20 ? " scale 2x" : "") << TestLog::EndMessage;
3783 }
3784
submit(SubmitContext & context)3785 void ImageBlitFromImage::submit (SubmitContext& context)
3786 {
3787 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
3788 const vk::VkCommandBuffer commandBuffer = context.getCommandBuffer();
3789 const vk::VkImageBlit region =
3790 {
3791 // Src
3792 {
3793 vk::VK_IMAGE_ASPECT_COLOR_BIT,
3794 0, // mipLevel
3795 0, // arrayLayer
3796 1 // layerCount
3797 },
3798 {
3799 { 0, 0, 0 },
3800 {
3801 m_srcImageWidth,
3802 m_srcImageHeight,
3803 1
3804 },
3805 },
3806
3807 // Dst
3808 {
3809 vk::VK_IMAGE_ASPECT_COLOR_BIT,
3810 0, // mipLevel
3811 0, // arrayLayer
3812 1 // layerCount
3813 },
3814 {
3815 { 0, 0, 0 },
3816 {
3817 m_imageWidth,
3818 m_imageHeight,
3819 1u
3820 }
3821 }
3822 };
3823 vkd.cmdBlitImage(commandBuffer, *m_srcImage, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, context.getImage(), m_imageLayout, 1, ®ion, vk::VK_FILTER_NEAREST);
3824 }
3825
verify(VerifyContext & context,size_t)3826 void ImageBlitFromImage::verify (VerifyContext& context, size_t)
3827 {
3828 ReferenceMemory& reference (context.getReference());
3829 de::Random rng (m_seed);
3830
3831 reference.setUndefined(0, (size_t)m_imageMemorySize);
3832
3833 {
3834 const PixelBufferAccess& refAccess (context.getReferenceImage().getAccess());
3835
3836 if (m_scale == BLIT_SCALE_10)
3837 {
3838 for (deInt32 y = 0; y < m_imageHeight; y++)
3839 for (deInt32 x = 0; x < m_imageWidth; x++)
3840 {
3841 const deUint8 r8 = rng.getUint8();
3842 const deUint8 g8 = rng.getUint8();
3843 const deUint8 b8 = rng.getUint8();
3844 const deUint8 a8 = rng.getUint8();
3845
3846 refAccess.setPixel(UVec4(r8, g8, b8, a8), x, y);
3847 }
3848 }
3849 else if (m_scale == BLIT_SCALE_20)
3850 {
3851 tcu::TextureLevel source (TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8), m_srcImageWidth, m_srcImageHeight);
3852 const float xscale = ((float)m_srcImageWidth) / (float)m_imageWidth;
3853 const float yscale = ((float)m_srcImageHeight) / (float)m_imageHeight;
3854
3855 for (deInt32 y = 0; y < m_srcImageHeight; y++)
3856 for (deInt32 x = 0; x < m_srcImageWidth; x++)
3857 {
3858 const deUint8 r8 = rng.getUint8();
3859 const deUint8 g8 = rng.getUint8();
3860 const deUint8 b8 = rng.getUint8();
3861 const deUint8 a8 = rng.getUint8();
3862
3863 source.getAccess().setPixel(UVec4(r8, g8, b8, a8), x, y);
3864 }
3865
3866 for (deInt32 y = 0; y < m_imageHeight; y++)
3867 for (deInt32 x = 0; x < m_imageWidth; x++)
3868 refAccess.setPixel(source.getAccess().getPixelUint(int((float(x) + 0.5f) * xscale), int((float(y) + 0.5f) * yscale)), x, y);
3869 }
3870 else
3871 DE_FATAL("Unsupported scale");
3872 }
3873 }
3874
3875 class ImageBlitToImage : public CmdCommand
3876 {
3877 public:
ImageBlitToImage(BlitScale scale,vk::VkImageLayout imageLayout)3878 ImageBlitToImage (BlitScale scale, vk::VkImageLayout imageLayout) : m_scale(scale), m_imageLayout(imageLayout) {}
~ImageBlitToImage(void)3879 ~ImageBlitToImage (void) {}
getName(void) const3880 const char* getName (void) const { return "ImageBlitToImage"; }
3881
3882 void logPrepare (TestLog& log, size_t commandIndex) const;
3883 void prepare (PrepareContext& context);
3884 void logSubmit (TestLog& log, size_t commandIndex) const;
3885 void submit (SubmitContext& context);
3886 void verify (VerifyContext& context, size_t commandIndex);
3887
3888 private:
3889 const BlitScale m_scale;
3890 const vk::VkImageLayout m_imageLayout;
3891 deInt32 m_imageWidth;
3892 deInt32 m_imageHeight;
3893 vk::VkDeviceSize m_imageMemorySize;
3894 deInt32 m_dstImageWidth;
3895 deInt32 m_dstImageHeight;
3896 vk::Move<vk::VkImage> m_dstImage;
3897 vk::Move<vk::VkDeviceMemory> m_memory;
3898 };
3899
logPrepare(TestLog & log,size_t commandIndex) const3900 void ImageBlitToImage::logPrepare (TestLog& log, size_t commandIndex) const
3901 {
3902 log << TestLog::Message << commandIndex << ":" << getName() << " Allocate destination image for image to image blit." << TestLog::EndMessage;
3903 }
3904
prepare(PrepareContext & context)3905 void ImageBlitToImage::prepare (PrepareContext& context)
3906 {
3907 const vk::InstanceInterface& vki = context.getContext().getInstanceInterface();
3908 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
3909 const vk::VkPhysicalDevice physicalDevice = context.getContext().getPhysicalDevice();
3910 const vk::VkDevice device = context.getContext().getDevice();
3911 const vk::VkQueue queue = context.getContext().getQueue();
3912 const vk::VkCommandPool commandPool = context.getContext().getCommandPool();
3913 const vector<deUint32>& queueFamilies = context.getContext().getQueueFamilies();
3914
3915 m_imageWidth = context.getImageWidth();
3916 m_imageHeight = context.getImageHeight();
3917 m_imageMemorySize = context.getImageMemorySize();
3918
3919 if (m_scale == BLIT_SCALE_10)
3920 {
3921 m_dstImageWidth = context.getImageWidth();
3922 m_dstImageHeight = context.getImageHeight();
3923 }
3924 else if (m_scale == BLIT_SCALE_20)
3925 {
3926 m_dstImageWidth = context.getImageWidth() * 2;
3927 m_dstImageHeight = context.getImageHeight() * 2;
3928 }
3929 else
3930 DE_FATAL("Unsupportd blit scale");
3931
3932 {
3933 const vk::VkImageCreateInfo createInfo =
3934 {
3935 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
3936 DE_NULL,
3937
3938 0,
3939 vk::VK_IMAGE_TYPE_2D,
3940 vk::VK_FORMAT_R8G8B8A8_UNORM,
3941 {
3942 (deUint32)m_dstImageWidth,
3943 (deUint32)m_dstImageHeight,
3944 1u,
3945 },
3946 1, 1, // mipLevels, arrayLayers
3947 vk::VK_SAMPLE_COUNT_1_BIT,
3948
3949 vk::VK_IMAGE_TILING_OPTIMAL,
3950 vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT|vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
3951 vk::VK_SHARING_MODE_EXCLUSIVE,
3952
3953 (deUint32)queueFamilies.size(),
3954 &queueFamilies[0],
3955 vk::VK_IMAGE_LAYOUT_UNDEFINED
3956 };
3957
3958 m_dstImage = vk::createImage(vkd, device, &createInfo);
3959 }
3960
3961 m_memory = bindImageMemory(vki, vkd, physicalDevice, device, *m_dstImage, 0);
3962
3963 {
3964 const vk::Unique<vk::VkCommandBuffer> commandBuffer (createBeginCommandBuffer(vkd, device, commandPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
3965 const vk::VkImageMemoryBarrier barrier =
3966 {
3967 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
3968 DE_NULL,
3969
3970 0,
3971 vk::VK_ACCESS_TRANSFER_WRITE_BIT,
3972
3973 vk::VK_IMAGE_LAYOUT_UNDEFINED,
3974 vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
3975
3976 VK_QUEUE_FAMILY_IGNORED,
3977 VK_QUEUE_FAMILY_IGNORED,
3978
3979 *m_dstImage,
3980 {
3981 vk::VK_IMAGE_ASPECT_COLOR_BIT,
3982 0, // Mip level
3983 1, // Mip level count
3984 0, // Layer
3985 1 // Layer count
3986 }
3987 };
3988
3989 vkd.cmdPipelineBarrier(*commandBuffer, vk::VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1, &barrier);
3990
3991 endCommandBuffer(vkd, *commandBuffer);
3992 submitCommandsAndWait(vkd, device, queue, *commandBuffer);
3993 }
3994 }
3995
logSubmit(TestLog & log,size_t commandIndex) const3996 void ImageBlitToImage::logSubmit (TestLog& log, size_t commandIndex) const
3997 {
3998 log << TestLog::Message << commandIndex << ":" << getName() << " Blit image to another image" << (m_scale == BLIT_SCALE_20 ? " scale 2x" : "") << TestLog::EndMessage;
3999 }
4000
submit(SubmitContext & context)4001 void ImageBlitToImage::submit (SubmitContext& context)
4002 {
4003 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
4004 const vk::VkCommandBuffer commandBuffer = context.getCommandBuffer();
4005 const vk::VkImageBlit region =
4006 {
4007 // Src
4008 {
4009 vk::VK_IMAGE_ASPECT_COLOR_BIT,
4010 0, // mipLevel
4011 0, // arrayLayer
4012 1 // layerCount
4013 },
4014 {
4015 { 0, 0, 0 },
4016 {
4017 m_imageWidth,
4018 m_imageHeight,
4019 1
4020 },
4021 },
4022
4023 // Dst
4024 {
4025 vk::VK_IMAGE_ASPECT_COLOR_BIT,
4026 0, // mipLevel
4027 0, // arrayLayer
4028 1 // layerCount
4029 },
4030 {
4031 { 0, 0, 0 },
4032 {
4033 m_dstImageWidth,
4034 m_dstImageHeight,
4035 1u
4036 }
4037 }
4038 };
4039 vkd.cmdBlitImage(commandBuffer, context.getImage(), m_imageLayout, *m_dstImage, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion, vk::VK_FILTER_NEAREST);
4040 }
4041
verify(VerifyContext & context,size_t commandIndex)4042 void ImageBlitToImage::verify (VerifyContext& context, size_t commandIndex)
4043 {
4044 tcu::ResultCollector& resultCollector (context.getResultCollector());
4045 const vk::InstanceInterface& vki = context.getContext().getInstanceInterface();
4046 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
4047 const vk::VkPhysicalDevice physicalDevice = context.getContext().getPhysicalDevice();
4048 const vk::VkDevice device = context.getContext().getDevice();
4049 const vk::VkQueue queue = context.getContext().getQueue();
4050 const vk::VkCommandPool commandPool = context.getContext().getCommandPool();
4051 const vk::Unique<vk::VkCommandBuffer> commandBuffer (createBeginCommandBuffer(vkd, device, commandPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
4052 const vector<deUint32>& queueFamilies = context.getContext().getQueueFamilies();
4053 const vk::Unique<vk::VkBuffer> dstBuffer (createBuffer(vkd, device, 4 * m_dstImageWidth * m_dstImageHeight, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT, vk::VK_SHARING_MODE_EXCLUSIVE, queueFamilies));
4054 const vk::Unique<vk::VkDeviceMemory> memory (bindBufferMemory(vki, vkd, physicalDevice, device, *dstBuffer, vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));
4055 {
4056 const vk::VkImageMemoryBarrier imageBarrier =
4057 {
4058 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
4059 DE_NULL,
4060
4061 vk::VK_ACCESS_TRANSFER_WRITE_BIT,
4062 vk::VK_ACCESS_TRANSFER_READ_BIT,
4063
4064 vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
4065 vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
4066
4067 VK_QUEUE_FAMILY_IGNORED,
4068 VK_QUEUE_FAMILY_IGNORED,
4069
4070 *m_dstImage,
4071 {
4072 vk::VK_IMAGE_ASPECT_COLOR_BIT,
4073 0, // Mip level
4074 1, // Mip level count
4075 0, // Layer
4076 1 // Layer count
4077 }
4078 };
4079 const vk::VkBufferMemoryBarrier bufferBarrier =
4080 {
4081 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
4082 DE_NULL,
4083
4084 vk::VK_ACCESS_TRANSFER_WRITE_BIT,
4085 vk::VK_ACCESS_HOST_READ_BIT,
4086
4087 VK_QUEUE_FAMILY_IGNORED,
4088 VK_QUEUE_FAMILY_IGNORED,
4089 *dstBuffer,
4090 0,
4091 VK_WHOLE_SIZE
4092 };
4093 const vk::VkBufferImageCopy region =
4094 {
4095 0,
4096 0, 0,
4097 {
4098 vk::VK_IMAGE_ASPECT_COLOR_BIT,
4099 0, // mipLevel
4100 0, // arrayLayer
4101 1 // layerCount
4102 },
4103 { 0, 0, 0 },
4104 {
4105 (deUint32)m_dstImageWidth,
4106 (deUint32)m_dstImageHeight,
4107 1
4108 }
4109 };
4110
4111 vkd.cmdPipelineBarrier(*commandBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1, &imageBarrier);
4112 vkd.cmdCopyImageToBuffer(*commandBuffer, *m_dstImage, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *dstBuffer, 1, ®ion);
4113 vkd.cmdPipelineBarrier(*commandBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 1, &bufferBarrier, 0, (const vk::VkImageMemoryBarrier*)DE_NULL);
4114 }
4115
4116 endCommandBuffer(vkd, *commandBuffer);
4117 submitCommandsAndWait(vkd, device, queue, *commandBuffer);
4118
4119 {
4120 void* const ptr = mapMemory(vkd, device, *memory, 4 * m_dstImageWidth * m_dstImageHeight);
4121
4122 vk::invalidateMappedMemoryRange(vkd, device, *memory, 0, VK_WHOLE_SIZE);
4123
4124 if (m_scale == BLIT_SCALE_10)
4125 {
4126 const deUint8* const data = (const deUint8*)ptr;
4127 const ConstPixelBufferAccess resAccess (TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8), m_dstImageWidth, m_dstImageHeight, 1, data);
4128 const ConstPixelBufferAccess& refAccess (context.getReferenceImage().getAccess());
4129
4130 if (!tcu::intThresholdCompare(context.getLog(), (de::toString(commandIndex) + ":" + getName()).c_str(), (de::toString(commandIndex) + ":" + getName()).c_str(), refAccess, resAccess, UVec4(0), tcu::COMPARE_LOG_ON_ERROR))
4131 resultCollector.fail(de::toString(commandIndex) + ":" + getName() + " Image comparison failed");
4132 }
4133 else if (m_scale == BLIT_SCALE_20)
4134 {
4135 const deUint8* const data = (const deUint8*)ptr;
4136 const ConstPixelBufferAccess resAccess (TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8), m_dstImageWidth, m_dstImageHeight, 1, data);
4137 tcu::TextureLevel reference (TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8), m_dstImageWidth, m_dstImageHeight, 1);
4138
4139 {
4140 const ConstPixelBufferAccess& refAccess (context.getReferenceImage().getAccess());
4141
4142 for (deInt32 y = 0; y < m_dstImageHeight; y++)
4143 for (deInt32 x = 0; x < m_dstImageWidth; x++)
4144 {
4145 reference.getAccess().setPixel(refAccess.getPixel(x/2, y/2), x, y);
4146 }
4147 }
4148
4149 if (!tcu::intThresholdCompare(context.getLog(), (de::toString(commandIndex) + ":" + getName()).c_str(), (de::toString(commandIndex) + ":" + getName()).c_str(), reference.getAccess(), resAccess, UVec4(0), tcu::COMPARE_LOG_ON_ERROR))
4150 resultCollector.fail(de::toString(commandIndex) + ":" + getName() + " Image comparison failed");
4151 }
4152 else
4153 DE_FATAL("Unknown scale");
4154
4155 vkd.unmapMemory(device, *memory);
4156 }
4157 }
4158
4159 class PrepareRenderPassContext
4160 {
4161 public:
PrepareRenderPassContext(PrepareContext & context,vk::VkRenderPass renderPass,vk::VkFramebuffer framebuffer,deInt32 targetWidth,deInt32 targetHeight)4162 PrepareRenderPassContext (PrepareContext& context,
4163 vk::VkRenderPass renderPass,
4164 vk::VkFramebuffer framebuffer,
4165 deInt32 targetWidth,
4166 deInt32 targetHeight)
4167 : m_context (context)
4168 , m_renderPass (renderPass)
4169 , m_framebuffer (framebuffer)
4170 , m_targetWidth (targetWidth)
4171 , m_targetHeight (targetHeight)
4172 {
4173 }
4174
getMemory(void) const4175 const Memory& getMemory (void) const { return m_context.getMemory(); }
getContext(void) const4176 const Context& getContext (void) const { return m_context.getContext(); }
getBinaryCollection(void) const4177 const vk::BinaryCollection& getBinaryCollection (void) const { return m_context.getBinaryCollection(); }
4178
getBuffer(void) const4179 vk::VkBuffer getBuffer (void) const { return m_context.getBuffer(); }
getBufferSize(void) const4180 vk::VkDeviceSize getBufferSize (void) const { return m_context.getBufferSize(); }
4181
getImage(void) const4182 vk::VkImage getImage (void) const { return m_context.getImage(); }
getImageWidth(void) const4183 deInt32 getImageWidth (void) const { return m_context.getImageWidth(); }
getImageHeight(void) const4184 deInt32 getImageHeight (void) const { return m_context.getImageHeight(); }
getImageLayout(void) const4185 vk::VkImageLayout getImageLayout (void) const { return m_context.getImageLayout(); }
4186
getTargetWidth(void) const4187 deInt32 getTargetWidth (void) const { return m_targetWidth; }
getTargetHeight(void) const4188 deInt32 getTargetHeight (void) const { return m_targetHeight; }
4189
getRenderPass(void) const4190 vk::VkRenderPass getRenderPass (void) const { return m_renderPass; }
4191
4192 private:
4193 PrepareContext& m_context;
4194 const vk::VkRenderPass m_renderPass;
4195 const vk::VkFramebuffer m_framebuffer;
4196 const deInt32 m_targetWidth;
4197 const deInt32 m_targetHeight;
4198 };
4199
4200 class VerifyRenderPassContext
4201 {
4202 public:
VerifyRenderPassContext(VerifyContext & context,deInt32 targetWidth,deInt32 targetHeight)4203 VerifyRenderPassContext (VerifyContext& context,
4204 deInt32 targetWidth,
4205 deInt32 targetHeight)
4206 : m_context (context)
4207 , m_referenceTarget (TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8), targetWidth, targetHeight)
4208 {
4209 }
4210
getContext(void) const4211 const Context& getContext (void) const { return m_context.getContext(); }
getLog(void) const4212 TestLog& getLog (void) const { return m_context.getLog(); }
getResultCollector(void) const4213 tcu::ResultCollector& getResultCollector (void) const { return m_context.getResultCollector(); }
4214
getReferenceTarget(void)4215 TextureLevel& getReferenceTarget (void) { return m_referenceTarget; }
4216
getReference(void)4217 ReferenceMemory& getReference (void) { return m_context.getReference(); }
getReferenceImage(void)4218 TextureLevel& getReferenceImage (void) { return m_context.getReferenceImage();}
4219
4220 private:
4221 VerifyContext& m_context;
4222 TextureLevel m_referenceTarget;
4223 };
4224
4225 class RenderPassCommand
4226 {
4227 public:
~RenderPassCommand(void)4228 virtual ~RenderPassCommand (void) {}
4229 virtual const char* getName (void) const = 0;
4230
4231 // Log things that are done during prepare
logPrepare(TestLog &,size_t) const4232 virtual void logPrepare (TestLog&, size_t) const {}
4233 // Log submitted calls etc.
logSubmit(TestLog &,size_t) const4234 virtual void logSubmit (TestLog&, size_t) const {}
4235
4236 // Allocate vulkan resources and prepare for submit.
prepare(PrepareRenderPassContext &)4237 virtual void prepare (PrepareRenderPassContext&) {}
4238
4239 // Submit commands to command buffer.
submit(SubmitContext &)4240 virtual void submit (SubmitContext&) {}
4241
4242 // Verify results
verify(VerifyRenderPassContext &,size_t)4243 virtual void verify (VerifyRenderPassContext&, size_t) {}
4244 };
4245
4246 class SubmitRenderPass : public CmdCommand
4247 {
4248 public:
4249 SubmitRenderPass (const vector<RenderPassCommand*>& commands);
4250 ~SubmitRenderPass (void);
getName(void) const4251 const char* getName (void) const { return "SubmitRenderPass"; }
4252
4253 void logPrepare (TestLog&, size_t) const;
4254 void logSubmit (TestLog&, size_t) const;
4255
4256 void prepare (PrepareContext&);
4257 void submit (SubmitContext&);
4258
4259 void verify (VerifyContext&, size_t);
4260
4261 private:
4262 const deInt32 m_targetWidth;
4263 const deInt32 m_targetHeight;
4264 vk::Move<vk::VkRenderPass> m_renderPass;
4265 vk::Move<vk::VkDeviceMemory> m_colorTargetMemory;
4266 de::MovePtr<vk::Allocation> m_colorTargetMemory2;
4267 vk::Move<vk::VkImage> m_colorTarget;
4268 vk::Move<vk::VkImageView> m_colorTargetView;
4269 vk::Move<vk::VkFramebuffer> m_framebuffer;
4270 vector<RenderPassCommand*> m_commands;
4271 };
4272
SubmitRenderPass(const vector<RenderPassCommand * > & commands)4273 SubmitRenderPass::SubmitRenderPass (const vector<RenderPassCommand*>& commands)
4274 : m_targetWidth (256)
4275 , m_targetHeight (256)
4276 , m_commands (commands)
4277 {
4278 }
4279
~SubmitRenderPass()4280 SubmitRenderPass::~SubmitRenderPass()
4281 {
4282 for (size_t cmdNdx = 0; cmdNdx < m_commands.size(); cmdNdx++)
4283 delete m_commands[cmdNdx];
4284 }
4285
logPrepare(TestLog & log,size_t commandIndex) const4286 void SubmitRenderPass::logPrepare (TestLog& log, size_t commandIndex) const
4287 {
4288 const string sectionName (de::toString(commandIndex) + ":" + getName());
4289 const tcu::ScopedLogSection section (log, sectionName, sectionName);
4290
4291 for (size_t cmdNdx = 0; cmdNdx < m_commands.size(); cmdNdx++)
4292 {
4293 RenderPassCommand& command = *m_commands[cmdNdx];
4294 command.logPrepare(log, cmdNdx);
4295 }
4296 }
4297
logSubmit(TestLog & log,size_t commandIndex) const4298 void SubmitRenderPass::logSubmit (TestLog& log, size_t commandIndex) const
4299 {
4300 const string sectionName (de::toString(commandIndex) + ":" + getName());
4301 const tcu::ScopedLogSection section (log, sectionName, sectionName);
4302
4303 for (size_t cmdNdx = 0; cmdNdx < m_commands.size(); cmdNdx++)
4304 {
4305 RenderPassCommand& command = *m_commands[cmdNdx];
4306 command.logSubmit(log, cmdNdx);
4307 }
4308 }
4309
prepare(PrepareContext & context)4310 void SubmitRenderPass::prepare (PrepareContext& context)
4311 {
4312 const vk::InstanceInterface& vki = context.getContext().getInstanceInterface();
4313 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
4314 const vk::VkPhysicalDevice physicalDevice = context.getContext().getPhysicalDevice();
4315 const vk::VkDevice device = context.getContext().getDevice();
4316 const vector<deUint32>& queueFamilies = context.getContext().getQueueFamilies();
4317
4318 {
4319 const vk::VkImageCreateInfo createInfo =
4320 {
4321 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
4322 DE_NULL,
4323 0u,
4324
4325 vk::VK_IMAGE_TYPE_2D,
4326 vk::VK_FORMAT_R8G8B8A8_UNORM,
4327 { (deUint32)m_targetWidth, (deUint32)m_targetHeight, 1u },
4328 1u,
4329 1u,
4330 vk::VK_SAMPLE_COUNT_1_BIT,
4331 vk::VK_IMAGE_TILING_OPTIMAL,
4332 vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
4333 vk::VK_SHARING_MODE_EXCLUSIVE,
4334 (deUint32)queueFamilies.size(),
4335 &queueFamilies[0],
4336 vk::VK_IMAGE_LAYOUT_UNDEFINED
4337 };
4338
4339 m_colorTarget = vk::createImage(vkd, device, &createInfo);
4340 }
4341
4342 m_colorTargetMemory = bindImageMemory(vki, vkd, physicalDevice, device, *m_colorTarget, 0);
4343
4344 {
4345 const vk::VkImageViewCreateInfo createInfo =
4346 {
4347 vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
4348 DE_NULL,
4349
4350 0u,
4351 *m_colorTarget,
4352 vk::VK_IMAGE_VIEW_TYPE_2D,
4353 vk::VK_FORMAT_R8G8B8A8_UNORM,
4354 {
4355 vk::VK_COMPONENT_SWIZZLE_R,
4356 vk::VK_COMPONENT_SWIZZLE_G,
4357 vk::VK_COMPONENT_SWIZZLE_B,
4358 vk::VK_COMPONENT_SWIZZLE_A
4359 },
4360 {
4361 vk::VK_IMAGE_ASPECT_COLOR_BIT,
4362 0u,
4363 1u,
4364 0u,
4365 1u
4366 }
4367 };
4368
4369 m_colorTargetView = vk::createImageView(vkd, device, &createInfo);
4370 }
4371
4372 m_renderPass = vk::makeRenderPass(vkd, device, vk::VK_FORMAT_R8G8B8A8_UNORM, vk::VK_FORMAT_UNDEFINED, vk::VK_ATTACHMENT_LOAD_OP_CLEAR, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
4373
4374 {
4375 const vk::VkImageView imageViews[] =
4376 {
4377 *m_colorTargetView
4378 };
4379 const vk::VkFramebufferCreateInfo createInfo =
4380 {
4381 vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
4382 DE_NULL,
4383 0u,
4384
4385 *m_renderPass,
4386 DE_LENGTH_OF_ARRAY(imageViews),
4387 imageViews,
4388 (deUint32)m_targetWidth,
4389 (deUint32)m_targetHeight,
4390 1u
4391 };
4392
4393 m_framebuffer = vk::createFramebuffer(vkd, device, &createInfo);
4394 }
4395
4396 {
4397 PrepareRenderPassContext renderpassContext (context, *m_renderPass, *m_framebuffer, m_targetWidth, m_targetHeight);
4398
4399 for (size_t cmdNdx = 0; cmdNdx < m_commands.size(); cmdNdx++)
4400 {
4401 RenderPassCommand& command = *m_commands[cmdNdx];
4402 command.prepare(renderpassContext);
4403 }
4404 }
4405 }
4406
submit(SubmitContext & context)4407 void SubmitRenderPass::submit (SubmitContext& context)
4408 {
4409 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
4410 const vk::VkCommandBuffer commandBuffer = context.getCommandBuffer();
4411
4412 beginRenderPass(vkd, commandBuffer, *m_renderPass, *m_framebuffer, vk::makeRect2D(0, 0, m_targetWidth, m_targetHeight), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
4413
4414 for (size_t cmdNdx = 0; cmdNdx < m_commands.size(); cmdNdx++)
4415 {
4416 RenderPassCommand& command = *m_commands[cmdNdx];
4417
4418 command.submit(context);
4419 }
4420
4421 endRenderPass(vkd, commandBuffer);
4422 }
4423
verify(VerifyContext & context,size_t commandIndex)4424 void SubmitRenderPass::verify (VerifyContext& context, size_t commandIndex)
4425 {
4426 TestLog& log (context.getLog());
4427 tcu::ResultCollector& resultCollector (context.getResultCollector());
4428 const string sectionName (de::toString(commandIndex) + ":" + getName());
4429 const tcu::ScopedLogSection section (log, sectionName, sectionName);
4430 VerifyRenderPassContext verifyContext (context, m_targetWidth, m_targetHeight);
4431
4432 tcu::clear(verifyContext.getReferenceTarget().getAccess(), Vec4(0.0f, 0.0f, 0.0f, 1.0f));
4433
4434 for (size_t cmdNdx = 0; cmdNdx < m_commands.size(); cmdNdx++)
4435 {
4436 RenderPassCommand& command = *m_commands[cmdNdx];
4437 command.verify(verifyContext, cmdNdx);
4438 }
4439
4440 {
4441 const vk::InstanceInterface& vki = context.getContext().getInstanceInterface();
4442 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
4443 const vk::VkPhysicalDevice physicalDevice = context.getContext().getPhysicalDevice();
4444 const vk::VkDevice device = context.getContext().getDevice();
4445 const vk::VkQueue queue = context.getContext().getQueue();
4446 const vk::VkCommandPool commandPool = context.getContext().getCommandPool();
4447 const vk::Unique<vk::VkCommandBuffer> commandBuffer (createBeginCommandBuffer(vkd, device, commandPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
4448 const vector<deUint32>& queueFamilies = context.getContext().getQueueFamilies();
4449 const vk::Unique<vk::VkBuffer> dstBuffer (createBuffer(vkd, device, 4 * m_targetWidth * m_targetHeight, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT, vk::VK_SHARING_MODE_EXCLUSIVE, queueFamilies));
4450 const vk::Unique<vk::VkDeviceMemory> memory (bindBufferMemory(vki, vkd, physicalDevice, device, *dstBuffer, vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));
4451 {
4452 const vk::VkImageMemoryBarrier imageBarrier =
4453 {
4454 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
4455 DE_NULL,
4456
4457 vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
4458 vk::VK_ACCESS_TRANSFER_READ_BIT,
4459
4460 vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
4461 vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
4462
4463 VK_QUEUE_FAMILY_IGNORED,
4464 VK_QUEUE_FAMILY_IGNORED,
4465
4466 *m_colorTarget,
4467 {
4468 vk::VK_IMAGE_ASPECT_COLOR_BIT,
4469 0, // Mip level
4470 1, // Mip level count
4471 0, // Layer
4472 1 // Layer count
4473 }
4474 };
4475 const vk::VkBufferMemoryBarrier bufferBarrier =
4476 {
4477 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
4478 DE_NULL,
4479
4480 vk::VK_ACCESS_TRANSFER_WRITE_BIT,
4481 vk::VK_ACCESS_HOST_READ_BIT,
4482
4483 VK_QUEUE_FAMILY_IGNORED,
4484 VK_QUEUE_FAMILY_IGNORED,
4485 *dstBuffer,
4486 0,
4487 VK_WHOLE_SIZE
4488 };
4489 const vk::VkBufferImageCopy region =
4490 {
4491 0,
4492 0, 0,
4493 {
4494 vk::VK_IMAGE_ASPECT_COLOR_BIT,
4495 0, // mipLevel
4496 0, // arrayLayer
4497 1 // layerCount
4498 },
4499 { 0, 0, 0 },
4500 {
4501 (deUint32)m_targetWidth,
4502 (deUint32)m_targetHeight,
4503 1u
4504 }
4505 };
4506
4507 vkd.cmdPipelineBarrier(*commandBuffer, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1, &imageBarrier);
4508 vkd.cmdCopyImageToBuffer(*commandBuffer, *m_colorTarget, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *dstBuffer, 1, ®ion);
4509 vkd.cmdPipelineBarrier(*commandBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 1, &bufferBarrier, 0, (const vk::VkImageMemoryBarrier*)DE_NULL);
4510 }
4511
4512 endCommandBuffer(vkd, *commandBuffer);
4513 submitCommandsAndWait(vkd, device, queue, *commandBuffer);
4514
4515 {
4516 void* const ptr = mapMemory(vkd, device, *memory, 4 * m_targetWidth * m_targetHeight);
4517
4518 vk::invalidateMappedMemoryRange(vkd, device, *memory, 0, VK_WHOLE_SIZE);
4519
4520 {
4521 const deUint8* const data = (const deUint8*)ptr;
4522 const ConstPixelBufferAccess resAccess (TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8), m_targetWidth, m_targetHeight, 1, data);
4523 const ConstPixelBufferAccess& refAccess (verifyContext.getReferenceTarget().getAccess());
4524
4525 if (!tcu::intThresholdCompare(context.getLog(), (de::toString(commandIndex) + ":" + getName()).c_str(), (de::toString(commandIndex) + ":" + getName()).c_str(), refAccess, resAccess, UVec4(0), tcu::COMPARE_LOG_ON_ERROR))
4526 resultCollector.fail(de::toString(commandIndex) + ":" + getName() + " Image comparison failed");
4527 }
4528
4529 vkd.unmapMemory(device, *memory);
4530 }
4531 }
4532 }
4533
4534 class ExecuteSecondaryCommandBuffer : public CmdCommand
4535 {
4536 public:
4537 ExecuteSecondaryCommandBuffer (const vector<CmdCommand*>& commands);
4538 ~ExecuteSecondaryCommandBuffer (void);
getName(void) const4539 const char* getName (void) const { return "ExecuteSecondaryCommandBuffer"; }
4540
4541 void logPrepare (TestLog&, size_t) const;
4542 void logSubmit (TestLog&, size_t) const;
4543
4544 void prepare (PrepareContext&);
4545 void submit (SubmitContext&);
4546
4547 void verify (VerifyContext&, size_t);
4548
4549 private:
4550 vk::Move<vk::VkCommandBuffer> m_commandBuffer;
4551 vk::Move<vk::VkDeviceMemory> m_colorTargetMemory;
4552 de::MovePtr<vk::Allocation> m_colorTargetMemory2;
4553 vk::Move<vk::VkImage> m_colorTarget;
4554 vk::Move<vk::VkImageView> m_colorTargetView;
4555 vk::Move<vk::VkFramebuffer> m_framebuffer;
4556 vector<CmdCommand*> m_commands;
4557 };
4558
ExecuteSecondaryCommandBuffer(const vector<CmdCommand * > & commands)4559 ExecuteSecondaryCommandBuffer::ExecuteSecondaryCommandBuffer(const vector<CmdCommand*>& commands)
4560 : m_commands (commands)
4561 {
4562 }
4563
~ExecuteSecondaryCommandBuffer(void)4564 ExecuteSecondaryCommandBuffer::~ExecuteSecondaryCommandBuffer (void)
4565 {
4566 for (size_t cmdNdx = 0; cmdNdx < m_commands.size(); cmdNdx++)
4567 delete m_commands[cmdNdx];
4568 }
4569
logPrepare(TestLog & log,size_t commandIndex) const4570 void ExecuteSecondaryCommandBuffer::logPrepare (TestLog& log, size_t commandIndex) const
4571 {
4572 const string sectionName (de::toString(commandIndex) + ":" + getName());
4573 const tcu::ScopedLogSection section (log, sectionName, sectionName);
4574
4575 for (size_t cmdNdx = 0; cmdNdx < m_commands.size(); cmdNdx++)
4576 {
4577 CmdCommand& command = *m_commands[cmdNdx];
4578 command.logPrepare(log, cmdNdx);
4579 }
4580 }
4581
logSubmit(TestLog & log,size_t commandIndex) const4582 void ExecuteSecondaryCommandBuffer::logSubmit (TestLog& log, size_t commandIndex) const
4583 {
4584 const string sectionName (de::toString(commandIndex) + ":" + getName());
4585 const tcu::ScopedLogSection section (log, sectionName, sectionName);
4586
4587 for (size_t cmdNdx = 0; cmdNdx < m_commands.size(); cmdNdx++)
4588 {
4589 CmdCommand& command = *m_commands[cmdNdx];
4590 command.logSubmit(log, cmdNdx);
4591 }
4592 }
4593
prepare(PrepareContext & context)4594 void ExecuteSecondaryCommandBuffer::prepare (PrepareContext& context)
4595 {
4596 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
4597 const vk::VkDevice device = context.getContext().getDevice();
4598 const vk::VkCommandPool commandPool = context.getContext().getCommandPool();
4599
4600 for (size_t cmdNdx = 0; cmdNdx < m_commands.size(); cmdNdx++)
4601 {
4602 CmdCommand& command = *m_commands[cmdNdx];
4603
4604 command.prepare(context);
4605 }
4606
4607 m_commandBuffer = createBeginCommandBuffer(vkd, device, commandPool, vk::VK_COMMAND_BUFFER_LEVEL_SECONDARY);
4608 {
4609 SubmitContext submitContext (context, *m_commandBuffer);
4610
4611 for (size_t cmdNdx = 0; cmdNdx < m_commands.size(); cmdNdx++)
4612 {
4613 CmdCommand& command = *m_commands[cmdNdx];
4614
4615 command.submit(submitContext);
4616 }
4617
4618 endCommandBuffer(vkd, *m_commandBuffer);
4619 }
4620 }
4621
submit(SubmitContext & context)4622 void ExecuteSecondaryCommandBuffer::submit (SubmitContext& context)
4623 {
4624 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
4625 const vk::VkCommandBuffer commandBuffer = context.getCommandBuffer();
4626
4627
4628 {
4629 vkd.cmdExecuteCommands(commandBuffer, 1, &m_commandBuffer.get());
4630 }
4631 }
4632
verify(VerifyContext & context,size_t commandIndex)4633 void ExecuteSecondaryCommandBuffer::verify (VerifyContext& context, size_t commandIndex)
4634 {
4635 const string sectionName (de::toString(commandIndex) + ":" + getName());
4636 const tcu::ScopedLogSection section (context.getLog(), sectionName, sectionName);
4637
4638 for (size_t cmdNdx = 0; cmdNdx < m_commands.size(); cmdNdx++)
4639 m_commands[cmdNdx]->verify(context, cmdNdx);
4640 }
4641
4642 struct PipelineResources
4643 {
4644 vk::Move<vk::VkPipeline> pipeline;
4645 vk::Move<vk::VkDescriptorSetLayout> descriptorSetLayout;
4646 vk::Move<vk::VkPipelineLayout> pipelineLayout;
4647 };
4648
createPipelineWithResources(const vk::DeviceInterface & vkd,const vk::VkDevice device,const vk::VkRenderPass renderPass,const deUint32 subpass,const vk::VkShaderModule & vertexShaderModule,const vk::VkShaderModule & fragmentShaderModule,const deUint32 viewPortWidth,const deUint32 viewPortHeight,const vector<vk::VkVertexInputBindingDescription> & vertexBindingDescriptions,const vector<vk::VkVertexInputAttributeDescription> & vertexAttributeDescriptions,const vector<vk::VkDescriptorSetLayoutBinding> & bindings,const vk::VkPrimitiveTopology topology,deUint32 pushConstantRangeCount,const vk::VkPushConstantRange * pushConstantRanges,PipelineResources & resources)4649 void createPipelineWithResources (const vk::DeviceInterface& vkd,
4650 const vk::VkDevice device,
4651 const vk::VkRenderPass renderPass,
4652 const deUint32 subpass,
4653 const vk::VkShaderModule& vertexShaderModule,
4654 const vk::VkShaderModule& fragmentShaderModule,
4655 const deUint32 viewPortWidth,
4656 const deUint32 viewPortHeight,
4657 const vector<vk::VkVertexInputBindingDescription>& vertexBindingDescriptions,
4658 const vector<vk::VkVertexInputAttributeDescription>& vertexAttributeDescriptions,
4659 const vector<vk::VkDescriptorSetLayoutBinding>& bindings,
4660 const vk::VkPrimitiveTopology topology,
4661 deUint32 pushConstantRangeCount,
4662 const vk::VkPushConstantRange* pushConstantRanges,
4663 PipelineResources& resources)
4664 {
4665 if (!bindings.empty())
4666 {
4667 const vk::VkDescriptorSetLayoutCreateInfo createInfo =
4668 {
4669 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
4670 DE_NULL,
4671
4672 0u,
4673 (deUint32)bindings.size(),
4674 bindings.empty() ? DE_NULL : &bindings[0]
4675 };
4676
4677 resources.descriptorSetLayout = vk::createDescriptorSetLayout(vkd, device, &createInfo);
4678 }
4679
4680 {
4681 const vk::VkDescriptorSetLayout descriptorSetLayout_ = *resources.descriptorSetLayout;
4682 const vk::VkPipelineLayoutCreateInfo createInfo =
4683 {
4684 vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
4685 DE_NULL,
4686 0,
4687
4688 resources.descriptorSetLayout ? 1u : 0u,
4689 resources.descriptorSetLayout ? &descriptorSetLayout_ : DE_NULL,
4690
4691 pushConstantRangeCount,
4692 pushConstantRanges
4693 };
4694
4695 resources.pipelineLayout = vk::createPipelineLayout(vkd, device, &createInfo);
4696 }
4697
4698 {
4699 const std::vector<vk::VkViewport> viewports (1, vk::makeViewport(0.0f, 0.0f, (float)viewPortWidth, (float)viewPortHeight, 0.0f, 1.0f));
4700 const std::vector<vk::VkRect2D> scissors (1, vk::makeRect2D(0, 0, viewPortWidth, viewPortHeight));
4701
4702 const vk::VkPipelineVertexInputStateCreateInfo vertexInputState =
4703 {
4704 vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
4705 DE_NULL,
4706 0u,
4707
4708 (deUint32)vertexBindingDescriptions.size(),
4709 vertexBindingDescriptions.empty() ? DE_NULL : &vertexBindingDescriptions[0],
4710
4711 (deUint32)vertexAttributeDescriptions.size(),
4712 vertexAttributeDescriptions.empty() ? DE_NULL : &vertexAttributeDescriptions[0]
4713 };
4714
4715 resources.pipeline = vk::makeGraphicsPipeline(vkd, // const DeviceInterface& vk
4716 device, // const VkDevice device
4717 *resources.pipelineLayout, // const VkPipelineLayout pipelineLayout
4718 vertexShaderModule, // const VkShaderModule vertexShaderModule
4719 DE_NULL, // const VkShaderModule tessellationControlModule
4720 DE_NULL, // const VkShaderModule tessellationEvalModule
4721 DE_NULL, // const VkShaderModule geometryShaderModule
4722 fragmentShaderModule, // const VkShaderModule fragmentShaderModule
4723 renderPass, // const VkRenderPass renderPass
4724 viewports, // const std::vector<VkViewport>& viewports
4725 scissors, // const std::vector<VkRect2D>& scissors
4726 topology, // const VkPrimitiveTopology topology
4727 subpass, // const deUint32 subpass
4728 0u, // const deUint32 patchControlPoints
4729 &vertexInputState); // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo
4730 }
4731 }
4732
4733 class RenderIndexBuffer : public RenderPassCommand
4734 {
4735 public:
RenderIndexBuffer(void)4736 RenderIndexBuffer (void) {}
~RenderIndexBuffer(void)4737 ~RenderIndexBuffer (void) {}
4738
getName(void) const4739 const char* getName (void) const { return "RenderIndexBuffer"; }
4740 void logPrepare (TestLog&, size_t) const;
4741 void logSubmit (TestLog&, size_t) const;
4742 void prepare (PrepareRenderPassContext&);
4743 void submit (SubmitContext& context);
4744 void verify (VerifyRenderPassContext&, size_t);
4745
4746 private:
4747 PipelineResources m_resources;
4748 vk::VkDeviceSize m_bufferSize;
4749 };
4750
logPrepare(TestLog & log,size_t commandIndex) const4751 void RenderIndexBuffer::logPrepare (TestLog& log, size_t commandIndex) const
4752 {
4753 log << TestLog::Message << commandIndex << ":" << getName() << " Create pipeline for render buffer as index buffer." << TestLog::EndMessage;
4754 }
4755
logSubmit(TestLog & log,size_t commandIndex) const4756 void RenderIndexBuffer::logSubmit (TestLog& log, size_t commandIndex) const
4757 {
4758 log << TestLog::Message << commandIndex << ":" << getName() << " Render using buffer as index buffer." << TestLog::EndMessage;
4759 }
4760
prepare(PrepareRenderPassContext & context)4761 void RenderIndexBuffer::prepare (PrepareRenderPassContext& context)
4762 {
4763 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
4764 const vk::VkDevice device = context.getContext().getDevice();
4765 const vk::VkRenderPass renderPass = context.getRenderPass();
4766 const deUint32 subpass = 0;
4767 const vk::Unique<vk::VkShaderModule> vertexShaderModule (vk::createShaderModule(vkd, device, context.getBinaryCollection().get("index-buffer.vert"), 0));
4768 const vk::Unique<vk::VkShaderModule> fragmentShaderModule (vk::createShaderModule(vkd, device, context.getBinaryCollection().get("render-white.frag"), 0));
4769
4770 createPipelineWithResources(vkd, device, renderPass, subpass, *vertexShaderModule, *fragmentShaderModule, context.getTargetWidth(), context.getTargetHeight(),
4771 vector<vk::VkVertexInputBindingDescription>(), vector<vk::VkVertexInputAttributeDescription>(), vector<vk::VkDescriptorSetLayoutBinding>(), vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST, 0u, DE_NULL, m_resources);
4772 m_bufferSize = context.getBufferSize();
4773 }
4774
submit(SubmitContext & context)4775 void RenderIndexBuffer::submit (SubmitContext& context)
4776 {
4777 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
4778 const vk::VkCommandBuffer commandBuffer = context.getCommandBuffer();
4779
4780 vkd.cmdBindPipeline(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_resources.pipeline);
4781 vkd.cmdBindIndexBuffer(commandBuffer, context.getBuffer(), 0, vk::VK_INDEX_TYPE_UINT16);
4782 vkd.cmdDrawIndexed(commandBuffer, (deUint32)(context.getBufferSize() / 2), 1, 0, 0, 0);
4783 }
4784
verify(VerifyRenderPassContext & context,size_t)4785 void RenderIndexBuffer::verify (VerifyRenderPassContext& context, size_t)
4786 {
4787 for (size_t pos = 0; pos < (size_t)m_bufferSize / 2; pos++)
4788 {
4789 const deUint8 x = context.getReference().get(pos * 2);
4790 const deUint8 y = context.getReference().get((pos * 2) + 1);
4791
4792 context.getReferenceTarget().getAccess().setPixel(Vec4(1.0f, 1.0f, 1.0f, 1.0f), x, y);
4793 }
4794 }
4795
4796 class RenderVertexBuffer : public RenderPassCommand
4797 {
4798 public:
RenderVertexBuffer(deUint32 stride)4799 RenderVertexBuffer (deUint32 stride)
4800 : m_stride(stride)
4801 , m_name("RenderVertexBuffer" + de::toString(stride))
4802 {}
~RenderVertexBuffer(void)4803 ~RenderVertexBuffer (void) {}
4804
getName(void) const4805 const char* getName (void) const { return m_name.c_str(); }
4806 void logPrepare (TestLog&, size_t) const;
4807 void logSubmit (TestLog&, size_t) const;
4808 void prepare (PrepareRenderPassContext&);
4809 void submit (SubmitContext& context);
4810 void verify (VerifyRenderPassContext&, size_t);
4811
4812 private:
4813 const deUint32 m_stride;
4814 const std::string m_name;
4815 PipelineResources m_resources;
4816 vk::VkDeviceSize m_bufferSize;
4817 };
4818
logPrepare(TestLog & log,size_t commandIndex) const4819 void RenderVertexBuffer::logPrepare (TestLog& log, size_t commandIndex) const
4820 {
4821 log << TestLog::Message << commandIndex << ":" << getName() << " Create pipeline for render buffer as vertex buffer." << TestLog::EndMessage;
4822 }
4823
logSubmit(TestLog & log,size_t commandIndex) const4824 void RenderVertexBuffer::logSubmit (TestLog& log, size_t commandIndex) const
4825 {
4826 log << TestLog::Message << commandIndex << ":" << getName() << " Render using buffer as vertex buffer." << TestLog::EndMessage;
4827 }
4828
prepare(PrepareRenderPassContext & context)4829 void RenderVertexBuffer::prepare (PrepareRenderPassContext& context)
4830 {
4831 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
4832 const vk::VkDevice device = context.getContext().getDevice();
4833 const vk::VkRenderPass renderPass = context.getRenderPass();
4834 const deUint32 subpass = 0;
4835 const vk::Unique<vk::VkShaderModule> vertexShaderModule (vk::createShaderModule(vkd, device, context.getBinaryCollection().get("vertex-buffer.vert"), 0));
4836 const vk::Unique<vk::VkShaderModule> fragmentShaderModule (vk::createShaderModule(vkd, device, context.getBinaryCollection().get("render-white.frag"), 0));
4837
4838 vector<vk::VkVertexInputAttributeDescription> vertexAttributeDescriptions;
4839 vector<vk::VkVertexInputBindingDescription> vertexBindingDescriptions;
4840
4841 {
4842 const vk::VkVertexInputBindingDescription vertexBindingDescription =
4843 {
4844 0,
4845 m_stride,
4846 vk::VK_VERTEX_INPUT_RATE_VERTEX
4847 };
4848
4849 vertexBindingDescriptions.push_back(vertexBindingDescription);
4850 }
4851 {
4852 const vk::VkVertexInputAttributeDescription vertexAttributeDescription =
4853 {
4854 0,
4855 0,
4856 vk::VK_FORMAT_R8G8_UNORM,
4857 0
4858 };
4859
4860 vertexAttributeDescriptions.push_back(vertexAttributeDescription);
4861 }
4862 createPipelineWithResources(vkd, device, renderPass, subpass, *vertexShaderModule, *fragmentShaderModule, context.getTargetWidth(), context.getTargetHeight(),
4863 vertexBindingDescriptions, vertexAttributeDescriptions, vector<vk::VkDescriptorSetLayoutBinding>(), vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST, 0u, DE_NULL, m_resources);
4864
4865 m_bufferSize = context.getBufferSize();
4866 }
4867
submit(SubmitContext & context)4868 void RenderVertexBuffer::submit (SubmitContext& context)
4869 {
4870 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
4871 const vk::VkCommandBuffer commandBuffer = context.getCommandBuffer();
4872 const vk::VkDeviceSize offset = 0;
4873 const vk::VkBuffer buffer = context.getBuffer();
4874
4875 vkd.cmdBindPipeline(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_resources.pipeline);
4876 vkd.cmdBindVertexBuffers(commandBuffer, 0, 1, &buffer, &offset);
4877 vkd.cmdDraw(commandBuffer, (deUint32)(context.getBufferSize() / m_stride), 1, 0, 0);
4878 }
4879
verify(VerifyRenderPassContext & context,size_t)4880 void RenderVertexBuffer::verify (VerifyRenderPassContext& context, size_t)
4881 {
4882 for (size_t pos = 0; pos < (size_t)m_bufferSize / m_stride; pos++)
4883 {
4884 const deUint8 x = context.getReference().get(pos * m_stride);
4885 const deUint8 y = context.getReference().get((pos * m_stride) + 1);
4886
4887 context.getReferenceTarget().getAccess().setPixel(Vec4(1.0f, 1.0f, 1.0f, 1.0f), x, y);
4888 }
4889 }
4890
4891 class RenderVertexUniformBuffer : public RenderPassCommand
4892 {
4893 public:
RenderVertexUniformBuffer(void)4894 RenderVertexUniformBuffer (void) {}
4895 ~RenderVertexUniformBuffer (void);
4896
getName(void) const4897 const char* getName (void) const { return "RenderVertexUniformBuffer"; }
4898 void logPrepare (TestLog&, size_t) const;
4899 void logSubmit (TestLog&, size_t) const;
4900 void prepare (PrepareRenderPassContext&);
4901 void submit (SubmitContext& context);
4902 void verify (VerifyRenderPassContext&, size_t);
4903
4904 protected:
4905
4906 deUint32 calculateBufferPartSize (size_t descriptorSetNdx) const;
4907
4908 private:
4909 PipelineResources m_resources;
4910 vk::Move<vk::VkDescriptorPool> m_descriptorPool;
4911 vector<vk::VkDescriptorSet> m_descriptorSets;
4912
4913 vk::VkDeviceSize m_bufferSize;
4914 };
4915
~RenderVertexUniformBuffer(void)4916 RenderVertexUniformBuffer::~RenderVertexUniformBuffer (void)
4917 {
4918 }
4919
logPrepare(TestLog & log,size_t commandIndex) const4920 void RenderVertexUniformBuffer::logPrepare (TestLog& log, size_t commandIndex) const
4921 {
4922 log << TestLog::Message << commandIndex << ":" << getName() << " Create pipeline for render buffer as uniform buffer." << TestLog::EndMessage;
4923 }
4924
logSubmit(TestLog & log,size_t commandIndex) const4925 void RenderVertexUniformBuffer::logSubmit (TestLog& log, size_t commandIndex) const
4926 {
4927 log << TestLog::Message << commandIndex << ":" << getName() << " Render using buffer as uniform buffer." << TestLog::EndMessage;
4928 }
4929
prepare(PrepareRenderPassContext & context)4930 void RenderVertexUniformBuffer::prepare (PrepareRenderPassContext& context)
4931 {
4932 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
4933 const vk::VkDevice device = context.getContext().getDevice();
4934 const vk::VkRenderPass renderPass = context.getRenderPass();
4935 const deUint32 subpass = 0;
4936 const vk::Unique<vk::VkShaderModule> vertexShaderModule (vk::createShaderModule(vkd, device, context.getBinaryCollection().get("uniform-buffer.vert"), 0));
4937 const vk::Unique<vk::VkShaderModule> fragmentShaderModule (vk::createShaderModule(vkd, device, context.getBinaryCollection().get("render-white.frag"), 0));
4938 vector<vk::VkDescriptorSetLayoutBinding> bindings;
4939
4940 // make sure buffer size is multiple of 16 (in glsl we use uvec4 to store 16 values)
4941 m_bufferSize = context.getBufferSize();
4942 m_bufferSize = static_cast<vk::VkDeviceSize>(m_bufferSize / 16u) * 16u;
4943
4944 {
4945 const vk::VkDescriptorSetLayoutBinding binding =
4946 {
4947 0u,
4948 vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
4949 1,
4950 vk::VK_SHADER_STAGE_VERTEX_BIT,
4951 DE_NULL
4952 };
4953
4954 bindings.push_back(binding);
4955 }
4956
4957 createPipelineWithResources(vkd, device, renderPass, subpass, *vertexShaderModule, *fragmentShaderModule, context.getTargetWidth(), context.getTargetHeight(),
4958 vector<vk::VkVertexInputBindingDescription>(), vector<vk::VkVertexInputAttributeDescription>(), bindings, vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST, 0u, DE_NULL, m_resources);
4959
4960 {
4961 const deUint32 descriptorCount = (deUint32)(divRoundUp(m_bufferSize, (vk::VkDeviceSize)MAX_UNIFORM_BUFFER_SIZE));
4962 const vk::VkDescriptorPoolSize poolSizes =
4963 {
4964 vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
4965 descriptorCount
4966 };
4967 const vk::VkDescriptorPoolCreateInfo createInfo =
4968 {
4969 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
4970 DE_NULL,
4971 vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
4972
4973 descriptorCount,
4974 1u,
4975 &poolSizes,
4976 };
4977
4978 m_descriptorPool = vk::createDescriptorPool(vkd, device, &createInfo);
4979 m_descriptorSets.resize(descriptorCount);
4980 }
4981
4982 for (size_t descriptorSetNdx = 0; descriptorSetNdx < m_descriptorSets.size(); descriptorSetNdx++)
4983 {
4984 const vk::VkDescriptorSetLayout layout = *m_resources.descriptorSetLayout;
4985 const vk::VkDescriptorSetAllocateInfo allocateInfo =
4986 {
4987 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
4988 DE_NULL,
4989
4990 *m_descriptorPool,
4991 1,
4992 &layout
4993 };
4994
4995 m_descriptorSets[descriptorSetNdx] = vk::allocateDescriptorSet(vkd, device, &allocateInfo).disown();
4996
4997 {
4998 const vk::VkDescriptorBufferInfo bufferInfo =
4999 {
5000 context.getBuffer(),
5001 (vk::VkDeviceSize)(descriptorSetNdx * (size_t)MAX_UNIFORM_BUFFER_SIZE),
5002 calculateBufferPartSize(descriptorSetNdx)
5003 };
5004 const vk::VkWriteDescriptorSet write =
5005 {
5006 vk::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
5007 DE_NULL,
5008 m_descriptorSets[descriptorSetNdx],
5009 0u,
5010 0u,
5011 1u,
5012 vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
5013 DE_NULL,
5014 &bufferInfo,
5015 DE_NULL,
5016 };
5017
5018 vkd.updateDescriptorSets(device, 1u, &write, 0u, DE_NULL);
5019 }
5020 }
5021 }
5022
submit(SubmitContext & context)5023 void RenderVertexUniformBuffer::submit (SubmitContext& context)
5024 {
5025 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
5026 const vk::VkCommandBuffer commandBuffer = context.getCommandBuffer();
5027
5028 vkd.cmdBindPipeline(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_resources.pipeline);
5029
5030 for (size_t descriptorSetNdx = 0; descriptorSetNdx < m_descriptorSets.size(); descriptorSetNdx++)
5031 {
5032 const size_t size = calculateBufferPartSize(descriptorSetNdx);
5033 const deUint32 count = (deUint32)(size / 2);
5034
5035 vkd.cmdBindDescriptorSets(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_resources.pipelineLayout, 0u, 1u, &m_descriptorSets[descriptorSetNdx], 0u, DE_NULL);
5036 vkd.cmdDraw(commandBuffer, count, 1, 0, 0);
5037 }
5038 }
5039
verify(VerifyRenderPassContext & context,size_t)5040 void RenderVertexUniformBuffer::verify (VerifyRenderPassContext& context, size_t)
5041 {
5042 for (size_t descriptorSetNdx = 0; descriptorSetNdx < m_descriptorSets.size(); descriptorSetNdx++)
5043 {
5044 const size_t offset = descriptorSetNdx * MAX_UNIFORM_BUFFER_SIZE;
5045 const size_t size = calculateBufferPartSize(descriptorSetNdx);
5046 const size_t count = size / 2;
5047
5048 for (size_t pos = 0; pos < count; pos++)
5049 {
5050 const deUint8 x = context.getReference().get(offset + pos * 2);
5051 const deUint8 y = context.getReference().get(offset + (pos * 2) + 1);
5052
5053 context.getReferenceTarget().getAccess().setPixel(Vec4(1.0f, 1.0f, 1.0f, 1.0f), x, y);
5054 }
5055 }
5056 }
5057
calculateBufferPartSize(size_t descriptorSetNdx) const5058 deUint32 RenderVertexUniformBuffer::calculateBufferPartSize(size_t descriptorSetNdx) const
5059 {
5060 deUint32 size = static_cast<deUint32>(m_bufferSize) - static_cast<deUint32>(descriptorSetNdx) * MAX_UNIFORM_BUFFER_SIZE;
5061 if (size < MAX_UNIFORM_BUFFER_SIZE)
5062 return size;
5063 return MAX_UNIFORM_BUFFER_SIZE;
5064 }
5065
5066 class RenderVertexUniformTexelBuffer : public RenderPassCommand
5067 {
5068 public:
RenderVertexUniformTexelBuffer(void)5069 RenderVertexUniformTexelBuffer (void) {}
5070 ~RenderVertexUniformTexelBuffer (void);
5071
getName(void) const5072 const char* getName (void) const { return "RenderVertexUniformTexelBuffer"; }
5073 void logPrepare (TestLog&, size_t) const;
5074 void logSubmit (TestLog&, size_t) const;
5075 void prepare (PrepareRenderPassContext&);
5076 void submit (SubmitContext& context);
5077 void verify (VerifyRenderPassContext&, size_t);
5078
5079 private:
5080 PipelineResources m_resources;
5081 vk::Move<vk::VkDescriptorPool> m_descriptorPool;
5082 vector<vk::VkDescriptorSet> m_descriptorSets;
5083 vector<vk::VkBufferView> m_bufferViews;
5084
5085 const vk::DeviceInterface* m_vkd;
5086 vk::VkDevice m_device;
5087 vk::VkDeviceSize m_bufferSize;
5088 deUint32 m_maxUniformTexelCount;
5089 };
5090
~RenderVertexUniformTexelBuffer(void)5091 RenderVertexUniformTexelBuffer::~RenderVertexUniformTexelBuffer (void)
5092 {
5093 for (size_t bufferViewNdx = 0; bufferViewNdx < m_bufferViews.size(); bufferViewNdx++)
5094 {
5095 if (!!m_bufferViews[bufferViewNdx])
5096 {
5097 m_vkd->destroyBufferView(m_device, m_bufferViews[bufferViewNdx], DE_NULL);
5098 m_bufferViews[bufferViewNdx] = (vk::VkBufferView)0;
5099 }
5100 }
5101 }
5102
logPrepare(TestLog & log,size_t commandIndex) const5103 void RenderVertexUniformTexelBuffer::logPrepare (TestLog& log, size_t commandIndex) const
5104 {
5105 log << TestLog::Message << commandIndex << ":" << getName() << " Create pipeline for render buffer as uniform buffer." << TestLog::EndMessage;
5106 }
5107
logSubmit(TestLog & log,size_t commandIndex) const5108 void RenderVertexUniformTexelBuffer::logSubmit (TestLog& log, size_t commandIndex) const
5109 {
5110 log << TestLog::Message << commandIndex << ":" << getName() << " Render using buffer as uniform buffer." << TestLog::EndMessage;
5111 }
5112
prepare(PrepareRenderPassContext & context)5113 void RenderVertexUniformTexelBuffer::prepare (PrepareRenderPassContext& context)
5114 {
5115 const vk::InstanceInterface& vki = context.getContext().getInstanceInterface();
5116 const vk::VkPhysicalDevice physicalDevice = context.getContext().getPhysicalDevice();
5117 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
5118 const vk::VkDevice device = context.getContext().getDevice();
5119 const vk::VkRenderPass renderPass = context.getRenderPass();
5120 const deUint32 subpass = 0;
5121 const vk::Unique<vk::VkShaderModule> vertexShaderModule (vk::createShaderModule(vkd, device, context.getBinaryCollection().get("uniform-texel-buffer.vert"), 0));
5122 const vk::Unique<vk::VkShaderModule> fragmentShaderModule (vk::createShaderModule(vkd, device, context.getBinaryCollection().get("render-white.frag"), 0));
5123 vector<vk::VkDescriptorSetLayoutBinding> bindings;
5124
5125 m_device = device;
5126 m_vkd = &vkd;
5127 m_bufferSize = context.getBufferSize();
5128 m_maxUniformTexelCount = vk::getPhysicalDeviceProperties(vki, physicalDevice).limits.maxTexelBufferElements;
5129
5130 {
5131 const vk::VkDescriptorSetLayoutBinding binding =
5132 {
5133 0u,
5134 vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
5135 1,
5136 vk::VK_SHADER_STAGE_VERTEX_BIT,
5137 DE_NULL
5138 };
5139
5140 bindings.push_back(binding);
5141 }
5142
5143 createPipelineWithResources(vkd, device, renderPass, subpass, *vertexShaderModule, *fragmentShaderModule, context.getTargetWidth(), context.getTargetHeight(),
5144 vector<vk::VkVertexInputBindingDescription>(), vector<vk::VkVertexInputAttributeDescription>(), bindings, vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST, 0u, DE_NULL, m_resources);
5145
5146 {
5147 const deUint32 descriptorCount = (deUint32)(divRoundUp(m_bufferSize, (vk::VkDeviceSize)m_maxUniformTexelCount * 2));
5148 const vk::VkDescriptorPoolSize poolSizes =
5149 {
5150 vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
5151 descriptorCount
5152 };
5153 const vk::VkDescriptorPoolCreateInfo createInfo =
5154 {
5155 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
5156 DE_NULL,
5157 vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
5158
5159 descriptorCount,
5160 1u,
5161 &poolSizes,
5162 };
5163
5164 m_descriptorPool = vk::createDescriptorPool(vkd, device, &createInfo);
5165 m_descriptorSets.resize(descriptorCount, (vk::VkDescriptorSet)0);
5166 m_bufferViews.resize(descriptorCount, (vk::VkBufferView)0);
5167 }
5168
5169 for (size_t descriptorSetNdx = 0; descriptorSetNdx < m_descriptorSets.size(); descriptorSetNdx++)
5170 {
5171 const deUint32 count = (deUint32)(m_bufferSize < (descriptorSetNdx + 1) * m_maxUniformTexelCount * 2
5172 ? m_bufferSize - descriptorSetNdx * m_maxUniformTexelCount * 2
5173 : m_maxUniformTexelCount * 2) / 2;
5174 const vk::VkDescriptorSetLayout layout = *m_resources.descriptorSetLayout;
5175 const vk::VkDescriptorSetAllocateInfo allocateInfo =
5176 {
5177 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
5178 DE_NULL,
5179
5180 *m_descriptorPool,
5181 1,
5182 &layout
5183 };
5184
5185 m_descriptorSets[descriptorSetNdx] = vk::allocateDescriptorSet(vkd, device, &allocateInfo).disown();
5186
5187 {
5188 const vk::VkBufferViewCreateInfo createInfo =
5189 {
5190 vk::VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,
5191 DE_NULL,
5192 0u,
5193
5194 context.getBuffer(),
5195 vk::VK_FORMAT_R16_UINT,
5196 descriptorSetNdx * m_maxUniformTexelCount * 2,
5197 count * 2
5198 };
5199
5200 VK_CHECK(vkd.createBufferView(device, &createInfo, DE_NULL, &m_bufferViews[descriptorSetNdx]));
5201 }
5202
5203 {
5204 const vk::VkWriteDescriptorSet write =
5205 {
5206 vk::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
5207 DE_NULL,
5208 m_descriptorSets[descriptorSetNdx],
5209 0u,
5210 0u,
5211 1u,
5212 vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
5213 DE_NULL,
5214 DE_NULL,
5215 &m_bufferViews[descriptorSetNdx]
5216 };
5217
5218 vkd.updateDescriptorSets(device, 1u, &write, 0u, DE_NULL);
5219 }
5220 }
5221 }
5222
submit(SubmitContext & context)5223 void RenderVertexUniformTexelBuffer::submit (SubmitContext& context)
5224 {
5225 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
5226 const vk::VkCommandBuffer commandBuffer = context.getCommandBuffer();
5227
5228 vkd.cmdBindPipeline(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_resources.pipeline);
5229
5230 for (size_t descriptorSetNdx = 0; descriptorSetNdx < m_descriptorSets.size(); descriptorSetNdx++)
5231 {
5232 const deUint32 count = (deUint32)(m_bufferSize < (descriptorSetNdx + 1) * m_maxUniformTexelCount * 2
5233 ? m_bufferSize - descriptorSetNdx * m_maxUniformTexelCount * 2
5234 : m_maxUniformTexelCount * 2) / 2;
5235
5236 vkd.cmdBindDescriptorSets(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_resources.pipelineLayout, 0u, 1u, &m_descriptorSets[descriptorSetNdx], 0u, DE_NULL);
5237 vkd.cmdDraw(commandBuffer, count, 1, 0, 0);
5238 }
5239 }
5240
verify(VerifyRenderPassContext & context,size_t)5241 void RenderVertexUniformTexelBuffer::verify (VerifyRenderPassContext& context, size_t)
5242 {
5243 for (size_t descriptorSetNdx = 0; descriptorSetNdx < m_descriptorSets.size(); descriptorSetNdx++)
5244 {
5245 const size_t offset = descriptorSetNdx * m_maxUniformTexelCount * 2;
5246 const deUint32 count = (deUint32)(m_bufferSize < (descriptorSetNdx + 1) * m_maxUniformTexelCount * 2
5247 ? m_bufferSize - descriptorSetNdx * m_maxUniformTexelCount * 2
5248 : m_maxUniformTexelCount * 2) / 2;
5249
5250 for (size_t pos = 0; pos < (size_t)count; pos++)
5251 {
5252 const deUint8 x = context.getReference().get(offset + pos * 2);
5253 const deUint8 y = context.getReference().get(offset + (pos * 2) + 1);
5254
5255 context.getReferenceTarget().getAccess().setPixel(Vec4(1.0f, 1.0f, 1.0f, 1.0f), x, y);
5256 }
5257 }
5258 }
5259
5260 class RenderVertexStorageBuffer : public RenderPassCommand
5261 {
5262 public:
RenderVertexStorageBuffer(void)5263 RenderVertexStorageBuffer (void) {}
5264 ~RenderVertexStorageBuffer (void);
5265
getName(void) const5266 const char* getName (void) const { return "RenderVertexStorageBuffer"; }
5267 void logPrepare (TestLog&, size_t) const;
5268 void logSubmit (TestLog&, size_t) const;
5269 void prepare (PrepareRenderPassContext&);
5270 void submit (SubmitContext& context);
5271 void verify (VerifyRenderPassContext&, size_t);
5272
5273 private:
5274 PipelineResources m_resources;
5275 vk::Move<vk::VkDescriptorPool> m_descriptorPool;
5276 vector<vk::VkDescriptorSet> m_descriptorSets;
5277
5278 vk::VkDeviceSize m_bufferSize;
5279 };
5280
~RenderVertexStorageBuffer(void)5281 RenderVertexStorageBuffer::~RenderVertexStorageBuffer (void)
5282 {
5283 }
5284
logPrepare(TestLog & log,size_t commandIndex) const5285 void RenderVertexStorageBuffer::logPrepare (TestLog& log, size_t commandIndex) const
5286 {
5287 log << TestLog::Message << commandIndex << ":" << getName() << " Create pipeline for render buffer as storage buffer." << TestLog::EndMessage;
5288 }
5289
logSubmit(TestLog & log,size_t commandIndex) const5290 void RenderVertexStorageBuffer::logSubmit (TestLog& log, size_t commandIndex) const
5291 {
5292 log << TestLog::Message << commandIndex << ":" << getName() << " Render using buffer as storage buffer." << TestLog::EndMessage;
5293 }
5294
prepare(PrepareRenderPassContext & context)5295 void RenderVertexStorageBuffer::prepare (PrepareRenderPassContext& context)
5296 {
5297 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
5298 const vk::VkDevice device = context.getContext().getDevice();
5299 const vk::VkRenderPass renderPass = context.getRenderPass();
5300 const deUint32 subpass = 0;
5301 const vk::Unique<vk::VkShaderModule> vertexShaderModule (vk::createShaderModule(vkd, device, context.getBinaryCollection().get("storage-buffer.vert"), 0));
5302 const vk::Unique<vk::VkShaderModule> fragmentShaderModule (vk::createShaderModule(vkd, device, context.getBinaryCollection().get("render-white.frag"), 0));
5303 vector<vk::VkDescriptorSetLayoutBinding> bindings;
5304
5305 m_bufferSize = context.getBufferSize();
5306
5307 {
5308 const vk::VkDescriptorSetLayoutBinding binding =
5309 {
5310 0u,
5311 vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
5312 1,
5313 vk::VK_SHADER_STAGE_VERTEX_BIT,
5314 DE_NULL
5315 };
5316
5317 bindings.push_back(binding);
5318 }
5319
5320 createPipelineWithResources(vkd, device, renderPass, subpass, *vertexShaderModule, *fragmentShaderModule, context.getTargetWidth(), context.getTargetHeight(),
5321 vector<vk::VkVertexInputBindingDescription>(), vector<vk::VkVertexInputAttributeDescription>(), bindings, vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST, 0u, DE_NULL, m_resources);
5322
5323 {
5324 const deUint32 descriptorCount = (deUint32)(divRoundUp(m_bufferSize, (vk::VkDeviceSize)MAX_STORAGE_BUFFER_SIZE));
5325 const vk::VkDescriptorPoolSize poolSizes =
5326 {
5327 vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
5328 descriptorCount
5329 };
5330 const vk::VkDescriptorPoolCreateInfo createInfo =
5331 {
5332 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
5333 DE_NULL,
5334 vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
5335
5336 descriptorCount,
5337 1u,
5338 &poolSizes,
5339 };
5340
5341 m_descriptorPool = vk::createDescriptorPool(vkd, device, &createInfo);
5342 m_descriptorSets.resize(descriptorCount);
5343 }
5344
5345 for (size_t descriptorSetNdx = 0; descriptorSetNdx < m_descriptorSets.size(); descriptorSetNdx++)
5346 {
5347 const vk::VkDescriptorSetLayout layout = *m_resources.descriptorSetLayout;
5348 const vk::VkDescriptorSetAllocateInfo allocateInfo =
5349 {
5350 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
5351 DE_NULL,
5352
5353 *m_descriptorPool,
5354 1,
5355 &layout
5356 };
5357
5358 m_descriptorSets[descriptorSetNdx] = vk::allocateDescriptorSet(vkd, device, &allocateInfo).disown();
5359
5360 {
5361 const vk::VkDescriptorBufferInfo bufferInfo =
5362 {
5363 context.getBuffer(),
5364 descriptorSetNdx * MAX_STORAGE_BUFFER_SIZE,
5365 de::min(m_bufferSize - descriptorSetNdx * MAX_STORAGE_BUFFER_SIZE, (vk::VkDeviceSize)MAX_STORAGE_BUFFER_SIZE)
5366 };
5367 const vk::VkWriteDescriptorSet write =
5368 {
5369 vk::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
5370 DE_NULL,
5371 m_descriptorSets[descriptorSetNdx],
5372 0u,
5373 0u,
5374 1u,
5375 vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
5376 DE_NULL,
5377 &bufferInfo,
5378 DE_NULL,
5379 };
5380
5381 vkd.updateDescriptorSets(device, 1u, &write, 0u, DE_NULL);
5382 }
5383 }
5384 }
5385
submit(SubmitContext & context)5386 void RenderVertexStorageBuffer::submit (SubmitContext& context)
5387 {
5388 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
5389 const vk::VkCommandBuffer commandBuffer = context.getCommandBuffer();
5390
5391 vkd.cmdBindPipeline(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_resources.pipeline);
5392
5393 for (size_t descriptorSetNdx = 0; descriptorSetNdx < m_descriptorSets.size(); descriptorSetNdx++)
5394 {
5395 const size_t size = m_bufferSize < (descriptorSetNdx + 1) * MAX_STORAGE_BUFFER_SIZE
5396 ? (size_t)(m_bufferSize - descriptorSetNdx * MAX_STORAGE_BUFFER_SIZE)
5397 : (size_t)(MAX_STORAGE_BUFFER_SIZE);
5398
5399 vkd.cmdBindDescriptorSets(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_resources.pipelineLayout, 0u, 1u, &m_descriptorSets[descriptorSetNdx], 0u, DE_NULL);
5400 vkd.cmdDraw(commandBuffer, (deUint32)(size / 2), 1, 0, 0);
5401 }
5402 }
5403
verify(VerifyRenderPassContext & context,size_t)5404 void RenderVertexStorageBuffer::verify (VerifyRenderPassContext& context, size_t)
5405 {
5406 for (size_t descriptorSetNdx = 0; descriptorSetNdx < m_descriptorSets.size(); descriptorSetNdx++)
5407 {
5408 const size_t offset = descriptorSetNdx * MAX_STORAGE_BUFFER_SIZE;
5409 const size_t size = m_bufferSize < (descriptorSetNdx + 1) * MAX_STORAGE_BUFFER_SIZE
5410 ? (size_t)(m_bufferSize - descriptorSetNdx * MAX_STORAGE_BUFFER_SIZE)
5411 : (size_t)(MAX_STORAGE_BUFFER_SIZE);
5412
5413 for (size_t pos = 0; pos < size / 2; pos++)
5414 {
5415 const deUint8 x = context.getReference().get(offset + pos * 2);
5416 const deUint8 y = context.getReference().get(offset + (pos * 2) + 1);
5417
5418 context.getReferenceTarget().getAccess().setPixel(Vec4(1.0f, 1.0f, 1.0f, 1.0f), x, y);
5419 }
5420 }
5421 }
5422
5423 class RenderVertexStorageTexelBuffer : public RenderPassCommand
5424 {
5425 public:
RenderVertexStorageTexelBuffer(void)5426 RenderVertexStorageTexelBuffer (void) {}
5427 ~RenderVertexStorageTexelBuffer (void);
5428
getName(void) const5429 const char* getName (void) const { return "RenderVertexStorageTexelBuffer"; }
5430 void logPrepare (TestLog&, size_t) const;
5431 void logSubmit (TestLog&, size_t) const;
5432 void prepare (PrepareRenderPassContext&);
5433 void submit (SubmitContext& context);
5434 void verify (VerifyRenderPassContext&, size_t);
5435
5436 private:
5437 PipelineResources m_resources;
5438 vk::Move<vk::VkDescriptorPool> m_descriptorPool;
5439 vector<vk::VkDescriptorSet> m_descriptorSets;
5440 vector<vk::VkBufferView> m_bufferViews;
5441
5442 const vk::DeviceInterface* m_vkd;
5443 vk::VkDevice m_device;
5444 vk::VkDeviceSize m_bufferSize;
5445 deUint32 m_maxStorageTexelCount;
5446 };
5447
~RenderVertexStorageTexelBuffer(void)5448 RenderVertexStorageTexelBuffer::~RenderVertexStorageTexelBuffer (void)
5449 {
5450 for (size_t bufferViewNdx = 0; bufferViewNdx < m_bufferViews.size(); bufferViewNdx++)
5451 {
5452 if (!!m_bufferViews[bufferViewNdx])
5453 {
5454 m_vkd->destroyBufferView(m_device, m_bufferViews[bufferViewNdx], DE_NULL);
5455 m_bufferViews[bufferViewNdx] = (vk::VkBufferView)0;
5456 }
5457 }
5458 }
5459
logPrepare(TestLog & log,size_t commandIndex) const5460 void RenderVertexStorageTexelBuffer::logPrepare (TestLog& log, size_t commandIndex) const
5461 {
5462 log << TestLog::Message << commandIndex << ":" << getName() << " Create pipeline for render buffer as storage buffer." << TestLog::EndMessage;
5463 }
5464
logSubmit(TestLog & log,size_t commandIndex) const5465 void RenderVertexStorageTexelBuffer::logSubmit (TestLog& log, size_t commandIndex) const
5466 {
5467 log << TestLog::Message << commandIndex << ":" << getName() << " Render using buffer as storage buffer." << TestLog::EndMessage;
5468 }
5469
prepare(PrepareRenderPassContext & context)5470 void RenderVertexStorageTexelBuffer::prepare (PrepareRenderPassContext& context)
5471 {
5472 const vk::InstanceInterface& vki = context.getContext().getInstanceInterface();
5473 const vk::VkPhysicalDevice physicalDevice = context.getContext().getPhysicalDevice();
5474 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
5475 const vk::VkDevice device = context.getContext().getDevice();
5476 const vk::VkRenderPass renderPass = context.getRenderPass();
5477 const deUint32 subpass = 0;
5478 const vk::Unique<vk::VkShaderModule> vertexShaderModule (vk::createShaderModule(vkd, device, context.getBinaryCollection().get("storage-texel-buffer.vert"), 0));
5479 const vk::Unique<vk::VkShaderModule> fragmentShaderModule (vk::createShaderModule(vkd, device, context.getBinaryCollection().get("render-white.frag"), 0));
5480 vector<vk::VkDescriptorSetLayoutBinding> bindings;
5481
5482 m_device = device;
5483 m_vkd = &vkd;
5484 m_bufferSize = context.getBufferSize();
5485 m_maxStorageTexelCount = vk::getPhysicalDeviceProperties(vki, physicalDevice).limits.maxTexelBufferElements;
5486
5487 {
5488 const vk::VkDescriptorSetLayoutBinding binding =
5489 {
5490 0u,
5491 vk::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
5492 1,
5493 vk::VK_SHADER_STAGE_VERTEX_BIT,
5494 DE_NULL
5495 };
5496
5497 bindings.push_back(binding);
5498 }
5499
5500 createPipelineWithResources(vkd, device, renderPass, subpass, *vertexShaderModule, *fragmentShaderModule, context.getTargetWidth(), context.getTargetHeight(),
5501 vector<vk::VkVertexInputBindingDescription>(), vector<vk::VkVertexInputAttributeDescription>(), bindings, vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST, 0u, DE_NULL, m_resources);
5502
5503 {
5504 const deUint32 descriptorCount = (deUint32)(divRoundUp(m_bufferSize, (vk::VkDeviceSize)m_maxStorageTexelCount * 4));
5505 const vk::VkDescriptorPoolSize poolSizes =
5506 {
5507 vk::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
5508 descriptorCount
5509 };
5510 const vk::VkDescriptorPoolCreateInfo createInfo =
5511 {
5512 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
5513 DE_NULL,
5514 vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
5515
5516 descriptorCount,
5517 1u,
5518 &poolSizes,
5519 };
5520
5521 m_descriptorPool = vk::createDescriptorPool(vkd, device, &createInfo);
5522 m_descriptorSets.resize(descriptorCount, (vk::VkDescriptorSet)0);
5523 m_bufferViews.resize(descriptorCount, (vk::VkBufferView)0);
5524 }
5525
5526 for (size_t descriptorSetNdx = 0; descriptorSetNdx < m_descriptorSets.size(); descriptorSetNdx++)
5527 {
5528 const vk::VkDescriptorSetLayout layout = *m_resources.descriptorSetLayout;
5529 const vk::VkDescriptorSetAllocateInfo allocateInfo =
5530 {
5531 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
5532 DE_NULL,
5533
5534 *m_descriptorPool,
5535 1,
5536 &layout
5537 };
5538
5539 m_descriptorSets[descriptorSetNdx] = vk::allocateDescriptorSet(vkd, device, &allocateInfo).disown();
5540
5541 {
5542 const vk::VkBufferViewCreateInfo createInfo =
5543 {
5544 vk::VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,
5545 DE_NULL,
5546 0u,
5547
5548 context.getBuffer(),
5549 vk::VK_FORMAT_R32_UINT,
5550 descriptorSetNdx * m_maxStorageTexelCount * 4,
5551 (deUint32)de::min<vk::VkDeviceSize>(m_maxStorageTexelCount * 4, m_bufferSize - descriptorSetNdx * m_maxStorageTexelCount * 4)
5552 };
5553
5554 VK_CHECK(vkd.createBufferView(device, &createInfo, DE_NULL, &m_bufferViews[descriptorSetNdx]));
5555 }
5556
5557 {
5558 const vk::VkWriteDescriptorSet write =
5559 {
5560 vk::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
5561 DE_NULL,
5562 m_descriptorSets[descriptorSetNdx],
5563 0u,
5564 0u,
5565 1u,
5566 vk::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
5567 DE_NULL,
5568 DE_NULL,
5569 &m_bufferViews[descriptorSetNdx]
5570 };
5571
5572 vkd.updateDescriptorSets(device, 1u, &write, 0u, DE_NULL);
5573 }
5574 }
5575 }
5576
submit(SubmitContext & context)5577 void RenderVertexStorageTexelBuffer::submit (SubmitContext& context)
5578 {
5579 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
5580 const vk::VkCommandBuffer commandBuffer = context.getCommandBuffer();
5581
5582 vkd.cmdBindPipeline(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_resources.pipeline);
5583
5584 for (size_t descriptorSetNdx = 0; descriptorSetNdx < m_descriptorSets.size(); descriptorSetNdx++)
5585 {
5586 const deUint32 count = (deUint32)(m_bufferSize < (descriptorSetNdx + 1) * m_maxStorageTexelCount * 4
5587 ? m_bufferSize - descriptorSetNdx * m_maxStorageTexelCount * 4
5588 : m_maxStorageTexelCount * 4) / 2;
5589
5590 vkd.cmdBindDescriptorSets(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_resources.pipelineLayout, 0u, 1u, &m_descriptorSets[descriptorSetNdx], 0u, DE_NULL);
5591 vkd.cmdDraw(commandBuffer, count, 1, 0, 0);
5592 }
5593 }
5594
verify(VerifyRenderPassContext & context,size_t)5595 void RenderVertexStorageTexelBuffer::verify (VerifyRenderPassContext& context, size_t)
5596 {
5597 for (size_t descriptorSetNdx = 0; descriptorSetNdx < m_descriptorSets.size(); descriptorSetNdx++)
5598 {
5599 const size_t offset = descriptorSetNdx * m_maxStorageTexelCount * 4;
5600 const deUint32 count = (deUint32)(m_bufferSize < (descriptorSetNdx + 1) * m_maxStorageTexelCount * 4
5601 ? m_bufferSize - descriptorSetNdx * m_maxStorageTexelCount * 4
5602 : m_maxStorageTexelCount * 4) / 2;
5603
5604 DE_ASSERT(context.getReference().getSize() <= 4 * m_maxStorageTexelCount * m_descriptorSets.size());
5605 DE_ASSERT(context.getReference().getSize() > offset);
5606 DE_ASSERT(offset + count * 2 <= context.getReference().getSize());
5607
5608 for (size_t pos = 0; pos < (size_t)count; pos++)
5609 {
5610 const deUint8 x = context.getReference().get(offset + pos * 2);
5611 const deUint8 y = context.getReference().get(offset + (pos * 2) + 1);
5612
5613 context.getReferenceTarget().getAccess().setPixel(Vec4(1.0f, 1.0f, 1.0f, 1.0f), x, y);
5614 }
5615 }
5616 }
5617
5618 class RenderVertexStorageImage : public RenderPassCommand
5619 {
5620 public:
RenderVertexStorageImage(void)5621 RenderVertexStorageImage (void) {}
5622 ~RenderVertexStorageImage (void);
5623
getName(void) const5624 const char* getName (void) const { return "RenderVertexStorageImage"; }
5625 void logPrepare (TestLog&, size_t) const;
5626 void logSubmit (TestLog&, size_t) const;
5627 void prepare (PrepareRenderPassContext&);
5628 void submit (SubmitContext& context);
5629 void verify (VerifyRenderPassContext&, size_t);
5630
5631 private:
5632 PipelineResources m_resources;
5633 vk::Move<vk::VkDescriptorPool> m_descriptorPool;
5634 vk::Move<vk::VkDescriptorSet> m_descriptorSet;
5635 vk::Move<vk::VkImageView> m_imageView;
5636 };
5637
~RenderVertexStorageImage(void)5638 RenderVertexStorageImage::~RenderVertexStorageImage (void)
5639 {
5640 }
5641
logPrepare(TestLog & log,size_t commandIndex) const5642 void RenderVertexStorageImage::logPrepare (TestLog& log, size_t commandIndex) const
5643 {
5644 log << TestLog::Message << commandIndex << ":" << getName() << " Create pipeline for render storage image." << TestLog::EndMessage;
5645 }
5646
logSubmit(TestLog & log,size_t commandIndex) const5647 void RenderVertexStorageImage::logSubmit (TestLog& log, size_t commandIndex) const
5648 {
5649 log << TestLog::Message << commandIndex << ":" << getName() << " Render using storage image." << TestLog::EndMessage;
5650 }
5651
prepare(PrepareRenderPassContext & context)5652 void RenderVertexStorageImage::prepare (PrepareRenderPassContext& context)
5653 {
5654 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
5655 const vk::VkDevice device = context.getContext().getDevice();
5656 const vk::VkRenderPass renderPass = context.getRenderPass();
5657 const deUint32 subpass = 0;
5658 const vk::Unique<vk::VkShaderModule> vertexShaderModule (vk::createShaderModule(vkd, device, context.getBinaryCollection().get("storage-image.vert"), 0));
5659 const vk::Unique<vk::VkShaderModule> fragmentShaderModule (vk::createShaderModule(vkd, device, context.getBinaryCollection().get("render-white.frag"), 0));
5660 vector<vk::VkDescriptorSetLayoutBinding> bindings;
5661
5662 {
5663 const vk::VkDescriptorSetLayoutBinding binding =
5664 {
5665 0u,
5666 vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
5667 1,
5668 vk::VK_SHADER_STAGE_VERTEX_BIT,
5669 DE_NULL
5670 };
5671
5672 bindings.push_back(binding);
5673 }
5674
5675 createPipelineWithResources(vkd, device, renderPass, subpass, *vertexShaderModule, *fragmentShaderModule, context.getTargetWidth(), context.getTargetHeight(),
5676 vector<vk::VkVertexInputBindingDescription>(), vector<vk::VkVertexInputAttributeDescription>(), bindings, vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST, 0u, DE_NULL, m_resources);
5677
5678 {
5679 const vk::VkDescriptorPoolSize poolSizes =
5680 {
5681 vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
5682 1
5683 };
5684 const vk::VkDescriptorPoolCreateInfo createInfo =
5685 {
5686 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
5687 DE_NULL,
5688 vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
5689
5690 1u,
5691 1u,
5692 &poolSizes,
5693 };
5694
5695 m_descriptorPool = vk::createDescriptorPool(vkd, device, &createInfo);
5696 }
5697
5698 {
5699 const vk::VkDescriptorSetLayout layout = *m_resources.descriptorSetLayout;
5700 const vk::VkDescriptorSetAllocateInfo allocateInfo =
5701 {
5702 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
5703 DE_NULL,
5704
5705 *m_descriptorPool,
5706 1,
5707 &layout
5708 };
5709
5710 m_descriptorSet = vk::allocateDescriptorSet(vkd, device, &allocateInfo);
5711
5712 {
5713 const vk::VkImageViewCreateInfo createInfo =
5714 {
5715 vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
5716 DE_NULL,
5717 0u,
5718
5719 context.getImage(),
5720 vk::VK_IMAGE_VIEW_TYPE_2D,
5721 vk::VK_FORMAT_R8G8B8A8_UNORM,
5722 vk::makeComponentMappingRGBA(),
5723 {
5724 vk::VK_IMAGE_ASPECT_COLOR_BIT,
5725 0u,
5726 1u,
5727 0u,
5728 1u
5729 }
5730 };
5731
5732 m_imageView = vk::createImageView(vkd, device, &createInfo);
5733 }
5734
5735 {
5736 const vk::VkDescriptorImageInfo imageInfo =
5737 {
5738 0,
5739 *m_imageView,
5740 context.getImageLayout()
5741 };
5742 const vk::VkWriteDescriptorSet write =
5743 {
5744 vk::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
5745 DE_NULL,
5746 *m_descriptorSet,
5747 0u,
5748 0u,
5749 1u,
5750 vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
5751 &imageInfo,
5752 DE_NULL,
5753 DE_NULL,
5754 };
5755
5756 vkd.updateDescriptorSets(device, 1u, &write, 0u, DE_NULL);
5757 }
5758 }
5759 }
5760
submit(SubmitContext & context)5761 void RenderVertexStorageImage::submit (SubmitContext& context)
5762 {
5763 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
5764 const vk::VkCommandBuffer commandBuffer = context.getCommandBuffer();
5765
5766 vkd.cmdBindPipeline(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_resources.pipeline);
5767
5768 vkd.cmdBindDescriptorSets(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_resources.pipelineLayout, 0u, 1u, &(*m_descriptorSet), 0u, DE_NULL);
5769 vkd.cmdDraw(commandBuffer, context.getImageWidth() * context.getImageHeight() * 2, 1, 0, 0);
5770 }
5771
verify(VerifyRenderPassContext & context,size_t)5772 void RenderVertexStorageImage::verify (VerifyRenderPassContext& context, size_t)
5773 {
5774 for (int pos = 0; pos < (int)(context.getReferenceImage().getWidth() * context.getReferenceImage().getHeight() * 2); pos++)
5775 {
5776 const tcu::IVec3 size = context.getReferenceImage().getAccess().getSize();
5777 const tcu::UVec4 pixel = context.getReferenceImage().getAccess().getPixelUint((pos / 2) / size.x(), (pos / 2) % size.x());
5778
5779 if (pos % 2 == 0)
5780 context.getReferenceTarget().getAccess().setPixel(Vec4(1.0f, 1.0f, 1.0f, 1.0f), pixel.x(), pixel.y());
5781 else
5782 context.getReferenceTarget().getAccess().setPixel(Vec4(1.0f, 1.0f, 1.0f, 1.0f), pixel.z(), pixel.w());
5783 }
5784 }
5785
5786 class RenderVertexSampledImage : public RenderPassCommand
5787 {
5788 public:
RenderVertexSampledImage(void)5789 RenderVertexSampledImage (void) {}
5790 ~RenderVertexSampledImage (void);
5791
getName(void) const5792 const char* getName (void) const { return "RenderVertexSampledImage"; }
5793 void logPrepare (TestLog&, size_t) const;
5794 void logSubmit (TestLog&, size_t) const;
5795 void prepare (PrepareRenderPassContext&);
5796 void submit (SubmitContext& context);
5797 void verify (VerifyRenderPassContext&, size_t);
5798
5799 private:
5800 PipelineResources m_resources;
5801 vk::Move<vk::VkDescriptorPool> m_descriptorPool;
5802 vk::Move<vk::VkDescriptorSet> m_descriptorSet;
5803 vk::Move<vk::VkImageView> m_imageView;
5804 vk::Move<vk::VkSampler> m_sampler;
5805 };
5806
~RenderVertexSampledImage(void)5807 RenderVertexSampledImage::~RenderVertexSampledImage (void)
5808 {
5809 }
5810
logPrepare(TestLog & log,size_t commandIndex) const5811 void RenderVertexSampledImage::logPrepare (TestLog& log, size_t commandIndex) const
5812 {
5813 log << TestLog::Message << commandIndex << ":" << getName() << " Create pipeline for render sampled image." << TestLog::EndMessage;
5814 }
5815
logSubmit(TestLog & log,size_t commandIndex) const5816 void RenderVertexSampledImage::logSubmit (TestLog& log, size_t commandIndex) const
5817 {
5818 log << TestLog::Message << commandIndex << ":" << getName() << " Render using sampled image." << TestLog::EndMessage;
5819 }
5820
prepare(PrepareRenderPassContext & context)5821 void RenderVertexSampledImage::prepare (PrepareRenderPassContext& context)
5822 {
5823 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
5824 const vk::VkDevice device = context.getContext().getDevice();
5825 const vk::VkRenderPass renderPass = context.getRenderPass();
5826 const deUint32 subpass = 0;
5827 const vk::Unique<vk::VkShaderModule> vertexShaderModule (vk::createShaderModule(vkd, device, context.getBinaryCollection().get("sampled-image.vert"), 0));
5828 const vk::Unique<vk::VkShaderModule> fragmentShaderModule (vk::createShaderModule(vkd, device, context.getBinaryCollection().get("render-white.frag"), 0));
5829 vector<vk::VkDescriptorSetLayoutBinding> bindings;
5830
5831 {
5832 const vk::VkDescriptorSetLayoutBinding binding =
5833 {
5834 0u,
5835 vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
5836 1,
5837 vk::VK_SHADER_STAGE_VERTEX_BIT,
5838 DE_NULL
5839 };
5840
5841 bindings.push_back(binding);
5842 }
5843
5844 createPipelineWithResources(vkd, device, renderPass, subpass, *vertexShaderModule, *fragmentShaderModule, context.getTargetWidth(), context.getTargetHeight(),
5845 vector<vk::VkVertexInputBindingDescription>(), vector<vk::VkVertexInputAttributeDescription>(), bindings, vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST, 0u, DE_NULL, m_resources);
5846
5847 {
5848 const vk::VkDescriptorPoolSize poolSizes =
5849 {
5850 vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
5851 1
5852 };
5853 const vk::VkDescriptorPoolCreateInfo createInfo =
5854 {
5855 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
5856 DE_NULL,
5857 vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
5858
5859 1u,
5860 1u,
5861 &poolSizes,
5862 };
5863
5864 m_descriptorPool = vk::createDescriptorPool(vkd, device, &createInfo);
5865 }
5866
5867 {
5868 const vk::VkDescriptorSetLayout layout = *m_resources.descriptorSetLayout;
5869 const vk::VkDescriptorSetAllocateInfo allocateInfo =
5870 {
5871 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
5872 DE_NULL,
5873
5874 *m_descriptorPool,
5875 1,
5876 &layout
5877 };
5878
5879 m_descriptorSet = vk::allocateDescriptorSet(vkd, device, &allocateInfo);
5880
5881 {
5882 const vk::VkImageViewCreateInfo createInfo =
5883 {
5884 vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
5885 DE_NULL,
5886 0u,
5887
5888 context.getImage(),
5889 vk::VK_IMAGE_VIEW_TYPE_2D,
5890 vk::VK_FORMAT_R8G8B8A8_UNORM,
5891 vk::makeComponentMappingRGBA(),
5892 {
5893 vk::VK_IMAGE_ASPECT_COLOR_BIT,
5894 0u,
5895 1u,
5896 0u,
5897 1u
5898 }
5899 };
5900
5901 m_imageView = vk::createImageView(vkd, device, &createInfo);
5902 }
5903
5904 {
5905 const vk::VkSamplerCreateInfo createInfo =
5906 {
5907 vk::VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
5908 DE_NULL,
5909 0u,
5910
5911 vk::VK_FILTER_NEAREST,
5912 vk::VK_FILTER_NEAREST,
5913
5914 vk::VK_SAMPLER_MIPMAP_MODE_LINEAR,
5915 vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
5916 vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
5917 vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
5918 0.0f,
5919 VK_FALSE,
5920 1.0f,
5921 VK_FALSE,
5922 vk::VK_COMPARE_OP_ALWAYS,
5923 0.0f,
5924 0.0f,
5925 vk::VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,
5926 VK_FALSE
5927 };
5928
5929 m_sampler = vk::createSampler(vkd, device, &createInfo);
5930 }
5931
5932 {
5933 const vk::VkDescriptorImageInfo imageInfo =
5934 {
5935 *m_sampler,
5936 *m_imageView,
5937 context.getImageLayout()
5938 };
5939 const vk::VkWriteDescriptorSet write =
5940 {
5941 vk::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
5942 DE_NULL,
5943 *m_descriptorSet,
5944 0u,
5945 0u,
5946 1u,
5947 vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
5948 &imageInfo,
5949 DE_NULL,
5950 DE_NULL,
5951 };
5952
5953 vkd.updateDescriptorSets(device, 1u, &write, 0u, DE_NULL);
5954 }
5955 }
5956 }
5957
submit(SubmitContext & context)5958 void RenderVertexSampledImage::submit (SubmitContext& context)
5959 {
5960 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
5961 const vk::VkCommandBuffer commandBuffer = context.getCommandBuffer();
5962
5963 vkd.cmdBindPipeline(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_resources.pipeline);
5964
5965 vkd.cmdBindDescriptorSets(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_resources.pipelineLayout, 0u, 1u, &(*m_descriptorSet), 0u, DE_NULL);
5966 vkd.cmdDraw(commandBuffer, context.getImageWidth() * context.getImageHeight() * 2, 1, 0, 0);
5967 }
5968
verify(VerifyRenderPassContext & context,size_t)5969 void RenderVertexSampledImage::verify (VerifyRenderPassContext& context, size_t)
5970 {
5971 for (int pos = 0; pos < (int)(context.getReferenceImage().getWidth() * context.getReferenceImage().getHeight() * 2); pos++)
5972 {
5973 const tcu::IVec3 size = context.getReferenceImage().getAccess().getSize();
5974 const tcu::UVec4 pixel = context.getReferenceImage().getAccess().getPixelUint((pos / 2) / size.x(), (pos / 2) % size.x());
5975
5976 if (pos % 2 == 0)
5977 context.getReferenceTarget().getAccess().setPixel(Vec4(1.0f, 1.0f, 1.0f, 1.0f), pixel.x(), pixel.y());
5978 else
5979 context.getReferenceTarget().getAccess().setPixel(Vec4(1.0f, 1.0f, 1.0f, 1.0f), pixel.z(), pixel.w());
5980 }
5981 }
5982
5983 class RenderFragmentUniformBuffer : public RenderPassCommand
5984 {
5985 public:
RenderFragmentUniformBuffer(void)5986 RenderFragmentUniformBuffer (void) {}
5987 ~RenderFragmentUniformBuffer (void);
5988
getName(void) const5989 const char* getName (void) const { return "RenderFragmentUniformBuffer"; }
5990 void logPrepare (TestLog&, size_t) const;
5991 void logSubmit (TestLog&, size_t) const;
5992 void prepare (PrepareRenderPassContext&);
5993 void submit (SubmitContext& context);
5994 void verify (VerifyRenderPassContext&, size_t);
5995
5996 protected:
5997
5998 deUint32 calculateBufferPartSize (size_t descriptorSetNdx) const;
5999
6000 private:
6001 PipelineResources m_resources;
6002 vk::Move<vk::VkDescriptorPool> m_descriptorPool;
6003 vector<vk::VkDescriptorSet> m_descriptorSets;
6004
6005 vk::VkDeviceSize m_bufferSize;
6006 size_t m_targetWidth;
6007 size_t m_targetHeight;
6008 deUint32 m_valuesPerPixel;
6009 };
6010
~RenderFragmentUniformBuffer(void)6011 RenderFragmentUniformBuffer::~RenderFragmentUniformBuffer (void)
6012 {
6013 }
6014
logPrepare(TestLog & log,size_t commandIndex) const6015 void RenderFragmentUniformBuffer::logPrepare (TestLog& log, size_t commandIndex) const
6016 {
6017 log << TestLog::Message << commandIndex << ":" << getName() << " Create pipeline for render buffer as uniform buffer." << TestLog::EndMessage;
6018 }
6019
logSubmit(TestLog & log,size_t commandIndex) const6020 void RenderFragmentUniformBuffer::logSubmit (TestLog& log, size_t commandIndex) const
6021 {
6022 log << TestLog::Message << commandIndex << ":" << getName() << " Render using buffer as uniform buffer." << TestLog::EndMessage;
6023 }
6024
prepare(PrepareRenderPassContext & context)6025 void RenderFragmentUniformBuffer::prepare (PrepareRenderPassContext& context)
6026 {
6027 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
6028 const vk::VkDevice device = context.getContext().getDevice();
6029 const vk::VkRenderPass renderPass = context.getRenderPass();
6030 const deUint32 subpass = 0;
6031 const vk::Unique<vk::VkShaderModule> vertexShaderModule (vk::createShaderModule(vkd, device, context.getBinaryCollection().get("render-quad.vert"), 0));
6032 const vk::Unique<vk::VkShaderModule> fragmentShaderModule (vk::createShaderModule(vkd, device, context.getBinaryCollection().get("uniform-buffer.frag"), 0));
6033 vector<vk::VkDescriptorSetLayoutBinding> bindings;
6034
6035 // make sure buffer is smaller then MAX_SIZE and is multiple of 16 (in glsl we use uvec4 to store 16 values)
6036 m_bufferSize = de::min(context.getBufferSize(), (vk::VkDeviceSize)MAX_SIZE);
6037 m_bufferSize = static_cast<vk::VkDeviceSize>(m_bufferSize / 16u) * 16u;
6038 m_targetWidth = context.getTargetWidth();
6039 m_targetHeight = context.getTargetHeight();
6040
6041 {
6042 const vk::VkDescriptorSetLayoutBinding binding =
6043 {
6044 0u,
6045 vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
6046 1,
6047 vk::VK_SHADER_STAGE_FRAGMENT_BIT,
6048 DE_NULL
6049 };
6050
6051 bindings.push_back(binding);
6052 }
6053 const vk::VkPushConstantRange pushConstantRange =
6054 {
6055 vk::VK_SHADER_STAGE_FRAGMENT_BIT,
6056 0u,
6057 12u
6058 };
6059
6060 createPipelineWithResources(vkd, device, renderPass, subpass, *vertexShaderModule, *fragmentShaderModule, context.getTargetWidth(), context.getTargetHeight(),
6061 vector<vk::VkVertexInputBindingDescription>(), vector<vk::VkVertexInputAttributeDescription>(), bindings, vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 1u, &pushConstantRange, m_resources);
6062
6063 {
6064 const deUint32 descriptorCount = (deUint32)(divRoundUp(m_bufferSize, (vk::VkDeviceSize)MAX_UNIFORM_BUFFER_SIZE));
6065 const vk::VkDescriptorPoolSize poolSizes =
6066 {
6067 vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
6068 descriptorCount
6069 };
6070 const vk::VkDescriptorPoolCreateInfo createInfo =
6071 {
6072 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
6073 DE_NULL,
6074 vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
6075
6076 descriptorCount,
6077 1u,
6078 &poolSizes,
6079 };
6080
6081 m_descriptorPool = vk::createDescriptorPool(vkd, device, &createInfo);
6082 m_descriptorSets.resize(descriptorCount);
6083
6084 m_valuesPerPixel = (deUint32)divRoundUp<size_t>(descriptorCount * de::min<size_t>((size_t)m_bufferSize / 4, MAX_UNIFORM_BUFFER_SIZE / 4), m_targetWidth * m_targetHeight);
6085 }
6086
6087 for (size_t descriptorSetNdx = 0; descriptorSetNdx < m_descriptorSets.size(); descriptorSetNdx++)
6088 {
6089 const vk::VkDescriptorSetLayout layout = *m_resources.descriptorSetLayout;
6090 const vk::VkDescriptorSetAllocateInfo allocateInfo =
6091 {
6092 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
6093 DE_NULL,
6094
6095 *m_descriptorPool,
6096 1,
6097 &layout
6098 };
6099
6100 m_descriptorSets[descriptorSetNdx] = vk::allocateDescriptorSet(vkd, device, &allocateInfo).disown();
6101
6102 {
6103 const vk::VkDescriptorBufferInfo bufferInfo =
6104 {
6105 context.getBuffer(),
6106 (vk::VkDeviceSize)(descriptorSetNdx * (size_t)MAX_UNIFORM_BUFFER_SIZE),
6107 calculateBufferPartSize(descriptorSetNdx)
6108 };
6109 const vk::VkWriteDescriptorSet write =
6110 {
6111 vk::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
6112 DE_NULL,
6113 m_descriptorSets[descriptorSetNdx],
6114 0u,
6115 0u,
6116 1u,
6117 vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
6118 DE_NULL,
6119 &bufferInfo,
6120 DE_NULL,
6121 };
6122
6123 vkd.updateDescriptorSets(device, 1u, &write, 0u, DE_NULL);
6124 }
6125 }
6126 }
6127
submit(SubmitContext & context)6128 void RenderFragmentUniformBuffer::submit (SubmitContext& context)
6129 {
6130 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
6131 const vk::VkCommandBuffer commandBuffer = context.getCommandBuffer();
6132
6133 vkd.cmdBindPipeline(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_resources.pipeline);
6134
6135 for (size_t descriptorSetNdx = 0; descriptorSetNdx < m_descriptorSets.size(); descriptorSetNdx++)
6136 {
6137 const struct
6138 {
6139 const deUint32 callId;
6140 const deUint32 valuesPerPixel;
6141 const deUint32 bufferSize;
6142 } callParams =
6143 {
6144 (deUint32)descriptorSetNdx,
6145 m_valuesPerPixel,
6146 calculateBufferPartSize(descriptorSetNdx) / 16u
6147 };
6148
6149 vkd.cmdBindDescriptorSets(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_resources.pipelineLayout, 0u, 1u, &m_descriptorSets[descriptorSetNdx], 0u, DE_NULL);
6150 vkd.cmdPushConstants(commandBuffer, *m_resources.pipelineLayout, vk::VK_SHADER_STAGE_FRAGMENT_BIT, 0u, (deUint32)sizeof(callParams), &callParams);
6151 vkd.cmdDraw(commandBuffer, 6, 1, 0, 0);
6152 }
6153 }
6154
verify(VerifyRenderPassContext & context,size_t)6155 void RenderFragmentUniformBuffer::verify (VerifyRenderPassContext& context, size_t)
6156 {
6157 const size_t arrayIntSize = MAX_UNIFORM_BUFFER_SIZE / sizeof(deUint32);
6158
6159 for (int y = 0; y < context.getReferenceTarget().getSize().y(); y++)
6160 for (int x = 0; x < context.getReferenceTarget().getSize().x(); x++)
6161 {
6162 const deUint32 id = (deUint32)y * 256u + (deUint32)x;
6163 const size_t firstDescriptorSetNdx = de::min<size_t>(id / (arrayIntSize / m_valuesPerPixel), m_descriptorSets.size() - 1);
6164
6165 for (size_t descriptorSetNdx = firstDescriptorSetNdx; descriptorSetNdx < m_descriptorSets.size(); descriptorSetNdx++)
6166 {
6167 const size_t offset = descriptorSetNdx * MAX_UNIFORM_BUFFER_SIZE;
6168 const deUint32 callId = (deUint32)descriptorSetNdx;
6169 const deUint32 count = calculateBufferPartSize(descriptorSetNdx) / 16u;
6170
6171 if (id < callId * (arrayIntSize / m_valuesPerPixel))
6172 continue;
6173 else
6174 {
6175 deUint32 value = id;
6176
6177 for (deUint32 i = 0; i < m_valuesPerPixel; i++)
6178 {
6179 // in shader UBO has up to 64 items of uvec4, each uvec4 contains 16 values
6180 size_t index = offset + size_t((value % count) * 16u) + size_t((value % 4u) * 4u);
6181 value = (((deUint32)context.getReference().get(index + 0)))
6182 | (((deUint32)context.getReference().get(index + 1)) << 8u)
6183 | (((deUint32)context.getReference().get(index + 2)) << 16u)
6184 | (((deUint32)context.getReference().get(index + 3)) << 24u);
6185 }
6186 const UVec4 vec ((value >> 0u) & 0xFFu,
6187 (value >> 8u) & 0xFFu,
6188 (value >> 16u) & 0xFFu,
6189 (value >> 24u) & 0xFFu);
6190
6191 context.getReferenceTarget().getAccess().setPixel(vec.asFloat() / Vec4(255.0f), x, y);
6192 }
6193 }
6194 }
6195 }
6196
calculateBufferPartSize(size_t descriptorSetNdx) const6197 deUint32 RenderFragmentUniformBuffer::calculateBufferPartSize(size_t descriptorSetNdx) const
6198 {
6199 deUint32 size = static_cast<deUint32>(m_bufferSize) - static_cast<deUint32>(descriptorSetNdx) * MAX_UNIFORM_BUFFER_SIZE;
6200 if (size < MAX_UNIFORM_BUFFER_SIZE)
6201 return size;
6202 return MAX_UNIFORM_BUFFER_SIZE;
6203 }
6204
6205 class RenderFragmentStorageBuffer : public RenderPassCommand
6206 {
6207 public:
RenderFragmentStorageBuffer(void)6208 RenderFragmentStorageBuffer (void) {}
6209 ~RenderFragmentStorageBuffer (void);
6210
getName(void) const6211 const char* getName (void) const { return "RenderFragmentStorageBuffer"; }
6212 void logPrepare (TestLog&, size_t) const;
6213 void logSubmit (TestLog&, size_t) const;
6214 void prepare (PrepareRenderPassContext&);
6215 void submit (SubmitContext& context);
6216 void verify (VerifyRenderPassContext&, size_t);
6217
6218 private:
6219 PipelineResources m_resources;
6220 vk::Move<vk::VkDescriptorPool> m_descriptorPool;
6221 vk::Move<vk::VkDescriptorSet> m_descriptorSet;
6222
6223 vk::VkDeviceSize m_bufferSize;
6224 size_t m_targetWidth;
6225 size_t m_targetHeight;
6226 };
6227
~RenderFragmentStorageBuffer(void)6228 RenderFragmentStorageBuffer::~RenderFragmentStorageBuffer (void)
6229 {
6230 }
6231
logPrepare(TestLog & log,size_t commandIndex) const6232 void RenderFragmentStorageBuffer::logPrepare (TestLog& log, size_t commandIndex) const
6233 {
6234 log << TestLog::Message << commandIndex << ":" << getName() << " Create pipeline to render buffer as storage buffer." << TestLog::EndMessage;
6235 }
6236
logSubmit(TestLog & log,size_t commandIndex) const6237 void RenderFragmentStorageBuffer::logSubmit (TestLog& log, size_t commandIndex) const
6238 {
6239 log << TestLog::Message << commandIndex << ":" << getName() << " Render using buffer as storage buffer." << TestLog::EndMessage;
6240 }
6241
prepare(PrepareRenderPassContext & context)6242 void RenderFragmentStorageBuffer::prepare (PrepareRenderPassContext& context)
6243 {
6244 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
6245 const vk::VkDevice device = context.getContext().getDevice();
6246 const vk::VkRenderPass renderPass = context.getRenderPass();
6247 const deUint32 subpass = 0;
6248 const vk::Unique<vk::VkShaderModule> vertexShaderModule (vk::createShaderModule(vkd, device, context.getBinaryCollection().get("render-quad.vert"), 0));
6249 const vk::Unique<vk::VkShaderModule> fragmentShaderModule (vk::createShaderModule(vkd, device, context.getBinaryCollection().get("storage-buffer.frag"), 0));
6250 vector<vk::VkDescriptorSetLayoutBinding> bindings;
6251
6252 // make sure buffer size is multiple of 16 (in glsl we use uvec4 to store 16 values)
6253 m_bufferSize = context.getBufferSize();
6254 m_bufferSize = static_cast<vk::VkDeviceSize>(m_bufferSize / 16u) * 16u;
6255 m_targetWidth = context.getTargetWidth();
6256 m_targetHeight = context.getTargetHeight();
6257
6258 {
6259 const vk::VkDescriptorSetLayoutBinding binding =
6260 {
6261 0u,
6262 vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
6263 1,
6264 vk::VK_SHADER_STAGE_FRAGMENT_BIT,
6265 DE_NULL
6266 };
6267
6268 bindings.push_back(binding);
6269 }
6270 const vk::VkPushConstantRange pushConstantRange =
6271 {
6272 vk::VK_SHADER_STAGE_FRAGMENT_BIT,
6273 0u,
6274 12u
6275 };
6276
6277 createPipelineWithResources(vkd, device, renderPass, subpass, *vertexShaderModule, *fragmentShaderModule, context.getTargetWidth(), context.getTargetHeight(),
6278 vector<vk::VkVertexInputBindingDescription>(), vector<vk::VkVertexInputAttributeDescription>(), bindings, vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 1u, &pushConstantRange, m_resources);
6279
6280 {
6281 const deUint32 descriptorCount = 1;
6282 const vk::VkDescriptorPoolSize poolSizes =
6283 {
6284 vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
6285 descriptorCount
6286 };
6287 const vk::VkDescriptorPoolCreateInfo createInfo =
6288 {
6289 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
6290 DE_NULL,
6291 vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
6292
6293 descriptorCount,
6294 1u,
6295 &poolSizes,
6296 };
6297
6298 m_descriptorPool = vk::createDescriptorPool(vkd, device, &createInfo);
6299 }
6300
6301 {
6302 const vk::VkDescriptorSetLayout layout = *m_resources.descriptorSetLayout;
6303 const vk::VkDescriptorSetAllocateInfo allocateInfo =
6304 {
6305 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
6306 DE_NULL,
6307
6308 *m_descriptorPool,
6309 1,
6310 &layout
6311 };
6312
6313 m_descriptorSet = vk::allocateDescriptorSet(vkd, device, &allocateInfo);
6314
6315 {
6316 const vk::VkDescriptorBufferInfo bufferInfo =
6317 {
6318 context.getBuffer(),
6319 0u,
6320 m_bufferSize
6321 };
6322 const vk::VkWriteDescriptorSet write =
6323 {
6324 vk::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
6325 DE_NULL,
6326 m_descriptorSet.get(),
6327 0u,
6328 0u,
6329 1u,
6330 vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
6331 DE_NULL,
6332 &bufferInfo,
6333 DE_NULL,
6334 };
6335
6336 vkd.updateDescriptorSets(device, 1u, &write, 0u, DE_NULL);
6337 }
6338 }
6339 }
6340
submit(SubmitContext & context)6341 void RenderFragmentStorageBuffer::submit (SubmitContext& context)
6342 {
6343 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
6344 const vk::VkCommandBuffer commandBuffer = context.getCommandBuffer();
6345
6346 vkd.cmdBindPipeline(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_resources.pipeline);
6347
6348 const struct
6349 {
6350 const deUint32 valuesPerPixel;
6351 const deUint32 bufferSize;
6352 } callParams =
6353 {
6354 (deUint32)divRoundUp<vk::VkDeviceSize>(m_bufferSize / 4, m_targetWidth * m_targetHeight),
6355 (deUint32)m_bufferSize
6356 };
6357
6358 vkd.cmdBindDescriptorSets(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_resources.pipelineLayout, 0u, 1u, &m_descriptorSet.get(), 0u, DE_NULL);
6359 vkd.cmdPushConstants(commandBuffer, *m_resources.pipelineLayout, vk::VK_SHADER_STAGE_FRAGMENT_BIT, 0u, (deUint32)sizeof(callParams), &callParams);
6360 vkd.cmdDraw(commandBuffer, 6, 1, 0, 0);
6361 }
6362
verify(VerifyRenderPassContext & context,size_t)6363 void RenderFragmentStorageBuffer::verify (VerifyRenderPassContext& context, size_t)
6364 {
6365 const deUint32 valuesPerPixel = (deUint32)divRoundUp<vk::VkDeviceSize>(m_bufferSize / 4, m_targetWidth * m_targetHeight);
6366
6367 for (int y = 0; y < context.getReferenceTarget().getSize().y(); y++)
6368 for (int x = 0; x < context.getReferenceTarget().getSize().x(); x++)
6369 {
6370 const deUint32 id = (deUint32)y * 256u + (deUint32)x;
6371
6372 deUint32 value = id;
6373
6374 for (deUint32 i = 0; i < valuesPerPixel; i++)
6375 {
6376 value = (((deUint32)context.getReference().get((size_t)(value % (m_bufferSize / sizeof(deUint32))) * 4 + 0)) << 0u)
6377 | (((deUint32)context.getReference().get((size_t)(value % (m_bufferSize / sizeof(deUint32))) * 4 + 1)) << 8u)
6378 | (((deUint32)context.getReference().get((size_t)(value % (m_bufferSize / sizeof(deUint32))) * 4 + 2)) << 16u)
6379 | (((deUint32)context.getReference().get((size_t)(value % (m_bufferSize / sizeof(deUint32))) * 4 + 3)) << 24u);
6380
6381 }
6382 const UVec4 vec ((value >> 0u) & 0xFFu,
6383 (value >> 8u) & 0xFFu,
6384 (value >> 16u) & 0xFFu,
6385 (value >> 24u) & 0xFFu);
6386
6387 context.getReferenceTarget().getAccess().setPixel(vec.asFloat() / Vec4(255.0f), x, y);
6388 }
6389 }
6390
6391 class RenderFragmentUniformTexelBuffer : public RenderPassCommand
6392 {
6393 public:
RenderFragmentUniformTexelBuffer(void)6394 RenderFragmentUniformTexelBuffer (void) {}
6395 ~RenderFragmentUniformTexelBuffer (void);
6396
getName(void) const6397 const char* getName (void) const { return "RenderFragmentUniformTexelBuffer"; }
6398 void logPrepare (TestLog&, size_t) const;
6399 void logSubmit (TestLog&, size_t) const;
6400 void prepare (PrepareRenderPassContext&);
6401 void submit (SubmitContext& context);
6402 void verify (VerifyRenderPassContext&, size_t);
6403
6404 private:
6405 PipelineResources m_resources;
6406 vk::Move<vk::VkDescriptorPool> m_descriptorPool;
6407 vector<vk::VkDescriptorSet> m_descriptorSets;
6408 vector<vk::VkBufferView> m_bufferViews;
6409
6410 const vk::DeviceInterface* m_vkd;
6411 vk::VkDevice m_device;
6412 vk::VkDeviceSize m_bufferSize;
6413 deUint32 m_maxUniformTexelCount;
6414 size_t m_targetWidth;
6415 size_t m_targetHeight;
6416 };
6417
~RenderFragmentUniformTexelBuffer(void)6418 RenderFragmentUniformTexelBuffer::~RenderFragmentUniformTexelBuffer (void)
6419 {
6420 for (size_t bufferViewNdx = 0; bufferViewNdx < m_bufferViews.size(); bufferViewNdx++)
6421 {
6422 if (!!m_bufferViews[bufferViewNdx])
6423 {
6424 m_vkd->destroyBufferView(m_device, m_bufferViews[bufferViewNdx], DE_NULL);
6425 m_bufferViews[bufferViewNdx] = (vk::VkBufferView)0;
6426 }
6427 }
6428 }
6429
logPrepare(TestLog & log,size_t commandIndex) const6430 void RenderFragmentUniformTexelBuffer::logPrepare (TestLog& log, size_t commandIndex) const
6431 {
6432 log << TestLog::Message << commandIndex << ":" << getName() << " Create pipeline for render buffer as uniform buffer." << TestLog::EndMessage;
6433 }
6434
logSubmit(TestLog & log,size_t commandIndex) const6435 void RenderFragmentUniformTexelBuffer::logSubmit (TestLog& log, size_t commandIndex) const
6436 {
6437 log << TestLog::Message << commandIndex << ":" << getName() << " Render using buffer as uniform buffer." << TestLog::EndMessage;
6438 }
6439
prepare(PrepareRenderPassContext & context)6440 void RenderFragmentUniformTexelBuffer::prepare (PrepareRenderPassContext& context)
6441 {
6442 const vk::InstanceInterface& vki = context.getContext().getInstanceInterface();
6443 const vk::VkPhysicalDevice physicalDevice = context.getContext().getPhysicalDevice();
6444 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
6445 const vk::VkDevice device = context.getContext().getDevice();
6446 const vk::VkRenderPass renderPass = context.getRenderPass();
6447 const deUint32 subpass = 0;
6448 const vk::Unique<vk::VkShaderModule> vertexShaderModule (vk::createShaderModule(vkd, device, context.getBinaryCollection().get("render-quad.vert"), 0));
6449 const vk::Unique<vk::VkShaderModule> fragmentShaderModule (vk::createShaderModule(vkd, device, context.getBinaryCollection().get("uniform-texel-buffer.frag"), 0));
6450 vector<vk::VkDescriptorSetLayoutBinding> bindings;
6451
6452 m_device = device;
6453 m_vkd = &vkd;
6454 m_bufferSize = context.getBufferSize();
6455 m_maxUniformTexelCount = vk::getPhysicalDeviceProperties(vki, physicalDevice).limits.maxTexelBufferElements;
6456 m_targetWidth = context.getTargetWidth();
6457 m_targetHeight = context.getTargetHeight();
6458
6459 {
6460 const vk::VkDescriptorSetLayoutBinding binding =
6461 {
6462 0u,
6463 vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
6464 1,
6465 vk::VK_SHADER_STAGE_FRAGMENT_BIT,
6466 DE_NULL
6467 };
6468
6469 bindings.push_back(binding);
6470 }
6471 const vk::VkPushConstantRange pushConstantRange =
6472 {
6473 vk::VK_SHADER_STAGE_FRAGMENT_BIT,
6474 0u,
6475 12u
6476 };
6477
6478 createPipelineWithResources(vkd, device, renderPass, subpass, *vertexShaderModule, *fragmentShaderModule, context.getTargetWidth(), context.getTargetHeight(),
6479 vector<vk::VkVertexInputBindingDescription>(), vector<vk::VkVertexInputAttributeDescription>(), bindings, vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 1u, &pushConstantRange, m_resources);
6480
6481 {
6482 const deUint32 descriptorCount = (deUint32)(divRoundUp(m_bufferSize, (vk::VkDeviceSize)m_maxUniformTexelCount * 4));
6483 const vk::VkDescriptorPoolSize poolSizes =
6484 {
6485 vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
6486 descriptorCount
6487 };
6488 const vk::VkDescriptorPoolCreateInfo createInfo =
6489 {
6490 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
6491 DE_NULL,
6492 vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
6493
6494 descriptorCount,
6495 1u,
6496 &poolSizes,
6497 };
6498
6499 m_descriptorPool = vk::createDescriptorPool(vkd, device, &createInfo);
6500 m_descriptorSets.resize(descriptorCount, (vk::VkDescriptorSet)0);
6501 m_bufferViews.resize(descriptorCount, (vk::VkBufferView)0);
6502 }
6503
6504 for (size_t descriptorSetNdx = 0; descriptorSetNdx < m_descriptorSets.size(); descriptorSetNdx++)
6505 {
6506 const deUint32 count = (deUint32)(m_bufferSize < (descriptorSetNdx + 1) * m_maxUniformTexelCount * 4
6507 ? m_bufferSize - descriptorSetNdx * m_maxUniformTexelCount * 4
6508 : m_maxUniformTexelCount * 4) / 4;
6509 const vk::VkDescriptorSetLayout layout = *m_resources.descriptorSetLayout;
6510 const vk::VkDescriptorSetAllocateInfo allocateInfo =
6511 {
6512 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
6513 DE_NULL,
6514
6515 *m_descriptorPool,
6516 1,
6517 &layout
6518 };
6519
6520 m_descriptorSets[descriptorSetNdx] = vk::allocateDescriptorSet(vkd, device, &allocateInfo).disown();
6521
6522 {
6523 const vk::VkBufferViewCreateInfo createInfo =
6524 {
6525 vk::VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,
6526 DE_NULL,
6527 0u,
6528
6529 context.getBuffer(),
6530 vk::VK_FORMAT_R32_UINT,
6531 descriptorSetNdx * m_maxUniformTexelCount * 4,
6532 count * 4
6533 };
6534
6535 VK_CHECK(vkd.createBufferView(device, &createInfo, DE_NULL, &m_bufferViews[descriptorSetNdx]));
6536 }
6537
6538 {
6539 const vk::VkWriteDescriptorSet write =
6540 {
6541 vk::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
6542 DE_NULL,
6543 m_descriptorSets[descriptorSetNdx],
6544 0u,
6545 0u,
6546 1u,
6547 vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
6548 DE_NULL,
6549 DE_NULL,
6550 &m_bufferViews[descriptorSetNdx]
6551 };
6552
6553 vkd.updateDescriptorSets(device, 1u, &write, 0u, DE_NULL);
6554 }
6555 }
6556 }
6557
submit(SubmitContext & context)6558 void RenderFragmentUniformTexelBuffer::submit (SubmitContext& context)
6559 {
6560 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
6561 const vk::VkCommandBuffer commandBuffer = context.getCommandBuffer();
6562
6563 vkd.cmdBindPipeline(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_resources.pipeline);
6564
6565 for (size_t descriptorSetNdx = 0; descriptorSetNdx < m_descriptorSets.size(); descriptorSetNdx++)
6566 {
6567 const struct
6568 {
6569 const deUint32 callId;
6570 const deUint32 valuesPerPixel;
6571 const deUint32 maxUniformTexelCount;
6572 } callParams =
6573 {
6574 (deUint32)descriptorSetNdx,
6575 (deUint32)divRoundUp<size_t>(m_descriptorSets.size() * de::min<size_t>((size_t)m_bufferSize / 4, m_maxUniformTexelCount), m_targetWidth * m_targetHeight),
6576 m_maxUniformTexelCount
6577 };
6578
6579 vkd.cmdBindDescriptorSets(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_resources.pipelineLayout, 0u, 1u, &m_descriptorSets[descriptorSetNdx], 0u, DE_NULL);
6580 vkd.cmdPushConstants(commandBuffer, *m_resources.pipelineLayout, vk::VK_SHADER_STAGE_FRAGMENT_BIT, 0u, (deUint32)sizeof(callParams), &callParams);
6581 vkd.cmdDraw(commandBuffer, 6, 1, 0, 0);
6582 }
6583 }
6584
verify(VerifyRenderPassContext & context,size_t)6585 void RenderFragmentUniformTexelBuffer::verify (VerifyRenderPassContext& context, size_t)
6586 {
6587 const deUint32 valuesPerPixel = (deUint32)divRoundUp<size_t>(m_descriptorSets.size() * de::min<size_t>((size_t)m_bufferSize / 4, m_maxUniformTexelCount), m_targetWidth * m_targetHeight);
6588
6589 for (int y = 0; y < context.getReferenceTarget().getSize().y(); y++)
6590 for (int x = 0; x < context.getReferenceTarget().getSize().x(); x++)
6591 {
6592 const size_t firstDescriptorSetNdx = de::min<size_t>((y * 256u + x) / (m_maxUniformTexelCount / valuesPerPixel), m_descriptorSets.size() - 1);
6593
6594 for (size_t descriptorSetNdx = firstDescriptorSetNdx; descriptorSetNdx < m_descriptorSets.size(); descriptorSetNdx++)
6595 {
6596 const size_t offset = descriptorSetNdx * m_maxUniformTexelCount * 4;
6597 const deUint32 callId = (deUint32)descriptorSetNdx;
6598
6599 const deUint32 id = (deUint32)y * 256u + (deUint32)x;
6600 const deUint32 count = (deUint32)(m_bufferSize < (descriptorSetNdx + 1) * m_maxUniformTexelCount * 4
6601 ? m_bufferSize - descriptorSetNdx * m_maxUniformTexelCount * 4
6602 : m_maxUniformTexelCount * 4) / 4;
6603
6604 if (y * 256u + x < callId * (m_maxUniformTexelCount / valuesPerPixel))
6605 continue;
6606 else
6607 {
6608 deUint32 value = id;
6609
6610 for (deUint32 i = 0; i < valuesPerPixel; i++)
6611 {
6612 value = ((deUint32)context.getReference().get(offset + (value % count) * 4 + 0))
6613 | (((deUint32)context.getReference().get(offset + (value % count) * 4 + 1)) << 8u)
6614 | (((deUint32)context.getReference().get(offset + (value % count) * 4 + 2)) << 16u)
6615 | (((deUint32)context.getReference().get(offset + (value % count) * 4 + 3)) << 24u);
6616
6617 }
6618 const UVec4 vec ((value >> 0u) & 0xFFu,
6619 (value >> 8u) & 0xFFu,
6620 (value >> 16u) & 0xFFu,
6621 (value >> 24u) & 0xFFu);
6622
6623 context.getReferenceTarget().getAccess().setPixel(vec.asFloat() / Vec4(255.0f), x, y);
6624 }
6625 }
6626 }
6627 }
6628
6629 class RenderFragmentStorageTexelBuffer : public RenderPassCommand
6630 {
6631 public:
RenderFragmentStorageTexelBuffer(void)6632 RenderFragmentStorageTexelBuffer (void) {}
6633 ~RenderFragmentStorageTexelBuffer (void);
6634
getName(void) const6635 const char* getName (void) const { return "RenderFragmentStorageTexelBuffer"; }
6636 void logPrepare (TestLog&, size_t) const;
6637 void logSubmit (TestLog&, size_t) const;
6638 void prepare (PrepareRenderPassContext&);
6639 void submit (SubmitContext& context);
6640 void verify (VerifyRenderPassContext&, size_t);
6641
6642 private:
6643 PipelineResources m_resources;
6644 vk::Move<vk::VkDescriptorPool> m_descriptorPool;
6645 vector<vk::VkDescriptorSet> m_descriptorSets;
6646 vector<vk::VkBufferView> m_bufferViews;
6647
6648 const vk::DeviceInterface* m_vkd;
6649 vk::VkDevice m_device;
6650 vk::VkDeviceSize m_bufferSize;
6651 deUint32 m_maxStorageTexelCount;
6652 size_t m_targetWidth;
6653 size_t m_targetHeight;
6654 };
6655
~RenderFragmentStorageTexelBuffer(void)6656 RenderFragmentStorageTexelBuffer::~RenderFragmentStorageTexelBuffer (void)
6657 {
6658 for (size_t bufferViewNdx = 0; bufferViewNdx < m_bufferViews.size(); bufferViewNdx++)
6659 {
6660 if (!!m_bufferViews[bufferViewNdx])
6661 {
6662 m_vkd->destroyBufferView(m_device, m_bufferViews[bufferViewNdx], DE_NULL);
6663 m_bufferViews[bufferViewNdx] = (vk::VkBufferView)0;
6664 }
6665 }
6666 }
6667
logPrepare(TestLog & log,size_t commandIndex) const6668 void RenderFragmentStorageTexelBuffer::logPrepare (TestLog& log, size_t commandIndex) const
6669 {
6670 log << TestLog::Message << commandIndex << ":" << getName() << " Create pipeline for render buffer as storage buffer." << TestLog::EndMessage;
6671 }
6672
logSubmit(TestLog & log,size_t commandIndex) const6673 void RenderFragmentStorageTexelBuffer::logSubmit (TestLog& log, size_t commandIndex) const
6674 {
6675 log << TestLog::Message << commandIndex << ":" << getName() << " Render using buffer as storage buffer." << TestLog::EndMessage;
6676 }
6677
prepare(PrepareRenderPassContext & context)6678 void RenderFragmentStorageTexelBuffer::prepare (PrepareRenderPassContext& context)
6679 {
6680 const vk::InstanceInterface& vki = context.getContext().getInstanceInterface();
6681 const vk::VkPhysicalDevice physicalDevice = context.getContext().getPhysicalDevice();
6682 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
6683 const vk::VkDevice device = context.getContext().getDevice();
6684 const vk::VkRenderPass renderPass = context.getRenderPass();
6685 const deUint32 subpass = 0;
6686 const vk::Unique<vk::VkShaderModule> vertexShaderModule (vk::createShaderModule(vkd, device, context.getBinaryCollection().get("render-quad.vert"), 0));
6687 const vk::Unique<vk::VkShaderModule> fragmentShaderModule (vk::createShaderModule(vkd, device, context.getBinaryCollection().get("storage-texel-buffer.frag"), 0));
6688 vector<vk::VkDescriptorSetLayoutBinding> bindings;
6689
6690 m_device = device;
6691 m_vkd = &vkd;
6692 m_bufferSize = context.getBufferSize();
6693 m_maxStorageTexelCount = vk::getPhysicalDeviceProperties(vki, physicalDevice).limits.maxTexelBufferElements;
6694 m_targetWidth = context.getTargetWidth();
6695 m_targetHeight = context.getTargetHeight();
6696
6697 {
6698 const vk::VkDescriptorSetLayoutBinding binding =
6699 {
6700 0u,
6701 vk::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
6702 1,
6703 vk::VK_SHADER_STAGE_FRAGMENT_BIT,
6704 DE_NULL
6705 };
6706
6707 bindings.push_back(binding);
6708 }
6709 const vk::VkPushConstantRange pushConstantRange =
6710 {
6711 vk::VK_SHADER_STAGE_FRAGMENT_BIT,
6712 0u,
6713 16u
6714 };
6715
6716 createPipelineWithResources(vkd, device, renderPass, subpass, *vertexShaderModule, *fragmentShaderModule, context.getTargetWidth(), context.getTargetHeight(),
6717 vector<vk::VkVertexInputBindingDescription>(), vector<vk::VkVertexInputAttributeDescription>(), bindings, vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 1u, &pushConstantRange, m_resources);
6718
6719 {
6720 const deUint32 descriptorCount = (deUint32)(divRoundUp(m_bufferSize, (vk::VkDeviceSize)m_maxStorageTexelCount * 4));
6721 const vk::VkDescriptorPoolSize poolSizes =
6722 {
6723 vk::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
6724 descriptorCount
6725 };
6726 const vk::VkDescriptorPoolCreateInfo createInfo =
6727 {
6728 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
6729 DE_NULL,
6730 vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
6731
6732 descriptorCount,
6733 1u,
6734 &poolSizes,
6735 };
6736
6737 m_descriptorPool = vk::createDescriptorPool(vkd, device, &createInfo);
6738 m_descriptorSets.resize(descriptorCount, (vk::VkDescriptorSet)0);
6739 m_bufferViews.resize(descriptorCount, (vk::VkBufferView)0);
6740 }
6741
6742 for (size_t descriptorSetNdx = 0; descriptorSetNdx < m_descriptorSets.size(); descriptorSetNdx++)
6743 {
6744 const deUint32 count = (deUint32)(m_bufferSize < (descriptorSetNdx + 1) * m_maxStorageTexelCount * 4
6745 ? m_bufferSize - descriptorSetNdx * m_maxStorageTexelCount * 4
6746 : m_maxStorageTexelCount * 4) / 4;
6747 const vk::VkDescriptorSetLayout layout = *m_resources.descriptorSetLayout;
6748 const vk::VkDescriptorSetAllocateInfo allocateInfo =
6749 {
6750 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
6751 DE_NULL,
6752
6753 *m_descriptorPool,
6754 1,
6755 &layout
6756 };
6757
6758 m_descriptorSets[descriptorSetNdx] = vk::allocateDescriptorSet(vkd, device, &allocateInfo).disown();
6759
6760 {
6761 const vk::VkBufferViewCreateInfo createInfo =
6762 {
6763 vk::VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,
6764 DE_NULL,
6765 0u,
6766
6767 context.getBuffer(),
6768 vk::VK_FORMAT_R32_UINT,
6769 descriptorSetNdx * m_maxStorageTexelCount * 4,
6770 count * 4
6771 };
6772
6773 VK_CHECK(vkd.createBufferView(device, &createInfo, DE_NULL, &m_bufferViews[descriptorSetNdx]));
6774 }
6775
6776 {
6777 const vk::VkWriteDescriptorSet write =
6778 {
6779 vk::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
6780 DE_NULL,
6781 m_descriptorSets[descriptorSetNdx],
6782 0u,
6783 0u,
6784 1u,
6785 vk::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
6786 DE_NULL,
6787 DE_NULL,
6788 &m_bufferViews[descriptorSetNdx]
6789 };
6790
6791 vkd.updateDescriptorSets(device, 1u, &write, 0u, DE_NULL);
6792 }
6793 }
6794 }
6795
submit(SubmitContext & context)6796 void RenderFragmentStorageTexelBuffer::submit (SubmitContext& context)
6797 {
6798 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
6799 const vk::VkCommandBuffer commandBuffer = context.getCommandBuffer();
6800
6801 vkd.cmdBindPipeline(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_resources.pipeline);
6802
6803 for (size_t descriptorSetNdx = 0; descriptorSetNdx < m_descriptorSets.size(); descriptorSetNdx++)
6804 {
6805 const struct
6806 {
6807 const deUint32 callId;
6808 const deUint32 valuesPerPixel;
6809 const deUint32 maxStorageTexelCount;
6810 const deUint32 width;
6811 } callParams =
6812 {
6813 (deUint32)descriptorSetNdx,
6814 (deUint32)divRoundUp<size_t>(m_descriptorSets.size() * de::min<size_t>(m_maxStorageTexelCount, (size_t)m_bufferSize / 4), m_targetWidth * m_targetHeight),
6815 m_maxStorageTexelCount,
6816 (deUint32)(m_bufferSize < (descriptorSetNdx + 1u) * m_maxStorageTexelCount * 4u
6817 ? m_bufferSize - descriptorSetNdx * m_maxStorageTexelCount * 4u
6818 : m_maxStorageTexelCount * 4u) / 4u
6819 };
6820
6821 vkd.cmdBindDescriptorSets(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_resources.pipelineLayout, 0u, 1u, &m_descriptorSets[descriptorSetNdx], 0u, DE_NULL);
6822 vkd.cmdPushConstants(commandBuffer, *m_resources.pipelineLayout, vk::VK_SHADER_STAGE_FRAGMENT_BIT, 0u, (deUint32)sizeof(callParams), &callParams);
6823 vkd.cmdDraw(commandBuffer, 6, 1, 0, 0);
6824 }
6825 }
6826
verify(VerifyRenderPassContext & context,size_t)6827 void RenderFragmentStorageTexelBuffer::verify (VerifyRenderPassContext& context, size_t)
6828 {
6829 const deUint32 valuesPerPixel = (deUint32)divRoundUp<size_t>(m_descriptorSets.size() * de::min<size_t>(m_maxStorageTexelCount, (size_t)m_bufferSize / 4), m_targetWidth * m_targetHeight);
6830
6831 for (int y = 0; y < context.getReferenceTarget().getSize().y(); y++)
6832 for (int x = 0; x < context.getReferenceTarget().getSize().x(); x++)
6833 {
6834 const size_t firstDescriptorSetNdx = de::min<size_t>((y * 256u + x) / (m_maxStorageTexelCount / valuesPerPixel), m_descriptorSets.size() - 1);
6835
6836 for (size_t descriptorSetNdx = firstDescriptorSetNdx; descriptorSetNdx < m_descriptorSets.size(); descriptorSetNdx++)
6837 {
6838 const size_t offset = descriptorSetNdx * m_maxStorageTexelCount * 4;
6839 const deUint32 callId = (deUint32)descriptorSetNdx;
6840
6841 const deUint32 id = (deUint32)y * 256u + (deUint32)x;
6842 const deUint32 count = (deUint32)(m_bufferSize < (descriptorSetNdx + 1) * m_maxStorageTexelCount * 4
6843 ? m_bufferSize - descriptorSetNdx * m_maxStorageTexelCount * 4
6844 : m_maxStorageTexelCount * 4) / 4;
6845
6846 if (y * 256u + x < callId * (m_maxStorageTexelCount / valuesPerPixel))
6847 continue;
6848 else
6849 {
6850 deUint32 value = id;
6851
6852 for (deUint32 i = 0; i < valuesPerPixel; i++)
6853 {
6854 value = ((deUint32)context.getReference().get( offset + (value % count) * 4 + 0))
6855 | (((deUint32)context.getReference().get(offset + (value % count) * 4 + 1)) << 8u)
6856 | (((deUint32)context.getReference().get(offset + (value % count) * 4 + 2)) << 16u)
6857 | (((deUint32)context.getReference().get(offset + (value % count) * 4 + 3)) << 24u);
6858
6859 }
6860 const UVec4 vec ((value >> 0u) & 0xFFu,
6861 (value >> 8u) & 0xFFu,
6862 (value >> 16u) & 0xFFu,
6863 (value >> 24u) & 0xFFu);
6864
6865 context.getReferenceTarget().getAccess().setPixel(vec.asFloat() / Vec4(255.0f), x, y);
6866 }
6867 }
6868 }
6869 }
6870
6871 class RenderFragmentStorageImage : public RenderPassCommand
6872 {
6873 public:
RenderFragmentStorageImage(void)6874 RenderFragmentStorageImage (void) {}
6875 ~RenderFragmentStorageImage (void);
6876
getName(void) const6877 const char* getName (void) const { return "RenderFragmentStorageImage"; }
6878 void logPrepare (TestLog&, size_t) const;
6879 void logSubmit (TestLog&, size_t) const;
6880 void prepare (PrepareRenderPassContext&);
6881 void submit (SubmitContext& context);
6882 void verify (VerifyRenderPassContext&, size_t);
6883
6884 private:
6885 PipelineResources m_resources;
6886 vk::Move<vk::VkDescriptorPool> m_descriptorPool;
6887 vk::Move<vk::VkDescriptorSet> m_descriptorSet;
6888 vk::Move<vk::VkImageView> m_imageView;
6889 };
6890
~RenderFragmentStorageImage(void)6891 RenderFragmentStorageImage::~RenderFragmentStorageImage (void)
6892 {
6893 }
6894
logPrepare(TestLog & log,size_t commandIndex) const6895 void RenderFragmentStorageImage::logPrepare (TestLog& log, size_t commandIndex) const
6896 {
6897 log << TestLog::Message << commandIndex << ":" << getName() << " Create pipeline for render storage image." << TestLog::EndMessage;
6898 }
6899
logSubmit(TestLog & log,size_t commandIndex) const6900 void RenderFragmentStorageImage::logSubmit (TestLog& log, size_t commandIndex) const
6901 {
6902 log << TestLog::Message << commandIndex << ":" << getName() << " Render using storage image." << TestLog::EndMessage;
6903 }
6904
prepare(PrepareRenderPassContext & context)6905 void RenderFragmentStorageImage::prepare (PrepareRenderPassContext& context)
6906 {
6907 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
6908 const vk::VkDevice device = context.getContext().getDevice();
6909 const vk::VkRenderPass renderPass = context.getRenderPass();
6910 const deUint32 subpass = 0;
6911 const vk::Unique<vk::VkShaderModule> vertexShaderModule (vk::createShaderModule(vkd, device, context.getBinaryCollection().get("render-quad.vert"), 0));
6912 const vk::Unique<vk::VkShaderModule> fragmentShaderModule (vk::createShaderModule(vkd, device, context.getBinaryCollection().get("storage-image.frag"), 0));
6913 vector<vk::VkDescriptorSetLayoutBinding> bindings;
6914
6915 {
6916 const vk::VkDescriptorSetLayoutBinding binding =
6917 {
6918 0u,
6919 vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
6920 1,
6921 vk::VK_SHADER_STAGE_FRAGMENT_BIT,
6922 DE_NULL
6923 };
6924
6925 bindings.push_back(binding);
6926 }
6927
6928 createPipelineWithResources(vkd, device, renderPass, subpass, *vertexShaderModule, *fragmentShaderModule, context.getTargetWidth(), context.getTargetHeight(),
6929 vector<vk::VkVertexInputBindingDescription>(), vector<vk::VkVertexInputAttributeDescription>(), bindings, vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0u, DE_NULL, m_resources);
6930
6931 {
6932 const vk::VkDescriptorPoolSize poolSizes =
6933 {
6934 vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
6935 1
6936 };
6937 const vk::VkDescriptorPoolCreateInfo createInfo =
6938 {
6939 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
6940 DE_NULL,
6941 vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
6942
6943 1u,
6944 1u,
6945 &poolSizes,
6946 };
6947
6948 m_descriptorPool = vk::createDescriptorPool(vkd, device, &createInfo);
6949 }
6950
6951 {
6952 const vk::VkDescriptorSetLayout layout = *m_resources.descriptorSetLayout;
6953 const vk::VkDescriptorSetAllocateInfo allocateInfo =
6954 {
6955 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
6956 DE_NULL,
6957
6958 *m_descriptorPool,
6959 1,
6960 &layout
6961 };
6962
6963 m_descriptorSet = vk::allocateDescriptorSet(vkd, device, &allocateInfo);
6964
6965 {
6966 const vk::VkImageViewCreateInfo createInfo =
6967 {
6968 vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
6969 DE_NULL,
6970 0u,
6971
6972 context.getImage(),
6973 vk::VK_IMAGE_VIEW_TYPE_2D,
6974 vk::VK_FORMAT_R8G8B8A8_UNORM,
6975 vk::makeComponentMappingRGBA(),
6976 {
6977 vk::VK_IMAGE_ASPECT_COLOR_BIT,
6978 0u,
6979 1u,
6980 0u,
6981 1u
6982 }
6983 };
6984
6985 m_imageView = vk::createImageView(vkd, device, &createInfo);
6986 }
6987
6988 {
6989 const vk::VkDescriptorImageInfo imageInfo =
6990 {
6991 0,
6992 *m_imageView,
6993 context.getImageLayout()
6994 };
6995 const vk::VkWriteDescriptorSet write =
6996 {
6997 vk::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
6998 DE_NULL,
6999 *m_descriptorSet,
7000 0u,
7001 0u,
7002 1u,
7003 vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
7004 &imageInfo,
7005 DE_NULL,
7006 DE_NULL,
7007 };
7008
7009 vkd.updateDescriptorSets(device, 1u, &write, 0u, DE_NULL);
7010 }
7011 }
7012 }
7013
submit(SubmitContext & context)7014 void RenderFragmentStorageImage::submit (SubmitContext& context)
7015 {
7016 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
7017 const vk::VkCommandBuffer commandBuffer = context.getCommandBuffer();
7018
7019 vkd.cmdBindPipeline(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_resources.pipeline);
7020
7021 vkd.cmdBindDescriptorSets(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_resources.pipelineLayout, 0u, 1u, &(*m_descriptorSet), 0u, DE_NULL);
7022 vkd.cmdDraw(commandBuffer, 6, 1, 0, 0);
7023 }
7024
verify(VerifyRenderPassContext & context,size_t)7025 void RenderFragmentStorageImage::verify (VerifyRenderPassContext& context, size_t)
7026 {
7027 const UVec2 size = UVec2(context.getReferenceImage().getWidth(), context.getReferenceImage().getHeight());
7028 const deUint32 valuesPerPixel = de::max<deUint32>(1u, (size.x() * size.y()) / (256u * 256u));
7029
7030 for (int y = 0; y < context.getReferenceTarget().getSize().y(); y++)
7031 for (int x = 0; x < context.getReferenceTarget().getSize().x(); x++)
7032 {
7033 UVec4 value = UVec4(x, y, 0u, 0u);
7034
7035 for (deUint32 i = 0; i < valuesPerPixel; i++)
7036 {
7037 const UVec2 pos = UVec2(value.z() * 256u + (value.x() ^ value.z()), value.w() * 256u + (value.y() ^ value.w()));
7038 const Vec4 floatValue = context.getReferenceImage().getAccess().getPixel(pos.x() % size.x(), pos.y() % size.y());
7039
7040 value = UVec4((deUint32)round(floatValue.x() * 255.0f),
7041 (deUint32)round(floatValue.y() * 255.0f),
7042 (deUint32)round(floatValue.z() * 255.0f),
7043 (deUint32)round(floatValue.w() * 255.0f));
7044
7045 }
7046 context.getReferenceTarget().getAccess().setPixel(value.asFloat() / Vec4(255.0f), x, y);
7047 }
7048 }
7049
7050 class RenderFragmentSampledImage : public RenderPassCommand
7051 {
7052 public:
RenderFragmentSampledImage(void)7053 RenderFragmentSampledImage (void) {}
7054 ~RenderFragmentSampledImage (void);
7055
getName(void) const7056 const char* getName (void) const { return "RenderFragmentSampledImage"; }
7057 void logPrepare (TestLog&, size_t) const;
7058 void logSubmit (TestLog&, size_t) const;
7059 void prepare (PrepareRenderPassContext&);
7060 void submit (SubmitContext& context);
7061 void verify (VerifyRenderPassContext&, size_t);
7062
7063 private:
7064 PipelineResources m_resources;
7065 vk::Move<vk::VkDescriptorPool> m_descriptorPool;
7066 vk::Move<vk::VkDescriptorSet> m_descriptorSet;
7067 vk::Move<vk::VkImageView> m_imageView;
7068 vk::Move<vk::VkSampler> m_sampler;
7069 };
7070
~RenderFragmentSampledImage(void)7071 RenderFragmentSampledImage::~RenderFragmentSampledImage (void)
7072 {
7073 }
7074
logPrepare(TestLog & log,size_t commandIndex) const7075 void RenderFragmentSampledImage::logPrepare (TestLog& log, size_t commandIndex) const
7076 {
7077 log << TestLog::Message << commandIndex << ":" << getName() << " Create pipeline for render storage image." << TestLog::EndMessage;
7078 }
7079
logSubmit(TestLog & log,size_t commandIndex) const7080 void RenderFragmentSampledImage::logSubmit (TestLog& log, size_t commandIndex) const
7081 {
7082 log << TestLog::Message << commandIndex << ":" << getName() << " Render using storage image." << TestLog::EndMessage;
7083 }
7084
prepare(PrepareRenderPassContext & context)7085 void RenderFragmentSampledImage::prepare (PrepareRenderPassContext& context)
7086 {
7087 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
7088 const vk::VkDevice device = context.getContext().getDevice();
7089 const vk::VkRenderPass renderPass = context.getRenderPass();
7090 const deUint32 subpass = 0;
7091 const vk::Unique<vk::VkShaderModule> vertexShaderModule (vk::createShaderModule(vkd, device, context.getBinaryCollection().get("render-quad.vert"), 0));
7092 const vk::Unique<vk::VkShaderModule> fragmentShaderModule (vk::createShaderModule(vkd, device, context.getBinaryCollection().get("sampled-image.frag"), 0));
7093 vector<vk::VkDescriptorSetLayoutBinding> bindings;
7094
7095 {
7096 const vk::VkDescriptorSetLayoutBinding binding =
7097 {
7098 0u,
7099 vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
7100 1,
7101 vk::VK_SHADER_STAGE_FRAGMENT_BIT,
7102 DE_NULL
7103 };
7104
7105 bindings.push_back(binding);
7106 }
7107
7108 createPipelineWithResources(vkd, device, renderPass, subpass, *vertexShaderModule, *fragmentShaderModule, context.getTargetWidth(), context.getTargetHeight(),
7109 vector<vk::VkVertexInputBindingDescription>(), vector<vk::VkVertexInputAttributeDescription>(), bindings, vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0u, DE_NULL, m_resources);
7110
7111 {
7112 const vk::VkDescriptorPoolSize poolSizes =
7113 {
7114 vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
7115 1
7116 };
7117 const vk::VkDescriptorPoolCreateInfo createInfo =
7118 {
7119 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
7120 DE_NULL,
7121 vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
7122
7123 1u,
7124 1u,
7125 &poolSizes,
7126 };
7127
7128 m_descriptorPool = vk::createDescriptorPool(vkd, device, &createInfo);
7129 }
7130
7131 {
7132 const vk::VkDescriptorSetLayout layout = *m_resources.descriptorSetLayout;
7133 const vk::VkDescriptorSetAllocateInfo allocateInfo =
7134 {
7135 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
7136 DE_NULL,
7137
7138 *m_descriptorPool,
7139 1,
7140 &layout
7141 };
7142
7143 m_descriptorSet = vk::allocateDescriptorSet(vkd, device, &allocateInfo);
7144
7145 {
7146 const vk::VkImageViewCreateInfo createInfo =
7147 {
7148 vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
7149 DE_NULL,
7150 0u,
7151
7152 context.getImage(),
7153 vk::VK_IMAGE_VIEW_TYPE_2D,
7154 vk::VK_FORMAT_R8G8B8A8_UNORM,
7155 vk::makeComponentMappingRGBA(),
7156 {
7157 vk::VK_IMAGE_ASPECT_COLOR_BIT,
7158 0u,
7159 1u,
7160 0u,
7161 1u
7162 }
7163 };
7164
7165 m_imageView = vk::createImageView(vkd, device, &createInfo);
7166 }
7167
7168 {
7169 const vk::VkSamplerCreateInfo createInfo =
7170 {
7171 vk::VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
7172 DE_NULL,
7173 0u,
7174
7175 vk::VK_FILTER_NEAREST,
7176 vk::VK_FILTER_NEAREST,
7177
7178 vk::VK_SAMPLER_MIPMAP_MODE_LINEAR,
7179 vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
7180 vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
7181 vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
7182 0.0f,
7183 VK_FALSE,
7184 1.0f,
7185 VK_FALSE,
7186 vk::VK_COMPARE_OP_ALWAYS,
7187 0.0f,
7188 0.0f,
7189 vk::VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,
7190 VK_FALSE
7191 };
7192
7193 m_sampler = vk::createSampler(vkd, device, &createInfo);
7194 }
7195
7196 {
7197 const vk::VkDescriptorImageInfo imageInfo =
7198 {
7199 *m_sampler,
7200 *m_imageView,
7201 context.getImageLayout()
7202 };
7203 const vk::VkWriteDescriptorSet write =
7204 {
7205 vk::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
7206 DE_NULL,
7207 *m_descriptorSet,
7208 0u,
7209 0u,
7210 1u,
7211 vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
7212 &imageInfo,
7213 DE_NULL,
7214 DE_NULL,
7215 };
7216
7217 vkd.updateDescriptorSets(device, 1u, &write, 0u, DE_NULL);
7218 }
7219 }
7220 }
7221
submit(SubmitContext & context)7222 void RenderFragmentSampledImage::submit (SubmitContext& context)
7223 {
7224 const vk::DeviceInterface& vkd = context.getContext().getDeviceInterface();
7225 const vk::VkCommandBuffer commandBuffer = context.getCommandBuffer();
7226
7227 vkd.cmdBindPipeline(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_resources.pipeline);
7228
7229 vkd.cmdBindDescriptorSets(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_resources.pipelineLayout, 0u, 1u, &(*m_descriptorSet), 0u, DE_NULL);
7230 vkd.cmdDraw(commandBuffer, 6u, 1u, 0u, 0u);
7231 }
7232
verify(VerifyRenderPassContext & context,size_t)7233 void RenderFragmentSampledImage::verify (VerifyRenderPassContext& context, size_t)
7234 {
7235 const UVec2 size = UVec2(context.getReferenceImage().getWidth(), context.getReferenceImage().getHeight());
7236 const deUint32 valuesPerPixel = de::max<deUint32>(1u, (size.x() * size.y()) / (256u * 256u));
7237
7238 for (int y = 0; y < context.getReferenceTarget().getSize().y(); y++)
7239 for (int x = 0; x < context.getReferenceTarget().getSize().x(); x++)
7240 {
7241 UVec4 value = UVec4(x, y, 0u, 0u);
7242
7243 for (deUint32 i = 0; i < valuesPerPixel; i++)
7244 {
7245 const UVec2 pos = UVec2(value.z() * 256u + (value.x() ^ value.z()), value.w() * 256u + (value.y() ^ value.w()));
7246 const Vec4 floatValue = context.getReferenceImage().getAccess().getPixel(pos.x() % size.x(), pos.y() % size.y());
7247
7248 value = UVec4((deUint32)round(floatValue.x() * 255.0f),
7249 (deUint32)round(floatValue.y() * 255.0f),
7250 (deUint32)round(floatValue.z() * 255.0f),
7251 (deUint32)round(floatValue.w() * 255.0f));
7252
7253 }
7254
7255 context.getReferenceTarget().getAccess().setPixel(value.asFloat() / Vec4(255.0f), x, y);
7256 }
7257 }
7258
7259 enum Op
7260 {
7261 OP_MAP,
7262 OP_UNMAP,
7263
7264 OP_MAP_FLUSH,
7265 OP_MAP_INVALIDATE,
7266
7267 OP_MAP_READ,
7268 OP_MAP_WRITE,
7269 OP_MAP_MODIFY,
7270
7271 OP_BUFFER_CREATE,
7272 OP_BUFFER_DESTROY,
7273 OP_BUFFER_BINDMEMORY,
7274
7275 OP_QUEUE_WAIT_FOR_IDLE,
7276 OP_DEVICE_WAIT_FOR_IDLE,
7277
7278 OP_COMMAND_BUFFER_BEGIN,
7279 OP_COMMAND_BUFFER_END,
7280
7281 // Secondary, non render pass command buffers
7282 // Render pass secondary command buffers are not currently covered
7283 OP_SECONDARY_COMMAND_BUFFER_BEGIN,
7284 OP_SECONDARY_COMMAND_BUFFER_END,
7285
7286 // Buffer transfer operations
7287 OP_BUFFER_FILL,
7288 OP_BUFFER_UPDATE,
7289
7290 OP_BUFFER_COPY_TO_BUFFER,
7291 OP_BUFFER_COPY_FROM_BUFFER,
7292
7293 OP_BUFFER_COPY_TO_IMAGE,
7294 OP_BUFFER_COPY_FROM_IMAGE,
7295
7296 OP_IMAGE_CREATE,
7297 OP_IMAGE_DESTROY,
7298 OP_IMAGE_BINDMEMORY,
7299
7300 OP_IMAGE_TRANSITION_LAYOUT,
7301
7302 OP_IMAGE_COPY_TO_BUFFER,
7303 OP_IMAGE_COPY_FROM_BUFFER,
7304
7305 OP_IMAGE_COPY_TO_IMAGE,
7306 OP_IMAGE_COPY_FROM_IMAGE,
7307
7308 OP_IMAGE_BLIT_TO_IMAGE,
7309 OP_IMAGE_BLIT_FROM_IMAGE,
7310
7311 OP_IMAGE_RESOLVE,
7312
7313 OP_PIPELINE_BARRIER_GLOBAL,
7314 OP_PIPELINE_BARRIER_BUFFER,
7315 OP_PIPELINE_BARRIER_IMAGE,
7316
7317 // Renderpass operations
7318 OP_RENDERPASS_BEGIN,
7319 OP_RENDERPASS_END,
7320
7321 // Commands inside render pass
7322 OP_RENDER_VERTEX_BUFFER,
7323 OP_RENDER_INDEX_BUFFER,
7324
7325 OP_RENDER_VERTEX_UNIFORM_BUFFER,
7326 OP_RENDER_FRAGMENT_UNIFORM_BUFFER,
7327
7328 OP_RENDER_VERTEX_UNIFORM_TEXEL_BUFFER,
7329 OP_RENDER_FRAGMENT_UNIFORM_TEXEL_BUFFER,
7330
7331 OP_RENDER_VERTEX_STORAGE_BUFFER,
7332 OP_RENDER_FRAGMENT_STORAGE_BUFFER,
7333
7334 OP_RENDER_VERTEX_STORAGE_TEXEL_BUFFER,
7335 OP_RENDER_FRAGMENT_STORAGE_TEXEL_BUFFER,
7336
7337 OP_RENDER_VERTEX_STORAGE_IMAGE,
7338 OP_RENDER_FRAGMENT_STORAGE_IMAGE,
7339
7340 OP_RENDER_VERTEX_SAMPLED_IMAGE,
7341 OP_RENDER_FRAGMENT_SAMPLED_IMAGE,
7342 };
7343
7344 enum Stage
7345 {
7346 STAGE_HOST,
7347 STAGE_COMMAND_BUFFER,
7348 STAGE_SECONDARY_COMMAND_BUFFER,
7349
7350 STAGE_RENDER_PASS
7351 };
7352
getWriteAccessFlags(void)7353 vk::VkAccessFlags getWriteAccessFlags (void)
7354 {
7355 return vk::VK_ACCESS_SHADER_WRITE_BIT
7356 | vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
7357 | vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT
7358 | vk::VK_ACCESS_TRANSFER_WRITE_BIT
7359 | vk::VK_ACCESS_HOST_WRITE_BIT
7360 | vk::VK_ACCESS_MEMORY_WRITE_BIT;
7361 }
7362
isWriteAccess(vk::VkAccessFlagBits access)7363 bool isWriteAccess (vk::VkAccessFlagBits access)
7364 {
7365 return (getWriteAccessFlags() & access) != 0;
7366 }
7367
7368 class CacheState
7369 {
7370 public:
7371 CacheState (vk::VkPipelineStageFlags allowedStages, vk::VkAccessFlags allowedAccesses);
7372
7373 bool isValid (vk::VkPipelineStageFlagBits stage,
7374 vk::VkAccessFlagBits access) const;
7375
7376 void perform (vk::VkPipelineStageFlagBits stage,
7377 vk::VkAccessFlagBits access);
7378
7379 void submitCommandBuffer (void);
7380 void waitForIdle (void);
7381
7382 void getFullBarrier (vk::VkPipelineStageFlags& srcStages,
7383 vk::VkAccessFlags& srcAccesses,
7384 vk::VkPipelineStageFlags& dstStages,
7385 vk::VkAccessFlags& dstAccesses) const;
7386
7387 void barrier (vk::VkPipelineStageFlags srcStages,
7388 vk::VkAccessFlags srcAccesses,
7389 vk::VkPipelineStageFlags dstStages,
7390 vk::VkAccessFlags dstAccesses);
7391
7392 void imageLayoutBarrier (vk::VkPipelineStageFlags srcStages,
7393 vk::VkAccessFlags srcAccesses,
7394 vk::VkPipelineStageFlags dstStages,
7395 vk::VkAccessFlags dstAccesses);
7396
7397 void checkImageLayoutBarrier (vk::VkPipelineStageFlags srcStages,
7398 vk::VkAccessFlags srcAccesses,
7399 vk::VkPipelineStageFlags dstStages,
7400 vk::VkAccessFlags dstAccesses);
7401
7402 // Everything is clean and there is no need for barriers
7403 bool isClean (void) const;
7404
getAllowedStages(void) const7405 vk::VkPipelineStageFlags getAllowedStages (void) const { return m_allowedStages; }
getAllowedAcceses(void) const7406 vk::VkAccessFlags getAllowedAcceses (void) const { return m_allowedAccesses; }
7407 private:
7408 // Limit which stages and accesses are used by the CacheState tracker
7409 const vk::VkPipelineStageFlags m_allowedStages;
7410 const vk::VkAccessFlags m_allowedAccesses;
7411
7412 // [dstStage][srcStage][dstAccess] = srcAccesses
7413 // In stage dstStage write srcAccesses from srcStage are not yet available for dstAccess
7414 vk::VkAccessFlags m_unavailableWriteOperations[PIPELINESTAGE_LAST][PIPELINESTAGE_LAST][ACCESS_LAST];
7415 // Latest pipeline transition is not available in stage
7416 bool m_unavailableLayoutTransition[PIPELINESTAGE_LAST];
7417 // [dstStage] = dstAccesses
7418 // In stage dstStage ops with dstAccesses are not yet visible
7419 vk::VkAccessFlags m_invisibleOperations[PIPELINESTAGE_LAST];
7420
7421 // [dstStage] = srcStage
7422 // Memory operation in srcStage have not completed before dstStage
7423 vk::VkPipelineStageFlags m_incompleteOperations[PIPELINESTAGE_LAST];
7424 };
7425
CacheState(vk::VkPipelineStageFlags allowedStages,vk::VkAccessFlags allowedAccesses)7426 CacheState::CacheState (vk::VkPipelineStageFlags allowedStages, vk::VkAccessFlags allowedAccesses)
7427 : m_allowedStages (allowedStages)
7428 , m_allowedAccesses (allowedAccesses)
7429 {
7430 for (vk::VkPipelineStageFlags dstStage_ = 1; dstStage_ <= m_allowedStages; dstStage_ <<= 1)
7431 {
7432 const PipelineStage dstStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)dstStage_);
7433
7434 if ((dstStage_ & m_allowedStages) == 0)
7435 continue;
7436
7437 // All operations are initially visible
7438 m_invisibleOperations[dstStage] = 0;
7439
7440 // There are no incomplete read operations initially
7441 m_incompleteOperations[dstStage] = 0;
7442
7443 // There are no incomplete layout transitions
7444 m_unavailableLayoutTransition[dstStage] = false;
7445
7446 for (vk::VkPipelineStageFlags srcStage_ = 1; srcStage_ <= m_allowedStages; srcStage_ <<= 1)
7447 {
7448 const PipelineStage srcStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)srcStage_);
7449
7450 if ((srcStage_ & m_allowedStages) == 0)
7451 continue;
7452
7453 // There are no write operations that are not yet available
7454 // initially.
7455 for (vk::VkAccessFlags dstAccess_ = 1; dstAccess_ <= m_allowedAccesses; dstAccess_ <<= 1)
7456 {
7457 const Access dstAccess = accessFlagToAccess((vk::VkAccessFlagBits)dstAccess_);
7458
7459 if ((dstAccess_ & m_allowedAccesses) == 0)
7460 continue;
7461
7462 m_unavailableWriteOperations[dstStage][srcStage][dstAccess] = 0;
7463 }
7464 }
7465 }
7466 }
7467
isValid(vk::VkPipelineStageFlagBits stage,vk::VkAccessFlagBits access) const7468 bool CacheState::isValid (vk::VkPipelineStageFlagBits stage,
7469 vk::VkAccessFlagBits access) const
7470 {
7471 DE_ASSERT((access & (~m_allowedAccesses)) == 0);
7472 DE_ASSERT((stage & (~m_allowedStages)) == 0);
7473
7474 const PipelineStage dstStage = pipelineStageFlagToPipelineStage(stage);
7475
7476 // Previous operations are not visible to access on stage
7477 if (m_unavailableLayoutTransition[dstStage] || (m_invisibleOperations[dstStage] & access) != 0)
7478 return false;
7479
7480 if (isWriteAccess(access))
7481 {
7482 // Memory operations from other stages have not completed before
7483 // dstStage
7484 if (m_incompleteOperations[dstStage] != 0)
7485 return false;
7486 }
7487
7488 return true;
7489 }
7490
perform(vk::VkPipelineStageFlagBits stage,vk::VkAccessFlagBits access)7491 void CacheState::perform (vk::VkPipelineStageFlagBits stage,
7492 vk::VkAccessFlagBits access)
7493 {
7494 DE_ASSERT((access & (~m_allowedAccesses)) == 0);
7495 DE_ASSERT((stage & (~m_allowedStages)) == 0);
7496
7497 const PipelineStage srcStage = pipelineStageFlagToPipelineStage(stage);
7498
7499 for (vk::VkPipelineStageFlags dstStage_ = 1; dstStage_ <= m_allowedStages; dstStage_ <<= 1)
7500 {
7501 const PipelineStage dstStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)dstStage_);
7502
7503 if ((dstStage_ & m_allowedStages) == 0)
7504 continue;
7505
7506 // Mark stage as incomplete for all stages
7507 m_incompleteOperations[dstStage] |= stage;
7508
7509 if (isWriteAccess(access))
7510 {
7511 // Mark all accesses from all stages invisible
7512 m_invisibleOperations[dstStage] |= m_allowedAccesses;
7513
7514 // Mark write access from srcStage unavailable to all stages for all accesses
7515 for (vk::VkAccessFlags dstAccess_ = 1; dstAccess_ <= m_allowedAccesses; dstAccess_ <<= 1)
7516 {
7517 const Access dstAccess = accessFlagToAccess((vk::VkAccessFlagBits)dstAccess_);
7518
7519 if ((dstAccess_ & m_allowedAccesses) == 0)
7520 continue;
7521
7522 m_unavailableWriteOperations[dstStage][srcStage][dstAccess] |= access;
7523 }
7524 }
7525 }
7526 }
7527
submitCommandBuffer(void)7528 void CacheState::submitCommandBuffer (void)
7529 {
7530 // Flush all host writes and reads
7531 barrier(m_allowedStages & vk::VK_PIPELINE_STAGE_HOST_BIT,
7532 m_allowedAccesses & (vk::VK_ACCESS_HOST_READ_BIT | vk::VK_ACCESS_HOST_WRITE_BIT),
7533 m_allowedStages,
7534 m_allowedAccesses);
7535 }
7536
waitForIdle(void)7537 void CacheState::waitForIdle (void)
7538 {
7539 // Make all writes available
7540 barrier(m_allowedStages,
7541 m_allowedAccesses & getWriteAccessFlags(),
7542 m_allowedStages,
7543 0);
7544
7545 // Make all writes visible on device side
7546 barrier(m_allowedStages,
7547 0,
7548 m_allowedStages & (~vk::VK_PIPELINE_STAGE_HOST_BIT),
7549 m_allowedAccesses);
7550 }
7551
getFullBarrier(vk::VkPipelineStageFlags & srcStages,vk::VkAccessFlags & srcAccesses,vk::VkPipelineStageFlags & dstStages,vk::VkAccessFlags & dstAccesses) const7552 void CacheState::getFullBarrier (vk::VkPipelineStageFlags& srcStages,
7553 vk::VkAccessFlags& srcAccesses,
7554 vk::VkPipelineStageFlags& dstStages,
7555 vk::VkAccessFlags& dstAccesses) const
7556 {
7557 srcStages = 0;
7558 srcAccesses = 0;
7559 dstStages = 0;
7560 dstAccesses = 0;
7561
7562 for (vk::VkPipelineStageFlags dstStage_ = 1; dstStage_ <= m_allowedStages; dstStage_ <<= 1)
7563 {
7564 const PipelineStage dstStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)dstStage_);
7565
7566 if ((dstStage_ & m_allowedStages) == 0)
7567 continue;
7568
7569 // Make sure all previous operation are complete in all stages
7570 if (m_incompleteOperations[dstStage])
7571 {
7572 dstStages |= dstStage_;
7573 srcStages |= m_incompleteOperations[dstStage];
7574 }
7575
7576 // Make sure all read operations are visible in dstStage
7577 if (m_invisibleOperations[dstStage])
7578 {
7579 dstStages |= dstStage_;
7580 dstAccesses |= m_invisibleOperations[dstStage];
7581 }
7582
7583 // Make sure all write operations from all stages are available
7584 for (vk::VkPipelineStageFlags srcStage_ = 1; srcStage_ <= m_allowedStages; srcStage_ <<= 1)
7585 {
7586 const PipelineStage srcStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)srcStage_);
7587
7588 if ((srcStage_ & m_allowedStages) == 0)
7589 continue;
7590
7591 for (vk::VkAccessFlags dstAccess_ = 1; dstAccess_ <= m_allowedAccesses; dstAccess_ <<= 1)
7592 {
7593 const Access dstAccess = accessFlagToAccess((vk::VkAccessFlagBits)dstAccess_);
7594
7595 if ((dstAccess_ & m_allowedAccesses) == 0)
7596 continue;
7597
7598 if (m_unavailableWriteOperations[dstStage][srcStage][dstAccess])
7599 {
7600 dstStages |= dstStage_;
7601 srcStages |= dstStage_;
7602 srcAccesses |= m_unavailableWriteOperations[dstStage][srcStage][dstAccess];
7603 }
7604 }
7605
7606 if (m_unavailableLayoutTransition[dstStage] && !m_unavailableLayoutTransition[srcStage])
7607 {
7608 // Add dependency between srcStage and dstStage if layout transition has not completed in dstStage,
7609 // but has completed in srcStage.
7610 dstStages |= dstStage_;
7611 srcStages |= dstStage_;
7612 }
7613 }
7614 }
7615
7616 DE_ASSERT((srcStages & (~m_allowedStages)) == 0);
7617 DE_ASSERT((srcAccesses & (~m_allowedAccesses)) == 0);
7618 DE_ASSERT((dstStages & (~m_allowedStages)) == 0);
7619 DE_ASSERT((dstAccesses & (~m_allowedAccesses)) == 0);
7620 }
7621
checkImageLayoutBarrier(vk::VkPipelineStageFlags srcStages,vk::VkAccessFlags srcAccesses,vk::VkPipelineStageFlags dstStages,vk::VkAccessFlags dstAccesses)7622 void CacheState::checkImageLayoutBarrier (vk::VkPipelineStageFlags srcStages,
7623 vk::VkAccessFlags srcAccesses,
7624 vk::VkPipelineStageFlags dstStages,
7625 vk::VkAccessFlags dstAccesses)
7626 {
7627 DE_ASSERT((srcStages & (~m_allowedStages)) == 0);
7628 DE_ASSERT((srcAccesses & (~m_allowedAccesses)) == 0);
7629 DE_ASSERT((dstStages & (~m_allowedStages)) == 0);
7630 DE_ASSERT((dstAccesses & (~m_allowedAccesses)) == 0);
7631
7632 DE_UNREF(srcStages);
7633 DE_UNREF(srcAccesses);
7634
7635 DE_UNREF(dstStages);
7636 DE_UNREF(dstAccesses);
7637
7638 #if defined(DE_DEBUG)
7639 // Check that all stages have completed before srcStages or are in srcStages.
7640 {
7641 vk::VkPipelineStageFlags completedStages = srcStages;
7642
7643 for (vk::VkPipelineStageFlags srcStage_ = 1; srcStage_ <= srcStages; srcStage_ <<= 1)
7644 {
7645 const PipelineStage srcStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)srcStage_);
7646
7647 if ((srcStage_ & srcStages) == 0)
7648 continue;
7649
7650 completedStages |= (~m_incompleteOperations[srcStage]);
7651 }
7652
7653 DE_ASSERT((completedStages & m_allowedStages) == m_allowedStages);
7654 }
7655
7656 // Check that any write is available at least in one stage. Since all stages are complete even single flush is enough.
7657 if ((getWriteAccessFlags() & m_allowedAccesses) != 0 && (srcAccesses & getWriteAccessFlags()) == 0)
7658 {
7659 bool anyWriteAvailable = false;
7660
7661 for (vk::VkPipelineStageFlags dstStage_ = 1; dstStage_ <= m_allowedStages; dstStage_ <<= 1)
7662 {
7663 const PipelineStage dstStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)dstStage_);
7664
7665 if ((dstStage_ & m_allowedStages) == 0)
7666 continue;
7667
7668 for (vk::VkPipelineStageFlags srcStage_ = 1; srcStage_ <= m_allowedStages; srcStage_ <<= 1)
7669 {
7670 const PipelineStage srcStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)srcStage_);
7671
7672 if ((srcStage_ & m_allowedStages) == 0)
7673 continue;
7674
7675 for (vk::VkAccessFlags dstAccess_ = 1; dstAccess_ <= m_allowedAccesses; dstAccess_ <<= 1)
7676 {
7677 const Access dstAccess = accessFlagToAccess((vk::VkAccessFlagBits)dstAccess_);
7678
7679 if ((dstAccess_ & m_allowedAccesses) == 0)
7680 continue;
7681
7682 if (m_unavailableWriteOperations[dstStage][srcStage][dstAccess] != (getWriteAccessFlags() & m_allowedAccesses))
7683 {
7684 anyWriteAvailable = true;
7685 break;
7686 }
7687 }
7688 }
7689 }
7690
7691 DE_ASSERT(anyWriteAvailable);
7692 }
7693 #endif
7694 }
7695
imageLayoutBarrier(vk::VkPipelineStageFlags srcStages,vk::VkAccessFlags srcAccesses,vk::VkPipelineStageFlags dstStages,vk::VkAccessFlags dstAccesses)7696 void CacheState::imageLayoutBarrier (vk::VkPipelineStageFlags srcStages,
7697 vk::VkAccessFlags srcAccesses,
7698 vk::VkPipelineStageFlags dstStages,
7699 vk::VkAccessFlags dstAccesses)
7700 {
7701 checkImageLayoutBarrier(srcStages, srcAccesses, dstStages, dstAccesses);
7702
7703 for (vk::VkPipelineStageFlags dstStage_ = 1; dstStage_ <= m_allowedStages; dstStage_ <<= 1)
7704 {
7705 const PipelineStage dstStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)dstStage_);
7706
7707 if ((dstStage_ & m_allowedStages) == 0)
7708 continue;
7709
7710 // All stages are incomplete after the barrier except each dstStage in it self.
7711 m_incompleteOperations[dstStage] = m_allowedStages & (~dstStage_);
7712
7713 // All memory operations are invisible unless they are listed in dstAccess
7714 m_invisibleOperations[dstStage] = m_allowedAccesses & (~dstAccesses);
7715
7716 // Layout transition is unavailable in stage unless it was listed in dstStages
7717 m_unavailableLayoutTransition[dstStage]= (dstStage_ & dstStages) == 0;
7718
7719 for (vk::VkPipelineStageFlags srcStage_ = 1; srcStage_ <= m_allowedStages; srcStage_ <<= 1)
7720 {
7721 const PipelineStage srcStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)srcStage_);
7722
7723 if ((srcStage_ & m_allowedStages) == 0)
7724 continue;
7725
7726 // All write operations are available after layout transition
7727 for (vk::VkAccessFlags dstAccess_ = 1; dstAccess_ <= m_allowedAccesses; dstAccess_ <<= 1)
7728 {
7729 const Access dstAccess = accessFlagToAccess((vk::VkAccessFlagBits)dstAccess_);
7730
7731 if ((dstAccess_ & m_allowedAccesses) == 0)
7732 continue;
7733
7734 m_unavailableWriteOperations[dstStage][srcStage][dstAccess] = 0;
7735 }
7736 }
7737 }
7738 }
7739
barrier(vk::VkPipelineStageFlags srcStages,vk::VkAccessFlags srcAccesses,vk::VkPipelineStageFlags dstStages,vk::VkAccessFlags dstAccesses)7740 void CacheState::barrier (vk::VkPipelineStageFlags srcStages,
7741 vk::VkAccessFlags srcAccesses,
7742 vk::VkPipelineStageFlags dstStages,
7743 vk::VkAccessFlags dstAccesses)
7744 {
7745 DE_ASSERT((srcStages & (~m_allowedStages)) == 0);
7746 DE_ASSERT((srcAccesses & (~m_allowedAccesses)) == 0);
7747 DE_ASSERT((dstStages & (~m_allowedStages)) == 0);
7748 DE_ASSERT((dstAccesses & (~m_allowedAccesses)) == 0);
7749
7750 // Transitivity
7751 {
7752 vk::VkPipelineStageFlags oldIncompleteOperations[PIPELINESTAGE_LAST];
7753 vk::VkAccessFlags oldUnavailableWriteOperations[PIPELINESTAGE_LAST][PIPELINESTAGE_LAST][ACCESS_LAST];
7754 bool oldUnavailableLayoutTransition[PIPELINESTAGE_LAST];
7755
7756 deMemcpy(oldIncompleteOperations, m_incompleteOperations, sizeof(oldIncompleteOperations));
7757 deMemcpy(oldUnavailableWriteOperations, m_unavailableWriteOperations, sizeof(oldUnavailableWriteOperations));
7758 deMemcpy(oldUnavailableLayoutTransition, m_unavailableLayoutTransition, sizeof(oldUnavailableLayoutTransition));
7759
7760 for (vk::VkPipelineStageFlags srcStage_ = 1; srcStage_ <= srcStages; srcStage_ <<= 1)
7761 {
7762 const PipelineStage srcStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)srcStage_);
7763
7764 if ((srcStage_ & srcStages) == 0)
7765 continue;
7766
7767 for (vk::VkPipelineStageFlags dstStage_ = 1; dstStage_ <= dstStages; dstStage_ <<= 1)
7768 {
7769 const PipelineStage dstStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)dstStage_);
7770
7771 if ((dstStage_ & dstStages) == 0)
7772 continue;
7773
7774 // Stages that have completed before srcStage have also completed before dstStage
7775 m_incompleteOperations[dstStage] &= oldIncompleteOperations[srcStage];
7776
7777 // Image layout transition in srcStage are now available in dstStage
7778 m_unavailableLayoutTransition[dstStage] &= oldUnavailableLayoutTransition[srcStage];
7779
7780 for (vk::VkPipelineStageFlags sharedStage_ = 1; sharedStage_ <= m_allowedStages; sharedStage_ <<= 1)
7781 {
7782 const PipelineStage sharedStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)sharedStage_);
7783
7784 if ((sharedStage_ & m_allowedStages) == 0)
7785 continue;
7786
7787 // Writes that are available in srcStage are also available in dstStage
7788 for (vk::VkAccessFlags sharedAccess_ = 1; sharedAccess_ <= m_allowedAccesses; sharedAccess_ <<= 1)
7789 {
7790 const Access sharedAccess = accessFlagToAccess((vk::VkAccessFlagBits)sharedAccess_);
7791
7792 if ((sharedAccess_ & m_allowedAccesses) == 0)
7793 continue;
7794
7795 m_unavailableWriteOperations[dstStage][sharedStage][sharedAccess] &= oldUnavailableWriteOperations[srcStage][sharedStage][sharedAccess];
7796 }
7797 }
7798 }
7799 }
7800 }
7801
7802 // Barrier
7803 for (vk::VkPipelineStageFlags dstStage_ = 1; dstStage_ <= dstStages; dstStage_ <<= 1)
7804 {
7805 const PipelineStage dstStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)dstStage_);
7806 bool allWritesAvailable = true;
7807
7808 if ((dstStage_ & dstStages) == 0)
7809 continue;
7810
7811 // Operations in srcStages have completed before any stage in dstStages
7812 m_incompleteOperations[dstStage] &= ~srcStages;
7813
7814 for (vk::VkPipelineStageFlags srcStage_ = 1; srcStage_ <= m_allowedStages; srcStage_ <<= 1)
7815 {
7816 const PipelineStage srcStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)srcStage_);
7817
7818 if ((srcStage_ & m_allowedStages) == 0)
7819 continue;
7820
7821 // Make srcAccesses from srcStage available in dstStage for dstAccess
7822 for (vk::VkAccessFlags dstAccess_ = 1; dstAccess_ <= m_allowedAccesses; dstAccess_ <<= 1)
7823 {
7824 const Access dstAccess = accessFlagToAccess((vk::VkAccessFlagBits)dstAccess_);
7825
7826 if ((dstAccess_ & m_allowedAccesses) == 0)
7827 continue;
7828
7829 if (((srcStage_ & srcStages) != 0) && ((dstAccess_ & dstAccesses) != 0))
7830 m_unavailableWriteOperations[dstStage][srcStage][dstAccess] &= ~srcAccesses;
7831
7832 if (m_unavailableWriteOperations[dstStage][srcStage][dstAccess] != 0)
7833 allWritesAvailable = false;
7834 }
7835 }
7836
7837 // If all writes are available in dstStage make dstAccesses also visible
7838 if (allWritesAvailable)
7839 m_invisibleOperations[dstStage] &= ~dstAccesses;
7840 }
7841 }
7842
isClean(void) const7843 bool CacheState::isClean (void) const
7844 {
7845 for (vk::VkPipelineStageFlags dstStage_ = 1; dstStage_ <= m_allowedStages; dstStage_ <<= 1)
7846 {
7847 const PipelineStage dstStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)dstStage_);
7848
7849 if ((dstStage_ & m_allowedStages) == 0)
7850 continue;
7851
7852 // Some operations are not visible to some stages
7853 if (m_invisibleOperations[dstStage] != 0)
7854 return false;
7855
7856 // There are operation that have not completed yet
7857 if (m_incompleteOperations[dstStage] != 0)
7858 return false;
7859
7860 // Layout transition has not completed yet
7861 if (m_unavailableLayoutTransition[dstStage])
7862 return false;
7863
7864 for (vk::VkPipelineStageFlags srcStage_ = 1; srcStage_ <= m_allowedStages; srcStage_ <<= 1)
7865 {
7866 const PipelineStage srcStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)srcStage_);
7867
7868 if ((srcStage_ & m_allowedStages) == 0)
7869 continue;
7870
7871 for (vk::VkAccessFlags dstAccess_ = 1; dstAccess_ <= m_allowedAccesses; dstAccess_ <<= 1)
7872 {
7873 const Access dstAccess = accessFlagToAccess((vk::VkAccessFlagBits)dstAccess_);
7874
7875 if ((dstAccess_ & m_allowedAccesses) == 0)
7876 continue;
7877
7878 // Some write operations are not available yet
7879 if (m_unavailableWriteOperations[dstStage][srcStage][dstAccess] != 0)
7880 return false;
7881 }
7882 }
7883 }
7884
7885 return true;
7886 }
7887
layoutSupportedByUsage(Usage usage,vk::VkImageLayout layout)7888 bool layoutSupportedByUsage (Usage usage, vk::VkImageLayout layout)
7889 {
7890 switch (layout)
7891 {
7892 case vk::VK_IMAGE_LAYOUT_GENERAL:
7893 return true;
7894
7895 case vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
7896 return (usage & USAGE_COLOR_ATTACHMENT) != 0;
7897
7898 case vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
7899 return (usage & USAGE_DEPTH_STENCIL_ATTACHMENT) != 0;
7900
7901 case vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
7902 return (usage & USAGE_DEPTH_STENCIL_ATTACHMENT) != 0;
7903
7904 case vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
7905 // \todo [2016-03-09 mika] Should include input attachment
7906 return (usage & USAGE_SAMPLED_IMAGE) != 0;
7907
7908 case vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
7909 return (usage & USAGE_TRANSFER_SRC) != 0;
7910
7911 case vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
7912 return (usage & USAGE_TRANSFER_DST) != 0;
7913
7914 case vk::VK_IMAGE_LAYOUT_PREINITIALIZED:
7915 return true;
7916
7917 default:
7918 DE_FATAL("Unknown layout");
7919 return false;
7920 }
7921 }
7922
getNumberOfSupportedLayouts(Usage usage)7923 size_t getNumberOfSupportedLayouts (Usage usage)
7924 {
7925 const vk::VkImageLayout layouts[] =
7926 {
7927 vk::VK_IMAGE_LAYOUT_GENERAL,
7928 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
7929 vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
7930 vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL,
7931 vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
7932 vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
7933 vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
7934 };
7935 size_t supportedLayoutCount = 0;
7936
7937 for (size_t layoutNdx = 0; layoutNdx < DE_LENGTH_OF_ARRAY(layouts); layoutNdx++)
7938 {
7939 const vk::VkImageLayout layout = layouts[layoutNdx];
7940
7941 if (layoutSupportedByUsage(usage, layout))
7942 supportedLayoutCount++;
7943 }
7944
7945 return supportedLayoutCount;
7946 }
7947
getRandomNextLayout(de::Random & rng,Usage usage,vk::VkImageLayout previousLayout)7948 vk::VkImageLayout getRandomNextLayout (de::Random& rng,
7949 Usage usage,
7950 vk::VkImageLayout previousLayout)
7951 {
7952 const vk::VkImageLayout layouts[] =
7953 {
7954 vk::VK_IMAGE_LAYOUT_GENERAL,
7955 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
7956 vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
7957 vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL,
7958 vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
7959 vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
7960 vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
7961 };
7962 const size_t supportedLayoutCount = getNumberOfSupportedLayouts(usage);
7963
7964 DE_ASSERT(supportedLayoutCount > 0);
7965
7966 size_t nextLayoutNdx = ((size_t)rng.getUint32()) % (previousLayout == vk::VK_IMAGE_LAYOUT_UNDEFINED
7967 ? supportedLayoutCount
7968 : supportedLayoutCount - 1);
7969
7970 for (size_t layoutNdx = 0; layoutNdx < DE_LENGTH_OF_ARRAY(layouts); layoutNdx++)
7971 {
7972 const vk::VkImageLayout layout = layouts[layoutNdx];
7973
7974 if (layoutSupportedByUsage(usage, layout) && layout != previousLayout)
7975 {
7976 if (nextLayoutNdx == 0)
7977 return layout;
7978 else
7979 nextLayoutNdx--;
7980 }
7981 }
7982
7983 DE_FATAL("Unreachable");
7984 return vk::VK_IMAGE_LAYOUT_UNDEFINED;
7985 }
7986
7987 struct State
7988 {
Statevkt::memory::__anon58c89e6c0111::State7989 State (Usage usage, deUint32 seed)
7990 : stage (STAGE_HOST)
7991 , cache (usageToStageFlags(usage), usageToAccessFlags(usage))
7992 , rng (seed)
7993 , mapped (false)
7994 , hostInvalidated (true)
7995 , hostFlushed (true)
7996 , memoryDefined (false)
7997 , hasBuffer (false)
7998 , hasBoundBufferMemory (false)
7999 , hasImage (false)
8000 , hasBoundImageMemory (false)
8001 , imageLayout (vk::VK_IMAGE_LAYOUT_UNDEFINED)
8002 , imageDefined (false)
8003 , queueIdle (true)
8004 , deviceIdle (true)
8005 , commandBufferIsEmpty (true)
8006 , primaryCommandBufferIsEmpty (true)
8007 , renderPassIsEmpty (true)
8008 {
8009 }
8010
8011 Stage stage;
8012 CacheState cache;
8013 de::Random rng;
8014
8015 bool mapped;
8016 bool hostInvalidated;
8017 bool hostFlushed;
8018 bool memoryDefined;
8019
8020 bool hasBuffer;
8021 bool hasBoundBufferMemory;
8022
8023 bool hasImage;
8024 bool hasBoundImageMemory;
8025 vk::VkImageLayout imageLayout;
8026 bool imageDefined;
8027
8028 bool queueIdle;
8029 bool deviceIdle;
8030
8031 bool commandBufferIsEmpty;
8032
8033 // a copy of commandBufferIsEmpty value, when secondary command buffer is in use
8034 bool primaryCommandBufferIsEmpty;
8035
8036 bool renderPassIsEmpty;
8037 };
8038
getAvailableOps(const State & state,bool supportsBuffers,bool supportsImages,Usage usage,vector<Op> & ops)8039 void getAvailableOps (const State& state, bool supportsBuffers, bool supportsImages, Usage usage, vector<Op>& ops)
8040 {
8041 if (state.stage == STAGE_HOST)
8042 {
8043 if (usage & (USAGE_HOST_READ | USAGE_HOST_WRITE))
8044 {
8045 // Host memory operations
8046 if (state.mapped)
8047 {
8048 ops.push_back(OP_UNMAP);
8049
8050 // Avoid flush and finish if they are not needed
8051 if (!state.hostFlushed)
8052 ops.push_back(OP_MAP_FLUSH);
8053
8054 if (!state.hostInvalidated
8055 && state.queueIdle
8056 && ((usage & USAGE_HOST_READ) == 0
8057 || state.cache.isValid(vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_ACCESS_HOST_READ_BIT))
8058 && ((usage & USAGE_HOST_WRITE) == 0
8059 || state.cache.isValid(vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_ACCESS_HOST_WRITE_BIT)))
8060 {
8061 ops.push_back(OP_MAP_INVALIDATE);
8062 }
8063
8064 if (usage & USAGE_HOST_READ
8065 && usage & USAGE_HOST_WRITE
8066 && state.memoryDefined
8067 && state.hostInvalidated
8068 && state.queueIdle
8069 && state.cache.isValid(vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_ACCESS_HOST_WRITE_BIT)
8070 && state.cache.isValid(vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_ACCESS_HOST_READ_BIT))
8071 {
8072 ops.push_back(OP_MAP_MODIFY);
8073 }
8074
8075 if (usage & USAGE_HOST_READ
8076 && state.memoryDefined
8077 && state.hostInvalidated
8078 && state.queueIdle
8079 && state.cache.isValid(vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_ACCESS_HOST_READ_BIT))
8080 {
8081 ops.push_back(OP_MAP_READ);
8082 }
8083
8084 if (usage & USAGE_HOST_WRITE
8085 && state.hostInvalidated
8086 && state.queueIdle
8087 && state.cache.isValid(vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_ACCESS_HOST_WRITE_BIT))
8088 {
8089 ops.push_back(OP_MAP_WRITE);
8090 }
8091 }
8092 else
8093 ops.push_back(OP_MAP);
8094 }
8095
8096 if (state.hasBoundBufferMemory && state.queueIdle)
8097 {
8098 // \note Destroy only buffers after they have been bound
8099 ops.push_back(OP_BUFFER_DESTROY);
8100 }
8101 else
8102 {
8103 if (state.hasBuffer)
8104 {
8105 if (!state.hasBoundBufferMemory)
8106 ops.push_back(OP_BUFFER_BINDMEMORY);
8107 }
8108 else if (!state.hasImage && supportsBuffers) // Avoid creating buffer if there is already image
8109 ops.push_back(OP_BUFFER_CREATE);
8110 }
8111
8112 if (state.hasBoundImageMemory && state.queueIdle)
8113 {
8114 // \note Destroy only image after they have been bound
8115 ops.push_back(OP_IMAGE_DESTROY);
8116 }
8117 else
8118 {
8119 if (state.hasImage)
8120 {
8121 if (!state.hasBoundImageMemory)
8122 ops.push_back(OP_IMAGE_BINDMEMORY);
8123 }
8124 else if (!state.hasBuffer && supportsImages) // Avoid creating image if there is already buffer
8125 ops.push_back(OP_IMAGE_CREATE);
8126 }
8127
8128 // Host writes must be flushed before GPU commands and there must be
8129 // buffer or image for GPU commands
8130 if (state.hostFlushed
8131 && (state.memoryDefined || supportsDeviceBufferWrites(usage) || state.imageDefined || supportsDeviceImageWrites(usage))
8132 && (state.hasBoundBufferMemory || state.hasBoundImageMemory) // Avoid command buffers if there is no object to use
8133 && (usageToStageFlags(usage) & (~vk::VK_PIPELINE_STAGE_HOST_BIT)) != 0) // Don't start command buffer if there are no ways to use memory from gpu
8134 {
8135 ops.push_back(OP_COMMAND_BUFFER_BEGIN);
8136 }
8137
8138 if (!state.deviceIdle)
8139 ops.push_back(OP_DEVICE_WAIT_FOR_IDLE);
8140
8141 if (!state.queueIdle)
8142 ops.push_back(OP_QUEUE_WAIT_FOR_IDLE);
8143 }
8144 else if (state.stage == STAGE_COMMAND_BUFFER)
8145 {
8146 if (!state.cache.isClean())
8147 {
8148 ops.push_back(OP_PIPELINE_BARRIER_GLOBAL);
8149
8150 if (state.hasImage && (state.imageLayout != vk::VK_IMAGE_LAYOUT_UNDEFINED))
8151 ops.push_back(OP_PIPELINE_BARRIER_IMAGE);
8152
8153 if (state.hasBuffer)
8154 ops.push_back(OP_PIPELINE_BARRIER_BUFFER);
8155 }
8156
8157 if (state.hasBoundBufferMemory)
8158 {
8159 if (usage & USAGE_TRANSFER_DST
8160 && state.cache.isValid(vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_ACCESS_TRANSFER_WRITE_BIT))
8161 {
8162 ops.push_back(OP_BUFFER_FILL);
8163 ops.push_back(OP_BUFFER_UPDATE);
8164 ops.push_back(OP_BUFFER_COPY_FROM_BUFFER);
8165 ops.push_back(OP_BUFFER_COPY_FROM_IMAGE);
8166 }
8167
8168 if (usage & USAGE_TRANSFER_SRC
8169 && state.memoryDefined
8170 && state.cache.isValid(vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT))
8171 {
8172 ops.push_back(OP_BUFFER_COPY_TO_BUFFER);
8173 ops.push_back(OP_BUFFER_COPY_TO_IMAGE);
8174 }
8175 }
8176
8177 if (state.hasBoundImageMemory
8178 && (state.imageLayout == vk::VK_IMAGE_LAYOUT_UNDEFINED
8179 || getNumberOfSupportedLayouts(usage) > 1))
8180 {
8181 ops.push_back(OP_IMAGE_TRANSITION_LAYOUT);
8182
8183 {
8184 if (usage & USAGE_TRANSFER_DST
8185 && (state.imageLayout == vk::VK_IMAGE_LAYOUT_GENERAL
8186 || state.imageLayout == vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
8187 && state.cache.isValid(vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_ACCESS_TRANSFER_WRITE_BIT))
8188 {
8189 ops.push_back(OP_IMAGE_COPY_FROM_BUFFER);
8190 ops.push_back(OP_IMAGE_COPY_FROM_IMAGE);
8191 ops.push_back(OP_IMAGE_BLIT_FROM_IMAGE);
8192 }
8193
8194 if (usage & USAGE_TRANSFER_SRC
8195 && (state.imageLayout == vk::VK_IMAGE_LAYOUT_GENERAL
8196 || state.imageLayout == vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL)
8197 && state.imageDefined
8198 && state.cache.isValid(vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT))
8199 {
8200 ops.push_back(OP_IMAGE_COPY_TO_BUFFER);
8201 ops.push_back(OP_IMAGE_COPY_TO_IMAGE);
8202 ops.push_back(OP_IMAGE_BLIT_TO_IMAGE);
8203 }
8204 }
8205 }
8206
8207 // \todo [2016-03-09 mika] Add other usages?
8208 if ((state.memoryDefined
8209 && state.hasBoundBufferMemory
8210 && (((usage & USAGE_VERTEX_BUFFER)
8211 && state.cache.isValid(vk::VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, vk::VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT))
8212 || ((usage & USAGE_INDEX_BUFFER)
8213 && state.cache.isValid(vk::VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, vk::VK_ACCESS_INDEX_READ_BIT))
8214 || ((usage & USAGE_UNIFORM_BUFFER)
8215 && (state.cache.isValid(vk::VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, vk::VK_ACCESS_UNIFORM_READ_BIT)
8216 || state.cache.isValid(vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, vk::VK_ACCESS_UNIFORM_READ_BIT)))
8217 || ((usage & USAGE_UNIFORM_TEXEL_BUFFER)
8218 && (state.cache.isValid(vk::VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, vk::VK_ACCESS_UNIFORM_READ_BIT)
8219 || state.cache.isValid(vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, vk::VK_ACCESS_UNIFORM_READ_BIT)))
8220 || ((usage & USAGE_STORAGE_BUFFER)
8221 && (state.cache.isValid(vk::VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, vk::VK_ACCESS_SHADER_READ_BIT)
8222 || state.cache.isValid(vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, vk::VK_ACCESS_SHADER_READ_BIT)))
8223 || ((usage & USAGE_STORAGE_TEXEL_BUFFER)
8224 && state.cache.isValid(vk::VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, vk::VK_ACCESS_SHADER_READ_BIT))))
8225 || (state.imageDefined
8226 && state.hasBoundImageMemory
8227 && (((usage & USAGE_STORAGE_IMAGE)
8228 && state.imageLayout == vk::VK_IMAGE_LAYOUT_GENERAL
8229 && (state.cache.isValid(vk::VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, vk::VK_ACCESS_SHADER_READ_BIT)
8230 || state.cache.isValid(vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, vk::VK_ACCESS_SHADER_READ_BIT)))
8231 || ((usage & USAGE_SAMPLED_IMAGE)
8232 && (state.imageLayout == vk::VK_IMAGE_LAYOUT_GENERAL
8233 || state.imageLayout == vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
8234 && (state.cache.isValid(vk::VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, vk::VK_ACCESS_SHADER_READ_BIT)
8235 || state.cache.isValid(vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, vk::VK_ACCESS_SHADER_READ_BIT))))))
8236 {
8237 ops.push_back(OP_RENDERPASS_BEGIN);
8238 }
8239
8240 ops.push_back(OP_SECONDARY_COMMAND_BUFFER_BEGIN);
8241
8242 // \note This depends on previous operations and has to be always the
8243 // last command buffer operation check
8244 if (ops.empty() || !state.commandBufferIsEmpty)
8245 ops.push_back(OP_COMMAND_BUFFER_END);
8246 }
8247 else if (state.stage == STAGE_SECONDARY_COMMAND_BUFFER)
8248 {
8249 if (!state.cache.isClean())
8250 {
8251 ops.push_back(OP_PIPELINE_BARRIER_GLOBAL);
8252
8253 if (state.hasImage && (state.imageLayout != vk::VK_IMAGE_LAYOUT_UNDEFINED))
8254 ops.push_back(OP_PIPELINE_BARRIER_IMAGE);
8255
8256 if (state.hasBuffer)
8257 ops.push_back(OP_PIPELINE_BARRIER_BUFFER);
8258 }
8259
8260 if (state.hasBoundBufferMemory)
8261 {
8262 if (usage & USAGE_TRANSFER_DST
8263 && state.cache.isValid(vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_ACCESS_TRANSFER_WRITE_BIT))
8264 {
8265 ops.push_back(OP_BUFFER_FILL);
8266 ops.push_back(OP_BUFFER_UPDATE);
8267 ops.push_back(OP_BUFFER_COPY_FROM_BUFFER);
8268 ops.push_back(OP_BUFFER_COPY_FROM_IMAGE);
8269 }
8270
8271 if (usage & USAGE_TRANSFER_SRC
8272 && state.memoryDefined
8273 && state.cache.isValid(vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT))
8274 {
8275 ops.push_back(OP_BUFFER_COPY_TO_BUFFER);
8276 ops.push_back(OP_BUFFER_COPY_TO_IMAGE);
8277 }
8278 }
8279
8280 if (state.hasBoundImageMemory
8281 && (state.imageLayout == vk::VK_IMAGE_LAYOUT_UNDEFINED
8282 || getNumberOfSupportedLayouts(usage) > 1))
8283 {
8284 ops.push_back(OP_IMAGE_TRANSITION_LAYOUT);
8285
8286 {
8287 if (usage & USAGE_TRANSFER_DST
8288 && (state.imageLayout == vk::VK_IMAGE_LAYOUT_GENERAL
8289 || state.imageLayout == vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
8290 && state.cache.isValid(vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_ACCESS_TRANSFER_WRITE_BIT))
8291 {
8292 ops.push_back(OP_IMAGE_COPY_FROM_BUFFER);
8293 ops.push_back(OP_IMAGE_COPY_FROM_IMAGE);
8294 ops.push_back(OP_IMAGE_BLIT_FROM_IMAGE);
8295 }
8296
8297 if (usage & USAGE_TRANSFER_SRC
8298 && (state.imageLayout == vk::VK_IMAGE_LAYOUT_GENERAL
8299 || state.imageLayout == vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL)
8300 && state.imageDefined
8301 && state.cache.isValid(vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT))
8302 {
8303 ops.push_back(OP_IMAGE_COPY_TO_BUFFER);
8304 ops.push_back(OP_IMAGE_COPY_TO_IMAGE);
8305 ops.push_back(OP_IMAGE_BLIT_TO_IMAGE);
8306 }
8307 }
8308 }
8309
8310 // \note This depends on previous operations and has to be always the
8311 // last command buffer operation check
8312 if (ops.empty() || !state.commandBufferIsEmpty)
8313 ops.push_back(OP_SECONDARY_COMMAND_BUFFER_END);
8314 }
8315 else if (state.stage == STAGE_RENDER_PASS)
8316 {
8317 if ((usage & USAGE_VERTEX_BUFFER) != 0
8318 && state.memoryDefined
8319 && state.hasBoundBufferMemory
8320 && state.cache.isValid(vk::VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, vk::VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT))
8321 {
8322 ops.push_back(OP_RENDER_VERTEX_BUFFER);
8323 }
8324
8325 if ((usage & USAGE_INDEX_BUFFER) != 0
8326 && state.memoryDefined
8327 && state.hasBoundBufferMemory
8328 && state.cache.isValid(vk::VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, vk::VK_ACCESS_INDEX_READ_BIT))
8329 {
8330 ops.push_back(OP_RENDER_INDEX_BUFFER);
8331 }
8332
8333 if ((usage & USAGE_UNIFORM_BUFFER) != 0
8334 && state.memoryDefined
8335 && state.hasBoundBufferMemory)
8336 {
8337 if (state.cache.isValid(vk::VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, vk::VK_ACCESS_UNIFORM_READ_BIT))
8338 ops.push_back(OP_RENDER_VERTEX_UNIFORM_BUFFER);
8339
8340 if (state.cache.isValid(vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, vk::VK_ACCESS_UNIFORM_READ_BIT))
8341 ops.push_back(OP_RENDER_FRAGMENT_UNIFORM_BUFFER);
8342 }
8343
8344 if ((usage & USAGE_UNIFORM_TEXEL_BUFFER) != 0
8345 && state.memoryDefined
8346 && state.hasBoundBufferMemory)
8347 {
8348 if (state.cache.isValid(vk::VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, vk::VK_ACCESS_UNIFORM_READ_BIT))
8349 ops.push_back(OP_RENDER_VERTEX_UNIFORM_TEXEL_BUFFER);
8350
8351 if (state.cache.isValid(vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, vk::VK_ACCESS_UNIFORM_READ_BIT))
8352 ops.push_back(OP_RENDER_FRAGMENT_UNIFORM_TEXEL_BUFFER);
8353 }
8354
8355 if ((usage & USAGE_STORAGE_BUFFER) != 0
8356 && state.memoryDefined
8357 && state.hasBoundBufferMemory)
8358 {
8359 if (state.cache.isValid(vk::VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, vk::VK_ACCESS_SHADER_READ_BIT))
8360 ops.push_back(OP_RENDER_VERTEX_STORAGE_BUFFER);
8361
8362 if (state.cache.isValid(vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, vk::VK_ACCESS_SHADER_READ_BIT))
8363 ops.push_back(OP_RENDER_FRAGMENT_STORAGE_BUFFER);
8364 }
8365
8366 if ((usage & USAGE_STORAGE_TEXEL_BUFFER) != 0
8367 && state.memoryDefined
8368 && state.hasBoundBufferMemory)
8369 {
8370 if (state.cache.isValid(vk::VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, vk::VK_ACCESS_SHADER_READ_BIT))
8371 ops.push_back(OP_RENDER_VERTEX_STORAGE_TEXEL_BUFFER);
8372
8373 if (state.cache.isValid(vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, vk::VK_ACCESS_SHADER_READ_BIT))
8374 ops.push_back(OP_RENDER_FRAGMENT_STORAGE_TEXEL_BUFFER);
8375 }
8376
8377 if ((usage & USAGE_STORAGE_IMAGE) != 0
8378 && state.imageDefined
8379 && state.hasBoundImageMemory
8380 && (state.imageLayout == vk::VK_IMAGE_LAYOUT_GENERAL))
8381 {
8382 if (state.cache.isValid(vk::VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, vk::VK_ACCESS_SHADER_READ_BIT))
8383 ops.push_back(OP_RENDER_VERTEX_STORAGE_IMAGE);
8384
8385 if (state.cache.isValid(vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, vk::VK_ACCESS_SHADER_READ_BIT))
8386 ops.push_back(OP_RENDER_FRAGMENT_STORAGE_IMAGE);
8387 }
8388
8389 if ((usage & USAGE_SAMPLED_IMAGE) != 0
8390 && state.imageDefined
8391 && state.hasBoundImageMemory
8392 && (state.imageLayout == vk::VK_IMAGE_LAYOUT_GENERAL
8393 || state.imageLayout == vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL))
8394 {
8395 if (state.cache.isValid(vk::VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, vk::VK_ACCESS_SHADER_READ_BIT))
8396 ops.push_back(OP_RENDER_VERTEX_SAMPLED_IMAGE);
8397
8398 if (state.cache.isValid(vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, vk::VK_ACCESS_SHADER_READ_BIT))
8399 ops.push_back(OP_RENDER_FRAGMENT_SAMPLED_IMAGE);
8400 }
8401
8402 if (!state.renderPassIsEmpty)
8403 ops.push_back(OP_RENDERPASS_END);
8404 }
8405 else
8406 DE_FATAL("Unknown stage");
8407 }
8408
removeIllegalAccessFlags(vk::VkAccessFlags & accessflags,vk::VkPipelineStageFlags stageflags)8409 void removeIllegalAccessFlags (vk::VkAccessFlags& accessflags, vk::VkPipelineStageFlags stageflags)
8410 {
8411 if (!(stageflags & vk::VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT))
8412 accessflags &= ~vk::VK_ACCESS_INDIRECT_COMMAND_READ_BIT;
8413
8414 if (!(stageflags & vk::VK_PIPELINE_STAGE_VERTEX_INPUT_BIT))
8415 accessflags &= ~vk::VK_ACCESS_INDEX_READ_BIT;
8416
8417 if (!(stageflags & vk::VK_PIPELINE_STAGE_VERTEX_INPUT_BIT))
8418 accessflags &= ~vk::VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
8419
8420 if (!(stageflags & (vk::VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
8421 vk::VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT |
8422 vk::VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT |
8423 vk::VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT |
8424 vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
8425 vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT)))
8426 accessflags &= ~vk::VK_ACCESS_UNIFORM_READ_BIT;
8427
8428 if (!(stageflags & vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT))
8429 accessflags &= ~vk::VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
8430
8431 if (!(stageflags & (vk::VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
8432 vk::VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT |
8433 vk::VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT |
8434 vk::VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT |
8435 vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
8436 vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT)))
8437 accessflags &= ~vk::VK_ACCESS_SHADER_READ_BIT;
8438
8439 if (!(stageflags & (vk::VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
8440 vk::VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT |
8441 vk::VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT |
8442 vk::VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT |
8443 vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
8444 vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT)))
8445 accessflags &= ~vk::VK_ACCESS_SHADER_WRITE_BIT;
8446
8447 if (!(stageflags & vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT))
8448 accessflags &= ~vk::VK_ACCESS_COLOR_ATTACHMENT_READ_BIT;
8449
8450 if (!(stageflags & vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT))
8451 accessflags &= ~vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
8452
8453 if (!(stageflags & (vk::VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
8454 vk::VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT)))
8455 accessflags &= ~vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
8456
8457 if (!(stageflags & (vk::VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
8458 vk::VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT)))
8459 accessflags &= ~vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
8460
8461 if (!(stageflags & vk::VK_PIPELINE_STAGE_TRANSFER_BIT))
8462 accessflags &= ~vk::VK_ACCESS_TRANSFER_READ_BIT;
8463
8464 if (!(stageflags & vk::VK_PIPELINE_STAGE_TRANSFER_BIT))
8465 accessflags &= ~vk::VK_ACCESS_TRANSFER_WRITE_BIT;
8466
8467 if (!(stageflags & vk::VK_PIPELINE_STAGE_HOST_BIT))
8468 accessflags &= ~vk::VK_ACCESS_HOST_READ_BIT;
8469
8470 if (!(stageflags & vk::VK_PIPELINE_STAGE_HOST_BIT))
8471 accessflags &= ~vk::VK_ACCESS_HOST_WRITE_BIT;
8472 }
8473
applyOp(State & state,const Memory & memory,Op op,Usage usage)8474 void applyOp (State& state, const Memory& memory, Op op, Usage usage)
8475 {
8476 switch (op)
8477 {
8478 case OP_MAP:
8479 DE_ASSERT(state.stage == STAGE_HOST);
8480 DE_ASSERT(!state.mapped);
8481 state.mapped = true;
8482 break;
8483
8484 case OP_UNMAP:
8485 DE_ASSERT(state.stage == STAGE_HOST);
8486 DE_ASSERT(state.mapped);
8487 state.mapped = false;
8488 break;
8489
8490 case OP_MAP_FLUSH:
8491 DE_ASSERT(state.stage == STAGE_HOST);
8492 DE_ASSERT(!state.hostFlushed);
8493 state.hostFlushed = true;
8494 break;
8495
8496 case OP_MAP_INVALIDATE:
8497 DE_ASSERT(state.stage == STAGE_HOST);
8498 DE_ASSERT(!state.hostInvalidated);
8499 state.hostInvalidated = true;
8500 break;
8501
8502 case OP_MAP_READ:
8503 DE_ASSERT(state.stage == STAGE_HOST);
8504 DE_ASSERT(state.hostInvalidated);
8505 state.rng.getUint32();
8506 break;
8507
8508 case OP_MAP_WRITE:
8509 DE_ASSERT(state.stage == STAGE_HOST);
8510 if ((memory.getMemoryType().propertyFlags & vk::VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) == 0)
8511 state.hostFlushed = false;
8512
8513 state.memoryDefined = true;
8514 state.imageDefined = false;
8515 state.imageLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
8516 state.rng.getUint32();
8517 break;
8518
8519 case OP_MAP_MODIFY:
8520 DE_ASSERT(state.stage == STAGE_HOST);
8521 DE_ASSERT(state.hostInvalidated);
8522
8523 if ((memory.getMemoryType().propertyFlags & vk::VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) == 0)
8524 state.hostFlushed = false;
8525
8526 state.rng.getUint32();
8527 break;
8528
8529 case OP_BUFFER_CREATE:
8530 DE_ASSERT(state.stage == STAGE_HOST);
8531 DE_ASSERT(!state.hasBuffer);
8532
8533 state.hasBuffer = true;
8534 break;
8535
8536 case OP_BUFFER_DESTROY:
8537 DE_ASSERT(state.stage == STAGE_HOST);
8538 DE_ASSERT(state.hasBuffer);
8539 DE_ASSERT(state.hasBoundBufferMemory);
8540
8541 state.hasBuffer = false;
8542 state.hasBoundBufferMemory = false;
8543 break;
8544
8545 case OP_BUFFER_BINDMEMORY:
8546 DE_ASSERT(state.stage == STAGE_HOST);
8547 DE_ASSERT(state.hasBuffer);
8548 DE_ASSERT(!state.hasBoundBufferMemory);
8549
8550 state.hasBoundBufferMemory = true;
8551 break;
8552
8553 case OP_IMAGE_CREATE:
8554 DE_ASSERT(state.stage == STAGE_HOST);
8555 DE_ASSERT(!state.hasImage);
8556 DE_ASSERT(!state.hasBuffer);
8557
8558 state.hasImage = true;
8559 break;
8560
8561 case OP_IMAGE_DESTROY:
8562 DE_ASSERT(state.stage == STAGE_HOST);
8563 DE_ASSERT(state.hasImage);
8564 DE_ASSERT(state.hasBoundImageMemory);
8565
8566 state.hasImage = false;
8567 state.hasBoundImageMemory = false;
8568 state.imageLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
8569 state.imageDefined = false;
8570 break;
8571
8572 case OP_IMAGE_BINDMEMORY:
8573 DE_ASSERT(state.stage == STAGE_HOST);
8574 DE_ASSERT(state.hasImage);
8575 DE_ASSERT(!state.hasBoundImageMemory);
8576
8577 state.hasBoundImageMemory = true;
8578 break;
8579
8580 case OP_IMAGE_TRANSITION_LAYOUT:
8581 {
8582 DE_ASSERT(state.stage == STAGE_COMMAND_BUFFER || state.stage == STAGE_SECONDARY_COMMAND_BUFFER);
8583 DE_ASSERT(state.hasImage);
8584 DE_ASSERT(state.hasBoundImageMemory);
8585
8586 // \todo [2016-03-09 mika] Support linear tiling and predefined data
8587 const vk::VkImageLayout srcLayout = state.rng.getFloat() < 0.9f ? state.imageLayout : vk::VK_IMAGE_LAYOUT_UNDEFINED;
8588 const vk::VkImageLayout dstLayout = getRandomNextLayout(state.rng, usage, srcLayout);
8589
8590 vk::VkPipelineStageFlags dirtySrcStages;
8591 vk::VkAccessFlags dirtySrcAccesses;
8592 vk::VkPipelineStageFlags dirtyDstStages;
8593 vk::VkAccessFlags dirtyDstAccesses;
8594
8595 vk::VkPipelineStageFlags srcStages;
8596 vk::VkAccessFlags srcAccesses;
8597 vk::VkPipelineStageFlags dstStages;
8598 vk::VkAccessFlags dstAccesses;
8599
8600 state.cache.getFullBarrier(dirtySrcStages, dirtySrcAccesses, dirtyDstStages, dirtyDstAccesses);
8601
8602 // Try masking some random bits
8603 srcStages = dirtySrcStages;
8604 srcAccesses = dirtySrcAccesses;
8605
8606 dstStages = state.cache.getAllowedStages() & state.rng.getUint32();
8607 dstAccesses = state.cache.getAllowedAcceses() & state.rng.getUint32();
8608
8609 // If there are no bits in dst stage mask use all stages
8610 dstStages = dstStages ? dstStages : state.cache.getAllowedStages();
8611
8612 if (!srcStages)
8613 srcStages = dstStages;
8614
8615 removeIllegalAccessFlags(dstAccesses, dstStages);
8616 removeIllegalAccessFlags(srcAccesses, srcStages);
8617
8618 if (srcLayout == vk::VK_IMAGE_LAYOUT_UNDEFINED)
8619 state.imageDefined = false;
8620
8621 state.commandBufferIsEmpty = false;
8622 state.imageLayout = dstLayout;
8623 state.memoryDefined = false;
8624 state.cache.imageLayoutBarrier(srcStages, srcAccesses, dstStages, dstAccesses);
8625 break;
8626 }
8627
8628 case OP_QUEUE_WAIT_FOR_IDLE:
8629 DE_ASSERT(state.stage == STAGE_HOST);
8630 DE_ASSERT(!state.queueIdle);
8631
8632 state.queueIdle = true;
8633
8634 state.cache.waitForIdle();
8635 break;
8636
8637 case OP_DEVICE_WAIT_FOR_IDLE:
8638 DE_ASSERT(state.stage == STAGE_HOST);
8639 DE_ASSERT(!state.deviceIdle);
8640
8641 state.queueIdle = true;
8642 state.deviceIdle = true;
8643
8644 state.cache.waitForIdle();
8645 break;
8646
8647 case OP_COMMAND_BUFFER_BEGIN:
8648 DE_ASSERT(state.stage == STAGE_HOST);
8649 state.stage = STAGE_COMMAND_BUFFER;
8650 state.commandBufferIsEmpty = true;
8651 // Makes host writes visible to command buffer
8652 state.cache.submitCommandBuffer();
8653 break;
8654
8655 case OP_COMMAND_BUFFER_END:
8656 DE_ASSERT(state.stage == STAGE_COMMAND_BUFFER || state.stage == STAGE_SECONDARY_COMMAND_BUFFER);
8657 state.stage = STAGE_HOST;
8658 state.queueIdle = false;
8659 state.deviceIdle = false;
8660 break;
8661
8662 case OP_SECONDARY_COMMAND_BUFFER_BEGIN:
8663 DE_ASSERT(state.stage == STAGE_COMMAND_BUFFER || state.stage == STAGE_SECONDARY_COMMAND_BUFFER);
8664 state.stage = STAGE_SECONDARY_COMMAND_BUFFER;
8665 state.primaryCommandBufferIsEmpty = state.commandBufferIsEmpty;
8666 state.commandBufferIsEmpty = true;
8667 break;
8668
8669 case OP_SECONDARY_COMMAND_BUFFER_END:
8670 DE_ASSERT(state.stage == STAGE_SECONDARY_COMMAND_BUFFER || state.stage == STAGE_SECONDARY_COMMAND_BUFFER);
8671 state.stage = STAGE_COMMAND_BUFFER;
8672 state.commandBufferIsEmpty = state.primaryCommandBufferIsEmpty;
8673 break;
8674
8675 case OP_BUFFER_COPY_FROM_BUFFER:
8676 case OP_BUFFER_COPY_FROM_IMAGE:
8677 case OP_BUFFER_UPDATE:
8678 case OP_BUFFER_FILL:
8679 state.rng.getUint32();
8680 DE_ASSERT(state.stage == STAGE_COMMAND_BUFFER || state.stage == STAGE_SECONDARY_COMMAND_BUFFER);
8681
8682 if ((memory.getMemoryType().propertyFlags & vk::VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) == 0)
8683 state.hostInvalidated = false;
8684
8685 state.commandBufferIsEmpty = false;
8686 state.memoryDefined = true;
8687 state.imageDefined = false;
8688 state.imageLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
8689 state.cache.perform(vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_ACCESS_TRANSFER_WRITE_BIT);
8690 break;
8691
8692 case OP_BUFFER_COPY_TO_BUFFER:
8693 case OP_BUFFER_COPY_TO_IMAGE:
8694 DE_ASSERT(state.stage == STAGE_COMMAND_BUFFER || state.stage == STAGE_SECONDARY_COMMAND_BUFFER);
8695
8696 state.commandBufferIsEmpty = false;
8697 state.cache.perform(vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT);
8698 break;
8699
8700 case OP_IMAGE_BLIT_FROM_IMAGE:
8701 state.rng.getBool();
8702 // Fall through
8703 case OP_IMAGE_COPY_FROM_BUFFER:
8704 case OP_IMAGE_COPY_FROM_IMAGE:
8705 state.rng.getUint32();
8706 DE_ASSERT(state.stage == STAGE_COMMAND_BUFFER || state.stage == STAGE_SECONDARY_COMMAND_BUFFER);
8707
8708 if ((memory.getMemoryType().propertyFlags & vk::VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) == 0)
8709 state.hostInvalidated = false;
8710
8711 state.commandBufferIsEmpty = false;
8712 state.memoryDefined = false;
8713 state.imageDefined = true;
8714 state.cache.perform(vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_ACCESS_TRANSFER_WRITE_BIT);
8715 break;
8716
8717 case OP_IMAGE_BLIT_TO_IMAGE:
8718 state.rng.getBool();
8719 // Fall through
8720 case OP_IMAGE_COPY_TO_BUFFER:
8721 case OP_IMAGE_COPY_TO_IMAGE:
8722 DE_ASSERT(state.stage == STAGE_COMMAND_BUFFER || state.stage == STAGE_SECONDARY_COMMAND_BUFFER);
8723
8724 state.commandBufferIsEmpty = false;
8725 state.cache.perform(vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT);
8726 break;
8727
8728 case OP_PIPELINE_BARRIER_GLOBAL:
8729 case OP_PIPELINE_BARRIER_BUFFER:
8730 case OP_PIPELINE_BARRIER_IMAGE:
8731 {
8732 DE_ASSERT(state.stage == STAGE_COMMAND_BUFFER || state.stage == STAGE_SECONDARY_COMMAND_BUFFER);
8733
8734 vk::VkPipelineStageFlags dirtySrcStages;
8735 vk::VkAccessFlags dirtySrcAccesses;
8736 vk::VkPipelineStageFlags dirtyDstStages;
8737 vk::VkAccessFlags dirtyDstAccesses;
8738
8739 vk::VkPipelineStageFlags srcStages;
8740 vk::VkAccessFlags srcAccesses;
8741 vk::VkPipelineStageFlags dstStages;
8742 vk::VkAccessFlags dstAccesses;
8743
8744 state.cache.getFullBarrier(dirtySrcStages, dirtySrcAccesses, dirtyDstStages, dirtyDstAccesses);
8745
8746 // Try masking some random bits
8747 srcStages = dirtySrcStages & state.rng.getUint32();
8748 srcAccesses = dirtySrcAccesses & state.rng.getUint32();
8749
8750 dstStages = dirtyDstStages & state.rng.getUint32();
8751 dstAccesses = dirtyDstAccesses & state.rng.getUint32();
8752
8753 // If there are no bits in stage mask use the original dirty stages
8754 srcStages = srcStages ? srcStages : dirtySrcStages;
8755 dstStages = dstStages ? dstStages : dirtyDstStages;
8756
8757 if (!srcStages)
8758 srcStages = dstStages;
8759
8760 removeIllegalAccessFlags(dstAccesses, dstStages);
8761 removeIllegalAccessFlags(srcAccesses, srcStages);
8762
8763 state.commandBufferIsEmpty = false;
8764 state.cache.barrier(srcStages, srcAccesses, dstStages, dstAccesses);
8765 break;
8766 }
8767
8768 case OP_RENDERPASS_BEGIN:
8769 {
8770 DE_ASSERT(state.stage == STAGE_COMMAND_BUFFER);
8771
8772 state.renderPassIsEmpty = true;
8773 state.stage = STAGE_RENDER_PASS;
8774 break;
8775 }
8776
8777 case OP_RENDERPASS_END:
8778 {
8779 DE_ASSERT(state.stage == STAGE_RENDER_PASS);
8780
8781 state.renderPassIsEmpty = true;
8782 state.stage = STAGE_COMMAND_BUFFER;
8783 break;
8784 }
8785
8786 case OP_RENDER_VERTEX_BUFFER:
8787 {
8788 DE_ASSERT(state.stage == STAGE_RENDER_PASS);
8789
8790 state.renderPassIsEmpty = false;
8791 state.cache.perform(vk::VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, vk::VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT);
8792 break;
8793 }
8794
8795 case OP_RENDER_INDEX_BUFFER:
8796 {
8797 DE_ASSERT(state.stage == STAGE_RENDER_PASS);
8798
8799 state.renderPassIsEmpty = false;
8800 state.cache.perform(vk::VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, vk::VK_ACCESS_INDEX_READ_BIT);
8801 break;
8802 }
8803
8804 case OP_RENDER_VERTEX_UNIFORM_BUFFER:
8805 case OP_RENDER_VERTEX_UNIFORM_TEXEL_BUFFER:
8806 {
8807 DE_ASSERT(state.stage == STAGE_RENDER_PASS);
8808
8809 state.renderPassIsEmpty = false;
8810 state.cache.perform(vk::VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, vk::VK_ACCESS_UNIFORM_READ_BIT);
8811 break;
8812 }
8813
8814 case OP_RENDER_FRAGMENT_UNIFORM_BUFFER:
8815 case OP_RENDER_FRAGMENT_UNIFORM_TEXEL_BUFFER:
8816 {
8817 DE_ASSERT(state.stage == STAGE_RENDER_PASS);
8818
8819 state.renderPassIsEmpty = false;
8820 state.cache.perform(vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, vk::VK_ACCESS_UNIFORM_READ_BIT);
8821 break;
8822 }
8823
8824 case OP_RENDER_VERTEX_STORAGE_BUFFER:
8825 case OP_RENDER_VERTEX_STORAGE_TEXEL_BUFFER:
8826 {
8827 DE_ASSERT(state.stage == STAGE_RENDER_PASS);
8828
8829 state.renderPassIsEmpty = false;
8830 state.cache.perform(vk::VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, vk::VK_ACCESS_SHADER_READ_BIT);
8831 break;
8832 }
8833
8834 case OP_RENDER_FRAGMENT_STORAGE_BUFFER:
8835 case OP_RENDER_FRAGMENT_STORAGE_TEXEL_BUFFER:
8836 {
8837 DE_ASSERT(state.stage == STAGE_RENDER_PASS);
8838
8839 state.renderPassIsEmpty = false;
8840 state.cache.perform(vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, vk::VK_ACCESS_SHADER_READ_BIT);
8841 break;
8842 }
8843
8844 case OP_RENDER_FRAGMENT_STORAGE_IMAGE:
8845 case OP_RENDER_FRAGMENT_SAMPLED_IMAGE:
8846 {
8847 DE_ASSERT(state.stage == STAGE_RENDER_PASS);
8848
8849 state.renderPassIsEmpty = false;
8850 state.cache.perform(vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, vk::VK_ACCESS_SHADER_READ_BIT);
8851 break;
8852 }
8853
8854 case OP_RENDER_VERTEX_STORAGE_IMAGE:
8855 case OP_RENDER_VERTEX_SAMPLED_IMAGE:
8856 {
8857 DE_ASSERT(state.stage == STAGE_RENDER_PASS);
8858
8859 state.renderPassIsEmpty = false;
8860 state.cache.perform(vk::VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, vk::VK_ACCESS_SHADER_READ_BIT);
8861 break;
8862 }
8863
8864 default:
8865 DE_FATAL("Unknown op");
8866 }
8867 }
8868
createHostCommand(Op op,de::Random & rng,Usage usage,vk::VkSharingMode sharing)8869 de::MovePtr<Command> createHostCommand (Op op,
8870 de::Random& rng,
8871 Usage usage,
8872 vk::VkSharingMode sharing)
8873 {
8874 switch (op)
8875 {
8876 case OP_MAP: return de::MovePtr<Command>(new Map());
8877 case OP_UNMAP: return de::MovePtr<Command>(new UnMap());
8878
8879 case OP_MAP_FLUSH: return de::MovePtr<Command>(new Flush());
8880 case OP_MAP_INVALIDATE: return de::MovePtr<Command>(new Invalidate());
8881
8882 case OP_MAP_READ: return de::MovePtr<Command>(new HostMemoryAccess(true, false, rng.getUint32()));
8883 case OP_MAP_WRITE: return de::MovePtr<Command>(new HostMemoryAccess(false, true, rng.getUint32()));
8884 case OP_MAP_MODIFY: return de::MovePtr<Command>(new HostMemoryAccess(true, true, rng.getUint32()));
8885
8886 case OP_BUFFER_CREATE: return de::MovePtr<Command>(new CreateBuffer(usageToBufferUsageFlags(usage), sharing));
8887 case OP_BUFFER_DESTROY: return de::MovePtr<Command>(new DestroyBuffer());
8888 case OP_BUFFER_BINDMEMORY: return de::MovePtr<Command>(new BindBufferMemory());
8889
8890 case OP_IMAGE_CREATE: return de::MovePtr<Command>(new CreateImage(usageToImageUsageFlags(usage), sharing));
8891 case OP_IMAGE_DESTROY: return de::MovePtr<Command>(new DestroyImage());
8892 case OP_IMAGE_BINDMEMORY: return de::MovePtr<Command>(new BindImageMemory());
8893
8894 case OP_QUEUE_WAIT_FOR_IDLE: return de::MovePtr<Command>(new QueueWaitIdle());
8895 case OP_DEVICE_WAIT_FOR_IDLE: return de::MovePtr<Command>(new DeviceWaitIdle());
8896
8897 default:
8898 DE_FATAL("Unknown op");
8899 return de::MovePtr<Command>(DE_NULL);
8900 }
8901 }
8902
createCmdCommand(de::Random & rng,const State & state,Op op,Usage usage)8903 de::MovePtr<CmdCommand> createCmdCommand (de::Random& rng,
8904 const State& state,
8905 Op op,
8906 Usage usage)
8907 {
8908 switch (op)
8909 {
8910 case OP_BUFFER_FILL: return de::MovePtr<CmdCommand>(new FillBuffer(rng.getUint32()));
8911 case OP_BUFFER_UPDATE: return de::MovePtr<CmdCommand>(new UpdateBuffer(rng.getUint32()));
8912 case OP_BUFFER_COPY_TO_BUFFER: return de::MovePtr<CmdCommand>(new BufferCopyToBuffer());
8913 case OP_BUFFER_COPY_FROM_BUFFER: return de::MovePtr<CmdCommand>(new BufferCopyFromBuffer(rng.getUint32()));
8914
8915 case OP_BUFFER_COPY_TO_IMAGE: return de::MovePtr<CmdCommand>(new BufferCopyToImage());
8916 case OP_BUFFER_COPY_FROM_IMAGE: return de::MovePtr<CmdCommand>(new BufferCopyFromImage(rng.getUint32()));
8917
8918 case OP_IMAGE_TRANSITION_LAYOUT:
8919 {
8920 DE_ASSERT(state.stage == STAGE_COMMAND_BUFFER || state.stage == STAGE_SECONDARY_COMMAND_BUFFER);
8921 DE_ASSERT(state.hasImage);
8922 DE_ASSERT(state.hasBoundImageMemory);
8923
8924 const vk::VkImageLayout srcLayout = rng.getFloat() < 0.9f ? state.imageLayout : vk::VK_IMAGE_LAYOUT_UNDEFINED;
8925 const vk::VkImageLayout dstLayout = getRandomNextLayout(rng, usage, srcLayout);
8926
8927 vk::VkPipelineStageFlags dirtySrcStages;
8928 vk::VkAccessFlags dirtySrcAccesses;
8929 vk::VkPipelineStageFlags dirtyDstStages;
8930 vk::VkAccessFlags dirtyDstAccesses;
8931
8932 vk::VkPipelineStageFlags srcStages;
8933 vk::VkAccessFlags srcAccesses;
8934 vk::VkPipelineStageFlags dstStages;
8935 vk::VkAccessFlags dstAccesses;
8936
8937 state.cache.getFullBarrier(dirtySrcStages, dirtySrcAccesses, dirtyDstStages, dirtyDstAccesses);
8938
8939 // Try masking some random bits
8940 srcStages = dirtySrcStages;
8941 srcAccesses = dirtySrcAccesses;
8942
8943 dstStages = state.cache.getAllowedStages() & rng.getUint32();
8944 dstAccesses = state.cache.getAllowedAcceses() & rng.getUint32();
8945
8946 // If there are no bits in dst stage mask use all stages
8947 dstStages = dstStages ? dstStages : state.cache.getAllowedStages();
8948
8949 if (!srcStages)
8950 srcStages = dstStages;
8951
8952 removeIllegalAccessFlags(dstAccesses, dstStages);
8953 removeIllegalAccessFlags(srcAccesses, srcStages);
8954
8955 return de::MovePtr<CmdCommand>(new ImageTransition(srcStages, srcAccesses, dstStages, dstAccesses, srcLayout, dstLayout));
8956 }
8957
8958 case OP_IMAGE_COPY_TO_BUFFER: return de::MovePtr<CmdCommand>(new ImageCopyToBuffer(state.imageLayout));
8959 case OP_IMAGE_COPY_FROM_BUFFER: return de::MovePtr<CmdCommand>(new ImageCopyFromBuffer(rng.getUint32(), state.imageLayout));
8960 case OP_IMAGE_COPY_TO_IMAGE: return de::MovePtr<CmdCommand>(new ImageCopyToImage(state.imageLayout));
8961 case OP_IMAGE_COPY_FROM_IMAGE: return de::MovePtr<CmdCommand>(new ImageCopyFromImage(rng.getUint32(), state.imageLayout));
8962 case OP_IMAGE_BLIT_TO_IMAGE:
8963 {
8964 const BlitScale scale = rng.getBool() ? BLIT_SCALE_20 : BLIT_SCALE_10;
8965 return de::MovePtr<CmdCommand>(new ImageBlitToImage(scale, state.imageLayout));
8966 }
8967
8968 case OP_IMAGE_BLIT_FROM_IMAGE:
8969 {
8970 const BlitScale scale = rng.getBool() ? BLIT_SCALE_20 : BLIT_SCALE_10;
8971 return de::MovePtr<CmdCommand>(new ImageBlitFromImage(rng.getUint32(), scale, state.imageLayout));
8972 }
8973
8974 case OP_PIPELINE_BARRIER_GLOBAL:
8975 case OP_PIPELINE_BARRIER_BUFFER:
8976 case OP_PIPELINE_BARRIER_IMAGE:
8977 {
8978 vk::VkPipelineStageFlags dirtySrcStages;
8979 vk::VkAccessFlags dirtySrcAccesses;
8980 vk::VkPipelineStageFlags dirtyDstStages;
8981 vk::VkAccessFlags dirtyDstAccesses;
8982
8983 vk::VkPipelineStageFlags srcStages;
8984 vk::VkAccessFlags srcAccesses;
8985 vk::VkPipelineStageFlags dstStages;
8986 vk::VkAccessFlags dstAccesses;
8987
8988 state.cache.getFullBarrier(dirtySrcStages, dirtySrcAccesses, dirtyDstStages, dirtyDstAccesses);
8989
8990 // Try masking some random bits
8991 srcStages = dirtySrcStages & rng.getUint32();
8992 srcAccesses = dirtySrcAccesses & rng.getUint32();
8993
8994 dstStages = dirtyDstStages & rng.getUint32();
8995 dstAccesses = dirtyDstAccesses & rng.getUint32();
8996
8997 // If there are no bits in stage mask use the original dirty stages
8998 srcStages = srcStages ? srcStages : dirtySrcStages;
8999 dstStages = dstStages ? dstStages : dirtyDstStages;
9000
9001 if (!srcStages)
9002 srcStages = dstStages;
9003
9004 removeIllegalAccessFlags(dstAccesses, dstStages);
9005 removeIllegalAccessFlags(srcAccesses, srcStages);
9006
9007 PipelineBarrier::Type type;
9008
9009 if (op == OP_PIPELINE_BARRIER_IMAGE)
9010 type = PipelineBarrier::TYPE_IMAGE;
9011 else if (op == OP_PIPELINE_BARRIER_BUFFER)
9012 type = PipelineBarrier::TYPE_BUFFER;
9013 else if (op == OP_PIPELINE_BARRIER_GLOBAL)
9014 type = PipelineBarrier::TYPE_GLOBAL;
9015 else
9016 {
9017 type = PipelineBarrier::TYPE_LAST;
9018 DE_FATAL("Unknown op");
9019 }
9020
9021 if (type == PipelineBarrier::TYPE_IMAGE)
9022 return de::MovePtr<CmdCommand>(new PipelineBarrier(srcStages, srcAccesses, dstStages, dstAccesses, type, tcu::just(state.imageLayout)));
9023 else
9024 return de::MovePtr<CmdCommand>(new PipelineBarrier(srcStages, srcAccesses, dstStages, dstAccesses, type, tcu::nothing<vk::VkImageLayout>()));
9025 }
9026
9027 default:
9028 DE_FATAL("Unknown op");
9029 return de::MovePtr<CmdCommand>(DE_NULL);
9030 }
9031 }
9032
createRenderPassCommand(de::Random &,const State &,const TestConfig & testConfig,Op op)9033 de::MovePtr<RenderPassCommand> createRenderPassCommand (de::Random&,
9034 const State&,
9035 const TestConfig& testConfig,
9036 Op op)
9037 {
9038 switch (op)
9039 {
9040 case OP_RENDER_VERTEX_BUFFER: return de::MovePtr<RenderPassCommand>(new RenderVertexBuffer(testConfig.vertexBufferStride));
9041 case OP_RENDER_INDEX_BUFFER: return de::MovePtr<RenderPassCommand>(new RenderIndexBuffer());
9042
9043 case OP_RENDER_VERTEX_UNIFORM_BUFFER: return de::MovePtr<RenderPassCommand>(new RenderVertexUniformBuffer());
9044 case OP_RENDER_FRAGMENT_UNIFORM_BUFFER: return de::MovePtr<RenderPassCommand>(new RenderFragmentUniformBuffer());
9045
9046 case OP_RENDER_VERTEX_UNIFORM_TEXEL_BUFFER: return de::MovePtr<RenderPassCommand>(new RenderVertexUniformTexelBuffer());
9047 case OP_RENDER_FRAGMENT_UNIFORM_TEXEL_BUFFER: return de::MovePtr<RenderPassCommand>(new RenderFragmentUniformTexelBuffer());
9048
9049 case OP_RENDER_VERTEX_STORAGE_BUFFER: return de::MovePtr<RenderPassCommand>(new RenderVertexStorageBuffer());
9050 case OP_RENDER_FRAGMENT_STORAGE_BUFFER: return de::MovePtr<RenderPassCommand>(new RenderFragmentStorageBuffer());
9051
9052 case OP_RENDER_VERTEX_STORAGE_TEXEL_BUFFER: return de::MovePtr<RenderPassCommand>(new RenderVertexStorageTexelBuffer());
9053 case OP_RENDER_FRAGMENT_STORAGE_TEXEL_BUFFER: return de::MovePtr<RenderPassCommand>(new RenderFragmentStorageTexelBuffer());
9054
9055 case OP_RENDER_VERTEX_STORAGE_IMAGE: return de::MovePtr<RenderPassCommand>(new RenderVertexStorageImage());
9056 case OP_RENDER_FRAGMENT_STORAGE_IMAGE: return de::MovePtr<RenderPassCommand>(new RenderFragmentStorageImage());
9057
9058 case OP_RENDER_VERTEX_SAMPLED_IMAGE: return de::MovePtr<RenderPassCommand>(new RenderVertexSampledImage());
9059 case OP_RENDER_FRAGMENT_SAMPLED_IMAGE: return de::MovePtr<RenderPassCommand>(new RenderFragmentSampledImage());
9060
9061 default:
9062 DE_FATAL("Unknown op");
9063 return de::MovePtr<RenderPassCommand>(DE_NULL);
9064 }
9065 }
9066
createRenderPassCommands(const Memory & memory,de::Random & nextOpRng,State & state,const TestConfig & testConfig,size_t & opNdx,size_t opCount)9067 de::MovePtr<CmdCommand> createRenderPassCommands (const Memory& memory,
9068 de::Random& nextOpRng,
9069 State& state,
9070 const TestConfig& testConfig,
9071 size_t& opNdx,
9072 size_t opCount)
9073 {
9074 vector<RenderPassCommand*> commands;
9075
9076 try
9077 {
9078 for (; opNdx < opCount; opNdx++)
9079 {
9080 vector<Op> ops;
9081
9082 getAvailableOps(state, memory.getSupportBuffers(), memory.getSupportImages(), testConfig.usage, ops);
9083
9084 DE_ASSERT(!ops.empty());
9085
9086 {
9087 const Op op = nextOpRng.choose<Op>(ops.begin(), ops.end());
9088
9089 if (op == OP_RENDERPASS_END)
9090 {
9091 break;
9092 }
9093 else
9094 {
9095 de::Random rng (state.rng);
9096
9097 commands.push_back(createRenderPassCommand(rng, state, testConfig, op).release());
9098 applyOp(state, memory, op, testConfig.usage);
9099
9100 DE_ASSERT(state.rng == rng);
9101 }
9102 }
9103 }
9104
9105 applyOp(state, memory, OP_RENDERPASS_END, testConfig.usage);
9106 return de::MovePtr<CmdCommand>(new SubmitRenderPass(commands));
9107 }
9108 catch (...)
9109 {
9110 for (size_t commandNdx = 0; commandNdx < commands.size(); commandNdx++)
9111 delete commands[commandNdx];
9112
9113 throw;
9114 }
9115 }
9116
createSecondaryCmdCommands(const Memory & memory,de::Random & nextOpRng,State & state,Usage usage,size_t & opNdx,size_t opCount)9117 de::MovePtr<CmdCommand> createSecondaryCmdCommands (const Memory& memory,
9118 de::Random& nextOpRng,
9119 State& state,
9120 Usage usage,
9121 size_t& opNdx,
9122 size_t opCount)
9123 {
9124 vector<CmdCommand*> commands;
9125
9126 try
9127 {
9128 for (; opNdx < opCount; opNdx++)
9129 {
9130 vector<Op> ops;
9131
9132 getAvailableOps(state, memory.getSupportBuffers(), memory.getSupportImages(), usage, ops);
9133
9134 DE_ASSERT(!ops.empty());
9135
9136 {
9137 const Op op = nextOpRng.choose<Op>(ops.begin(), ops.end());
9138
9139 if (op == OP_SECONDARY_COMMAND_BUFFER_END)
9140 {
9141 break;
9142 }
9143 else
9144 {
9145 de::Random rng(state.rng);
9146
9147 commands.push_back(createCmdCommand(rng, state, op, usage).release());
9148 applyOp(state, memory, op, usage);
9149
9150 DE_ASSERT(state.rng == rng);
9151 }
9152 }
9153 }
9154
9155 applyOp(state, memory, OP_SECONDARY_COMMAND_BUFFER_END, usage);
9156 return de::MovePtr<CmdCommand>(new ExecuteSecondaryCommandBuffer(commands));
9157 }
9158 catch (...)
9159 {
9160 for (size_t commandNdx = 0; commandNdx < commands.size(); commandNdx++)
9161 delete commands[commandNdx];
9162
9163 throw;
9164 }
9165 }
9166
createCmdCommands(const Memory & memory,de::Random & nextOpRng,State & state,const TestConfig & testConfig,size_t & opNdx,size_t opCount)9167 de::MovePtr<Command> createCmdCommands (const Memory& memory,
9168 de::Random& nextOpRng,
9169 State& state,
9170 const TestConfig& testConfig,
9171 size_t& opNdx,
9172 size_t opCount)
9173 {
9174 vector<CmdCommand*> commands;
9175
9176 try
9177 {
9178 // Insert a mostly-full barrier to order this work wrt previous command buffer.
9179 commands.push_back(new PipelineBarrier(state.cache.getAllowedStages(),
9180 state.cache.getAllowedAcceses(),
9181 state.cache.getAllowedStages(),
9182 state.cache.getAllowedAcceses(),
9183 PipelineBarrier::TYPE_GLOBAL,
9184 tcu::nothing<vk::VkImageLayout>()));
9185
9186 for (; opNdx < opCount; opNdx++)
9187 {
9188 vector<Op> ops;
9189
9190 getAvailableOps(state, memory.getSupportBuffers(), memory.getSupportImages(), testConfig.usage, ops);
9191
9192 DE_ASSERT(!ops.empty());
9193
9194 {
9195 const Op op = nextOpRng.choose<Op>(ops.begin(), ops.end());
9196
9197 if (op == OP_COMMAND_BUFFER_END)
9198 {
9199 break;
9200 }
9201 else
9202 {
9203 // \note Command needs to known the state before the operation
9204 if (op == OP_RENDERPASS_BEGIN)
9205 {
9206 applyOp(state, memory, op, testConfig.usage);
9207 commands.push_back(createRenderPassCommands(memory, nextOpRng, state, testConfig, opNdx, opCount).release());
9208 }
9209 else if (op == OP_SECONDARY_COMMAND_BUFFER_BEGIN)
9210 {
9211 applyOp(state, memory, op, testConfig.usage);
9212 commands.push_back(createSecondaryCmdCommands(memory, nextOpRng, state, testConfig.usage, opNdx, opCount).release());
9213 }
9214 else
9215 {
9216 de::Random rng (state.rng);
9217
9218 commands.push_back(createCmdCommand(rng, state, op, testConfig.usage).release());
9219 applyOp(state, memory, op, testConfig.usage);
9220
9221 DE_ASSERT(state.rng == rng);
9222 }
9223
9224 }
9225 }
9226 }
9227
9228 applyOp(state, memory, OP_COMMAND_BUFFER_END, testConfig.usage);
9229 return de::MovePtr<Command>(new SubmitCommandBuffer(commands));
9230 }
9231 catch (...)
9232 {
9233 for (size_t commandNdx = 0; commandNdx < commands.size(); commandNdx++)
9234 delete commands[commandNdx];
9235
9236 throw;
9237 }
9238 }
9239
createCommands(vector<Command * > & commands,deUint32 seed,const Memory & memory,const TestConfig & testConfig,size_t opCount)9240 void createCommands (vector<Command*>& commands,
9241 deUint32 seed,
9242 const Memory& memory,
9243 const TestConfig& testConfig,
9244 size_t opCount)
9245 {
9246 State state (testConfig.usage, seed);
9247 // Used to select next operation only
9248 de::Random nextOpRng (seed ^ 12930809);
9249
9250 commands.reserve(opCount);
9251
9252 for (size_t opNdx = 0; opNdx < opCount; opNdx++)
9253 {
9254 vector<Op> ops;
9255
9256 getAvailableOps(state, memory.getSupportBuffers(), memory.getSupportImages(), testConfig.usage, ops);
9257
9258 DE_ASSERT(!ops.empty());
9259
9260 {
9261 const Op op = nextOpRng.choose<Op>(ops.begin(), ops.end());
9262
9263 if (op == OP_COMMAND_BUFFER_BEGIN)
9264 {
9265 applyOp(state, memory, op, testConfig.usage);
9266 commands.push_back(createCmdCommands(memory, nextOpRng, state, testConfig, opNdx, opCount).release());
9267 }
9268 else
9269 {
9270 de::Random rng (state.rng);
9271
9272 commands.push_back(createHostCommand(op, rng, testConfig.usage, testConfig.sharing).release());
9273 applyOp(state, memory, op, testConfig.usage);
9274
9275 // Make sure that random generator is in sync
9276 DE_ASSERT(state.rng == rng);
9277 }
9278 }
9279 }
9280
9281 // Clean up resources
9282 if (state.hasBuffer && state.hasImage)
9283 {
9284 if (!state.queueIdle)
9285 commands.push_back(new QueueWaitIdle());
9286
9287 if (state.hasBuffer)
9288 commands.push_back(new DestroyBuffer());
9289
9290 if (state.hasImage)
9291 commands.push_back(new DestroyImage());
9292 }
9293 }
9294
9295 class MemoryTestInstance : public TestInstance
9296 {
9297 public:
9298
9299 typedef bool(MemoryTestInstance::*StageFunc)(void);
9300
9301 MemoryTestInstance (::vkt::Context& context, const TestConfig& config);
9302 ~MemoryTestInstance (void);
9303
9304 tcu::TestStatus iterate (void);
9305
9306 private:
9307 const TestConfig m_config;
9308 const size_t m_iterationCount;
9309 const size_t m_opCount;
9310 const vk::VkPhysicalDeviceMemoryProperties m_memoryProperties;
9311 deUint32 m_memoryTypeNdx;
9312 size_t m_iteration;
9313 StageFunc m_stage;
9314 tcu::ResultCollector m_resultCollector;
9315
9316 vector<Command*> m_commands;
9317 MovePtr<Memory> m_memory;
9318 MovePtr<Context> m_renderContext;
9319 MovePtr<PrepareContext> m_prepareContext;
9320
9321 bool nextIteration (void);
9322 bool nextMemoryType (void);
9323
9324 bool createCommandsAndAllocateMemory (void);
9325 bool prepare (void);
9326 bool execute (void);
9327 bool verify (void);
9328 void resetResources (void);
9329 };
9330
resetResources(void)9331 void MemoryTestInstance::resetResources (void)
9332 {
9333 const vk::DeviceInterface& vkd = m_context.getDeviceInterface();
9334 const vk::VkDevice device = m_context.getDevice();
9335
9336 VK_CHECK(vkd.deviceWaitIdle(device));
9337
9338 for (size_t commandNdx = 0; commandNdx < m_commands.size(); commandNdx++)
9339 {
9340 delete m_commands[commandNdx];
9341 m_commands[commandNdx] = DE_NULL;
9342 }
9343
9344 m_commands.clear();
9345 m_prepareContext.clear();
9346 m_memory.clear();
9347 }
9348
nextIteration(void)9349 bool MemoryTestInstance::nextIteration (void)
9350 {
9351 m_iteration++;
9352
9353 if (m_iteration < m_iterationCount)
9354 {
9355 resetResources();
9356 m_stage = &MemoryTestInstance::createCommandsAndAllocateMemory;
9357 return true;
9358 }
9359 else
9360 return nextMemoryType();
9361 }
9362
nextMemoryType(void)9363 bool MemoryTestInstance::nextMemoryType (void)
9364 {
9365 resetResources();
9366
9367 DE_ASSERT(m_commands.empty());
9368
9369 m_memoryTypeNdx++;
9370
9371 if (m_memoryTypeNdx < m_memoryProperties.memoryTypeCount)
9372 {
9373 m_iteration = 0;
9374 m_stage = &MemoryTestInstance::createCommandsAndAllocateMemory;
9375
9376 return true;
9377 }
9378 else
9379 {
9380 m_stage = DE_NULL;
9381 return false;
9382 }
9383 }
9384
MemoryTestInstance(::vkt::Context & context,const TestConfig & config)9385 MemoryTestInstance::MemoryTestInstance (::vkt::Context& context, const TestConfig& config)
9386 : TestInstance (context)
9387 , m_config (config)
9388 , m_iterationCount (5)
9389 , m_opCount (50)
9390 , m_memoryProperties (vk::getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()))
9391 , m_memoryTypeNdx (0)
9392 , m_iteration (0)
9393 , m_stage (&MemoryTestInstance::createCommandsAndAllocateMemory)
9394 , m_resultCollector (context.getTestContext().getLog())
9395
9396 , m_memory (DE_NULL)
9397 {
9398 TestLog& log = context.getTestContext().getLog();
9399 {
9400 const tcu::ScopedLogSection section (log, "TestCaseInfo", "Test Case Info");
9401
9402 log << TestLog::Message << "Buffer size: " << config.size << TestLog::EndMessage;
9403 log << TestLog::Message << "Sharing: " << config.sharing << TestLog::EndMessage;
9404 log << TestLog::Message << "Access: " << config.usage << TestLog::EndMessage;
9405 }
9406
9407 {
9408 const tcu::ScopedLogSection section (log, "MemoryProperties", "Memory Properties");
9409
9410 for (deUint32 heapNdx = 0; heapNdx < m_memoryProperties.memoryHeapCount; heapNdx++)
9411 {
9412 const tcu::ScopedLogSection heapSection (log, "Heap" + de::toString(heapNdx), "Heap " + de::toString(heapNdx));
9413
9414 log << TestLog::Message << "Size: " << m_memoryProperties.memoryHeaps[heapNdx].size << TestLog::EndMessage;
9415 log << TestLog::Message << "Flags: " << m_memoryProperties.memoryHeaps[heapNdx].flags << TestLog::EndMessage;
9416 }
9417
9418 for (deUint32 memoryTypeNdx = 0; memoryTypeNdx < m_memoryProperties.memoryTypeCount; memoryTypeNdx++)
9419 {
9420 const tcu::ScopedLogSection memoryTypeSection (log, "MemoryType" + de::toString(memoryTypeNdx), "Memory type " + de::toString(memoryTypeNdx));
9421
9422 log << TestLog::Message << "Properties: " << m_memoryProperties.memoryTypes[memoryTypeNdx].propertyFlags << TestLog::EndMessage;
9423 log << TestLog::Message << "Heap: " << m_memoryProperties.memoryTypes[memoryTypeNdx].heapIndex << TestLog::EndMessage;
9424 }
9425 }
9426
9427 {
9428 const vk::InstanceInterface& vki = context.getInstanceInterface();
9429 const vk::VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
9430 const vk::DeviceInterface& vkd = context.getDeviceInterface();
9431 const vk::VkDevice device = context.getDevice();
9432 const vk::VkQueue queue = context.getUniversalQueue();
9433 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
9434 vector<pair<deUint32, vk::VkQueue> > queues;
9435
9436 queues.push_back(std::make_pair(queueFamilyIndex, queue));
9437
9438 m_renderContext = MovePtr<Context>(new Context(vki, vkd, physicalDevice, device, queue, queueFamilyIndex, queues, context.getBinaryCollection()));
9439 }
9440 }
9441
~MemoryTestInstance(void)9442 MemoryTestInstance::~MemoryTestInstance (void)
9443 {
9444 resetResources();
9445 }
9446
createCommandsAndAllocateMemory(void)9447 bool MemoryTestInstance::createCommandsAndAllocateMemory (void)
9448 {
9449 const vk::VkDevice device = m_context.getDevice();
9450 TestLog& log = m_context.getTestContext().getLog();
9451 const vk::InstanceInterface& vki = m_context.getInstanceInterface();
9452 const vk::VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
9453 const vk::DeviceInterface& vkd = m_context.getDeviceInterface();
9454 const vk::VkPhysicalDeviceMemoryProperties memoryProperties = vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice);
9455 const tcu::ScopedLogSection section (log, "MemoryType" + de::toString(m_memoryTypeNdx) + "CreateCommands" + de::toString(m_iteration),
9456 "Memory type " + de::toString(m_memoryTypeNdx) + " create commands iteration " + de::toString(m_iteration));
9457 const vector<deUint32>& queues = m_renderContext->getQueueFamilies();
9458
9459 DE_ASSERT(m_commands.empty());
9460
9461 if (m_config.usage & (USAGE_HOST_READ | USAGE_HOST_WRITE)
9462 && !(memoryProperties.memoryTypes[m_memoryTypeNdx].propertyFlags & vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT))
9463 {
9464 log << TestLog::Message << "Memory type not supported" << TestLog::EndMessage;
9465
9466 return nextMemoryType();
9467 }
9468 else
9469 {
9470 try
9471 {
9472 const vk::VkBufferUsageFlags bufferUsage = usageToBufferUsageFlags(m_config.usage);
9473 const vk::VkImageUsageFlags imageUsage = usageToImageUsageFlags(m_config.usage);
9474 const vk::VkDeviceSize maxBufferSize = bufferUsage != 0
9475 ? roundBufferSizeToWxHx4(findMaxBufferSize(vkd, device, bufferUsage, m_config.sharing, queues, m_config.size, m_memoryTypeNdx))
9476 : 0;
9477 const IVec2 maxImageSize = imageUsage != 0
9478 ? findMaxRGBA8ImageSize(vkd, device, imageUsage, m_config.sharing, queues, m_config.size, m_memoryTypeNdx)
9479 : IVec2(0, 0);
9480
9481 log << TestLog::Message << "Max buffer size: " << maxBufferSize << TestLog::EndMessage;
9482 log << TestLog::Message << "Max RGBA8 image size: " << maxImageSize << TestLog::EndMessage;
9483
9484 // Skip tests if there are no supported operations
9485 if (maxBufferSize == 0
9486 && maxImageSize[0] == 0
9487 && (m_config.usage & (USAGE_HOST_READ|USAGE_HOST_WRITE)) == 0)
9488 {
9489 log << TestLog::Message << "Skipping memory type. None of the usages are supported." << TestLog::EndMessage;
9490
9491 return nextMemoryType();
9492 }
9493 else
9494 {
9495 const deUint32 seed = 2830980989u ^ deUint32Hash((deUint32)(m_iteration) * m_memoryProperties.memoryTypeCount + m_memoryTypeNdx);
9496
9497 m_memory = MovePtr<Memory>(new Memory(vki, vkd, physicalDevice, device, m_config.size, m_memoryTypeNdx, maxBufferSize, maxImageSize[0], maxImageSize[1]));
9498
9499 log << TestLog::Message << "Create commands" << TestLog::EndMessage;
9500 createCommands(m_commands, seed, *m_memory, m_config, m_opCount);
9501
9502 m_stage = &MemoryTestInstance::prepare;
9503 return true;
9504 }
9505 }
9506 catch (const tcu::TestError& e)
9507 {
9508 m_resultCollector.fail("Failed, got exception: " + string(e.getMessage()));
9509 return nextMemoryType();
9510 }
9511 }
9512 }
9513
prepare(void)9514 bool MemoryTestInstance::prepare (void)
9515 {
9516 TestLog& log = m_context.getTestContext().getLog();
9517 const tcu::ScopedLogSection section (log, "MemoryType" + de::toString(m_memoryTypeNdx) + "Prepare" + de::toString(m_iteration),
9518 "Memory type " + de::toString(m_memoryTypeNdx) + " prepare iteration " + de::toString(m_iteration));
9519
9520 m_prepareContext = MovePtr<PrepareContext>(new PrepareContext(*m_renderContext, *m_memory));
9521
9522 DE_ASSERT(!m_commands.empty());
9523
9524 for (size_t cmdNdx = 0; cmdNdx < m_commands.size(); cmdNdx++)
9525 {
9526 Command& command = *m_commands[cmdNdx];
9527
9528 try
9529 {
9530 command.prepare(*m_prepareContext);
9531 }
9532 catch (const tcu::TestError& e)
9533 {
9534 m_resultCollector.fail(de::toString(cmdNdx) + ":" + command.getName() + " failed to prepare, got exception: " + string(e.getMessage()));
9535 return nextMemoryType();
9536 }
9537 }
9538
9539 m_stage = &MemoryTestInstance::execute;
9540 return true;
9541 }
9542
execute(void)9543 bool MemoryTestInstance::execute (void)
9544 {
9545 TestLog& log = m_context.getTestContext().getLog();
9546 const tcu::ScopedLogSection section (log, "MemoryType" + de::toString(m_memoryTypeNdx) + "Execute" + de::toString(m_iteration),
9547 "Memory type " + de::toString(m_memoryTypeNdx) + " execute iteration " + de::toString(m_iteration));
9548 ExecuteContext executeContext (*m_renderContext);
9549 const vk::VkDevice device = m_context.getDevice();
9550 const vk::DeviceInterface& vkd = m_context.getDeviceInterface();
9551
9552 DE_ASSERT(!m_commands.empty());
9553
9554 for (size_t cmdNdx = 0; cmdNdx < m_commands.size(); cmdNdx++)
9555 {
9556 Command& command = *m_commands[cmdNdx];
9557
9558 try
9559 {
9560 command.execute(executeContext);
9561 }
9562 catch (const tcu::TestError& e)
9563 {
9564 m_resultCollector.fail(de::toString(cmdNdx) + ":" + command.getName() + " failed to execute, got exception: " + string(e.getMessage()));
9565 return nextIteration();
9566 }
9567 }
9568
9569 VK_CHECK(vkd.deviceWaitIdle(device));
9570
9571 m_stage = &MemoryTestInstance::verify;
9572 return true;
9573 }
9574
verify(void)9575 bool MemoryTestInstance::verify (void)
9576 {
9577 DE_ASSERT(!m_commands.empty());
9578
9579 TestLog& log = m_context.getTestContext().getLog();
9580 const tcu::ScopedLogSection section (log, "MemoryType" + de::toString(m_memoryTypeNdx) + "Verify" + de::toString(m_iteration),
9581 "Memory type " + de::toString(m_memoryTypeNdx) + " verify iteration " + de::toString(m_iteration));
9582 VerifyContext verifyContext (log, m_resultCollector, *m_renderContext, m_config.size);
9583
9584 log << TestLog::Message << "Begin verify" << TestLog::EndMessage;
9585
9586 for (size_t cmdNdx = 0; cmdNdx < m_commands.size(); cmdNdx++)
9587 {
9588 Command& command = *m_commands[cmdNdx];
9589
9590 try
9591 {
9592 command.verify(verifyContext, cmdNdx);
9593 }
9594 catch (const tcu::TestError& e)
9595 {
9596 m_resultCollector.fail(de::toString(cmdNdx) + ":" + command.getName() + " failed to verify, got exception: " + string(e.getMessage()));
9597 return nextIteration();
9598 }
9599 }
9600
9601 return nextIteration();
9602 }
9603
iterate(void)9604 tcu::TestStatus MemoryTestInstance::iterate (void)
9605 {
9606 if ((this->*m_stage)())
9607 return tcu::TestStatus::incomplete();
9608 else
9609 return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
9610 }
9611
9612 struct AddPrograms
9613 {
initvkt::memory::__anon58c89e6c0111::AddPrograms9614 void init (vk::SourceCollections& sources, TestConfig config) const
9615 {
9616 // Vertex buffer rendering
9617 if (config.usage & USAGE_VERTEX_BUFFER)
9618 {
9619 const char* const vertexShader =
9620 "#version 310 es\n"
9621 "layout(location = 0) in highp vec2 a_position;\n"
9622 "void main (void) {\n"
9623 "\tgl_PointSize = 1.0;\n"
9624 "\tgl_Position = vec4(1.998 * a_position - vec2(0.999), 0.0, 1.0);\n"
9625 "}\n";
9626
9627 sources.glslSources.add("vertex-buffer.vert")
9628 << glu::VertexSource(vertexShader);
9629 }
9630
9631 // Index buffer rendering
9632 if (config.usage & USAGE_INDEX_BUFFER)
9633 {
9634 const char* const vertexShader =
9635 "#version 310 es\n"
9636 "precision highp float;\n"
9637 "void main (void) {\n"
9638 "\tgl_PointSize = 1.0;\n"
9639 "\thighp vec2 pos = vec2(gl_VertexIndex % 256, gl_VertexIndex / 256) / vec2(255.0);\n"
9640 "\tgl_Position = vec4(1.998 * pos - vec2(0.999), 0.0, 1.0);\n"
9641 "}\n";
9642
9643 sources.glslSources.add("index-buffer.vert")
9644 << glu::VertexSource(vertexShader);
9645 }
9646
9647 if (config.usage & USAGE_UNIFORM_BUFFER)
9648 {
9649 {
9650 std::ostringstream vertexShader;
9651
9652 vertexShader <<
9653 "#version 310 es\n"
9654 "precision highp float;\n"
9655 "layout(set=0, binding=0) uniform Block\n"
9656 "{\n"
9657 "\thighp uvec4 values[" << de::toString<size_t>(MAX_UNIFORM_BUFFER_SIZE / (sizeof(deUint32) * 4)) << "];\n"
9658 "} block;\n"
9659 "void main (void) {\n"
9660 "\tgl_PointSize = 1.0;\n"
9661 "\thighp uvec4 vecVal = block.values[gl_VertexIndex / 8];\n"
9662 "\thighp uint val;\n"
9663 "\tif (((gl_VertexIndex / 2) % 4 == 0))\n"
9664 "\t\tval = vecVal.x;\n"
9665 "\telse if (((gl_VertexIndex / 2) % 4 == 1))\n"
9666 "\t\tval = vecVal.y;\n"
9667 "\telse if (((gl_VertexIndex / 2) % 4 == 2))\n"
9668 "\t\tval = vecVal.z;\n"
9669 "\telse if (((gl_VertexIndex / 2) % 4 == 3))\n"
9670 "\t\tval = vecVal.w;\n"
9671 "\tif ((gl_VertexIndex % 2) == 0)\n"
9672 "\t\tval = val & 0xFFFFu;\n"
9673 "\telse\n"
9674 "\t\tval = val >> 16u;\n"
9675 "\thighp vec2 pos = vec2(val & 0xFFu, val >> 8u) / vec2(255.0);\n"
9676 "\tgl_Position = vec4(1.998 * pos - vec2(0.999), 0.0, 1.0);\n"
9677 "}\n";
9678
9679 sources.glslSources.add("uniform-buffer.vert")
9680 << glu::VertexSource(vertexShader.str());
9681 }
9682
9683 {
9684 const size_t arraySize = MAX_UNIFORM_BUFFER_SIZE / (sizeof(deUint32) * 4);
9685 const size_t arrayIntSize = arraySize * 4;
9686 std::ostringstream fragmentShader;
9687
9688 fragmentShader <<
9689 "#version 310 es\n"
9690 "precision highp float;\n"
9691 "precision highp int;\n"
9692 "layout(location = 0) out highp vec4 o_color;\n"
9693 "layout(set=0, binding=0) uniform Block\n"
9694 "{\n"
9695 "\thighp uvec4 values[" << arraySize << "];\n"
9696 "} block;\n"
9697 "layout(push_constant) uniform PushC\n"
9698 "{\n"
9699 "\tuint callId;\n"
9700 "\tuint valuesPerPixel;\n"
9701 "\tuint bufferSize;\n"
9702 "} pushC;\n"
9703 "void main (void) {\n"
9704 "\thighp uint id = uint(gl_FragCoord.y) * 256u + uint(gl_FragCoord.x);\n"
9705 "\tif (uint(gl_FragCoord.y) * 256u + uint(gl_FragCoord.x) < pushC.callId * (" << arrayIntSize << "u / pushC.valuesPerPixel))\n"
9706 "\t\tdiscard;\n"
9707 "\thighp uint value = id;\n"
9708 "\tfor (uint i = 0u; i < pushC.valuesPerPixel; i++)\n"
9709 "\t{\n"
9710 "\t\thighp uvec4 vecVal = block.values[value % pushC.bufferSize];\n"
9711 "\t\tif ((value % 4u) == 0u)\n"
9712 "\t\t\tvalue = vecVal.x;\n"
9713 "\t\telse if ((value % 4u) == 1u)\n"
9714 "\t\t\tvalue = vecVal.y;\n"
9715 "\t\telse if ((value % 4u) == 2u)\n"
9716 "\t\t\tvalue = vecVal.z;\n"
9717 "\t\telse if ((value % 4u) == 3u)\n"
9718 "\t\t\tvalue = vecVal.w;\n"
9719 "\t}\n"
9720 "\tuvec4 valueOut = uvec4(value & 0xFFu, (value >> 8u) & 0xFFu, (value >> 16u) & 0xFFu, (value >> 24u) & 0xFFu);\n"
9721 "\to_color = vec4(valueOut) / vec4(255.0);\n"
9722 "}\n";
9723
9724 sources.glslSources.add("uniform-buffer.frag")
9725 << glu::FragmentSource(fragmentShader.str());
9726 }
9727 }
9728
9729 if (config.usage & USAGE_STORAGE_BUFFER)
9730 {
9731 {
9732 // Vertex storage buffer rendering
9733 const char* const vertexShader =
9734 "#version 310 es\n"
9735 "precision highp float;\n"
9736 "readonly layout(set=0, binding=0) buffer Block\n"
9737 "{\n"
9738 "\thighp uvec4 values[];\n"
9739 "} block;\n"
9740 "void main (void) {\n"
9741 "\tgl_PointSize = 1.0;\n"
9742 "\thighp uvec4 vecVal = block.values[gl_VertexIndex / 8];\n"
9743 "\thighp uint val;\n"
9744 "\tif (((gl_VertexIndex / 2) % 4 == 0))\n"
9745 "\t\tval = vecVal.x;\n"
9746 "\telse if (((gl_VertexIndex / 2) % 4 == 1))\n"
9747 "\t\tval = vecVal.y;\n"
9748 "\telse if (((gl_VertexIndex / 2) % 4 == 2))\n"
9749 "\t\tval = vecVal.z;\n"
9750 "\telse if (((gl_VertexIndex / 2) % 4 == 3))\n"
9751 "\t\tval = vecVal.w;\n"
9752 "\tif ((gl_VertexIndex % 2) == 0)\n"
9753 "\t\tval = val & 0xFFFFu;\n"
9754 "\telse\n"
9755 "\t\tval = val >> 16u;\n"
9756 "\thighp vec2 pos = vec2(val & 0xFFu, val >> 8u) / vec2(255.0);\n"
9757 "\tgl_Position = vec4(1.998 * pos - vec2(0.999), 0.0, 1.0);\n"
9758 "}\n";
9759
9760 sources.glslSources.add("storage-buffer.vert")
9761 << glu::VertexSource(vertexShader);
9762 }
9763
9764 {
9765 std::ostringstream fragmentShader;
9766
9767 fragmentShader <<
9768 "#version 310 es\n"
9769 "precision highp float;\n"
9770 "precision highp int;\n"
9771 "layout(location = 0) out highp vec4 o_color;\n"
9772 "layout(set=0, binding=0) buffer Block\n"
9773 "{\n"
9774 "\thighp uvec4 values[];\n"
9775 "} block;\n"
9776 "layout(push_constant) uniform PushC\n"
9777 "{\n"
9778 "\tuint valuesPerPixel;\n"
9779 "\tuint bufferSize;\n"
9780 "} pushC;\n"
9781 "void main (void) {\n"
9782 "\thighp uint arrayIntSize = pushC.bufferSize / 4u;\n"
9783 "\thighp uint id = uint(gl_FragCoord.y) * 256u + uint(gl_FragCoord.x);\n"
9784 "\thighp uint value = id;\n"
9785 "\tfor (uint i = 0u; i < pushC.valuesPerPixel; i++)\n"
9786 "\t{\n"
9787 "\t\thighp uvec4 vecVal = block.values[(value / 4u) % (arrayIntSize / 4u)];\n"
9788 "\t\tif ((value % 4u) == 0u)\n"
9789 "\t\t\tvalue = vecVal.x;\n"
9790 "\t\telse if ((value % 4u) == 1u)\n"
9791 "\t\t\tvalue = vecVal.y;\n"
9792 "\t\telse if ((value % 4u) == 2u)\n"
9793 "\t\t\tvalue = vecVal.z;\n"
9794 "\t\telse if ((value % 4u) == 3u)\n"
9795 "\t\t\tvalue = vecVal.w;\n"
9796 "\t}\n"
9797 "\tuvec4 valueOut = uvec4(value & 0xFFu, (value >> 8u) & 0xFFu, (value >> 16u) & 0xFFu, (value >> 24u) & 0xFFu);\n"
9798 "\to_color = vec4(valueOut) / vec4(255.0);\n"
9799 "}\n";
9800
9801 sources.glslSources.add("storage-buffer.frag")
9802 << glu::FragmentSource(fragmentShader.str());
9803 }
9804 }
9805
9806 if (config.usage & USAGE_UNIFORM_TEXEL_BUFFER)
9807 {
9808 {
9809 // Vertex uniform texel buffer rendering
9810 const char* const vertexShader =
9811 "#version 310 es\n"
9812 "#extension GL_EXT_texture_buffer : require\n"
9813 "precision highp float;\n"
9814 "layout(set=0, binding=0) uniform highp utextureBuffer u_sampler;\n"
9815 "void main (void) {\n"
9816 "\tgl_PointSize = 1.0;\n"
9817 "\thighp uint val = texelFetch(u_sampler, gl_VertexIndex).x;\n"
9818 "\thighp vec2 pos = vec2(val & 0xFFu, val >> 8u) / vec2(255.0);\n"
9819 "\tgl_Position = vec4(1.998 * pos - vec2(0.999), 0.0, 1.0);\n"
9820 "}\n";
9821
9822 sources.glslSources.add("uniform-texel-buffer.vert")
9823 << glu::VertexSource(vertexShader);
9824 }
9825
9826 {
9827 // Fragment uniform texel buffer rendering
9828 const char* const fragmentShader =
9829 "#version 310 es\n"
9830 "#extension GL_EXT_texture_buffer : require\n"
9831 "#extension GL_EXT_samplerless_texture_functions : require\n"
9832 "precision highp float;\n"
9833 "precision highp int;\n"
9834 "layout(set=0, binding=0) uniform highp utextureBuffer u_sampler;\n"
9835 "layout(location = 0) out highp vec4 o_color;\n"
9836 "layout(push_constant) uniform PushC\n"
9837 "{\n"
9838 "\tuint callId;\n"
9839 "\tuint valuesPerPixel;\n"
9840 "\tuint maxTexelCount;\n"
9841 "} pushC;\n"
9842 "void main (void) {\n"
9843 "\thighp uint id = uint(gl_FragCoord.y) * 256u + uint(gl_FragCoord.x);\n"
9844 "\thighp uint value = id;\n"
9845 "\tif (uint(gl_FragCoord.y) * 256u + uint(gl_FragCoord.x) < pushC.callId * (pushC.maxTexelCount / pushC.valuesPerPixel))\n"
9846 "\t\tdiscard;\n"
9847 "\tfor (uint i = 0u; i < pushC.valuesPerPixel; i++)\n"
9848 "\t{\n"
9849 "\t\tvalue = texelFetch(u_sampler, int(value % uint(textureSize(u_sampler)))).x;\n"
9850 "\t}\n"
9851 "\tuvec4 valueOut = uvec4(value & 0xFFu, (value >> 8u) & 0xFFu, (value >> 16u) & 0xFFu, (value >> 24u) & 0xFFu);\n"
9852 "\to_color = vec4(valueOut) / vec4(255.0);\n"
9853 "}\n";
9854
9855 sources.glslSources.add("uniform-texel-buffer.frag")
9856 << glu::FragmentSource(fragmentShader);
9857 }
9858 }
9859
9860 if (config.usage & USAGE_STORAGE_TEXEL_BUFFER)
9861 {
9862 {
9863 // Vertex storage texel buffer rendering
9864 const char* const vertexShader =
9865 "#version 450\n"
9866 "#extension GL_EXT_texture_buffer : require\n"
9867 "precision highp float;\n"
9868 "layout(set=0, binding=0, r32ui) uniform readonly highp uimageBuffer u_sampler;\n"
9869 "out gl_PerVertex {\n"
9870 "\tvec4 gl_Position;\n"
9871 "\tfloat gl_PointSize;\n"
9872 "};\n"
9873 "void main (void) {\n"
9874 "\tgl_PointSize = 1.0;\n"
9875 "\thighp uint val = imageLoad(u_sampler, gl_VertexIndex / 2).x;\n"
9876 "\tif (gl_VertexIndex % 2 == 0)\n"
9877 "\t\tval = val & 0xFFFFu;\n"
9878 "\telse\n"
9879 "\t\tval = val >> 16;\n"
9880 "\thighp vec2 pos = vec2(val & 0xFFu, val >> 8u) / vec2(255.0);\n"
9881 "\tgl_Position = vec4(1.998 * pos - vec2(0.999), 0.0, 1.0);\n"
9882 "}\n";
9883
9884 sources.glslSources.add("storage-texel-buffer.vert")
9885 << glu::VertexSource(vertexShader);
9886 }
9887 {
9888 // Fragment storage texel buffer rendering
9889 const char* const fragmentShader =
9890 "#version 310 es\n"
9891 "#extension GL_EXT_texture_buffer : require\n"
9892 "precision highp float;\n"
9893 "precision highp int;\n"
9894 "layout(set=0, binding=0, r32ui) uniform readonly highp uimageBuffer u_sampler;\n"
9895 "layout(location = 0) out highp vec4 o_color;\n"
9896 "layout(push_constant) uniform PushC\n"
9897 "{\n"
9898 "\tuint callId;\n"
9899 "\tuint valuesPerPixel;\n"
9900 "\tuint maxTexelCount;\n"
9901 "\tuint width;\n"
9902 "} pushC;\n"
9903 "void main (void) {\n"
9904 "\thighp uint id = uint(gl_FragCoord.y) * 256u + uint(gl_FragCoord.x);\n"
9905 "\thighp uint value = id;\n"
9906 "\tif (uint(gl_FragCoord.y) * 256u + uint(gl_FragCoord.x) < pushC.callId * (pushC.maxTexelCount / pushC.valuesPerPixel))\n"
9907 "\t\tdiscard;\n"
9908 "\tfor (uint i = 0u; i < pushC.valuesPerPixel; i++)\n"
9909 "\t{\n"
9910 "\t\tvalue = imageLoad(u_sampler, int(value % pushC.width)).x;\n"
9911 "\t}\n"
9912 "\tuvec4 valueOut = uvec4(value & 0xFFu, (value >> 8u) & 0xFFu, (value >> 16u) & 0xFFu, (value >> 24u) & 0xFFu);\n"
9913 "\to_color = vec4(valueOut) / vec4(255.0);\n"
9914 "}\n";
9915
9916 sources.glslSources.add("storage-texel-buffer.frag")
9917 << glu::FragmentSource(fragmentShader);
9918 }
9919 }
9920
9921 if (config.usage & USAGE_STORAGE_IMAGE)
9922 {
9923 {
9924 // Vertex storage image
9925 const char* const vertexShader =
9926 "#version 450\n"
9927 "precision highp float;\n"
9928 "layout(set=0, binding=0, rgba8) uniform image2D u_image;\n"
9929 "out gl_PerVertex {\n"
9930 "\tvec4 gl_Position;\n"
9931 "\tfloat gl_PointSize;\n"
9932 "};\n"
9933 "void main (void) {\n"
9934 "\tgl_PointSize = 1.0;\n"
9935 "\thighp vec4 val = imageLoad(u_image, ivec2((gl_VertexIndex / 2) / imageSize(u_image).x, (gl_VertexIndex / 2) % imageSize(u_image).x));\n"
9936 "\thighp vec2 pos;\n"
9937 "\tif (gl_VertexIndex % 2 == 0)\n"
9938 "\t\tpos = val.xy;\n"
9939 "\telse\n"
9940 "\t\tpos = val.zw;\n"
9941 "\tgl_Position = vec4(1.998 * pos - vec2(0.999), 0.0, 1.0);\n"
9942 "}\n";
9943
9944 sources.glslSources.add("storage-image.vert")
9945 << glu::VertexSource(vertexShader);
9946 }
9947 {
9948 // Fragment storage image
9949 const char* const fragmentShader =
9950 "#version 450\n"
9951 "#extension GL_EXT_texture_buffer : require\n"
9952 "precision highp float;\n"
9953 "layout(set=0, binding=0, rgba8) uniform image2D u_image;\n"
9954 "layout(location = 0) out highp vec4 o_color;\n"
9955 "void main (void) {\n"
9956 "\thighp uvec2 size = uvec2(imageSize(u_image).x, imageSize(u_image).y);\n"
9957 "\thighp uint valuesPerPixel = max(1u, (size.x * size.y) / (256u * 256u));\n"
9958 "\thighp uvec4 value = uvec4(uint(gl_FragCoord.x), uint(gl_FragCoord.y), 0u, 0u);\n"
9959 "\tfor (uint i = 0u; i < valuesPerPixel; i++)\n"
9960 "\t{\n"
9961 "\t\thighp vec4 floatValue = imageLoad(u_image, ivec2(int((value.z * 256u + (value.x ^ value.z)) % size.x), int((value.w * 256u + (value.y ^ value.w)) % size.y)));\n"
9962 "\t\tvalue = uvec4(uint(round(floatValue.x * 255.0)), uint(round(floatValue.y * 255.0)), uint(round(floatValue.z * 255.0)), uint(round(floatValue.w * 255.0)));\n"
9963 "\t}\n"
9964 "\to_color = vec4(value) / vec4(255.0);\n"
9965 "}\n";
9966
9967 sources.glslSources.add("storage-image.frag")
9968 << glu::FragmentSource(fragmentShader);
9969 }
9970 }
9971
9972 if (config.usage & USAGE_SAMPLED_IMAGE)
9973 {
9974 {
9975 // Vertex storage image
9976 const char* const vertexShader =
9977 "#version 450\n"
9978 "precision highp float;\n"
9979 "layout(set=0, binding=0) uniform sampler2D u_sampler;\n"
9980 "out gl_PerVertex {\n"
9981 "\tvec4 gl_Position;\n"
9982 "\tfloat gl_PointSize;\n"
9983 "};\n"
9984 "void main (void) {\n"
9985 "\tgl_PointSize = 1.0;\n"
9986 "\thighp vec4 val = texelFetch(u_sampler, ivec2((gl_VertexIndex / 2) / textureSize(u_sampler, 0).x, (gl_VertexIndex / 2) % textureSize(u_sampler, 0).x), 0);\n"
9987 "\thighp vec2 pos;\n"
9988 "\tif (gl_VertexIndex % 2 == 0)\n"
9989 "\t\tpos = val.xy;\n"
9990 "\telse\n"
9991 "\t\tpos = val.zw;\n"
9992 "\tgl_Position = vec4(1.998 * pos - vec2(0.999), 0.0, 1.0);\n"
9993 "}\n";
9994
9995 sources.glslSources.add("sampled-image.vert")
9996 << glu::VertexSource(vertexShader);
9997 }
9998 {
9999 // Fragment storage image
10000 const char* const fragmentShader =
10001 "#version 450\n"
10002 "#extension GL_EXT_texture_buffer : require\n"
10003 "precision highp float;\n"
10004 "layout(set=0, binding=0) uniform sampler2D u_sampler;\n"
10005 "layout(location = 0) out highp vec4 o_color;\n"
10006 "void main (void) {\n"
10007 "\thighp uvec2 size = uvec2(textureSize(u_sampler, 0).x, textureSize(u_sampler, 0).y);\n"
10008 "\thighp uint valuesPerPixel = max(1u, (size.x * size.y) / (256u * 256u));\n"
10009 "\thighp uvec4 value = uvec4(uint(gl_FragCoord.x), uint(gl_FragCoord.y), 0u, 0u);\n"
10010 "\tfor (uint i = 0u; i < valuesPerPixel; i++)\n"
10011 "\t{\n"
10012 "\t\thighp vec4 floatValue = texelFetch(u_sampler, ivec2(int((value.z * 256u + (value.x ^ value.z)) % size.x), int((value.w * 256u + (value.y ^ value.w)) % size.y)), 0);\n"
10013 "\t\tvalue = uvec4(uint(round(floatValue.x * 255.0)), uint(round(floatValue.y * 255.0)), uint(round(floatValue.z * 255.0)), uint(round(floatValue.w * 255.0)));\n"
10014 "\t}\n"
10015 "\to_color = vec4(value) / vec4(255.0);\n"
10016 "}\n";
10017
10018 sources.glslSources.add("sampled-image.frag")
10019 << glu::FragmentSource(fragmentShader);
10020 }
10021 }
10022
10023 {
10024 const char* const vertexShader =
10025 "#version 450\n"
10026 "out gl_PerVertex {\n"
10027 "\tvec4 gl_Position;\n"
10028 "};\n"
10029 "precision highp float;\n"
10030 "void main (void) {\n"
10031 "\tgl_Position = vec4(((gl_VertexIndex + 2) / 3) % 2 == 0 ? -1.0 : 1.0,\n"
10032 "\t ((gl_VertexIndex + 1) / 3) % 2 == 0 ? -1.0 : 1.0, 0.0, 1.0);\n"
10033 "}\n";
10034
10035 sources.glslSources.add("render-quad.vert")
10036 << glu::VertexSource(vertexShader);
10037 }
10038
10039 {
10040 const char* const fragmentShader =
10041 "#version 310 es\n"
10042 "layout(location = 0) out highp vec4 o_color;\n"
10043 "void main (void) {\n"
10044 "\to_color = vec4(1.0);\n"
10045 "}\n";
10046
10047 sources.glslSources.add("render-white.frag")
10048 << glu::FragmentSource(fragmentShader);
10049 }
10050 }
10051 };
10052
10053 } // anonymous
10054
createPipelineBarrierTests(tcu::TestContext & testCtx)10055 tcu::TestCaseGroup* createPipelineBarrierTests (tcu::TestContext& testCtx)
10056 {
10057 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "pipeline_barrier", "Pipeline barrier tests."));
10058 const vk::VkDeviceSize sizes[] =
10059 {
10060 1024, // 1K
10061 8*1024, // 8K
10062 64*1024, // 64K
10063 ONE_MEGABYTE, // 1M
10064 };
10065 const Usage usages[] =
10066 {
10067 USAGE_HOST_READ,
10068 USAGE_HOST_WRITE,
10069 USAGE_TRANSFER_SRC,
10070 USAGE_TRANSFER_DST,
10071 USAGE_VERTEX_BUFFER,
10072 USAGE_INDEX_BUFFER,
10073 USAGE_UNIFORM_BUFFER,
10074 USAGE_UNIFORM_TEXEL_BUFFER,
10075 USAGE_STORAGE_BUFFER,
10076 USAGE_STORAGE_TEXEL_BUFFER,
10077 USAGE_STORAGE_IMAGE,
10078 USAGE_SAMPLED_IMAGE
10079 };
10080 const Usage readUsages[] =
10081 {
10082 USAGE_HOST_READ,
10083 USAGE_TRANSFER_SRC,
10084 USAGE_VERTEX_BUFFER,
10085 USAGE_INDEX_BUFFER,
10086 USAGE_UNIFORM_BUFFER,
10087 USAGE_UNIFORM_TEXEL_BUFFER,
10088 USAGE_STORAGE_BUFFER,
10089 USAGE_STORAGE_TEXEL_BUFFER,
10090 USAGE_STORAGE_IMAGE,
10091 USAGE_SAMPLED_IMAGE
10092 };
10093
10094 const Usage writeUsages[] =
10095 {
10096 USAGE_HOST_WRITE,
10097 USAGE_TRANSFER_DST
10098 };
10099
10100 const deUint32 vertexStrides[] =
10101 {
10102 DEFAULT_VERTEX_BUFFER_STRIDE,
10103 ALTERNATIVE_VERTEX_BUFFER_STRIDE,
10104 };
10105
10106 for (size_t writeUsageNdx = 0; writeUsageNdx < DE_LENGTH_OF_ARRAY(writeUsages); writeUsageNdx++)
10107 {
10108 const Usage writeUsage = writeUsages[writeUsageNdx];
10109
10110 for (size_t readUsageNdx = 0; readUsageNdx < DE_LENGTH_OF_ARRAY(readUsages); readUsageNdx++)
10111 {
10112 const Usage readUsage = readUsages[readUsageNdx];
10113 const Usage usage = writeUsage | readUsage;
10114 const string usageGroupName (usageToName(usage));
10115 de::MovePtr<tcu::TestCaseGroup> usageGroup (new tcu::TestCaseGroup(testCtx, usageGroupName.c_str(), usageGroupName.c_str()));
10116
10117 for (size_t sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes); sizeNdx++)
10118 {
10119 const vk::VkDeviceSize size = sizes[sizeNdx];
10120 TestConfig config =
10121 {
10122 usage,
10123 DEFAULT_VERTEX_BUFFER_STRIDE,
10124 size,
10125 vk::VK_SHARING_MODE_EXCLUSIVE
10126 };
10127 const string testName (de::toString((deUint64)(size)));
10128
10129 if (readUsage == USAGE_VERTEX_BUFFER)
10130 {
10131 for (size_t strideNdx = 0; strideNdx < DE_LENGTH_OF_ARRAY(vertexStrides); ++strideNdx)
10132 {
10133 const deUint32 stride = vertexStrides[strideNdx];
10134 const string finalTestName = testName + "_vertex_buffer_stride_" + de::toString(stride);
10135
10136 config.vertexBufferStride = stride;
10137 usageGroup->addChild(new InstanceFactory1<MemoryTestInstance, TestConfig, AddPrograms>(testCtx,tcu::NODETYPE_SELF_VALIDATE, finalTestName, finalTestName, AddPrograms(), config));
10138 }
10139 }
10140 else
10141 {
10142 usageGroup->addChild(new InstanceFactory1<MemoryTestInstance, TestConfig, AddPrograms>(testCtx,tcu::NODETYPE_SELF_VALIDATE, testName, testName, AddPrograms(), config));
10143 }
10144 }
10145
10146 group->addChild(usageGroup.get());
10147 usageGroup.release();
10148 }
10149 }
10150
10151 {
10152 Usage all = (Usage)0;
10153
10154 for (size_t usageNdx = 0; usageNdx < DE_LENGTH_OF_ARRAY(usages); usageNdx++)
10155 all = all | usages[usageNdx];
10156
10157 {
10158 const string usageGroupName ("all");
10159 de::MovePtr<tcu::TestCaseGroup> usageGroup (new tcu::TestCaseGroup(testCtx, usageGroupName.c_str(), usageGroupName.c_str()));
10160
10161 for (size_t sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes); sizeNdx++)
10162 {
10163 const vk::VkDeviceSize size = sizes[sizeNdx];
10164
10165 for (size_t strideNdx = 0; strideNdx < DE_LENGTH_OF_ARRAY(vertexStrides); ++strideNdx)
10166 {
10167 const deUint32 stride = vertexStrides[strideNdx];
10168 const string testName = de::toString(size) + "_vertex_buffer_stride_" + de::toString(stride);
10169 const TestConfig config =
10170 {
10171 all,
10172 stride,
10173 size,
10174 vk::VK_SHARING_MODE_EXCLUSIVE
10175 };
10176
10177 usageGroup->addChild(new InstanceFactory1<MemoryTestInstance, TestConfig, AddPrograms>(testCtx,tcu::NODETYPE_SELF_VALIDATE, testName, testName, AddPrograms(), config));
10178 }
10179 }
10180
10181 group->addChild(usageGroup.get());
10182 usageGroup.release();
10183 }
10184
10185 {
10186 const string usageGroupName ("all_device");
10187 de::MovePtr<tcu::TestCaseGroup> usageGroup (new tcu::TestCaseGroup(testCtx, usageGroupName.c_str(), usageGroupName.c_str()));
10188
10189 for (size_t sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes); sizeNdx++)
10190 {
10191 const vk::VkDeviceSize size = sizes[sizeNdx];
10192
10193 for (size_t strideNdx = 0; strideNdx < DE_LENGTH_OF_ARRAY(vertexStrides); ++strideNdx)
10194 {
10195 const deUint32 stride = vertexStrides[strideNdx];
10196 const string testName = de::toString(size) + "_vertex_buffer_stride_" + de::toString(stride);
10197 const TestConfig config =
10198 {
10199 (Usage)(all & (~(USAGE_HOST_READ|USAGE_HOST_WRITE))),
10200 stride,
10201 size,
10202 vk::VK_SHARING_MODE_EXCLUSIVE
10203 };
10204
10205 usageGroup->addChild(new InstanceFactory1<MemoryTestInstance, TestConfig, AddPrograms>(testCtx,tcu::NODETYPE_SELF_VALIDATE, testName, testName, AddPrograms(), config));
10206 }
10207 }
10208
10209 group->addChild(usageGroup.get());
10210 usageGroup.release();
10211 }
10212 }
10213
10214 return group.release();
10215 }
10216
10217 } // memory
10218 } // vkt
10219