1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2016 The Khronos Group Inc.
6 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 * \brief Instanced Draw Tests
23 *//*--------------------------------------------------------------------*/
25 #include "vktDrawInstancedTests.hpp"
27 #include "deSharedPtr.hpp"
28 #include "rrRenderer.hpp"
29 #include "tcuImageCompare.hpp"
30 #include "tcuRGBA.hpp"
31 #include "tcuTextureUtil.hpp"
32 #include "vkImageUtil.hpp"
33 #include "vkPrograms.hpp"
34 #include "vktDrawBufferObjectUtil.hpp"
35 #include "vktDrawCreateInfoUtil.hpp"
36 #include "vktDrawImageObjectUtil.hpp"
37 #include "vktDrawTestCaseUtil.hpp"
46 static const int QUAD_GRID_SIZE = 8;
47 static const int WIDTH = 128;
48 static const int HEIGHT = 128;
55 FUNCTION_DRAW_INDEXED,
56 FUNCTION_DRAW_INDIRECT,
57 FUNCTION_DRAW_INDEXED_INDIRECT,
62 DrawFunction function;
63 vk::VkPrimitiveTopology topology;
66 struct VertexPositionAndColor
68 VertexPositionAndColor (tcu::Vec4 position_, tcu::Vec4 color_)
69 : position (position_)
78 std::ostream & operator<<(std::ostream & str, TestParams const & v)
80 std::ostringstream string;
83 case TestParams::FUNCTION_DRAW:
86 case TestParams::FUNCTION_DRAW_INDEXED:
87 string << "draw_indexed";
89 case TestParams::FUNCTION_DRAW_INDIRECT:
90 string << "draw_indirect";
92 case TestParams::FUNCTION_DRAW_INDEXED_INDIRECT:
93 string << "draw_indexed_indirect";
99 string << "_" << de::toString(v.topology);
100 return str << string.str();
103 rr::PrimitiveType mapVkPrimitiveTopology (vk::VkPrimitiveTopology primitiveTopology)
105 switch (primitiveTopology)
107 case vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST: return rr::PRIMITIVETYPE_POINTS;
108 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST: return rr::PRIMITIVETYPE_LINES;
109 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP: return rr::PRIMITIVETYPE_LINE_STRIP;
110 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST: return rr::PRIMITIVETYPE_TRIANGLES;
111 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN: return rr::PRIMITIVETYPE_TRIANGLE_FAN;
112 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP: return rr::PRIMITIVETYPE_TRIANGLE_STRIP;
113 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY: return rr::PRIMITIVETYPE_LINES_ADJACENCY;
114 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY: return rr::PRIMITIVETYPE_LINE_STRIP_ADJACENCY;
115 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY: return rr::PRIMITIVETYPE_TRIANGLES_ADJACENCY;
116 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY: return rr::PRIMITIVETYPE_TRIANGLE_STRIP_ADJACENCY;
120 return rr::PRIMITIVETYPE_LAST;
124 de::SharedPtr<Buffer> createAndUploadBuffer(const std::vector<T> data, const vk::DeviceInterface& vk, const Context& context)
126 const vk::VkDeviceSize dataSize = data.size() * sizeof(T);
127 de::SharedPtr<Buffer> vertexBuffer = Buffer::createAndAlloc(vk, context.getDevice(),
128 BufferCreateInfo(dataSize, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT),
129 context.getDefaultAllocator(),
130 vk::MemoryRequirement::HostVisible);
132 deUint8* ptr = reinterpret_cast<deUint8*>(vertexBuffer->getBoundMemory().getHostPtr());
134 deMemcpy(ptr, &data[0], static_cast<size_t>(dataSize));
136 vk::flushMappedMemoryRange(vk, context.getDevice(),
137 vertexBuffer->getBoundMemory().getMemory(),
138 vertexBuffer->getBoundMemory().getOffset(),
143 class TestVertShader : public rr::VertexShader
146 TestVertShader (int numInstances, int firstInstance)
147 : rr::VertexShader (3, 1)
148 , m_numInstances (numInstances)
149 , m_firstInstance (firstInstance)
151 m_inputs[0].type = rr::GENERICVECTYPE_FLOAT;
152 m_inputs[1].type = rr::GENERICVECTYPE_FLOAT;
153 m_inputs[2].type = rr::GENERICVECTYPE_FLOAT;
154 m_outputs[0].type = rr::GENERICVECTYPE_FLOAT;
157 void shadeVertices (const rr::VertexAttrib* inputs,
158 rr::VertexPacket* const* packets,
159 const int numPackets) const
161 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
163 const int instanceNdx = packets[packetNdx]->instanceNdx + m_firstInstance;
164 const tcu::Vec4 position = rr::readVertexAttribFloat(inputs[0], instanceNdx, packets[packetNdx]->vertexNdx);
165 const tcu::Vec4 color = rr::readVertexAttribFloat(inputs[1], instanceNdx, packets[packetNdx]->vertexNdx);
166 const tcu::Vec4 color2 = rr::readVertexAttribFloat(inputs[2], instanceNdx, packets[packetNdx]->vertexNdx);
167 packets[packetNdx]->position = position + tcu::Vec4((float)(packets[packetNdx]->instanceNdx * 2.0 / m_numInstances), 0.0, 0.0, 0.0);
168 packets[packetNdx]->outputs[0] = color + tcu::Vec4((float)instanceNdx / (float)m_numInstances, 0.0, 0.0, 1.0) + color2;
173 const int m_numInstances;
174 const int m_firstInstance;
177 class TestFragShader : public rr::FragmentShader
180 TestFragShader (void)
181 : rr::FragmentShader(1, 1)
183 m_inputs[0].type = rr::GENERICVECTYPE_FLOAT;
184 m_outputs[0].type = rr::GENERICVECTYPE_FLOAT;
187 void shadeFragments (rr::FragmentPacket* packets,
188 const int numPackets,
189 const rr::FragmentShadingContext& context) const
191 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
193 rr::FragmentPacket& packet = packets[packetNdx];
194 for (int fragNdx = 0; fragNdx < rr::NUM_FRAGMENTS_PER_PACKET; ++fragNdx)
196 const tcu::Vec4 color = rr::readVarying<float>(packet, context, 0, fragNdx);
197 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
203 class InstancedDrawInstance : public TestInstance
206 InstancedDrawInstance (Context& context, TestParams params);
207 virtual tcu::TestStatus iterate (void);
210 void prepareVertexData (int instanceCount, int firstInstance);
212 const TestParams m_params;
213 const vk::DeviceInterface& m_vk;
215 vk::VkFormat m_colorAttachmentFormat;
217 vk::Move<vk::VkPipeline> m_pipeline;
218 vk::Move<vk::VkPipelineLayout> m_pipelineLayout;
220 de::SharedPtr<Image> m_colorTargetImage;
221 vk::Move<vk::VkImageView> m_colorTargetView;
223 PipelineCreateInfo::VertexInputState m_vertexInputState;
225 vk::Move<vk::VkCommandPool> m_cmdPool;
226 vk::Move<vk::VkCommandBuffer> m_cmdBuffer;
228 vk::Move<vk::VkFramebuffer> m_framebuffer;
229 vk::Move<vk::VkRenderPass> m_renderPass;
232 std::vector<VertexPositionAndColor> m_data;
233 std::vector<deUint32> m_indexes;
234 std::vector<tcu::Vec4> m_instancedColor;
237 class InstancedDrawCase : public TestCase
240 InstancedDrawCase (tcu::TestContext& testCtx,
241 const std::string& name,
242 const std::string& desc,
244 : TestCase (testCtx, name, desc)
247 m_vertexShader = "#version 430\n"
248 "layout(location = 0) in vec4 in_position;\n"
249 "layout(location = 1) in vec4 in_color;\n"
250 "layout(location = 2) in vec4 in_color_2;\n"
251 "layout(push_constant) uniform TestParams {\n"
252 " float firstInstance;\n"
253 " float instanceCount;\n"
255 "layout(location = 0) out vec4 out_color;\n"
256 "out gl_PerVertex {\n"
257 " vec4 gl_Position;\n"
258 " float gl_PointSize;\n"
261 " gl_PointSize = 1.0;\n"
262 " gl_Position = in_position + vec4(float(gl_InstanceIndex - params.firstInstance) * 2.0 / params.instanceCount, 0.0, 0.0, 0.0);\n"
263 " out_color = in_color + vec4(float(gl_InstanceIndex) / params.instanceCount, 0.0, 0.0, 1.0) + in_color_2;\n"
266 m_fragmentShader = "#version 430\n"
267 "layout(location = 0) in vec4 in_color;\n"
268 "layout(location = 0) out vec4 out_color;\n"
271 " out_color = in_color;\n"
275 TestInstance* createInstance (Context& context) const
277 return new InstancedDrawInstance(context, m_params);
280 virtual void initPrograms (vk::SourceCollections& programCollection) const
282 programCollection.glslSources.add("InstancedDrawVert") << glu::VertexSource(m_vertexShader);
283 programCollection.glslSources.add("InstancedDrawFrag") << glu::FragmentSource(m_fragmentShader);
287 const TestParams m_params;
288 std::string m_vertexShader;
289 std::string m_fragmentShader;
292 InstancedDrawInstance::InstancedDrawInstance(Context &context, TestParams params)
293 : TestInstance (context)
295 , m_vk (context.getDeviceInterface())
296 , m_colorAttachmentFormat (vk::VK_FORMAT_R8G8B8A8_UNORM)
298 const vk::VkDevice device = m_context.getDevice();
299 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
301 const vk::VkPushConstantRange pushConstantRange = {
302 vk::VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlags stageFlags;
303 0u, // uint32_t offset;
304 (deUint32)sizeof(float) * 2, // uint32_t size;
307 const PipelineLayoutCreateInfo pipelineLayoutCreateInfo(0, DE_NULL, 1, &pushConstantRange);
308 m_pipelineLayout = vk::createPipelineLayout(m_vk, device, &pipelineLayoutCreateInfo);
310 const vk::VkExtent3D targetImageExtent = { WIDTH, HEIGHT, 1 };
311 const ImageCreateInfo targetImageCreateInfo(vk::VK_IMAGE_TYPE_2D, m_colorAttachmentFormat, targetImageExtent, 1, 1, vk::VK_SAMPLE_COUNT_1_BIT,
312 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);
314 m_colorTargetImage = Image::createAndAlloc(m_vk, device, targetImageCreateInfo, m_context.getDefaultAllocator());
316 const ImageViewCreateInfo colorTargetViewInfo(m_colorTargetImage->object(), vk::VK_IMAGE_VIEW_TYPE_2D, m_colorAttachmentFormat);
317 m_colorTargetView = vk::createImageView(m_vk, device, &colorTargetViewInfo);
319 RenderPassCreateInfo renderPassCreateInfo;
320 renderPassCreateInfo.addAttachment(AttachmentDescription(m_colorAttachmentFormat,
321 vk::VK_SAMPLE_COUNT_1_BIT,
322 vk::VK_ATTACHMENT_LOAD_OP_LOAD,
323 vk::VK_ATTACHMENT_STORE_OP_STORE,
324 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,
325 vk::VK_ATTACHMENT_STORE_OP_STORE,
326 vk::VK_IMAGE_LAYOUT_GENERAL,
327 vk::VK_IMAGE_LAYOUT_GENERAL));
329 const vk::VkAttachmentReference colorAttachmentReference =
332 vk::VK_IMAGE_LAYOUT_GENERAL
335 renderPassCreateInfo.addSubpass(SubpassDescription(vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
340 &colorAttachmentReference,
342 AttachmentReference(),
346 m_renderPass = vk::createRenderPass(m_vk, device, &renderPassCreateInfo);
348 std::vector<vk::VkImageView> colorAttachments(1);
349 colorAttachments[0] = *m_colorTargetView;
351 const FramebufferCreateInfo framebufferCreateInfo(*m_renderPass, colorAttachments, WIDTH, HEIGHT, 1);
353 m_framebuffer = vk::createFramebuffer(m_vk, device, &framebufferCreateInfo);
355 const vk::VkVertexInputBindingDescription vertexInputBindingDescription[2] =
359 (deUint32)sizeof(VertexPositionAndColor),
360 vk::VK_VERTEX_INPUT_RATE_VERTEX,
364 (deUint32)sizeof(tcu::Vec4),
365 vk::VK_VERTEX_INPUT_RATE_INSTANCE,
369 const vk::VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] =
374 vk::VK_FORMAT_R32G32B32A32_SFLOAT,
380 vk::VK_FORMAT_R32G32B32A32_SFLOAT,
381 (deUint32)sizeof(tcu::Vec4),
386 vk::VK_FORMAT_R32G32B32A32_SFLOAT,
391 m_vertexInputState = PipelineCreateInfo::VertexInputState(2,
392 vertexInputBindingDescription,
393 DE_LENGTH_OF_ARRAY(vertexInputAttributeDescriptions),
394 vertexInputAttributeDescriptions);
396 const CmdPoolCreateInfo cmdPoolCreateInfo(queueFamilyIndex);
397 m_cmdPool = vk::createCommandPool(m_vk, device, &cmdPoolCreateInfo);
399 m_cmdBuffer = vk::allocateCommandBuffer(m_vk, device, *m_cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
401 const vk::Unique<vk::VkShaderModule> vs(createShaderModule(m_vk, device, m_context.getBinaryCollection().get("InstancedDrawVert"), 0));
402 const vk::Unique<vk::VkShaderModule> fs(createShaderModule(m_vk, device, m_context.getBinaryCollection().get("InstancedDrawFrag"), 0));
404 const PipelineCreateInfo::ColorBlendState::Attachment vkCbAttachmentState;
406 vk::VkViewport viewport;
409 viewport.width = static_cast<float>(WIDTH);
410 viewport.height = static_cast<float>(HEIGHT);
411 viewport.minDepth = 0.0f;
412 viewport.maxDepth = 1.0f;
414 vk::VkRect2D scissor;
415 scissor.offset.x = 0;
416 scissor.offset.y = 0;
417 scissor.extent.width = WIDTH;
418 scissor.extent.height = HEIGHT;
420 PipelineCreateInfo pipelineCreateInfo(*m_pipelineLayout, *m_renderPass, 0, 0);
421 pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vs, "main", vk::VK_SHADER_STAGE_VERTEX_BIT));
422 pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*fs, "main", vk::VK_SHADER_STAGE_FRAGMENT_BIT));
423 pipelineCreateInfo.addState(PipelineCreateInfo::VertexInputState(m_vertexInputState));
424 pipelineCreateInfo.addState(PipelineCreateInfo::InputAssemblerState(m_params.topology));
425 pipelineCreateInfo.addState(PipelineCreateInfo::ColorBlendState(1, &vkCbAttachmentState));
426 pipelineCreateInfo.addState(PipelineCreateInfo::ViewportState(1, std::vector<vk::VkViewport>(1, viewport), std::vector<vk::VkRect2D>(1, scissor)));
427 pipelineCreateInfo.addState(PipelineCreateInfo::DepthStencilState());
428 pipelineCreateInfo.addState(PipelineCreateInfo::RasterizerState());
429 pipelineCreateInfo.addState(PipelineCreateInfo::MultiSampleState());
431 m_pipeline = vk::createGraphicsPipeline(m_vk, device, DE_NULL, &pipelineCreateInfo);
434 tcu::TestStatus InstancedDrawInstance::iterate()
436 const vk::VkQueue queue = m_context.getUniversalQueue();
437 static const deUint32 instanceCounts[] = { 1, 2, 4, 20 };
438 static const deUint32 firstInstanceIndices[] = { 0, 1, 3, 4, 20 };
440 qpTestResult res = QP_TEST_RESULT_PASS;
442 const vk::VkClearColorValue clearColor = { { 0.0f, 0.0f, 0.0f, 1.0f } };
443 const CmdBufferBeginInfo beginInfo;
444 int firstInstanceIndicesCount = 1;
446 // Require 'drawIndirectFirstInstance' feature to run non-zero firstInstance indirect draw tests.
447 if (m_context.getDeviceFeatures().drawIndirectFirstInstance)
448 firstInstanceIndicesCount = DE_LENGTH_OF_ARRAY(firstInstanceIndices);
450 for (int instanceCountNdx = 0; instanceCountNdx < DE_LENGTH_OF_ARRAY(instanceCounts); instanceCountNdx++)
452 const deUint32 instanceCount = instanceCounts[instanceCountNdx];
453 for (int firstInstanceIndexNdx = 0; firstInstanceIndexNdx < firstInstanceIndicesCount; firstInstanceIndexNdx++)
455 const deUint32 firstInstance = firstInstanceIndices[firstInstanceIndexNdx];
457 prepareVertexData(instanceCount, firstInstance);
458 const de::SharedPtr<Buffer> vertexBuffer = createAndUploadBuffer(m_data, m_vk, m_context);
459 const de::SharedPtr<Buffer> instancedVertexBuffer = createAndUploadBuffer(m_instancedColor, m_vk, m_context);
460 de::SharedPtr<Buffer> indexBuffer;
461 de::SharedPtr<Buffer> indirectBuffer;
462 m_vk.beginCommandBuffer(*m_cmdBuffer, &beginInfo);
464 initialTransitionColor2DImage(m_vk, *m_cmdBuffer, m_colorTargetImage->object(), vk::VK_IMAGE_LAYOUT_GENERAL);
466 const ImageSubresourceRange subresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT);
467 m_vk.cmdClearColorImage(*m_cmdBuffer, m_colorTargetImage->object(),
468 vk::VK_IMAGE_LAYOUT_GENERAL, &clearColor, 1, &subresourceRange);
470 const vk::VkMemoryBarrier memBarrier =
472 vk::VK_STRUCTURE_TYPE_MEMORY_BARRIER,
474 vk::VK_ACCESS_TRANSFER_WRITE_BIT,
475 vk::VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
478 m_vk.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
479 vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
480 0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL);
482 const vk::VkRect2D renderArea = { { 0, 0 }, { WIDTH, HEIGHT } };
483 const RenderPassBeginInfo renderPassBegin(*m_renderPass, *m_framebuffer, renderArea);
485 m_vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBegin, vk::VK_SUBPASS_CONTENTS_INLINE);
487 if (m_params.function == TestParams::FUNCTION_DRAW_INDEXED || m_params.function == TestParams::FUNCTION_DRAW_INDEXED_INDIRECT)
489 indexBuffer = createAndUploadBuffer(m_indexes, m_vk, m_context);
490 m_vk.cmdBindIndexBuffer(*m_cmdBuffer, indexBuffer->object(), 0, vk::VK_INDEX_TYPE_UINT32);
493 const vk::VkBuffer vertexBuffers[] =
495 vertexBuffer->object(),
496 instancedVertexBuffer->object(),
499 const vk::VkDeviceSize vertexBufferOffsets[] =
501 0, // vertexBufferOffset
502 0, // instancedVertexBufferOffset
505 m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, DE_LENGTH_OF_ARRAY(vertexBuffers), vertexBuffers, vertexBufferOffsets);
507 const float pushConstants[] = { (float)firstInstance, (float)instanceCount };
508 m_vk.cmdPushConstants(*m_cmdBuffer, *m_pipelineLayout, vk::VK_SHADER_STAGE_VERTEX_BIT, 0u, (deUint32)sizeof(pushConstants), pushConstants);
510 m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
512 switch (m_params.function)
514 case TestParams::FUNCTION_DRAW:
515 m_vk.cmdDraw(*m_cmdBuffer, (deUint32)m_data.size(), instanceCount, 0u, firstInstance);
518 case TestParams::FUNCTION_DRAW_INDEXED:
519 m_vk.cmdDrawIndexed(*m_cmdBuffer, (deUint32)m_indexes.size(), instanceCount, 0u, 0u, firstInstance);
522 case TestParams::FUNCTION_DRAW_INDIRECT:
524 vk::VkDrawIndirectCommand drawCommand =
526 (deUint32)m_data.size(), // uint32_t vertexCount;
527 instanceCount, // uint32_t instanceCount;
528 0u, // uint32_t firstVertex;
529 firstInstance, // uint32_t firstInstance;
531 std::vector<vk::VkDrawIndirectCommand> drawCommands;
532 drawCommands.push_back(drawCommand);
533 indirectBuffer = createAndUploadBuffer(drawCommands, m_vk, m_context);
535 m_vk.cmdDrawIndirect(*m_cmdBuffer, indirectBuffer->object(), 0, 1u, 0u);
538 case TestParams::FUNCTION_DRAW_INDEXED_INDIRECT:
540 vk::VkDrawIndexedIndirectCommand drawCommand =
542 (deUint32)m_indexes.size(), // uint32_t indexCount;
543 instanceCount, // uint32_t instanceCount;
544 0u, // uint32_t firstIndex;
545 0, // int32_t vertexOffset;
546 firstInstance, // uint32_t firstInstance;
548 std::vector<vk::VkDrawIndexedIndirectCommand> drawCommands;
549 drawCommands.push_back(drawCommand);
550 indirectBuffer = createAndUploadBuffer(drawCommands, m_vk, m_context);
552 m_vk.cmdDrawIndexedIndirect(*m_cmdBuffer, indirectBuffer->object(), 0, 1u, 0u);
559 m_vk.cmdEndRenderPass(*m_cmdBuffer);
560 m_vk.endCommandBuffer(*m_cmdBuffer);
562 vk::VkSubmitInfo submitInfo =
564 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
565 DE_NULL, // const void* pNext;
566 0, // deUint32 waitSemaphoreCount;
567 DE_NULL, // const VkSemaphore* pWaitSemaphores;
568 (const vk::VkPipelineStageFlags*)DE_NULL, // const VkPipelineStageFlags* pWaitDstStageMask;
569 1, // deUint32 commandBufferCount;
570 &m_cmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
571 0, // deUint32 signalSemaphoreCount;
572 DE_NULL // const VkSemaphore* pSignalSemaphores;
574 VK_CHECK(m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL));
576 VK_CHECK(m_vk.queueWaitIdle(queue));
578 // Reference rendering
579 std::vector<tcu::Vec4> vetrices;
580 std::vector<tcu::Vec4> colors;
582 for (std::vector<VertexPositionAndColor>::const_iterator it = m_data.begin(); it != m_data.end(); ++it)
584 vetrices.push_back(it->position);
585 colors.push_back(it->color);
588 tcu::TextureLevel refImage (vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5 + WIDTH), (int)(0.5 + HEIGHT));
590 tcu::clear(refImage.getAccess(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
592 const TestVertShader vertShader(instanceCount, firstInstance);
593 const TestFragShader fragShader;
594 const rr::Program program (&vertShader, &fragShader);
595 const rr::MultisamplePixelBufferAccess colorBuffer = rr::MultisamplePixelBufferAccess::fromSinglesampleAccess(refImage.getAccess());
596 const rr::RenderTarget renderTarget (colorBuffer);
597 const rr::RenderState renderState ((rr::ViewportState(colorBuffer)));
598 const rr::Renderer renderer;
600 const rr::VertexAttrib vertexAttribs[] =
602 rr::VertexAttrib(rr::VERTEXATTRIBTYPE_FLOAT, 4, sizeof(tcu::Vec4), 0, &vetrices[0]),
603 rr::VertexAttrib(rr::VERTEXATTRIBTYPE_FLOAT, 4, sizeof(tcu::Vec4), 0, &colors[0]),
604 rr::VertexAttrib(rr::VERTEXATTRIBTYPE_FLOAT, 4, sizeof(tcu::Vec4), 1, &m_instancedColor[0])
607 if (m_params.function == TestParams::FUNCTION_DRAW || m_params.function == TestParams::FUNCTION_DRAW_INDIRECT)
609 const rr::PrimitiveList primitives = rr::PrimitiveList(mapVkPrimitiveTopology(m_params.topology), (int)vetrices.size(), 0);
610 const rr::DrawCommand command(renderState, renderTarget, program, DE_LENGTH_OF_ARRAY(vertexAttribs), &vertexAttribs[0],
612 renderer.drawInstanced(command, instanceCount);
616 const rr::DrawIndices indicies(m_indexes.data());
618 const rr::PrimitiveList primitives = rr::PrimitiveList(mapVkPrimitiveTopology(m_params.topology), (int)m_indexes.size(), indicies);
619 const rr::DrawCommand command(renderState, renderTarget, program, DE_LENGTH_OF_ARRAY(vertexAttribs), &vertexAttribs[0],
621 renderer.drawInstanced(command, instanceCount);
624 const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
625 const tcu::ConstPixelBufferAccess renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
626 vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
628 tcu::TestLog &log = m_context.getTestContext().getLog();
630 std::ostringstream resultDesc;
631 resultDesc << "Image comparison result. Instance count: " << instanceCount << " first instance index: " << firstInstance;
633 if (m_params.topology == vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST)
635 const bool ok = tcu::intThresholdPositionDeviationCompare(
636 log, "Result", resultDesc.str().c_str(), refImage.getAccess(), renderedFrame,
637 tcu::UVec4(4u), // color threshold
638 tcu::IVec3(1, 1, 0), // position deviation tolerance
639 true, // don't check the pixels at the boundary
640 tcu::COMPARE_LOG_RESULT);
643 res = QP_TEST_RESULT_FAIL;
647 if (!tcu::fuzzyCompare(log, "Result", resultDesc.str().c_str(), refImage.getAccess(), renderedFrame, 0.05f, tcu::COMPARE_LOG_RESULT))
648 res = QP_TEST_RESULT_FAIL;
652 return tcu::TestStatus(res, qpGetTestResultName(res));
655 void InstancedDrawInstance::prepareVertexData(int instanceCount, int firstInstance)
659 m_instancedColor.clear();
661 if (m_params.function == TestParams::FUNCTION_DRAW || m_params.function == TestParams::FUNCTION_DRAW_INDIRECT)
663 for (int y = 0; y < QUAD_GRID_SIZE; y++)
665 for (int x = 0; x < QUAD_GRID_SIZE; x++)
667 const float fx0 = -1.0f + (float)(x+0) / (float)QUAD_GRID_SIZE * 2.0f / (float)instanceCount;
668 const float fx1 = -1.0f + (float)(x+1) / (float)QUAD_GRID_SIZE * 2.0f / (float)instanceCount;
669 const float fy0 = -1.0f + (float)(y+0) / (float)QUAD_GRID_SIZE * 2.0f;
670 const float fy1 = -1.0f + (float)(y+1) / (float)QUAD_GRID_SIZE * 2.0f;
672 // Vertices of a quad's lower-left triangle: (fx0, fy0), (fx1, fy0) and (fx0, fy1)
673 m_data.push_back(VertexPositionAndColor(tcu::Vec4(fx0, fy0, 1.0f, 1.0f), tcu::RGBA::blue().toVec()));
674 m_data.push_back(VertexPositionAndColor(tcu::Vec4(fx1, fy0, 1.0f, 1.0f), tcu::RGBA::blue().toVec()));
675 m_data.push_back(VertexPositionAndColor(tcu::Vec4(fx0, fy1, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
677 // Vertices of a quad's upper-right triangle: (fx1, fy1), (fx0, fy1) and (fx1, fy0)
678 m_data.push_back(VertexPositionAndColor(tcu::Vec4(fx1, fy1, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
679 m_data.push_back(VertexPositionAndColor(tcu::Vec4(fx0, fy1, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
680 m_data.push_back(VertexPositionAndColor(tcu::Vec4(fx1, fy0, 1.0f, 1.0f), tcu::RGBA::blue().toVec()));
686 for (int y = 0; y < QUAD_GRID_SIZE + 1; y++)
688 for (int x = 0; x < QUAD_GRID_SIZE + 1; x++)
690 const float fx = -1.0f + (float)x / (float)QUAD_GRID_SIZE * 2.0f / (float)instanceCount;
691 const float fy = -1.0f + (float)y / (float)QUAD_GRID_SIZE * 2.0f;
693 m_data.push_back(VertexPositionAndColor(tcu::Vec4(fx, fy, 1.0f, 1.0f),
694 (y % 2 ? tcu::RGBA::blue().toVec() : tcu::RGBA::green().toVec())));
698 for (int y = 0; y < QUAD_GRID_SIZE; y++)
700 for (int x = 0; x < QUAD_GRID_SIZE; x++)
702 const int ndx00 = y*(QUAD_GRID_SIZE + 1) + x;
703 const int ndx10 = y*(QUAD_GRID_SIZE + 1) + x + 1;
704 const int ndx01 = (y + 1)*(QUAD_GRID_SIZE + 1) + x;
705 const int ndx11 = (y + 1)*(QUAD_GRID_SIZE + 1) + x + 1;
707 // Lower-left triangle of a quad.
708 m_indexes.push_back((deUint16)ndx00);
709 m_indexes.push_back((deUint16)ndx10);
710 m_indexes.push_back((deUint16)ndx01);
712 // Upper-right triangle of a quad.
713 m_indexes.push_back((deUint16)ndx11);
714 m_indexes.push_back((deUint16)ndx01);
715 m_indexes.push_back((deUint16)ndx10);
720 for (int i = 0; i < instanceCount + firstInstance; i++)
722 m_instancedColor.push_back(tcu::Vec4(0.0, (float)(1.0 - i * 1.0 / (instanceCount + firstInstance)) / 2, 0.0, 1.0));
728 InstancedTests::InstancedTests(tcu::TestContext& testCtx)
729 : TestCaseGroup (testCtx, "instanced", "Instanced drawing tests")
731 static const vk::VkPrimitiveTopology topologies[] =
733 vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST,
734 vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST,
735 vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,
736 vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
737 vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
738 vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,
740 static const TestParams::DrawFunction functions[] =
742 TestParams::FUNCTION_DRAW,
743 TestParams::FUNCTION_DRAW_INDEXED,
744 TestParams::FUNCTION_DRAW_INDIRECT,
745 TestParams::FUNCTION_DRAW_INDEXED_INDIRECT,
748 for (int topologyNdx = 0; topologyNdx < DE_LENGTH_OF_ARRAY(topologies); topologyNdx++)
750 for (int functionNdx = 0; functionNdx < DE_LENGTH_OF_ARRAY(functions); functionNdx++)
753 param.function = functions[functionNdx];
754 param.topology = topologies[topologyNdx];
756 std::string testName = de::toString(param);
758 addChild(new InstancedDrawCase(m_testCtx, de::toLower(testName), "Instanced drawing test", param));
763 InstancedTests::~InstancedTests() {}