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 RenderPass tests
22 *//*--------------------------------------------------------------------*/
23
24 #include "vktRenderPassTests.hpp"
25
26 #include "vktTestCaseUtil.hpp"
27
28 #include "vkDefs.hpp"
29 #include "vkDeviceUtil.hpp"
30 #include "vkImageUtil.hpp"
31 #include "vkMemUtil.hpp"
32 #include "vkPlatform.hpp"
33 #include "vkPrograms.hpp"
34 #include "vkQueryUtil.hpp"
35 #include "vkRef.hpp"
36 #include "vkRefUtil.hpp"
37 #include "vkStrUtil.hpp"
38 #include "vkTypeUtil.hpp"
39
40 #include "tcuTestLog.hpp"
41 #include "tcuResultCollector.hpp"
42 #include "tcuFormatUtil.hpp"
43 #include "tcuTextureUtil.hpp"
44 #include "tcuFloat.hpp"
45 #include "tcuMaybe.hpp"
46 #include "tcuVectorUtil.hpp"
47
48 #include "deUniquePtr.hpp"
49 #include "deSharedPtr.hpp"
50 #include "deStringUtil.hpp"
51 #include "deSTLUtil.hpp"
52 #include "deRandom.hpp"
53
54 #include <limits>
55
56 using namespace vk;
57
58 using tcu::Maybe;
59 using tcu::nothing;
60 using tcu::just;
61 using tcu::TestLog;
62 using tcu::Vec2;
63 using tcu::IVec2;
64 using tcu::UVec2;
65 using tcu::IVec4;
66 using tcu::UVec4;
67 using tcu::Vec4;
68 using tcu::BVec4;
69 using tcu::ConstPixelBufferAccess;
70 using tcu::PixelBufferAccess;
71
72 using de::UniquePtr;
73
74 using std::vector;
75 using std::string;
76
77 namespace vkt
78 {
79 namespace
80 {
81 enum
82 {
83 STENCIL_VALUE = 84u,
84 // Limit integer values that are representable as floats
85 MAX_INTEGER_VALUE = ((1u<<22u)-1u)
86 };
87
88 // Utility functions using flattened structs
createFence(const DeviceInterface & vk,VkDevice device,VkFenceCreateFlags flags)89 Move<VkFence> createFence (const DeviceInterface& vk, VkDevice device, VkFenceCreateFlags flags)
90 {
91 const VkFenceCreateInfo pCreateInfo =
92 {
93 VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
94 DE_NULL,
95
96 flags
97 };
98 return createFence(vk, device, &pCreateInfo);
99 }
100
createFramebuffer(const DeviceInterface & vk,VkDevice device,VkFramebufferCreateFlags pCreateInfo_flags,VkRenderPass pCreateInfo_renderPass,deUint32 pCreateInfo_attachmentCount,const VkImageView * pCreateInfo_pAttachments,deUint32 pCreateInfo_width,deUint32 pCreateInfo_height,deUint32 pCreateInfo_layers)101 Move<VkFramebuffer> createFramebuffer (const DeviceInterface& vk,
102 VkDevice device,
103 VkFramebufferCreateFlags pCreateInfo_flags,
104 VkRenderPass pCreateInfo_renderPass,
105 deUint32 pCreateInfo_attachmentCount,
106 const VkImageView* pCreateInfo_pAttachments,
107 deUint32 pCreateInfo_width,
108 deUint32 pCreateInfo_height,
109 deUint32 pCreateInfo_layers)
110 {
111 const VkFramebufferCreateInfo pCreateInfo =
112 {
113 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
114 DE_NULL,
115 pCreateInfo_flags,
116 pCreateInfo_renderPass,
117 pCreateInfo_attachmentCount,
118 pCreateInfo_pAttachments,
119 pCreateInfo_width,
120 pCreateInfo_height,
121 pCreateInfo_layers,
122 };
123 return createFramebuffer(vk, device, &pCreateInfo);
124 }
125
createImage(const DeviceInterface & vk,VkDevice device,VkImageCreateFlags pCreateInfo_flags,VkImageType pCreateInfo_imageType,VkFormat pCreateInfo_format,VkExtent3D pCreateInfo_extent,deUint32 pCreateInfo_mipLevels,deUint32 pCreateInfo_arrayLayers,VkSampleCountFlagBits pCreateInfo_samples,VkImageTiling pCreateInfo_tiling,VkImageUsageFlags pCreateInfo_usage,VkSharingMode pCreateInfo_sharingMode,deUint32 pCreateInfo_queueFamilyCount,const deUint32 * pCreateInfo_pQueueFamilyIndices,VkImageLayout pCreateInfo_initialLayout)126 Move<VkImage> createImage (const DeviceInterface& vk,
127 VkDevice device,
128 VkImageCreateFlags pCreateInfo_flags,
129 VkImageType pCreateInfo_imageType,
130 VkFormat pCreateInfo_format,
131 VkExtent3D pCreateInfo_extent,
132 deUint32 pCreateInfo_mipLevels,
133 deUint32 pCreateInfo_arrayLayers,
134 VkSampleCountFlagBits pCreateInfo_samples,
135 VkImageTiling pCreateInfo_tiling,
136 VkImageUsageFlags pCreateInfo_usage,
137 VkSharingMode pCreateInfo_sharingMode,
138 deUint32 pCreateInfo_queueFamilyCount,
139 const deUint32* pCreateInfo_pQueueFamilyIndices,
140 VkImageLayout pCreateInfo_initialLayout)
141 {
142 const VkImageCreateInfo pCreateInfo =
143 {
144 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
145 DE_NULL,
146 pCreateInfo_flags,
147 pCreateInfo_imageType,
148 pCreateInfo_format,
149 pCreateInfo_extent,
150 pCreateInfo_mipLevels,
151 pCreateInfo_arrayLayers,
152 pCreateInfo_samples,
153 pCreateInfo_tiling,
154 pCreateInfo_usage,
155 pCreateInfo_sharingMode,
156 pCreateInfo_queueFamilyCount,
157 pCreateInfo_pQueueFamilyIndices,
158 pCreateInfo_initialLayout
159 };
160 return createImage(vk, device, &pCreateInfo);
161 }
162
bindBufferMemory(const DeviceInterface & vk,VkDevice device,VkBuffer buffer,VkDeviceMemory mem,VkDeviceSize memOffset)163 void bindBufferMemory (const DeviceInterface& vk, VkDevice device, VkBuffer buffer, VkDeviceMemory mem, VkDeviceSize memOffset)
164 {
165 VK_CHECK(vk.bindBufferMemory(device, buffer, mem, memOffset));
166 }
167
bindImageMemory(const DeviceInterface & vk,VkDevice device,VkImage image,VkDeviceMemory mem,VkDeviceSize memOffset)168 void bindImageMemory (const DeviceInterface& vk, VkDevice device, VkImage image, VkDeviceMemory mem, VkDeviceSize memOffset)
169 {
170 VK_CHECK(vk.bindImageMemory(device, image, mem, memOffset));
171 }
172
createImageView(const DeviceInterface & vk,VkDevice device,VkImageViewCreateFlags pCreateInfo_flags,VkImage pCreateInfo_image,VkImageViewType pCreateInfo_viewType,VkFormat pCreateInfo_format,VkComponentMapping pCreateInfo_components,VkImageSubresourceRange pCreateInfo_subresourceRange)173 Move<VkImageView> createImageView (const DeviceInterface& vk,
174 VkDevice device,
175 VkImageViewCreateFlags pCreateInfo_flags,
176 VkImage pCreateInfo_image,
177 VkImageViewType pCreateInfo_viewType,
178 VkFormat pCreateInfo_format,
179 VkComponentMapping pCreateInfo_components,
180 VkImageSubresourceRange pCreateInfo_subresourceRange)
181 {
182 const VkImageViewCreateInfo pCreateInfo =
183 {
184 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
185 DE_NULL,
186 pCreateInfo_flags,
187 pCreateInfo_image,
188 pCreateInfo_viewType,
189 pCreateInfo_format,
190 pCreateInfo_components,
191 pCreateInfo_subresourceRange,
192 };
193 return createImageView(vk, device, &pCreateInfo);
194 }
195
createBuffer(const DeviceInterface & vk,VkDevice device,VkBufferCreateFlags pCreateInfo_flags,VkDeviceSize pCreateInfo_size,VkBufferUsageFlags pCreateInfo_usage,VkSharingMode pCreateInfo_sharingMode,deUint32 pCreateInfo_queueFamilyCount,const deUint32 * pCreateInfo_pQueueFamilyIndices)196 Move<VkBuffer> createBuffer (const DeviceInterface& vk,
197 VkDevice device,
198 VkBufferCreateFlags pCreateInfo_flags,
199 VkDeviceSize pCreateInfo_size,
200 VkBufferUsageFlags pCreateInfo_usage,
201 VkSharingMode pCreateInfo_sharingMode,
202 deUint32 pCreateInfo_queueFamilyCount,
203 const deUint32* pCreateInfo_pQueueFamilyIndices)
204 {
205 const VkBufferCreateInfo pCreateInfo =
206 {
207 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
208 DE_NULL,
209 pCreateInfo_flags,
210 pCreateInfo_size,
211 pCreateInfo_usage,
212 pCreateInfo_sharingMode,
213 pCreateInfo_queueFamilyCount,
214 pCreateInfo_pQueueFamilyIndices,
215 };
216 return createBuffer(vk, device, &pCreateInfo);
217 }
218
createCommandPool(const DeviceInterface & vk,VkDevice device,VkCommandPoolCreateFlags pCreateInfo_flags,deUint32 pCreateInfo_queueFamilyIndex)219 Move<VkCommandPool> createCommandPool (const DeviceInterface& vk,
220 VkDevice device,
221 VkCommandPoolCreateFlags pCreateInfo_flags,
222 deUint32 pCreateInfo_queueFamilyIndex)
223 {
224 const VkCommandPoolCreateInfo pCreateInfo =
225 {
226 VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
227 DE_NULL,
228 pCreateInfo_flags,
229 pCreateInfo_queueFamilyIndex,
230 };
231 return createCommandPool(vk, device, &pCreateInfo);
232 }
233
cmdBeginRenderPass(const DeviceInterface & vk,VkCommandBuffer cmdBuffer,VkRenderPass pRenderPassBegin_renderPass,VkFramebuffer pRenderPassBegin_framebuffer,VkRect2D pRenderPassBegin_renderArea,deUint32 pRenderPassBegin_clearValueCount,const VkClearValue * pRenderPassBegin_pAttachmentClearValues,VkSubpassContents contents)234 void cmdBeginRenderPass (const DeviceInterface& vk,
235 VkCommandBuffer cmdBuffer,
236 VkRenderPass pRenderPassBegin_renderPass,
237 VkFramebuffer pRenderPassBegin_framebuffer,
238 VkRect2D pRenderPassBegin_renderArea,
239 deUint32 pRenderPassBegin_clearValueCount,
240 const VkClearValue* pRenderPassBegin_pAttachmentClearValues,
241 VkSubpassContents contents)
242 {
243 const VkRenderPassBeginInfo pRenderPassBegin =
244 {
245 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
246 DE_NULL,
247 pRenderPassBegin_renderPass,
248 pRenderPassBegin_framebuffer,
249 pRenderPassBegin_renderArea,
250 pRenderPassBegin_clearValueCount,
251 pRenderPassBegin_pAttachmentClearValues,
252 };
253 vk.cmdBeginRenderPass(cmdBuffer, &pRenderPassBegin, contents);
254 }
255
allocateCommandBuffer(const DeviceInterface & vk,VkDevice device,VkCommandPool pCreateInfo_commandPool,VkCommandBufferLevel pCreateInfo_level)256 Move<VkCommandBuffer> allocateCommandBuffer (const DeviceInterface& vk,
257 VkDevice device,
258 VkCommandPool pCreateInfo_commandPool,
259 VkCommandBufferLevel pCreateInfo_level)
260 {
261 const VkCommandBufferAllocateInfo pAllocateInfo =
262 {
263 VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
264 DE_NULL,
265 pCreateInfo_commandPool,
266 pCreateInfo_level,
267 1u, // bufferCount
268 };
269 return allocateCommandBuffer(vk, device, &pAllocateInfo);
270 }
271
beginCommandBuffer(const DeviceInterface & vk,VkCommandBuffer cmdBuffer,VkCommandBufferUsageFlags pBeginInfo_flags,VkRenderPass pInheritanceInfo_renderPass,deUint32 pInheritanceInfo_subpass,VkFramebuffer pInheritanceInfo_framebuffer,VkBool32 pInheritanceInfo_occlusionQueryEnable,VkQueryControlFlags pInheritanceInfo_queryFlags,VkQueryPipelineStatisticFlags pInheritanceInfo_pipelineStatistics)272 void beginCommandBuffer (const DeviceInterface& vk,
273 VkCommandBuffer cmdBuffer,
274 VkCommandBufferUsageFlags pBeginInfo_flags,
275 VkRenderPass pInheritanceInfo_renderPass,
276 deUint32 pInheritanceInfo_subpass,
277 VkFramebuffer pInheritanceInfo_framebuffer,
278 VkBool32 pInheritanceInfo_occlusionQueryEnable,
279 VkQueryControlFlags pInheritanceInfo_queryFlags,
280 VkQueryPipelineStatisticFlags pInheritanceInfo_pipelineStatistics)
281 {
282 const VkCommandBufferInheritanceInfo pInheritanceInfo =
283 {
284 VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
285 DE_NULL,
286 pInheritanceInfo_renderPass,
287 pInheritanceInfo_subpass,
288 pInheritanceInfo_framebuffer,
289 pInheritanceInfo_occlusionQueryEnable,
290 pInheritanceInfo_queryFlags,
291 pInheritanceInfo_pipelineStatistics,
292 };
293 const VkCommandBufferBeginInfo pBeginInfo =
294 {
295 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
296 DE_NULL,
297 pBeginInfo_flags,
298 &pInheritanceInfo,
299 };
300 VK_CHECK(vk.beginCommandBuffer(cmdBuffer, &pBeginInfo));
301 }
302
endCommandBuffer(const DeviceInterface & vk,VkCommandBuffer cmdBuffer)303 void endCommandBuffer (const DeviceInterface& vk, VkCommandBuffer cmdBuffer)
304 {
305 VK_CHECK(vk.endCommandBuffer(cmdBuffer));
306 }
307
queueSubmit(const DeviceInterface & vk,VkQueue queue,deUint32 cmdBufferCount,const VkCommandBuffer * pCmdBuffers,VkFence fence)308 void queueSubmit (const DeviceInterface& vk, VkQueue queue, deUint32 cmdBufferCount, const VkCommandBuffer* pCmdBuffers, VkFence fence)
309 {
310 const VkSubmitInfo submitInfo =
311 {
312 VK_STRUCTURE_TYPE_SUBMIT_INFO,
313 DE_NULL,
314 0u, // waitSemaphoreCount
315 (const VkSemaphore*)DE_NULL, // pWaitSemaphores
316 (const VkPipelineStageFlags*)DE_NULL,
317 cmdBufferCount, // commandBufferCount
318 pCmdBuffers,
319 0u, // signalSemaphoreCount
320 (const VkSemaphore*)DE_NULL, // pSignalSemaphores
321 };
322 VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, fence));
323 }
324
waitForFences(const DeviceInterface & vk,VkDevice device,deUint32 fenceCount,const VkFence * pFences,VkBool32 waitAll,deUint64 timeout)325 void waitForFences (const DeviceInterface& vk, VkDevice device, deUint32 fenceCount, const VkFence* pFences, VkBool32 waitAll, deUint64 timeout)
326 {
327 VK_CHECK(vk.waitForFences(device, fenceCount, pFences, waitAll, timeout));
328 }
329
getImageAspectFlags(VkFormat vkFormat)330 VkImageAspectFlags getImageAspectFlags (VkFormat vkFormat)
331 {
332 const tcu::TextureFormat format = mapVkFormat(vkFormat);
333
334 DE_STATIC_ASSERT(tcu::TextureFormat::CHANNELORDER_LAST == 21);
335
336 switch (format.order)
337 {
338 case tcu::TextureFormat::DS:
339 return VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_DEPTH_BIT;
340
341 case tcu::TextureFormat::D:
342 return VK_IMAGE_ASPECT_DEPTH_BIT;
343
344 case tcu::TextureFormat::S:
345 return VK_IMAGE_ASPECT_STENCIL_BIT;
346
347 default:
348 return VK_IMAGE_ASPECT_COLOR_BIT;
349 }
350 }
351
getAllMemoryReadFlags(void)352 VkAccessFlags getAllMemoryReadFlags (void)
353 {
354 return VK_ACCESS_TRANSFER_READ_BIT
355 | VK_ACCESS_UNIFORM_READ_BIT
356 | VK_ACCESS_HOST_READ_BIT
357 | VK_ACCESS_INDEX_READ_BIT
358 | VK_ACCESS_SHADER_READ_BIT
359 | VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT
360 | VK_ACCESS_INDIRECT_COMMAND_READ_BIT
361 | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT
362 | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT
363 | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
364 }
365
getAllMemoryWriteFlags(void)366 VkAccessFlags getAllMemoryWriteFlags (void)
367 {
368 return VK_ACCESS_TRANSFER_WRITE_BIT
369 | VK_ACCESS_HOST_WRITE_BIT
370 | VK_ACCESS_SHADER_WRITE_BIT
371 | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT
372 | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
373 }
374
getMemoryFlagsForLayout(const VkImageLayout layout)375 VkAccessFlags getMemoryFlagsForLayout (const VkImageLayout layout)
376 {
377 switch (layout)
378 {
379 case VK_IMAGE_LAYOUT_GENERAL: return getAllMemoryReadFlags() | getAllMemoryWriteFlags();
380 case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: return VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
381 case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: return VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
382 case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL: return VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
383 case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: return VK_ACCESS_SHADER_READ_BIT;
384 case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: return VK_ACCESS_TRANSFER_READ_BIT;
385 case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: return VK_ACCESS_TRANSFER_WRITE_BIT;
386
387 default:
388 return (VkAccessFlags)0;
389 }
390 }
391
getAllPipelineStageFlags(void)392 VkPipelineStageFlags getAllPipelineStageFlags (void)
393 {
394 return VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT
395 | VK_PIPELINE_STAGE_TRANSFER_BIT
396 | VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT
397 | VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT
398 | VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT
399 | VK_PIPELINE_STAGE_VERTEX_INPUT_BIT
400 | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT
401 | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
402 | VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT
403 | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
404 | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT
405 | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
406 | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
407 }
408
409 class AttachmentReference
410 {
411 public:
AttachmentReference(deUint32 attachment,VkImageLayout layout)412 AttachmentReference (deUint32 attachment,
413 VkImageLayout layout)
414 : m_attachment (attachment)
415 , m_layout (layout)
416 {
417 }
418
getAttachment(void) const419 deUint32 getAttachment (void) const { return m_attachment; }
getImageLayout(void) const420 VkImageLayout getImageLayout (void) const { return m_layout; }
421
422 private:
423 deUint32 m_attachment;
424 VkImageLayout m_layout;
425 };
426
427 class Subpass
428 {
429 public:
Subpass(VkPipelineBindPoint pipelineBindPoint,VkSubpassDescriptionFlags flags,const vector<AttachmentReference> & inputAttachments,const vector<AttachmentReference> & colorAttachments,const vector<AttachmentReference> & resolveAttachments,AttachmentReference depthStencilAttachment,const vector<AttachmentReference> & preserveAttachments)430 Subpass (VkPipelineBindPoint pipelineBindPoint,
431 VkSubpassDescriptionFlags flags,
432 const vector<AttachmentReference>& inputAttachments,
433 const vector<AttachmentReference>& colorAttachments,
434 const vector<AttachmentReference>& resolveAttachments,
435 AttachmentReference depthStencilAttachment,
436 const vector<AttachmentReference>& preserveAttachments)
437 : m_pipelineBindPoint (pipelineBindPoint)
438 , m_flags (flags)
439 , m_inputAttachments (inputAttachments)
440 , m_colorAttachments (colorAttachments)
441 , m_resolveAttachments (resolveAttachments)
442 , m_depthStencilAttachment (depthStencilAttachment)
443 , m_preserveAttachments (preserveAttachments)
444 {
445 }
446
getPipelineBindPoint(void) const447 VkPipelineBindPoint getPipelineBindPoint (void) const { return m_pipelineBindPoint; }
getFlags(void) const448 VkSubpassDescriptionFlags getFlags (void) const { return m_flags; }
getInputAttachments(void) const449 const vector<AttachmentReference>& getInputAttachments (void) const { return m_inputAttachments; }
getColorAttachments(void) const450 const vector<AttachmentReference>& getColorAttachments (void) const { return m_colorAttachments; }
getResolveAttachments(void) const451 const vector<AttachmentReference>& getResolveAttachments (void) const { return m_resolveAttachments; }
getDepthStencilAttachment(void) const452 const AttachmentReference& getDepthStencilAttachment (void) const { return m_depthStencilAttachment; }
getPreserveAttachments(void) const453 const vector<AttachmentReference>& getPreserveAttachments (void) const { return m_preserveAttachments; }
454
455 private:
456 VkPipelineBindPoint m_pipelineBindPoint;
457 VkSubpassDescriptionFlags m_flags;
458
459 vector<AttachmentReference> m_inputAttachments;
460 vector<AttachmentReference> m_colorAttachments;
461 vector<AttachmentReference> m_resolveAttachments;
462 AttachmentReference m_depthStencilAttachment;
463
464 vector<AttachmentReference> m_preserveAttachments;
465 };
466
467 class SubpassDependency
468 {
469 public:
SubpassDependency(deUint32 srcPass,deUint32 dstPass,VkPipelineStageFlags srcStageMask,VkPipelineStageFlags dstStageMask,VkAccessFlags outputMask,VkAccessFlags inputMask,VkDependencyFlags flags)470 SubpassDependency (deUint32 srcPass,
471 deUint32 dstPass,
472
473 VkPipelineStageFlags srcStageMask,
474 VkPipelineStageFlags dstStageMask,
475
476 VkAccessFlags outputMask,
477 VkAccessFlags inputMask,
478
479 VkDependencyFlags flags)
480 : m_srcPass (srcPass)
481 , m_dstPass (dstPass)
482
483 , m_srcStageMask (srcStageMask)
484 , m_dstStageMask (dstStageMask)
485
486 , m_outputMask (outputMask)
487 , m_inputMask (inputMask)
488 , m_flags (flags)
489 {
490 }
491
getSrcPass(void) const492 deUint32 getSrcPass (void) const { return m_srcPass; }
getDstPass(void) const493 deUint32 getDstPass (void) const { return m_dstPass; }
494
getSrcStageMask(void) const495 VkPipelineStageFlags getSrcStageMask (void) const { return m_srcStageMask; }
getDstStageMask(void) const496 VkPipelineStageFlags getDstStageMask (void) const { return m_dstStageMask; }
497
getOutputMask(void) const498 VkAccessFlags getOutputMask (void) const { return m_outputMask; }
getInputMask(void) const499 VkAccessFlags getInputMask (void) const { return m_inputMask; }
500
getFlags(void) const501 VkDependencyFlags getFlags (void) const { return m_flags; }
502
503 private:
504 deUint32 m_srcPass;
505 deUint32 m_dstPass;
506
507 VkPipelineStageFlags m_srcStageMask;
508 VkPipelineStageFlags m_dstStageMask;
509
510 VkAccessFlags m_outputMask;
511 VkAccessFlags m_inputMask;
512 VkDependencyFlags m_flags;
513 };
514
515 class Attachment
516 {
517 public:
Attachment(VkFormat format,VkSampleCountFlagBits samples,VkAttachmentLoadOp loadOp,VkAttachmentStoreOp storeOp,VkAttachmentLoadOp stencilLoadOp,VkAttachmentStoreOp stencilStoreOp,VkImageLayout initialLayout,VkImageLayout finalLayout)518 Attachment (VkFormat format,
519 VkSampleCountFlagBits samples,
520
521 VkAttachmentLoadOp loadOp,
522 VkAttachmentStoreOp storeOp,
523
524 VkAttachmentLoadOp stencilLoadOp,
525 VkAttachmentStoreOp stencilStoreOp,
526
527 VkImageLayout initialLayout,
528 VkImageLayout finalLayout)
529 : m_format (format)
530 , m_samples (samples)
531
532 , m_loadOp (loadOp)
533 , m_storeOp (storeOp)
534
535 , m_stencilLoadOp (stencilLoadOp)
536 , m_stencilStoreOp (stencilStoreOp)
537
538 , m_initialLayout (initialLayout)
539 , m_finalLayout (finalLayout)
540 {
541 }
542
getFormat(void) const543 VkFormat getFormat (void) const { return m_format; }
getSamples(void) const544 VkSampleCountFlagBits getSamples (void) const { return m_samples; }
545
getLoadOp(void) const546 VkAttachmentLoadOp getLoadOp (void) const { return m_loadOp; }
getStoreOp(void) const547 VkAttachmentStoreOp getStoreOp (void) const { return m_storeOp; }
548
549
getStencilLoadOp(void) const550 VkAttachmentLoadOp getStencilLoadOp (void) const { return m_stencilLoadOp; }
getStencilStoreOp(void) const551 VkAttachmentStoreOp getStencilStoreOp (void) const { return m_stencilStoreOp; }
552
getInitialLayout(void) const553 VkImageLayout getInitialLayout (void) const { return m_initialLayout; }
getFinalLayout(void) const554 VkImageLayout getFinalLayout (void) const { return m_finalLayout; }
555
556 private:
557 VkFormat m_format;
558 VkSampleCountFlagBits m_samples;
559
560 VkAttachmentLoadOp m_loadOp;
561 VkAttachmentStoreOp m_storeOp;
562
563 VkAttachmentLoadOp m_stencilLoadOp;
564 VkAttachmentStoreOp m_stencilStoreOp;
565
566 VkImageLayout m_initialLayout;
567 VkImageLayout m_finalLayout;
568 };
569
570 class RenderPass
571 {
572 public:
RenderPass(const vector<Attachment> & attachments,const vector<Subpass> & subpasses,const vector<SubpassDependency> & dependencies)573 RenderPass (const vector<Attachment>& attachments,
574 const vector<Subpass>& subpasses,
575 const vector<SubpassDependency>& dependencies)
576 : m_attachments (attachments)
577 , m_subpasses (subpasses)
578 , m_dependencies (dependencies)
579 {
580 }
581
getAttachments(void) const582 const vector<Attachment>& getAttachments (void) const { return m_attachments; }
getSubpasses(void) const583 const vector<Subpass>& getSubpasses (void) const { return m_subpasses; }
getDependencies(void) const584 const vector<SubpassDependency>& getDependencies (void) const { return m_dependencies; }
585
586 private:
587 const vector<Attachment> m_attachments;
588 const vector<Subpass> m_subpasses;
589 const vector<SubpassDependency> m_dependencies;
590 };
591
592 struct TestConfig
593 {
594 enum RenderTypes
595 {
596 RENDERTYPES_NONE = 0,
597 RENDERTYPES_CLEAR = (1<<1),
598 RENDERTYPES_DRAW = (1<<2)
599 };
600
601 enum CommandBufferTypes
602 {
603 COMMANDBUFFERTYPES_INLINE = (1<<0),
604 COMMANDBUFFERTYPES_SECONDARY = (1<<1)
605 };
606
607 enum ImageMemory
608 {
609 IMAGEMEMORY_STRICT = (1<<0),
610 IMAGEMEMORY_LAZY = (1<<1)
611 };
612
TestConfigvkt::__anondc024f7e0111::TestConfig613 TestConfig (const RenderPass& renderPass_,
614 RenderTypes renderTypes_,
615 CommandBufferTypes commandBufferTypes_,
616 ImageMemory imageMemory_,
617 const UVec2& targetSize_,
618 const UVec2& renderPos_,
619 const UVec2& renderSize_,
620 deUint32 seed_)
621 : renderPass (renderPass_)
622 , renderTypes (renderTypes_)
623 , commandBufferTypes (commandBufferTypes_)
624 , imageMemory (imageMemory_)
625 , targetSize (targetSize_)
626 , renderPos (renderPos_)
627 , renderSize (renderSize_)
628 , seed (seed_)
629 {
630 }
631
632 RenderPass renderPass;
633 RenderTypes renderTypes;
634 CommandBufferTypes commandBufferTypes;
635 ImageMemory imageMemory;
636 UVec2 targetSize;
637 UVec2 renderPos;
638 UVec2 renderSize;
639 deUint32 seed;
640 };
641
operator |(TestConfig::RenderTypes a,TestConfig::RenderTypes b)642 TestConfig::RenderTypes operator| (TestConfig::RenderTypes a, TestConfig::RenderTypes b)
643 {
644 return (TestConfig::RenderTypes)(((deUint32)a) | ((deUint32)b));
645 }
646
operator |(TestConfig::CommandBufferTypes a,TestConfig::CommandBufferTypes b)647 TestConfig::CommandBufferTypes operator| (TestConfig::CommandBufferTypes a, TestConfig::CommandBufferTypes b)
648 {
649 return (TestConfig::CommandBufferTypes)(((deUint32)a) | ((deUint32)b));
650 }
651
operator |(TestConfig::ImageMemory a,TestConfig::ImageMemory b)652 TestConfig::ImageMemory operator| (TestConfig::ImageMemory a, TestConfig::ImageMemory b)
653 {
654 return (TestConfig::ImageMemory)(((deUint32)a) | ((deUint32)b));
655 }
656
logRenderPassInfo(TestLog & log,const RenderPass & renderPass)657 void logRenderPassInfo (TestLog& log,
658 const RenderPass& renderPass)
659 {
660 const tcu::ScopedLogSection section (log, "RenderPass", "RenderPass");
661
662 {
663 const tcu::ScopedLogSection attachmentsSection (log, "Attachments", "Attachments");
664 const vector<Attachment>& attachments = renderPass.getAttachments();
665
666 for (size_t attachmentNdx = 0; attachmentNdx < attachments.size(); attachmentNdx++)
667 {
668 const tcu::ScopedLogSection attachmentSection (log, "Attachment" + de::toString(attachmentNdx), "Attachment " + de::toString(attachmentNdx));
669 const Attachment& attachment = attachments[attachmentNdx];
670
671 log << TestLog::Message << "Format: " << attachment.getFormat() << TestLog::EndMessage;
672 log << TestLog::Message << "Samples: " << attachment.getSamples() << TestLog::EndMessage;
673
674 log << TestLog::Message << "LoadOp: " << attachment.getLoadOp() << TestLog::EndMessage;
675 log << TestLog::Message << "StoreOp: " << attachment.getStoreOp() << TestLog::EndMessage;
676
677 log << TestLog::Message << "StencilLoadOp: " << attachment.getStencilLoadOp() << TestLog::EndMessage;
678 log << TestLog::Message << "StencilStoreOp: " << attachment.getStencilStoreOp() << TestLog::EndMessage;
679
680 log << TestLog::Message << "InitialLayout: " << attachment.getInitialLayout() << TestLog::EndMessage;
681 log << TestLog::Message << "FinalLayout: " << attachment.getFinalLayout() << TestLog::EndMessage;
682 }
683 }
684
685 {
686 const tcu::ScopedLogSection subpassesSection (log, "Subpasses", "Subpasses");
687 const vector<Subpass>& subpasses = renderPass.getSubpasses();
688
689 for (size_t subpassNdx = 0; subpassNdx < subpasses.size(); subpassNdx++)
690 {
691 const tcu::ScopedLogSection subpassSection (log, "Subpass" + de::toString(subpassNdx), "Subpass " + de::toString(subpassNdx));
692 const Subpass& subpass = subpasses[subpassNdx];
693
694 const vector<AttachmentReference>& inputAttachments = subpass.getInputAttachments();
695 const vector<AttachmentReference>& colorAttachments = subpass.getColorAttachments();
696 const vector<AttachmentReference>& resolveAttachments = subpass.getResolveAttachments();
697 const vector<AttachmentReference>& preserveAttachments = subpass.getPreserveAttachments();
698
699 if (!inputAttachments.empty())
700 {
701 const tcu::ScopedLogSection inputAttachmentsSection (log, "Inputs", "Inputs");
702
703 for (size_t inputNdx = 0; inputNdx < inputAttachments.size(); inputNdx++)
704 {
705 const tcu::ScopedLogSection inputAttachmentSection (log, "Input" + de::toString(inputNdx), "Input " + de::toString(inputNdx));
706 const AttachmentReference& inputAttachment = inputAttachments[inputNdx];
707
708 log << TestLog::Message << "Attachment: " << inputAttachment.getAttachment() << TestLog::EndMessage;
709 log << TestLog::Message << "Layout: " << inputAttachment.getImageLayout() << TestLog::EndMessage;
710 }
711 }
712
713 if (subpass.getDepthStencilAttachment().getAttachment() != VK_ATTACHMENT_UNUSED)
714 {
715 const tcu::ScopedLogSection depthStencilAttachmentSection (log, "DepthStencil", "DepthStencil");
716 const AttachmentReference& depthStencilAttachment = subpass.getDepthStencilAttachment();
717
718 log << TestLog::Message << "Attachment: " << depthStencilAttachment.getAttachment() << TestLog::EndMessage;
719 log << TestLog::Message << "Layout: " << depthStencilAttachment.getImageLayout() << TestLog::EndMessage;
720 }
721
722 if (!colorAttachments.empty())
723 {
724 const tcu::ScopedLogSection colorAttachmentsSection (log, "Colors", "Colors");
725
726 for (size_t colorNdx = 0; colorNdx < colorAttachments.size(); colorNdx++)
727 {
728 const tcu::ScopedLogSection colorAttachmentSection (log, "Color" + de::toString(colorNdx), "Color " + de::toString(colorNdx));
729 const AttachmentReference& colorAttachment = colorAttachments[colorNdx];
730
731 log << TestLog::Message << "Attachment: " << colorAttachment.getAttachment() << TestLog::EndMessage;
732 log << TestLog::Message << "Layout: " << colorAttachment.getImageLayout() << TestLog::EndMessage;
733 }
734 }
735
736 if (!resolveAttachments.empty())
737 {
738 const tcu::ScopedLogSection resolveAttachmentsSection (log, "Resolves", "Resolves");
739
740 for (size_t resolveNdx = 0; resolveNdx < resolveAttachments.size(); resolveNdx++)
741 {
742 const tcu::ScopedLogSection resolveAttachmentSection (log, "Resolve" + de::toString(resolveNdx), "Resolve " + de::toString(resolveNdx));
743 const AttachmentReference& resolveAttachment = resolveAttachments[resolveNdx];
744
745 log << TestLog::Message << "Attachment: " << resolveAttachment.getAttachment() << TestLog::EndMessage;
746 log << TestLog::Message << "Layout: " << resolveAttachment.getImageLayout() << TestLog::EndMessage;
747 }
748 }
749
750 if (!preserveAttachments.empty())
751 {
752 const tcu::ScopedLogSection preserveAttachmentsSection (log, "Preserves", "Preserves");
753
754 for (size_t preserveNdx = 0; preserveNdx < preserveAttachments.size(); preserveNdx++)
755 {
756 const tcu::ScopedLogSection preserveAttachmentSection (log, "Preserve" + de::toString(preserveNdx), "Preserve " + de::toString(preserveNdx));
757 const AttachmentReference& preserveAttachment = preserveAttachments[preserveNdx];
758
759 log << TestLog::Message << "Attachment: " << preserveAttachment.getAttachment() << TestLog::EndMessage;
760 log << TestLog::Message << "Layout: " << preserveAttachment.getImageLayout() << TestLog::EndMessage;
761 }
762 }
763 }
764
765 }
766
767 if (!renderPass.getDependencies().empty())
768 {
769 const tcu::ScopedLogSection dependenciesSection (log, "Dependencies", "Dependencies");
770
771 for (size_t depNdx = 0; depNdx < renderPass.getDependencies().size(); depNdx++)
772 {
773 const tcu::ScopedLogSection dependencySection (log, "Dependency" + de::toString(depNdx), "Dependency " + de::toString(depNdx));
774 const SubpassDependency& dep = renderPass.getDependencies()[depNdx];
775
776 log << TestLog::Message << "Source: " << dep.getSrcPass() << TestLog::EndMessage;
777 log << TestLog::Message << "Destination: " << dep.getDstPass() << TestLog::EndMessage;
778
779 log << TestLog::Message << "Source Stage Mask: " << dep.getSrcStageMask() << TestLog::EndMessage;
780 log << TestLog::Message << "Destination Stage Mask: " << dep.getDstStageMask() << TestLog::EndMessage;
781
782 log << TestLog::Message << "Input Mask: " << dep.getInputMask() << TestLog::EndMessage;
783 log << TestLog::Message << "Output Mask: " << dep.getOutputMask() << TestLog::EndMessage;
784 log << TestLog::Message << "Dependency Flags: " << getDependencyFlagsStr(dep.getFlags()) << TestLog::EndMessage;
785 }
786 }
787 }
788
clearColorToString(VkFormat vkFormat,VkClearColorValue value)789 std::string clearColorToString (VkFormat vkFormat, VkClearColorValue value)
790 {
791 const tcu::TextureFormat format = mapVkFormat(vkFormat);
792 const tcu::TextureChannelClass channelClass = tcu::getTextureChannelClass(format.type);
793 const tcu::BVec4 channelMask = tcu::getTextureFormatChannelMask(format);
794
795 std::ostringstream stream;
796
797 stream << "(";
798
799 switch (channelClass)
800 {
801 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
802 for (int i = 0; i < 4; i++)
803 {
804 if (i > 0)
805 stream << ", ";
806
807 if (channelMask[i])
808 stream << value.int32[i];
809 else
810 stream << "Undef";
811 }
812 break;
813
814 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
815 for (int i = 0; i < 4; i++)
816 {
817 if (i > 0)
818 stream << ", ";
819
820 if (channelMask[i])
821 stream << value.uint32[i];
822 else
823 stream << "Undef";
824 }
825 break;
826
827 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
828 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
829 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
830 for (int i = 0; i < 4; i++)
831 {
832 if (i > 0)
833 stream << ", ";
834
835 if (channelMask[i])
836 stream << value.float32[i];
837 else
838 stream << "Undef";
839 }
840 break;
841
842 default:
843 DE_FATAL("Unknown channel class");
844 }
845
846 stream << ")";
847
848 return stream.str();
849 }
850
clearValueToString(VkFormat vkFormat,VkClearValue value)851 std::string clearValueToString (VkFormat vkFormat, VkClearValue value)
852 {
853 const tcu::TextureFormat format = mapVkFormat(vkFormat);
854
855 if (tcu::hasStencilComponent(format.order) || tcu::hasDepthComponent(format.order))
856 {
857 std::ostringstream stream;
858
859 stream << "(";
860
861 if (tcu::hasStencilComponent(format.order))
862 stream << "stencil: " << value.depthStencil.stencil;
863
864 if (tcu::hasStencilComponent(format.order) && tcu::hasDepthComponent(format.order))
865 stream << ", ";
866
867 if (tcu::hasDepthComponent(format.order))
868 stream << "depth: " << value.depthStencil.depth;
869
870 stream << ")";
871
872 return stream.str();
873 }
874 else
875 return clearColorToString(vkFormat, value.color);
876 }
877
randomColorClearValue(const Attachment & attachment,de::Random & rng)878 VkClearColorValue randomColorClearValue (const Attachment& attachment, de::Random& rng)
879 {
880 const float clearNan = tcu::Float32::nan().asFloat();
881 const tcu::TextureFormat format = mapVkFormat(attachment.getFormat());
882 const tcu::TextureChannelClass channelClass = tcu::getTextureChannelClass(format.type);
883 const tcu::BVec4 channelMask = tcu::getTextureFormatChannelMask(format);
884 VkClearColorValue clearColor;
885
886 switch (channelClass)
887 {
888 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
889 {
890 const tcu::IVec4 valueMin = tcu::getFormatMinIntValue(format);
891 const tcu::IVec4 valueMax = tcu::getFormatMaxIntValue(format);
892
893 for (int ndx = 0; ndx < 4; ndx++)
894 {
895 if (!channelMask[ndx])
896 clearColor.int32[ndx] = std::numeric_limits<deInt32>::min();
897 else
898 clearColor.uint32[ndx] = rng.getInt(valueMin[ndx], valueMax[ndx]);
899 }
900 break;
901 }
902
903 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
904 {
905 const UVec4 valueMax = tcu::getFormatMaxUintValue(format);
906
907 for (int ndx = 0; ndx < 4; ndx++)
908 {
909 if (!channelMask[ndx])
910 clearColor.uint32[ndx] = std::numeric_limits<deUint32>::max();
911 else
912 clearColor.uint32[ndx] = rng.getUint32() % valueMax[ndx];
913 }
914 break;
915 }
916
917 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
918 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
919 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
920 {
921 const tcu::TextureFormatInfo formatInfo = tcu::getTextureFormatInfo(format);
922
923 for (int ndx = 0; ndx < 4; ndx++)
924 {
925 if (!channelMask[ndx])
926 clearColor.float32[ndx] = clearNan;
927 else
928 clearColor.float32[ndx] = formatInfo.valueMin[ndx] + rng.getFloat() * (formatInfo.valueMax[ndx] - formatInfo.valueMin[ndx]);
929 }
930 break;
931 }
932
933 default:
934 DE_FATAL("Unknown channel class");
935 }
936
937 return clearColor;
938 }
939
createAttachmentDescription(const Attachment & attachment)940 VkAttachmentDescription createAttachmentDescription (const Attachment& attachment)
941 {
942 const VkAttachmentDescription attachmentDescription =
943 {
944 0, // flags
945
946 attachment.getFormat(), // format
947 attachment.getSamples(), // samples
948
949 attachment.getLoadOp(), // loadOp
950 attachment.getStoreOp(), // storeOp
951
952 attachment.getStencilLoadOp(), // stencilLoadOp
953 attachment.getStencilStoreOp(), // stencilStoreOp
954
955 attachment.getInitialLayout(), // initialLayout
956 attachment.getFinalLayout(), // finalLayout
957 };
958
959 return attachmentDescription;
960 }
961
createAttachmentReference(const AttachmentReference & referenceInfo)962 VkAttachmentReference createAttachmentReference (const AttachmentReference& referenceInfo)
963 {
964 const VkAttachmentReference reference =
965 {
966 referenceInfo.getAttachment(), // attachment;
967 referenceInfo.getImageLayout() // layout;
968 };
969
970 return reference;
971 }
972
createSubpassDescription(const Subpass & subpass,vector<VkAttachmentReference> * attachmentReferenceLists,vector<deUint32> * preserveAttachmentReferences)973 VkSubpassDescription createSubpassDescription (const Subpass& subpass,
974 vector<VkAttachmentReference>* attachmentReferenceLists,
975 vector<deUint32>* preserveAttachmentReferences)
976 {
977 vector<VkAttachmentReference>& inputAttachmentReferences = attachmentReferenceLists[0];
978 vector<VkAttachmentReference>& colorAttachmentReferences = attachmentReferenceLists[1];
979 vector<VkAttachmentReference>& resolveAttachmentReferences = attachmentReferenceLists[2];
980 vector<VkAttachmentReference>& depthStencilAttachmentReferences = attachmentReferenceLists[3];
981
982 for (size_t attachmentNdx = 0; attachmentNdx < subpass.getColorAttachments().size(); attachmentNdx++)
983 colorAttachmentReferences.push_back(createAttachmentReference(subpass.getColorAttachments()[attachmentNdx]));
984
985 for (size_t attachmentNdx = 0; attachmentNdx < subpass.getInputAttachments().size(); attachmentNdx++)
986 inputAttachmentReferences.push_back(createAttachmentReference(subpass.getInputAttachments()[attachmentNdx]));
987
988 for (size_t attachmentNdx = 0; attachmentNdx < subpass.getResolveAttachments().size(); attachmentNdx++)
989 resolveAttachmentReferences.push_back(createAttachmentReference(subpass.getResolveAttachments()[attachmentNdx]));
990
991 depthStencilAttachmentReferences.push_back(createAttachmentReference(subpass.getDepthStencilAttachment()));
992
993 for (size_t attachmentNdx = 0; attachmentNdx < subpass.getPreserveAttachments().size(); attachmentNdx++)
994 preserveAttachmentReferences->push_back(subpass.getPreserveAttachments()[attachmentNdx].getAttachment());
995
996 DE_ASSERT(resolveAttachmentReferences.empty() || colorAttachmentReferences.size() == resolveAttachmentReferences.size());
997
998 {
999 const VkSubpassDescription subpassDescription =
1000 {
1001 subpass.getFlags(), // flags;
1002 subpass.getPipelineBindPoint(), // pipelineBindPoint;
1003
1004 (deUint32)inputAttachmentReferences.size(), // inputCount;
1005 inputAttachmentReferences.empty() ? DE_NULL : &inputAttachmentReferences[0], // inputAttachments;
1006
1007 (deUint32)colorAttachmentReferences.size(), // colorCount;
1008 colorAttachmentReferences.empty() ? DE_NULL : &colorAttachmentReferences[0], // colorAttachments;
1009 resolveAttachmentReferences.empty() ? DE_NULL : &resolveAttachmentReferences[0], // resolveAttachments;
1010
1011 &depthStencilAttachmentReferences[0], // pDepthStencilAttachment;
1012 (deUint32)preserveAttachmentReferences->size(), // preserveCount;
1013 preserveAttachmentReferences->empty() ? DE_NULL : &(*preserveAttachmentReferences)[0] // preserveAttachments;
1014 };
1015
1016 return subpassDescription;
1017 }
1018 }
1019
createSubpassDependency(const SubpassDependency & dependencyInfo)1020 VkSubpassDependency createSubpassDependency (const SubpassDependency& dependencyInfo)
1021 {
1022 const VkSubpassDependency dependency =
1023 {
1024 dependencyInfo.getSrcPass(), // srcSubpass;
1025 dependencyInfo.getDstPass(), // destSubpass;
1026
1027 dependencyInfo.getSrcStageMask(), // srcStageMask;
1028 dependencyInfo.getDstStageMask(), // destStageMask;
1029
1030 dependencyInfo.getOutputMask(), // outputMask;
1031 dependencyInfo.getInputMask(), // inputMask;
1032
1033 dependencyInfo.getFlags() // dependencyFlags;
1034 };
1035
1036 return dependency;
1037 }
1038
createRenderPass(const DeviceInterface & vk,VkDevice device,const RenderPass & renderPassInfo)1039 Move<VkRenderPass> createRenderPass (const DeviceInterface& vk,
1040 VkDevice device,
1041 const RenderPass& renderPassInfo)
1042 {
1043 const size_t perSubpassAttachmentReferenceLists = 4;
1044 vector<VkAttachmentDescription> attachments;
1045 vector<VkSubpassDescription> subpasses;
1046 vector<VkSubpassDependency> dependencies;
1047 vector<vector<VkAttachmentReference> > attachmentReferenceLists(renderPassInfo.getSubpasses().size() * perSubpassAttachmentReferenceLists);
1048 vector<vector<deUint32> > preserveAttachments(renderPassInfo.getSubpasses().size());
1049
1050 for (size_t attachmentNdx = 0; attachmentNdx < renderPassInfo.getAttachments().size(); attachmentNdx++)
1051 attachments.push_back(createAttachmentDescription(renderPassInfo.getAttachments()[attachmentNdx]));
1052
1053 for (size_t subpassNdx = 0; subpassNdx < renderPassInfo.getSubpasses().size(); subpassNdx++)
1054 subpasses.push_back(createSubpassDescription(renderPassInfo.getSubpasses()[subpassNdx], &(attachmentReferenceLists[subpassNdx * perSubpassAttachmentReferenceLists]), &preserveAttachments[subpassNdx]));
1055
1056 for (size_t depNdx = 0; depNdx < renderPassInfo.getDependencies().size(); depNdx++)
1057 dependencies.push_back(createSubpassDependency(renderPassInfo.getDependencies()[depNdx]));
1058
1059 {
1060 const VkRenderPassCreateInfo createInfo =
1061 {
1062 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
1063 DE_NULL,
1064 (VkRenderPassCreateFlags)0u,
1065 (deUint32)attachments.size(),
1066 (attachments.empty() ? DE_NULL : &attachments[0]),
1067 (deUint32)subpasses.size(),
1068 (subpasses.empty() ? DE_NULL : &subpasses[0]),
1069 (deUint32)dependencies.size(),
1070 (dependencies.empty() ? DE_NULL : &dependencies[0])
1071 };
1072
1073 return createRenderPass(vk, device, &createInfo);
1074 }
1075 }
1076
createFramebuffer(const DeviceInterface & vk,VkDevice device,VkRenderPass renderPass,const UVec2 & size,const vector<VkImageView> & attachments)1077 Move<VkFramebuffer> createFramebuffer (const DeviceInterface& vk,
1078 VkDevice device,
1079 VkRenderPass renderPass,
1080 const UVec2& size,
1081 const vector<VkImageView>& attachments)
1082 {
1083 return createFramebuffer(vk, device, 0u, renderPass, (deUint32)attachments.size(), attachments.empty() ? DE_NULL : &attachments[0], size.x(), size.y(), 1u);
1084 }
1085
createAttachmentImage(const DeviceInterface & vk,VkDevice device,deUint32 queueIndex,const UVec2 & size,VkFormat format,VkSampleCountFlagBits samples,VkImageUsageFlags usageFlags,VkImageLayout layout)1086 Move<VkImage> createAttachmentImage (const DeviceInterface& vk,
1087 VkDevice device,
1088 deUint32 queueIndex,
1089 const UVec2& size,
1090 VkFormat format,
1091 VkSampleCountFlagBits samples,
1092 VkImageUsageFlags usageFlags,
1093 VkImageLayout layout)
1094 {
1095 const VkExtent3D size_ = { size.x(), size.y(), 1u };
1096 VkImageUsageFlags targetUsageFlags = 0;
1097 const tcu::TextureFormat textureFormat = mapVkFormat(format);
1098
1099 if (tcu::hasDepthComponent(textureFormat.order) || tcu::hasStencilComponent(textureFormat.order))
1100 {
1101 targetUsageFlags |= vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
1102 }
1103 else
1104 {
1105 targetUsageFlags |= vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
1106 }
1107
1108 return createImage(vk, device,
1109 (VkImageCreateFlags)0,
1110 VK_IMAGE_TYPE_2D,
1111 format,
1112 size_,
1113 1u /* mipLevels */,
1114 1u /* arraySize */,
1115 samples,
1116 VK_IMAGE_TILING_OPTIMAL,
1117 usageFlags | targetUsageFlags,
1118 VK_SHARING_MODE_EXCLUSIVE,
1119 1,
1120 &queueIndex,
1121 layout);
1122 }
1123
createImageMemory(const DeviceInterface & vk,VkDevice device,Allocator & allocator,VkImage image,bool lazy)1124 de::MovePtr<Allocation> createImageMemory (const DeviceInterface& vk,
1125 VkDevice device,
1126 Allocator& allocator,
1127 VkImage image,
1128 bool lazy)
1129 {
1130 de::MovePtr<Allocation> allocation (allocator.allocate(getImageMemoryRequirements(vk, device, image), lazy ? MemoryRequirement::LazilyAllocated : MemoryRequirement::Any));
1131 bindImageMemory(vk, device, image, allocation->getMemory(), allocation->getOffset());
1132 return allocation;
1133 }
1134
createImageAttachmentView(const DeviceInterface & vk,VkDevice device,VkImage image,VkFormat format,VkImageAspectFlags aspect)1135 Move<VkImageView> createImageAttachmentView (const DeviceInterface& vk,
1136 VkDevice device,
1137 VkImage image,
1138 VkFormat format,
1139 VkImageAspectFlags aspect)
1140 {
1141 const VkImageSubresourceRange range =
1142 {
1143 aspect,
1144 0,
1145 1,
1146 0,
1147 1
1148 };
1149
1150 return createImageView(vk, device, 0u, image, VK_IMAGE_VIEW_TYPE_2D, format, makeComponentMappingRGBA(), range);
1151 }
1152
randomClearValue(const Attachment & attachment,de::Random & rng)1153 VkClearValue randomClearValue (const Attachment& attachment, de::Random& rng)
1154 {
1155 const float clearNan = tcu::Float32::nan().asFloat();
1156 const tcu::TextureFormat format = mapVkFormat(attachment.getFormat());
1157
1158 if (tcu::hasStencilComponent(format.order) || tcu::hasDepthComponent(format.order))
1159 {
1160 VkClearValue clearValue;
1161
1162 clearValue.depthStencil.depth = clearNan;
1163 clearValue.depthStencil.stencil = 255;
1164
1165 if (tcu::hasStencilComponent(format.order))
1166 clearValue.depthStencil.stencil = rng.getInt(0, 255);
1167
1168 if (tcu::hasDepthComponent(format.order))
1169 clearValue.depthStencil.depth = rng.getFloat();
1170
1171 return clearValue;
1172 }
1173 else
1174 {
1175 VkClearValue clearValue;
1176
1177 clearValue.color = randomColorClearValue(attachment, rng);
1178
1179 return clearValue;
1180 }
1181 }
1182
1183 class AttachmentResources
1184 {
1185 public:
AttachmentResources(const DeviceInterface & vk,VkDevice device,Allocator & allocator,deUint32 queueIndex,const UVec2 & size,const Attachment & attachmentInfo,VkImageUsageFlags usageFlags)1186 AttachmentResources (const DeviceInterface& vk,
1187 VkDevice device,
1188 Allocator& allocator,
1189 deUint32 queueIndex,
1190 const UVec2& size,
1191 const Attachment& attachmentInfo,
1192 VkImageUsageFlags usageFlags)
1193 : m_image (createAttachmentImage(vk, device, queueIndex, size, attachmentInfo.getFormat(), attachmentInfo.getSamples(), usageFlags, VK_IMAGE_LAYOUT_UNDEFINED))
1194 , m_imageMemory (createImageMemory(vk, device, allocator, *m_image, ((usageFlags & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT) != 0)))
1195 , m_attachmentView (createImageAttachmentView(vk, device, *m_image, attachmentInfo.getFormat(), getImageAspectFlags(attachmentInfo.getFormat())))
1196 {
1197 if ((usageFlags & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT) == 0)
1198 {
1199 const tcu::TextureFormat format = mapVkFormat(attachmentInfo.getFormat());
1200
1201 if (tcu::hasDepthComponent(format.order) && tcu::hasStencilComponent(format.order))
1202 {
1203 const tcu::TextureFormat depthFormat = getDepthCopyFormat(attachmentInfo.getFormat());
1204 const tcu::TextureFormat stencilFormat = getStencilCopyFormat(attachmentInfo.getFormat());
1205
1206 m_bufferSize = size.x() * size.y() * depthFormat.getPixelSize();
1207 m_secondaryBufferSize = size.x() * size.y() * stencilFormat.getPixelSize();
1208
1209 m_buffer = createBuffer(vk, device, 0, m_bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_SHARING_MODE_EXCLUSIVE, 1, &queueIndex);
1210 m_bufferMemory = allocator.allocate(getBufferMemoryRequirements(vk, device, *m_buffer), MemoryRequirement::HostVisible);
1211
1212 bindBufferMemory(vk, device, *m_buffer, m_bufferMemory->getMemory(), m_bufferMemory->getOffset());
1213
1214 m_secondaryBuffer = createBuffer(vk, device, 0, m_secondaryBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_SHARING_MODE_EXCLUSIVE, 1, &queueIndex);
1215 m_secondaryBufferMemory = allocator.allocate(getBufferMemoryRequirements(vk, device, *m_secondaryBuffer), MemoryRequirement::HostVisible);
1216
1217 bindBufferMemory(vk, device, *m_secondaryBuffer, m_secondaryBufferMemory->getMemory(), m_secondaryBufferMemory->getOffset());
1218 }
1219 else
1220 {
1221 m_bufferSize = size.x() * size.y() * format.getPixelSize();
1222
1223 m_buffer = createBuffer(vk, device, 0, m_bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_SHARING_MODE_EXCLUSIVE, 1, &queueIndex);
1224 m_bufferMemory = allocator.allocate(getBufferMemoryRequirements(vk, device, *m_buffer), MemoryRequirement::HostVisible);
1225
1226 bindBufferMemory(vk, device, *m_buffer, m_bufferMemory->getMemory(), m_bufferMemory->getOffset());
1227 }
1228 }
1229 }
1230
~AttachmentResources(void)1231 ~AttachmentResources (void)
1232 {
1233 }
1234
getAttachmentView(void) const1235 VkImageView getAttachmentView (void) const
1236 {
1237 return *m_attachmentView;
1238 }
1239
getImage(void) const1240 VkImage getImage (void) const
1241 {
1242 return *m_image;
1243 }
1244
getBuffer(void) const1245 VkBuffer getBuffer (void) const
1246 {
1247 DE_ASSERT(*m_buffer != DE_NULL);
1248 return *m_buffer;
1249 }
1250
getBufferSize(void) const1251 VkDeviceSize getBufferSize (void) const
1252 {
1253 DE_ASSERT(*m_buffer != DE_NULL);
1254 return m_bufferSize;
1255 }
1256
getResultMemory(void) const1257 const Allocation& getResultMemory (void) const
1258 {
1259 DE_ASSERT(m_bufferMemory);
1260 return *m_bufferMemory;
1261 }
1262
getSecondaryBuffer(void) const1263 VkBuffer getSecondaryBuffer (void) const
1264 {
1265 DE_ASSERT(*m_secondaryBuffer != DE_NULL);
1266 return *m_secondaryBuffer;
1267 }
1268
getSecondaryBufferSize(void) const1269 VkDeviceSize getSecondaryBufferSize (void) const
1270 {
1271 DE_ASSERT(*m_secondaryBuffer != DE_NULL);
1272 return m_secondaryBufferSize;
1273 }
1274
getSecondaryResultMemory(void) const1275 const Allocation& getSecondaryResultMemory (void) const
1276 {
1277 DE_ASSERT(m_secondaryBufferMemory);
1278 return *m_secondaryBufferMemory;
1279 }
1280
1281 private:
1282 const Unique<VkImage> m_image;
1283 const UniquePtr<Allocation> m_imageMemory;
1284 const Unique<VkImageView> m_attachmentView;
1285
1286 Move<VkBuffer> m_buffer;
1287 VkDeviceSize m_bufferSize;
1288 de::MovePtr<Allocation> m_bufferMemory;
1289
1290 Move<VkBuffer> m_secondaryBuffer;
1291 VkDeviceSize m_secondaryBufferSize;
1292 de::MovePtr<Allocation> m_secondaryBufferMemory;
1293 };
1294
uploadBufferData(const DeviceInterface & vk,VkDevice device,const Allocation & memory,size_t size,const void * data)1295 void uploadBufferData (const DeviceInterface& vk,
1296 VkDevice device,
1297 const Allocation& memory,
1298 size_t size,
1299 const void* data)
1300 {
1301 const VkMappedMemoryRange range =
1302 {
1303 VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // sType;
1304 DE_NULL, // pNext;
1305 memory.getMemory(), // mem;
1306 memory.getOffset(), // offset;
1307 (VkDeviceSize)size // size;
1308 };
1309 void* const ptr = memory.getHostPtr();
1310
1311 deMemcpy(ptr, data, size);
1312 VK_CHECK(vk.flushMappedMemoryRanges(device, 1, &range));
1313 }
1314
getPrimaryImageAspect(tcu::TextureFormat::ChannelOrder order)1315 VkImageAspectFlagBits getPrimaryImageAspect (tcu::TextureFormat::ChannelOrder order)
1316 {
1317 DE_STATIC_ASSERT(tcu::TextureFormat::CHANNELORDER_LAST == 21);
1318
1319 switch (order)
1320 {
1321 case tcu::TextureFormat::D:
1322 case tcu::TextureFormat::DS:
1323 return VK_IMAGE_ASPECT_DEPTH_BIT;
1324
1325 case tcu::TextureFormat::S:
1326 return VK_IMAGE_ASPECT_STENCIL_BIT;
1327
1328 default:
1329 return VK_IMAGE_ASPECT_COLOR_BIT;
1330 }
1331 }
1332
1333 class RenderQuad
1334 {
1335 public:
RenderQuad(const Vec4 & posA,const Vec4 & posB)1336 RenderQuad (const Vec4& posA, const Vec4& posB)
1337 : m_vertices(6)
1338 {
1339 m_vertices[0] = posA;
1340 m_vertices[1] = Vec4(posA[0], posB[1], posA[2], posA[3]);
1341 m_vertices[2] = posB;
1342
1343 m_vertices[3] = posB;
1344 m_vertices[4] = Vec4(posB[0], posA[1], posB[2], posA[3]);
1345 m_vertices[5] = posA;
1346 }
1347
getCornerA(void) const1348 const Vec4& getCornerA (void) const
1349 {
1350 return m_vertices[0];
1351 }
1352
getCornerB(void) const1353 const Vec4& getCornerB (void) const
1354 {
1355 return m_vertices[2];
1356 }
1357
getVertexPointer(void) const1358 const void* getVertexPointer (void) const
1359 {
1360 return &m_vertices[0];
1361 }
1362
getVertexDataSize(void) const1363 size_t getVertexDataSize (void) const
1364 {
1365 return sizeof(Vec4) * m_vertices.size();
1366 }
1367
1368 private:
1369 vector<Vec4> m_vertices;
1370 };
1371
1372 class ColorClear
1373 {
1374 public:
ColorClear(const UVec2 & offset,const UVec2 & size,const VkClearColorValue & color)1375 ColorClear (const UVec2& offset,
1376 const UVec2& size,
1377 const VkClearColorValue& color)
1378 : m_offset (offset)
1379 , m_size (size)
1380 , m_color (color)
1381 {
1382 }
1383
getOffset(void) const1384 const UVec2& getOffset (void) const { return m_offset; }
getSize(void) const1385 const UVec2& getSize (void) const { return m_size; }
getColor(void) const1386 const VkClearColorValue& getColor (void) const { return m_color; }
1387
1388 private:
1389 UVec2 m_offset;
1390 UVec2 m_size;
1391 VkClearColorValue m_color;
1392 };
1393
1394 class DepthStencilClear
1395 {
1396 public:
DepthStencilClear(const UVec2 & offset,const UVec2 & size,float depth,deUint32 stencil)1397 DepthStencilClear (const UVec2& offset,
1398 const UVec2& size,
1399 float depth,
1400 deUint32 stencil)
1401 : m_offset (offset)
1402 , m_size (size)
1403 , m_depth (depth)
1404 , m_stencil (stencil)
1405 {
1406 }
1407
getOffset(void) const1408 const UVec2& getOffset (void) const { return m_offset; }
getSize(void) const1409 const UVec2& getSize (void) const { return m_size; }
getDepth(void) const1410 float getDepth (void) const { return m_depth; }
getStencil(void) const1411 deUint32 getStencil (void) const { return m_stencil; }
1412
1413 private:
1414 UVec2 m_offset;
1415 UVec2 m_size;
1416
1417 float m_depth;
1418 deUint32 m_stencil;
1419 };
1420
1421 class SubpassRenderInfo
1422 {
1423 public:
SubpassRenderInfo(const RenderPass & renderPass,deUint32 subpassIndex,bool isSecondary_,const UVec2 & viewportOffset,const UVec2 & viewportSize,const Maybe<RenderQuad> & renderQuad,const vector<ColorClear> & colorClears,const Maybe<DepthStencilClear> & depthStencilClear)1424 SubpassRenderInfo (const RenderPass& renderPass,
1425 deUint32 subpassIndex,
1426
1427 bool isSecondary_,
1428
1429 const UVec2& viewportOffset,
1430 const UVec2& viewportSize,
1431
1432 const Maybe<RenderQuad>& renderQuad,
1433 const vector<ColorClear>& colorClears,
1434 const Maybe<DepthStencilClear>& depthStencilClear)
1435 : m_viewportOffset (viewportOffset)
1436 , m_viewportSize (viewportSize)
1437 , m_subpassIndex (subpassIndex)
1438 , m_isSecondary (isSecondary_)
1439 , m_flags (renderPass.getSubpasses()[subpassIndex].getFlags())
1440 , m_renderQuad (renderQuad)
1441 , m_colorClears (colorClears)
1442 , m_depthStencilClear (depthStencilClear)
1443 , m_colorAttachments (renderPass.getSubpasses()[subpassIndex].getColorAttachments())
1444 {
1445 for (deUint32 attachmentNdx = 0; attachmentNdx < (deUint32)m_colorAttachments.size(); attachmentNdx++)
1446 m_colorAttachmentInfo.push_back(renderPass.getAttachments()[m_colorAttachments[attachmentNdx].getAttachment()]);
1447
1448 if (renderPass.getSubpasses()[subpassIndex].getDepthStencilAttachment().getAttachment() != VK_ATTACHMENT_UNUSED)
1449 {
1450 m_depthStencilAttachment = tcu::just(renderPass.getSubpasses()[subpassIndex].getDepthStencilAttachment());
1451 m_depthStencilAttachmentInfo = tcu::just(renderPass.getAttachments()[renderPass.getSubpasses()[subpassIndex].getDepthStencilAttachment().getAttachment()]);
1452 }
1453 }
1454
getViewportOffset(void) const1455 const UVec2& getViewportOffset (void) const { return m_viewportOffset; }
getViewportSize(void) const1456 const UVec2& getViewportSize (void) const { return m_viewportSize; }
1457
getSubpassIndex(void) const1458 deUint32 getSubpassIndex (void) const { return m_subpassIndex; }
isSecondary(void) const1459 bool isSecondary (void) const { return m_isSecondary; }
1460
getRenderQuad(void) const1461 const Maybe<RenderQuad>& getRenderQuad (void) const { return m_renderQuad; }
getColorClears(void) const1462 const vector<ColorClear>& getColorClears (void) const { return m_colorClears; }
getDepthStencilClear(void) const1463 const Maybe<DepthStencilClear>& getDepthStencilClear (void) const { return m_depthStencilClear; }
1464
getColorAttachmentCount(void) const1465 deUint32 getColorAttachmentCount (void) const { return (deUint32)m_colorAttachments.size(); }
getColorAttachmentLayout(deUint32 attachmentNdx) const1466 VkImageLayout getColorAttachmentLayout (deUint32 attachmentNdx) const { return m_colorAttachments[attachmentNdx].getImageLayout(); }
getColorAttachmentIndex(deUint32 attachmentNdx) const1467 deUint32 getColorAttachmentIndex (deUint32 attachmentNdx) const { return m_colorAttachments[attachmentNdx].getAttachment(); }
getColorAttachment(deUint32 attachmentNdx) const1468 const Attachment& getColorAttachment (deUint32 attachmentNdx) const { return m_colorAttachmentInfo[attachmentNdx]; }
getDepthStencilAttachmentLayout(void) const1469 Maybe<VkImageLayout> getDepthStencilAttachmentLayout (void) const { return m_depthStencilAttachment ? tcu::just(m_depthStencilAttachment->getImageLayout()) : tcu::nothing<VkImageLayout>(); }
getDepthStencilAttachmentIndex(void) const1470 Maybe<deUint32> getDepthStencilAttachmentIndex (void) const { return m_depthStencilAttachment ? tcu::just(m_depthStencilAttachment->getAttachment()) : tcu::nothing<deUint32>(); };
getDepthStencilAttachment(void) const1471 const Maybe<Attachment>& getDepthStencilAttachment (void) const { return m_depthStencilAttachmentInfo; }
getSubpassFlags(void) const1472 VkSubpassDescriptionFlags getSubpassFlags (void) const { return m_flags; }
1473 private:
1474 UVec2 m_viewportOffset;
1475 UVec2 m_viewportSize;
1476
1477 deUint32 m_subpassIndex;
1478 bool m_isSecondary;
1479 VkSubpassDescriptionFlags m_flags;
1480
1481 Maybe<RenderQuad> m_renderQuad;
1482 vector<ColorClear> m_colorClears;
1483 Maybe<DepthStencilClear> m_depthStencilClear;
1484
1485 vector<AttachmentReference> m_colorAttachments;
1486 vector<Attachment> m_colorAttachmentInfo;
1487
1488 Maybe<AttachmentReference> m_depthStencilAttachment;
1489 Maybe<Attachment> m_depthStencilAttachmentInfo;
1490 };
1491
createSubpassPipeline(const DeviceInterface & vk,VkDevice device,VkRenderPass renderPass,VkShaderModule vertexShaderModule,VkShaderModule fragmentShaderModule,VkPipelineLayout pipelineLayout,const SubpassRenderInfo & renderInfo)1492 Move<VkPipeline> createSubpassPipeline (const DeviceInterface& vk,
1493 VkDevice device,
1494 VkRenderPass renderPass,
1495 VkShaderModule vertexShaderModule,
1496 VkShaderModule fragmentShaderModule,
1497 VkPipelineLayout pipelineLayout,
1498 const SubpassRenderInfo& renderInfo)
1499 {
1500 const VkSpecializationInfo emptyShaderSpecializations =
1501 {
1502 0u, // mapEntryCount
1503 DE_NULL, // pMap
1504 0u, // dataSize
1505 DE_NULL, // pData
1506 };
1507
1508 Maybe<VkSampleCountFlagBits> rasterSamples;
1509 vector<VkPipelineColorBlendAttachmentState> attachmentBlendStates;
1510
1511 for (deUint32 attachmentNdx = 0; attachmentNdx < renderInfo.getColorAttachmentCount(); attachmentNdx++)
1512 {
1513 const Attachment& attachment = renderInfo.getColorAttachment(attachmentNdx);
1514
1515 DE_ASSERT(!rasterSamples || *rasterSamples == attachment.getSamples());
1516
1517 rasterSamples = attachment.getSamples();
1518
1519 {
1520 const VkPipelineColorBlendAttachmentState attachmentBlendState =
1521 {
1522 VK_FALSE, // blendEnable
1523 VK_BLEND_FACTOR_SRC_ALPHA, // srcBlendColor
1524 VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, // destBlendColor
1525 VK_BLEND_OP_ADD, // blendOpColor
1526 VK_BLEND_FACTOR_ONE, // srcBlendAlpha
1527 VK_BLEND_FACTOR_ONE, // destBlendAlpha
1528 VK_BLEND_OP_ADD, // blendOpAlpha
1529 VK_COLOR_COMPONENT_R_BIT|VK_COLOR_COMPONENT_G_BIT|VK_COLOR_COMPONENT_B_BIT|VK_COLOR_COMPONENT_A_BIT, // channelWriteMask
1530 };
1531
1532 attachmentBlendStates.push_back(attachmentBlendState);
1533 }
1534 }
1535
1536 if (renderInfo.getDepthStencilAttachment())
1537 {
1538 const Attachment& attachment = *renderInfo.getDepthStencilAttachment();
1539
1540 DE_ASSERT(!rasterSamples || *rasterSamples == attachment.getSamples());
1541 rasterSamples = attachment.getSamples();
1542 }
1543
1544 // If there are no attachment use single sample
1545 if (!rasterSamples)
1546 rasterSamples = VK_SAMPLE_COUNT_1_BIT;
1547
1548 const VkPipelineShaderStageCreateInfo shaderStages[2] =
1549 {
1550 {
1551 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // sType
1552 DE_NULL, // pNext
1553 (VkPipelineShaderStageCreateFlags)0u,
1554 VK_SHADER_STAGE_VERTEX_BIT, // stage
1555 vertexShaderModule, // shader
1556 "main",
1557 &emptyShaderSpecializations
1558 },
1559 {
1560 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // sType
1561 DE_NULL, // pNext
1562 (VkPipelineShaderStageCreateFlags)0u,
1563 VK_SHADER_STAGE_FRAGMENT_BIT, // stage
1564 fragmentShaderModule, // shader
1565 "main",
1566 &emptyShaderSpecializations
1567 }
1568 };
1569 const VkVertexInputBindingDescription vertexBinding =
1570 {
1571 0u, // binding
1572 (deUint32)sizeof(tcu::Vec4), // strideInBytes
1573 VK_VERTEX_INPUT_RATE_VERTEX, // stepRate
1574 };
1575 const VkVertexInputAttributeDescription vertexAttrib =
1576 {
1577 0u, // location
1578 0u, // binding
1579 VK_FORMAT_R32G32B32A32_SFLOAT, // format
1580 0u, // offsetInBytes
1581 };
1582 const VkPipelineVertexInputStateCreateInfo vertexInputState =
1583 {
1584 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // sType
1585 DE_NULL, // pNext
1586 (VkPipelineVertexInputStateCreateFlags)0u,
1587 1u, // bindingCount
1588 &vertexBinding, // pVertexBindingDescriptions
1589 1u, // attributeCount
1590 &vertexAttrib, // pVertexAttributeDescriptions
1591 };
1592 const VkPipelineInputAssemblyStateCreateInfo inputAssemblyState =
1593 {
1594 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // sType
1595 DE_NULL, // pNext
1596 (VkPipelineInputAssemblyStateCreateFlags)0u,
1597 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // topology
1598 VK_FALSE, // primitiveRestartEnable
1599 };
1600 const VkViewport viewport =
1601 {
1602 (float)renderInfo.getViewportOffset().x(), (float)renderInfo.getViewportOffset().y(),
1603 (float)renderInfo.getViewportSize().x(), (float)renderInfo.getViewportSize().y(),
1604 0.0f, 1.0f
1605 };
1606 const VkRect2D scissor =
1607 {
1608 { (deInt32)renderInfo.getViewportOffset().x(), (deInt32)renderInfo.getViewportOffset().y() },
1609 { renderInfo.getViewportSize().x(), renderInfo.getViewportSize().y() }
1610 };
1611 const VkPipelineViewportStateCreateInfo viewportState =
1612 {
1613 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
1614 DE_NULL,
1615 (VkPipelineViewportStateCreateFlags)0u,
1616 1u,
1617 &viewport,
1618 1u,
1619 &scissor
1620 };
1621 const VkPipelineRasterizationStateCreateInfo rasterState =
1622 {
1623 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // sType
1624 DE_NULL, // pNext
1625 (VkPipelineRasterizationStateCreateFlags)0u,
1626 VK_TRUE, // depthClipEnable
1627 VK_FALSE, // rasterizerDiscardEnable
1628 VK_POLYGON_MODE_FILL, // fillMode
1629 VK_CULL_MODE_NONE, // cullMode
1630 VK_FRONT_FACE_COUNTER_CLOCKWISE, // frontFace
1631 VK_FALSE, // depthBiasEnable
1632 0.0f, // depthBias
1633 0.0f, // depthBiasClamp
1634 0.0f, // slopeScaledDepthBias
1635 1.0f // lineWidth
1636 };
1637 const VkPipelineMultisampleStateCreateInfo multisampleState =
1638 {
1639 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // sType
1640 DE_NULL, // pNext
1641 (VkPipelineMultisampleStateCreateFlags)0u,
1642 *rasterSamples, // rasterSamples
1643 VK_FALSE, // sampleShadingEnable
1644 0.0f, // minSampleShading
1645 DE_NULL, // pSampleMask
1646 VK_FALSE, // alphaToCoverageEnable
1647 VK_FALSE, // alphaToOneEnable
1648 };
1649 const VkPipelineDepthStencilStateCreateInfo depthStencilState =
1650 {
1651 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // sType
1652 DE_NULL, // pNext
1653 (VkPipelineDepthStencilStateCreateFlags)0u,
1654 VK_TRUE, // depthTestEnable
1655 VK_TRUE, // depthWriteEnable
1656 VK_COMPARE_OP_ALWAYS, // depthCompareOp
1657 VK_FALSE, // depthBoundsEnable
1658 VK_TRUE, // stencilTestEnable
1659 {
1660 VK_STENCIL_OP_REPLACE, // stencilFailOp
1661 VK_STENCIL_OP_REPLACE, // stencilPassOp
1662 VK_STENCIL_OP_REPLACE, // stencilDepthFailOp
1663 VK_COMPARE_OP_ALWAYS, // stencilCompareOp
1664 ~0u, // stencilCompareMask
1665 ~0u, // stencilWriteMask
1666 STENCIL_VALUE // stencilReference
1667 }, // front
1668 {
1669 VK_STENCIL_OP_REPLACE, // stencilFailOp
1670 VK_STENCIL_OP_REPLACE, // stencilPassOp
1671 VK_STENCIL_OP_REPLACE, // stencilDepthFailOp
1672 VK_COMPARE_OP_ALWAYS, // stencilCompareOp
1673 ~0u, // stencilCompareMask
1674 ~0u, // stencilWriteMask
1675 STENCIL_VALUE // stencilReference
1676 }, // back
1677
1678 0.0f, // minDepthBounds;
1679 1.0f // maxDepthBounds;
1680 };
1681 const VkPipelineColorBlendStateCreateInfo blendState =
1682 {
1683 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // sType
1684 DE_NULL, // pNext
1685 (VkPipelineColorBlendStateCreateFlags)0u,
1686 VK_FALSE, // logicOpEnable
1687 VK_LOGIC_OP_COPY, // logicOp
1688 (deUint32)attachmentBlendStates.size(), // attachmentCount
1689 attachmentBlendStates.empty() ? DE_NULL : &attachmentBlendStates[0],// pAttachments
1690 { 0.0f, 0.0f, 0.0f, 0.0f } // blendConst
1691 };
1692 const VkGraphicsPipelineCreateInfo createInfo =
1693 {
1694 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // sType
1695 DE_NULL, // pNext
1696 (VkPipelineCreateFlags)0u,
1697
1698 2, // stageCount
1699 shaderStages, // pStages
1700
1701 &vertexInputState, // pVertexInputState
1702 &inputAssemblyState, // pInputAssemblyState
1703 DE_NULL, // pTessellationState
1704 &viewportState, // pViewportState
1705 &rasterState, // pRasterState
1706 &multisampleState, // pMultisampleState
1707 &depthStencilState, // pDepthStencilState
1708 &blendState, // pColorBlendState
1709 (const VkPipelineDynamicStateCreateInfo*)DE_NULL, // pDynamicState
1710 pipelineLayout, // layout
1711
1712 renderPass, // renderPass
1713 renderInfo.getSubpassIndex(), // subpass
1714 DE_NULL, // basePipelineHandle
1715 0u // basePipelineIndex
1716 };
1717
1718 return createGraphicsPipeline(vk, device, DE_NULL, &createInfo);
1719 }
1720
1721 class SubpassRenderer
1722 {
1723 public:
SubpassRenderer(Context & context,const DeviceInterface & vk,VkDevice device,Allocator & allocator,VkRenderPass renderPass,VkFramebuffer framebuffer,VkCommandPool commandBufferPool,deUint32 queueFamilyIndex,const SubpassRenderInfo & renderInfo)1724 SubpassRenderer (Context& context,
1725 const DeviceInterface& vk,
1726 VkDevice device,
1727 Allocator& allocator,
1728 VkRenderPass renderPass,
1729 VkFramebuffer framebuffer,
1730 VkCommandPool commandBufferPool,
1731 deUint32 queueFamilyIndex,
1732 const SubpassRenderInfo& renderInfo)
1733 : m_renderInfo (renderInfo)
1734 {
1735 const deUint32 subpassIndex = renderInfo.getSubpassIndex();
1736
1737 if (renderInfo.getRenderQuad())
1738 {
1739 const RenderQuad& renderQuad = *renderInfo.getRenderQuad();
1740 const VkPipelineLayoutCreateInfo pipelineLayoutParams =
1741 {
1742 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // sType;
1743 DE_NULL, // pNext;
1744 (vk::VkPipelineLayoutCreateFlags)0,
1745 0u, // descriptorSetCount;
1746 DE_NULL, // pSetLayouts;
1747 0u, // pushConstantRangeCount;
1748 DE_NULL, // pPushConstantRanges;
1749 };
1750
1751 m_vertexShaderModule = createShaderModule(vk, device, context.getBinaryCollection().get(de::toString(subpassIndex) + "-vert"), 0u);
1752 m_fragmentShaderModule = createShaderModule(vk, device, context.getBinaryCollection().get(de::toString(subpassIndex) + "-frag"), 0u);
1753 m_pipelineLayout = createPipelineLayout(vk, device, &pipelineLayoutParams);
1754 m_pipeline = createSubpassPipeline(vk, device, renderPass, *m_vertexShaderModule, *m_fragmentShaderModule, *m_pipelineLayout, m_renderInfo);
1755
1756 m_vertexBuffer = createBuffer(vk, device, 0u, (VkDeviceSize)renderQuad.getVertexDataSize(), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_SHARING_MODE_EXCLUSIVE, 1u, &queueFamilyIndex);
1757 m_vertexBufferMemory = allocator.allocate(getBufferMemoryRequirements(vk, device, *m_vertexBuffer), MemoryRequirement::HostVisible);
1758
1759 bindBufferMemory(vk, device, *m_vertexBuffer, m_vertexBufferMemory->getMemory(), m_vertexBufferMemory->getOffset());
1760 uploadBufferData(vk, device, *m_vertexBufferMemory, renderQuad.getVertexDataSize(), renderQuad.getVertexPointer());
1761 }
1762
1763 if (renderInfo.isSecondary())
1764 {
1765 m_commandBuffer = allocateCommandBuffer(vk, device, commandBufferPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
1766
1767 beginCommandBuffer(vk, *m_commandBuffer, vk::VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, renderPass, subpassIndex, framebuffer, VK_FALSE, (VkQueryControlFlags)0, (VkQueryPipelineStatisticFlags)0);
1768 pushRenderCommands(vk, *m_commandBuffer);
1769 endCommandBuffer(vk, *m_commandBuffer);
1770 }
1771 }
1772
isSecondary(void) const1773 bool isSecondary (void) const
1774 {
1775 return m_commandBuffer;
1776 }
1777
getCommandBuffer(void) const1778 VkCommandBuffer getCommandBuffer (void) const
1779 {
1780 DE_ASSERT(isSecondary());
1781 return *m_commandBuffer;
1782 }
1783
pushRenderCommands(const DeviceInterface & vk,VkCommandBuffer commandBuffer)1784 void pushRenderCommands (const DeviceInterface& vk,
1785 VkCommandBuffer commandBuffer)
1786 {
1787 if (!m_renderInfo.getColorClears().empty())
1788 {
1789 const vector<ColorClear>& colorClears (m_renderInfo.getColorClears());
1790
1791 for (deUint32 attachmentNdx = 0; attachmentNdx < m_renderInfo.getColorAttachmentCount(); attachmentNdx++)
1792 {
1793 const ColorClear& colorClear = colorClears[attachmentNdx];
1794 const VkClearAttachment attachment =
1795 {
1796 VK_IMAGE_ASPECT_COLOR_BIT,
1797 attachmentNdx,
1798 makeClearValue(colorClear.getColor()),
1799 };
1800 const VkClearRect rect =
1801 {
1802 {
1803 { (deInt32)colorClear.getOffset().x(), (deInt32)colorClear.getOffset().y() },
1804 { colorClear.getSize().x(), colorClear.getSize().y() }
1805 }, // rect
1806 0u, // baseArrayLayer
1807 1u, // layerCount
1808 };
1809
1810 vk.cmdClearAttachments(commandBuffer, 1u, &attachment, 1u, &rect);
1811 }
1812 }
1813
1814 if (m_renderInfo.getDepthStencilClear())
1815 {
1816 const DepthStencilClear& depthStencilClear = *m_renderInfo.getDepthStencilClear();
1817 const deUint32 attachmentNdx = m_renderInfo.getColorAttachmentCount();
1818 tcu::TextureFormat format = mapVkFormat(m_renderInfo.getDepthStencilAttachment()->getFormat());
1819 const VkClearAttachment attachment =
1820 {
1821 (VkImageAspectFlags)((hasDepthComponent(format.order) ? VK_IMAGE_ASPECT_DEPTH_BIT : 0)
1822 | (hasStencilComponent(format.order) ? VK_IMAGE_ASPECT_STENCIL_BIT : 0)),
1823 attachmentNdx,
1824 makeClearValueDepthStencil(depthStencilClear.getDepth(), depthStencilClear.getStencil())
1825 };
1826 const VkClearRect rect =
1827 {
1828 {
1829 { (deInt32)depthStencilClear.getOffset().x(), (deInt32)depthStencilClear.getOffset().y() },
1830 { depthStencilClear.getSize().x(), depthStencilClear.getSize().y() }
1831 }, // rect
1832 0u, // baseArrayLayer
1833 1u, // layerCount
1834 };
1835
1836 vk.cmdClearAttachments(commandBuffer, 1u, &attachment, 1u, &rect);
1837 }
1838
1839 if (m_renderInfo.getRenderQuad())
1840 {
1841 const VkDeviceSize offset = 0;
1842 const VkBuffer vertexBuffer = *m_vertexBuffer;
1843
1844 vk.cmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
1845 vk.cmdBindVertexBuffers(commandBuffer, 0u, 1u, &vertexBuffer, &offset);
1846 vk.cmdDraw(commandBuffer, 6u, 1u, 0u, 0u);
1847 }
1848 }
1849
1850 private:
1851 const SubpassRenderInfo m_renderInfo;
1852 Move<VkCommandBuffer> m_commandBuffer;
1853 Move<VkPipeline> m_pipeline;
1854 Move<VkPipelineLayout> m_pipelineLayout;
1855
1856 Move<VkShaderModule> m_vertexShaderModule;
1857
1858 Move<VkShaderModule> m_fragmentShaderModule;
1859
1860 Move<VkBuffer> m_vertexBuffer;
1861 de::MovePtr<Allocation> m_vertexBufferMemory;
1862 };
1863
pushImageInitializationCommands(const DeviceInterface & vk,VkCommandBuffer commandBuffer,const vector<Attachment> & attachmentInfo,const vector<de::SharedPtr<AttachmentResources>> & attachmentResources,deUint32 queueIndex,const vector<Maybe<VkClearValue>> & clearValues)1864 void pushImageInitializationCommands (const DeviceInterface& vk,
1865 VkCommandBuffer commandBuffer,
1866 const vector<Attachment>& attachmentInfo,
1867 const vector<de::SharedPtr<AttachmentResources> >& attachmentResources,
1868 deUint32 queueIndex,
1869 const vector<Maybe<VkClearValue> >& clearValues)
1870 {
1871 {
1872 vector<VkImageMemoryBarrier> initializeLayouts;
1873
1874 for (size_t attachmentNdx = 0; attachmentNdx < attachmentInfo.size(); attachmentNdx++)
1875 {
1876 if (!clearValues[attachmentNdx])
1877 continue;
1878
1879 const VkImageMemoryBarrier barrier =
1880 {
1881 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType;
1882 DE_NULL, // pNext;
1883
1884 (VkAccessFlags)0, // srcAccessMask
1885 getAllMemoryReadFlags() | VK_ACCESS_TRANSFER_WRITE_BIT, // dstAccessMask
1886
1887 VK_IMAGE_LAYOUT_UNDEFINED, // oldLayout
1888 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // newLayout;
1889
1890 queueIndex, // srcQueueFamilyIndex;
1891 queueIndex, // destQueueFamilyIndex;
1892
1893 attachmentResources[attachmentNdx]->getImage(), // image;
1894 { // subresourceRange;
1895 getImageAspectFlags(attachmentInfo[attachmentNdx].getFormat()), // aspect;
1896 0, // baseMipLevel;
1897 1, // mipLevels;
1898 0, // baseArraySlice;
1899 1 // arraySize;
1900 }
1901 };
1902
1903 initializeLayouts.push_back(barrier);
1904 }
1905
1906 if (!initializeLayouts.empty())
1907 vk.cmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
1908 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (VkDependencyFlags)0,
1909 0, (const VkMemoryBarrier*)DE_NULL,
1910 0, (const VkBufferMemoryBarrier*)DE_NULL,
1911 (deUint32)initializeLayouts.size(), &initializeLayouts[0]);
1912 }
1913
1914 for (size_t attachmentNdx = 0; attachmentNdx < attachmentInfo.size(); attachmentNdx++)
1915 {
1916 if (!clearValues[attachmentNdx])
1917 continue;
1918
1919 const tcu::TextureFormat format = mapVkFormat(attachmentInfo[attachmentNdx].getFormat());
1920
1921 if (hasStencilComponent(format.order) || hasDepthComponent(format.order))
1922 {
1923 const float clearNan = tcu::Float32::nan().asFloat();
1924 const float clearDepth = hasDepthComponent(format.order) ? clearValues[attachmentNdx]->depthStencil.depth : clearNan;
1925 const deUint32 clearStencil = hasStencilComponent(format.order) ? clearValues[attachmentNdx]->depthStencil.stencil : ~0u;
1926 const VkClearDepthStencilValue depthStencil =
1927 {
1928 clearDepth,
1929 clearStencil
1930 };
1931 const VkImageSubresourceRange range =
1932 {
1933 (VkImageAspectFlags)((hasDepthComponent(format.order) ? VK_IMAGE_ASPECT_DEPTH_BIT : 0)
1934 | (hasStencilComponent(format.order) ? VK_IMAGE_ASPECT_STENCIL_BIT : 0)),
1935 0,
1936 1,
1937 0,
1938 1
1939 };
1940
1941 vk.cmdClearDepthStencilImage(commandBuffer, attachmentResources[attachmentNdx]->getImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &depthStencil, 1, &range);
1942 }
1943 else
1944 {
1945 const VkImageSubresourceRange range =
1946 {
1947 VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask;
1948 0, // baseMipLevel;
1949 1, // mipLevels;
1950 0, // baseArrayLayer;
1951 1 // layerCount;
1952 };
1953 const VkClearColorValue clearColor = clearValues[attachmentNdx]->color;
1954
1955 vk.cmdClearColorImage(commandBuffer, attachmentResources[attachmentNdx]->getImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColor, 1, &range);
1956 }
1957 }
1958
1959 {
1960 vector<VkImageMemoryBarrier> renderPassLayouts;
1961
1962 for (size_t attachmentNdx = 0; attachmentNdx < attachmentInfo.size(); attachmentNdx++)
1963 {
1964 const VkImageLayout oldLayout = clearValues[attachmentNdx] ? VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL : VK_IMAGE_LAYOUT_UNDEFINED;
1965 const VkImageMemoryBarrier barrier =
1966 {
1967 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType;
1968 DE_NULL, // pNext;
1969
1970 (oldLayout != VK_IMAGE_LAYOUT_UNDEFINED ? getAllMemoryWriteFlags() : (VkAccessFlags)0), // srcAccessMask
1971 getAllMemoryReadFlags() | getMemoryFlagsForLayout(attachmentInfo[attachmentNdx].getInitialLayout()), // dstAccessMask
1972
1973 oldLayout, // oldLayout
1974 attachmentInfo[attachmentNdx].getInitialLayout(), // newLayout;
1975
1976 queueIndex, // srcQueueFamilyIndex;
1977 queueIndex, // destQueueFamilyIndex;
1978
1979 attachmentResources[attachmentNdx]->getImage(), // image;
1980 { // subresourceRange;
1981 getImageAspectFlags(attachmentInfo[attachmentNdx].getFormat()), // aspect;
1982 0, // baseMipLevel;
1983 1, // mipLevels;
1984 0, // baseArraySlice;
1985 1 // arraySize;
1986 }
1987 };
1988
1989 renderPassLayouts.push_back(barrier);
1990 }
1991
1992 if (!renderPassLayouts.empty())
1993 vk.cmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
1994 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (VkDependencyFlags)0,
1995 0, (const VkMemoryBarrier*)DE_NULL,
1996 0, (const VkBufferMemoryBarrier*)DE_NULL,
1997 (deUint32)renderPassLayouts.size(), &renderPassLayouts[0]);
1998 }
1999 }
2000
pushRenderPassCommands(const DeviceInterface & vk,VkCommandBuffer commandBuffer,VkRenderPass renderPass,VkFramebuffer framebuffer,const vector<de::SharedPtr<SubpassRenderer>> & subpassRenderers,const UVec2 & renderPos,const UVec2 & renderSize,const vector<Maybe<VkClearValue>> & renderPassClearValues,TestConfig::RenderTypes render)2001 void pushRenderPassCommands (const DeviceInterface& vk,
2002 VkCommandBuffer commandBuffer,
2003 VkRenderPass renderPass,
2004 VkFramebuffer framebuffer,
2005 const vector<de::SharedPtr<SubpassRenderer> >& subpassRenderers,
2006 const UVec2& renderPos,
2007 const UVec2& renderSize,
2008 const vector<Maybe<VkClearValue> >& renderPassClearValues,
2009 TestConfig::RenderTypes render)
2010 {
2011 const float clearNan = tcu::Float32::nan().asFloat();
2012 vector<VkClearValue> attachmentClearValues;
2013
2014 for (size_t attachmentNdx = 0; attachmentNdx < renderPassClearValues.size(); attachmentNdx++)
2015 {
2016 if (renderPassClearValues[attachmentNdx])
2017 attachmentClearValues.push_back(*renderPassClearValues[attachmentNdx]);
2018 else
2019 attachmentClearValues.push_back(makeClearValueColorF32(clearNan, clearNan, clearNan, clearNan));
2020 }
2021
2022 {
2023 const VkRect2D renderArea =
2024 {
2025 { (deInt32)renderPos.x(), (deInt32)renderPos.y() },
2026 { renderSize.x(), renderSize.y() }
2027 };
2028
2029 for (size_t subpassNdx = 0; subpassNdx < subpassRenderers.size(); subpassNdx++)
2030 {
2031 const VkSubpassContents contents = subpassRenderers[subpassNdx]->isSecondary() ? VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS : VK_SUBPASS_CONTENTS_INLINE;
2032
2033 if (subpassNdx == 0)
2034 cmdBeginRenderPass(vk, commandBuffer, renderPass, framebuffer, renderArea, (deUint32)attachmentClearValues.size(), attachmentClearValues.empty() ? DE_NULL : &attachmentClearValues[0], contents);
2035 else
2036 vk.cmdNextSubpass(commandBuffer, contents);
2037
2038 if (render)
2039 {
2040 if (contents == VK_SUBPASS_CONTENTS_INLINE)
2041 {
2042 subpassRenderers[subpassNdx]->pushRenderCommands(vk, commandBuffer);
2043 }
2044 else if (contents == VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS)
2045 {
2046 const VkCommandBuffer cmd = subpassRenderers[subpassNdx]->getCommandBuffer();
2047 vk.cmdExecuteCommands(commandBuffer, 1, &cmd);
2048 }
2049 else
2050 DE_FATAL("Invalid contents");
2051 }
2052 }
2053
2054 vk.cmdEndRenderPass(commandBuffer);
2055 }
2056 }
2057
pushReadImagesToBuffers(const DeviceInterface & vk,VkCommandBuffer commandBuffer,deUint32 queueIndex,const vector<de::SharedPtr<AttachmentResources>> & attachmentResources,const vector<Attachment> & attachmentInfo,const vector<bool> & isLazy,const UVec2 & targetSize)2058 void pushReadImagesToBuffers (const DeviceInterface& vk,
2059 VkCommandBuffer commandBuffer,
2060 deUint32 queueIndex,
2061
2062 const vector<de::SharedPtr<AttachmentResources> >& attachmentResources,
2063 const vector<Attachment>& attachmentInfo,
2064 const vector<bool>& isLazy,
2065
2066 const UVec2& targetSize)
2067 {
2068 {
2069 vector<VkImageMemoryBarrier> imageBarriers;
2070
2071 for (size_t attachmentNdx = 0; attachmentNdx < attachmentInfo.size(); attachmentNdx++)
2072 {
2073 if (isLazy[attachmentNdx])
2074 continue;
2075
2076 const VkImageLayout oldLayout = attachmentInfo[attachmentNdx].getFinalLayout();
2077 const VkImageMemoryBarrier barrier =
2078 {
2079 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
2080 DE_NULL, // pNext
2081
2082 getAllMemoryWriteFlags() | getMemoryFlagsForLayout(oldLayout), // srcAccessMask
2083 getAllMemoryReadFlags(), // dstAccessMask
2084
2085 oldLayout, // oldLayout
2086 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // newLayout
2087
2088 queueIndex, // srcQueueFamilyIndex
2089 queueIndex, // destQueueFamilyIndex
2090
2091 attachmentResources[attachmentNdx]->getImage(), // image
2092 { // subresourceRange
2093 getImageAspectFlags(attachmentInfo[attachmentNdx].getFormat()), // aspect;
2094 0, // baseMipLevel
2095 1, // mipLevels
2096 0, // baseArraySlice
2097 1 // arraySize
2098 }
2099 };
2100
2101 imageBarriers.push_back(barrier);
2102 }
2103
2104 if (!imageBarriers.empty())
2105 vk.cmdPipelineBarrier(commandBuffer,
2106 getAllPipelineStageFlags(),
2107 getAllPipelineStageFlags(),
2108 (VkDependencyFlags)0,
2109 0, (const VkMemoryBarrier*)DE_NULL,
2110 0, (const VkBufferMemoryBarrier*)DE_NULL,
2111 (deUint32)imageBarriers.size(), &imageBarriers[0]);
2112 }
2113
2114 for (size_t attachmentNdx = 0; attachmentNdx < attachmentInfo.size(); attachmentNdx++)
2115 {
2116 if (isLazy[attachmentNdx])
2117 continue;
2118
2119 const tcu::TextureFormat::ChannelOrder order = mapVkFormat(attachmentInfo[attachmentNdx].getFormat()).order;
2120 const VkBufferImageCopy rect =
2121 {
2122 0, // bufferOffset
2123 0, // bufferRowLength
2124 0, // bufferImageHeight
2125 { // imageSubresource
2126 getPrimaryImageAspect(mapVkFormat(attachmentInfo[attachmentNdx].getFormat()).order), // aspect
2127 0, // mipLevel
2128 0, // arraySlice
2129 1 // arraySize
2130 },
2131 { 0, 0, 0 }, // imageOffset
2132 { targetSize.x(), targetSize.y(), 1u } // imageExtent
2133 };
2134
2135 vk.cmdCopyImageToBuffer(commandBuffer, attachmentResources[attachmentNdx]->getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, attachmentResources[attachmentNdx]->getBuffer(), 1, &rect);
2136
2137 if (tcu::TextureFormat::DS == order)
2138 {
2139 const VkBufferImageCopy stencilRect =
2140 {
2141 0, // bufferOffset
2142 0, // bufferRowLength
2143 0, // bufferImageHeight
2144 { // imageSubresource
2145 VK_IMAGE_ASPECT_STENCIL_BIT, // aspect
2146 0, // mipLevel
2147 0, // arraySlice
2148 1 // arraySize
2149 },
2150 { 0, 0, 0 }, // imageOffset
2151 { targetSize.x(), targetSize.y(), 1u } // imageExtent
2152 };
2153
2154 vk.cmdCopyImageToBuffer(commandBuffer, attachmentResources[attachmentNdx]->getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, attachmentResources[attachmentNdx]->getSecondaryBuffer(), 1, &stencilRect);
2155 }
2156 }
2157
2158 {
2159 vector<VkBufferMemoryBarrier> bufferBarriers;
2160
2161 for (size_t attachmentNdx = 0; attachmentNdx < attachmentInfo.size(); attachmentNdx++)
2162 {
2163 if (isLazy[attachmentNdx])
2164 continue;
2165
2166 const tcu::TextureFormat::ChannelOrder order = mapVkFormat(attachmentInfo[attachmentNdx].getFormat()).order;
2167 const VkBufferMemoryBarrier bufferBarrier =
2168 {
2169 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
2170 DE_NULL,
2171
2172 getAllMemoryWriteFlags(),
2173 getAllMemoryReadFlags(),
2174
2175 queueIndex,
2176 queueIndex,
2177
2178 attachmentResources[attachmentNdx]->getBuffer(),
2179 0,
2180 attachmentResources[attachmentNdx]->getBufferSize()
2181 };
2182
2183 bufferBarriers.push_back(bufferBarrier);
2184
2185 if (tcu::TextureFormat::DS == order)
2186 {
2187 const VkBufferMemoryBarrier secondaryBufferBarrier =
2188 {
2189 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
2190 DE_NULL,
2191
2192 getAllMemoryWriteFlags(),
2193 getAllMemoryReadFlags(),
2194
2195 queueIndex,
2196 queueIndex,
2197
2198 attachmentResources[attachmentNdx]->getSecondaryBuffer(),
2199 0,
2200 attachmentResources[attachmentNdx]->getSecondaryBufferSize()
2201 };
2202
2203 bufferBarriers.push_back(secondaryBufferBarrier);
2204 }
2205 }
2206
2207 if (!bufferBarriers.empty())
2208 vk.cmdPipelineBarrier(commandBuffer,
2209 getAllPipelineStageFlags(),
2210 getAllPipelineStageFlags(),
2211 (VkDependencyFlags)0,
2212 0, (const VkMemoryBarrier*)DE_NULL,
2213 (deUint32)bufferBarriers.size(), &bufferBarriers[0],
2214 0, (const VkImageMemoryBarrier*)DE_NULL);
2215 }
2216 }
2217
clear(const PixelBufferAccess & access,const VkClearValue & value)2218 void clear (const PixelBufferAccess& access, const VkClearValue& value)
2219 {
2220 const tcu::TextureFormat& format = access.getFormat();
2221
2222 if (tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order))
2223 {
2224 if (tcu::hasDepthComponent(format.order))
2225 tcu::clearDepth(access, value.depthStencil.depth);
2226
2227 if (tcu::hasStencilComponent(format.order))
2228 tcu::clearStencil(access, value.depthStencil.stencil);
2229 }
2230 else
2231 {
2232 if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_FLOATING_POINT
2233 || tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT
2234 || tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT)
2235 {
2236 const tcu::Vec4 color (value.color.float32[0],
2237 value.color.float32[1],
2238 value.color.float32[2],
2239 value.color.float32[3]);
2240
2241 if (tcu::isSRGB(format))
2242 tcu::clear(access, tcu::linearToSRGB(color));
2243 else
2244 tcu::clear(access, color);
2245 }
2246 else if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
2247 {
2248 const tcu::UVec4 color (value.color.uint32[0],
2249 value.color.uint32[1],
2250 value.color.uint32[2],
2251 value.color.uint32[3]);
2252
2253 tcu::clear(access, color);
2254 }
2255 else if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
2256 {
2257 const tcu::IVec4 color (value.color.int32[0],
2258 value.color.int32[1],
2259 value.color.int32[2],
2260 value.color.int32[3]);
2261
2262 tcu::clear(access, color);
2263 }
2264 else
2265 DE_FATAL("Unknown channel class");
2266 }
2267 }
2268
computeUvs(const IVec2 & posA,const IVec2 & posB,const IVec2 & pos)2269 Vec4 computeUvs (const IVec2& posA, const IVec2& posB, const IVec2& pos)
2270 {
2271 const float u = de::clamp((float)(pos.x() - posA.x()) / (float)(posB.x() - posA.x()), 0.0f, 1.0f);
2272 const float v = de::clamp((float)(pos.y() - posA.y()) / (float)(posB.y() - posA.y()), 0.0f, 1.0f);
2273
2274 return Vec4(u, v, u * v, (u + v) / 2.0f);
2275 }
2276
renderReferenceImages(vector<tcu::TextureLevel> & referenceAttachments,const RenderPass & renderPassInfo,const UVec2 & targetSize,const vector<Maybe<VkClearValue>> & imageClearValues,const vector<Maybe<VkClearValue>> & renderPassClearValues,const vector<SubpassRenderInfo> & subpassRenderInfo,const UVec2 & renderPos,const UVec2 & renderSize)2277 void renderReferenceImages (vector<tcu::TextureLevel>& referenceAttachments,
2278 const RenderPass& renderPassInfo,
2279 const UVec2& targetSize,
2280 const vector<Maybe<VkClearValue> >& imageClearValues,
2281 const vector<Maybe<VkClearValue> >& renderPassClearValues,
2282 const vector<SubpassRenderInfo>& subpassRenderInfo,
2283 const UVec2& renderPos,
2284 const UVec2& renderSize)
2285 {
2286 const vector<Subpass>& subpasses = renderPassInfo.getSubpasses();
2287 vector<bool> attachmentUsed (renderPassInfo.getAttachments().size(), false);
2288
2289 referenceAttachments.resize(renderPassInfo.getAttachments().size());
2290
2291 for (size_t attachmentNdx = 0; attachmentNdx < renderPassInfo.getAttachments().size(); attachmentNdx++)
2292 {
2293 const Attachment attachment = renderPassInfo.getAttachments()[attachmentNdx];
2294 const tcu::TextureFormat format = mapVkFormat(attachment.getFormat());
2295 const tcu::TextureFormatInfo textureInfo = tcu::getTextureFormatInfo(format);
2296 tcu::TextureLevel& reference = referenceAttachments[attachmentNdx];
2297 const bool isDepthOrStencilAttachment = hasDepthComponent(format.order) || hasStencilComponent(format.order);
2298
2299 reference = tcu::TextureLevel(format, targetSize.x(), targetSize.y());
2300
2301 if (imageClearValues[attachmentNdx])
2302 clear(reference.getAccess(), *imageClearValues[attachmentNdx]);
2303 else
2304 {
2305 // Fill with grid if image contentst are undefined before renderpass
2306 if (isDepthOrStencilAttachment)
2307 {
2308 if (tcu::hasDepthComponent(format.order))
2309 tcu::fillWithGrid(tcu::getEffectiveDepthStencilAccess(reference.getAccess(), tcu::Sampler::MODE_DEPTH), 2, textureInfo.valueMin, textureInfo.valueMax);
2310
2311 if (tcu::hasStencilComponent(format.order))
2312 tcu::fillWithGrid(tcu::getEffectiveDepthStencilAccess(reference.getAccess(), tcu::Sampler::MODE_STENCIL), 2, textureInfo.valueMin, textureInfo.valueMax);
2313 }
2314 else
2315 tcu::fillWithGrid(reference.getAccess(), 2, textureInfo.valueMin, textureInfo.valueMax);
2316 }
2317 }
2318
2319 for (size_t subpassNdx = 0; subpassNdx < subpasses.size(); subpassNdx++)
2320 {
2321 const Subpass& subpass = subpasses[subpassNdx];
2322 const SubpassRenderInfo& renderInfo = subpassRenderInfo[subpassNdx];
2323 const vector<AttachmentReference>& colorAttachments = subpass.getColorAttachments();
2324
2325 // Apply load op if attachment was used for the first time
2326 for (size_t attachmentNdx = 0; attachmentNdx < colorAttachments.size(); attachmentNdx++)
2327 {
2328 const deUint32 attachmentIndex = colorAttachments[attachmentNdx].getAttachment();
2329
2330 if (!attachmentUsed[attachmentIndex])
2331 {
2332 const Attachment& attachment = renderPassInfo.getAttachments()[attachmentIndex];
2333 tcu::TextureLevel& reference = referenceAttachments[attachmentIndex];
2334
2335 DE_ASSERT(!tcu::hasDepthComponent(reference.getFormat().order));
2336 DE_ASSERT(!tcu::hasStencilComponent(reference.getFormat().order));
2337
2338 if (attachment.getLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR)
2339 clear(tcu::getSubregion(reference.getAccess(), renderPos.x(), renderPos.y(), renderSize.x(), renderSize.y()), *renderPassClearValues[attachmentIndex]);
2340 else if (attachment.getLoadOp() == VK_ATTACHMENT_LOAD_OP_DONT_CARE)
2341 {
2342 const tcu::TextureFormatInfo textureInfo = tcu::getTextureFormatInfo(reference.getFormat());
2343
2344 tcu::fillWithGrid(tcu::getSubregion(reference.getAccess(), renderPos.x(), renderPos.y(), renderSize.x(), renderSize.y()), 2, textureInfo.valueMin, textureInfo.valueMax);
2345 }
2346
2347 attachmentUsed[attachmentIndex] = true;
2348 }
2349 }
2350
2351 // Apply load op to depth/stencil attachment if it was used for the first time
2352 if (subpass.getDepthStencilAttachment().getAttachment() != VK_ATTACHMENT_UNUSED && !attachmentUsed[subpass.getDepthStencilAttachment().getAttachment()])
2353 {
2354 const deUint32 attachmentIndex = subpass.getDepthStencilAttachment().getAttachment();
2355
2356 // Apply load op if attachment was used for the first time
2357 if (!attachmentUsed[attachmentIndex])
2358 {
2359 const Attachment& attachment = renderPassInfo.getAttachments()[attachmentIndex];
2360 tcu::TextureLevel& reference = referenceAttachments[attachmentIndex];
2361
2362 if (tcu::hasDepthComponent(reference.getFormat().order))
2363 {
2364 if (attachment.getLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR)
2365 clear(tcu::getSubregion(tcu::getEffectiveDepthStencilAccess(reference.getAccess(), tcu::Sampler::MODE_DEPTH), renderPos.x(), renderPos.y(), renderSize.x(), renderSize.y()), *renderPassClearValues[attachmentIndex]);
2366 else if (attachment.getLoadOp() == VK_ATTACHMENT_LOAD_OP_DONT_CARE)
2367 {
2368 const tcu::TextureFormatInfo textureInfo = tcu::getTextureFormatInfo(reference.getFormat());
2369
2370 tcu::fillWithGrid(tcu::getSubregion(tcu::getEffectiveDepthStencilAccess(reference.getAccess(), tcu::Sampler::MODE_DEPTH), renderPos.x(), renderPos.y(), renderSize.x(), renderSize.y()), 2, textureInfo.valueMin, textureInfo.valueMax);
2371 }
2372 }
2373
2374 if (tcu::hasStencilComponent(reference.getFormat().order))
2375 {
2376 if (attachment.getStencilLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR)
2377 clear(tcu::getSubregion(tcu::getEffectiveDepthStencilAccess(reference.getAccess(), tcu::Sampler::MODE_STENCIL), renderPos.x(), renderPos.y(), renderSize.x(), renderSize.y()), *renderPassClearValues[attachmentIndex]);
2378 else if (attachment.getStencilLoadOp() == VK_ATTACHMENT_LOAD_OP_DONT_CARE)
2379 {
2380 const tcu::TextureFormatInfo textureInfo = tcu::getTextureFormatInfo(reference.getFormat());
2381
2382 tcu::fillWithGrid(tcu::getSubregion(tcu::getEffectiveDepthStencilAccess(reference.getAccess(), tcu::Sampler::MODE_STENCIL), renderPos.x(), renderPos.y(), renderSize.x(), renderSize.y()), 2, textureInfo.valueMin, textureInfo.valueMax);
2383 }
2384 }
2385 }
2386
2387 attachmentUsed[attachmentIndex] = true;
2388 }
2389
2390 for (size_t colorClearNdx = 0; colorClearNdx < renderInfo.getColorClears().size(); colorClearNdx++)
2391 {
2392 const ColorClear& colorClear = renderInfo.getColorClears()[colorClearNdx];
2393 const UVec2 offset = colorClear.getOffset();
2394 const UVec2 size = colorClear.getSize();
2395 tcu::TextureLevel& reference = referenceAttachments[subpass.getColorAttachments()[colorClearNdx].getAttachment()];
2396 VkClearValue value;
2397
2398 value.color = colorClear.getColor();
2399
2400 clear(tcu::getSubregion(reference.getAccess(), offset.x(), offset.y(), 0, size.x(), size.y(), 1), value);
2401 }
2402
2403 if (renderInfo.getDepthStencilClear())
2404 {
2405 const DepthStencilClear& dsClear = *renderInfo.getDepthStencilClear();
2406 const UVec2 offset = dsClear.getOffset();
2407 const UVec2 size = dsClear.getSize();
2408 tcu::TextureLevel& reference = referenceAttachments[subpass.getDepthStencilAttachment().getAttachment()];
2409
2410 if (tcu::hasDepthComponent(reference.getFormat().order))
2411 clearDepth(tcu::getSubregion(reference.getAccess(), offset.x(), offset.y(), 0, size.x(), size.y(), 1), dsClear.getDepth());
2412
2413 if (tcu::hasStencilComponent(reference.getFormat().order))
2414 clearStencil(tcu::getSubregion(reference.getAccess(), offset.x(), offset.y(), 0, size.x(), size.y(), 1), dsClear.getStencil());
2415 }
2416
2417 if (renderInfo.getRenderQuad())
2418 {
2419 const RenderQuad& renderQuad = *renderInfo.getRenderQuad();
2420 const Vec4 posA = renderQuad.getCornerA();
2421 const Vec4 posB = renderQuad.getCornerB();
2422 const Vec2 origin = Vec2((float)renderInfo.getViewportOffset().x(), (float)renderInfo.getViewportOffset().y()) + Vec2((float)renderInfo.getViewportSize().x(), (float)renderInfo.getViewportSize().y()) / Vec2(2.0f);
2423 const Vec2 p = Vec2((float)renderInfo.getViewportSize().x(), (float)renderInfo.getViewportSize().y()) / Vec2(2.0f);
2424 const IVec2 posAI ((deInt32)(origin.x() + (p.x() * posA.x())),
2425 (deInt32)(origin.y() + (p.y() * posA.y())));
2426 const IVec2 posBI ((deInt32)(origin.x() + (p.x() * posB.x())),
2427 (deInt32)(origin.y() + (p.y() * posB.y())));
2428
2429 for (size_t attachmentRefNdx = 0; attachmentRefNdx < subpass.getColorAttachments().size(); attachmentRefNdx++)
2430 {
2431 const Attachment attachment = renderPassInfo.getAttachments()[subpass.getColorAttachments()[attachmentRefNdx].getAttachment()];
2432 const tcu::TextureFormatInfo textureInfo = tcu::getTextureFormatInfo(mapVkFormat(attachment.getFormat()));
2433 tcu::TextureLevel& referenceTexture = referenceAttachments[subpass.getColorAttachments()[attachmentRefNdx].getAttachment()];
2434 const bool srgb = tcu::isSRGB(referenceTexture.getFormat());
2435 const PixelBufferAccess reference = referenceTexture.getAccess();
2436 const float clampMin = (float)(-MAX_INTEGER_VALUE);
2437 const float clampMax = (float)(MAX_INTEGER_VALUE);
2438 const Vec4 valueMax (de::clamp(textureInfo.valueMax[0], clampMin, clampMax),
2439 de::clamp(textureInfo.valueMax[1], clampMin, clampMax),
2440 de::clamp(textureInfo.valueMax[2], clampMin, clampMax),
2441 de::clamp(textureInfo.valueMax[3], clampMin, clampMax));
2442
2443 const Vec4 valueMin (de::clamp(textureInfo.valueMin[0], clampMin, clampMax),
2444 de::clamp(textureInfo.valueMin[1], clampMin, clampMax),
2445 de::clamp(textureInfo.valueMin[2], clampMin, clampMax),
2446 de::clamp(textureInfo.valueMin[3], clampMin, clampMax));
2447
2448 DE_ASSERT(posAI.x() < posBI.x());
2449 DE_ASSERT(posAI.y() < posBI.y());
2450
2451 for (int y = posAI.y(); y <= (int)posBI.y(); y++)
2452 for (int x = posAI.x(); x <= (int)posBI.x(); x++)
2453 {
2454 const Vec4 uvs = computeUvs(posAI, posBI, IVec2(x, y));
2455 const Vec4 color = valueMax * uvs + valueMin * (Vec4(1.0f) - uvs);
2456
2457 if (srgb)
2458 reference.setPixel(tcu::linearToSRGB(color), x, y);
2459 else
2460 reference.setPixel(color, x, y);
2461 }
2462 }
2463
2464 if (subpass.getDepthStencilAttachment().getAttachment() != VK_ATTACHMENT_UNUSED)
2465 {
2466 tcu::TextureLevel& referenceTexture = referenceAttachments[subpass.getDepthStencilAttachment().getAttachment()];
2467 const PixelBufferAccess reference = referenceTexture.getAccess();
2468
2469 DE_ASSERT(posAI.x() < posBI.x());
2470 DE_ASSERT(posAI.y() < posBI.y());
2471
2472 for (int y = posAI.y(); y <= (int)posBI.y(); y++)
2473 for (int x = posAI.x(); x <= (int)posBI.x(); x++)
2474 {
2475 const Vec4 uvs = computeUvs(posAI, posBI, IVec2(x, y));
2476
2477 if (tcu::hasDepthComponent(reference.getFormat().order))
2478 reference.setPixDepth(uvs.x(), x, y);
2479
2480 if (tcu::hasStencilComponent(reference.getFormat().order))
2481 reference.setPixStencil(STENCIL_VALUE, x, y);
2482 }
2483 }
2484 }
2485 }
2486
2487 // Mark all attachments that were used but not stored as undefined
2488 for (size_t attachmentNdx = 0; attachmentNdx < renderPassInfo.getAttachments().size(); attachmentNdx++)
2489 {
2490 const Attachment attachment = renderPassInfo.getAttachments()[attachmentNdx];
2491 const tcu::TextureFormat format = mapVkFormat(attachment.getFormat());
2492 const tcu::TextureFormatInfo textureInfo = tcu::getTextureFormatInfo(format);
2493 tcu::TextureLevel& reference = referenceAttachments[attachmentNdx];
2494
2495 if (attachmentUsed[attachmentNdx] && renderPassInfo.getAttachments()[attachmentNdx].getStoreOp() == VK_ATTACHMENT_STORE_OP_DONT_CARE)
2496 tcu::fillWithGrid(tcu::getSubregion(reference.getAccess(), renderPos.x(), renderPos.y(), renderSize.x(), renderSize.y()), 2, textureInfo.valueMin, textureInfo.valueMax);
2497 }
2498 }
2499
findColorAttachment(const Subpass & subpass,deUint32 attachmentIndex)2500 Maybe<deUint32> findColorAttachment (const Subpass& subpass,
2501 deUint32 attachmentIndex)
2502 {
2503 for (size_t colorAttachmentNdx = 0; colorAttachmentNdx < subpass.getColorAttachments().size(); colorAttachmentNdx++)
2504 {
2505 if (subpass.getColorAttachments()[colorAttachmentNdx].getAttachment() == attachmentIndex)
2506 return tcu::just((deUint32)colorAttachmentNdx);
2507 }
2508
2509 return tcu::nothing<deUint32>();
2510 }
2511
calcFloatDiff(float a,float b)2512 int calcFloatDiff (float a, float b)
2513 {
2514 const deUint32 au = tcu::Float32(a).bits();
2515 const deUint32 bu = tcu::Float32(b).bits();
2516
2517 const bool asign = (au & (0x1u << 31u)) != 0u;
2518 const bool bsign = (bu & (0x1u << 31u)) != 0u;
2519
2520 const deUint32 avalue = (au & ((0x1u << 31u) - 1u));
2521 const deUint32 bvalue = (bu & ((0x1u << 31u) - 1u));
2522
2523 if (asign != bsign)
2524 return avalue + bvalue + 1u;
2525 else if (avalue < bvalue)
2526 return bvalue - avalue;
2527 else
2528 return avalue - bvalue;
2529 }
2530
comparePixelToDepthClearValue(const ConstPixelBufferAccess & access,int x,int y,float ref)2531 bool comparePixelToDepthClearValue (const ConstPixelBufferAccess& access,
2532 int x,
2533 int y,
2534 float ref)
2535 {
2536 const tcu::TextureFormat format = tcu::getEffectiveDepthStencilTextureFormat(access.getFormat(), tcu::Sampler::MODE_DEPTH);
2537 const tcu::TextureChannelClass channelClass = tcu::getTextureChannelClass(format.type);
2538
2539 switch (channelClass)
2540 {
2541 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
2542 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
2543 {
2544 const int bitDepth = tcu::getTextureFormatBitDepth(format).x();
2545 const float depth = access.getPixDepth(x, y);
2546 const float threshold = 2.0f / (float)((1 << bitDepth) - 1);
2547
2548 return deFloatAbs(depth - ref) <= threshold;
2549 }
2550
2551 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
2552 {
2553 const float depth = access.getPixDepth(x, y);
2554 const int mantissaBits = tcu::getTextureFormatMantissaBitDepth(format).x();
2555 const int threshold = 10 * 1 << (23 - mantissaBits);
2556
2557 DE_ASSERT(mantissaBits <= 23);
2558
2559 return calcFloatDiff(depth, ref) <= threshold;
2560 }
2561
2562 default:
2563 DE_FATAL("Invalid channel class");
2564 return false;
2565 }
2566 }
2567
comparePixelToStencilClearValue(const ConstPixelBufferAccess & access,int x,int y,deUint32 ref)2568 bool comparePixelToStencilClearValue (const ConstPixelBufferAccess& access,
2569 int x,
2570 int y,
2571 deUint32 ref)
2572 {
2573 const deUint32 stencil = access.getPixStencil(x, y);
2574
2575 return stencil == ref;
2576 }
2577
comparePixelToColorClearValue(const ConstPixelBufferAccess & access,int x,int y,const VkClearColorValue & ref)2578 bool comparePixelToColorClearValue (const ConstPixelBufferAccess& access,
2579 int x,
2580 int y,
2581 const VkClearColorValue& ref)
2582 {
2583 const tcu::TextureFormat format = access.getFormat();
2584 const tcu::TextureChannelClass channelClass = tcu::getTextureChannelClass(format.type);
2585 const BVec4 channelMask = tcu::getTextureFormatChannelMask(format);
2586
2587 switch (channelClass)
2588 {
2589 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
2590 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
2591 {
2592 const IVec4 bitDepth (tcu::getTextureFormatBitDepth(format));
2593 const Vec4 resColor (access.getPixel(x, y));
2594 const Vec4 refColor (ref.float32[0],
2595 ref.float32[1],
2596 ref.float32[2],
2597 ref.float32[3]);
2598 const Vec4 threshold (bitDepth[0] > 0 ? 20.0f / (float)((1 << bitDepth[0]) - 1) : 1.0f,
2599 bitDepth[1] > 0 ? 20.0f / (float)((1 << bitDepth[1]) - 1) : 1.0f,
2600 bitDepth[2] > 0 ? 20.0f / (float)((1 << bitDepth[2]) - 1) : 1.0f,
2601 bitDepth[3] > 0 ? 20.0f / (float)((1 << bitDepth[3]) - 1) : 1.0f);
2602
2603 if (tcu::isSRGB(access.getFormat()))
2604 return !(tcu::anyNotEqual(tcu::logicalAnd(lessThanEqual(tcu::absDiff(resColor, tcu::linearToSRGB(refColor)), threshold), channelMask), channelMask));
2605 else
2606 return !(tcu::anyNotEqual(tcu::logicalAnd(lessThanEqual(tcu::absDiff(resColor, refColor), threshold), channelMask), channelMask));
2607 }
2608
2609 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
2610 {
2611 const UVec4 resColor (access.getPixelUint(x, y));
2612 const UVec4 refColor (ref.uint32[0],
2613 ref.uint32[1],
2614 ref.uint32[2],
2615 ref.uint32[3]);
2616 const UVec4 threshold (1);
2617
2618 return !(tcu::anyNotEqual(tcu::logicalAnd(lessThanEqual(tcu::absDiff(resColor, refColor), threshold), channelMask), channelMask));
2619 }
2620
2621 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
2622 {
2623 const IVec4 resColor (access.getPixelInt(x, y));
2624 const IVec4 refColor (ref.int32[0],
2625 ref.int32[1],
2626 ref.int32[2],
2627 ref.int32[3]);
2628 const IVec4 threshold (1);
2629
2630 return !(tcu::anyNotEqual(tcu::logicalAnd(lessThanEqual(tcu::absDiff(resColor, refColor), threshold), channelMask), channelMask));
2631 }
2632
2633 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
2634 {
2635 const Vec4 resColor (access.getPixel(x, y));
2636 const Vec4 refColor (ref.float32[0],
2637 ref.float32[1],
2638 ref.float32[2],
2639 ref.float32[3]);
2640 const IVec4 mantissaBits (tcu::getTextureFormatMantissaBitDepth(format));
2641 const IVec4 threshold (10 * IVec4(1) << (23 - mantissaBits));
2642
2643 DE_ASSERT(tcu::allEqual(greaterThanEqual(threshold, IVec4(0)), BVec4(true)));
2644
2645 for (int ndx = 0; ndx < 4; ndx++)
2646 {
2647 if (calcFloatDiff(resColor[ndx], refColor[ndx]) > threshold[ndx] && channelMask[ndx])
2648 return false;
2649 }
2650
2651 return true;
2652 }
2653
2654 default:
2655 DE_FATAL("Invalid channel class");
2656 return false;
2657 }
2658 }
2659
2660 class PixelStatus
2661 {
2662 public:
2663 enum Status
2664 {
2665 STATUS_UNDEFINED = 0,
2666 STATUS_OK = 1,
2667 STATUS_FAIL = 2,
2668
2669 STATUS_LAST
2670 };
2671
PixelStatus(Status color,Status depth,Status stencil)2672 PixelStatus (Status color, Status depth, Status stencil)
2673 : m_status ((deUint8)((color << COLOR_OFFSET)
2674 | (depth << DEPTH_OFFSET)
2675 | (stencil << STENCIL_OFFSET)))
2676 {
2677 }
2678
getColorStatus(void) const2679 Status getColorStatus (void) const { return (Status)((m_status & COLOR_MASK) >> COLOR_OFFSET); }
getDepthStatus(void) const2680 Status getDepthStatus (void) const { return (Status)((m_status & DEPTH_MASK) >> DEPTH_OFFSET); }
getStencilStatus(void) const2681 Status getStencilStatus (void) const { return (Status)((m_status & STENCIL_MASK) >> STENCIL_OFFSET); }
2682
setColorStatus(Status status)2683 void setColorStatus (Status status)
2684 {
2685 DE_ASSERT(getColorStatus() == STATUS_UNDEFINED);
2686 m_status |= (deUint8)(status << COLOR_OFFSET);
2687 }
2688
setDepthStatus(Status status)2689 void setDepthStatus (Status status)
2690 {
2691 DE_ASSERT(getDepthStatus() == STATUS_UNDEFINED);
2692 m_status |= (deUint8)(status << DEPTH_OFFSET);
2693 }
2694
setStencilStatus(Status status)2695 void setStencilStatus (Status status)
2696 {
2697 DE_ASSERT(getStencilStatus() == STATUS_UNDEFINED);
2698 m_status |= (deUint8)(status << STENCIL_OFFSET);
2699 }
2700
2701 private:
2702 enum
2703 {
2704 COLOR_OFFSET = 0,
2705 DEPTH_OFFSET = 2,
2706 STENCIL_OFFSET = 4,
2707
2708 COLOR_MASK = (3<<COLOR_OFFSET),
2709 DEPTH_MASK = (3<<DEPTH_OFFSET),
2710 STENCIL_MASK = (3<<STENCIL_OFFSET),
2711 };
2712 deUint8 m_status;
2713 };
2714
checkDepthRenderQuad(const ConstPixelBufferAccess & result,const IVec2 & posA,const IVec2 & posB,vector<PixelStatus> & status)2715 void checkDepthRenderQuad (const ConstPixelBufferAccess& result,
2716 const IVec2& posA,
2717 const IVec2& posB,
2718 vector<PixelStatus>& status)
2719 {
2720 for (int y = posA.y(); y <= posB.y(); y++)
2721 for (int x = posA.x(); x <= posB.x(); x++)
2722 {
2723 PixelStatus& pixelStatus = status[x + y * result.getWidth()];
2724
2725 if (pixelStatus.getDepthStatus() == PixelStatus::STATUS_UNDEFINED)
2726 {
2727 const Vec4 minUvs = computeUvs(posA, posB, IVec2(x-1, y-1));
2728 const Vec4 maxUvs = computeUvs(posA, posB, IVec2(x+1, y+1));
2729 const bool softCheck = std::abs(x - posA.x()) <= 1 || std::abs(x - posB.x()) <= 1
2730 || std::abs(y - posA.y()) <= 1 || std::abs(y - posB.y()) <= 1;
2731 const float resDepth = result.getPixDepth(x, y);
2732
2733 if (resDepth >= minUvs.x() && resDepth <= maxUvs.x())
2734 pixelStatus.setDepthStatus(PixelStatus::STATUS_OK);
2735 else if (!softCheck)
2736 pixelStatus.setDepthStatus(PixelStatus::STATUS_FAIL);
2737 }
2738 }
2739 }
2740
checkStencilRenderQuad(const ConstPixelBufferAccess & result,const IVec2 & posA,const IVec2 & posB,vector<PixelStatus> & status)2741 void checkStencilRenderQuad (const ConstPixelBufferAccess& result,
2742 const IVec2& posA,
2743 const IVec2& posB,
2744 vector<PixelStatus>& status)
2745 {
2746 for (int y = posA.y(); y <= posB.y(); y++)
2747 for (int x = posA.x(); x <= posB.x(); x++)
2748 {
2749 PixelStatus& pixelStatus = status[x + y * result.getWidth()];
2750
2751 if (pixelStatus.getStencilStatus() == PixelStatus::STATUS_UNDEFINED)
2752 {
2753 const bool softCheck = std::abs(x - posA.x()) <= 1 || std::abs(x - posB.x()) <= 1
2754 || std::abs(y - posA.y()) <= 1 || std::abs(y - posB.y()) <= 1;
2755
2756 if (result.getPixStencil(x, y) == STENCIL_VALUE)
2757 pixelStatus.setStencilStatus(PixelStatus::STATUS_OK);
2758 else if (!softCheck)
2759 pixelStatus.setStencilStatus(PixelStatus::STATUS_FAIL);
2760 }
2761 }
2762 }
2763
checkColorRenderQuad(const ConstPixelBufferAccess & result,const IVec2 & posA,const IVec2 & posB,vector<PixelStatus> & status)2764 void checkColorRenderQuad (const ConstPixelBufferAccess& result,
2765 const IVec2& posA,
2766 const IVec2& posB,
2767 vector<PixelStatus>& status)
2768 {
2769 const tcu::TextureFormat& format = result.getFormat();
2770 const bool srgb = tcu::isSRGB(format);
2771 const tcu::TextureChannelClass channelClass = tcu::getTextureChannelClass(format.type);
2772 const tcu::TextureFormatInfo textureInfo = tcu::getTextureFormatInfo(format);
2773 const float clampMin = (float)(-MAX_INTEGER_VALUE);
2774 const float clampMax = (float)(MAX_INTEGER_VALUE);
2775 const Vec4 valueMax (de::clamp(textureInfo.valueMax[0], clampMin, clampMax),
2776 de::clamp(textureInfo.valueMax[1], clampMin, clampMax),
2777 de::clamp(textureInfo.valueMax[2], clampMin, clampMax),
2778 de::clamp(textureInfo.valueMax[3], clampMin, clampMax));
2779
2780 const Vec4 valueMin (de::clamp(textureInfo.valueMin[0], clampMin, clampMax),
2781 de::clamp(textureInfo.valueMin[1], clampMin, clampMax),
2782 de::clamp(textureInfo.valueMin[2], clampMin, clampMax),
2783 de::clamp(textureInfo.valueMin[3], clampMin, clampMax));
2784 const BVec4 channelMask = tcu::getTextureFormatChannelMask(format);
2785
2786 IVec4 formatBitDepths = tcu::getTextureFormatBitDepth(format);
2787 Vec4 threshold = Vec4(1.0f) / Vec4((float)(1 << formatBitDepths.x()),
2788 (float)(1 << formatBitDepths.y()),
2789 (float)(1 << formatBitDepths.z()),
2790 (float)(1 << formatBitDepths.w()));
2791
2792 switch (channelClass)
2793 {
2794 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
2795 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
2796 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
2797 {
2798 for (int y = posA.y(); y <= posB.y(); y++)
2799 for (int x = posA.x(); x <= posB.x(); x++)
2800 {
2801 PixelStatus& pixelStatus = status[x + y * result.getWidth()];
2802
2803 if (pixelStatus.getColorStatus() == PixelStatus::STATUS_UNDEFINED)
2804 {
2805 const Vec4 minDiff = Vec4(1.0f) / (IVec4(1) << tcu::getTextureFormatMantissaBitDepth(format)).cast<float>();
2806 const Vec4 minUvs = computeUvs(posA, posB, IVec2(x-1, y-1));
2807 const Vec4 maxUvs = computeUvs(posA, posB, IVec2(x+1, y+1));
2808 const bool softCheck = std::abs(x - posA.x()) <= 1 || std::abs(x - posB.x()) <= 1
2809 || std::abs(y - posA.y()) <= 1 || std::abs(y - posB.y()) <= 1;
2810
2811 const Vec4 resColor (result.getPixel(x, y));
2812
2813 Vec4 minRefColor = srgb ? tcu::linearToSRGB(valueMax * minUvs + valueMin * (Vec4(1.0f) - minUvs))
2814 : valueMax * minUvs + valueMin * (Vec4(1.0f) - minUvs) - threshold;
2815 Vec4 maxRefColor = srgb ? tcu::linearToSRGB(valueMax * maxUvs + valueMin * (Vec4(1.0f) - maxUvs))
2816 : valueMax * maxUvs + valueMin * (Vec4(1.0f) - maxUvs) + threshold;
2817
2818 // Take into account rounding and quantization
2819 if (channelClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT)
2820 {
2821 minRefColor = tcu::min(minRefColor * (Vec4(1.0f) - minDiff), minRefColor * (Vec4(1.0f) + minDiff));
2822 maxRefColor = tcu::max(maxRefColor * (Vec4(1.0f) - minDiff), maxRefColor * (Vec4(1.0f) + minDiff));
2823 }
2824 else
2825 {
2826 minRefColor = minRefColor - minDiff;
2827 maxRefColor = maxRefColor + minDiff;
2828 }
2829
2830 DE_ASSERT(minRefColor[0] <= maxRefColor[0]);
2831 DE_ASSERT(minRefColor[1] <= maxRefColor[1]);
2832 DE_ASSERT(minRefColor[2] <= maxRefColor[2]);
2833 DE_ASSERT(minRefColor[3] <= maxRefColor[3]);
2834
2835 if (tcu::anyNotEqual(tcu::logicalAnd(
2836 tcu::logicalAnd(greaterThanEqual(resColor, minRefColor),
2837 lessThanEqual(resColor, maxRefColor)),
2838 channelMask), channelMask))
2839 {
2840 if (!softCheck)
2841 pixelStatus.setColorStatus(PixelStatus::STATUS_FAIL);
2842 }
2843 else
2844 pixelStatus.setColorStatus(PixelStatus::STATUS_OK);
2845 }
2846 }
2847
2848 break;
2849 }
2850
2851 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
2852 {
2853 for (int y = posA.y(); y <= posB.y(); y++)
2854 for (int x = posA.x(); x <= posB.x(); x++)
2855 {
2856 PixelStatus& pixelStatus = status[x + y * result.getWidth()];
2857
2858 if (pixelStatus.getColorStatus() == PixelStatus::STATUS_UNDEFINED)
2859 {
2860 const Vec4 minUvs = computeUvs(posA, posB, IVec2(x-1, y-1));
2861 const Vec4 maxUvs = computeUvs(posA, posB, IVec2(x+1, y+1));
2862 const bool softCheck = std::abs(x - posA.x()) <= 1 || std::abs(x - posB.x()) <= 1
2863 || std::abs(y - posA.y()) <= 1 || std::abs(y - posB.y()) <= 1;
2864
2865 const UVec4 resColor (result.getPixelUint(x, y));
2866
2867 const Vec4 minRefColorF = valueMax * minUvs + valueMin * (Vec4(1.0f) - minUvs);
2868 const Vec4 maxRefColorF = valueMax * maxUvs + valueMin * (Vec4(1.0f) - maxUvs);
2869
2870 const UVec4 minRefColor (minRefColorF.asUint());
2871 const UVec4 maxRefColor (maxRefColorF.asUint());
2872
2873 DE_ASSERT(minRefColor[0] <= maxRefColor[0]);
2874 DE_ASSERT(minRefColor[1] <= maxRefColor[1]);
2875 DE_ASSERT(minRefColor[2] <= maxRefColor[2]);
2876 DE_ASSERT(minRefColor[3] <= maxRefColor[3]);
2877
2878 if (tcu::anyNotEqual(tcu::logicalAnd(
2879 tcu::logicalAnd(greaterThanEqual(resColor, minRefColor),
2880 lessThanEqual(resColor, maxRefColor)),
2881 channelMask), channelMask))
2882 {
2883 if (!softCheck)
2884 pixelStatus.setColorStatus(PixelStatus::STATUS_FAIL);
2885 }
2886 else
2887 pixelStatus.setColorStatus(PixelStatus::STATUS_OK);
2888 }
2889 }
2890
2891 break;
2892 }
2893
2894 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
2895 {
2896 for (int y = posA.y(); y <= posB.y(); y++)
2897 for (int x = posA.x(); x <= posB.x(); x++)
2898 {
2899 PixelStatus& pixelStatus = status[x + y * result.getWidth()];
2900
2901 if (pixelStatus.getColorStatus() == PixelStatus::STATUS_UNDEFINED)
2902 {
2903 const Vec4 minUvs = computeUvs(posA, posB, IVec2(x-1, y-1));
2904 const Vec4 maxUvs = computeUvs(posA, posB, IVec2(x+1, y+1));
2905 const bool softCheck = std::abs(x - posA.x()) <= 1 || std::abs(x - posB.x()) <= 1
2906 || std::abs(y - posA.y()) <= 1 || std::abs(y - posB.y()) <= 1;
2907
2908 const IVec4 resColor (result.getPixelInt(x, y));
2909
2910 const Vec4 minRefColorF = valueMax * minUvs + valueMin * (Vec4(1.0f) - minUvs);
2911 const Vec4 maxRefColorF = valueMax * maxUvs + valueMin * (Vec4(1.0f) - maxUvs);
2912
2913 const IVec4 minRefColor (minRefColorF.asInt());
2914 const IVec4 maxRefColor (maxRefColorF.asInt());
2915
2916 DE_ASSERT(minRefColor[0] <= maxRefColor[0]);
2917 DE_ASSERT(minRefColor[1] <= maxRefColor[1]);
2918 DE_ASSERT(minRefColor[2] <= maxRefColor[2]);
2919 DE_ASSERT(minRefColor[3] <= maxRefColor[3]);
2920
2921 if (tcu::anyNotEqual(tcu::logicalAnd(
2922 tcu::logicalAnd(greaterThanEqual(resColor, minRefColor),
2923 lessThanEqual(resColor, maxRefColor)),
2924 channelMask), channelMask))
2925 {
2926 if (!softCheck)
2927 pixelStatus.setColorStatus(PixelStatus::STATUS_FAIL);
2928 }
2929 else
2930 pixelStatus.setColorStatus(PixelStatus::STATUS_OK);
2931 }
2932 }
2933
2934 break;
2935 }
2936
2937 default:
2938 DE_FATAL("Invalid channel class");
2939 }
2940 }
2941
checkColorClear(const ConstPixelBufferAccess & result,const UVec2 & offset,const UVec2 & size,vector<PixelStatus> & status,const VkClearColorValue & color)2942 void checkColorClear (const ConstPixelBufferAccess& result,
2943 const UVec2& offset,
2944 const UVec2& size,
2945 vector<PixelStatus>& status,
2946 const VkClearColorValue& color)
2947 {
2948 DE_ASSERT(offset.x() + size.x() <= (deUint32)result.getWidth());
2949 DE_ASSERT(offset.y() + size.y() <= (deUint32)result.getHeight());
2950
2951 DE_ASSERT(result.getWidth() * result.getHeight() == (int)status.size());
2952
2953 for (int y = offset.y(); y < (int)(offset.y() + size.y()); y++)
2954 for (int x = offset.x(); x < (int)(offset.x() + size.x()); x++)
2955 {
2956 PixelStatus& pixelStatus = status[x + y * result.getWidth()];
2957
2958 DE_ASSERT(x + y * result.getWidth() < (int)status.size());
2959
2960 if (pixelStatus.getColorStatus() == PixelStatus::STATUS_UNDEFINED)
2961 {
2962 if (comparePixelToColorClearValue(result, x, y, color))
2963 pixelStatus.setColorStatus(PixelStatus::STATUS_OK);
2964 else
2965 pixelStatus.setColorStatus(PixelStatus::STATUS_FAIL);
2966 }
2967 }
2968 }
2969
checkDepthClear(const ConstPixelBufferAccess & result,const UVec2 & offset,const UVec2 & size,vector<PixelStatus> & status,float depth)2970 void checkDepthClear (const ConstPixelBufferAccess& result,
2971 const UVec2& offset,
2972 const UVec2& size,
2973 vector<PixelStatus>& status,
2974 float depth)
2975 {
2976 for (int y = offset.y(); y < (int)(offset.y() + size.y()); y++)
2977 for (int x = offset.x(); x < (int)(offset.x() + size.x()); x++)
2978 {
2979 PixelStatus& pixelStatus = status[x + y * result.getWidth()];
2980
2981 if (pixelStatus.getDepthStatus() == PixelStatus::STATUS_UNDEFINED)
2982 {
2983 if (comparePixelToDepthClearValue(result, x, y, depth))
2984 pixelStatus.setDepthStatus(PixelStatus::STATUS_OK);
2985 else
2986 pixelStatus.setDepthStatus(PixelStatus::STATUS_FAIL);
2987 }
2988 }
2989 }
2990
checkStencilClear(const ConstPixelBufferAccess & result,const UVec2 & offset,const UVec2 & size,vector<PixelStatus> & status,deUint32 stencil)2991 void checkStencilClear (const ConstPixelBufferAccess& result,
2992 const UVec2& offset,
2993 const UVec2& size,
2994 vector<PixelStatus>& status,
2995 deUint32 stencil)
2996 {
2997 for (int y = offset.y(); y < (int)(offset.y() + size.y()); y++)
2998 for (int x = offset.x(); x < (int)(offset.x() + size.x()); x++)
2999 {
3000 PixelStatus& pixelStatus = status[x + y * result.getWidth()];
3001
3002 if (pixelStatus.getStencilStatus() == PixelStatus::STATUS_UNDEFINED)
3003 {
3004 if (comparePixelToStencilClearValue(result, x, y, stencil))
3005 pixelStatus.setStencilStatus(PixelStatus::STATUS_OK);
3006 else
3007 pixelStatus.setStencilStatus(PixelStatus::STATUS_FAIL);
3008 }
3009 }
3010 }
3011
verifyAttachment(const ConstPixelBufferAccess & result,const Maybe<ConstPixelBufferAccess> & secondaryResult,const RenderPass & renderPassInfo,const Maybe<VkClearValue> & renderPassClearValue,const Maybe<VkClearValue> & imageClearValue,const vector<Subpass> & subpasses,const vector<SubpassRenderInfo> & subpassRenderInfo,const PixelBufferAccess & errorImage,deUint32 attachmentIndex,const UVec2 & renderPos,const UVec2 & renderSize)3012 bool verifyAttachment (const ConstPixelBufferAccess& result,
3013 const Maybe<ConstPixelBufferAccess>& secondaryResult,
3014 const RenderPass& renderPassInfo,
3015 const Maybe<VkClearValue>& renderPassClearValue,
3016 const Maybe<VkClearValue>& imageClearValue,
3017 const vector<Subpass>& subpasses,
3018 const vector<SubpassRenderInfo>& subpassRenderInfo,
3019 const PixelBufferAccess& errorImage,
3020 deUint32 attachmentIndex,
3021 const UVec2& renderPos,
3022 const UVec2& renderSize)
3023 {
3024 const tcu::TextureFormat& format = result.getFormat();
3025 const bool hasDepth = tcu::hasDepthComponent(format.order);
3026 const bool hasStencil = tcu::hasStencilComponent(format.order);
3027 const bool isColorFormat = !hasDepth && !hasStencil;
3028 const PixelStatus initialStatus (isColorFormat ? PixelStatus::STATUS_UNDEFINED : PixelStatus::STATUS_OK,
3029 hasDepth ? PixelStatus::STATUS_UNDEFINED : PixelStatus::STATUS_OK,
3030 hasStencil ? PixelStatus::STATUS_UNDEFINED : PixelStatus::STATUS_OK);
3031
3032 bool attachmentIsUsed = false;
3033 vector<PixelStatus> status (result.getWidth() * result.getHeight(), initialStatus);
3034 tcu::clear(errorImage, Vec4(0.0f, 1.0f, 0.0f, 1.0f));
3035
3036 // Check if attachment is used
3037 for (int subpassNdx = 0; subpassNdx < (int)subpasses.size(); subpassNdx++)
3038 {
3039 const Subpass& subpass = subpasses[subpassNdx];
3040 const Maybe<deUint32> attachmentNdx = findColorAttachment(subpass, attachmentIndex);
3041
3042 if (attachmentNdx || subpass.getDepthStencilAttachment().getAttachment() == attachmentIndex)
3043 attachmentIsUsed = true;
3044 }
3045
3046 // Set all pixels that have undefined values to OK
3047 if (attachmentIsUsed && (((isColorFormat || hasDepth) && renderPassInfo.getAttachments()[attachmentIndex].getStoreOp() == VK_ATTACHMENT_STORE_OP_DONT_CARE)
3048 || (hasStencil && renderPassInfo.getAttachments()[attachmentIndex].getStencilStoreOp() == VK_ATTACHMENT_STORE_OP_DONT_CARE)))
3049 {
3050 for(int y = renderPos.y(); y < (int)(renderPos.y() + renderSize.y()); y++)
3051 for(int x = renderPos.x(); x < (int)(renderPos.x() + renderSize.x()); x++)
3052 {
3053 PixelStatus& pixelStatus = status[x + y * result.getWidth()];
3054
3055 if (isColorFormat && renderPassInfo.getAttachments()[attachmentIndex].getStoreOp() == VK_ATTACHMENT_STORE_OP_DONT_CARE)
3056 pixelStatus.setColorStatus(PixelStatus::STATUS_OK);
3057 else
3058 {
3059 if (hasDepth && renderPassInfo.getAttachments()[attachmentIndex].getStoreOp() == VK_ATTACHMENT_STORE_OP_DONT_CARE)
3060 pixelStatus.setDepthStatus(PixelStatus::STATUS_OK);
3061
3062 if (hasStencil && renderPassInfo.getAttachments()[attachmentIndex].getStencilStoreOp() == VK_ATTACHMENT_STORE_OP_DONT_CARE)
3063 pixelStatus.setStencilStatus(PixelStatus::STATUS_OK);
3064 }
3065 }
3066 }
3067
3068 // Check renderpass rendering results
3069 if (renderPassInfo.getAttachments()[attachmentIndex].getStoreOp() == VK_ATTACHMENT_STORE_OP_STORE
3070 || (hasStencil && renderPassInfo.getAttachments()[attachmentIndex].getStencilStoreOp() == VK_ATTACHMENT_STORE_OP_STORE))
3071 {
3072 // Check subpass rendering results
3073 for (int subpassNdx = (int)subpasses.size() - 1; subpassNdx >= 0; subpassNdx--)
3074 {
3075 const Subpass& subpass = subpasses[subpassNdx];
3076 const SubpassRenderInfo& renderInfo = subpassRenderInfo[subpassNdx];
3077 const Maybe<deUint32> attachmentNdx = findColorAttachment(subpass, attachmentIndex);
3078
3079 // Check rendered quad
3080 if (renderInfo.getRenderQuad() && (attachmentNdx || subpass.getDepthStencilAttachment().getAttachment() == attachmentIndex))
3081 {
3082 const RenderQuad& renderQuad = *renderInfo.getRenderQuad();
3083 const Vec4 posA = renderQuad.getCornerA();
3084 const Vec4 posB = renderQuad.getCornerB();
3085 const Vec2 origin = Vec2((float)renderInfo.getViewportOffset().x(), (float)renderInfo.getViewportOffset().y()) + Vec2((float)renderInfo.getViewportSize().x(), (float)renderInfo.getViewportSize().y()) / Vec2(2.0f);
3086 const Vec2 p = Vec2((float)renderInfo.getViewportSize().x(), (float)renderInfo.getViewportSize().y()) / Vec2(2.0f);
3087 const IVec2 posAI ((deInt32)(origin.x() + (p.x() * posA.x())),
3088 (deInt32)(origin.y() + (p.y() * posA.y())));
3089 const IVec2 posBI ((deInt32)(origin.x() + (p.x() * posB.x())),
3090 (deInt32)(origin.y() + (p.y() * posB.y())));
3091
3092 if (isColorFormat)
3093 checkColorRenderQuad(result, posAI, posBI, status);
3094 else
3095 {
3096 if (hasDepth)
3097 checkDepthRenderQuad(result, posAI, posBI, status);
3098
3099 if (hasDepth && hasStencil)
3100 checkStencilRenderQuad(*secondaryResult, posAI, posBI, status);
3101 else if (hasStencil)
3102 checkStencilRenderQuad(result, posAI, posBI, status);
3103 }
3104 }
3105
3106 // Check color attachment clears
3107 if (attachmentNdx && !renderInfo.getColorClears().empty())
3108 {
3109 const ColorClear& clear = renderInfo.getColorClears()[*attachmentNdx];
3110
3111 checkColorClear(result, clear.getOffset(), clear.getSize(), status, clear.getColor());
3112 }
3113
3114 // Check depth/stencil attachment clears
3115 if (subpass.getDepthStencilAttachment().getAttachment() == attachmentIndex && renderInfo.getDepthStencilClear())
3116 {
3117 const DepthStencilClear clear = *renderInfo.getDepthStencilClear();
3118
3119 if (hasDepth)
3120 checkDepthClear(result, clear.getOffset(), clear.getSize(), status, clear.getDepth());
3121
3122 if (hasDepth && hasStencil)
3123 checkStencilClear(*secondaryResult, clear.getOffset(), clear.getSize(), status, clear.getStencil());
3124 else if (hasStencil)
3125 checkStencilClear(result, clear.getOffset(), clear.getSize(), status, clear.getStencil());
3126 }
3127 }
3128
3129 // Check renderpas clear results
3130 if (attachmentIsUsed && renderPassClearValue)
3131 {
3132 if (isColorFormat)
3133 {
3134 if (renderPassInfo.getAttachments()[attachmentIndex].getLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR)
3135 checkColorClear(result, renderPos, renderSize, status, renderPassClearValue->color);
3136 }
3137 else
3138 {
3139 if (hasDepth && renderPassInfo.getAttachments()[attachmentIndex].getLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR)
3140 checkDepthClear(result, renderPos, renderSize, status, renderPassClearValue->depthStencil.depth);
3141
3142 if (hasDepth && hasStencil && renderPassInfo.getAttachments()[attachmentIndex].getStencilLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR)
3143 checkStencilClear(*secondaryResult, renderPos, renderSize, status, renderPassClearValue->depthStencil.stencil);
3144 else if (hasStencil && renderPassInfo.getAttachments()[attachmentIndex].getStencilLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR)
3145 checkStencilClear(result, renderPos, renderSize, status, renderPassClearValue->depthStencil.stencil);
3146 }
3147 }
3148 }
3149
3150 // Set all pixels that have undefined values fater renderpass to OK
3151 if (attachmentIsUsed && (((isColorFormat || hasDepth) && renderPassInfo.getAttachments()[attachmentIndex].getLoadOp() == VK_ATTACHMENT_LOAD_OP_DONT_CARE)
3152 || (hasStencil && renderPassInfo.getAttachments()[attachmentIndex].getStencilLoadOp() == VK_ATTACHMENT_LOAD_OP_DONT_CARE)))
3153 {
3154 for(int y = renderPos.y(); y < (int)(renderPos.y() + renderSize.y()); y++)
3155 for(int x = renderPos.x(); x < (int)(renderPos.x() + renderSize.x()); x++)
3156 {
3157 PixelStatus& pixelStatus = status[x + y * result.getWidth()];
3158
3159 if (pixelStatus.getColorStatus() == PixelStatus::STATUS_UNDEFINED
3160 && isColorFormat && renderPassInfo.getAttachments()[attachmentIndex].getLoadOp() == VK_ATTACHMENT_LOAD_OP_DONT_CARE)
3161 pixelStatus.setColorStatus(PixelStatus::STATUS_OK);
3162 else
3163 {
3164 if (pixelStatus.getDepthStatus() == PixelStatus::STATUS_UNDEFINED
3165 && hasDepth && renderPassInfo.getAttachments()[attachmentIndex].getLoadOp() == VK_ATTACHMENT_LOAD_OP_DONT_CARE)
3166 pixelStatus.setDepthStatus(PixelStatus::STATUS_OK);
3167
3168 if (pixelStatus.getStencilStatus() == PixelStatus::STATUS_UNDEFINED
3169 && hasStencil && renderPassInfo.getAttachments()[attachmentIndex].getStencilLoadOp() == VK_ATTACHMENT_LOAD_OP_DONT_CARE)
3170 pixelStatus.setStencilStatus(PixelStatus::STATUS_OK);
3171 }
3172 }
3173 }
3174
3175 if (imageClearValue)
3176 {
3177 if (isColorFormat)
3178 checkColorClear(result, UVec2(0, 0), UVec2(result.getWidth(), result.getHeight()), status, imageClearValue->color);
3179 else
3180 {
3181 if (hasDepth)
3182 checkDepthClear(result, UVec2(0, 0), UVec2(result.getWidth(), result.getHeight()), status, imageClearValue->depthStencil.depth);
3183
3184 if (hasDepth && hasStencil)
3185 checkStencilClear(*secondaryResult, UVec2(0, 0), UVec2(secondaryResult->getWidth(), result.getHeight()), status, imageClearValue->depthStencil.stencil);
3186 else if (hasStencil)
3187 checkStencilClear(result, UVec2(0, 0), UVec2(result.getWidth(), result.getHeight()), status, imageClearValue->depthStencil.stencil);
3188 }
3189 }
3190
3191 {
3192 bool isOk = true;
3193
3194 for(int y = 0; y < result.getHeight(); y++)
3195 for(int x = 0; x < result.getWidth(); x++)
3196 {
3197 const PixelStatus& pixelStatus = status[x + y * result.getWidth()];
3198
3199 if (isColorFormat)
3200 {
3201 if (pixelStatus.getColorStatus() != PixelStatus::STATUS_OK)
3202 {
3203 if (pixelStatus.getColorStatus() == PixelStatus::STATUS_UNDEFINED)
3204 errorImage.setPixel(Vec4(1.0f, 1.0f, 0.0f, 1.0f), x, y);
3205 else if (pixelStatus.getColorStatus() == PixelStatus::STATUS_FAIL)
3206 errorImage.setPixel(Vec4(1.0f, 0.0f, 0.0f, 1.0f), x, y);
3207
3208 isOk = false;
3209 }
3210 }
3211 else
3212 {
3213 if (hasDepth && pixelStatus.getDepthStatus() != PixelStatus::STATUS_OK)
3214 {
3215 errorImage.setPixel(Vec4(1.0f, 0.0f, 0.0f, 1.0f), x, y);
3216 isOk = false;
3217 }
3218
3219 if (hasStencil && pixelStatus.getStencilStatus() != PixelStatus::STATUS_OK)
3220 {
3221 errorImage.setPixel(Vec4(1.0f, 0.0f, 0.0f, 1.0f), x, y);
3222 isOk = false;
3223 }
3224 }
3225 }
3226
3227 return isOk;
3228 }
3229 }
3230
logAndVerifyImages(TestLog & log,const DeviceInterface & vk,VkDevice device,const vector<de::SharedPtr<AttachmentResources>> & attachmentResources,const vector<bool> & attachmentIsLazy,const RenderPass & renderPassInfo,const vector<Maybe<VkClearValue>> & renderPassClearValues,const vector<Maybe<VkClearValue>> & imageClearValues,const vector<SubpassRenderInfo> & subpassRenderInfo,const UVec2 & targetSize,const TestConfig & config)3231 bool logAndVerifyImages (TestLog& log,
3232 const DeviceInterface& vk,
3233 VkDevice device,
3234 const vector<de::SharedPtr<AttachmentResources> >& attachmentResources,
3235 const vector<bool>& attachmentIsLazy,
3236 const RenderPass& renderPassInfo,
3237 const vector<Maybe<VkClearValue> >& renderPassClearValues,
3238 const vector<Maybe<VkClearValue> >& imageClearValues,
3239 const vector<SubpassRenderInfo>& subpassRenderInfo,
3240 const UVec2& targetSize,
3241 const TestConfig& config)
3242 {
3243 vector<tcu::TextureLevel> referenceAttachments;
3244 bool isOk = true;
3245
3246 log << TestLog::Message << "Reference images fill undefined pixels with grid pattern." << TestLog::EndMessage;
3247
3248 renderReferenceImages(referenceAttachments, renderPassInfo, targetSize, imageClearValues, renderPassClearValues, subpassRenderInfo, config.renderPos, config.renderSize);
3249
3250 for (size_t attachmentNdx = 0; attachmentNdx < renderPassInfo.getAttachments().size(); attachmentNdx++)
3251 {
3252 if (!attachmentIsLazy[attachmentNdx])
3253 {
3254 const Attachment attachment = renderPassInfo.getAttachments()[attachmentNdx];
3255 const tcu::TextureFormat format = mapVkFormat(attachment.getFormat());
3256
3257 if (tcu::hasDepthComponent(format.order) && tcu::hasStencilComponent(format.order))
3258 {
3259 const tcu::TextureFormat depthFormat = getDepthCopyFormat(attachment.getFormat());
3260 const VkDeviceSize depthBufferSize = targetSize.x() * targetSize.y() * depthFormat.getPixelSize();
3261 void* const depthPtr = attachmentResources[attachmentNdx]->getResultMemory().getHostPtr();
3262
3263 const tcu::TextureFormat stencilFormat = getStencilCopyFormat(attachment.getFormat());
3264 const VkDeviceSize stencilBufferSize = targetSize.x() * targetSize.y() * stencilFormat.getPixelSize();
3265 void* const stencilPtr = attachmentResources[attachmentNdx]->getSecondaryResultMemory().getHostPtr();
3266
3267 const VkMappedMemoryRange ranges[] =
3268 {
3269 {
3270 VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // sType;
3271 DE_NULL, // pNext;
3272 attachmentResources[attachmentNdx]->getResultMemory().getMemory(), // mem;
3273 attachmentResources[attachmentNdx]->getResultMemory().getOffset(), // offset;
3274 depthBufferSize // size;
3275 },
3276 {
3277 VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // sType;
3278 DE_NULL, // pNext;
3279 attachmentResources[attachmentNdx]->getSecondaryResultMemory().getMemory(), // mem;
3280 attachmentResources[attachmentNdx]->getSecondaryResultMemory().getOffset(), // offset;
3281 stencilBufferSize // size;
3282 }
3283 };
3284 VK_CHECK(vk.invalidateMappedMemoryRanges(device, 2u, ranges));
3285
3286 {
3287 const ConstPixelBufferAccess depthAccess (depthFormat, targetSize.x(), targetSize.y(), 1, depthPtr);
3288 const ConstPixelBufferAccess stencilAccess (stencilFormat, targetSize.x(), targetSize.y(), 1, stencilPtr);
3289 tcu::TextureLevel errorImage (tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), targetSize.x(), targetSize.y());
3290
3291 log << TestLog::Image("Attachment" + de::toString(attachmentNdx) + "Depth", "Attachment " + de::toString(attachmentNdx) + " Depth", depthAccess);
3292 log << TestLog::Image("Attachment" + de::toString(attachmentNdx) + "Stencil", "Attachment " + de::toString(attachmentNdx) + " Stencil", stencilAccess);
3293
3294 log << TestLog::Image("AttachmentReference" + de::toString(attachmentNdx), "Attachment reference " + de::toString(attachmentNdx), referenceAttachments[attachmentNdx].getAccess());
3295
3296 if ((renderPassInfo.getAttachments()[attachmentNdx].getStoreOp() == VK_ATTACHMENT_STORE_OP_STORE || renderPassInfo.getAttachments()[attachmentNdx].getStencilStoreOp() == VK_ATTACHMENT_STORE_OP_STORE)
3297 && !verifyAttachment(depthAccess, tcu::just(stencilAccess), renderPassInfo, renderPassClearValues[attachmentNdx], imageClearValues[attachmentNdx], renderPassInfo.getSubpasses(), subpassRenderInfo, errorImage.getAccess(), (deUint32)attachmentNdx, config.renderPos, config.renderSize))
3298 {
3299 log << TestLog::Image("AttachmentError" + de::toString(attachmentNdx), "Attachment Error " + de::toString(attachmentNdx), errorImage.getAccess());
3300 isOk = false;
3301 }
3302 }
3303 }
3304 else
3305 {
3306 const VkDeviceSize bufferSize = targetSize.x() * targetSize.y() * format.getPixelSize();
3307 void* const ptr = attachmentResources[attachmentNdx]->getResultMemory().getHostPtr();
3308
3309 const VkMappedMemoryRange range =
3310 {
3311 VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // sType;
3312 DE_NULL, // pNext;
3313 attachmentResources[attachmentNdx]->getResultMemory().getMemory(), // mem;
3314 attachmentResources[attachmentNdx]->getResultMemory().getOffset(), // offset;
3315 bufferSize // size;
3316 };
3317 VK_CHECK(vk.invalidateMappedMemoryRanges(device, 1u, &range));
3318
3319 {
3320 const ConstPixelBufferAccess access (format, targetSize.x(), targetSize.y(), 1, ptr);
3321 tcu::TextureLevel errorImage (tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), targetSize.x(), targetSize.y());
3322
3323 log << TestLog::Image("Attachment" + de::toString(attachmentNdx), "Attachment " + de::toString(attachmentNdx), access);
3324 log << TestLog::Image("AttachmentReference" + de::toString(attachmentNdx), "Attachment reference " + de::toString(attachmentNdx), referenceAttachments[attachmentNdx].getAccess());
3325
3326 if ((renderPassInfo.getAttachments()[attachmentNdx].getStoreOp() == VK_ATTACHMENT_STORE_OP_STORE || renderPassInfo.getAttachments()[attachmentNdx].getStencilStoreOp() == VK_ATTACHMENT_STORE_OP_STORE)
3327 && !verifyAttachment(access, tcu::nothing<ConstPixelBufferAccess>(), renderPassInfo, renderPassClearValues[attachmentNdx], imageClearValues[attachmentNdx], renderPassInfo.getSubpasses(), subpassRenderInfo, errorImage.getAccess(), (deUint32)attachmentNdx, config.renderPos, config.renderSize))
3328 {
3329 log << TestLog::Image("AttachmentError" + de::toString(attachmentNdx), "Attachment Error " + de::toString(attachmentNdx), errorImage.getAccess());
3330 isOk = false;
3331 }
3332 }
3333 }
3334 }
3335 }
3336
3337 return isOk;
3338 }
3339
getAttachmentType(VkFormat vkFormat)3340 std::string getAttachmentType (VkFormat vkFormat)
3341 {
3342 const tcu::TextureFormat format = mapVkFormat(vkFormat);
3343 const tcu::TextureChannelClass channelClass = tcu::getTextureChannelClass(format.type);
3344
3345 switch (channelClass)
3346 {
3347 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
3348 return "ivec4";
3349
3350 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
3351 return "uvec4";
3352
3353 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
3354 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
3355 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
3356 return "vec4";
3357
3358 default:
3359 DE_FATAL("Unknown channel class");
3360 return "";
3361 }
3362 }
3363
createTestShaders(SourceCollections & dst,TestConfig config)3364 void createTestShaders (SourceCollections& dst, TestConfig config)
3365 {
3366 if (config.renderTypes & TestConfig::RENDERTYPES_DRAW)
3367 {
3368 const vector<Subpass>& subpasses = config.renderPass.getSubpasses();
3369
3370 for (size_t subpassNdx = 0; subpassNdx < subpasses.size(); subpassNdx++)
3371 {
3372 const Subpass& subpass = subpasses[subpassNdx];
3373 std::ostringstream vertexShader;
3374 std::ostringstream fragmentShader;
3375
3376 vertexShader << "#version 310 es\n"
3377 << "layout(location = 0) in highp vec4 a_position;\n"
3378 << "layout(location = 0) out highp vec2 v_color;\n"
3379 << "void main (void) {\n"
3380 << "\thighp float a = 0.5 + a_position.x;\n"
3381 << "\thighp float b = 0.5 + a_position.y;\n"
3382 << "\tv_color = vec2(a, b);\n"
3383 << "\tgl_Position = a_position;\n"
3384 << "}\n";
3385
3386 fragmentShader << "#version 310 es\n"
3387 << "layout(location = 0) in highp vec2 v_color;\n";
3388
3389 for (size_t attachmentNdx = 0; attachmentNdx < subpass.getColorAttachments().size(); attachmentNdx++)
3390 {
3391 const std::string attachmentType = getAttachmentType(config.renderPass.getAttachments()[subpass.getColorAttachments()[attachmentNdx].getAttachment()].getFormat());
3392 fragmentShader << "layout(location = " << attachmentNdx << ") out highp " << attachmentType << " o_color" << attachmentNdx << ";\n";
3393 }
3394
3395 fragmentShader << "void main (void) {\n"
3396 << "\thighp vec4 scale = vec4(v_color.x, v_color.y, v_color.x * v_color.y, (v_color.x + v_color.y) / 2.0);\n";
3397
3398 for (size_t attachmentNdx = 0; attachmentNdx < subpass.getColorAttachments().size(); attachmentNdx++)
3399 {
3400 const tcu::TextureFormat format = mapVkFormat(config.renderPass.getAttachments()[subpass.getColorAttachments()[attachmentNdx].getAttachment()].getFormat());
3401 const tcu::TextureFormatInfo formatInfo = tcu::getTextureFormatInfo(format);
3402 const float clampMin = (float)(-MAX_INTEGER_VALUE);
3403 const float clampMax = (float)(MAX_INTEGER_VALUE);
3404 const Vec4 valueMax (de::clamp(formatInfo.valueMax[0], clampMin, clampMax),
3405 de::clamp(formatInfo.valueMax[1], clampMin, clampMax),
3406 de::clamp(formatInfo.valueMax[2], clampMin, clampMax),
3407 de::clamp(formatInfo.valueMax[3], clampMin, clampMax));
3408
3409 const Vec4 valueMin (de::clamp(formatInfo.valueMin[0], clampMin, clampMax),
3410 de::clamp(formatInfo.valueMin[1], clampMin, clampMax),
3411 de::clamp(formatInfo.valueMin[2], clampMin, clampMax),
3412 de::clamp(formatInfo.valueMin[3], clampMin, clampMax));
3413 const std::string attachmentType = getAttachmentType(config.renderPass.getAttachments()[subpass.getColorAttachments()[attachmentNdx].getAttachment()].getFormat());
3414
3415 fragmentShader << "\to_color" << attachmentNdx << " = " << attachmentType << "(vec4" << valueMin << " + vec4" << (valueMax - valueMin) << " * scale);\n";
3416 }
3417
3418 fragmentShader << "}\n";
3419
3420 dst.glslSources.add(de::toString(subpassNdx) + "-vert") << glu::VertexSource(vertexShader.str());
3421 dst.glslSources.add(de::toString(subpassNdx) + "-frag") << glu::FragmentSource(fragmentShader.str());
3422 }
3423 }
3424 }
3425
initializeAttachmentIsLazy(vector<bool> & attachmentIsLazy,const vector<Attachment> & attachments,TestConfig::ImageMemory imageMemory)3426 void initializeAttachmentIsLazy (vector<bool>& attachmentIsLazy, const vector<Attachment>& attachments, TestConfig::ImageMemory imageMemory)
3427 {
3428 bool lastAttachmentWasLazy = false;
3429
3430 for (size_t attachmentNdx = 0; attachmentNdx < attachments.size(); attachmentNdx++)
3431 {
3432 if (attachments[attachmentNdx].getLoadOp() != VK_ATTACHMENT_LOAD_OP_LOAD
3433 && attachments[attachmentNdx].getStoreOp() != VK_ATTACHMENT_STORE_OP_STORE
3434 && attachments[attachmentNdx].getStencilLoadOp() != VK_ATTACHMENT_LOAD_OP_LOAD
3435 && attachments[attachmentNdx].getStencilStoreOp() != VK_ATTACHMENT_STORE_OP_STORE)
3436 {
3437 if (imageMemory == TestConfig::IMAGEMEMORY_LAZY || (imageMemory & TestConfig::IMAGEMEMORY_LAZY && !lastAttachmentWasLazy))
3438 {
3439 attachmentIsLazy.push_back(true);
3440 lastAttachmentWasLazy = true;
3441 }
3442 else if (imageMemory & TestConfig::IMAGEMEMORY_STRICT)
3443 {
3444 attachmentIsLazy.push_back(false);
3445 lastAttachmentWasLazy = false;
3446 }
3447 else
3448 DE_FATAL("Unknown imageMemory");
3449 }
3450 else
3451 attachmentIsLazy.push_back(false);
3452 }
3453 }
3454
3455 enum AttachmentRefType
3456 {
3457 ATTACHMENTREFTYPE_COLOR,
3458 ATTACHMENTREFTYPE_DEPTH_STENCIL,
3459 ATTACHMENTREFTYPE_INPUT,
3460 ATTACHMENTREFTYPE_RESOLVE,
3461 };
3462
getImageUsageFromLayout(VkImageLayout layout)3463 VkImageUsageFlags getImageUsageFromLayout(VkImageLayout layout)
3464 {
3465 switch (layout)
3466 {
3467 case VK_IMAGE_LAYOUT_GENERAL:
3468 case VK_IMAGE_LAYOUT_PREINITIALIZED:
3469 return 0;
3470 case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
3471 return VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
3472 case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
3473 case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
3474 return VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
3475 case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
3476 return VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
3477 case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
3478 return VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
3479 case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
3480 return VK_IMAGE_USAGE_TRANSFER_DST_BIT;
3481 default:
3482 DE_FATAL("Unexpected image layout");
3483 return 0;
3484 }
3485 }
3486
getImageUsageFromAttachmentReferences(vector<VkImageUsageFlags> & attachmentImageUsage,AttachmentRefType refType,size_t count,const AttachmentReference * references)3487 void getImageUsageFromAttachmentReferences(vector<VkImageUsageFlags>& attachmentImageUsage, AttachmentRefType refType, size_t count, const AttachmentReference* references)
3488 {
3489 for (size_t referenceNdx = 0; referenceNdx < count; ++referenceNdx)
3490 {
3491 const deUint32 attachment = references[referenceNdx].getAttachment();
3492
3493 if (attachment != VK_ATTACHMENT_UNUSED)
3494 {
3495 VkImageUsageFlags usage;
3496
3497 switch (refType)
3498 {
3499 case ATTACHMENTREFTYPE_COLOR:
3500 case ATTACHMENTREFTYPE_RESOLVE:
3501 usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
3502 break;
3503 case ATTACHMENTREFTYPE_DEPTH_STENCIL:
3504 usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
3505 break;
3506 case ATTACHMENTREFTYPE_INPUT:
3507 usage = VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
3508 break;
3509 default:
3510 DE_FATAL("Unexpected attachment reference type");
3511 usage = 0;
3512 break;
3513 }
3514
3515 attachmentImageUsage[attachment] |= usage;
3516 }
3517 }
3518 }
3519
getImageUsageFromAttachmentReferences(vector<VkImageUsageFlags> & attachmentImageUsage,AttachmentRefType refType,const vector<AttachmentReference> & references)3520 void getImageUsageFromAttachmentReferences(vector<VkImageUsageFlags>& attachmentImageUsage, AttachmentRefType refType, const vector<AttachmentReference>& references)
3521 {
3522 if (!references.empty())
3523 {
3524 getImageUsageFromAttachmentReferences(attachmentImageUsage, refType, references.size(), &references[0]);
3525 }
3526 }
3527
initializeAttachmentImageUsage(Context & context,vector<VkImageUsageFlags> & attachmentImageUsage,const RenderPass & renderPassInfo,const vector<bool> & attachmentIsLazy,const vector<Maybe<VkClearValue>> & clearValues)3528 void initializeAttachmentImageUsage (Context &context, vector<VkImageUsageFlags>& attachmentImageUsage, const RenderPass& renderPassInfo, const vector<bool>& attachmentIsLazy, const vector<Maybe<VkClearValue> >& clearValues)
3529 {
3530 attachmentImageUsage.resize(renderPassInfo.getAttachments().size(), VkImageUsageFlags(0));
3531
3532 for (size_t subpassNdx = 0; subpassNdx < renderPassInfo.getSubpasses().size(); ++subpassNdx)
3533 {
3534 const Subpass& subpass = renderPassInfo.getSubpasses()[subpassNdx];
3535
3536 getImageUsageFromAttachmentReferences(attachmentImageUsage, ATTACHMENTREFTYPE_COLOR, subpass.getColorAttachments());
3537 getImageUsageFromAttachmentReferences(attachmentImageUsage, ATTACHMENTREFTYPE_DEPTH_STENCIL, 1, &subpass.getDepthStencilAttachment());
3538 getImageUsageFromAttachmentReferences(attachmentImageUsage, ATTACHMENTREFTYPE_INPUT, subpass.getInputAttachments());
3539 getImageUsageFromAttachmentReferences(attachmentImageUsage, ATTACHMENTREFTYPE_RESOLVE, subpass.getResolveAttachments());
3540 }
3541
3542 for (size_t attachmentNdx = 0; attachmentNdx < renderPassInfo.getAttachments().size(); attachmentNdx++)
3543 {
3544 const Attachment& attachment = renderPassInfo.getAttachments()[attachmentNdx];
3545
3546 const VkFormatProperties formatProperties = getPhysicalDeviceFormatProperties(context.getInstanceInterface(), context.getPhysicalDevice(), attachment.getFormat());
3547 const VkFormatFeatureFlags supportedFeatures = formatProperties.optimalTilingFeatures;
3548
3549 if ((supportedFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) != 0)
3550 attachmentImageUsage[attachmentNdx] |= VK_IMAGE_USAGE_SAMPLED_BIT;
3551
3552 if ((supportedFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) != 0)
3553 attachmentImageUsage[attachmentNdx] |= VK_IMAGE_USAGE_STORAGE_BIT;
3554
3555 attachmentImageUsage[attachmentNdx] |= getImageUsageFromLayout(attachment.getInitialLayout());
3556 attachmentImageUsage[attachmentNdx] |= getImageUsageFromLayout(attachment.getFinalLayout());
3557
3558 if (!attachmentIsLazy[attachmentNdx])
3559 {
3560 if (clearValues[attachmentNdx])
3561 attachmentImageUsage[attachmentNdx] |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
3562
3563 attachmentImageUsage[attachmentNdx] |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
3564 }
3565 }
3566 }
3567
initializeSubpassIsSecondary(vector<bool> & subpassIsSecondary,const vector<Subpass> & subpasses,TestConfig::CommandBufferTypes commandBuffer)3568 void initializeSubpassIsSecondary (vector<bool>& subpassIsSecondary, const vector<Subpass>& subpasses, TestConfig::CommandBufferTypes commandBuffer)
3569 {
3570 bool lastSubpassWasSecondary = false;
3571
3572 for (size_t subpassNdx = 0; subpassNdx < subpasses.size(); subpassNdx++)
3573 {
3574 if (commandBuffer == TestConfig::COMMANDBUFFERTYPES_SECONDARY || (commandBuffer & TestConfig::COMMANDBUFFERTYPES_SECONDARY && !lastSubpassWasSecondary))
3575 {
3576 subpassIsSecondary.push_back(true);
3577 lastSubpassWasSecondary = true;
3578 }
3579 else if (commandBuffer & TestConfig::COMMANDBUFFERTYPES_INLINE)
3580 {
3581 subpassIsSecondary.push_back(false);
3582 lastSubpassWasSecondary = false;
3583 }
3584 else
3585 DE_FATAL("Unknown commandBuffer");
3586 }
3587 }
3588
initializeImageClearValues(de::Random & rng,vector<Maybe<VkClearValue>> & clearValues,const vector<Attachment> & attachments,const vector<bool> & isLazy)3589 void initializeImageClearValues (de::Random& rng, vector<Maybe<VkClearValue> >& clearValues, const vector<Attachment>& attachments, const vector<bool>& isLazy)
3590 {
3591 for (size_t attachmentNdx = 0; attachmentNdx < attachments.size(); attachmentNdx++)
3592 {
3593 if (!isLazy[attachmentNdx])
3594 clearValues.push_back(just(randomClearValue(attachments[attachmentNdx], rng)));
3595 else
3596 clearValues.push_back(nothing<VkClearValue>());
3597 }
3598 }
3599
initializeRenderPassClearValues(de::Random & rng,vector<Maybe<VkClearValue>> & clearValues,const vector<Attachment> & attachments)3600 void initializeRenderPassClearValues (de::Random& rng, vector<Maybe<VkClearValue> >& clearValues, const vector<Attachment>& attachments)
3601 {
3602 for (size_t attachmentNdx = 0; attachmentNdx < attachments.size(); attachmentNdx++)
3603 {
3604 if (attachments[attachmentNdx].getLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR
3605 || attachments[attachmentNdx].getStencilLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR)
3606 {
3607 clearValues.push_back(just(randomClearValue(attachments[attachmentNdx], rng)));
3608 }
3609 else
3610 clearValues.push_back(nothing<VkClearValue>());
3611 }
3612 }
3613
initializeSubpassClearValues(de::Random & rng,vector<vector<VkClearColorValue>> & clearValues,const RenderPass & renderPass)3614 void initializeSubpassClearValues (de::Random& rng, vector<vector<VkClearColorValue> >& clearValues, const RenderPass& renderPass)
3615 {
3616 clearValues.resize(renderPass.getSubpasses().size());
3617
3618 for (size_t subpassNdx = 0; subpassNdx < renderPass.getSubpasses().size(); subpassNdx++)
3619 {
3620 const Subpass& subpass = renderPass.getSubpasses()[subpassNdx];
3621 const vector<AttachmentReference>& colorAttachments = subpass.getColorAttachments();
3622
3623 clearValues[subpassNdx].resize(colorAttachments.size());
3624
3625 for (size_t attachmentRefNdx = 0; attachmentRefNdx < colorAttachments.size(); attachmentRefNdx++)
3626 {
3627 const AttachmentReference& attachmentRef = colorAttachments[attachmentRefNdx];
3628 const Attachment& attachment = renderPass.getAttachments()[attachmentRef.getAttachment()];
3629
3630 clearValues[subpassNdx][attachmentRefNdx] = randomColorClearValue(attachment, rng);
3631 }
3632 }
3633 }
3634
logSubpassRenderInfo(TestLog & log,const SubpassRenderInfo & info)3635 void logSubpassRenderInfo (TestLog& log,
3636 const SubpassRenderInfo& info)
3637 {
3638 log << TestLog::Message << "Viewport, offset: " << info.getViewportOffset() << ", size: " << info.getViewportSize() << TestLog::EndMessage;
3639
3640 if (info.isSecondary())
3641 log << TestLog::Message << "Subpass uses secondary command buffers" << TestLog::EndMessage;
3642 else
3643 log << TestLog::Message << "Subpass uses inlined commands" << TestLog::EndMessage;
3644
3645 for (deUint32 attachmentNdx = 0; attachmentNdx < info.getColorClears().size(); attachmentNdx++)
3646 {
3647 const ColorClear& colorClear = info.getColorClears()[attachmentNdx];
3648
3649 log << TestLog::Message << "Clearing color attachment " << attachmentNdx
3650 << ". Offset: " << colorClear.getOffset()
3651 << ", Size: " << colorClear.getSize()
3652 << ", Color: " << clearColorToString(info.getColorAttachment(attachmentNdx).getFormat(), colorClear.getColor()) << TestLog::EndMessage;
3653 }
3654
3655 if (info.getDepthStencilClear())
3656 {
3657 const DepthStencilClear& depthStencilClear = *info.getDepthStencilClear();
3658
3659 log << TestLog::Message << "Clearing depth stencil attachment"
3660 << ". Offset: " << depthStencilClear.getOffset()
3661 << ", Size: " << depthStencilClear.getSize()
3662 << ", Depth: " << depthStencilClear.getDepth()
3663 << ", Stencil: " << depthStencilClear.getStencil() << TestLog::EndMessage;
3664 }
3665
3666 if (info.getRenderQuad())
3667 {
3668 const RenderQuad& renderQuad = *info.getRenderQuad();
3669
3670 log << TestLog::Message << "Rendering gradient quad to " << renderQuad.getCornerA() << " -> " << renderQuad.getCornerB() << TestLog::EndMessage;
3671 }
3672 }
3673
logTestCaseInfo(TestLog & log,const TestConfig & config,const vector<bool> & attachmentIsLazy,const vector<Maybe<VkClearValue>> & imageClearValues,const vector<Maybe<VkClearValue>> & renderPassClearValues,const vector<SubpassRenderInfo> & subpassRenderInfo)3674 void logTestCaseInfo (TestLog& log,
3675 const TestConfig& config,
3676 const vector<bool>& attachmentIsLazy,
3677 const vector<Maybe<VkClearValue> >& imageClearValues,
3678 const vector<Maybe<VkClearValue> >& renderPassClearValues,
3679 const vector<SubpassRenderInfo>& subpassRenderInfo)
3680 {
3681 const RenderPass& renderPass = config.renderPass;
3682
3683 logRenderPassInfo(log, renderPass);
3684
3685 DE_ASSERT(attachmentIsLazy.size() == renderPass.getAttachments().size());
3686 DE_ASSERT(imageClearValues.size() == renderPass.getAttachments().size());
3687 DE_ASSERT(renderPassClearValues.size() == renderPass.getAttachments().size());
3688
3689 log << TestLog::Message << "TargetSize: " << config.targetSize << TestLog::EndMessage;
3690 log << TestLog::Message << "Render area, Offset: " << config.renderPos << ", Size: " << config.renderSize << TestLog::EndMessage;
3691
3692 for (size_t attachmentNdx = 0; attachmentNdx < attachmentIsLazy.size(); attachmentNdx++)
3693 {
3694 const tcu::ScopedLogSection section (log, "Attachment" + de::toString(attachmentNdx), "Attachment " + de::toString(attachmentNdx));
3695
3696 if (attachmentIsLazy[attachmentNdx])
3697 log << TestLog::Message << "Is lazy." << TestLog::EndMessage;
3698
3699 if (imageClearValues[attachmentNdx])
3700 log << TestLog::Message << "Image is cleared to " << clearValueToString(renderPass.getAttachments()[attachmentNdx].getFormat(), *imageClearValues[attachmentNdx]) << " before rendering." << TestLog::EndMessage;
3701
3702 if (renderPass.getAttachments()[attachmentNdx].getLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR && renderPassClearValues[attachmentNdx])
3703 log << TestLog::Message << "Attachment is cleared to " << clearValueToString(renderPass.getAttachments()[attachmentNdx].getFormat(), *renderPassClearValues[attachmentNdx]) << " in the beginning of the render pass." << TestLog::EndMessage;
3704 }
3705
3706 for (size_t subpassNdx = 0; subpassNdx < renderPass.getSubpasses().size(); subpassNdx++)
3707 {
3708 const tcu::ScopedLogSection section (log, "Subpass" + de::toString(subpassNdx), "Subpass " + de::toString(subpassNdx));
3709
3710 logSubpassRenderInfo(log, subpassRenderInfo[subpassNdx]);
3711 }
3712 }
3713
initializeSubpassRenderInfo(vector<SubpassRenderInfo> & renderInfos,de::Random & rng,const RenderPass & renderPass,const TestConfig & config)3714 void initializeSubpassRenderInfo (vector<SubpassRenderInfo>& renderInfos, de::Random& rng, const RenderPass& renderPass, const TestConfig& config)
3715 {
3716 const TestConfig::CommandBufferTypes commandBuffer = config.commandBufferTypes;
3717 const vector<Subpass>& subpasses = renderPass.getSubpasses();
3718 bool lastSubpassWasSecondary = false;
3719
3720 for (deUint32 subpassNdx = 0; subpassNdx < (deUint32)subpasses.size(); subpassNdx++)
3721 {
3722 const Subpass& subpass = subpasses[subpassNdx];
3723 const bool subpassIsSecondary = commandBuffer == TestConfig::COMMANDBUFFERTYPES_SECONDARY
3724 || (commandBuffer & TestConfig::COMMANDBUFFERTYPES_SECONDARY && !lastSubpassWasSecondary) ? true : false;
3725 const UVec2 viewportSize ((config.renderSize * UVec2(2)) / UVec2(3));
3726 const UVec2 viewportOffset (config.renderPos.x() + (subpassNdx % 2) * (config.renderSize.x() / 3),
3727 config.renderPos.y() + ((subpassNdx / 2) % 2) * (config.renderSize.y() / 3));
3728
3729 vector<ColorClear> colorClears;
3730 Maybe<DepthStencilClear> depthStencilClear;
3731 Maybe<RenderQuad> renderQuad;
3732
3733 lastSubpassWasSecondary = subpassIsSecondary;
3734
3735 if (config.renderTypes & TestConfig::RENDERTYPES_CLEAR)
3736 {
3737 const vector<AttachmentReference>& colorAttachments = subpass.getColorAttachments();
3738
3739 for (size_t attachmentRefNdx = 0; attachmentRefNdx < colorAttachments.size(); attachmentRefNdx++)
3740 {
3741 const AttachmentReference& attachmentRef = colorAttachments[attachmentRefNdx];
3742 const Attachment& attachment = renderPass.getAttachments()[attachmentRef.getAttachment()];
3743 const UVec2 size ((viewportSize * UVec2(2)) / UVec2(3));
3744 const UVec2 offset (viewportOffset.x() + ((deUint32)attachmentRefNdx % 2u) * (viewportSize.x() / 3u),
3745 viewportOffset.y() + (((deUint32)attachmentRefNdx / 2u) % 2u) * (viewportSize.y() / 3u));
3746 const VkClearColorValue color = randomColorClearValue(attachment, rng);
3747
3748 colorClears.push_back(ColorClear(offset, size, color));
3749 }
3750
3751 if (subpass.getDepthStencilAttachment().getAttachment() != VK_ATTACHMENT_UNUSED)
3752 {
3753 const Attachment& attachment = renderPass.getAttachments()[subpass.getDepthStencilAttachment().getAttachment()];
3754 const UVec2 size ((viewportSize * UVec2(2)) / UVec2(3));
3755 const UVec2 offset (viewportOffset.x() + ((deUint32)colorAttachments.size() % 2u) * (viewportSize.x() / 3u),
3756 viewportOffset.y() + (((deUint32)colorAttachments.size() / 2u) % 2u) * (viewportSize.y() / 3u));
3757 const VkClearValue value = randomClearValue(attachment, rng);
3758
3759 depthStencilClear = tcu::just(DepthStencilClear(offset, size, value.depthStencil.depth, value.depthStencil.stencil));
3760 }
3761 }
3762
3763 if (config.renderTypes & TestConfig::RENDERTYPES_DRAW)
3764 {
3765 // (-0.5,-0.5) - (0.5,0.5) rounded to pixel edges
3766 const float x = (float)(viewportSize.x() / 4) / (float)(viewportSize.x() / 2);
3767 const float y = (float)(viewportSize.y() / 4) / (float)(viewportSize.y() / 2);
3768 renderQuad = tcu::just(RenderQuad(tcu::Vec4(-x, -y, 0.0f, 1.0f), tcu::Vec4(x, y, 1.0f, 1.0f)));
3769 }
3770
3771 renderInfos.push_back(SubpassRenderInfo(renderPass, subpassNdx, subpassIsSecondary, viewportOffset, viewportSize, renderQuad, colorClears, depthStencilClear));
3772 }
3773 }
3774
checkTextureFormatSupport(TestLog & log,const InstanceInterface & vk,VkPhysicalDevice device,const vector<Attachment> & attachments)3775 void checkTextureFormatSupport (TestLog& log,
3776 const InstanceInterface& vk,
3777 VkPhysicalDevice device,
3778 const vector<Attachment>& attachments)
3779 {
3780 bool supported = true;
3781
3782 for (size_t attachmentNdx = 0; attachmentNdx < attachments.size(); attachmentNdx++)
3783 {
3784 const Attachment& attachment = attachments[attachmentNdx];
3785 const tcu::TextureFormat format = mapVkFormat(attachment.getFormat());
3786 const bool isDepthOrStencilAttachment = hasDepthComponent(format.order) || hasStencilComponent(format.order);
3787 const VkFormatFeatureFlags flags = isDepthOrStencilAttachment? VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT : VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
3788 VkFormatProperties properties;
3789
3790 vk.getPhysicalDeviceFormatProperties(device, attachment.getFormat(), &properties);
3791
3792 if ((properties.optimalTilingFeatures & flags) != flags)
3793 {
3794 supported = false;
3795 log << TestLog::Message << "Format: " << attachment.getFormat() << " not supported as " << (isDepthOrStencilAttachment ? "depth stencil attachment" : "color attachment") << TestLog::EndMessage;
3796 }
3797 }
3798
3799 if (!supported)
3800 TCU_THROW(NotSupportedError, "Format not supported");
3801 }
3802
renderPassTest(Context & context,TestConfig config)3803 tcu::TestStatus renderPassTest (Context& context, TestConfig config)
3804 {
3805 const UVec2 targetSize = config.targetSize;
3806 const UVec2 renderPos = config.renderPos;
3807 const UVec2 renderSize = config.renderSize;
3808 const RenderPass& renderPassInfo = config.renderPass;
3809
3810 TestLog& log = context.getTestContext().getLog();
3811 de::Random rng (config.seed);
3812
3813 vector<bool> attachmentIsLazy;
3814 vector<VkImageUsageFlags> attachmentImageUsage;
3815 vector<Maybe<VkClearValue> > imageClearValues;
3816 vector<Maybe<VkClearValue> > renderPassClearValues;
3817
3818 vector<bool> subpassIsSecondary;
3819 vector<SubpassRenderInfo> subpassRenderInfo;
3820 vector<vector<VkClearColorValue> > subpassColorClearValues;
3821
3822 initializeAttachmentIsLazy(attachmentIsLazy, renderPassInfo.getAttachments(), config.imageMemory);
3823 initializeImageClearValues(rng, imageClearValues, renderPassInfo.getAttachments(), attachmentIsLazy);
3824 initializeAttachmentImageUsage(context, attachmentImageUsage, renderPassInfo, attachmentIsLazy, imageClearValues);
3825 initializeRenderPassClearValues(rng, renderPassClearValues, renderPassInfo.getAttachments());
3826
3827 initializeSubpassIsSecondary(subpassIsSecondary, renderPassInfo.getSubpasses(), config.commandBufferTypes);
3828 initializeSubpassClearValues(rng, subpassColorClearValues, renderPassInfo);
3829 initializeSubpassRenderInfo(subpassRenderInfo, rng, renderPassInfo, config);
3830
3831 logTestCaseInfo(log, config, attachmentIsLazy, imageClearValues, renderPassClearValues, subpassRenderInfo);
3832
3833 checkTextureFormatSupport(log, context.getInstanceInterface(), context.getPhysicalDevice(), config.renderPass.getAttachments());
3834
3835 {
3836 const vk::VkPhysicalDeviceProperties properties = vk::getPhysicalDeviceProperties(context.getInstanceInterface(), context.getPhysicalDevice());
3837
3838 log << TestLog::Message << "Max color attachments: " << properties.limits.maxColorAttachments << TestLog::EndMessage;
3839
3840 for (size_t subpassNdx = 0; subpassNdx < renderPassInfo.getSubpasses().size(); subpassNdx++)
3841 {
3842 if (renderPassInfo.getSubpasses()[subpassNdx].getColorAttachments().size() > (size_t)properties.limits.maxColorAttachments)
3843 TCU_THROW(NotSupportedError, "Subpass uses more than maxColorAttachments.");
3844 }
3845 }
3846
3847 {
3848 const VkDevice device = context.getDevice();
3849 const DeviceInterface& vk = context.getDeviceInterface();
3850 const VkQueue queue = context.getUniversalQueue();
3851 const deUint32 queueIndex = context.getUniversalQueueFamilyIndex();
3852 Allocator& allocator = context.getDefaultAllocator();
3853
3854 const Unique<VkRenderPass> renderPass (createRenderPass(vk, device, renderPassInfo));
3855 const Unique<VkCommandPool> commandBufferPool (createCommandPool(vk, device, queueIndex, 0));
3856 const Unique<VkCommandBuffer> initializeImagesCommandBuffer (allocateCommandBuffer(vk, device, *commandBufferPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
3857 const Unique<VkCommandBuffer> renderCommandBuffer (allocateCommandBuffer(vk, device, *commandBufferPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
3858 const Unique<VkCommandBuffer> readImagesToBuffersCommandBuffer (allocateCommandBuffer(vk, device, *commandBufferPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
3859
3860 vector<de::SharedPtr<AttachmentResources> > attachmentResources;
3861 vector<de::SharedPtr<SubpassRenderer> > subpassRenderers;
3862 vector<VkImageView> attachmentViews;
3863
3864 for (size_t attachmentNdx = 0; attachmentNdx < renderPassInfo.getAttachments().size(); attachmentNdx++)
3865 {
3866 const Attachment& attachmentInfo = renderPassInfo.getAttachments()[attachmentNdx];
3867
3868 attachmentResources.push_back(de::SharedPtr<AttachmentResources>(new AttachmentResources(vk, device, allocator, queueIndex, targetSize, attachmentInfo, attachmentImageUsage[attachmentNdx])));
3869 attachmentViews.push_back(attachmentResources[attachmentNdx]->getAttachmentView());
3870 }
3871
3872 beginCommandBuffer(vk, *initializeImagesCommandBuffer, (VkCommandBufferUsageFlags)0, DE_NULL, 0, DE_NULL, VK_FALSE, (VkQueryControlFlags)0, (VkQueryPipelineStatisticFlags)0);
3873 pushImageInitializationCommands(vk, *initializeImagesCommandBuffer, renderPassInfo.getAttachments(), attachmentResources, queueIndex, imageClearValues);
3874 endCommandBuffer(vk, *initializeImagesCommandBuffer);
3875
3876 {
3877 const Unique<VkFramebuffer> framebuffer (createFramebuffer(vk, device, *renderPass, targetSize, attachmentViews));
3878
3879 for (size_t subpassNdx = 0; subpassNdx < renderPassInfo.getSubpasses().size(); subpassNdx++)
3880 subpassRenderers.push_back(de::SharedPtr<SubpassRenderer>(new SubpassRenderer(context, vk, device, allocator, *renderPass, *framebuffer, *commandBufferPool, queueIndex, subpassRenderInfo[subpassNdx])));
3881
3882 beginCommandBuffer(vk, *renderCommandBuffer, (VkCommandBufferUsageFlags)0, DE_NULL, 0, DE_NULL, VK_FALSE, (VkQueryControlFlags)0, (VkQueryPipelineStatisticFlags)0);
3883 pushRenderPassCommands(vk, *renderCommandBuffer, *renderPass, *framebuffer, subpassRenderers, renderPos, renderSize, renderPassClearValues, config.renderTypes);
3884 endCommandBuffer(vk, *renderCommandBuffer);
3885
3886 beginCommandBuffer(vk, *readImagesToBuffersCommandBuffer, (VkCommandBufferUsageFlags)0, DE_NULL, 0, DE_NULL, VK_FALSE, (VkQueryControlFlags)0, (VkQueryPipelineStatisticFlags)0);
3887 pushReadImagesToBuffers(vk, *readImagesToBuffersCommandBuffer, queueIndex, attachmentResources, renderPassInfo.getAttachments(), attachmentIsLazy, targetSize);
3888 endCommandBuffer(vk, *readImagesToBuffersCommandBuffer);
3889 {
3890 const VkCommandBuffer commandBuffers[] =
3891 {
3892 *initializeImagesCommandBuffer,
3893 *renderCommandBuffer,
3894 *readImagesToBuffersCommandBuffer
3895 };
3896 const Unique<VkFence> fence (createFence(vk, device, 0u));
3897
3898 queueSubmit(vk, queue, DE_LENGTH_OF_ARRAY(commandBuffers), commandBuffers, *fence);
3899 waitForFences(vk, device, 1, &fence.get(), VK_TRUE, ~0ull);
3900 }
3901 }
3902
3903 if (logAndVerifyImages(log, vk, device, attachmentResources, attachmentIsLazy, renderPassInfo, renderPassClearValues, imageClearValues, subpassRenderInfo, targetSize, config))
3904 return tcu::TestStatus::pass("Pass");
3905 else
3906 return tcu::TestStatus::fail("Result verification failed");
3907 }
3908 }
3909
3910 static const VkFormat s_coreColorFormats[] =
3911 {
3912 VK_FORMAT_R5G6B5_UNORM_PACK16,
3913 VK_FORMAT_R8_UNORM,
3914 VK_FORMAT_R8_SNORM,
3915 VK_FORMAT_R8_UINT,
3916 VK_FORMAT_R8_SINT,
3917 VK_FORMAT_R8G8_UNORM,
3918 VK_FORMAT_R8G8_SNORM,
3919 VK_FORMAT_R8G8_UINT,
3920 VK_FORMAT_R8G8_SINT,
3921 VK_FORMAT_R8G8B8A8_UNORM,
3922 VK_FORMAT_R8G8B8A8_SNORM,
3923 VK_FORMAT_R8G8B8A8_UINT,
3924 VK_FORMAT_R8G8B8A8_SINT,
3925 VK_FORMAT_R8G8B8A8_SRGB,
3926 VK_FORMAT_A8B8G8R8_UNORM_PACK32,
3927 VK_FORMAT_A8B8G8R8_SNORM_PACK32,
3928 VK_FORMAT_A8B8G8R8_UINT_PACK32,
3929 VK_FORMAT_A8B8G8R8_SINT_PACK32,
3930 VK_FORMAT_A8B8G8R8_SRGB_PACK32,
3931 VK_FORMAT_B8G8R8A8_UNORM,
3932 VK_FORMAT_B8G8R8A8_SRGB,
3933 VK_FORMAT_A2R10G10B10_UNORM_PACK32,
3934 VK_FORMAT_A2B10G10R10_UNORM_PACK32,
3935 VK_FORMAT_A2B10G10R10_UINT_PACK32,
3936 VK_FORMAT_R16_UNORM,
3937 VK_FORMAT_R16_SNORM,
3938 VK_FORMAT_R16_UINT,
3939 VK_FORMAT_R16_SINT,
3940 VK_FORMAT_R16_SFLOAT,
3941 VK_FORMAT_R16G16_UNORM,
3942 VK_FORMAT_R16G16_SNORM,
3943 VK_FORMAT_R16G16_UINT,
3944 VK_FORMAT_R16G16_SINT,
3945 VK_FORMAT_R16G16_SFLOAT,
3946 VK_FORMAT_R16G16B16A16_UNORM,
3947 VK_FORMAT_R16G16B16A16_SNORM,
3948 VK_FORMAT_R16G16B16A16_UINT,
3949 VK_FORMAT_R16G16B16A16_SINT,
3950 VK_FORMAT_R16G16B16A16_SFLOAT,
3951 VK_FORMAT_R32_UINT,
3952 VK_FORMAT_R32_SINT,
3953 VK_FORMAT_R32_SFLOAT,
3954 VK_FORMAT_R32G32_UINT,
3955 VK_FORMAT_R32G32_SINT,
3956 VK_FORMAT_R32G32_SFLOAT,
3957 VK_FORMAT_R32G32B32A32_UINT,
3958 VK_FORMAT_R32G32B32A32_SINT,
3959 VK_FORMAT_R32G32B32A32_SFLOAT
3960 };
3961
3962 static const VkFormat s_coreDepthStencilFormats[] =
3963 {
3964 VK_FORMAT_D16_UNORM,
3965
3966 VK_FORMAT_X8_D24_UNORM_PACK32,
3967 VK_FORMAT_D32_SFLOAT,
3968
3969 VK_FORMAT_D24_UNORM_S8_UINT,
3970 VK_FORMAT_D32_SFLOAT_S8_UINT
3971 };
3972
createAttachmentTestCaseGroup(tcu::TestContext & testCtx)3973 de::MovePtr<tcu::TestCaseGroup> createAttachmentTestCaseGroup (tcu::TestContext& testCtx)
3974 {
3975 const deUint32 attachmentCounts[] = { 1, 3, 4, 8 };
3976 const VkAttachmentLoadOp loadOps[] =
3977 {
3978 VK_ATTACHMENT_LOAD_OP_LOAD,
3979 VK_ATTACHMENT_LOAD_OP_CLEAR,
3980 VK_ATTACHMENT_LOAD_OP_DONT_CARE
3981 };
3982
3983 const VkAttachmentStoreOp storeOps[] =
3984 {
3985 VK_ATTACHMENT_STORE_OP_STORE,
3986 VK_ATTACHMENT_STORE_OP_DONT_CARE
3987 };
3988
3989 const VkImageLayout initialAndFinalColorLayouts[] =
3990 {
3991 VK_IMAGE_LAYOUT_GENERAL,
3992 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
3993 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
3994 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
3995 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
3996 };
3997
3998 const VkImageLayout initialAndFinalDepthStencilLayouts[] =
3999 {
4000 VK_IMAGE_LAYOUT_GENERAL,
4001 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
4002 VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL,
4003 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
4004 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
4005 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
4006 };
4007
4008 const VkImageLayout subpassLayouts[] =
4009 {
4010 VK_IMAGE_LAYOUT_GENERAL,
4011 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
4012 };
4013
4014 const VkImageLayout depthStencilLayouts[] =
4015 {
4016 VK_IMAGE_LAYOUT_GENERAL,
4017 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
4018 };
4019
4020 const TestConfig::RenderTypes renderCommands[] =
4021 {
4022 TestConfig::RENDERTYPES_NONE,
4023 TestConfig::RENDERTYPES_CLEAR,
4024 TestConfig::RENDERTYPES_DRAW,
4025 TestConfig::RENDERTYPES_CLEAR|TestConfig::RENDERTYPES_DRAW,
4026 };
4027
4028 const TestConfig::CommandBufferTypes commandBuffers[] =
4029 {
4030 TestConfig::COMMANDBUFFERTYPES_INLINE,
4031 TestConfig::COMMANDBUFFERTYPES_SECONDARY,
4032 TestConfig::COMMANDBUFFERTYPES_INLINE|TestConfig::COMMANDBUFFERTYPES_SECONDARY
4033 };
4034
4035 const TestConfig::ImageMemory imageMemories[] =
4036 {
4037 TestConfig::IMAGEMEMORY_STRICT,
4038 TestConfig::IMAGEMEMORY_LAZY,
4039 TestConfig::IMAGEMEMORY_STRICT|TestConfig::IMAGEMEMORY_LAZY
4040 };
4041
4042 const UVec2 targetSizes[] =
4043 {
4044 UVec2(64, 64),
4045 UVec2(63, 65)
4046 };
4047
4048 const UVec2 renderPositions[] =
4049 {
4050 UVec2(0, 0),
4051 UVec2(3, 17)
4052 };
4053
4054 const UVec2 renderSizes[] =
4055 {
4056 UVec2(32, 32),
4057 UVec2(60, 47)
4058 };
4059
4060 de::Random rng (1433774382u);
4061 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "attachment", "Attachment format and count tests with load and store ops and image layouts"));
4062
4063 for (size_t attachmentCountNdx = 0; attachmentCountNdx < DE_LENGTH_OF_ARRAY(attachmentCounts); attachmentCountNdx++)
4064 {
4065 const deUint32 attachmentCount = attachmentCounts[attachmentCountNdx];
4066 const deUint32 testCaseCount = (attachmentCount == 1 ? 100 : 200);
4067 de::MovePtr<tcu::TestCaseGroup> attachmentCountGroup (new tcu::TestCaseGroup(testCtx, de::toString(attachmentCount).c_str(), de::toString(attachmentCount).c_str()));
4068
4069 for (size_t testCaseNdx = 0; testCaseNdx < testCaseCount; testCaseNdx++)
4070 {
4071 const bool useDepthStencil = rng.getBool();
4072 VkImageLayout depthStencilLayout = VK_IMAGE_LAYOUT_GENERAL;
4073 vector<Attachment> attachments;
4074 vector<AttachmentReference> colorAttachmentReferences;
4075
4076 for (size_t attachmentNdx = 0; attachmentNdx < attachmentCount; attachmentNdx++)
4077 {
4078 const VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT;
4079 const VkFormat format = rng.choose<VkFormat>(DE_ARRAY_BEGIN(s_coreColorFormats), DE_ARRAY_END(s_coreColorFormats));
4080 const VkAttachmentLoadOp loadOp = rng.choose<VkAttachmentLoadOp>(DE_ARRAY_BEGIN(loadOps), DE_ARRAY_END(loadOps));
4081 const VkAttachmentStoreOp storeOp = rng.choose<VkAttachmentStoreOp>(DE_ARRAY_BEGIN(storeOps), DE_ARRAY_END(storeOps));
4082
4083 const VkImageLayout initialLayout = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalColorLayouts), DE_ARRAY_END(initialAndFinalColorLayouts));
4084 const VkImageLayout finalizeLayout = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalColorLayouts), DE_ARRAY_END(initialAndFinalColorLayouts));
4085 const VkImageLayout subpassLayout = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(subpassLayouts), DE_ARRAY_END(subpassLayouts));
4086
4087 const VkAttachmentLoadOp stencilLoadOp = rng.choose<VkAttachmentLoadOp>(DE_ARRAY_BEGIN(loadOps), DE_ARRAY_END(loadOps));
4088 const VkAttachmentStoreOp stencilStoreOp = rng.choose<VkAttachmentStoreOp>(DE_ARRAY_BEGIN(storeOps), DE_ARRAY_END(storeOps));
4089
4090 attachments.push_back(Attachment(format, sampleCount, loadOp, storeOp, stencilLoadOp, stencilStoreOp, initialLayout, finalizeLayout));
4091 colorAttachmentReferences.push_back(AttachmentReference((deUint32)attachmentNdx, subpassLayout));
4092 }
4093
4094 if (useDepthStencil)
4095 {
4096 const VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT;
4097 const VkFormat format = rng.choose<VkFormat>(DE_ARRAY_BEGIN(s_coreDepthStencilFormats), DE_ARRAY_END(s_coreDepthStencilFormats));
4098 const VkAttachmentLoadOp loadOp = rng.choose<VkAttachmentLoadOp>(DE_ARRAY_BEGIN(loadOps), DE_ARRAY_END(loadOps));
4099 const VkAttachmentStoreOp storeOp = rng.choose<VkAttachmentStoreOp>(DE_ARRAY_BEGIN(storeOps), DE_ARRAY_END(storeOps));
4100
4101 const VkImageLayout initialLayout = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalDepthStencilLayouts), DE_ARRAY_END(initialAndFinalDepthStencilLayouts));
4102 const VkImageLayout finalizeLayout = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalDepthStencilLayouts), DE_ARRAY_END(initialAndFinalDepthStencilLayouts));
4103
4104 const VkAttachmentLoadOp stencilLoadOp = rng.choose<VkAttachmentLoadOp>(DE_ARRAY_BEGIN(loadOps), DE_ARRAY_END(loadOps));
4105 const VkAttachmentStoreOp stencilStoreOp = rng.choose<VkAttachmentStoreOp>(DE_ARRAY_BEGIN(storeOps), DE_ARRAY_END(storeOps));
4106
4107 depthStencilLayout = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(depthStencilLayouts), DE_ARRAY_END(depthStencilLayouts));
4108 attachments.push_back(Attachment(format, sampleCount, loadOp, storeOp, stencilLoadOp, stencilStoreOp, initialLayout, finalizeLayout));
4109 }
4110
4111 {
4112 const TestConfig::RenderTypes render = rng.choose<TestConfig::RenderTypes>(DE_ARRAY_BEGIN(renderCommands), DE_ARRAY_END(renderCommands));
4113 const TestConfig::CommandBufferTypes commandBuffer = rng.choose<TestConfig::CommandBufferTypes>(DE_ARRAY_BEGIN(commandBuffers), DE_ARRAY_END(commandBuffers));
4114 const TestConfig::ImageMemory imageMemory = rng.choose<TestConfig::ImageMemory>(DE_ARRAY_BEGIN(imageMemories), DE_ARRAY_END(imageMemories));
4115 const vector<Subpass> subpasses (1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(), colorAttachmentReferences, vector<AttachmentReference>(), AttachmentReference((useDepthStencil ? (deUint32)(attachments.size() - 1) : VK_ATTACHMENT_UNUSED), depthStencilLayout), vector<AttachmentReference>()));
4116 const vector<SubpassDependency> deps;
4117
4118 const string testCaseName = de::toString(attachmentCountNdx * testCaseCount + testCaseNdx);
4119 const RenderPass renderPass (attachments, subpasses, deps);
4120 const UVec2 targetSize = rng.choose<UVec2>(DE_ARRAY_BEGIN(targetSizes), DE_ARRAY_END(targetSizes));
4121 const UVec2 renderPos = rng.choose<UVec2>(DE_ARRAY_BEGIN(renderPositions), DE_ARRAY_END(renderPositions));
4122 const UVec2 renderSize = rng.choose<UVec2>(DE_ARRAY_BEGIN(renderSizes), DE_ARRAY_END(renderSizes));
4123
4124 addFunctionCaseWithPrograms<TestConfig>(attachmentCountGroup.get(), testCaseName.c_str(), testCaseName.c_str(), createTestShaders, renderPassTest, TestConfig(renderPass, render, commandBuffer, imageMemory, targetSize, renderPos, renderSize, 1293809));
4125 }
4126 }
4127
4128 group->addChild(attachmentCountGroup.release());
4129 }
4130
4131 return group;
4132 }
4133
createAttachmentAllocationTestGroup(tcu::TestContext & testCtx)4134 de::MovePtr<tcu::TestCaseGroup> createAttachmentAllocationTestGroup (tcu::TestContext& testCtx)
4135 {
4136 const deUint32 attachmentCounts[] = { 4, 8 };
4137 const VkAttachmentLoadOp loadOps[] =
4138 {
4139 VK_ATTACHMENT_LOAD_OP_LOAD,
4140 VK_ATTACHMENT_LOAD_OP_CLEAR,
4141 VK_ATTACHMENT_LOAD_OP_DONT_CARE
4142 };
4143
4144 const VkAttachmentStoreOp storeOps[] =
4145 {
4146 VK_ATTACHMENT_STORE_OP_STORE,
4147 VK_ATTACHMENT_STORE_OP_DONT_CARE
4148 };
4149
4150 const VkImageLayout initialAndFinalColorLayouts[] =
4151 {
4152 VK_IMAGE_LAYOUT_GENERAL,
4153 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
4154 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
4155 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
4156 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
4157 };
4158
4159 const VkImageLayout subpassLayouts[] =
4160 {
4161 VK_IMAGE_LAYOUT_GENERAL,
4162 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
4163 };
4164
4165 enum AllocationType
4166 {
4167 // Each pass uses one more attachmen than previous one
4168 ALLOCATIONTYPE_GROW,
4169 // Each pass uses one less attachment than previous one
4170 ALLOCATIONTYPE_SHRINK,
4171 // Each pass drops one attachment and picks up new one
4172 ALLOCATIONTYPE_ROLL,
4173 // Start by growing and end by shrinking
4174 ALLOCATIONTYPE_GROW_SHRINK
4175 };
4176
4177 const AllocationType allocationTypes[] =
4178 {
4179 ALLOCATIONTYPE_GROW,
4180 ALLOCATIONTYPE_SHRINK,
4181 ALLOCATIONTYPE_ROLL,
4182 ALLOCATIONTYPE_GROW_SHRINK
4183 };
4184
4185 const char* const allocationTypeStr[] =
4186 {
4187 "grow",
4188 "shrink",
4189 "roll",
4190 "grow_shrink"
4191 };
4192
4193 const TestConfig::RenderTypes renderCommands[] =
4194 {
4195 TestConfig::RENDERTYPES_NONE,
4196 TestConfig::RENDERTYPES_CLEAR,
4197 TestConfig::RENDERTYPES_DRAW,
4198 TestConfig::RENDERTYPES_CLEAR|TestConfig::RENDERTYPES_DRAW,
4199 };
4200
4201 const TestConfig::CommandBufferTypes commandBuffers[] =
4202 {
4203 TestConfig::COMMANDBUFFERTYPES_INLINE,
4204 TestConfig::COMMANDBUFFERTYPES_SECONDARY,
4205 TestConfig::COMMANDBUFFERTYPES_INLINE|TestConfig::COMMANDBUFFERTYPES_SECONDARY
4206 };
4207
4208 const TestConfig::ImageMemory imageMemories[] =
4209 {
4210 TestConfig::IMAGEMEMORY_STRICT,
4211 TestConfig::IMAGEMEMORY_LAZY,
4212 TestConfig::IMAGEMEMORY_STRICT|TestConfig::IMAGEMEMORY_LAZY
4213 };
4214
4215 const UVec2 targetSizes[] =
4216 {
4217 UVec2(64, 64),
4218 UVec2(63, 65)
4219 };
4220
4221 const UVec2 renderPositions[] =
4222 {
4223 UVec2(0, 0),
4224 UVec2(3, 17)
4225 };
4226
4227 const UVec2 renderSizes[] =
4228 {
4229 UVec2(32, 32),
4230 UVec2(60, 47)
4231 };
4232
4233 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "attachment_allocation", "Attachment allocation tests"));
4234 de::Random rng (3700649827u);
4235
4236 for (size_t allocationTypeNdx = 0; allocationTypeNdx < DE_LENGTH_OF_ARRAY(allocationTypes); allocationTypeNdx++)
4237 {
4238 const AllocationType allocationType = allocationTypes[allocationTypeNdx];
4239 const size_t testCaseCount = 100;
4240 de::MovePtr<tcu::TestCaseGroup> allocationTypeGroup (new tcu::TestCaseGroup(testCtx, allocationTypeStr[allocationTypeNdx], allocationTypeStr[allocationTypeNdx]));
4241
4242 for (size_t testCaseNdx = 0; testCaseNdx < testCaseCount; testCaseNdx++)
4243 {
4244 const deUint32 attachmentCount = rng.choose<deUint32>(DE_ARRAY_BEGIN(attachmentCounts), DE_ARRAY_END(attachmentCounts));
4245 vector<Attachment> attachments;
4246 vector<Subpass> subpasses;
4247
4248 for (size_t attachmentNdx = 0; attachmentNdx < attachmentCount; attachmentNdx++)
4249 {
4250 const VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT;
4251 const VkFormat format = rng.choose<VkFormat>(DE_ARRAY_BEGIN(s_coreColorFormats), DE_ARRAY_END(s_coreColorFormats));
4252 const VkAttachmentLoadOp loadOp = rng.choose<VkAttachmentLoadOp>(DE_ARRAY_BEGIN(loadOps), DE_ARRAY_END(loadOps));
4253 const VkAttachmentStoreOp storeOp = rng.choose<VkAttachmentStoreOp>(DE_ARRAY_BEGIN(storeOps), DE_ARRAY_END(storeOps));
4254
4255 const VkImageLayout initialLayout = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalColorLayouts), DE_ARRAY_END(initialAndFinalColorLayouts));
4256 const VkImageLayout finalizeLayout = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalColorLayouts), DE_ARRAY_END(initialAndFinalColorLayouts));
4257
4258 const VkAttachmentLoadOp stencilLoadOp = rng.choose<VkAttachmentLoadOp>(DE_ARRAY_BEGIN(loadOps), DE_ARRAY_END(loadOps));
4259 const VkAttachmentStoreOp stencilStoreOp = rng.choose<VkAttachmentStoreOp>(DE_ARRAY_BEGIN(storeOps), DE_ARRAY_END(storeOps));
4260
4261 attachments.push_back(Attachment(format, sampleCount, loadOp, storeOp, stencilLoadOp, stencilStoreOp, initialLayout, finalizeLayout));
4262 }
4263
4264 if (allocationType == ALLOCATIONTYPE_GROW)
4265 {
4266 for (size_t subpassNdx = 0; subpassNdx < attachmentCount; subpassNdx++)
4267 {
4268 vector<AttachmentReference> colorAttachmentReferences;
4269
4270 for (size_t attachmentNdx = 0; attachmentNdx < subpassNdx + 1; attachmentNdx++)
4271 {
4272 const VkImageLayout subpassLayout = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(subpassLayouts), DE_ARRAY_END(subpassLayouts));
4273
4274 colorAttachmentReferences.push_back(AttachmentReference((deUint32)attachmentNdx, subpassLayout));
4275 }
4276
4277 subpasses.push_back(Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(), colorAttachmentReferences, vector<AttachmentReference>(), AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL), vector<AttachmentReference>()));
4278 }
4279 }
4280 else if (allocationType == ALLOCATIONTYPE_SHRINK)
4281 {
4282 for (size_t subpassNdx = 0; subpassNdx < attachmentCount; subpassNdx++)
4283 {
4284 vector<AttachmentReference> colorAttachmentReferences;
4285
4286 for (size_t attachmentNdx = 0; attachmentNdx < (attachmentCount - subpassNdx); attachmentNdx++)
4287 {
4288 const VkImageLayout subpassLayout = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(subpassLayouts), DE_ARRAY_END(subpassLayouts));
4289
4290 colorAttachmentReferences.push_back(AttachmentReference((deUint32)attachmentNdx, subpassLayout));
4291 }
4292
4293 subpasses.push_back(Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(), colorAttachmentReferences, vector<AttachmentReference>(), AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL), vector<AttachmentReference>()));
4294 }
4295 }
4296 else if (allocationType == ALLOCATIONTYPE_ROLL)
4297 {
4298 for (size_t subpassNdx = 0; subpassNdx < attachmentCount / 2; subpassNdx++)
4299 {
4300 vector<AttachmentReference> colorAttachmentReferences;
4301
4302 for (size_t attachmentNdx = 0; attachmentNdx < attachmentCount / 2; attachmentNdx++)
4303 {
4304 const VkImageLayout subpassLayout = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(subpassLayouts), DE_ARRAY_END(subpassLayouts));
4305
4306 colorAttachmentReferences.push_back(AttachmentReference((deUint32)(subpassNdx + attachmentNdx), subpassLayout));
4307 }
4308
4309 subpasses.push_back(Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(), colorAttachmentReferences, vector<AttachmentReference>(), AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL), vector<AttachmentReference>()));
4310 }
4311 }
4312 else if (allocationType == ALLOCATIONTYPE_GROW_SHRINK)
4313 {
4314 for (size_t subpassNdx = 0; subpassNdx < attachmentCount; subpassNdx++)
4315 {
4316 vector<AttachmentReference> colorAttachmentReferences;
4317
4318 for (size_t attachmentNdx = 0; attachmentNdx < subpassNdx + 1; attachmentNdx++)
4319 {
4320 const VkImageLayout subpassLayout = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(subpassLayouts), DE_ARRAY_END(subpassLayouts));
4321
4322 colorAttachmentReferences.push_back(AttachmentReference((deUint32)attachmentNdx, subpassLayout));
4323 }
4324
4325 subpasses.push_back(Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(), colorAttachmentReferences, vector<AttachmentReference>(), AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL), vector<AttachmentReference>()));
4326 }
4327
4328 for (size_t subpassNdx = 0; subpassNdx < attachmentCount; subpassNdx++)
4329 {
4330 vector<AttachmentReference> colorAttachmentReferences;
4331
4332 for (size_t attachmentNdx = 0; attachmentNdx < (attachmentCount - subpassNdx); attachmentNdx++)
4333 {
4334 const VkImageLayout subpassLayout = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(subpassLayouts), DE_ARRAY_END(subpassLayouts));
4335
4336 colorAttachmentReferences.push_back(AttachmentReference((deUint32)attachmentNdx, subpassLayout));
4337 }
4338
4339 subpasses.push_back(Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(), colorAttachmentReferences, vector<AttachmentReference>(), AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL), vector<AttachmentReference>()));
4340 }
4341 }
4342 else
4343 DE_FATAL("Unknown allocation type");
4344
4345 {
4346 const TestConfig::RenderTypes render = rng.choose<TestConfig::RenderTypes>(DE_ARRAY_BEGIN(renderCommands), DE_ARRAY_END(renderCommands));
4347 const TestConfig::CommandBufferTypes commandBuffer = rng.choose<TestConfig::CommandBufferTypes>(DE_ARRAY_BEGIN(commandBuffers), DE_ARRAY_END(commandBuffers));
4348 const TestConfig::ImageMemory imageMemory = rng.choose<TestConfig::ImageMemory>(DE_ARRAY_BEGIN(imageMemories), DE_ARRAY_END(imageMemories));
4349
4350 const string testCaseName = de::toString(testCaseNdx);
4351 const UVec2 targetSize = rng.choose<UVec2>(DE_ARRAY_BEGIN(targetSizes), DE_ARRAY_END(targetSizes));
4352 const UVec2 renderPos = rng.choose<UVec2>(DE_ARRAY_BEGIN(renderPositions), DE_ARRAY_END(renderPositions));
4353 const UVec2 renderSize = rng.choose<UVec2>(DE_ARRAY_BEGIN(renderSizes), DE_ARRAY_END(renderSizes));
4354
4355 vector<SubpassDependency> deps;
4356
4357 for (size_t subpassNdx = 0; subpassNdx < subpasses.size() - 1; subpassNdx++)
4358 {
4359 const bool byRegion = rng.getBool();
4360 deps.push_back(SubpassDependency((deUint32)subpassNdx, (deUint32)subpassNdx + 1,
4361 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
4362 | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
4363 | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
4364 | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
4365
4366 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
4367 | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
4368 | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
4369 | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
4370
4371 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
4372 VK_ACCESS_COLOR_ATTACHMENT_READ_BIT, // \todo [pyry] Correct?
4373
4374 byRegion ? (VkBool32)VK_TRUE : (VkBool32)VK_FALSE));
4375 }
4376
4377 const RenderPass renderPass (attachments, subpasses, deps);
4378
4379 addFunctionCaseWithPrograms<TestConfig>(allocationTypeGroup.get(), testCaseName.c_str(), testCaseName.c_str(), createTestShaders, renderPassTest, TestConfig(renderPass, render, commandBuffer, imageMemory, targetSize, renderPos, renderSize, 80329));
4380 }
4381 }
4382
4383 group->addChild(allocationTypeGroup.release());
4384 }
4385
4386 return group;
4387 }
4388
createSimpleTestGroup(tcu::TestContext & testCtx)4389 de::MovePtr<tcu::TestCaseGroup> createSimpleTestGroup (tcu::TestContext& testCtx)
4390 {
4391 const UVec2 targetSize (64, 64);
4392 const UVec2 renderPos (0, 0);
4393 const UVec2 renderSize (64, 64);
4394 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "simple", "Simple basic render pass tests"));
4395
4396 // color
4397 {
4398 const RenderPass renderPass (vector<Attachment>(1, Attachment(VK_FORMAT_R8G8B8A8_UNORM,
4399 VK_SAMPLE_COUNT_1_BIT,
4400 VK_ATTACHMENT_LOAD_OP_CLEAR,
4401 VK_ATTACHMENT_STORE_OP_STORE,
4402 VK_ATTACHMENT_LOAD_OP_DONT_CARE,
4403 VK_ATTACHMENT_STORE_OP_DONT_CARE,
4404 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
4405 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)),
4406 vector<Subpass>(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS,
4407 0u,
4408 vector<AttachmentReference>(),
4409 vector<AttachmentReference>(1, AttachmentReference(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)),
4410 vector<AttachmentReference>(),
4411 AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL),
4412 vector<AttachmentReference>())),
4413 vector<SubpassDependency>());
4414
4415 addFunctionCaseWithPrograms<TestConfig>(group.get(), "color", "Single color attachment case.", createTestShaders, renderPassTest, TestConfig(renderPass, TestConfig::RENDERTYPES_DRAW, TestConfig::COMMANDBUFFERTYPES_INLINE, TestConfig::IMAGEMEMORY_STRICT, targetSize, renderPos, renderSize, 90239));
4416 }
4417
4418 // depth
4419 {
4420 const RenderPass renderPass (vector<Attachment>(1, Attachment(VK_FORMAT_X8_D24_UNORM_PACK32,
4421 VK_SAMPLE_COUNT_1_BIT,
4422 VK_ATTACHMENT_LOAD_OP_CLEAR,
4423 VK_ATTACHMENT_STORE_OP_STORE,
4424 VK_ATTACHMENT_LOAD_OP_DONT_CARE,
4425 VK_ATTACHMENT_STORE_OP_DONT_CARE,
4426 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
4427 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)),
4428 vector<Subpass>(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS,
4429 0u,
4430 vector<AttachmentReference>(),
4431 vector<AttachmentReference>(),
4432 vector<AttachmentReference>(),
4433 AttachmentReference(0, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
4434 vector<AttachmentReference>())),
4435 vector<SubpassDependency>());
4436
4437 addFunctionCaseWithPrograms<TestConfig>(group.get(), "depth", "Single depth attachment case.", createTestShaders, renderPassTest, TestConfig(renderPass, TestConfig::RENDERTYPES_DRAW, TestConfig::COMMANDBUFFERTYPES_INLINE, TestConfig::IMAGEMEMORY_STRICT, targetSize, renderPos, renderSize, 90239));
4438 }
4439
4440 // stencil
4441 {
4442 const RenderPass renderPass (vector<Attachment>(1, Attachment(VK_FORMAT_S8_UINT,
4443 VK_SAMPLE_COUNT_1_BIT,
4444 VK_ATTACHMENT_LOAD_OP_DONT_CARE,
4445 VK_ATTACHMENT_STORE_OP_DONT_CARE,
4446 VK_ATTACHMENT_LOAD_OP_CLEAR,
4447 VK_ATTACHMENT_STORE_OP_STORE,
4448 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
4449 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)),
4450 vector<Subpass>(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS,
4451 0u,
4452 vector<AttachmentReference>(),
4453 vector<AttachmentReference>(),
4454 vector<AttachmentReference>(),
4455 AttachmentReference(0, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
4456 vector<AttachmentReference>())),
4457 vector<SubpassDependency>());
4458
4459 addFunctionCaseWithPrograms<TestConfig>(group.get(), "stencil", "Single stencil attachment case.", createTestShaders, renderPassTest, TestConfig(renderPass, TestConfig::RENDERTYPES_DRAW, TestConfig::COMMANDBUFFERTYPES_INLINE, TestConfig::IMAGEMEMORY_STRICT, targetSize, renderPos, renderSize, 90239));
4460 }
4461
4462 // depth_stencil
4463 {
4464 const RenderPass renderPass (vector<Attachment>(1, Attachment(VK_FORMAT_D24_UNORM_S8_UINT,
4465 VK_SAMPLE_COUNT_1_BIT,
4466 VK_ATTACHMENT_LOAD_OP_CLEAR,
4467 VK_ATTACHMENT_STORE_OP_STORE,
4468 VK_ATTACHMENT_LOAD_OP_CLEAR,
4469 VK_ATTACHMENT_STORE_OP_STORE,
4470 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
4471 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)),
4472 vector<Subpass>(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS,
4473 0u,
4474 vector<AttachmentReference>(),
4475 vector<AttachmentReference>(),
4476 vector<AttachmentReference>(),
4477 AttachmentReference(0, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
4478 vector<AttachmentReference>())),
4479 vector<SubpassDependency>());
4480
4481 addFunctionCaseWithPrograms<TestConfig>(group.get(), "depth_stencil", "Single depth stencil attachment case.", createTestShaders, renderPassTest, TestConfig(renderPass, TestConfig::RENDERTYPES_DRAW, TestConfig::COMMANDBUFFERTYPES_INLINE, TestConfig::IMAGEMEMORY_STRICT, targetSize, renderPos, renderSize, 90239));
4482 }
4483
4484 // color_depth
4485 {
4486 const Attachment attachments[] =
4487 {
4488 Attachment(VK_FORMAT_R8G8B8A8_UNORM,
4489 VK_SAMPLE_COUNT_1_BIT,
4490 VK_ATTACHMENT_LOAD_OP_CLEAR,
4491 VK_ATTACHMENT_STORE_OP_STORE,
4492 VK_ATTACHMENT_LOAD_OP_DONT_CARE,
4493 VK_ATTACHMENT_STORE_OP_DONT_CARE,
4494 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
4495 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL),
4496 Attachment(VK_FORMAT_X8_D24_UNORM_PACK32,
4497 VK_SAMPLE_COUNT_1_BIT,
4498 VK_ATTACHMENT_LOAD_OP_CLEAR,
4499 VK_ATTACHMENT_STORE_OP_STORE,
4500 VK_ATTACHMENT_LOAD_OP_DONT_CARE,
4501 VK_ATTACHMENT_STORE_OP_DONT_CARE,
4502 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
4503 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
4504 };
4505
4506 const RenderPass renderPass (vector<Attachment>(DE_ARRAY_BEGIN(attachments), DE_ARRAY_END(attachments)),
4507 vector<Subpass>(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS,
4508 0u,
4509 vector<AttachmentReference>(),
4510 vector<AttachmentReference>(1, AttachmentReference(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)),
4511 vector<AttachmentReference>(),
4512 AttachmentReference(1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
4513 vector<AttachmentReference>())),
4514 vector<SubpassDependency>());
4515
4516 addFunctionCaseWithPrograms<TestConfig>(group.get(), "color_depth", "Color and depth attachment case.", createTestShaders, renderPassTest, TestConfig(renderPass, TestConfig::RENDERTYPES_DRAW, TestConfig::COMMANDBUFFERTYPES_INLINE, TestConfig::IMAGEMEMORY_STRICT, targetSize, renderPos, renderSize, 90239));
4517 }
4518
4519 // color_stencil
4520 {
4521 const Attachment attachments[] =
4522 {
4523 Attachment(VK_FORMAT_R8G8B8A8_UNORM,
4524 VK_SAMPLE_COUNT_1_BIT,
4525 VK_ATTACHMENT_LOAD_OP_CLEAR,
4526 VK_ATTACHMENT_STORE_OP_STORE,
4527 VK_ATTACHMENT_LOAD_OP_DONT_CARE,
4528 VK_ATTACHMENT_STORE_OP_DONT_CARE,
4529 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
4530 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL),
4531 Attachment(VK_FORMAT_S8_UINT,
4532 VK_SAMPLE_COUNT_1_BIT,
4533 VK_ATTACHMENT_LOAD_OP_CLEAR,
4534 VK_ATTACHMENT_STORE_OP_STORE,
4535 VK_ATTACHMENT_LOAD_OP_DONT_CARE,
4536 VK_ATTACHMENT_STORE_OP_DONT_CARE,
4537 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
4538 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
4539 };
4540
4541 const RenderPass renderPass (vector<Attachment>(DE_ARRAY_BEGIN(attachments), DE_ARRAY_END(attachments)),
4542 vector<Subpass>(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS,
4543 0u,
4544 vector<AttachmentReference>(),
4545 vector<AttachmentReference>(1, AttachmentReference(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)),
4546 vector<AttachmentReference>(),
4547 AttachmentReference(1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
4548 vector<AttachmentReference>())),
4549 vector<SubpassDependency>());
4550
4551
4552 addFunctionCaseWithPrograms<TestConfig>(group.get(), "color_stencil", "Color and stencil attachment case.", createTestShaders, renderPassTest, TestConfig(renderPass, TestConfig::RENDERTYPES_DRAW, TestConfig::COMMANDBUFFERTYPES_INLINE, TestConfig::IMAGEMEMORY_STRICT, targetSize, renderPos, renderSize, 90239));
4553 }
4554
4555 // color_depth_stencil
4556 {
4557 const Attachment attachments[] =
4558 {
4559 Attachment(VK_FORMAT_R8G8B8A8_UNORM,
4560 VK_SAMPLE_COUNT_1_BIT,
4561 VK_ATTACHMENT_LOAD_OP_CLEAR,
4562 VK_ATTACHMENT_STORE_OP_STORE,
4563 VK_ATTACHMENT_LOAD_OP_DONT_CARE,
4564 VK_ATTACHMENT_STORE_OP_DONT_CARE,
4565 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
4566 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL),
4567 Attachment(VK_FORMAT_D24_UNORM_S8_UINT,
4568 VK_SAMPLE_COUNT_1_BIT,
4569 VK_ATTACHMENT_LOAD_OP_CLEAR,
4570 VK_ATTACHMENT_STORE_OP_STORE,
4571 VK_ATTACHMENT_LOAD_OP_CLEAR,
4572 VK_ATTACHMENT_STORE_OP_STORE,
4573 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
4574 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
4575 };
4576
4577 const RenderPass renderPass (vector<Attachment>(DE_ARRAY_BEGIN(attachments), DE_ARRAY_END(attachments)),
4578 vector<Subpass>(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS,
4579 0u,
4580 vector<AttachmentReference>(),
4581 vector<AttachmentReference>(1, AttachmentReference(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)),
4582 vector<AttachmentReference>(),
4583 AttachmentReference(1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
4584 vector<AttachmentReference>())),
4585 vector<SubpassDependency>());
4586
4587 addFunctionCaseWithPrograms<TestConfig>(group.get(), "color_depth_stencil", "Color, depth and stencil attachment case.", createTestShaders, renderPassTest, TestConfig(renderPass, TestConfig::RENDERTYPES_DRAW, TestConfig::COMMANDBUFFERTYPES_INLINE, TestConfig::IMAGEMEMORY_STRICT, targetSize, renderPos, renderSize, 90239));
4588 }
4589
4590 return group;
4591 }
4592
formatToName(VkFormat format)4593 std::string formatToName (VkFormat format)
4594 {
4595 const std::string formatStr = de::toString(format);
4596 const std::string prefix = "VK_FORMAT_";
4597
4598 DE_ASSERT(formatStr.substr(0, prefix.length()) == prefix);
4599
4600 return de::toLower(formatStr.substr(prefix.length()));
4601 }
4602
createFormatTestGroup(tcu::TestContext & testCtx)4603 de::MovePtr<tcu::TestCaseGroup> createFormatTestGroup(tcu::TestContext& testCtx)
4604 {
4605 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "formats", "Tests for different image formats."));
4606
4607 const UVec2 targetSize (64, 64);
4608 const UVec2 renderPos (0, 0);
4609 const UVec2 renderSize (64, 64);
4610
4611 const struct
4612 {
4613 const char* const str;
4614 const VkAttachmentLoadOp op;
4615 } loadOps[] =
4616 {
4617 { "clear", VK_ATTACHMENT_LOAD_OP_CLEAR },
4618 { "load", VK_ATTACHMENT_LOAD_OP_LOAD },
4619 { "dont_care", VK_ATTACHMENT_LOAD_OP_DONT_CARE }
4620 };
4621
4622 const struct
4623 {
4624 const char* const str;
4625 const TestConfig::RenderTypes types;
4626 } renderTypes[] =
4627 {
4628 { "clear", TestConfig::RENDERTYPES_CLEAR },
4629 { "draw", TestConfig::RENDERTYPES_DRAW },
4630 { "clear_draw", TestConfig::RENDERTYPES_CLEAR|TestConfig::RENDERTYPES_DRAW }
4631 };
4632
4633 // Color formats
4634 for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_coreColorFormats); formatNdx++)
4635 {
4636 const VkFormat format = s_coreColorFormats[formatNdx];
4637 de::MovePtr<tcu::TestCaseGroup> formatGroup (new tcu::TestCaseGroup(testCtx, formatToName(format).c_str(), de::toString(format).c_str()));
4638
4639 for (size_t loadOpNdx = 0; loadOpNdx < DE_LENGTH_OF_ARRAY(loadOps); loadOpNdx++)
4640 {
4641 const VkAttachmentLoadOp loadOp = loadOps[loadOpNdx].op;
4642 de::MovePtr<tcu::TestCaseGroup> loadOpGroup (new tcu::TestCaseGroup(testCtx, loadOps[loadOpNdx].str, loadOps[loadOpNdx].str));
4643
4644 for (size_t renderTypeNdx = 0; renderTypeNdx < DE_LENGTH_OF_ARRAY(renderTypes); renderTypeNdx++)
4645 {
4646 const RenderPass renderPass (vector<Attachment>(1, Attachment(format,
4647 VK_SAMPLE_COUNT_1_BIT,
4648 loadOp,
4649 VK_ATTACHMENT_STORE_OP_STORE,
4650 VK_ATTACHMENT_LOAD_OP_DONT_CARE,
4651 VK_ATTACHMENT_STORE_OP_DONT_CARE,
4652 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
4653 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)),
4654 vector<Subpass>(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS,
4655 0u,
4656 vector<AttachmentReference>(),
4657 vector<AttachmentReference>(1, AttachmentReference(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)),
4658 vector<AttachmentReference>(),
4659 AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL),
4660 vector<AttachmentReference>())),
4661 vector<SubpassDependency>());
4662
4663 addFunctionCaseWithPrograms<TestConfig>(loadOpGroup.get(), renderTypes[renderTypeNdx].str, renderTypes[renderTypeNdx].str, createTestShaders, renderPassTest, TestConfig(renderPass, renderTypes[renderTypeNdx].types, TestConfig::COMMANDBUFFERTYPES_INLINE, TestConfig::IMAGEMEMORY_STRICT, targetSize, renderPos, renderSize, 90239));
4664 }
4665
4666 formatGroup->addChild(loadOpGroup.release());
4667 }
4668
4669 group->addChild(formatGroup.release());
4670 }
4671
4672 // Depth stencil formats
4673 for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_coreDepthStencilFormats); formatNdx++)
4674 {
4675 const VkFormat vkFormat = s_coreDepthStencilFormats[formatNdx];
4676 de::MovePtr<tcu::TestCaseGroup> formatGroup (new tcu::TestCaseGroup(testCtx, formatToName(vkFormat).c_str(), de::toString(vkFormat).c_str()));
4677
4678 for (size_t loadOpNdx = 0; loadOpNdx < DE_LENGTH_OF_ARRAY(loadOps); loadOpNdx++)
4679 {
4680 const VkAttachmentLoadOp loadOp = loadOps[loadOpNdx].op;
4681 de::MovePtr<tcu::TestCaseGroup> loadOpGroup (new tcu::TestCaseGroup(testCtx, loadOps[loadOpNdx].str, loadOps[loadOpNdx].str));
4682
4683 for (size_t renderTypeNdx = 0; renderTypeNdx < DE_LENGTH_OF_ARRAY(renderTypes); renderTypeNdx++)
4684 {
4685 const tcu::TextureFormat format = mapVkFormat(vkFormat);
4686 const bool isStencilAttachment = hasStencilComponent(format.order);
4687 const bool isDepthAttachment = hasDepthComponent(format.order);
4688 const RenderPass renderPass (vector<Attachment>(1, Attachment(vkFormat,
4689 VK_SAMPLE_COUNT_1_BIT,
4690 isDepthAttachment ? loadOp : VK_ATTACHMENT_LOAD_OP_DONT_CARE,
4691 isDepthAttachment ? VK_ATTACHMENT_STORE_OP_STORE :VK_ATTACHMENT_STORE_OP_DONT_CARE,
4692 isStencilAttachment ? loadOp : VK_ATTACHMENT_LOAD_OP_DONT_CARE,
4693 isStencilAttachment ? VK_ATTACHMENT_STORE_OP_STORE :VK_ATTACHMENT_STORE_OP_DONT_CARE,
4694 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
4695 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)),
4696 vector<Subpass>(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS,
4697 0u,
4698 vector<AttachmentReference>(),
4699 vector<AttachmentReference>(),
4700 vector<AttachmentReference>(),
4701 AttachmentReference(0, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
4702 vector<AttachmentReference>())),
4703 vector<SubpassDependency>());
4704
4705 addFunctionCaseWithPrograms<TestConfig>(loadOpGroup.get(), renderTypes[renderTypeNdx].str, renderTypes[renderTypeNdx].str, createTestShaders, renderPassTest, TestConfig(renderPass, renderTypes[renderTypeNdx].types, TestConfig::COMMANDBUFFERTYPES_INLINE, TestConfig::IMAGEMEMORY_STRICT, targetSize, renderPos, renderSize, 90239));
4706 }
4707
4708 formatGroup->addChild(loadOpGroup.release());
4709 }
4710
4711 group->addChild(formatGroup.release());
4712 }
4713
4714 return group;
4715 }
4716
4717 } // anonymous
4718
createRenderPassTests(tcu::TestContext & testCtx)4719 tcu::TestCaseGroup* createRenderPassTests (tcu::TestContext& testCtx)
4720 {
4721 de::MovePtr<tcu::TestCaseGroup> renderpassTests (new tcu::TestCaseGroup(testCtx, "renderpass", "RenderPass Tests"));
4722
4723 renderpassTests->addChild(createSimpleTestGroup(testCtx).release());
4724 renderpassTests->addChild(createFormatTestGroup(testCtx).release());
4725 renderpassTests->addChild(createAttachmentTestCaseGroup(testCtx).release());
4726 renderpassTests->addChild(createAttachmentAllocationTestGroup(testCtx).release());
4727
4728 return renderpassTests.release();
4729 }
4730
4731 } // vkt
4732