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 Instanced Draw Tests
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktDrawInstancedTests.hpp"
26
27 #include <climits>
28
29 #include "deSharedPtr.hpp"
30 #include "rrRenderer.hpp"
31 #include "tcuImageCompare.hpp"
32 #include "tcuRGBA.hpp"
33 #include "tcuTextureUtil.hpp"
34 #include "vkImageUtil.hpp"
35 #include "vkPrograms.hpp"
36 #include "vkCmdUtil.hpp"
37 #include "vkTypeUtil.hpp"
38 #include "vkQueryUtil.hpp"
39 #include "vktDrawBufferObjectUtil.hpp"
40 #include "vktDrawCreateInfoUtil.hpp"
41 #include "vktDrawImageObjectUtil.hpp"
42 #include "vktDrawTestCaseUtil.hpp"
43
44 namespace vkt
45 {
46 namespace Draw
47 {
48 namespace
49 {
50
51 static const int QUAD_GRID_SIZE = 8;
52 static const int WIDTH = 128;
53 static const int HEIGHT = 128;
54
55 struct TestParams
56 {
57 enum DrawFunction
58 {
59 FUNCTION_DRAW = 0,
60 FUNCTION_DRAW_INDEXED,
61 FUNCTION_DRAW_INDIRECT,
62 FUNCTION_DRAW_INDEXED_INDIRECT,
63
64 FUNTION_LAST
65 };
66
67 DrawFunction function;
68 vk::VkPrimitiveTopology topology;
69 const SharedGroupParams groupParams;
70
71 deBool testAttribDivisor;
72 deUint32 attribDivisor;
73
74 deBool testMultiview;
75
76 deBool dynamicState;
77 };
78
79 struct VertexPositionAndColor
80 {
VertexPositionAndColorvkt::Draw::__anon44c184b70111::VertexPositionAndColor81 VertexPositionAndColor (tcu::Vec4 position_, tcu::Vec4 color_)
82 : position (position_)
83 , color (color_)
84 {
85 }
86
87 tcu::Vec4 position;
88 tcu::Vec4 color;
89 };
90
operator <<(std::ostream & str,TestParams const & v)91 std::ostream & operator<<(std::ostream & str, TestParams const & v)
92 {
93 std::ostringstream string;
94
95 if (v.dynamicState)
96 string << "dynamic_state_";
97
98 switch (v.function)
99 {
100 case TestParams::FUNCTION_DRAW:
101 string << "draw";
102 break;
103 case TestParams::FUNCTION_DRAW_INDEXED:
104 string << "draw_indexed";
105 break;
106 case TestParams::FUNCTION_DRAW_INDIRECT:
107 string << "draw_indirect";
108 break;
109 case TestParams::FUNCTION_DRAW_INDEXED_INDIRECT:
110 string << "draw_indexed_indirect";
111 break;
112 default:
113 DE_ASSERT(false);
114 }
115
116 string << "_" << de::toString(v.topology);
117
118 if (v.testAttribDivisor)
119 string << "_attrib_divisor_" << v.attribDivisor;
120
121 if (v.testMultiview)
122 string << "_multiview";
123
124 return str << string.str();
125 }
126
mapVkPrimitiveTopology(vk::VkPrimitiveTopology primitiveTopology)127 rr::PrimitiveType mapVkPrimitiveTopology (vk::VkPrimitiveTopology primitiveTopology)
128 {
129 switch (primitiveTopology)
130 {
131 case vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST: return rr::PRIMITIVETYPE_POINTS;
132 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST: return rr::PRIMITIVETYPE_LINES;
133 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP: return rr::PRIMITIVETYPE_LINE_STRIP;
134 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST: return rr::PRIMITIVETYPE_TRIANGLES;
135 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN: return rr::PRIMITIVETYPE_TRIANGLE_FAN;
136 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP: return rr::PRIMITIVETYPE_TRIANGLE_STRIP;
137 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY: return rr::PRIMITIVETYPE_LINES_ADJACENCY;
138 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY: return rr::PRIMITIVETYPE_LINE_STRIP_ADJACENCY;
139 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY: return rr::PRIMITIVETYPE_TRIANGLES_ADJACENCY;
140 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY: return rr::PRIMITIVETYPE_TRIANGLE_STRIP_ADJACENCY;
141 default:
142 DE_ASSERT(false);
143 }
144 return rr::PRIMITIVETYPE_LAST;
145 }
146
147 template<typename T>
createAndUploadBuffer(const std::vector<T> data,const vk::DeviceInterface & vk,const Context & context,vk::VkBufferUsageFlags usage)148 de::SharedPtr<Buffer> createAndUploadBuffer(const std::vector<T> data, const vk::DeviceInterface& vk, const Context& context, vk::VkBufferUsageFlags usage)
149 {
150 const vk::VkDeviceSize dataSize = data.size() * sizeof(T);
151 de::SharedPtr<Buffer> buffer = Buffer::createAndAlloc(vk, context.getDevice(),
152 BufferCreateInfo(dataSize, usage),
153 context.getDefaultAllocator(),
154 vk::MemoryRequirement::HostVisible);
155
156 deUint8* ptr = reinterpret_cast<deUint8*>(buffer->getBoundMemory().getHostPtr());
157
158 deMemcpy(ptr, &data[0], static_cast<size_t>(dataSize));
159
160 vk::flushAlloc(vk, context.getDevice(), buffer->getBoundMemory());
161 return buffer;
162 }
163
164 class TestVertShader : public rr::VertexShader
165 {
166 public:
TestVertShader(int numInstances,int firstInstance)167 TestVertShader (int numInstances, int firstInstance)
168 : rr::VertexShader (3, 1)
169 , m_numInstances (numInstances)
170 , m_firstInstance (firstInstance)
171 {
172 m_inputs[0].type = rr::GENERICVECTYPE_FLOAT;
173 m_inputs[1].type = rr::GENERICVECTYPE_FLOAT;
174 m_inputs[2].type = rr::GENERICVECTYPE_FLOAT;
175 m_outputs[0].type = rr::GENERICVECTYPE_FLOAT;
176 }
177
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const178 void shadeVertices (const rr::VertexAttrib* inputs,
179 rr::VertexPacket* const* packets,
180 const int numPackets) const
181 {
182 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
183 {
184 const int instanceNdx = packets[packetNdx]->instanceNdx + m_firstInstance;
185 const tcu::Vec4 position = rr::readVertexAttribFloat(inputs[0], packets[packetNdx]->instanceNdx, packets[packetNdx]->vertexNdx, m_firstInstance);
186 const tcu::Vec4 color = rr::readVertexAttribFloat(inputs[1], packets[packetNdx]->instanceNdx, packets[packetNdx]->vertexNdx, m_firstInstance);
187 const tcu::Vec4 color2 = rr::readVertexAttribFloat(inputs[2], packets[packetNdx]->instanceNdx, packets[packetNdx]->vertexNdx, m_firstInstance);
188 packets[packetNdx]->position = position + tcu::Vec4((float)(packets[packetNdx]->instanceNdx * 2.0 / m_numInstances), 0.0, 0.0, 0.0);
189 packets[packetNdx]->outputs[0] = color + tcu::Vec4((float)instanceNdx / (float)m_numInstances, 0.0, 0.0, 1.0) + color2;
190 }
191 }
192
193 private:
194 const int m_numInstances;
195 const int m_firstInstance;
196 };
197
198 class TestFragShader : public rr::FragmentShader
199 {
200 public:
TestFragShader(void)201 TestFragShader (void)
202 : rr::FragmentShader(1, 1)
203 {
204 m_inputs[0].type = rr::GENERICVECTYPE_FLOAT;
205 m_outputs[0].type = rr::GENERICVECTYPE_FLOAT;
206 }
207
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const208 void shadeFragments (rr::FragmentPacket* packets,
209 const int numPackets,
210 const rr::FragmentShadingContext& context) const
211 {
212 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
213 {
214 rr::FragmentPacket& packet = packets[packetNdx];
215 for (int fragNdx = 0; fragNdx < rr::NUM_FRAGMENTS_PER_PACKET; ++fragNdx)
216 {
217 const tcu::Vec4 color = rr::readVarying<float>(packet, context, 0, fragNdx);
218 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
219 }
220 }
221 }
222 };
223
224 class InstancedDrawInstance : public TestInstance
225 {
226 public:
227 InstancedDrawInstance (Context& context, TestParams params);
228 virtual tcu::TestStatus iterate (void);
229
230 private:
231 void prepareVertexData (int instanceCount, int firstInstance, int instanceDivisor);
232 void preRenderCommands (const vk::VkClearValue& clearColor, deUint32 numLayers);
233 void draw (vk::VkCommandBuffer cmdBuffer,
234 vk::VkBuffer vertexBuffer, vk::VkBuffer instancedVertexBuffer,
235 de::SharedPtr<Buffer> indexBuffer, de::SharedPtr<Buffer> indirectBuffer,
236 deUint32 firstInstance, deUint32 instanceCount);
237
238 #ifndef CTS_USES_VULKANSC
239 void beginSecondaryCmdBuffer (vk::VkRenderingFlagsKHR renderingFlags = 0u);
240 #endif // CTS_USES_VULKANSC
241
242 private:
243
244 const TestParams m_params;
245 const vk::DeviceInterface& m_vk;
246
247 vk::VkFormat m_colorAttachmentFormat;
248
249 vk::Move<vk::VkPipeline> m_pipeline;
250 vk::Move<vk::VkPipelineLayout> m_pipelineLayout;
251
252 de::SharedPtr<Image> m_colorTargetImage;
253 vk::Move<vk::VkImageView> m_colorTargetView;
254
255 PipelineCreateInfo::VertexInputState m_vertexInputState;
256
257 vk::Move<vk::VkCommandPool> m_cmdPool;
258 vk::Move<vk::VkCommandBuffer> m_cmdBuffer;
259 vk::Move<vk::VkCommandBuffer> m_secCmdBuffer;
260
261 vk::Move<vk::VkFramebuffer> m_framebuffer;
262 vk::Move<vk::VkRenderPass> m_renderPass;
263
264 // Vertex data
265 std::vector<VertexPositionAndColor> m_data;
266 std::vector<deUint32> m_indexes;
267 std::vector<tcu::Vec4> m_instancedColor;
268 };
269
270 class InstancedDrawCase : public TestCase
271 {
272 public:
InstancedDrawCase(tcu::TestContext & testCtx,const std::string & name,const std::string & desc,TestParams params)273 InstancedDrawCase (tcu::TestContext& testCtx,
274 const std::string& name,
275 const std::string& desc,
276 TestParams params)
277 : TestCase (testCtx, name, desc)
278 , m_params (params)
279 {
280 m_vertexShader = "#version 430\n"
281 "layout(location = 0) in vec4 in_position;\n"
282 "layout(location = 1) in vec4 in_color;\n"
283 "layout(location = 2) in vec4 in_color_2;\n"
284 "layout(push_constant) uniform TestParams {\n"
285 " float firstInstance;\n"
286 " float instanceCount;\n"
287 "} params;\n"
288 "layout(location = 0) out vec4 out_color;\n"
289 "out gl_PerVertex {\n"
290 " vec4 gl_Position;\n"
291 " float gl_PointSize;\n"
292 "};\n"
293 "void main() {\n"
294 " gl_PointSize = 1.0;\n"
295 " gl_Position = in_position + vec4(float(gl_InstanceIndex - params.firstInstance) * 2.0 / params.instanceCount, 0.0, 0.0, 0.0);\n"
296 " out_color = in_color + vec4(float(gl_InstanceIndex) / params.instanceCount, 0.0, 0.0, 1.0) + in_color_2;\n"
297 "}\n";
298
299 m_fragmentShader = "#version 430\n"
300 "layout(location = 0) in vec4 in_color;\n"
301 "layout(location = 0) out vec4 out_color;\n"
302 "void main()\n"
303 "{\n"
304 " out_color = in_color;\n"
305 "}\n";
306 }
307
checkSupport(Context & context) const308 virtual void checkSupport (Context& context) const
309 {
310 if (m_params.dynamicState)
311 {
312 const auto physicalVertexInputDynamicState = context.getVertexInputDynamicStateFeaturesEXT();
313 if (!physicalVertexInputDynamicState.vertexInputDynamicState)
314 TCU_THROW(NotSupportedError, "Implementation does not support vertexInputDynamicState");
315 }
316 if (m_params.testAttribDivisor)
317 {
318 context.requireDeviceFunctionality("VK_EXT_vertex_attribute_divisor");
319
320 const vk::VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT& vertexAttributeDivisorFeatures = context.getVertexAttributeDivisorFeaturesEXT();
321
322 if (m_params.attribDivisor != 1 && !vertexAttributeDivisorFeatures.vertexAttributeInstanceRateDivisor)
323 TCU_THROW(NotSupportedError, "Implementation does not support vertexAttributeInstanceRateDivisor");
324
325 if (m_params.attribDivisor == 0 && !vertexAttributeDivisorFeatures.vertexAttributeInstanceRateZeroDivisor)
326 TCU_THROW(NotSupportedError, "Implementation does not support vertexAttributeInstanceRateDivisorZero");
327
328 if (m_params.testMultiview)
329 {
330 context.requireDeviceFunctionality("VK_KHR_multiview");
331
332 const vk::VkPhysicalDeviceMultiviewFeatures& multiviewFeatures = context.getMultiviewFeatures();
333
334 if (!multiviewFeatures.multiview)
335 TCU_THROW(NotSupportedError, "Implementation does not support multiview feature");
336 }
337 }
338
339 #ifndef CTS_USES_VULKANSC
340 if (m_params.groupParams->useDynamicRendering)
341 context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
342
343 if (m_params.topology == vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN &&
344 context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
345 !context.getPortabilitySubsetFeatures().triangleFans)
346 {
347 TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Triangle fans are not supported by this implementation");
348 }
349 #endif // CTS_USES_VULKANSC
350 }
351
createInstance(Context & context) const352 TestInstance* createInstance (Context& context) const
353 {
354 return new InstancedDrawInstance(context, m_params);
355 }
356
initPrograms(vk::SourceCollections & programCollection) const357 virtual void initPrograms (vk::SourceCollections& programCollection) const
358 {
359 programCollection.glslSources.add("InstancedDrawVert") << glu::VertexSource(m_vertexShader);
360 programCollection.glslSources.add("InstancedDrawFrag") << glu::FragmentSource(m_fragmentShader);
361 }
362
363 private:
364 const TestParams m_params;
365 std::string m_vertexShader;
366 std::string m_fragmentShader;
367 };
368
InstancedDrawInstance(Context & context,TestParams params)369 InstancedDrawInstance::InstancedDrawInstance(Context &context, TestParams params)
370 : TestInstance (context)
371 , m_params (params)
372 , m_vk (context.getDeviceInterface())
373 , m_colorAttachmentFormat (vk::VK_FORMAT_R8G8B8A8_UNORM)
374 {
375 const vk::VkDevice device = m_context.getDevice();
376 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
377
378 const vk::VkPushConstantRange pushConstantRange = {
379 vk::VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlags stageFlags;
380 0u, // uint32_t offset;
381 (deUint32)sizeof(float) * 2, // uint32_t size;
382 };
383
384 const PipelineLayoutCreateInfo pipelineLayoutCreateInfo(0, DE_NULL, 1, &pushConstantRange);
385 m_pipelineLayout = vk::createPipelineLayout(m_vk, device, &pipelineLayoutCreateInfo);
386
387 deUint32 arrayLayers = m_params.testMultiview ? 2 : 1;
388 const vk::VkExtent3D targetImageExtent = { WIDTH, HEIGHT, 1 };
389 const ImageCreateInfo targetImageCreateInfo(vk::VK_IMAGE_TYPE_2D, m_colorAttachmentFormat, targetImageExtent, 1, arrayLayers, vk::VK_SAMPLE_COUNT_1_BIT,
390 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);
391
392 m_colorTargetImage = Image::createAndAlloc(m_vk, device, targetImageCreateInfo, m_context.getDefaultAllocator(), m_context.getUniversalQueueFamilyIndex());
393
394 const enum vk::VkImageViewType imageViewType = m_params.testMultiview ? vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY : vk::VK_IMAGE_VIEW_TYPE_2D;
395 ImageSubresourceRange subresourceRange = ImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT);
396
397 if (m_params.testMultiview)
398 subresourceRange.layerCount = 2;
399
400 const ImageViewCreateInfo colorTargetViewInfo(m_colorTargetImage->object(), imageViewType, m_colorAttachmentFormat, subresourceRange);
401 m_colorTargetView = vk::createImageView(m_vk, device, &colorTargetViewInfo);
402
403 if (!m_params.groupParams->useDynamicRendering)
404 {
405 RenderPassCreateInfo renderPassCreateInfo;
406 renderPassCreateInfo.addAttachment(AttachmentDescription(m_colorAttachmentFormat,
407 vk::VK_SAMPLE_COUNT_1_BIT,
408 vk::VK_ATTACHMENT_LOAD_OP_LOAD,
409 vk::VK_ATTACHMENT_STORE_OP_STORE,
410 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,
411 vk::VK_ATTACHMENT_STORE_OP_STORE,
412 vk::VK_IMAGE_LAYOUT_GENERAL,
413 vk::VK_IMAGE_LAYOUT_GENERAL));
414
415 const vk::VkAttachmentReference colorAttachmentReference =
416 {
417 0,
418 vk::VK_IMAGE_LAYOUT_GENERAL
419 };
420
421 renderPassCreateInfo.addSubpass(SubpassDescription(vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
422 0,
423 0,
424 DE_NULL,
425 1,
426 &colorAttachmentReference,
427 DE_NULL,
428 AttachmentReference(),
429 0,
430 DE_NULL));
431
432 vk::VkRenderPassMultiviewCreateInfo renderPassMultiviewCreateInfo;
433 // Bit mask that specifies which view rendering is broadcast to
434 // 0011 = Broadcast to first and second view (layer)
435 const deUint32 viewMask = 0x3;
436 // Bit mask that specifices correlation between views
437 // An implementation may use this for optimizations (concurrent render)
438 const deUint32 correlationMask = 0x3;
439
440 if (m_params.testMultiview)
441 {
442 DE_ASSERT(renderPassCreateInfo.subpassCount == 1);
443
444 renderPassMultiviewCreateInfo.sType = vk::VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO;
445 renderPassMultiviewCreateInfo.pNext = DE_NULL;
446 renderPassMultiviewCreateInfo.subpassCount = renderPassCreateInfo.subpassCount;
447 renderPassMultiviewCreateInfo.pViewMasks = &viewMask;
448 renderPassMultiviewCreateInfo.correlationMaskCount = 1u;
449 renderPassMultiviewCreateInfo.pCorrelationMasks = &correlationMask;
450 renderPassMultiviewCreateInfo.pViewOffsets = DE_NULL;
451 renderPassMultiviewCreateInfo.dependencyCount = 0u;
452
453 renderPassCreateInfo.pNext = &renderPassMultiviewCreateInfo;
454 }
455
456 m_renderPass = vk::createRenderPass(m_vk, device, &renderPassCreateInfo);
457
458 // create framebuffer
459 std::vector<vk::VkImageView> colorAttachments { *m_colorTargetView };
460 const FramebufferCreateInfo framebufferCreateInfo(*m_renderPass, colorAttachments, WIDTH, HEIGHT, 1);
461 m_framebuffer = vk::createFramebuffer(m_vk, device, &framebufferCreateInfo);
462 }
463
464 const vk::VkVertexInputBindingDescription vertexInputBindingDescription[2] =
465 {
466 {
467 0u,
468 (deUint32)sizeof(VertexPositionAndColor),
469 vk::VK_VERTEX_INPUT_RATE_VERTEX,
470 },
471 {
472 1u,
473 (deUint32)sizeof(tcu::Vec4),
474 vk::VK_VERTEX_INPUT_RATE_INSTANCE,
475 },
476 };
477
478 const vk::VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] =
479 {
480 {
481 0u,
482 0u,
483 vk::VK_FORMAT_R32G32B32A32_SFLOAT,
484 0u
485 },
486 {
487 1u,
488 0u,
489 vk::VK_FORMAT_R32G32B32A32_SFLOAT,
490 (deUint32)sizeof(tcu::Vec4),
491 },
492 {
493 2u,
494 1u,
495 vk::VK_FORMAT_R32G32B32A32_SFLOAT,
496 0,
497 }
498 };
499
500 m_vertexInputState = PipelineCreateInfo::VertexInputState(2,
501 vertexInputBindingDescription,
502 DE_LENGTH_OF_ARRAY(vertexInputAttributeDescriptions),
503 vertexInputAttributeDescriptions);
504
505 const vk::VkVertexInputBindingDivisorDescriptionEXT vertexInputBindingDivisorDescription =
506 {
507 1u,
508 m_params.attribDivisor,
509 };
510
511 if (m_params.testAttribDivisor)
512 m_vertexInputState.addDivisors(1, &vertexInputBindingDivisorDescription);
513
514 const CmdPoolCreateInfo cmdPoolCreateInfo(queueFamilyIndex);
515 m_cmdPool = vk::createCommandPool(m_vk, device, &cmdPoolCreateInfo);
516 m_cmdBuffer = vk::allocateCommandBuffer(m_vk, device, *m_cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
517 if (m_params.groupParams->useSecondaryCmdBuffer)
518 m_secCmdBuffer = vk::allocateCommandBuffer(m_vk, device, *m_cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_SECONDARY);
519
520 const vk::Unique<vk::VkShaderModule> vs(createShaderModule(m_vk, device, m_context.getBinaryCollection().get("InstancedDrawVert"), 0));
521 const vk::Unique<vk::VkShaderModule> fs(createShaderModule(m_vk, device, m_context.getBinaryCollection().get("InstancedDrawFrag"), 0));
522
523 const PipelineCreateInfo::ColorBlendState::Attachment vkCbAttachmentState;
524
525 vk::VkViewport viewport = vk::makeViewport(WIDTH, HEIGHT);
526 vk::VkRect2D scissor = vk::makeRect2D(WIDTH, HEIGHT);
527
528 PipelineCreateInfo pipelineCreateInfo(*m_pipelineLayout, *m_renderPass, 0, 0);
529 pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vs, "main", vk::VK_SHADER_STAGE_VERTEX_BIT));
530 pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*fs, "main", vk::VK_SHADER_STAGE_FRAGMENT_BIT));
531 pipelineCreateInfo.addState(PipelineCreateInfo::InputAssemblerState(m_params.topology));
532 pipelineCreateInfo.addState(PipelineCreateInfo::ColorBlendState(1, &vkCbAttachmentState));
533 pipelineCreateInfo.addState(PipelineCreateInfo::ViewportState(1, std::vector<vk::VkViewport>(1, viewport), std::vector<vk::VkRect2D>(1, scissor)));
534 pipelineCreateInfo.addState(PipelineCreateInfo::DepthStencilState());
535 pipelineCreateInfo.addState(PipelineCreateInfo::RasterizerState());
536 pipelineCreateInfo.addState(PipelineCreateInfo::MultiSampleState());
537
538 if (m_params.dynamicState)
539 {
540 vk::VkDynamicState dynStates[] =
541 {
542 vk::VK_DYNAMIC_STATE_VERTEX_INPUT_EXT
543 };
544
545 vk::VkPipelineDynamicStateCreateInfo dynamicState
546 {
547 vk::VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
548 DE_NULL,
549 0,
550 1,
551 dynStates
552 };
553 pipelineCreateInfo.addState(dynamicState);
554 }
555 else
556 {
557 pipelineCreateInfo.addState(PipelineCreateInfo::VertexInputState(m_vertexInputState));
558 }
559
560 #ifndef CTS_USES_VULKANSC
561 vk::VkPipelineRenderingCreateInfoKHR renderingFormatCreateInfo
562 {
563 vk::VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
564 DE_NULL,
565 0u,
566 1u,
567 &m_colorAttachmentFormat,
568 vk::VK_FORMAT_UNDEFINED,
569 vk::VK_FORMAT_UNDEFINED
570 };
571
572 if (m_params.groupParams->useDynamicRendering)
573 {
574 pipelineCreateInfo.pNext = &renderingFormatCreateInfo;
575
576 if (m_params.testMultiview)
577 renderingFormatCreateInfo.viewMask = 3u;
578 }
579 #endif // CTS_USES_VULKANSC
580
581 m_pipeline = vk::createGraphicsPipeline(m_vk, device, DE_NULL, &pipelineCreateInfo);
582 }
583
iterate()584 tcu::TestStatus InstancedDrawInstance::iterate()
585 {
586 const vk::VkQueue queue = m_context.getUniversalQueue();
587 const vk::VkDevice device = m_context.getDevice();
588 static const deUint32 instanceCounts[] = { 0, 1, 2, 4, 20 };
589 static const deUint32 firstInstanceIndices[] = { 0, 1, 3, 4, 20 };
590 const deUint32 numLayers = m_params.testMultiview ? 2 : 1;
591 const vk::VkRect2D renderArea = vk::makeRect2D(WIDTH, HEIGHT);
592
593 qpTestResult res = QP_TEST_RESULT_PASS;
594
595 const vk::VkClearValue clearColor = { { { 0.0f, 0.0f, 0.0f, 1.0f } } };
596 int firstInstanceIndicesCount = DE_LENGTH_OF_ARRAY(firstInstanceIndices);
597
598 // Require 'drawIndirectFirstInstance' feature to run non-zero firstInstance indirect draw tests.
599 if (m_params.function == TestParams::FUNCTION_DRAW_INDIRECT && !m_context.getDeviceFeatures().drawIndirectFirstInstance)
600 {
601 firstInstanceIndicesCount = 1;
602 }
603
604 for (int instanceCountNdx = 0; instanceCountNdx < DE_LENGTH_OF_ARRAY(instanceCounts); instanceCountNdx++)
605 {
606 const deUint32 instanceCount = instanceCounts[instanceCountNdx];
607 for (int firstInstanceIndexNdx = 0; firstInstanceIndexNdx < firstInstanceIndicesCount; firstInstanceIndexNdx++)
608 {
609 // Prepare vertex data for at least one instance
610 const deUint32 prepareCount = de::max(instanceCount, 1u);
611 const deUint32 firstInstance = firstInstanceIndices[firstInstanceIndexNdx];
612
613 prepareVertexData(prepareCount, firstInstance, m_params.testAttribDivisor ? m_params.attribDivisor : 1);
614 const de::SharedPtr<Buffer> vertexBuffer = createAndUploadBuffer(m_data, m_vk, m_context, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
615 const de::SharedPtr<Buffer> instancedVertexBuffer = createAndUploadBuffer(m_instancedColor, m_vk, m_context, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
616
617 de::SharedPtr<Buffer> indexBuffer;
618 if (m_params.function == TestParams::FUNCTION_DRAW_INDEXED || m_params.function == TestParams::FUNCTION_DRAW_INDEXED_INDIRECT)
619 indexBuffer = createAndUploadBuffer(m_indexes, m_vk, m_context, vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT);
620
621 de::SharedPtr<Buffer> indirectBuffer;
622 if (m_params.function == TestParams::FUNCTION_DRAW_INDIRECT)
623 {
624 std::vector<vk::VkDrawIndirectCommand> drawCommands;
625 drawCommands.push_back({
626 (deUint32)m_data.size(), // uint32_t vertexCount;
627 instanceCount, // uint32_t instanceCount;
628 0u, // uint32_t firstVertex;
629 firstInstance // uint32_t firstInstance;
630 });
631 indirectBuffer = createAndUploadBuffer(drawCommands, m_vk, m_context, vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT);
632 }
633 if (m_params.function == TestParams::FUNCTION_DRAW_INDEXED_INDIRECT)
634 {
635 std::vector<vk::VkDrawIndexedIndirectCommand> drawCommands;
636 drawCommands.push_back({
637 (deUint32)m_indexes.size(), // uint32_t indexCount;
638 instanceCount, // uint32_t instanceCount;
639 0u, // uint32_t firstIndex;
640 0, // int32_t vertexOffset;
641 firstInstance // uint32_t firstInstance;
642 });
643 indirectBuffer = createAndUploadBuffer(drawCommands, m_vk, m_context, vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT);
644 }
645
646 #ifndef CTS_USES_VULKANSC
647 const deUint32 layerCount = (m_params.testMultiview) ? 2u : 1u;
648 const deUint32 viewMask = (m_params.testMultiview) ? 3u : 0u;
649 if (m_params.groupParams->useSecondaryCmdBuffer)
650 {
651 // record secondary command buffer
652 if (m_params.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
653 {
654 beginSecondaryCmdBuffer(vk::VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
655 beginRendering(m_vk, *m_secCmdBuffer, *m_colorTargetView, renderArea, clearColor, vk::VK_IMAGE_LAYOUT_GENERAL,
656 vk::VK_ATTACHMENT_LOAD_OP_LOAD, 0u, layerCount, viewMask);
657 }
658 else
659 beginSecondaryCmdBuffer();
660
661 draw(*m_secCmdBuffer, vertexBuffer->object(), instancedVertexBuffer->object(), indexBuffer, indirectBuffer, firstInstance, instanceCount);
662
663 if (m_params.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
664 endRendering(m_vk, *m_secCmdBuffer);
665
666 endCommandBuffer(m_vk, *m_secCmdBuffer);
667
668 // record primary command buffer
669 beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
670
671 preRenderCommands(clearColor, numLayers);
672
673 if (!m_params.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
674 {
675 beginRendering(m_vk, *m_cmdBuffer, *m_colorTargetView, renderArea, clearColor, vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_ATTACHMENT_LOAD_OP_LOAD,
676 vk::VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT_KHR, layerCount, viewMask);
677 }
678
679 m_vk.cmdExecuteCommands(*m_cmdBuffer, 1u, &*m_secCmdBuffer);
680
681 if (!m_params.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
682 endRendering(m_vk, *m_cmdBuffer);
683
684 endCommandBuffer(m_vk, *m_cmdBuffer);
685 }
686 else if (m_params.groupParams->useDynamicRendering)
687 {
688 beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
689 preRenderCommands(clearColor, numLayers);
690
691 beginRendering(m_vk, *m_cmdBuffer, *m_colorTargetView, renderArea, clearColor, vk::VK_IMAGE_LAYOUT_GENERAL,
692 vk::VK_ATTACHMENT_LOAD_OP_LOAD, 0u, layerCount, viewMask);
693 draw(*m_cmdBuffer, vertexBuffer->object(), instancedVertexBuffer->object(), indexBuffer, indirectBuffer, firstInstance, instanceCount);
694 endRendering(m_vk, *m_cmdBuffer);
695
696 endCommandBuffer(m_vk, *m_cmdBuffer);
697 }
698 #endif // CTS_USES_VULKANSC
699
700 if (!m_params.groupParams->useDynamicRendering)
701 {
702 beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
703 preRenderCommands(clearColor, numLayers);
704
705 beginRenderPass(m_vk, *m_cmdBuffer, *m_renderPass, *m_framebuffer, renderArea);
706 draw(*m_cmdBuffer, vertexBuffer->object(), instancedVertexBuffer->object(), indexBuffer, indirectBuffer, firstInstance, instanceCount);
707 endRenderPass(m_vk, *m_cmdBuffer);
708
709 endCommandBuffer(m_vk, *m_cmdBuffer);
710 }
711
712 /*
713
714 void InstancedDrawInstance::beginRender(vk::VkCommandBuffer cmdBuffer, const vk::VkClearValue& clearColor, vk::VkRenderingFlagsKHR renderingFlags)
715 {
716
717 if (m_params.groupParams->useDynamicRendering)
718 else
719 */
720
721 submitCommandsAndWait(m_vk, device, queue, m_cmdBuffer.get());
722 m_context.resetCommandPoolForVKSC(device, *m_cmdPool);
723
724 // Reference rendering
725 std::vector<tcu::Vec4> vetrices;
726 std::vector<tcu::Vec4> colors;
727
728 for (std::vector<VertexPositionAndColor>::const_iterator it = m_data.begin(); it != m_data.end(); ++it)
729 {
730 vetrices.push_back(it->position);
731 colors.push_back(it->color);
732 }
733
734 tcu::TextureLevel refImage (vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5 + WIDTH), (int)(0.5 + HEIGHT));
735
736 tcu::clear(refImage.getAccess(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
737
738 const TestVertShader vertShader(instanceCount, firstInstance);
739 const TestFragShader fragShader;
740 const rr::Program program (&vertShader, &fragShader);
741 const rr::MultisamplePixelBufferAccess colorBuffer = rr::MultisamplePixelBufferAccess::fromSinglesampleAccess(refImage.getAccess());
742 const rr::RenderTarget renderTarget (colorBuffer);
743 const rr::RenderState renderState ((rr::ViewportState(colorBuffer)), m_context.getDeviceProperties().limits.subPixelPrecisionBits);
744 const rr::Renderer renderer;
745
746 const rr::VertexAttrib vertexAttribs[] =
747 {
748 rr::VertexAttrib(rr::VERTEXATTRIBTYPE_FLOAT, 4, sizeof(tcu::Vec4), 0, &vetrices[0]),
749 rr::VertexAttrib(rr::VERTEXATTRIBTYPE_FLOAT, 4, sizeof(tcu::Vec4), 0, &colors[0]),
750 // The reference renderer treats a divisor of 0 as meaning per-vertex. Use INT_MAX instead; it should work just as well.
751 rr::VertexAttrib(rr::VERTEXATTRIBTYPE_FLOAT, 4, sizeof(tcu::Vec4), m_params.testAttribDivisor ? (m_params.attribDivisor == 0 ? INT_MAX : m_params.attribDivisor) : 1, &m_instancedColor[0])
752 };
753
754 if (m_params.function == TestParams::FUNCTION_DRAW || m_params.function == TestParams::FUNCTION_DRAW_INDIRECT)
755 {
756 const rr::PrimitiveList primitives = rr::PrimitiveList(mapVkPrimitiveTopology(m_params.topology), (int)vetrices.size(), 0);
757 const rr::DrawCommand command(renderState, renderTarget, program, DE_LENGTH_OF_ARRAY(vertexAttribs), &vertexAttribs[0],
758 primitives);
759 renderer.drawInstanced(command, instanceCount);
760 }
761 else
762 {
763 const rr::DrawIndices indicies(m_indexes.data());
764
765 const rr::PrimitiveList primitives = rr::PrimitiveList(mapVkPrimitiveTopology(m_params.topology), (int)m_indexes.size(), indicies);
766 const rr::DrawCommand command(renderState, renderTarget, program, DE_LENGTH_OF_ARRAY(vertexAttribs), &vertexAttribs[0],
767 primitives);
768 renderer.drawInstanced(command, instanceCount);
769 }
770
771 const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
772 for (deUint32 i = 0; i < numLayers; i++)
773 {
774 const tcu::ConstPixelBufferAccess renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
775 vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT, 0, i);
776
777 tcu::TestLog &log = m_context.getTestContext().getLog();
778
779 std::ostringstream resultDesc;
780 resultDesc << "Image layer " << i << " comparison result. Instance count: " << instanceCount << " first instance index: " << firstInstance;
781
782 if (m_params.topology == vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST)
783 {
784 const bool ok = tcu::intThresholdPositionDeviationCompare(
785 log, "Result", resultDesc.str().c_str(), refImage.getAccess(), renderedFrame,
786 tcu::UVec4(4u), // color threshold
787 tcu::IVec3(1, 1, 0), // position deviation tolerance
788 true, // don't check the pixels at the boundary
789 tcu::COMPARE_LOG_RESULT);
790
791 if (!ok)
792 res = QP_TEST_RESULT_FAIL;
793 }
794 else
795 {
796 if (!tcu::fuzzyCompare(log, "Result", resultDesc.str().c_str(), refImage.getAccess(), renderedFrame, 0.05f, tcu::COMPARE_LOG_RESULT))
797 res = QP_TEST_RESULT_FAIL;
798 }
799 }
800 }
801 }
802 return tcu::TestStatus(res, qpGetTestResultName(res));
803 }
804
prepareVertexData(int instanceCount,int firstInstance,int instanceDivisor)805 void InstancedDrawInstance::prepareVertexData(int instanceCount, int firstInstance, int instanceDivisor)
806 {
807 m_data.clear();
808 m_indexes.clear();
809 m_instancedColor.clear();
810
811 if (m_params.function == TestParams::FUNCTION_DRAW || m_params.function == TestParams::FUNCTION_DRAW_INDIRECT)
812 {
813 for (int y = 0; y < QUAD_GRID_SIZE; y++)
814 {
815 for (int x = 0; x < QUAD_GRID_SIZE; x++)
816 {
817 const float fx0 = -1.0f + (float)(x+0) / (float)QUAD_GRID_SIZE * 2.0f / (float)instanceCount;
818 const float fx1 = -1.0f + (float)(x+1) / (float)QUAD_GRID_SIZE * 2.0f / (float)instanceCount;
819 const float fy0 = -1.0f + (float)(y+0) / (float)QUAD_GRID_SIZE * 2.0f;
820 const float fy1 = -1.0f + (float)(y+1) / (float)QUAD_GRID_SIZE * 2.0f;
821
822 // Vertices of a quad's lower-left triangle: (fx0, fy0), (fx1, fy0) and (fx0, fy1)
823 m_data.push_back(VertexPositionAndColor(tcu::Vec4(fx0, fy0, 1.0f, 1.0f), tcu::RGBA::blue().toVec()));
824 m_data.push_back(VertexPositionAndColor(tcu::Vec4(fx1, fy0, 1.0f, 1.0f), tcu::RGBA::blue().toVec()));
825 m_data.push_back(VertexPositionAndColor(tcu::Vec4(fx0, fy1, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
826
827 // Vertices of a quad's upper-right triangle: (fx1, fy1), (fx0, fy1) and (fx1, fy0)
828 m_data.push_back(VertexPositionAndColor(tcu::Vec4(fx1, fy1, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
829 m_data.push_back(VertexPositionAndColor(tcu::Vec4(fx0, fy1, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
830 m_data.push_back(VertexPositionAndColor(tcu::Vec4(fx1, fy0, 1.0f, 1.0f), tcu::RGBA::blue().toVec()));
831 }
832 }
833 }
834 else
835 {
836 for (int y = 0; y < QUAD_GRID_SIZE + 1; y++)
837 {
838 for (int x = 0; x < QUAD_GRID_SIZE + 1; x++)
839 {
840 const float fx = -1.0f + (float)x / (float)QUAD_GRID_SIZE * 2.0f / (float)instanceCount;
841 const float fy = -1.0f + (float)y / (float)QUAD_GRID_SIZE * 2.0f;
842
843 m_data.push_back(VertexPositionAndColor(tcu::Vec4(fx, fy, 1.0f, 1.0f),
844 (y % 2 ? tcu::RGBA::blue().toVec() : tcu::RGBA::green().toVec())));
845 }
846 }
847
848 for (int y = 0; y < QUAD_GRID_SIZE; y++)
849 {
850 for (int x = 0; x < QUAD_GRID_SIZE; x++)
851 {
852 const int ndx00 = y*(QUAD_GRID_SIZE + 1) + x;
853 const int ndx10 = y*(QUAD_GRID_SIZE + 1) + x + 1;
854 const int ndx01 = (y + 1)*(QUAD_GRID_SIZE + 1) + x;
855 const int ndx11 = (y + 1)*(QUAD_GRID_SIZE + 1) + x + 1;
856
857 // Lower-left triangle of a quad.
858 m_indexes.push_back((deUint16)ndx00);
859 m_indexes.push_back((deUint16)ndx10);
860 m_indexes.push_back((deUint16)ndx01);
861
862 // Upper-right triangle of a quad.
863 m_indexes.push_back((deUint16)ndx11);
864 m_indexes.push_back((deUint16)ndx01);
865 m_indexes.push_back((deUint16)ndx10);
866 }
867 }
868 }
869
870 const int colorCount = instanceDivisor == 0 ? 1 : (instanceCount + firstInstance + instanceDivisor - 1) / instanceDivisor;
871 for (int i = 0; i < instanceCount + firstInstance; i++)
872 {
873 m_instancedColor.push_back(tcu::Vec4(0.0, (float)(1.0 - i * 1.0 / colorCount) / 2, 0.0, 1.0));
874 }
875 }
876
preRenderCommands(const vk::VkClearValue & clearColor,deUint32 numLayers)877 void InstancedDrawInstance::preRenderCommands(const vk::VkClearValue& clearColor, deUint32 numLayers)
878 {
879 const ImageSubresourceRange subresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, numLayers);
880
881 if (m_params.testMultiview)
882 {
883 vk::VkImageMemoryBarrier barrier
884 {
885 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
886 DE_NULL, // const void* pNext;
887 0u, // VkAccessFlags srcAccessMask;
888 vk::VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask;
889 vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
890 vk::VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout;
891 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
892 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
893 m_colorTargetImage->object(), // VkImage image;
894 subresourceRange // VkImageSubresourceRange subresourceRange;
895 };
896
897 m_vk.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL,
898 0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1, &barrier);
899 }
900 else
901 {
902 initialTransitionColor2DImage(m_vk, *m_cmdBuffer, m_colorTargetImage->object(), vk::VK_IMAGE_LAYOUT_GENERAL,
903 vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT);
904 }
905
906 m_vk.cmdClearColorImage(*m_cmdBuffer, m_colorTargetImage->object(),
907 vk::VK_IMAGE_LAYOUT_GENERAL, &clearColor.color, 1, &subresourceRange);
908
909 const vk::VkMemoryBarrier memBarrier
910 {
911 vk::VK_STRUCTURE_TYPE_MEMORY_BARRIER,
912 DE_NULL,
913 vk::VK_ACCESS_TRANSFER_WRITE_BIT,
914 vk::VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
915 };
916
917 m_vk.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
918 vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
919 0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL);
920 }
921
draw(vk::VkCommandBuffer cmdBuffer,vk::VkBuffer vertexBuffer,vk::VkBuffer instancedVertexBuffer,de::SharedPtr<Buffer> indexBuffer,de::SharedPtr<Buffer> indirectBuffer,deUint32 firstInstance,deUint32 instanceCount)922 void InstancedDrawInstance::draw(vk::VkCommandBuffer cmdBuffer,
923 vk::VkBuffer vertexBuffer, vk::VkBuffer instancedVertexBuffer,
924 de::SharedPtr<Buffer> indexBuffer, de::SharedPtr<Buffer> indirectBuffer,
925 deUint32 firstInstance, deUint32 instanceCount)
926 {
927 if (m_params.function == TestParams::FUNCTION_DRAW_INDEXED || m_params.function == TestParams::FUNCTION_DRAW_INDEXED_INDIRECT)
928 m_vk.cmdBindIndexBuffer(cmdBuffer, indexBuffer->object(), 0, vk::VK_INDEX_TYPE_UINT32);
929
930 const vk::VkBuffer vertexBuffers[] { vertexBuffer, instancedVertexBuffer };
931 const vk::VkDeviceSize vertexBufferOffsets[] { 0, 0 };
932
933 m_vk.cmdBindVertexBuffers(cmdBuffer, 0, DE_LENGTH_OF_ARRAY(vertexBuffers), vertexBuffers, vertexBufferOffsets);
934
935 const float pushConstants[] = { (float)firstInstance, (float)instanceCount };
936 m_vk.cmdPushConstants(cmdBuffer, *m_pipelineLayout, vk::VK_SHADER_STAGE_VERTEX_BIT, 0u, (deUint32)sizeof(pushConstants), pushConstants);
937 m_vk.cmdBindPipeline(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
938
939 if (m_params.dynamicState)
940 {
941 vk::VkVertexInputBindingDescription2EXT vertexBindingDescription[2]
942 {
943 {
944 vk::VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT,
945 0,
946 0u,
947 (deUint32)sizeof(VertexPositionAndColor),
948 vk::VK_VERTEX_INPUT_RATE_VERTEX,
949 1
950 },
951 {
952 vk::VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT,
953 0,
954 1u,
955 (deUint32)sizeof(tcu::Vec4),
956 vk::VK_VERTEX_INPUT_RATE_INSTANCE,
957 m_params.attribDivisor
958 },
959
960 };
961 vk::VkVertexInputAttributeDescription2EXT vertexAttributeDescription[3]
962 {
963 {
964 vk::VK_STRUCTURE_TYPE_VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT,
965 0,
966 0u,
967 0u,
968 vk::VK_FORMAT_R32G32B32A32_SFLOAT,
969 0u
970 },
971 {
972 vk::VK_STRUCTURE_TYPE_VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT,
973 0,
974 1u,
975 0u,
976 vk::VK_FORMAT_R32G32B32A32_SFLOAT,
977 (deUint32)sizeof(tcu::Vec4),
978 },
979 {
980 vk::VK_STRUCTURE_TYPE_VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT,
981 0,
982 2u,
983 1u,
984 vk::VK_FORMAT_R32G32B32A32_SFLOAT,
985 0,
986 }
987 };
988
989 m_vk.cmdSetVertexInputEXT(cmdBuffer, 2, vertexBindingDescription, 3, vertexAttributeDescription);
990 }
991
992 switch (m_params.function)
993 {
994 case TestParams::FUNCTION_DRAW:
995 m_vk.cmdDraw(cmdBuffer, (deUint32)m_data.size(), instanceCount, 0u, firstInstance);
996 break;
997
998 case TestParams::FUNCTION_DRAW_INDEXED:
999 m_vk.cmdDrawIndexed(cmdBuffer, (deUint32)m_indexes.size(), instanceCount, 0u, 0u, firstInstance);
1000 break;
1001
1002 case TestParams::FUNCTION_DRAW_INDIRECT:
1003 m_vk.cmdDrawIndirect(cmdBuffer, indirectBuffer->object(), 0, 1u, 0u);
1004 break;
1005
1006 case TestParams::FUNCTION_DRAW_INDEXED_INDIRECT:
1007 m_vk.cmdDrawIndexedIndirect(cmdBuffer, indirectBuffer->object(), 0, 1u, 0u);
1008 break;
1009
1010 default:
1011 DE_ASSERT(false);
1012 }
1013 }
1014
1015 #ifndef CTS_USES_VULKANSC
beginSecondaryCmdBuffer(vk::VkRenderingFlagsKHR renderingFlags)1016 void InstancedDrawInstance::beginSecondaryCmdBuffer(vk::VkRenderingFlagsKHR renderingFlags)
1017 {
1018 const vk::VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo
1019 {
1020 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR, // VkStructureType sType;
1021 DE_NULL, // const void* pNext;
1022 renderingFlags, // VkRenderingFlagsKHR flags;
1023 (m_params.testMultiview) ? 3u : 0u, // uint32_t viewMask;
1024 1u, // uint32_t colorAttachmentCount;
1025 &m_colorAttachmentFormat, // const VkFormat* pColorAttachmentFormats;
1026 vk::VK_FORMAT_UNDEFINED, // VkFormat depthAttachmentFormat;
1027 vk::VK_FORMAT_UNDEFINED, // VkFormat stencilAttachmentFormat;
1028 vk::VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
1029 };
1030
1031 const vk::VkCommandBufferInheritanceInfo bufferInheritanceInfo
1032 {
1033 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, // VkStructureType sType;
1034 &inheritanceRenderingInfo, // const void* pNext;
1035 DE_NULL, // VkRenderPass renderPass;
1036 0u, // deUint32 subpass;
1037 DE_NULL, // VkFramebuffer framebuffer;
1038 VK_FALSE, // VkBool32 occlusionQueryEnable;
1039 (vk::VkQueryControlFlags)0u, // VkQueryControlFlags queryFlags;
1040 (vk::VkQueryPipelineStatisticFlags)0u // VkQueryPipelineStatisticFlags pipelineStatistics;
1041 };
1042
1043 vk::VkCommandBufferUsageFlags usageFlags = vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
1044 if (!m_params.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
1045 usageFlags |= vk::VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
1046
1047 const vk::VkCommandBufferBeginInfo commandBufBeginParams
1048 {
1049 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
1050 DE_NULL, // const void* pNext;
1051 usageFlags, // VkCommandBufferUsageFlags flags;
1052 &bufferInheritanceInfo
1053 };
1054
1055 VK_CHECK(m_vk.beginCommandBuffer(*m_secCmdBuffer, &commandBufBeginParams));
1056 }
1057 #endif // CTS_USES_VULKANSC
1058
1059 } // anonymus
1060
InstancedTests(tcu::TestContext & testCtx,const SharedGroupParams groupParams)1061 InstancedTests::InstancedTests(tcu::TestContext& testCtx, const SharedGroupParams groupParams)
1062 : TestCaseGroup (testCtx, "instanced", "Instanced drawing tests")
1063 , m_groupParams (groupParams)
1064 {
1065 static const vk::VkPrimitiveTopology topologies[] =
1066 {
1067 vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST,
1068 vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST,
1069 vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,
1070 vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
1071 vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
1072 vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,
1073 };
1074 static const TestParams::DrawFunction functions[] =
1075 {
1076 TestParams::FUNCTION_DRAW,
1077 TestParams::FUNCTION_DRAW_INDEXED,
1078 TestParams::FUNCTION_DRAW_INDIRECT,
1079 TestParams::FUNCTION_DRAW_INDEXED_INDIRECT,
1080 };
1081
1082 static const deBool multiviews[] = { DE_FALSE, DE_TRUE };
1083
1084 static const deUint32 divisors[] = { 0, 1, 2, 4, 20 };
1085 for (int dynState = 0; dynState < 2; dynState++)
1086 {
1087 for (int topologyNdx = 0; topologyNdx < DE_LENGTH_OF_ARRAY(topologies); topologyNdx++)
1088 {
1089 // reduce number of tests for dynamic rendering cases where secondary command buffer is used
1090 if (groupParams->useSecondaryCmdBuffer && (topologyNdx % 2u))
1091 continue;
1092
1093 for (int functionNdx = 0; functionNdx < DE_LENGTH_OF_ARRAY(functions); functionNdx++)
1094 {
1095 for (int testAttribDivisor = 0; testAttribDivisor < 2; testAttribDivisor++)
1096 {
1097 for (int divisorNdx = 0; divisorNdx < DE_LENGTH_OF_ARRAY(divisors); divisorNdx++)
1098 {
1099 // reduce number of tests for dynamic rendering cases where secondary command buffer is used
1100 if (groupParams->useSecondaryCmdBuffer && (divisorNdx % 2u))
1101 continue;
1102
1103 for (int multiviewNdx = 0; multiviewNdx < DE_LENGTH_OF_ARRAY(multiviews); multiviewNdx++)
1104 {
1105 // If we don't have VK_EXT_vertex_attribute_divisor, we only get a divisor or 1.
1106 if (!testAttribDivisor && divisors[divisorNdx] != 1)
1107 continue;
1108
1109 TestParams param
1110 {
1111 functions[functionNdx], // DrawFunction function;
1112 topologies[topologyNdx], // vk::VkPrimitiveTopology topology;
1113 groupParams, // const SharedGroupParams groupParams;
1114 testAttribDivisor ? DE_TRUE : DE_FALSE, // deBool testAttribDivisor;
1115 divisors[divisorNdx], // deUint32 attribDivisor;
1116 multiviews[multiviewNdx], // deBool testMultiview;
1117 dynState == 0 ? false : true // deBool dynamicState;
1118 };
1119
1120 // Add multiview tests only when vertex attribute divisor is enabled.
1121 if (param.testMultiview && !testAttribDivisor)
1122 continue;
1123
1124 std::string testName = de::toString(param);
1125
1126 addChild(new InstancedDrawCase(m_testCtx, de::toLower(testName), "Instanced drawing test", param));
1127 }
1128 }
1129 }
1130 }
1131 }
1132 }
1133 }
1134
~InstancedTests()1135 InstancedTests::~InstancedTests() {}
1136
1137 } // DrawTests
1138 } // vkt
1139