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 ¶meters);
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 ¶meters)
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 ¶meters);
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 ¶meters)
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 ¶meters)
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