1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2022 Google LLC
6  * Copyright (c) 2022 The Khronos Group Inc.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22  * \brief Vulkan Dynamic Rendering Random Tests
23  *//*--------------------------------------------------------------------*/
24 
25 #include "deRandom.hpp"
26 
27 #include "tcuImageCompare.hpp"
28 #include "tcuTestLog.hpp"
29 
30 #include "vkBarrierUtil.hpp"
31 #include "vkCmdUtil.hpp"
32 #include "vktDrawBufferObjectUtil.hpp"
33 #include "vktDynamicRenderingRandomTests.hpp"
34 #include "vkImageUtil.hpp"
35 #include "vkObjUtil.hpp"
36 #include "vktTestCase.hpp"
37 #include "vkTypeUtil.hpp"
38 
39 #include <iostream>
40 
41 namespace vkt
42 {
43 namespace renderpass
44 {
45 namespace
46 {
47 
48 using namespace vk;
49 
50 using tcu::UVec2;
51 using tcu::Vec4;
52 
53 const uint32_t maxQueries = 50u * 3u; // multiview with 3 bits can be used
54 const uint32_t numLayers  = 4u;
55 
56 struct TestParameters
57 {
58     VkFormat imageFormat;
59     UVec2 renderSize;
60     bool enableGeometry;
61     bool enableTessellation;
62     bool enableMultiview;
63     uint32_t randomSeed;
64 };
65 
66 struct PushConstantData
67 {
68     Vec4 scale;
69     Vec4 offset;
70     Vec4 color;
71     int32_t layer;
72 };
73 
74 class DynamicRenderingTestInstance : public TestInstance
75 {
76 public:
77     DynamicRenderingTestInstance(Context &context, const TestParameters &parameters);
78 
79 protected:
80     virtual tcu::TestStatus iterate(void);
81 
82     TestParameters m_parameters;
83     Move<VkImage> m_imageColor;
84     Move<VkImageView> m_colorAttachmentView;
85     de::MovePtr<Allocation> m_imageColorAlloc;
86     de::SharedPtr<Draw::Buffer> m_imageBuffer;
87     uint32_t m_layerSizeBytes;
88     Move<VkShaderModule> m_vertexModule;
89     Move<VkShaderModule> m_vertexPassthroughModule;
90     Move<VkShaderModule> m_vertexLayerModule;
91     Move<VkShaderModule> m_geometryModule;
92     Move<VkShaderModule> m_geometryLayerModule;
93     Move<VkShaderModule> m_tscModule;
94     Move<VkShaderModule> m_tseModule;
95     Move<VkShaderModule> m_fragmentModule;
96     de::SharedPtr<Draw::Buffer> m_vertexBuffer;
97     Move<VkPipelineLayout> m_pipelineLayout;
98     de::SharedPtr<Draw::Buffer> m_queryResults;
99     Move<VkQueryPool> m_queryPool;
100     Move<VkCommandPool> m_cmdPool;
101     de::Random m_random;
102     Move<VkPipeline> m_pipelineBasic;
103     Move<VkPipeline> m_pipelineGeom;
104     Move<VkPipeline> m_pipelineTess;
105     Move<VkPipeline> m_pipelineLayer;
106     Move<VkPipeline> m_pipelineMultiview;
107 };
108 
DynamicRenderingTestInstance(Context & context,const TestParameters & parameters)109 DynamicRenderingTestInstance::DynamicRenderingTestInstance(Context &context, const TestParameters &parameters)
110     : TestInstance(context)
111     , m_parameters(parameters)
112     , m_random(parameters.randomSeed)
113 {
114     const DeviceInterface &vk = m_context.getDeviceInterface();
115     const VkDevice device     = m_context.getDevice();
116     Allocator &allocator      = m_context.getDefaultAllocator();
117 
118     m_cmdPool = createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
119                                   m_context.getUniversalQueueFamilyIndex());
120 
121     // Vertices.
122     {
123         std::vector<Vec4> vertices = {Vec4(-0.5f, 0.5f, 0.0f, 1.0f), Vec4(-0.5f, -0.5f, 0.0f, 1.0f),
124                                       Vec4(0.5f, 0.5f, 0.0f, 1.0f), Vec4(0.5f, -0.5f, 0.0f, 1.0f)};
125 
126         const VkDeviceSize bufferSize       = vertices.size() * sizeof(vertices[0]);
127         const VkBufferCreateInfo bufferInfo = makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
128 
129         m_vertexBuffer =
130             Draw::Buffer::createAndAlloc(vk, device, bufferInfo, allocator, MemoryRequirement::HostVisible);
131 
132         deMemcpy(m_vertexBuffer->getBoundMemory().getHostPtr(), vertices.data(), static_cast<std::size_t>(bufferSize));
133         flushAlloc(vk, device, m_vertexBuffer->getBoundMemory());
134     }
135 
136     // Create color image.
137     {
138         const VkImageUsageFlags imageUsage =
139             VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
140         m_layerSizeBytes = m_parameters.renderSize.x() * m_parameters.renderSize.y() *
141                            tcu::getPixelSize(mapVkFormat(m_parameters.imageFormat));
142         const VkDeviceSize imageBufferSize = m_layerSizeBytes * numLayers;
143 
144         const VkImageCreateInfo imageInfo = {
145             VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType            sType
146             DE_NULL,                             // const void*                pNext
147             (VkImageCreateFlags)0,               // VkImageCreateFlags        flags
148             VK_IMAGE_TYPE_2D,                    // VkImageType                imageType
149             m_parameters.imageFormat,            // VkFormat                    format
150             makeExtent3D(m_parameters.renderSize.x(), m_parameters.renderSize.y(),
151                          1),           // VkExtent3D                extent
152             1u,                        // uint32_t                    mipLevels
153             numLayers,                 // uint32_t                    arrayLayers
154             VK_SAMPLE_COUNT_1_BIT,     // VkSampleCountFlagBits    samples
155             VK_IMAGE_TILING_OPTIMAL,   // VkImageTiling            tiling
156             imageUsage,                // VkImageUsageFlags        usage
157             VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode            sharingMode
158             0u,                        // uint32_t                    queueFamilyIndexCount
159             DE_NULL,                   // const uint32_t*            pQueueFamilyIndices
160             VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout            initialLayout
161         };
162 
163         const VkBufferCreateInfo bufferInfo = makeBufferCreateInfo(imageBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
164 
165         m_imageColor      = makeImage(vk, device, imageInfo);
166         m_imageColorAlloc = bindImage(vk, device, allocator, *m_imageColor, MemoryRequirement::Any);
167         m_imageBuffer = Draw::Buffer::createAndAlloc(vk, device, bufferInfo, allocator, MemoryRequirement::HostVisible);
168 
169         const VkImageSubresourceRange imageSubresource =
170             makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers);
171 
172         m_colorAttachmentView = makeImageView(vk, device, *m_imageColor, VK_IMAGE_VIEW_TYPE_2D_ARRAY,
173                                               m_parameters.imageFormat, imageSubresource);
174 
175         const Allocation alloc = m_imageBuffer->getBoundMemory();
176         deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(imageBufferSize));
177         flushAlloc(vk, device, alloc);
178     }
179 
180     // Pipeline layout.
181     {
182         const auto pcStages = VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_GEOMETRY_BIT;
183         const auto pcSize   = static_cast<uint32_t>(sizeof(PushConstantData));
184         const auto pcRange  = makePushConstantRange(pcStages, 0u, pcSize);
185 
186         m_pipelineLayout = makePipelineLayout(vk, device, 0u, DE_NULL, 1u, &pcRange);
187     }
188 
189     // Shader modules.
190     {
191         m_vertexModule   = createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u);
192         m_fragmentModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u);
193         if (m_parameters.enableGeometry)
194         {
195             m_vertexPassthroughModule =
196                 createShaderModule(vk, device, m_context.getBinaryCollection().get("vertPassthrough"), 0u);
197             m_vertexLayerModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("vertLayer"), 0u);
198             m_geometryModule    = createShaderModule(vk, device, m_context.getBinaryCollection().get("geom"), 0u);
199             m_geometryLayerModule =
200                 createShaderModule(vk, device, m_context.getBinaryCollection().get("geomLayer"), 0u);
201         }
202         if (m_parameters.enableTessellation)
203         {
204             m_tscModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("tsc"), 0u);
205             m_tseModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("tse"), 0u);
206         }
207     }
208 
209     // Pipelines.
210     {
211         const std::vector<vk::VkViewport> viewports(1u, vk::makeViewport(m_parameters.renderSize));
212         const std::vector<vk::VkRect2D> scissors(1u, vk::makeRect2D(m_parameters.renderSize));
213 
214         VkPipelineRenderingCreateInfoKHR renderingCreateInfo = {
215             VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR, // VkStructureType    sType
216             DE_NULL,                                              // const void*        pNext
217             0u,                                                   // uint32_t            viewMask
218             1u,                                                   // uint32_t            colorAttachmentCount
219             &m_parameters.imageFormat,                            // const VkFormat*    pColorAttachmentFormats
220             VK_FORMAT_UNDEFINED,                                  // VkFormat            depthAttachmentFormat
221             VK_FORMAT_UNDEFINED,                                  // VkFormat            stencilAttachmentFormat
222         };
223 
224         m_pipelineBasic = makeGraphicsPipeline(
225             vk,                // const DeviceInterface&                            vk
226             device,            // const VkDevice                                    device
227             *m_pipelineLayout, // const VkPipelineLayout                            pipelineLayout
228             *m_vertexModule,   // const VkShaderModule                                vertexShaderModule
229             DE_NULL,           // const VkShaderModule                                tessellationControlShaderModule
230             DE_NULL,           // const VkShaderModule                                tessellationEvalShaderModule
231             DE_NULL,           // const VkShaderModule                                geometryShaderModule
232             *m_fragmentModule, // const VkShaderModule                                fragmentShaderModule
233             DE_NULL,           // const VkRenderPass                                renderPass
234             viewports,         // const std::vector<VkViewport>&                    viewports
235             scissors,          // const std::vector<VkRect2D>&                        scissors
236             VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, // const VkPrimitiveTopology                        topology
237             0u,                                   // const uint32_t                                    subpass
238             0u,                    // const uint32_t                                    patchControlPoints
239             DE_NULL,               // const VkPipelineVertexInputStateCreateInfo*        vertexInputStateCreateInfo
240             DE_NULL,               // const VkPipelineRasterizationStateCreateInfo*    rasterizationStateCreateInfo
241             DE_NULL,               // const VkPipelineMultisampleStateCreateInfo*        multisampleStateCreateInfo
242             DE_NULL,               // const VkPipelineDepthStencilStateCreateInfo*        depthStencilStateCreateInfo
243             DE_NULL,               // const VkPipelineColorBlendStateCreateInfo*        colorBlendStateCreateInfo
244             DE_NULL,               // const VkPipelineDynamicStateCreateInfo*            dynamicStateCreateInfo
245             &renderingCreateInfo); // const void*                                        pNext
246 
247         if (m_parameters.enableGeometry)
248         {
249             m_pipelineGeom = makeGraphicsPipeline(
250                 vk,                         // const DeviceInterface&                            vk
251                 device,                     // const VkDevice                                    device
252                 *m_pipelineLayout,          // const VkPipelineLayout                            pipelineLayout
253                 *m_vertexPassthroughModule, // const VkShaderModule                                vertexShaderModule
254                 DE_NULL, // const VkShaderModule                                tessellationControlShaderModule
255                 DE_NULL, // const VkShaderModule                                tessellationEvalShaderModule
256                 *m_geometryModule, // const VkShaderModule                                geometryShaderModule
257                 *m_fragmentModule, // const VkShaderModule                                fragmentShaderModule
258                 DE_NULL,           // const VkRenderPass                                renderPass
259                 viewports,         // const std::vector<VkViewport>&                    viewports
260                 scissors,          // const std::vector<VkRect2D>&                        scissors
261                 VK_PRIMITIVE_TOPOLOGY_POINT_LIST, // const VkPrimitiveTopology                        topology
262                 0u,                               // const uint32_t                                    subpass
263                 0u,      // const uint32_t                                    patchControlPoints
264                 DE_NULL, // const VkPipelineVertexInputStateCreateInfo*        vertexInputStateCreateInfo
265                 DE_NULL, // const VkPipelineRasterizationStateCreateInfo*    rasterizationStateCreateInfo
266                 DE_NULL, // const VkPipelineMultisampleStateCreateInfo*        multisampleStateCreateInfo
267                 DE_NULL, // const VkPipelineDepthStencilStateCreateInfo*        depthStencilStateCreateInfo
268                 DE_NULL, // const VkPipelineColorBlendStateCreateInfo*        colorBlendStateCreateInfo
269                 DE_NULL, // const VkPipelineDynamicStateCreateInfo*            dynamicStateCreateInfo
270                 &renderingCreateInfo); // const void*                                        pNext
271 
272             m_pipelineLayer = makeGraphicsPipeline(
273                 vk,                   // const DeviceInterface&                            vk
274                 device,               // const VkDevice                                    device
275                 *m_pipelineLayout,    // const VkPipelineLayout                            pipelineLayout
276                 *m_vertexLayerModule, // const VkShaderModule                                vertexShaderModule
277                 DE_NULL, // const VkShaderModule                                tessellationControlShaderModule
278                 DE_NULL, // const VkShaderModule                                tessellationEvalShaderModule
279                 *m_geometryLayerModule, // const VkShaderModule                                geometryShaderModule
280                 *m_fragmentModule,      // const VkShaderModule                                fragmentShaderModule
281                 DE_NULL,                // const VkRenderPass                                renderPass
282                 viewports,              // const std::vector<VkViewport>&                    viewports
283                 scissors,               // const std::vector<VkRect2D>&                        scissors
284                 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, // const VkPrimitiveTopology                        topology
285                 0u,                                   // const uint32_t                                    subpass
286                 0u,      // const uint32_t                                    patchControlPoints
287                 DE_NULL, // const VkPipelineVertexInputStateCreateInfo*        vertexInputStateCreateInfo
288                 DE_NULL, // const VkPipelineRasterizationStateCreateInfo*    rasterizationStateCreateInfo
289                 DE_NULL, // const VkPipelineMultisampleStateCreateInfo*        multisampleStateCreateInfo
290                 DE_NULL, // const VkPipelineDepthStencilStateCreateInfo*        depthStencilStateCreateInfo
291                 DE_NULL, // const VkPipelineColorBlendStateCreateInfo*        colorBlendStateCreateInfo
292                 DE_NULL, // const VkPipelineDynamicStateCreateInfo*            dynamicStateCreateInfo
293                 &renderingCreateInfo); // const void*                                        pNext
294         }
295 
296         if (m_parameters.enableTessellation)
297         {
298             m_pipelineTess = makeGraphicsPipeline(
299                 vk,                // const DeviceInterface&                            vk
300                 device,            // const VkDevice                                    device
301                 *m_pipelineLayout, // const VkPipelineLayout                            pipelineLayout
302                 *m_vertexModule,   // const VkShaderModule                                vertexShaderModule
303                 *m_tscModule, // const VkShaderModule                                tessellationControlShaderModule
304                 *m_tseModule, // const VkShaderModule                                tessellationEvalShaderModule
305                 DE_NULL,      // const VkShaderModule                                geometryShaderModule
306                 *m_fragmentModule, // const VkShaderModule                                fragmentShaderModule
307                 DE_NULL,           // const VkRenderPass                                renderPass
308                 viewports,         // const std::vector<VkViewport>&                    viewports
309                 scissors,          // const std::vector<VkRect2D>&                        scissors
310                 vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST, // const VkPrimitiveTopology                        topology
311                 0u,                                   // const uint32_t                                    subpass
312                 4u,      // const uint32_t                                    patchControlPoints
313                 DE_NULL, // const VkPipelineVertexInputStateCreateInfo*        vertexInputStateCreateInfo
314                 DE_NULL, // const VkPipelineRasterizationStateCreateInfo*    rasterizationStateCreateInfo
315                 DE_NULL, // const VkPipelineMultisampleStateCreateInfo*        multisampleStateCreateInfo
316                 DE_NULL, // const VkPipelineDepthStencilStateCreateInfo*        depthStencilStateCreateInfo
317                 DE_NULL, // const VkPipelineColorBlendStateCreateInfo*        colorBlendStateCreateInfo
318                 DE_NULL, // const VkPipelineDynamicStateCreateInfo*            dynamicStateCreateInfo
319                 &renderingCreateInfo); // const void*                                        pNext
320         }
321 
322         renderingCreateInfo.viewMask = 0xb; // 1011b
323         m_pipelineMultiview          = makeGraphicsPipeline(
324             vk,                // const DeviceInterface&                            vk
325             device,            // const VkDevice                                    device
326             *m_pipelineLayout, // const VkPipelineLayout                            pipelineLayout
327             *m_vertexModule,   // const VkShaderModule                                vertexShaderModule
328             DE_NULL, // const VkShaderModule                                tessellationControlShaderModule
329             DE_NULL, // const VkShaderModule                                tessellationEvalShaderModule
330             DE_NULL, // const VkShaderModule                                geometryShaderModule
331             *m_fragmentModule, // const VkShaderModule                                fragmentShaderModule
332             DE_NULL,           // const VkRenderPass                                renderPass
333             viewports,         // const std::vector<VkViewport>&                    viewports
334             scissors,          // const std::vector<VkRect2D>&                        scissors
335             VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, // const VkPrimitiveTopology                        topology
336             0u,                                   // const uint32_t                                    subpass
337             0u,      // const uint32_t                                    patchControlPoints
338             DE_NULL, // const VkPipelineVertexInputStateCreateInfo*        vertexInputStateCreateInfo
339             DE_NULL, // const VkPipelineRasterizationStateCreateInfo*    rasterizationStateCreateInfo
340             DE_NULL, // const VkPipelineMultisampleStateCreateInfo*        multisampleStateCreateInfo
341             DE_NULL, // const VkPipelineDepthStencilStateCreateInfo*        depthStencilStateCreateInfo
342             DE_NULL, // const VkPipelineColorBlendStateCreateInfo*        colorBlendStateCreateInfo
343             DE_NULL, // const VkPipelineDynamicStateCreateInfo*            dynamicStateCreateInfo
344             &renderingCreateInfo); // const void*                                        pNext
345     }
346 
347     // Query result buffer.
348     {
349         const VkDeviceSize bufferSize = 1024u;
350         const VkBufferCreateInfo bufferInfo =
351             makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
352 
353         m_queryResults =
354             Draw::Buffer::createAndAlloc(vk, device, bufferInfo, allocator, MemoryRequirement::HostVisible);
355     }
356 
357     // Query pool.
358     {
359         VkQueryPoolCreateInfo queryPoolInfo = {
360             VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, // VkStructureType                    sType
361             DE_NULL,                                  // const void*                        pNext
362             0,                                        // VkQueryPoolCreateFlags            flags
363             vk::VK_QUERY_TYPE_OCCLUSION,              // VkQueryType                        queryType
364             maxQueries,                               // uint32_t                            queryCount
365             0                                         // VkQueryPipelineStatisticFlags    pipelineStatistics
366         };
367 
368         m_queryPool = createQueryPool(vk, device, &queryPoolInfo);
369     }
370 }
371 
iterate(void)372 tcu::TestStatus DynamicRenderingTestInstance::iterate(void)
373 {
374     const DeviceInterface &vk  = m_context.getDeviceInterface();
375     const VkDevice device      = m_context.getDevice();
376     const VkQueue queue        = m_context.getUniversalQueue();
377     const uint32_t queueFamily = m_context.getUniversalQueueFamilyIndex();
378     tcu::TestLog &log          = m_context.getTestContext().getLog();
379 
380     std::vector<Move<VkCommandBuffer>> cmdBuffers;
381     std::vector<Move<VkCommandBuffer>> secondaryCmdBuffers;
382     std::vector<tcu::TextureLevel> ref;
383 
384     for (uint32_t i = 0; i < numLayers; i++)
385     {
386         ref.emplace_back(mapVkFormat(m_parameters.imageFormat), m_parameters.renderSize.x(),
387                          m_parameters.renderSize.y(), 1u);
388 
389         tcu::PixelBufferAccess access = ref[i].getAccess();
390 
391         for (uint32_t y = 0; y < m_parameters.renderSize.x(); y++)
392             for (uint32_t x = 0; x < m_parameters.renderSize.x(); x++)
393                 access.setPixel(Vec4(0.0f), x, y);
394     }
395 
396     cmdBuffers.push_back(allocateCommandBuffer(vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
397     beginCommandBuffer(vk, *cmdBuffers.back());
398     vk.cmdResetQueryPool(*cmdBuffers.back(), *m_queryPool, 0, maxQueries);
399 
400     clearColorImage(vk, device, queue, queueFamily, *m_imageColor, Vec4(0.0), VK_IMAGE_LAYOUT_UNDEFINED,
401                     VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, numLayers);
402 
403     VkRenderingFlagsKHR prevFlags = 0;
404     Vec4 clearColor               = Vec4(0.0f);
405     VkRect2D renderArea           = makeRect2D(0, 0, 0, 0);
406     VkAttachmentLoadOp loadOp     = VK_ATTACHMENT_LOAD_OP_CLEAR;
407     uint32_t renderWidth          = 0u;
408     uint32_t renderHeight         = 0u;
409     uint32_t renderX              = 0u;
410     uint32_t renderY              = 0u;
411     uint32_t quadShrink           = 0u;
412     uint32_t queryIndex           = 0u;
413     std::vector<uint32_t> queryMultiviewCount;
414 
415     enum PipelineType
416     {
417         PIPELINE_TYPE_VERTEX_FRAGMENT            = 0,
418         PIPELINE_TYPE_VERTEX_GEOM_FRAGMENT       = 1,
419         PIPELINE_TYPE_VERTEX_TESS_FRAGMENT       = 2,
420         PIPELINE_TYPE_VERTEX_GEOM_FRAGMENT_LAYER = 3,
421         PIPELINE_TYPE_VERTEX_FRAGMENT_MULTIVIEW  = 4,
422         PIPELINE_TYPE_ATTACHMENT_CLEAR           = 5,
423         PIPELINE_TYPE_MAX                        = 6
424     } pipelineType = PIPELINE_TYPE_VERTEX_FRAGMENT;
425 
426     std::vector<VkPipeline> pipelines = {*m_pipelineBasic, *m_pipelineGeom,      *m_pipelineTess,
427                                          *m_pipelineLayer, *m_pipelineMultiview, *m_pipelineBasic};
428 
429     uint32_t validPipelines = (1 << PIPELINE_TYPE_VERTEX_FRAGMENT) | (1 << PIPELINE_TYPE_ATTACHMENT_CLEAR);
430 
431     if (m_parameters.enableMultiview)
432         validPipelines |= (1 << PIPELINE_TYPE_VERTEX_FRAGMENT_MULTIVIEW);
433 
434     if (m_parameters.enableGeometry)
435         validPipelines |= (1 << PIPELINE_TYPE_VERTEX_GEOM_FRAGMENT) | (1 << PIPELINE_TYPE_VERTEX_GEOM_FRAGMENT_LAYER);
436 
437     if (m_parameters.enableTessellation)
438         validPipelines |= (1 << PIPELINE_TYPE_VERTEX_TESS_FRAGMENT);
439 
440     const int numIterations = 50;
441 
442     for (int i = 0; i < numIterations; i++)
443     {
444         VkRenderingFlagsKHR flags             = 0;
445         bool useSecondaryCmdBuffer            = m_random.getUint32() % 5 == 0;
446         bool bindPipelineBeforeBeginRendering = m_random.getBool();
447 
448         if (useSecondaryCmdBuffer)
449         {
450             flags |= VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT_KHR;
451             // Pipeline bind needs to go to the same command buffer that has the draw call.
452             bindPipelineBeforeBeginRendering = false;
453         }
454 
455         if (prevFlags & VK_RENDERING_SUSPENDING_BIT_KHR)
456         {
457             // Resuming: Don't touch the beginRendering parameters as they need to
458             // match with the previous command buffer.
459 
460             flags |= VK_RENDERING_RESUMING_BIT_KHR;
461 
462             // Use a new command buffer.
463             VK_CHECK(vk.endCommandBuffer(*cmdBuffers.back()));
464 
465             cmdBuffers.push_back(allocateCommandBuffer(vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
466             beginCommandBuffer(vk, *cmdBuffers.back());
467 
468             // Make the drawn quad smaller so the previous quad is still visible.
469             quadShrink++;
470 
471             // Pipeline bind is not allowed between suspend and resume.
472             bindPipelineBeforeBeginRendering = false;
473         }
474         else
475         {
476             // Not resuming: we can randomize new beginRendering parameters.
477             clearColor = Vec4(m_random.getFloat(), m_random.getFloat(), m_random.getFloat(), 1.0f);
478 
479             const uint32_t minAreaSize = 32u;
480             // Use a render area with an even size to make the margin around the quad symmetrical.
481             renderWidth =
482                 (m_random.getUint32() % (m_parameters.renderSize.x() / 2 - minAreaSize) + minAreaSize) & (~1u);
483             renderHeight =
484                 (m_random.getUint32() % (m_parameters.renderSize.y() / 2 - minAreaSize) + minAreaSize) & (~1u);
485             renderX    = m_random.getUint32() % (m_parameters.renderSize.x() - renderWidth);
486             renderY    = m_random.getUint32() % (m_parameters.renderSize.y() - renderHeight);
487             renderArea = {makeOffset2D(renderX, renderY), makeExtent2D(renderWidth, renderHeight)};
488             loadOp     = m_random.getBool() ? vk::VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD;
489             quadShrink = 0u;
490         }
491 
492         // Randomize pipeline type on every round. Multiview pipeline is an exception: the view mask cannot change
493         // between suspend and resume.
494         if (!(prevFlags & VK_RENDERING_SUSPENDING_BIT_KHR) || pipelineType != PIPELINE_TYPE_VERTEX_FRAGMENT_MULTIVIEW)
495         {
496             uint32_t pipelineMask = validPipelines;
497 
498             if (prevFlags & VK_RENDERING_SUSPENDING_BIT_KHR)
499             {
500                 // If resuming from non-multiview pipeline the new pipeline must also be non-multiview to keep the view mask.
501                 if (pipelineType != PIPELINE_TYPE_VERTEX_FRAGMENT_MULTIVIEW)
502                     pipelineMask &= ~(1 << PIPELINE_TYPE_VERTEX_FRAGMENT_MULTIVIEW);
503 
504                 // The number of layers need to match too.
505                 const uint32_t layeredPipelines =
506                     (1 << PIPELINE_TYPE_VERTEX_GEOM_FRAGMENT_LAYER) | (1 << PIPELINE_TYPE_ATTACHMENT_CLEAR);
507                 if ((1 << pipelineType) & layeredPipelines)
508                 {
509                     // Filter out all non-layered pipelines.
510                     pipelineMask &= layeredPipelines;
511                 }
512                 else
513                 {
514                     // Filter out all layered pipelines.
515                     pipelineMask &= ~layeredPipelines;
516                 }
517             }
518 
519             do
520             {
521                 pipelineType = static_cast<PipelineType>(m_random.getUint32() % PIPELINE_TYPE_MAX);
522             } while (((1 << pipelineType) & pipelineMask) == 0);
523         }
524 
525         const bool occlusionQuery = m_random.getBool() && pipelineType != PIPELINE_TYPE_ATTACHMENT_CLEAR;
526         const uint32_t viewMask   = pipelineType == PIPELINE_TYPE_VERTEX_FRAGMENT_MULTIVIEW ? 0xb /* 1011b */ : 0;
527         const bool useLayers =
528             pipelineType == PIPELINE_TYPE_VERTEX_GEOM_FRAGMENT_LAYER || pipelineType == PIPELINE_TYPE_ATTACHMENT_CLEAR;
529         const bool suspend = m_random.getUint32() % 5 == 0 && i != numIterations - 1;
530 
531         if (suspend)
532         {
533             flags |= VK_RENDERING_SUSPENDING_BIT_KHR;
534         }
535 
536         const VkClearValue clearValue = makeClearValueColor(clearColor);
537 
538         if (bindPipelineBeforeBeginRendering)
539             vk.cmdBindPipeline(*cmdBuffers.back(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines[pipelineType]);
540 
541         // Begin rendering
542         {
543             const VkRenderingAttachmentInfoKHR renderingAttachmentInfo = {
544                 VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR, // VkStructureType            sType
545                 DE_NULL,                                         // const void*                pNext
546                 *m_colorAttachmentView,                          // VkImageView                imageView
547                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,        // VkImageLayout            imageLayout
548                 VK_RESOLVE_MODE_NONE,                            // VkResolveModeFlagBits    resolveMode
549                 DE_NULL,                                         // VkImageView                resolveImageView
550                 VK_IMAGE_LAYOUT_UNDEFINED,                       // VkImageLayout            resolveImageLayout
551                 loadOp,                                          // VkAttachmentLoadOp        loadOp
552                 VK_ATTACHMENT_STORE_OP_STORE,                    // VkAttachmentStoreOp        storeOp
553                 clearValue                                       // VkClearValue                clearValue
554             };
555 
556             const VkRenderingInfoKHR renderingInfo = {
557                 VK_STRUCTURE_TYPE_RENDERING_INFO_KHR, // VkStructureType                        sType
558                 DE_NULL,                              // const void*                            pNext
559                 flags,                                // VkRenderingFlagsKHR                    flags
560                 renderArea,                           // VkRect2D                                renderArea
561                 useLayers ? numLayers : 1u,           // uint32_t                                layerCount
562                 viewMask,                             // uint32_t                                viewMask
563                 1u,                                   // uint32_t                                colorAttachmentCount
564                 &renderingAttachmentInfo,             // const VkRenderingAttachmentInfoKHR*    pColorAttachments
565                 DE_NULL,                              // const VkRenderingAttachmentInfoKHR*    pDepthAttachment
566                 DE_NULL                               // const VkRenderingAttachmentInfoKHR*    pStencilAttachment
567             };
568 
569             vk.cmdBeginRendering(*cmdBuffers.back(), &renderingInfo);
570         }
571 
572         if (useSecondaryCmdBuffer)
573         {
574             secondaryCmdBuffers.push_back(
575                 allocateCommandBuffer(vk, device, *m_cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_SECONDARY));
576 
577             const VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo = {
578                 VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR,  // VkStructureType            sType
579                 DE_NULL,                                                          // const void*                pNext
580                 flags & ~VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT_KHR, // VkRenderingFlagsKHR        flags
581                 viewMask,                  // uint32_t                    viewMask
582                 1u,                        // uint32_t                    colorAttachmentCount
583                 &m_parameters.imageFormat, // const VkFormat*            pColorAttachmentFormats
584                 VK_FORMAT_UNDEFINED,       // VkFormat                    depthAttachmentFormat
585                 VK_FORMAT_UNDEFINED,       // VkFormat                    stencilAttachmentFormat
586                 VK_SAMPLE_COUNT_1_BIT,     // VkSampleCountFlagBits    rasterizationSamples
587             };
588 
589             const VkCommandBufferInheritanceInfo bufferInheritanceInfo = {
590                 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, // VkStructureType                    sType
591                 &inheritanceRenderingInfo,                             // const void*                        pNext
592                 DE_NULL,                                               // VkRenderPass                        renderPass
593                 0u,                                                    // uint32_t                            subpass
594                 DE_NULL,                                               // VkFramebuffer                    framebuffer
595                 VK_FALSE,                         // VkBool32                            occlusionQueryEnable
596                 (VkQueryControlFlags)0u,          // VkQueryControlFlags                queryFlags
597                 (VkQueryPipelineStatisticFlags)0u // VkQueryPipelineStatisticFlags    pipelineStatistics
598             };
599 
600             const VkCommandBufferBeginInfo commandBufBeginParams = {
601                 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType                sType
602                 DE_NULL,                                     // const void*                    pNext
603                 VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT |
604                     VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, // VkCommandBufferUsageFlags    flags
605                 &bufferInheritanceInfo};
606 
607             VK_CHECK(vk.beginCommandBuffer(*secondaryCmdBuffers.back(), &commandBufBeginParams));
608         }
609 
610         const VkCommandBuffer &cmdBuffer = useSecondaryCmdBuffer ? *secondaryCmdBuffers.back() : *cmdBuffers.back();
611 
612         if (!bindPipelineBeforeBeginRendering)
613             vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines[pipelineType]);
614 
615         // Calculate push constant data.
616         const float scaleX = static_cast<float>(renderArea.extent.width - quadShrink * 4) /
617                              static_cast<float>(m_parameters.renderSize.x());
618         const float scaleY = static_cast<float>(renderArea.extent.height - quadShrink * 4) /
619                              static_cast<float>(m_parameters.renderSize.y());
620 
621         DE_ASSERT(scaleX > 0.0f);
622         DE_ASSERT(scaleY > 0.0f);
623 
624         const float pixelSizeX = 2.0f / static_cast<float>(m_parameters.renderSize.x());
625         const float pixelSizeY = 2.0f / static_cast<float>(m_parameters.renderSize.y());
626         const Vec4 scale       = {scaleX + pixelSizeX * 0.5f, scaleY + pixelSizeY * 0.5f, 1.0f, 1.0f};
627         const float offsetX =
628             static_cast<float>(renderArea.offset.x -
629                                static_cast<int>(m_parameters.renderSize.x() - renderArea.extent.width) / 2) *
630             pixelSizeX;
631         const float offsetY =
632             static_cast<float>(renderArea.offset.y -
633                                static_cast<int>(m_parameters.renderSize.y() - renderArea.extent.height) / 2) *
634             pixelSizeY;
635         const Vec4 offset          = {offsetX, offsetY, 0.0f, 0.0f};
636         const uint32_t quadMarginX = renderWidth / 4 + quadShrink;
637         const uint32_t quadMarginY = renderHeight / 4 + quadShrink;
638         const uint32_t quadTop     = renderY + quadMarginY;
639         const uint32_t quadBottom  = renderY + renderHeight - quadMarginY;
640         const uint32_t quadLeft    = renderX + quadMarginX;
641         const uint32_t quadRight   = renderX + renderWidth - quadMarginX;
642 
643         const Vec4 color    = {m_random.getFloat(), m_random.getFloat(), m_random.getFloat(), 1.0f};
644         const int32_t layer = useLayers ? m_random.getUint32() % numLayers : 0;
645 
646         PushConstantData pcd = {scale, offset, color, layer};
647 
648         // Bind vertex buffer.
649         {
650             const VkBuffer vertexBuffer           = m_vertexBuffer->object();
651             const VkDeviceSize vertexBufferOffset = 0ull;
652 
653             vk.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer, &vertexBufferOffset);
654         }
655 
656         if (occlusionQuery)
657             vk.cmdBeginQuery(cmdBuffer, *m_queryPool, queryIndex, 0);
658 
659         vk.cmdPushConstants(cmdBuffer, *m_pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_GEOMETRY_BIT, 0,
660                             sizeof(pcd), &pcd);
661 
662         // Draw or clear a quad inside the render area.
663         switch (pipelineType)
664         {
665         case PIPELINE_TYPE_VERTEX_FRAGMENT:            // A quad using triangle strip.
666         case PIPELINE_TYPE_VERTEX_TESS_FRAGMENT:       // A quad using a tessellated patch.
667         case PIPELINE_TYPE_VERTEX_GEOM_FRAGMENT_LAYER: // A quad using triangle strip drawn to a chosen layer.
668         case PIPELINE_TYPE_VERTEX_FRAGMENT_MULTIVIEW:  // A quad using triangle strip drawn to layers 0, 1, and 3.
669         {
670             vk.cmdDraw(cmdBuffer, 4u, 1u, 0u, 0u);
671         }
672         break;
673         case PIPELINE_TYPE_VERTEX_GEOM_FRAGMENT: // A single point turned into a quad by geometry shader.
674         {
675             vk.cmdDraw(cmdBuffer, 1u, 1u, 0u, 0u);
676         }
677         break;
678         case PIPELINE_TYPE_ATTACHMENT_CLEAR: // A quad using vkCmdClearAttachments
679         {
680             VkClearAttachment clearAttachment = {VK_IMAGE_ASPECT_COLOR_BIT, 0u, makeClearValueColor(color)};
681             VkClearRect rect = {makeRect2D(quadLeft, quadTop, quadRight - quadLeft, quadBottom - quadTop),
682                                 static_cast<uint32_t>(layer), 1u};
683 
684             vk.cmdClearAttachments(cmdBuffer, 1u, &clearAttachment, 1u, &rect);
685         }
686         break;
687         default:
688         {
689             DE_ASSERT(0 && "Unexpected pipeline type.");
690         }
691         break;
692         }
693 
694         if (occlusionQuery)
695         {
696             vk.cmdEndQuery(cmdBuffer, *m_queryPool, queryIndex);
697             if (pipelineType == PIPELINE_TYPE_VERTEX_FRAGMENT_MULTIVIEW)
698             {
699                 queryIndex += 3;
700                 queryMultiviewCount.push_back(3);
701                 queryMultiviewCount.push_back(0);
702                 queryMultiviewCount.push_back(0);
703             }
704             else
705             {
706                 queryIndex++;
707                 queryMultiviewCount.push_back(1);
708             }
709         }
710 
711         uint32_t activeLayersClear = 0x1;
712         uint32_t activeLayersQuad  = 0x1;
713 
714         if (useLayers)
715         {
716             activeLayersClear = (1 << numLayers) - 1;
717             activeLayersQuad  = 1 << layer;
718         }
719         else if (pipelineType == PIPELINE_TYPE_VERTEX_FRAGMENT_MULTIVIEW)
720         {
721             activeLayersClear = activeLayersQuad = viewMask;
722         }
723 
724         // Update reference image.
725         for (uint32_t l = 0; l < numLayers; l++)
726         {
727             tcu::PixelBufferAccess access = ref[l].getAccess();
728             for (uint32_t y = renderY; y < renderY + renderHeight; y++)
729                 for (uint32_t x = renderX; x < renderX + renderWidth; x++)
730                 {
731                     if (loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR && !(flags & VK_RENDERING_RESUMING_BIT_KHR) &&
732                         (activeLayersClear & (1 << l)))
733                     {
734                         access.setPixel(clearColor, x, y);
735                     }
736 
737                     if (x >= quadLeft && x < quadRight && y >= quadTop && y < quadBottom &&
738                         (activeLayersQuad & (1 << l)))
739                     {
740                         // Inside the drawn quad.
741                         Vec4 refColor = color;
742 
743                         if (pipelineType == PIPELINE_TYPE_VERTEX_FRAGMENT_MULTIVIEW)
744                             refColor.z() = 0.15f * static_cast<float>(l);
745                         else if (pipelineType != PIPELINE_TYPE_ATTACHMENT_CLEAR)
746                             refColor.z() = 0.0f;
747 
748                         access.setPixel(refColor, x, y);
749                     }
750                 }
751         }
752 
753         if (useSecondaryCmdBuffer)
754         {
755             // End the secondary buffer
756             VK_CHECK(vk.endCommandBuffer(cmdBuffer));
757 
758             // Call the secondary buffer
759             vk.cmdExecuteCommands(*cmdBuffers.back(), 1u, &cmdBuffer);
760         }
761 
762         vk.cmdEndRendering(*cmdBuffers.back());
763 
764         // Insert a pipeline barrier if not suspending.
765         if (!suspend)
766         {
767             VkMemoryBarrier barrier = {
768                 VK_STRUCTURE_TYPE_MEMORY_BARRIER,     // VkStructureType    sType
769                 DE_NULL,                              // const void*        pNext
770                 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags    srcAccessMask
771                 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT  // VkAccessFlags    dstAccessMask
772             };
773 
774             vk.cmdPipelineBarrier(*cmdBuffers.back(), VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
775                                   VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 1u, &barrier, 0u, DE_NULL, 0u,
776                                   DE_NULL);
777         }
778 
779         prevFlags = flags;
780     }
781 
782     vk.cmdCopyQueryPoolResults(*cmdBuffers.back(), *m_queryPool, 0, queryIndex, m_queryResults->object(), 0,
783                                sizeof(uint32_t), VK_QUERY_RESULT_WAIT_BIT);
784     copyImageToBuffer(vk, *cmdBuffers.back(), *m_imageColor, m_imageBuffer->object(),
785                       tcu::IVec2(m_parameters.renderSize.x(), m_parameters.renderSize.y()),
786                       VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, numLayers,
787                       VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_ASPECT_COLOR_BIT);
788 
789     VK_CHECK(vk.endCommandBuffer(*cmdBuffers.back()));
790 
791     // Submit commands and wait.
792     {
793         const Unique<VkFence> fence(createFence(vk, device));
794         std::vector<VkCommandBuffer> cmdBufferHandles;
795 
796         for (const auto &cmdBuffer : cmdBuffers)
797             cmdBufferHandles.push_back(*cmdBuffer);
798 
799         const VkSubmitInfo submitInfo = {
800             VK_STRUCTURE_TYPE_SUBMIT_INFO,                  // VkStructureType                sType
801             DE_NULL,                                        // const void*                    pNext
802             0u,                                             // uint32_t                        waitSemaphoreCount
803             DE_NULL,                                        // const VkSemaphore*            pWaitSemaphores
804             DE_NULL,                                        // const VkPipelineStageFlags*    pWaitDstStageMask
805             static_cast<uint32_t>(cmdBufferHandles.size()), // uint32_t                        commandBufferCount
806             cmdBufferHandles.data(),                        // const VkCommandBuffer*        pCommandBuffers
807             0u,                                             // uint32_t                        signalSemaphoreCount
808             DE_NULL,                                        // const VkSemaphore*            pSignalSemaphores
809         };
810 
811         VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence));
812         VK_CHECK(vk.waitForFences(device, 1u, &fence.get(), true, ~0ull));
813     }
814 
815     // Verify result image.
816     for (uint32_t i = 0; i < numLayers; i++)
817     {
818         const Allocation allocColor = m_imageBuffer->getBoundMemory();
819         invalidateAlloc(vk, device, allocColor);
820 
821         const tcu::ConstPixelBufferAccess resultColorImage(
822             mapVkFormat(m_parameters.imageFormat), m_parameters.renderSize.x(), m_parameters.renderSize.y(), 1u,
823             static_cast<uint8_t *>(allocColor.getHostPtr()) + m_layerSizeBytes * i);
824 
825         if (!tcu::floatThresholdCompare(log, "Compare Color Image", "Result comparison", ref[i].getAccess(),
826                                         resultColorImage, Vec4(0.02f), tcu::COMPARE_LOG_ON_ERROR))
827         {
828             return tcu::TestStatus::fail("Rendered color image is not correct");
829         }
830     }
831 
832     // Verify query pool results.
833     {
834         uint32_t *queryPtr = static_cast<uint32_t *>(m_queryResults->getBoundMemory().getHostPtr());
835         invalidateAlloc(vk, device, m_queryResults->getBoundMemory());
836 
837         uint32_t i = 0;
838         while (i < queryIndex)
839         {
840             uint32_t querySum = 0;
841             for (uint32_t j = 0; j < queryMultiviewCount[i]; j++)
842             {
843                 querySum += queryPtr[i];
844             }
845             if (querySum == 0)
846             {
847                 return tcu::TestStatus::fail("Expected nonzero occlusion query results.");
848             }
849             i += queryMultiviewCount[i];
850         }
851     }
852 
853     return tcu::TestStatus::pass("Pass");
854 }
855 
856 class RandomTestCase : public TestCase
857 {
858 public:
859     RandomTestCase(tcu::TestContext &context, const std::string &name, const TestParameters &parameters);
860     virtual ~RandomTestCase(void);
861 
862 protected:
863     virtual void checkSupport(Context &context) const;
864     virtual void initPrograms(SourceCollections &programCollection) const;
865     virtual TestInstance *createInstance(Context &context) const;
866 
867     const TestParameters m_parameters;
868 };
869 
RandomTestCase(tcu::TestContext & context,const std::string & name,const TestParameters & parameters)870 RandomTestCase::RandomTestCase(tcu::TestContext &context, const std::string &name, const TestParameters &parameters)
871     : TestCase(context, name)
872     , m_parameters(parameters)
873 {
874 }
875 
~RandomTestCase()876 RandomTestCase::~RandomTestCase()
877 {
878 }
879 
checkSupport(Context & context) const880 void RandomTestCase::checkSupport(Context &context) const
881 {
882     if (!context.requireDeviceFunctionality("VK_KHR_dynamic_rendering"))
883         TCU_THROW(NotSupportedError, "VK_KHR_dynamic_rendering is not supported");
884 
885     if (m_parameters.enableMultiview && !context.requireDeviceFunctionality("VK_KHR_multiview"))
886         TCU_THROW(NotSupportedError, "VK_KHR_multiview is not supported");
887 
888     const VkPhysicalDeviceDynamicRenderingFeaturesKHR &dynamicRenderingFeatures(context.getDynamicRenderingFeatures());
889 
890     if (dynamicRenderingFeatures.dynamicRendering == false)
891         TCU_THROW(NotSupportedError, "dynamicRendering feature is not supported");
892 
893     if (m_parameters.enableGeometry)
894         context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
895     if (m_parameters.enableTessellation)
896         context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
897 }
898 
initPrograms(SourceCollections & programCollection) const899 void RandomTestCase::initPrograms(SourceCollections &programCollection) const
900 {
901     const std::string pushConstant = "layout( push_constant ) uniform constants\n"
902                                      "{\n"
903                                      "    vec4 scale;\n"
904                                      "    vec4 offset;\n"
905                                      "    vec4 color;\n"
906                                      "    int layer;\n"
907                                      "} pc;\n";
908 
909     // Vertex
910     {
911         std::ostringstream src;
912         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
913             << "\n"
914             << "layout(location = 0) in vec4 position;\n"
915             << "layout(location = 0) out vec4 vsColor;\n"
916             << "\n"
917             << pushConstant << "\n"
918             << "void main (void)\n"
919             << "{\n"
920             << "    gl_Position = position * pc.scale + pc.offset;\n"
921             << "    vsColor     = pc.color;\n"
922             << "}\n";
923         programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
924     }
925 
926     // Passthrough vertex
927     if (m_parameters.enableGeometry)
928     {
929         std::ostringstream src;
930         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
931             << "\n"
932             << "layout(location = 0) in vec4 position;\n"
933             << "\n"
934             << "void main (void)\n"
935             << "{\n"
936             << "    gl_Position = position;\n"
937             << "}\n";
938         programCollection.glslSources.add("vertPassthrough") << glu::VertexSource(src.str());
939     }
940 
941     // Vertex layered
942     if (m_parameters.enableGeometry)
943     {
944         std::ostringstream src;
945         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
946             << "layout(location = 0) in vec4 position;\n"
947             << "layout(location = 0) out vec4 positionOut;\n"
948             << "\n"
949             << pushConstant << "\n"
950             << "void main (void)\n"
951             << "{\n"
952             << "    positionOut = position * pc.scale + pc.offset;\n"
953             << "}\n";
954         programCollection.glslSources.add("vertLayer") << glu::VertexSource(src.str());
955     }
956 
957     // Geometry
958     if (m_parameters.enableGeometry)
959     {
960         std::ostringstream src;
961         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
962             << "\n"
963             << "layout(points) in;\n"
964             << "layout(triangle_strip, max_vertices = 4) out;\n"
965             << "layout(location = 0) out vec4 vsColor;\n"
966             << "\n"
967             << pushConstant << "\n"
968             << "void main (void)\n"
969             << "{\n"
970             << "    vec4 quad[4] = vec4[4](vec4(-0.5, 0.5, 0, 1), vec4(-0.5, -0.5, 0, 1), vec4(0.5, 0.5, 0, 1), "
971                "vec4(0.5, -0.5, 0, 1));\n"
972             << "    for (int i = 0; i < 4; i++)\n"
973             << "    {\n"
974             << "        gl_Position = quad[i] * pc.scale + pc.offset;\n"
975             << "        vsColor     = pc.color;\n"
976             << "        EmitVertex();\n"
977             << "    }\n"
978             << "    EndPrimitive();\n"
979             << "}\n";
980         programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
981     }
982 
983     // Geometry passthrough with layer
984     if (m_parameters.enableGeometry)
985     {
986         std::ostringstream src;
987         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
988             << "\n"
989             << "layout(triangles) in;\n"
990             << "layout(triangle_strip, max_vertices = 3) out;\n"
991             << "layout(location = 0) in vec4 position[];\n"
992             << "layout(location = 0) out vec4 vsColor;\n"
993             << "\n"
994             << pushConstant << "\n"
995             << "void main (void)\n"
996             << "{\n"
997             << "    for (int i = 0; i < 3; i++)\n"
998             << "    {\n"
999             << "        gl_Position = position[i];\n"
1000             << "        vsColor     = pc.color;\n"
1001             << "        gl_Layer    = pc.layer;\n"
1002             << "        EmitVertex();\n"
1003             << "    }\n"
1004             << "    EndPrimitive();\n"
1005             << "}\n";
1006         programCollection.glslSources.add("geomLayer") << glu::GeometrySource(src.str());
1007     }
1008 
1009     // Tessellation control
1010     if (m_parameters.enableTessellation)
1011     {
1012         std::ostringstream src;
1013         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1014             << "\n"
1015             << "layout(vertices = 4) out;\n"
1016             << "layout(location = 0) in vec4 in_color[];\n"
1017             << "layout(location = 0) out vec4 out_color[];\n"
1018             << "\n"
1019             << "void main (void)\n"
1020             << "{\n"
1021             << "    if (gl_InvocationID == 0)\n"
1022             << "    {\n"
1023             << "        gl_TessLevelInner[0] = 2.0f;\n"
1024             << "        gl_TessLevelInner[1] = 2.0f;\n"
1025             << "        gl_TessLevelOuter[0] = 2.0f;\n"
1026             << "        gl_TessLevelOuter[1] = 2.0f;\n"
1027             << "        gl_TessLevelOuter[2] = 2.0f;\n"
1028             << "        gl_TessLevelOuter[3] = 2.0f;\n"
1029             << "    }\n"
1030             << "    out_color[gl_InvocationID] = in_color[gl_InvocationID];\n"
1031             << "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
1032             << "}\n";
1033         programCollection.glslSources.add("tsc") << glu::TessellationControlSource(src.str());
1034     }
1035 
1036     // Tessellation evaluation
1037     if (m_parameters.enableTessellation)
1038     {
1039         std::ostringstream src;
1040         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1041             << "\n"
1042             << "layout(quads, equal_spacing, ccw) in;\n"
1043             << "layout(location = 0) in vec4 in_color[];\n"
1044             << "layout(location = 0) out vec4 out_color;\n"
1045             << "void main (void)\n"
1046             << "{\n"
1047             << "    const float u = gl_TessCoord.x;\n"
1048             << "    const float v = gl_TessCoord.y;\n"
1049             << "    gl_Position = (1 - u) * (1 - v) * gl_in[0].gl_Position + (1 - u) * v * gl_in[1].gl_Position + u * "
1050                "(1 - v) * gl_in[2].gl_Position + u * v * gl_in[3].gl_Position;\n"
1051             << "    out_color = in_color[0];\n"
1052             << "}\n";
1053         programCollection.glslSources.add("tse") << glu::TessellationEvaluationSource(src.str());
1054     }
1055 
1056     // Fragment
1057     {
1058         std::ostringstream src;
1059         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n";
1060         if (m_parameters.enableMultiview)
1061             src << "#extension GL_EXT_multiview : require\n";
1062         src << "\n"
1063             << "layout(location = 0) in vec4 vsColor;\n"
1064             << "layout(location = 0) out vec4 fsColor;\n"
1065             << "\n"
1066             << "void main (void)\n"
1067             << "{\n"
1068             << "    fsColor   = vsColor;\n";
1069         if (m_parameters.enableMultiview)
1070             src << "    fsColor.z = 0.15f * gl_ViewIndex;\n";
1071         else
1072             src << "    fsColor.z = 0.0f;\n";
1073         src << "}\n";
1074         programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
1075     }
1076 }
1077 
createInstance(Context & context) const1078 TestInstance *RandomTestCase::createInstance(Context &context) const
1079 {
1080     return new DynamicRenderingTestInstance(context, m_parameters);
1081 }
1082 
addDynamicRenderingTest(tcu::TestContext & testCtx,TestParameters & parameters)1083 tcu::TestNode *addDynamicRenderingTest(tcu::TestContext &testCtx, TestParameters &parameters)
1084 {
1085     const std::string testName =
1086         "seed" + de::toString(parameters.randomSeed) + (parameters.enableGeometry ? "_geometry" : "") +
1087         (parameters.enableTessellation ? "_tessellation" : "") + (parameters.enableMultiview ? "_multiview" : "");
1088 
1089     return new RandomTestCase(testCtx, testName, parameters);
1090 }
1091 
1092 } // namespace
1093 
createDynamicRenderingRandomTests(tcu::TestContext & testCtx)1094 tcu::TestCaseGroup *createDynamicRenderingRandomTests(tcu::TestContext &testCtx)
1095 {
1096     // Random dynamic rendering tests
1097     de::MovePtr<tcu::TestCaseGroup> dynamicRenderingGroup(new tcu::TestCaseGroup(testCtx, "random"));
1098 
1099     for (auto geometry : {true, false})
1100         for (auto tessellation : {true, false})
1101         {
1102             for (auto multiview : {true, false})
1103             {
1104                 TestParameters parameters = {
1105                     VK_FORMAT_R8G8B8A8_UNORM, (UVec2(256, 256)), geometry, tessellation, multiview, 0u};
1106 
1107                 for (uint32_t i = 0; i < 100u; i++)
1108                 {
1109                     parameters.randomSeed = i;
1110                     dynamicRenderingGroup->addChild(addDynamicRenderingTest(testCtx, parameters));
1111                 }
1112             }
1113         }
1114 
1115     return dynamicRenderingGroup.release();
1116 }
1117 
1118 } // namespace renderpass
1119 } // namespace vkt
1120