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