1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2016 The Khronos Group Inc.
6 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
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 Simple Draw Tests
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktBasicDrawTests.hpp"
26
27 #include "vktDrawBaseClass.hpp"
28 #include "vkQueryUtil.hpp"
29 #include "vkCmdUtil.hpp"
30 #include "vkTypeUtil.hpp"
31 #include "vktTestGroupUtil.hpp"
32
33 #include "deDefs.h"
34 #include "deRandom.hpp"
35 #include "deString.h"
36
37 #include "tcuTestCase.hpp"
38 #include "tcuRGBA.hpp"
39 #include "tcuTextureUtil.hpp"
40 #include "tcuImageCompare.hpp"
41 #include "tcuVectorUtil.hpp"
42
43 #include "rrRenderer.hpp"
44
45 #include <string>
46 #include <sstream>
47
48 namespace vkt
49 {
50 namespace Draw
51 {
52 namespace
53 {
54 static const uint32_t SEED = 0xc2a39fu;
55 static const uint32_t INDEX_LIMIT = 10000;
56 // To avoid too big and mostly empty structures
57 static const uint32_t OFFSET_LIMIT = 1000;
58 // Number of primitives to draw
59 static const uint32_t PRIMITIVE_COUNT[] = {1, 3, 17, 45};
60
61 enum DrawCommandType
62 {
63 DRAW_COMMAND_TYPE_DRAW,
64 DRAW_COMMAND_TYPE_DRAW_INDEXED,
65 DRAW_COMMAND_TYPE_DRAW_INDIRECT,
66 DRAW_COMMAND_TYPE_DRAW_INDEXED_INDIRECT,
67
68 DRAW_COMMAND_TYPE_DRAW_LAST
69 };
70
getDrawCommandTypeName(DrawCommandType command)71 const char *getDrawCommandTypeName(DrawCommandType command)
72 {
73 switch (command)
74 {
75 case DRAW_COMMAND_TYPE_DRAW:
76 return "draw";
77 case DRAW_COMMAND_TYPE_DRAW_INDEXED:
78 return "draw_indexed";
79 case DRAW_COMMAND_TYPE_DRAW_INDIRECT:
80 return "draw_indirect";
81 case DRAW_COMMAND_TYPE_DRAW_INDEXED_INDIRECT:
82 return "draw_indexed_indirect";
83 default:
84 DE_ASSERT(false);
85 }
86 return "";
87 }
88
mapVkPrimitiveTopology(vk::VkPrimitiveTopology primitiveTopology)89 rr::PrimitiveType mapVkPrimitiveTopology(vk::VkPrimitiveTopology primitiveTopology)
90 {
91 switch (primitiveTopology)
92 {
93 case vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
94 return rr::PRIMITIVETYPE_POINTS;
95 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
96 return rr::PRIMITIVETYPE_LINES;
97 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
98 return rr::PRIMITIVETYPE_LINE_STRIP;
99 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
100 return rr::PRIMITIVETYPE_TRIANGLES;
101 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
102 return rr::PRIMITIVETYPE_TRIANGLE_FAN;
103 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
104 return rr::PRIMITIVETYPE_TRIANGLE_STRIP;
105 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
106 return rr::PRIMITIVETYPE_LINES_ADJACENCY;
107 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
108 return rr::PRIMITIVETYPE_LINE_STRIP_ADJACENCY;
109 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
110 return rr::PRIMITIVETYPE_TRIANGLES_ADJACENCY;
111 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
112 return rr::PRIMITIVETYPE_TRIANGLE_STRIP_ADJACENCY;
113 default:
114 DE_ASSERT(false);
115 }
116 return rr::PRIMITIVETYPE_LAST;
117 }
118
119 struct DrawParamsBase
120 {
121 std::vector<PositionColorVertex> vertices;
122 vk::VkPrimitiveTopology topology;
123 bool useMaintenance5;
124 GroupParams groupParams; // we can't use SharedGroupParams here
125
DrawParamsBasevkt::Draw::__anon91bcb92a0111::DrawParamsBase126 DrawParamsBase()
127 {
128 }
129
~DrawParamsBasevkt::Draw::__anon91bcb92a0111::DrawParamsBase130 virtual ~DrawParamsBase()
131 {
132 }
133
DrawParamsBasevkt::Draw::__anon91bcb92a0111::DrawParamsBase134 DrawParamsBase(const vk::VkPrimitiveTopology top, const SharedGroupParams gParams)
135 : topology(top)
136 , useMaintenance5(false)
137 , groupParams{gParams->useDynamicRendering, gParams->useSecondaryCmdBuffer,
138 gParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass, gParams->nestedSecondaryCmdBuffer}
139 {
140 }
141 };
142
143 struct IndexedParamsBase
144 {
145 std::vector<uint32_t> indexes;
146 const vk::VkIndexType indexType;
147
IndexedParamsBasevkt::Draw::__anon91bcb92a0111::IndexedParamsBase148 IndexedParamsBase(const vk::VkIndexType indexT) : indexType(indexT)
149 {
150 }
151 };
152
153 // Structs to store draw parameters
154 struct DrawParams : DrawParamsBase
155 {
156 // vkCmdDraw parameters is like a single VkDrawIndirectCommand
157 vk::VkDrawIndirectCommand params;
158
DrawParamsvkt::Draw::__anon91bcb92a0111::DrawParams159 DrawParams(const vk::VkPrimitiveTopology top, const SharedGroupParams gParams, const uint32_t vertexC,
160 const uint32_t instanceC, const uint32_t firstV, const uint32_t firstI)
161 : DrawParamsBase(top, gParams)
162 {
163 params.vertexCount = vertexC;
164 params.instanceCount = instanceC;
165 params.firstVertex = firstV;
166 params.firstInstance = firstI;
167 }
168 };
169
170 struct DrawIndexedParams : DrawParamsBase, IndexedParamsBase
171 {
172 // vkCmdDrawIndexed parameters is like a single VkDrawIndexedIndirectCommand
173 vk::VkDrawIndexedIndirectCommand params;
174
DrawIndexedParamsvkt::Draw::__anon91bcb92a0111::DrawIndexedParams175 DrawIndexedParams(const vk::VkPrimitiveTopology top, const SharedGroupParams gParams, const vk::VkIndexType indexT,
176 const uint32_t indexC, const uint32_t instanceC, const uint32_t firstIdx, const int32_t vertexO,
177 const uint32_t firstIns)
178 : DrawParamsBase(top, gParams)
179 , IndexedParamsBase(indexT)
180 {
181 params.indexCount = indexC;
182 params.instanceCount = instanceC;
183 params.firstIndex = firstIdx;
184 params.vertexOffset = vertexO;
185 params.firstInstance = firstIns;
186 }
187 };
188
189 struct DrawIndirectParams : DrawParamsBase
190 {
191 std::vector<vk::VkDrawIndirectCommand> commands;
192
DrawIndirectParamsvkt::Draw::__anon91bcb92a0111::DrawIndirectParams193 DrawIndirectParams(const vk::VkPrimitiveTopology top, const SharedGroupParams gParams)
194 : DrawParamsBase(top, gParams)
195 {
196 }
197
addCommandvkt::Draw::__anon91bcb92a0111::DrawIndirectParams198 void addCommand(const uint32_t vertexC, const uint32_t instanceC, const uint32_t firstV, const uint32_t firstI)
199 {
200 vk::VkDrawIndirectCommand cmd;
201 cmd.vertexCount = vertexC;
202 cmd.instanceCount = instanceC;
203 cmd.firstVertex = firstV;
204 cmd.firstInstance = firstI;
205
206 commands.push_back(cmd);
207 }
208 };
209
210 struct DrawIndexedIndirectParams : DrawParamsBase, IndexedParamsBase
211 {
212 std::vector<vk::VkDrawIndexedIndirectCommand> commands;
213
DrawIndexedIndirectParamsvkt::Draw::__anon91bcb92a0111::DrawIndexedIndirectParams214 DrawIndexedIndirectParams(const vk::VkPrimitiveTopology top, const SharedGroupParams gParams,
215 const vk::VkIndexType indexT)
216 : DrawParamsBase(top, gParams)
217 , IndexedParamsBase(indexT)
218 {
219 }
220
addCommandvkt::Draw::__anon91bcb92a0111::DrawIndexedIndirectParams221 void addCommand(const uint32_t indexC, const uint32_t instanceC, const uint32_t firstIdx, const int32_t vertexO,
222 const uint32_t firstIns)
223 {
224 vk::VkDrawIndexedIndirectCommand cmd;
225 cmd.indexCount = indexC;
226 cmd.instanceCount = instanceC;
227 cmd.firstIndex = firstIdx;
228 cmd.vertexOffset = vertexO;
229 cmd.firstInstance = firstIns;
230
231 commands.push_back(cmd);
232 }
233 };
234
235 // Reference renderer shaders
236 class PassthruVertShader : public rr::VertexShader
237 {
238 public:
PassthruVertShader(void)239 PassthruVertShader(void) : rr::VertexShader(2, 1)
240 {
241 m_inputs[0].type = rr::GENERICVECTYPE_FLOAT;
242 m_inputs[1].type = rr::GENERICVECTYPE_FLOAT;
243 m_outputs[0].type = rr::GENERICVECTYPE_FLOAT;
244 }
245
~PassthruVertShader()246 virtual ~PassthruVertShader()
247 {
248 }
249
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const250 void shadeVertices(const rr::VertexAttrib *inputs, rr::VertexPacket *const *packets, const int numPackets) const
251 {
252 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
253 {
254 packets[packetNdx]->position =
255 rr::readVertexAttribFloat(inputs[0], packets[packetNdx]->instanceNdx, packets[packetNdx]->vertexNdx);
256
257 tcu::Vec4 color =
258 rr::readVertexAttribFloat(inputs[1], packets[packetNdx]->instanceNdx, packets[packetNdx]->vertexNdx);
259
260 packets[packetNdx]->outputs[0] = color;
261 }
262 }
263 };
264
265 class PassthruFragShader : public rr::FragmentShader
266 {
267 public:
PassthruFragShader(void)268 PassthruFragShader(void) : rr::FragmentShader(1, 1)
269 {
270 m_inputs[0].type = rr::GENERICVECTYPE_FLOAT;
271 m_outputs[0].type = rr::GENERICVECTYPE_FLOAT;
272 }
273
~PassthruFragShader()274 virtual ~PassthruFragShader()
275 {
276 }
277
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const278 void shadeFragments(rr::FragmentPacket *packets, const int numPackets,
279 const rr::FragmentShadingContext &context) const
280 {
281 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
282 {
283 rr::FragmentPacket &packet = packets[packetNdx];
284 for (uint32_t fragNdx = 0; fragNdx < rr::NUM_FRAGMENTS_PER_PACKET; ++fragNdx)
285 {
286 tcu::Vec4 color = rr::readVarying<float>(packet, context, 0, fragNdx);
287 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
288 }
289 }
290 }
291 };
292
imageCompare(tcu::TestLog & log,const tcu::ConstPixelBufferAccess & reference,const tcu::ConstPixelBufferAccess & result,const vk::VkPrimitiveTopology topology)293 inline bool imageCompare(tcu::TestLog &log, const tcu::ConstPixelBufferAccess &reference,
294 const tcu::ConstPixelBufferAccess &result, const vk::VkPrimitiveTopology topology)
295 {
296 if (topology == vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST)
297 {
298 return tcu::intThresholdPositionDeviationCompare(log, "Result", "Image comparison result", reference, result,
299 tcu::UVec4(4u), // color threshold
300 tcu::IVec3(1, 1, 0), // position deviation tolerance
301 true, // don't check the pixels at the boundary
302 tcu::COMPARE_LOG_RESULT);
303 }
304 else
305 return tcu::fuzzyCompare(log, "Result", "Image comparison result", reference, result, 0.053f,
306 tcu::COMPARE_LOG_RESULT);
307 }
308
309 class DrawTestInstanceBase : public TestInstance
310 {
311 public:
312 DrawTestInstanceBase(Context &context);
313 virtual ~DrawTestInstanceBase(void) = 0;
314 void initialize(const DrawParamsBase &data);
315 void initPipeline(const vk::VkDevice device);
316 void preRenderBarriers(void);
317 void beginRenderPass(vk::VkCommandBuffer cmdBuffer);
318 void endRenderPass(vk::VkCommandBuffer cmdBuffer);
319
320 #ifndef CTS_USES_VULKANSC
321 void beginSecondaryCmdBuffer(const vk::DeviceInterface &vk, vk::VkRenderingFlagsKHR renderingFlags = 0u);
322 void beginNestedCmdBuffer(const vk::DeviceInterface &vk, vk::VkRenderingFlagsKHR renderingFlags = 0u);
323 void beginDynamicRender(vk::VkCommandBuffer cmdBuffer, vk::VkRenderingFlagsKHR renderingFlags = 0u);
324 void beginNestedDynamicRender(vk::VkCommandBuffer cmdBuffer, bool nested,
325 vk::VkRenderingFlagsKHR renderingFlags = 0u);
326 void endDynamicRender(vk::VkCommandBuffer cmdBuffer);
327 #endif // CTS_USES_VULKANSC
328
329 // Specialize this function for each type
330 virtual tcu::TestStatus iterate(void) = 0;
331
332 protected:
333 // Specialize this function for each type
334 virtual void generateDrawData(void) = 0;
335 void generateRefImage(const tcu::PixelBufferAccess &access, const std::vector<tcu::Vec4> &vertices,
336 const std::vector<tcu::Vec4> &colors) const;
337
338 DrawParamsBase m_data;
339 const vk::DeviceInterface &m_vk;
340 vk::Move<vk::VkPipeline> m_pipeline;
341 vk::Move<vk::VkPipelineLayout> m_pipelineLayout;
342 vk::VkFormat m_colorAttachmentFormat;
343 de::SharedPtr<Image> m_colorTargetImage;
344 vk::Move<vk::VkImageView> m_colorTargetView;
345 vk::Move<vk::VkRenderPass> m_renderPass;
346 vk::Move<vk::VkFramebuffer> m_framebuffer;
347 PipelineCreateInfo::VertexInputState m_vertexInputState;
348 de::SharedPtr<Buffer> m_vertexBuffer;
349 vk::Move<vk::VkCommandPool> m_cmdPool;
350 vk::Move<vk::VkCommandBuffer> m_cmdBuffer;
351 vk::Move<vk::VkCommandBuffer> m_secCmdBuffer;
352 vk::Move<vk::VkCommandBuffer> m_nestedCmdBuffer;
353
354 enum
355 {
356 WIDTH = 256,
357 HEIGHT = 256
358 };
359 };
360
DrawTestInstanceBase(Context & context)361 DrawTestInstanceBase::DrawTestInstanceBase(Context &context)
362 : vkt::TestInstance(context)
363 , m_vk(context.getDeviceInterface())
364 , m_colorAttachmentFormat(vk::VK_FORMAT_R8G8B8A8_UNORM)
365 {
366 }
367
~DrawTestInstanceBase(void)368 DrawTestInstanceBase::~DrawTestInstanceBase(void)
369 {
370 }
371
initialize(const DrawParamsBase & data)372 void DrawTestInstanceBase::initialize(const DrawParamsBase &data)
373 {
374 m_data = data;
375
376 const vk::VkDevice device = m_context.getDevice();
377 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
378
379 const PipelineLayoutCreateInfo pipelineLayoutCreateInfo;
380 m_pipelineLayout = vk::createPipelineLayout(m_vk, device, &pipelineLayoutCreateInfo);
381
382 const vk::VkExtent3D targetImageExtent = {WIDTH, HEIGHT, 1};
383 const ImageCreateInfo targetImageCreateInfo(vk::VK_IMAGE_TYPE_2D, m_colorAttachmentFormat, targetImageExtent, 1, 1,
384 vk::VK_SAMPLE_COUNT_1_BIT, vk::VK_IMAGE_TILING_OPTIMAL,
385 vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
386 vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
387 vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT);
388
389 m_colorTargetImage = Image::createAndAlloc(m_vk, device, targetImageCreateInfo, m_context.getDefaultAllocator(),
390 m_context.getUniversalQueueFamilyIndex());
391
392 const ImageViewCreateInfo colorTargetViewInfo(m_colorTargetImage->object(), vk::VK_IMAGE_VIEW_TYPE_2D,
393 m_colorAttachmentFormat);
394 m_colorTargetView = vk::createImageView(m_vk, device, &colorTargetViewInfo);
395
396 // create render pass only when we are not using dynamic rendering
397 if (!m_data.groupParams.useDynamicRendering)
398 {
399 RenderPassCreateInfo renderPassCreateInfo;
400 renderPassCreateInfo.addAttachment(AttachmentDescription(
401 m_colorAttachmentFormat, vk::VK_SAMPLE_COUNT_1_BIT, vk::VK_ATTACHMENT_LOAD_OP_LOAD,
402 vk::VK_ATTACHMENT_STORE_OP_STORE, vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE, vk::VK_ATTACHMENT_STORE_OP_STORE,
403 vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_IMAGE_LAYOUT_GENERAL));
404
405 const vk::VkAttachmentReference colorAttachmentReference{0, vk::VK_IMAGE_LAYOUT_GENERAL};
406
407 renderPassCreateInfo.addSubpass(SubpassDescription(vk::VK_PIPELINE_BIND_POINT_GRAPHICS, 0, 0, DE_NULL, 1,
408 &colorAttachmentReference, DE_NULL, AttachmentReference(), 0,
409 DE_NULL));
410
411 m_renderPass = vk::createRenderPass(m_vk, device, &renderPassCreateInfo);
412
413 // create framebuffer
414 std::vector<vk::VkImageView> colorAttachments{*m_colorTargetView};
415 const FramebufferCreateInfo framebufferCreateInfo(*m_renderPass, colorAttachments, WIDTH, HEIGHT, 1);
416 m_framebuffer = vk::createFramebuffer(m_vk, device, &framebufferCreateInfo);
417 }
418
419 const vk::VkVertexInputBindingDescription vertexInputBindingDescription = {
420 0,
421 (uint32_t)sizeof(tcu::Vec4) * 2,
422 vk::VK_VERTEX_INPUT_RATE_VERTEX,
423 };
424
425 const vk::VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] = {
426 {0u, 0u, vk::VK_FORMAT_R32G32B32A32_SFLOAT, 0u},
427 {
428 1u,
429 0u,
430 vk::VK_FORMAT_R32G32B32A32_SFLOAT,
431 (uint32_t)(sizeof(float) * 4),
432 }};
433
434 m_vertexInputState =
435 PipelineCreateInfo::VertexInputState(1, &vertexInputBindingDescription, 2, vertexInputAttributeDescriptions);
436
437 const vk::VkDeviceSize dataSize = m_data.vertices.size() * sizeof(PositionColorVertex);
438 BufferCreateInfo createInfo(dataSize, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
439
440 #ifndef CTS_USES_VULKANSC
441 vk::VkBufferUsageFlags2CreateInfoKHR bufferUsageFlags2 = vk::initVulkanStructure();
442 if (m_data.useMaintenance5)
443 {
444 bufferUsageFlags2.usage = vk::VK_BUFFER_USAGE_2_VERTEX_BUFFER_BIT_KHR;
445 createInfo.pNext = &bufferUsageFlags2;
446 createInfo.usage = 0xBAD00000;
447 }
448 #endif // CTS_USES_VULKANSC
449
450 m_vertexBuffer = Buffer::createAndAlloc(m_vk, device, createInfo, m_context.getDefaultAllocator(),
451 vk::MemoryRequirement::HostVisible);
452
453 uint8_t *ptr = reinterpret_cast<uint8_t *>(m_vertexBuffer->getBoundMemory().getHostPtr());
454 deMemcpy(ptr, &(m_data.vertices[0]), static_cast<size_t>(dataSize));
455
456 vk::flushAlloc(m_vk, device, m_vertexBuffer->getBoundMemory());
457
458 const CmdPoolCreateInfo cmdPoolCreateInfo(queueFamilyIndex);
459 m_cmdPool = vk::createCommandPool(m_vk, device, &cmdPoolCreateInfo);
460 m_cmdBuffer = vk::allocateCommandBuffer(m_vk, device, *m_cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
461
462 if (m_data.groupParams.useSecondaryCmdBuffer)
463 m_secCmdBuffer = vk::allocateCommandBuffer(m_vk, device, *m_cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_SECONDARY);
464
465 if (m_data.groupParams.nestedSecondaryCmdBuffer)
466 m_nestedCmdBuffer = vk::allocateCommandBuffer(m_vk, device, *m_cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_SECONDARY);
467
468 initPipeline(device);
469 }
470
initPipeline(const vk::VkDevice device)471 void DrawTestInstanceBase::initPipeline(const vk::VkDevice device)
472 {
473 const vk::Unique<vk::VkShaderModule> vs(
474 createShaderModule(m_vk, device, m_context.getBinaryCollection().get("vert"), 0));
475 const vk::Unique<vk::VkShaderModule> fs(
476 createShaderModule(m_vk, device, m_context.getBinaryCollection().get("frag"), 0));
477
478 const PipelineCreateInfo::ColorBlendState::Attachment vkCbAttachmentState;
479
480 vk::VkViewport viewport = vk::makeViewport(WIDTH, HEIGHT);
481 vk::VkRect2D scissor = vk::makeRect2D(WIDTH, HEIGHT);
482
483 // when dynamic_rendering is tested then renderPass won't be created and VK_NULL_HANDLE will be used here
484 PipelineCreateInfo pipelineCreateInfo(*m_pipelineLayout, *m_renderPass, 0, 0);
485 pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vs, "main", vk::VK_SHADER_STAGE_VERTEX_BIT));
486 pipelineCreateInfo.addShader(
487 PipelineCreateInfo::PipelineShaderStage(*fs, "main", vk::VK_SHADER_STAGE_FRAGMENT_BIT));
488 pipelineCreateInfo.addState(PipelineCreateInfo::VertexInputState(m_vertexInputState));
489 pipelineCreateInfo.addState(PipelineCreateInfo::InputAssemblerState(m_data.topology));
490 pipelineCreateInfo.addState(PipelineCreateInfo::ColorBlendState(1, &vkCbAttachmentState));
491 pipelineCreateInfo.addState(PipelineCreateInfo::ViewportState(1, std::vector<vk::VkViewport>(1, viewport),
492 std::vector<vk::VkRect2D>(1, scissor)));
493 pipelineCreateInfo.addState(PipelineCreateInfo::DepthStencilState());
494 pipelineCreateInfo.addState(PipelineCreateInfo::RasterizerState());
495 pipelineCreateInfo.addState(PipelineCreateInfo::MultiSampleState());
496
497 #ifndef CTS_USES_VULKANSC
498 vk::VkPipelineRenderingCreateInfoKHR renderingCreateInfo{vk::VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
499 DE_NULL,
500 0u,
501 1u,
502 &m_colorAttachmentFormat,
503 vk::VK_FORMAT_UNDEFINED,
504 vk::VK_FORMAT_UNDEFINED};
505
506 if (m_data.groupParams.useDynamicRendering)
507 pipelineCreateInfo.pNext = &renderingCreateInfo;
508
509 vk::VkPipelineCreateFlags2CreateInfoKHR pipelineFlags2CreateInfo{
510 vk::VK_STRUCTURE_TYPE_PIPELINE_CREATE_FLAGS_2_CREATE_INFO_KHR, pipelineCreateInfo.pNext,
511 vk::VK_PIPELINE_CREATE_2_ALLOW_DERIVATIVES_BIT_KHR};
512 if (m_data.useMaintenance5)
513 {
514 pipelineCreateInfo.flags = 0xBAD00000;
515 pipelineCreateInfo.pNext = &pipelineFlags2CreateInfo;
516 }
517 #endif // CTS_USES_VULKANSC
518
519 m_pipeline = vk::createGraphicsPipeline(m_vk, device, DE_NULL, &pipelineCreateInfo);
520 }
521
preRenderBarriers(void)522 void DrawTestInstanceBase::preRenderBarriers(void)
523 {
524 const vk::VkClearValue clearColor{{{0.0f, 0.0f, 0.0f, 1.0f}}};
525
526 initialTransitionColor2DImage(m_vk, *m_cmdBuffer, m_colorTargetImage->object(), vk::VK_IMAGE_LAYOUT_GENERAL,
527 vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT);
528
529 const ImageSubresourceRange subresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT);
530 m_vk.cmdClearColorImage(*m_cmdBuffer, m_colorTargetImage->object(), vk::VK_IMAGE_LAYOUT_GENERAL, &clearColor.color,
531 1, &subresourceRange);
532
533 const vk::VkMemoryBarrier memBarrier{
534 vk::VK_STRUCTURE_TYPE_MEMORY_BARRIER, DE_NULL, vk::VK_ACCESS_TRANSFER_WRITE_BIT,
535 vk::VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT};
536
537 m_vk.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
538 vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 1, &memBarrier, 0, DE_NULL, 0,
539 DE_NULL);
540 }
541
beginRenderPass(vk::VkCommandBuffer cmdBuffer)542 void DrawTestInstanceBase::beginRenderPass(vk::VkCommandBuffer cmdBuffer)
543 {
544 const vk::VkClearValue clearColor{{{0.0f, 0.0f, 0.0f, 1.0f}}};
545 const vk::VkRect2D renderArea = vk::makeRect2D(WIDTH, HEIGHT);
546
547 vk::beginRenderPass(m_vk, cmdBuffer, *m_renderPass, *m_framebuffer, renderArea, 1u, &clearColor);
548 }
549
endRenderPass(vk::VkCommandBuffer cmdBuffer)550 void DrawTestInstanceBase::endRenderPass(vk::VkCommandBuffer cmdBuffer)
551 {
552 vk::endRenderPass(m_vk, cmdBuffer);
553 }
554
555 #ifndef CTS_USES_VULKANSC
beginSecondaryCmdBuffer(const vk::DeviceInterface & vk,vk::VkRenderingFlagsKHR renderingFlags)556 void DrawTestInstanceBase::beginSecondaryCmdBuffer(const vk::DeviceInterface &vk,
557 vk::VkRenderingFlagsKHR renderingFlags)
558 {
559 const vk::VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo{
560 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR, // VkStructureType sType;
561 DE_NULL, // const void* pNext;
562 renderingFlags, // VkRenderingFlagsKHR flags;
563 0u, // uint32_t viewMask;
564 1u, // uint32_t colorAttachmentCount;
565 &m_colorAttachmentFormat, // const VkFormat* pColorAttachmentFormats;
566 vk::VK_FORMAT_UNDEFINED, // VkFormat depthAttachmentFormat;
567 vk::VK_FORMAT_UNDEFINED, // VkFormat stencilAttachmentFormat;
568 vk::VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
569 };
570
571 const vk::VkCommandBufferInheritanceInfo bufferInheritanceInfo{
572 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, // VkStructureType sType;
573 &inheritanceRenderingInfo, // const void* pNext;
574 DE_NULL, // VkRenderPass renderPass;
575 0u, // uint32_t subpass;
576 DE_NULL, // VkFramebuffer framebuffer;
577 VK_FALSE, // VkBool32 occlusionQueryEnable;
578 (vk::VkQueryControlFlags)0u, // VkQueryControlFlags queryFlags;
579 (vk::VkQueryPipelineStatisticFlags)0u // VkQueryPipelineStatisticFlags pipelineStatistics;
580 };
581
582 vk::VkCommandBufferUsageFlags usageFlags = vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
583 if (!m_data.groupParams.secondaryCmdBufferCompletelyContainsDynamicRenderpass)
584 usageFlags |= vk::VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
585
586 const vk::VkCommandBufferBeginInfo commandBufBeginParams{
587 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
588 DE_NULL, // const void* pNext;
589 usageFlags, // VkCommandBufferUsageFlags flags;
590 &bufferInheritanceInfo};
591
592 VK_CHECK(vk.beginCommandBuffer(*m_secCmdBuffer, &commandBufBeginParams));
593 }
594
beginNestedCmdBuffer(const vk::DeviceInterface & vk,vk::VkRenderingFlagsKHR renderingFlags)595 void DrawTestInstanceBase::beginNestedCmdBuffer(const vk::DeviceInterface &vk, vk::VkRenderingFlagsKHR renderingFlags)
596 {
597 const vk::VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo{
598 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR, // VkStructureType sType;
599 DE_NULL, // const void* pNext;
600 renderingFlags, // VkRenderingFlagsKHR flags;
601 0u, // uint32_t viewMask;
602 1u, // uint32_t colorAttachmentCount;
603 &m_colorAttachmentFormat, // const VkFormat* pColorAttachmentFormats;
604 vk::VK_FORMAT_UNDEFINED, // VkFormat depthAttachmentFormat;
605 vk::VK_FORMAT_UNDEFINED, // VkFormat stencilAttachmentFormat;
606 vk::VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
607 };
608
609 const vk::VkCommandBufferInheritanceInfo bufferInheritanceInfo{
610 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, // VkStructureType sType;
611 &inheritanceRenderingInfo, // const void* pNext;
612 DE_NULL, // VkRenderPass renderPass;
613 0u, // uint32_t subpass;
614 DE_NULL, // VkFramebuffer framebuffer;
615 VK_FALSE, // VkBool32 occlusionQueryEnable;
616 (vk::VkQueryControlFlags)0u, // VkQueryControlFlags queryFlags;
617 (vk::VkQueryPipelineStatisticFlags)0u // VkQueryPipelineStatisticFlags pipelineStatistics;
618 };
619
620 vk::VkCommandBufferUsageFlags usageFlags = vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
621 if (!m_data.groupParams.secondaryCmdBufferCompletelyContainsDynamicRenderpass)
622 usageFlags |= vk::VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
623
624 const vk::VkCommandBufferBeginInfo commandBufBeginParams{
625 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
626 DE_NULL, // const void* pNext;
627 usageFlags, // VkCommandBufferUsageFlags flags;
628 &bufferInheritanceInfo};
629
630 VK_CHECK(vk.beginCommandBuffer(*m_nestedCmdBuffer, &commandBufBeginParams));
631 }
632
beginDynamicRender(vk::VkCommandBuffer cmdBuffer,vk::VkRenderingFlagsKHR renderingFlags)633 void DrawTestInstanceBase::beginDynamicRender(vk::VkCommandBuffer cmdBuffer, vk::VkRenderingFlagsKHR renderingFlags)
634 {
635 const vk::VkClearValue clearColor{{{0.0f, 0.0f, 0.0f, 1.0f}}};
636 const vk::VkRect2D renderArea = vk::makeRect2D(WIDTH, HEIGHT);
637
638 vk::beginRendering(m_vk, cmdBuffer, *m_colorTargetView, renderArea, clearColor, vk::VK_IMAGE_LAYOUT_GENERAL,
639 vk::VK_ATTACHMENT_LOAD_OP_LOAD, renderingFlags);
640 }
641
endDynamicRender(vk::VkCommandBuffer cmdBuffer)642 void DrawTestInstanceBase::endDynamicRender(vk::VkCommandBuffer cmdBuffer)
643 {
644 vk::endRendering(m_vk, cmdBuffer);
645 }
646 #endif // CTS_USES_VULKANSC
647
generateRefImage(const tcu::PixelBufferAccess & access,const std::vector<tcu::Vec4> & vertices,const std::vector<tcu::Vec4> & colors) const648 void DrawTestInstanceBase::generateRefImage(const tcu::PixelBufferAccess &access,
649 const std::vector<tcu::Vec4> &vertices,
650 const std::vector<tcu::Vec4> &colors) const
651 {
652 const PassthruVertShader vertShader;
653 const PassthruFragShader fragShader;
654 const rr::Program program(&vertShader, &fragShader);
655 const rr::MultisamplePixelBufferAccess colorBuffer =
656 rr::MultisamplePixelBufferAccess::fromSinglesampleAccess(access);
657 const rr::RenderTarget renderTarget(colorBuffer);
658 const rr::RenderState renderState((rr::ViewportState(colorBuffer)),
659 m_context.getDeviceProperties().limits.subPixelPrecisionBits);
660 const rr::Renderer renderer;
661
662 const rr::VertexAttrib vertexAttribs[] = {
663 rr::VertexAttrib(rr::VERTEXATTRIBTYPE_FLOAT, 4, sizeof(tcu::Vec4), 0, &vertices[0]),
664 rr::VertexAttrib(rr::VERTEXATTRIBTYPE_FLOAT, 4, sizeof(tcu::Vec4), 0, &colors[0])};
665
666 renderer.draw(
667 rr::DrawCommand(renderState, renderTarget, program, DE_LENGTH_OF_ARRAY(vertexAttribs), &vertexAttribs[0],
668 rr::PrimitiveList(mapVkPrimitiveTopology(m_data.topology), (uint32_t)vertices.size(), 0)));
669 }
670
671 template <typename T>
672 class DrawTestInstance : public DrawTestInstanceBase
673 {
674 public:
675 DrawTestInstance(Context &context, const T &data);
676 virtual ~DrawTestInstance(void);
677 virtual void generateDrawData(void);
678 virtual void draw(vk::VkCommandBuffer cmdBuffer, vk::VkBuffer indirectBuffer = DE_NULL,
679 vk::VkDeviceSize indirectOffset = 0ul);
680 virtual tcu::TestStatus iterate(void);
681
682 private:
683 T m_data;
684 };
685
686 template <typename T>
DrawTestInstance(Context & context,const T & data)687 DrawTestInstance<T>::DrawTestInstance(Context &context, const T &data) : DrawTestInstanceBase(context)
688 , m_data(data)
689 {
690 generateDrawData();
691 initialize(m_data);
692 }
693
694 template <typename T>
~DrawTestInstance(void)695 DrawTestInstance<T>::~DrawTestInstance(void)
696 {
697 }
698
699 template <typename T>
generateDrawData(void)700 void DrawTestInstance<T>::generateDrawData(void)
701 {
702 DE_FATAL("Using the general case of this function is forbidden!");
703 }
704
705 template <typename T>
draw(vk::VkCommandBuffer,vk::VkBuffer,vk::VkDeviceSize)706 void DrawTestInstance<T>::draw(vk::VkCommandBuffer, vk::VkBuffer, vk::VkDeviceSize)
707 {
708 DE_FATAL("Using the general case of this function is forbidden!");
709 }
710
711 template <typename T>
iterate(void)712 tcu::TestStatus DrawTestInstance<T>::iterate(void)
713 {
714 DE_FATAL("Using the general case of this function is forbidden!");
715 return tcu::TestStatus::fail("");
716 }
717
718 template <typename T>
719 class DrawTestCase : public TestCase
720 {
721 public:
722 DrawTestCase(tcu::TestContext &context, const char *name, const T data);
723 ~DrawTestCase(void);
724 virtual void initPrograms(vk::SourceCollections &programCollection) const;
725 virtual void initShaderSources(void);
726 virtual void checkSupport(Context &context) const;
727 virtual TestInstance *createInstance(Context &context) const;
728
729 private:
730 T m_data;
731 std::string m_vertShaderSource;
732 std::string m_fragShaderSource;
733 };
734
735 template <typename T>
DrawTestCase(tcu::TestContext & context,const char * name,const T data)736 DrawTestCase<T>::DrawTestCase(tcu::TestContext &context, const char *name, const T data)
737 : vkt::TestCase(context, name)
738 , m_data(data)
739 {
740 initShaderSources();
741 }
742
743 template <typename T>
~DrawTestCase(void)744 DrawTestCase<T>::~DrawTestCase(void)
745 {
746 }
747
748 template <typename T>
initPrograms(vk::SourceCollections & programCollection) const749 void DrawTestCase<T>::initPrograms(vk::SourceCollections &programCollection) const
750 {
751 programCollection.glslSources.add("vert") << glu::VertexSource(m_vertShaderSource);
752 programCollection.glslSources.add("frag") << glu::FragmentSource(m_fragShaderSource);
753 }
754
755 template <typename T>
checkSupport(Context & context) const756 void DrawTestCase<T>::checkSupport(Context &context) const
757 {
758 if (m_data.topology == vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY ||
759 m_data.topology == vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY ||
760 m_data.topology == vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY ||
761 m_data.topology == vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY)
762 {
763 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
764 }
765
766 #ifndef CTS_USES_VULKANSC
767 if (m_data.useMaintenance5)
768 context.requireDeviceFunctionality("VK_KHR_maintenance5");
769
770 if (m_data.groupParams.useDynamicRendering)
771 context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
772
773 if (m_data.groupParams.nestedSecondaryCmdBuffer)
774 {
775 context.requireDeviceFunctionality("VK_EXT_nested_command_buffer");
776 const auto &features =
777 *vk::findStructure<vk::VkPhysicalDeviceNestedCommandBufferFeaturesEXT>(&context.getDeviceFeatures2());
778 if (!features.nestedCommandBuffer)
779 TCU_THROW(NotSupportedError, "nestedCommandBuffer is not supported");
780 if (!features.nestedCommandBufferRendering)
781 TCU_THROW(NotSupportedError, "nestedCommandBufferRendering is not supported, so "
782 "VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT cannot be used");
783 }
784
785 if (m_data.topology == vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN &&
786 context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
787 !context.getPortabilitySubsetFeatures().triangleFans)
788 {
789 TCU_THROW(NotSupportedError,
790 "VK_KHR_portability_subset: Triangle fans are not supported by this implementation");
791 }
792 #endif // CTS_USES_VULKANSC
793 }
794
795 template <typename T>
initShaderSources(void)796 void DrawTestCase<T>::initShaderSources(void)
797 {
798 std::stringstream vertShader;
799 vertShader << "#version 430\n"
800 << "layout(location = 0) in vec4 in_position;\n"
801 << "layout(location = 1) in vec4 in_color;\n"
802 << "layout(location = 0) out vec4 out_color;\n"
803
804 << "out gl_PerVertex {\n"
805 << " vec4 gl_Position;\n"
806 << " float gl_PointSize;\n"
807 << "};\n"
808 << "void main() {\n"
809 << " gl_PointSize = 1.0;\n"
810 << " gl_Position = in_position;\n"
811 << " out_color = in_color;\n"
812 << "}\n";
813
814 m_vertShaderSource = vertShader.str();
815
816 std::stringstream fragShader;
817 fragShader << "#version 430\n"
818 << "layout(location = 0) in vec4 in_color;\n"
819 << "layout(location = 0) out vec4 out_color;\n"
820 << "void main()\n"
821 << "{\n"
822 << " out_color = in_color;\n"
823 << "}\n";
824
825 m_fragShaderSource = fragShader.str();
826 }
827
828 template <typename T>
createInstance(Context & context) const829 TestInstance *DrawTestCase<T>::createInstance(Context &context) const
830 {
831 return new DrawTestInstance<T>(context, m_data);
832 }
833
834 // Specialized cases
835 template <>
generateDrawData(void)836 void DrawTestInstance<DrawParams>::generateDrawData(void)
837 {
838 de::Random rnd(SEED ^ m_data.params.firstVertex ^ m_data.params.vertexCount);
839
840 const uint32_t vectorSize = m_data.params.firstVertex + m_data.params.vertexCount;
841
842 // Initialize the vector
843 m_data.vertices = std::vector<PositionColorVertex>(
844 vectorSize, PositionColorVertex(tcu::Vec4(0.0, 0.0, 0.0, 0.0), tcu::Vec4(0.0, 0.0, 0.0, 0.0)));
845
846 // Fill only the used indexes
847 for (uint32_t vertexIdx = m_data.params.firstVertex; vertexIdx < vectorSize; ++vertexIdx)
848 {
849 const float f0 = rnd.getFloat(-1.0f, 1.0f);
850 const float f1 = rnd.getFloat(-1.0f, 1.0f);
851
852 m_data.vertices[vertexIdx] = PositionColorVertex(tcu::Vec4(f0, f1, 1.0f, 1.0f), // Coord
853 tcu::randomVec4(rnd)); // Color
854 }
855 }
856
857 template <>
draw(vk::VkCommandBuffer cmdBuffer,vk::VkBuffer,vk::VkDeviceSize)858 void DrawTestInstance<DrawParams>::draw(vk::VkCommandBuffer cmdBuffer, vk::VkBuffer, vk::VkDeviceSize)
859 {
860 m_vk.cmdDraw(cmdBuffer, m_data.params.vertexCount, m_data.params.instanceCount, m_data.params.firstVertex,
861 m_data.params.firstInstance);
862 }
863
864 template <>
iterate(void)865 tcu::TestStatus DrawTestInstance<DrawParams>::iterate(void)
866 {
867 tcu::TestLog &log = m_context.getTestContext().getLog();
868 const vk::VkQueue queue = m_context.getUniversalQueue();
869 const vk::VkDevice device = m_context.getDevice();
870 const vk::VkDeviceSize vertexBufferOffset = 0;
871 const vk::VkBuffer vertexBuffer = m_vertexBuffer->object();
872
873 #ifndef CTS_USES_VULKANSC
874 if (m_data.groupParams.useSecondaryCmdBuffer)
875 {
876 // record secondary command buffer
877 if (m_data.groupParams.secondaryCmdBufferCompletelyContainsDynamicRenderpass)
878 {
879 beginSecondaryCmdBuffer(m_vk, vk::VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
880 beginDynamicRender(*m_secCmdBuffer);
881 }
882 else
883 beginSecondaryCmdBuffer(m_vk);
884
885 m_vk.cmdBindVertexBuffers(*m_secCmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
886 m_vk.cmdBindPipeline(*m_secCmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
887 draw(*m_secCmdBuffer);
888
889 if (m_data.groupParams.secondaryCmdBufferCompletelyContainsDynamicRenderpass)
890 endDynamicRender(*m_secCmdBuffer);
891
892 endCommandBuffer(m_vk, *m_secCmdBuffer);
893
894 if (m_data.groupParams.nestedSecondaryCmdBuffer)
895 {
896 // record buffer to nest secondary buffer in
897 beginNestedCmdBuffer(m_vk, vk::VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT |
898 vk::VK_RENDERING_CONTENTS_INLINE_BIT_EXT);
899 m_vk.cmdExecuteCommands(*m_nestedCmdBuffer, 1u, &*m_secCmdBuffer);
900 endCommandBuffer(m_vk, *m_nestedCmdBuffer);
901 }
902
903 // record primary command buffer
904 beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
905
906 preRenderBarriers();
907
908 if (!m_data.groupParams.secondaryCmdBufferCompletelyContainsDynamicRenderpass)
909 beginDynamicRender(*m_cmdBuffer, vk::VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
910
911 if (m_data.groupParams.nestedSecondaryCmdBuffer)
912 {
913 m_vk.cmdExecuteCommands(*m_cmdBuffer, 1u, &*m_nestedCmdBuffer);
914 }
915 else
916 {
917 m_vk.cmdExecuteCommands(*m_cmdBuffer, 1u, &*m_secCmdBuffer);
918 }
919
920 if (!m_data.groupParams.secondaryCmdBufferCompletelyContainsDynamicRenderpass)
921 endDynamicRender(*m_cmdBuffer);
922
923 endCommandBuffer(m_vk, *m_cmdBuffer);
924 }
925 else if (m_data.groupParams.useDynamicRendering)
926 {
927 beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
928 preRenderBarriers();
929 beginDynamicRender(*m_cmdBuffer);
930
931 m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
932 m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
933 draw(*m_cmdBuffer);
934
935 endDynamicRender(*m_cmdBuffer);
936 endCommandBuffer(m_vk, *m_cmdBuffer);
937 }
938 #endif // CTS_USES_VULKANSC
939
940 if (!m_data.groupParams.useDynamicRendering)
941 {
942 beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
943 preRenderBarriers();
944 beginRenderPass(*m_cmdBuffer);
945
946 m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
947 m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
948 draw(*m_cmdBuffer);
949
950 endRenderPass(*m_cmdBuffer);
951 endCommandBuffer(m_vk, *m_cmdBuffer);
952 }
953
954 submitCommandsAndWait(m_vk, device, queue, m_cmdBuffer.get());
955
956 // Validation
957 tcu::TextureLevel refImage(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5f + static_cast<float>(WIDTH)),
958 (int)(0.5f + static_cast<float>(HEIGHT)));
959 tcu::clear(refImage.getAccess(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
960
961 std::vector<tcu::Vec4> vertices;
962 std::vector<tcu::Vec4> colors;
963
964 for (std::vector<PositionColorVertex>::const_iterator vertex = m_data.vertices.begin() + m_data.params.firstVertex;
965 vertex != m_data.vertices.end(); ++vertex)
966 {
967 vertices.push_back(vertex->position);
968 colors.push_back(vertex->color);
969 }
970 generateRefImage(refImage.getAccess(), vertices, colors);
971
972 const vk::VkOffset3D zeroOffset = {0, 0, 0};
973 const tcu::ConstPixelBufferAccess renderedFrame =
974 m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(), vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset,
975 WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
976
977 qpTestResult res = QP_TEST_RESULT_PASS;
978
979 if (!imageCompare(log, refImage.getAccess(), renderedFrame, m_data.topology))
980 res = QP_TEST_RESULT_FAIL;
981
982 return tcu::TestStatus(res, qpGetTestResultName(res));
983 }
984
985 template <>
generateDrawData(void)986 void DrawTestInstance<DrawIndexedParams>::generateDrawData(void)
987 {
988 de::Random rnd(SEED ^ m_data.params.firstIndex ^ m_data.params.indexCount);
989 const uint32_t indexSize = m_data.params.firstIndex + m_data.params.indexCount;
990
991 // Initialize the vector with zeros
992 m_data.indexes = std::vector<uint32_t>(indexSize, 0);
993
994 uint32_t highestIndex = 0; // Store to highest index to calculate the vertices size
995 // Fill the indexes from firstIndex
996 for (uint32_t idx = 0; idx < m_data.params.indexCount; ++idx)
997 {
998 uint32_t vertexIdx = rnd.getInt(m_data.params.vertexOffset, INDEX_LIMIT);
999 highestIndex = (vertexIdx > highestIndex) ? vertexIdx : highestIndex;
1000
1001 m_data.indexes[m_data.params.firstIndex + idx] = vertexIdx;
1002 }
1003
1004 // Fill up the vertex coordinates with zeros until the highestIndex including the vertexOffset
1005 m_data.vertices = std::vector<PositionColorVertex>(
1006 m_data.params.vertexOffset + highestIndex + 1,
1007 PositionColorVertex(tcu::Vec4(0.0, 0.0, 0.0, 0.0), tcu::Vec4(0.0, 0.0, 0.0, 0.0)));
1008
1009 // Generate random vertex only where you have index pointing at
1010 for (std::vector<uint32_t>::const_iterator indexIt = m_data.indexes.begin() + m_data.params.firstIndex;
1011 indexIt != m_data.indexes.end(); ++indexIt)
1012 {
1013 // Get iterator to the vertex position with the vertexOffset
1014 std::vector<PositionColorVertex>::iterator vertexIt =
1015 m_data.vertices.begin() + m_data.params.vertexOffset + *indexIt;
1016
1017 tcu::VecAccess<float, 4, 4> positionAccess = vertexIt->position.xyzw();
1018 const float f0 = rnd.getFloat(-1.0f, 1.0f);
1019 const float f1 = rnd.getFloat(-1.0f, 1.0f);
1020 positionAccess = tcu::Vec4(f0, f1, 1.0f, 1.0f);
1021
1022 tcu::VecAccess<float, 4, 4> colorAccess = vertexIt->color.xyzw();
1023 colorAccess = tcu::randomVec4(rnd);
1024 }
1025 }
1026
1027 template <>
draw(vk::VkCommandBuffer cmdBuffer,vk::VkBuffer,vk::VkDeviceSize)1028 void DrawTestInstance<DrawIndexedParams>::draw(vk::VkCommandBuffer cmdBuffer, vk::VkBuffer, vk::VkDeviceSize)
1029 {
1030 m_vk.cmdDrawIndexed(cmdBuffer, m_data.params.indexCount, m_data.params.instanceCount, m_data.params.firstIndex,
1031 m_data.params.vertexOffset, m_data.params.firstInstance);
1032 }
1033
1034 template <>
iterate(void)1035 tcu::TestStatus DrawTestInstance<DrawIndexedParams>::iterate(void)
1036 {
1037 tcu::TestLog &log = m_context.getTestContext().getLog();
1038 const vk::DeviceInterface &vk = m_context.getDeviceInterface();
1039 const vk::VkDevice vkDevice = m_context.getDevice();
1040 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1041 const vk::VkQueue queue = m_context.getUniversalQueue();
1042 vk::Allocator &allocator = m_context.getDefaultAllocator();
1043 const vk::VkDeviceSize vertexBufferOffset = 0;
1044 const vk::VkBuffer vertexBuffer = m_vertexBuffer->object();
1045 const uint32_t bufferSize = (uint32_t)(m_data.indexes.size() * sizeof(uint32_t));
1046
1047 const vk::VkBufferCreateInfo bufferCreateInfo = {
1048 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
1049 DE_NULL, // const void* pNext;
1050 0u, // VkBufferCreateFlags flags;
1051 bufferSize, // VkDeviceSize size;
1052 vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT, // VkBufferUsageFlags usage;
1053 vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1054 1u, // uint32_t queueFamilyIndexCount;
1055 &queueFamilyIndex, // const uint32_t* pQueueFamilyIndices;
1056 };
1057
1058 vk::Move<vk::VkBuffer> indexBuffer = createBuffer(vk, vkDevice, &bufferCreateInfo);
1059 de::MovePtr<vk::Allocation> indexAlloc;
1060
1061 indexAlloc =
1062 allocator.allocate(getBufferMemoryRequirements(vk, vkDevice, *indexBuffer), vk::MemoryRequirement::HostVisible);
1063 VK_CHECK(vk.bindBufferMemory(vkDevice, *indexBuffer, indexAlloc->getMemory(), indexAlloc->getOffset()));
1064
1065 deMemcpy(indexAlloc->getHostPtr(), &(m_data.indexes[0]), bufferSize);
1066
1067 vk::flushAlloc(m_vk, vkDevice, *indexAlloc);
1068
1069 #ifndef CTS_USES_VULKANSC
1070 if (m_data.groupParams.useSecondaryCmdBuffer)
1071 {
1072 // record secondary command buffer
1073 if (m_data.groupParams.secondaryCmdBufferCompletelyContainsDynamicRenderpass)
1074 {
1075 beginSecondaryCmdBuffer(m_vk, vk::VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
1076 beginDynamicRender(*m_secCmdBuffer);
1077 }
1078 else
1079 beginSecondaryCmdBuffer(m_vk);
1080
1081 m_vk.cmdBindPipeline(*m_secCmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
1082 m_vk.cmdBindVertexBuffers(*m_secCmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
1083 m_vk.cmdBindIndexBuffer(*m_secCmdBuffer, *indexBuffer, 0u, m_data.indexType);
1084 draw(*m_secCmdBuffer);
1085
1086 if (m_data.groupParams.secondaryCmdBufferCompletelyContainsDynamicRenderpass)
1087 endDynamicRender(*m_secCmdBuffer);
1088
1089 endCommandBuffer(m_vk, *m_secCmdBuffer);
1090
1091 // record primary command buffer
1092 beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
1093
1094 preRenderBarriers();
1095
1096 if (!m_data.groupParams.secondaryCmdBufferCompletelyContainsDynamicRenderpass)
1097 beginDynamicRender(*m_cmdBuffer, vk::VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
1098
1099 m_vk.cmdExecuteCommands(*m_cmdBuffer, 1u, &*m_secCmdBuffer);
1100
1101 if (!m_data.groupParams.secondaryCmdBufferCompletelyContainsDynamicRenderpass)
1102 endDynamicRender(*m_cmdBuffer);
1103
1104 endCommandBuffer(m_vk, *m_cmdBuffer);
1105 }
1106 else if (m_data.groupParams.useDynamicRendering)
1107 {
1108 beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
1109 preRenderBarriers();
1110 beginDynamicRender(*m_cmdBuffer);
1111
1112 m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
1113 m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
1114 m_vk.cmdBindIndexBuffer(*m_cmdBuffer, *indexBuffer, 0u, m_data.indexType);
1115 draw(*m_cmdBuffer);
1116
1117 endDynamicRender(*m_cmdBuffer);
1118 endCommandBuffer(m_vk, *m_cmdBuffer);
1119 }
1120 #endif // CTS_USES_VULKANSC
1121
1122 if (!m_data.groupParams.useDynamicRendering)
1123 {
1124 beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
1125 preRenderBarriers();
1126 beginRenderPass(*m_cmdBuffer);
1127
1128 m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
1129 m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
1130 m_vk.cmdBindIndexBuffer(*m_cmdBuffer, *indexBuffer, 0u, m_data.indexType);
1131 draw(*m_cmdBuffer);
1132
1133 endRenderPass(*m_cmdBuffer);
1134 endCommandBuffer(m_vk, *m_cmdBuffer);
1135 }
1136
1137 submitCommandsAndWait(m_vk, vkDevice, queue, m_cmdBuffer.get());
1138
1139 // Validation
1140 tcu::TextureLevel refImage(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5f + static_cast<float>(WIDTH)),
1141 (int)(0.5f + static_cast<float>(HEIGHT)));
1142 tcu::clear(refImage.getAccess(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
1143
1144 std::vector<tcu::Vec4> vertices;
1145 std::vector<tcu::Vec4> colors;
1146
1147 for (std::vector<uint32_t>::const_iterator it = m_data.indexes.begin() + m_data.params.firstIndex;
1148 it != m_data.indexes.end(); ++it)
1149 {
1150 uint32_t idx = m_data.params.vertexOffset + *it;
1151 vertices.push_back(m_data.vertices[idx].position);
1152 colors.push_back(m_data.vertices[idx].color);
1153 }
1154 generateRefImage(refImage.getAccess(), vertices, colors);
1155
1156 const vk::VkOffset3D zeroOffset = {0, 0, 0};
1157 const tcu::ConstPixelBufferAccess renderedFrame =
1158 m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(), vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset,
1159 WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
1160
1161 qpTestResult res = QP_TEST_RESULT_PASS;
1162
1163 if (!imageCompare(log, refImage.getAccess(), renderedFrame, m_data.topology))
1164 res = QP_TEST_RESULT_FAIL;
1165
1166 return tcu::TestStatus(res, qpGetTestResultName(res));
1167 }
1168
1169 template <>
generateDrawData(void)1170 void DrawTestInstance<DrawIndirectParams>::generateDrawData(void)
1171 {
1172 de::Random rnd(SEED ^ m_data.commands[0].vertexCount ^ m_data.commands[0].firstVertex);
1173
1174 uint32_t lastIndex = 0;
1175
1176 // Find the interval which will be used
1177 for (std::vector<vk::VkDrawIndirectCommand>::const_iterator it = m_data.commands.begin();
1178 it != m_data.commands.end(); ++it)
1179 {
1180 const uint32_t index = it->firstVertex + it->vertexCount;
1181 lastIndex = (index > lastIndex) ? index : lastIndex;
1182 }
1183
1184 // Initialize with zeros
1185 m_data.vertices = std::vector<PositionColorVertex>(
1186 lastIndex, PositionColorVertex(tcu::Vec4(0.0, 0.0, 0.0, 0.0), tcu::Vec4(0.0, 0.0, 0.0, 0.0)));
1187
1188 // Generate random vertices only where necessary
1189 for (std::vector<vk::VkDrawIndirectCommand>::const_iterator it = m_data.commands.begin();
1190 it != m_data.commands.end(); ++it)
1191 {
1192 std::vector<PositionColorVertex>::iterator vertexStart = m_data.vertices.begin() + it->firstVertex;
1193
1194 for (uint32_t idx = 0; idx < it->vertexCount; ++idx)
1195 {
1196 std::vector<PositionColorVertex>::iterator vertexIt = vertexStart + idx;
1197
1198 tcu::VecAccess<float, 4, 4> positionAccess = vertexIt->position.xyzw();
1199 const float f0 = rnd.getFloat(-1.0f, 1.0f);
1200 const float f1 = rnd.getFloat(-1.0f, 1.0f);
1201 positionAccess = tcu::Vec4(f0, f1, 1.0f, 1.0f);
1202
1203 tcu::VecAccess<float, 4, 4> colorAccess = vertexIt->color.xyzw();
1204 colorAccess = tcu::randomVec4(rnd);
1205 }
1206 }
1207 }
1208
1209 template <>
draw(vk::VkCommandBuffer cmdBuffer,vk::VkBuffer indirectBuffer,vk::VkDeviceSize indirectOffset)1210 void DrawTestInstance<DrawIndirectParams>::draw(vk::VkCommandBuffer cmdBuffer, vk::VkBuffer indirectBuffer,
1211 vk::VkDeviceSize indirectOffset)
1212 {
1213 const vk::VkPhysicalDeviceFeatures features = m_context.getDeviceFeatures();
1214
1215 // If multiDrawIndirect not supported execute single calls
1216 if (m_data.commands.size() > 1 && !(features.multiDrawIndirect))
1217 {
1218 for (uint32_t cmdIdx = 0; cmdIdx < m_data.commands.size(); ++cmdIdx)
1219 {
1220 const uint32_t offset = (uint32_t)(indirectOffset + cmdIdx * sizeof(vk::VkDrawIndirectCommand));
1221 m_vk.cmdDrawIndirect(cmdBuffer, indirectBuffer, offset, 1, sizeof(vk::VkDrawIndirectCommand));
1222 }
1223 }
1224 else
1225 {
1226 m_vk.cmdDrawIndirect(cmdBuffer, indirectBuffer, indirectOffset, (uint32_t)m_data.commands.size(),
1227 sizeof(vk::VkDrawIndirectCommand));
1228 }
1229 }
1230
1231 template <>
iterate(void)1232 tcu::TestStatus DrawTestInstance<DrawIndirectParams>::iterate(void)
1233 {
1234 tcu::TestLog &log = m_context.getTestContext().getLog();
1235 const vk::DeviceInterface &vk = m_context.getDeviceInterface();
1236 const vk::VkDevice vkDevice = m_context.getDevice();
1237 vk::Allocator &allocator = m_context.getDefaultAllocator();
1238 const vk::VkQueue queue = m_context.getUniversalQueue();
1239 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1240 const vk::VkDeviceSize vertexBufferOffset = 0;
1241 const vk::VkBuffer vertexBuffer = m_vertexBuffer->object();
1242 vk::Move<vk::VkBuffer> indirectBuffer;
1243 de::MovePtr<vk::Allocation> indirectAlloc;
1244
1245 {
1246 const vk::VkDeviceSize indirectInfoSize = m_data.commands.size() * sizeof(vk::VkDrawIndirectCommand);
1247
1248 const vk::VkBufferCreateInfo indirectCreateInfo = {
1249 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
1250 DE_NULL, // const void* pNext;
1251 0u, // VkBufferCreateFlags flags;
1252 indirectInfoSize, // VkDeviceSize size;
1253 vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, // VkBufferUsageFlags usage;
1254 vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1255 1u, // uint32_t queueFamilyIndexCount;
1256 &queueFamilyIndex, // const uint32_t* pQueueFamilyIndices;
1257 };
1258
1259 indirectBuffer = createBuffer(vk, vkDevice, &indirectCreateInfo);
1260 indirectAlloc = allocator.allocate(getBufferMemoryRequirements(vk, vkDevice, *indirectBuffer),
1261 vk::MemoryRequirement::HostVisible);
1262 VK_CHECK(
1263 vk.bindBufferMemory(vkDevice, *indirectBuffer, indirectAlloc->getMemory(), indirectAlloc->getOffset()));
1264
1265 deMemcpy(indirectAlloc->getHostPtr(), &(m_data.commands[0]), (size_t)indirectInfoSize);
1266
1267 vk::flushAlloc(m_vk, vkDevice, *indirectAlloc);
1268 }
1269
1270 #ifndef CTS_USES_VULKANSC
1271 if (m_data.groupParams.useSecondaryCmdBuffer)
1272 {
1273 // record secondary command buffer
1274 if (m_data.groupParams.secondaryCmdBufferCompletelyContainsDynamicRenderpass)
1275 {
1276 beginSecondaryCmdBuffer(m_vk, vk::VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
1277 beginDynamicRender(*m_secCmdBuffer);
1278 }
1279 else
1280 beginSecondaryCmdBuffer(m_vk);
1281
1282 m_vk.cmdBindVertexBuffers(*m_secCmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
1283 m_vk.cmdBindPipeline(*m_secCmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
1284 draw(*m_secCmdBuffer, *indirectBuffer, indirectAlloc->getOffset());
1285
1286 if (m_data.groupParams.secondaryCmdBufferCompletelyContainsDynamicRenderpass)
1287 endDynamicRender(*m_secCmdBuffer);
1288
1289 endCommandBuffer(m_vk, *m_secCmdBuffer);
1290
1291 // record primary command buffer
1292 beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
1293
1294 preRenderBarriers();
1295
1296 if (!m_data.groupParams.secondaryCmdBufferCompletelyContainsDynamicRenderpass)
1297 beginDynamicRender(*m_cmdBuffer, vk::VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
1298
1299 m_vk.cmdExecuteCommands(*m_cmdBuffer, 1u, &*m_secCmdBuffer);
1300
1301 if (!m_data.groupParams.secondaryCmdBufferCompletelyContainsDynamicRenderpass)
1302 endDynamicRender(*m_cmdBuffer);
1303
1304 endCommandBuffer(m_vk, *m_cmdBuffer);
1305 }
1306 else if (m_data.groupParams.useDynamicRendering)
1307 {
1308 beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
1309 preRenderBarriers();
1310 beginDynamicRender(*m_cmdBuffer);
1311
1312 m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
1313 m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
1314 draw(*m_cmdBuffer, *indirectBuffer, indirectAlloc->getOffset());
1315
1316 endDynamicRender(*m_cmdBuffer);
1317 endCommandBuffer(m_vk, *m_cmdBuffer);
1318 }
1319 #endif // CTS_USES_VULKANSC
1320
1321 if (!m_data.groupParams.useDynamicRendering)
1322 {
1323 beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
1324 preRenderBarriers();
1325 beginRenderPass(*m_cmdBuffer);
1326
1327 m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
1328 m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
1329 draw(*m_cmdBuffer, *indirectBuffer, indirectAlloc->getOffset());
1330
1331 endRenderPass(*m_cmdBuffer);
1332 endCommandBuffer(m_vk, *m_cmdBuffer);
1333 }
1334
1335 submitCommandsAndWait(m_vk, vkDevice, queue, m_cmdBuffer.get());
1336
1337 // Validation
1338 tcu::TextureLevel refImage(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5f + static_cast<float>(WIDTH)),
1339 (int)(0.5f + static_cast<float>(HEIGHT)));
1340 tcu::clear(refImage.getAccess(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
1341
1342 for (std::vector<vk::VkDrawIndirectCommand>::const_iterator it = m_data.commands.begin();
1343 it != m_data.commands.end(); ++it)
1344 {
1345 std::vector<tcu::Vec4> vertices;
1346 std::vector<tcu::Vec4> colors;
1347
1348 std::vector<PositionColorVertex>::const_iterator firstIt = m_data.vertices.begin() + it->firstVertex;
1349 std::vector<PositionColorVertex>::const_iterator lastIt = firstIt + it->vertexCount;
1350
1351 for (std::vector<PositionColorVertex>::const_iterator vertex = firstIt; vertex != lastIt; ++vertex)
1352 {
1353 vertices.push_back(vertex->position);
1354 colors.push_back(vertex->color);
1355 }
1356 generateRefImage(refImage.getAccess(), vertices, colors);
1357 }
1358
1359 const vk::VkOffset3D zeroOffset = {0, 0, 0};
1360 const tcu::ConstPixelBufferAccess renderedFrame =
1361 m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(), vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset,
1362 WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
1363
1364 qpTestResult res = QP_TEST_RESULT_PASS;
1365
1366 if (!imageCompare(log, refImage.getAccess(), renderedFrame, m_data.topology))
1367 res = QP_TEST_RESULT_FAIL;
1368
1369 return tcu::TestStatus(res, qpGetTestResultName(res));
1370 }
1371
1372 template <>
generateDrawData(void)1373 void DrawTestInstance<DrawIndexedIndirectParams>::generateDrawData(void)
1374 {
1375 de::Random rnd(SEED ^ m_data.commands[0].firstIndex ^ m_data.commands[0].indexCount);
1376
1377 uint32_t lastIndex = 0;
1378
1379 // Get the maximum range of indexes
1380 for (std::vector<vk::VkDrawIndexedIndirectCommand>::const_iterator it = m_data.commands.begin();
1381 it != m_data.commands.end(); ++it)
1382 {
1383 const uint32_t index = it->firstIndex + it->indexCount;
1384 lastIndex = (index > lastIndex) ? index : lastIndex;
1385 }
1386
1387 // Initialize the vector with zeros
1388 m_data.indexes = std::vector<uint32_t>(lastIndex, 0);
1389
1390 uint32_t highestIndex = 0;
1391
1392 // Generate random indexes for the ranges
1393 for (std::vector<vk::VkDrawIndexedIndirectCommand>::const_iterator it = m_data.commands.begin();
1394 it != m_data.commands.end(); ++it)
1395 {
1396 for (uint32_t idx = 0; idx < it->indexCount; ++idx)
1397 {
1398 const uint32_t vertexIdx = rnd.getInt(it->vertexOffset, INDEX_LIMIT);
1399 const uint32_t maxIndex = vertexIdx + it->vertexOffset;
1400
1401 highestIndex = (maxIndex > highestIndex) ? maxIndex : highestIndex;
1402 m_data.indexes[it->firstIndex + idx] = vertexIdx;
1403 }
1404 }
1405
1406 // Initialize the vertex vector
1407 m_data.vertices = std::vector<PositionColorVertex>(
1408 highestIndex + 1, PositionColorVertex(tcu::Vec4(0.0, 0.0, 0.0, 0.0), tcu::Vec4(0.0, 0.0, 0.0, 0.0)));
1409
1410 // Generate random vertices in the used locations
1411 for (std::vector<vk::VkDrawIndexedIndirectCommand>::const_iterator cmdIt = m_data.commands.begin();
1412 cmdIt != m_data.commands.end(); ++cmdIt)
1413 {
1414 uint32_t firstIdx = cmdIt->firstIndex;
1415 uint32_t lastIdx = firstIdx + cmdIt->indexCount;
1416
1417 for (uint32_t idx = firstIdx; idx < lastIdx; ++idx)
1418 {
1419 std::vector<PositionColorVertex>::iterator vertexIt =
1420 m_data.vertices.begin() + cmdIt->vertexOffset + m_data.indexes[idx];
1421
1422 tcu::VecAccess<float, 4, 4> positionAccess = vertexIt->position.xyzw();
1423 const float f0 = rnd.getFloat(-1.0f, 1.0f);
1424 const float f1 = rnd.getFloat(-1.0f, 1.0f);
1425 positionAccess = tcu::Vec4(f0, f1, 1.0f, 1.0f);
1426
1427 tcu::VecAccess<float, 4, 4> colorAccess = vertexIt->color.xyzw();
1428 colorAccess = tcu::randomVec4(rnd);
1429 }
1430 }
1431 }
1432
1433 template <>
draw(vk::VkCommandBuffer cmdBuffer,vk::VkBuffer indirectBuffer,vk::VkDeviceSize indirectOffset)1434 void DrawTestInstance<DrawIndexedIndirectParams>::draw(vk::VkCommandBuffer cmdBuffer, vk::VkBuffer indirectBuffer,
1435 vk::VkDeviceSize indirectOffset)
1436 {
1437 const vk::VkPhysicalDeviceFeatures features = m_context.getDeviceFeatures();
1438
1439 // If multiDrawIndirect not supported execute single calls
1440 if (m_data.commands.size() > 1 && !(features.multiDrawIndirect))
1441 {
1442 for (uint32_t cmdIdx = 0; cmdIdx < m_data.commands.size(); ++cmdIdx)
1443 {
1444 const uint32_t offset = (uint32_t)(indirectOffset + cmdIdx * sizeof(vk::VkDrawIndexedIndirectCommand));
1445 m_vk.cmdDrawIndexedIndirect(cmdBuffer, indirectBuffer, offset, 1, sizeof(vk::VkDrawIndexedIndirectCommand));
1446 }
1447 }
1448 else
1449 {
1450 m_vk.cmdDrawIndexedIndirect(cmdBuffer, indirectBuffer, indirectOffset, (uint32_t)m_data.commands.size(),
1451 sizeof(vk::VkDrawIndexedIndirectCommand));
1452 }
1453 }
1454
1455 template <>
iterate(void)1456 tcu::TestStatus DrawTestInstance<DrawIndexedIndirectParams>::iterate(void)
1457 {
1458 tcu::TestLog &log = m_context.getTestContext().getLog();
1459 const vk::DeviceInterface &vk = m_context.getDeviceInterface();
1460 const vk::VkDevice vkDevice = m_context.getDevice();
1461 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1462 const vk::VkQueue queue = m_context.getUniversalQueue();
1463 vk::Allocator &allocator = m_context.getDefaultAllocator();
1464 const vk::VkDeviceSize vertexBufferOffset = 0;
1465 const vk::VkBuffer vertexBuffer = m_vertexBuffer->object();
1466 vk::Move<vk::VkBuffer> indirectBuffer;
1467 de::MovePtr<vk::Allocation> indirectAlloc;
1468
1469 {
1470 const vk::VkDeviceSize indirectInfoSize = m_data.commands.size() * sizeof(vk::VkDrawIndexedIndirectCommand);
1471
1472 vk::VkBufferCreateInfo indirectCreateInfo{
1473 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
1474 DE_NULL, // const void* pNext;
1475 0u, // VkBufferCreateFlags flags;
1476 indirectInfoSize, // VkDeviceSize size;
1477 vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, // VkBufferUsageFlags usage;
1478 vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1479 1u, // uint32_t queueFamilyIndexCount;
1480 &queueFamilyIndex, // const uint32_t* pQueueFamilyIndices;
1481 };
1482
1483 #ifndef CTS_USES_VULKANSC
1484 vk::VkBufferUsageFlags2CreateInfoKHR bufferUsageFlags2 = vk::initVulkanStructure();
1485 if (m_data.useMaintenance5)
1486 {
1487 bufferUsageFlags2.usage = vk::VK_BUFFER_USAGE_2_INDIRECT_BUFFER_BIT_KHR;
1488 indirectCreateInfo.pNext = &bufferUsageFlags2;
1489 indirectCreateInfo.usage = 0xBAD00000;
1490 }
1491 #endif // CTS_USES_VULKANSC
1492
1493 indirectBuffer = createBuffer(vk, vkDevice, &indirectCreateInfo);
1494 indirectAlloc = allocator.allocate(getBufferMemoryRequirements(vk, vkDevice, *indirectBuffer),
1495 vk::MemoryRequirement::HostVisible);
1496 VK_CHECK(
1497 vk.bindBufferMemory(vkDevice, *indirectBuffer, indirectAlloc->getMemory(), indirectAlloc->getOffset()));
1498
1499 deMemcpy(indirectAlloc->getHostPtr(), &(m_data.commands[0]), (size_t)indirectInfoSize);
1500
1501 vk::flushAlloc(m_vk, vkDevice, *indirectAlloc);
1502 }
1503
1504 const uint32_t bufferSize = (uint32_t)(m_data.indexes.size() * sizeof(uint32_t));
1505
1506 vk::Move<vk::VkBuffer> indexBuffer;
1507
1508 vk::VkBufferCreateInfo bufferCreateInfo{
1509 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
1510 DE_NULL, // const void* pNext;
1511 0u, // VkBufferCreateFlags flags;
1512 bufferSize, // VkDeviceSize size;
1513 vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT, // VkBufferUsageFlags usage;
1514 vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1515 1u, // uint32_t queueFamilyIndexCount;
1516 &queueFamilyIndex, // const uint32_t* pQueueFamilyIndices;
1517 };
1518
1519 #ifndef CTS_USES_VULKANSC
1520 vk::VkBufferUsageFlags2CreateInfoKHR bufferUsageFlags2 = vk::initVulkanStructure();
1521 if (m_data.useMaintenance5)
1522 {
1523 bufferUsageFlags2.usage = vk::VK_BUFFER_USAGE_2_INDEX_BUFFER_BIT_KHR;
1524 bufferCreateInfo.pNext = &bufferUsageFlags2;
1525 bufferCreateInfo.usage = 0xBAD00000;
1526 }
1527 #endif // CTS_USES_VULKANSC
1528
1529 indexBuffer = createBuffer(vk, vkDevice, &bufferCreateInfo);
1530
1531 de::MovePtr<vk::Allocation> indexAlloc;
1532
1533 indexAlloc =
1534 allocator.allocate(getBufferMemoryRequirements(vk, vkDevice, *indexBuffer), vk::MemoryRequirement::HostVisible);
1535 VK_CHECK(vk.bindBufferMemory(vkDevice, *indexBuffer, indexAlloc->getMemory(), indexAlloc->getOffset()));
1536
1537 deMemcpy(indexAlloc->getHostPtr(), &(m_data.indexes[0]), bufferSize);
1538
1539 vk::flushAlloc(m_vk, vkDevice, *indexAlloc);
1540
1541 #ifndef CTS_USES_VULKANSC
1542 if (m_data.groupParams.useSecondaryCmdBuffer)
1543 {
1544 // record secondary command buffer
1545 if (m_data.groupParams.secondaryCmdBufferCompletelyContainsDynamicRenderpass)
1546 {
1547 beginSecondaryCmdBuffer(m_vk, vk::VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
1548 beginDynamicRender(*m_secCmdBuffer);
1549 }
1550 else
1551 beginSecondaryCmdBuffer(m_vk);
1552
1553 m_vk.cmdBindPipeline(*m_secCmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
1554 m_vk.cmdBindVertexBuffers(*m_secCmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
1555 m_vk.cmdBindIndexBuffer(*m_secCmdBuffer, *indexBuffer, 0u, m_data.indexType);
1556 draw(*m_secCmdBuffer, *indirectBuffer, indirectAlloc->getOffset());
1557
1558 if (m_data.groupParams.secondaryCmdBufferCompletelyContainsDynamicRenderpass)
1559 endDynamicRender(*m_secCmdBuffer);
1560
1561 endCommandBuffer(m_vk, *m_secCmdBuffer);
1562
1563 // record primary command buffer
1564 beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
1565
1566 preRenderBarriers();
1567
1568 if (!m_data.groupParams.secondaryCmdBufferCompletelyContainsDynamicRenderpass)
1569 beginDynamicRender(*m_cmdBuffer, vk::VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
1570
1571 m_vk.cmdExecuteCommands(*m_cmdBuffer, 1u, &*m_secCmdBuffer);
1572
1573 if (!m_data.groupParams.secondaryCmdBufferCompletelyContainsDynamicRenderpass)
1574 endDynamicRender(*m_cmdBuffer);
1575
1576 endCommandBuffer(m_vk, *m_cmdBuffer);
1577 }
1578 else if (m_data.groupParams.useDynamicRendering)
1579 {
1580 beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
1581 preRenderBarriers();
1582 beginDynamicRender(*m_cmdBuffer);
1583
1584 m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
1585 m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
1586 m_vk.cmdBindIndexBuffer(*m_cmdBuffer, *indexBuffer, 0u, m_data.indexType);
1587 draw(*m_cmdBuffer, *indirectBuffer, indirectAlloc->getOffset());
1588
1589 endDynamicRender(*m_cmdBuffer);
1590 endCommandBuffer(m_vk, *m_cmdBuffer);
1591 }
1592 #endif // CTS_USES_VULKANSC
1593
1594 if (!m_data.groupParams.useDynamicRendering)
1595 {
1596 beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
1597 preRenderBarriers();
1598 beginRenderPass(*m_cmdBuffer);
1599
1600 m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
1601 m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
1602 m_vk.cmdBindIndexBuffer(*m_cmdBuffer, *indexBuffer, 0u, m_data.indexType);
1603 draw(*m_cmdBuffer, *indirectBuffer, indirectAlloc->getOffset());
1604
1605 endRenderPass(*m_cmdBuffer);
1606 endCommandBuffer(m_vk, *m_cmdBuffer);
1607 }
1608
1609 submitCommandsAndWait(m_vk, vkDevice, queue, m_cmdBuffer.get());
1610
1611 // Validation
1612 tcu::TextureLevel refImage(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5f + static_cast<float>(WIDTH)),
1613 (int)(0.5f + static_cast<float>(HEIGHT)));
1614 tcu::clear(refImage.getAccess(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
1615
1616 for (std::vector<vk::VkDrawIndexedIndirectCommand>::const_iterator cmd = m_data.commands.begin();
1617 cmd != m_data.commands.end(); ++cmd)
1618 {
1619 std::vector<tcu::Vec4> vertices;
1620 std::vector<tcu::Vec4> colors;
1621
1622 for (uint32_t idx = 0; idx < cmd->indexCount; ++idx)
1623 {
1624 const uint32_t vertexIndex = cmd->vertexOffset + m_data.indexes[cmd->firstIndex + idx];
1625 vertices.push_back(m_data.vertices[vertexIndex].position);
1626 colors.push_back(m_data.vertices[vertexIndex].color);
1627 }
1628 generateRefImage(refImage.getAccess(), vertices, colors);
1629 }
1630
1631 const vk::VkOffset3D zeroOffset = {0, 0, 0};
1632 const tcu::ConstPixelBufferAccess renderedFrame =
1633 m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(), vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset,
1634 WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
1635
1636 qpTestResult res = QP_TEST_RESULT_PASS;
1637
1638 if (!imageCompare(log, refImage.getAccess(), renderedFrame, m_data.topology))
1639 res = QP_TEST_RESULT_FAIL;
1640
1641 return tcu::TestStatus(res, qpGetTestResultName(res));
1642 }
1643
1644 typedef DrawTestCase<DrawParams> DrawCase;
1645 typedef DrawTestCase<DrawIndexedParams> IndexedCase;
1646 typedef DrawTestCase<DrawIndirectParams> IndirectCase;
1647 typedef DrawTestCase<DrawIndexedIndirectParams> IndexedIndirectCase;
1648
1649 struct TestCaseParams
1650 {
1651 const DrawCommandType command;
1652 const vk::VkPrimitiveTopology topology;
1653 const SharedGroupParams groupParams;
1654
TestCaseParamsvkt::Draw::__anon91bcb92a0111::TestCaseParams1655 TestCaseParams(const DrawCommandType cmd, const vk::VkPrimitiveTopology top, const SharedGroupParams gParams)
1656 : command(cmd)
1657 , topology(top)
1658 , groupParams(gParams)
1659 {
1660 }
1661 };
1662
1663 } // namespace
1664
populateSubGroup(tcu::TestCaseGroup * testGroup,const TestCaseParams caseParams)1665 void populateSubGroup(tcu::TestCaseGroup *testGroup, const TestCaseParams caseParams)
1666 {
1667 de::Random rnd(SEED ^ deStringHash(testGroup->getName()));
1668 tcu::TestContext &testCtx = testGroup->getTestContext();
1669 const DrawCommandType command = caseParams.command;
1670 const vk::VkPrimitiveTopology topology = caseParams.topology;
1671 const SharedGroupParams groupParams = caseParams.groupParams;
1672 const uint32_t primitiveCountArrLength = DE_LENGTH_OF_ARRAY(PRIMITIVE_COUNT);
1673
1674 for (uint32_t primitiveCountIdx = 0; primitiveCountIdx < primitiveCountArrLength; ++primitiveCountIdx)
1675 {
1676 const uint32_t primitives = PRIMITIVE_COUNT[primitiveCountIdx];
1677
1678 // when testing VK_KHR_dynamic_rendering there is no need to duplicate tests for all primitive counts; use just 1 and 45
1679 if (groupParams->useDynamicRendering && (primitiveCountIdx != 0) &&
1680 (primitiveCountIdx != primitiveCountArrLength - 1))
1681 continue;
1682
1683 uint32_t multiplier = 1;
1684 uint32_t offset = 0;
1685 // Calculated by Vulkan 23.1
1686 switch (topology)
1687 {
1688 case vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
1689 break;
1690 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
1691 multiplier = 2;
1692 break;
1693 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
1694 break;
1695 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
1696 multiplier = 3;
1697 break;
1698 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
1699 break;
1700 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
1701 offset = 1;
1702 break;
1703 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
1704 multiplier = 4;
1705 offset = 1;
1706 break;
1707 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
1708 offset = 1;
1709 break;
1710 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
1711 multiplier = 6;
1712 break;
1713 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
1714 multiplier = 2;
1715 break;
1716 default:
1717 DE_FATAL("Unsupported topology.");
1718 }
1719
1720 const uint32_t vertexCount = multiplier * primitives + offset;
1721 std::string name = de::toString(primitives);
1722
1723 switch (command)
1724 {
1725 case DRAW_COMMAND_TYPE_DRAW:
1726 {
1727 uint32_t firstPrimitive = rnd.getInt(0, primitives);
1728 uint32_t firstVertex = multiplier * firstPrimitive;
1729 testGroup->addChild(
1730 new DrawCase(testCtx, name.c_str(), DrawParams(topology, groupParams, vertexCount, 1, firstVertex, 0)));
1731 break;
1732 }
1733 case DRAW_COMMAND_TYPE_DRAW_INDEXED:
1734 {
1735 uint32_t firstIndex = rnd.getInt(0, OFFSET_LIMIT);
1736 uint32_t vertexOffset = rnd.getInt(0, OFFSET_LIMIT);
1737 testGroup->addChild(new IndexedCase(testCtx, name.c_str(),
1738 DrawIndexedParams(topology, groupParams, vk::VK_INDEX_TYPE_UINT32,
1739 vertexCount, 1, firstIndex, vertexOffset, 0)));
1740 break;
1741 }
1742 case DRAW_COMMAND_TYPE_DRAW_INDIRECT:
1743 {
1744 uint32_t firstVertex = rnd.getInt(0, OFFSET_LIMIT);
1745
1746 DrawIndirectParams params = DrawIndirectParams(topology, groupParams);
1747
1748 params.addCommand(vertexCount, 1, 0, 0);
1749 testGroup->addChild(new IndirectCase(testCtx, (name + "_single_command").c_str(), params));
1750
1751 params.addCommand(vertexCount, 1, firstVertex, 0);
1752 testGroup->addChild(new IndirectCase(testCtx, (name + "_multi_command").c_str(), params));
1753 break;
1754 }
1755 case DRAW_COMMAND_TYPE_DRAW_INDEXED_INDIRECT:
1756 {
1757 uint32_t firstIndex = rnd.getInt(vertexCount, OFFSET_LIMIT);
1758 uint32_t vertexOffset = rnd.getInt(vertexCount, OFFSET_LIMIT);
1759
1760 DrawIndexedIndirectParams params =
1761 DrawIndexedIndirectParams(topology, groupParams, vk::VK_INDEX_TYPE_UINT32);
1762 params.addCommand(vertexCount, 1, 0, 0, 0);
1763 testGroup->addChild(new IndexedIndirectCase(testCtx, (name + "_single_command").c_str(), params));
1764
1765 params.addCommand(vertexCount, 1, firstIndex, vertexOffset, 0);
1766 testGroup->addChild(new IndexedIndirectCase(testCtx, (name + "_multi_command").c_str(), params));
1767 break;
1768 }
1769 default:
1770 DE_FATAL("Unsupported draw command.");
1771 }
1772 }
1773 }
1774
createDrawTests(tcu::TestCaseGroup * testGroup,const SharedGroupParams groupParams)1775 void createDrawTests(tcu::TestCaseGroup *testGroup, const SharedGroupParams groupParams)
1776 {
1777 for (uint32_t drawTypeIndex = 0; drawTypeIndex < DRAW_COMMAND_TYPE_DRAW_LAST; ++drawTypeIndex)
1778 {
1779 const DrawCommandType command(static_cast<DrawCommandType>(drawTypeIndex));
1780 de::MovePtr<tcu::TestCaseGroup> topologyGroup(
1781 new tcu::TestCaseGroup(testGroup->getTestContext(), getDrawCommandTypeName(command)));
1782
1783 for (uint32_t topologyIdx = 0; topologyIdx != vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST; ++topologyIdx)
1784 {
1785 const vk::VkPrimitiveTopology topology(static_cast<vk::VkPrimitiveTopology>(topologyIdx));
1786 const std::string groupName(de::toLower(getPrimitiveTopologyName(topology)).substr(22));
1787
1788 // reduce number of tests for dynamic rendering cases where secondary command buffer is used
1789 if (groupParams->useSecondaryCmdBuffer && (topologyIdx % 2u))
1790 continue;
1791
1792 if (groupParams->nestedSecondaryCmdBuffer && drawTypeIndex != DRAW_COMMAND_TYPE_DRAW)
1793 continue;
1794
1795 // Testcases with a specific topology.
1796 addTestGroup(topologyGroup.get(), groupName, populateSubGroup,
1797 TestCaseParams(command, topology, groupParams));
1798 }
1799
1800 testGroup->addChild(topologyGroup.release());
1801 }
1802
1803 #ifndef CTS_USES_VULKANSC
1804 de::MovePtr<tcu::TestCaseGroup> miscGroup(new tcu::TestCaseGroup(testGroup->getTestContext(), "misc"));
1805 if (groupParams->useDynamicRendering == false)
1806 {
1807 DrawIndexedIndirectParams params(vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, groupParams,
1808 vk::VK_INDEX_TYPE_UINT32);
1809 params.addCommand(4, 1, 0, 0, 0);
1810 params.useMaintenance5 = true;
1811 miscGroup->addChild(new IndexedIndirectCase(testGroup->getTestContext(), "maintenance5", params));
1812 }
1813 testGroup->addChild(miscGroup.release());
1814 #endif // CTS_USES_VULKANSC
1815 }
1816
createBasicDrawTests(tcu::TestContext & testCtx,const SharedGroupParams groupParams)1817 tcu::TestCaseGroup *createBasicDrawTests(tcu::TestContext &testCtx, const SharedGroupParams groupParams)
1818 {
1819 return createTestGroup(testCtx, "basic_draw", createDrawTests, groupParams);
1820 }
1821
1822 } // namespace Draw
1823 } // namespace vkt
1824