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