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