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 Simple Draw Tests
23 *//*--------------------------------------------------------------------*/
25 #include "vktBasicDrawTests.hpp"
27 #include "vktDrawBaseClass.hpp"
28 #include "vkQueryUtil.hpp"
29 #include "vktTestGroupUtil.hpp"
32 #include "deRandom.hpp"
35 #include "tcuTestCase.hpp"
36 #include "tcuRGBA.hpp"
37 #include "tcuTextureUtil.hpp"
38 #include "tcuImageCompare.hpp"
40 #include "rrRenderer.hpp"
51 static const deUint32 SEED = 0xc2a39fu;
52 static const deUint32 INDEX_LIMIT = 10000;
53 // To avoid too big and mostly empty structures
54 static const deUint32 OFFSET_LIMIT = 1000;
55 // Number of primitives to draw
56 static const deUint32 PRIMITIVE_COUNT[] = {1, 3, 17, 45};
60 DRAW_COMMAND_TYPE_DRAW,
61 DRAW_COMMAND_TYPE_DRAW_INDEXED,
62 DRAW_COMMAND_TYPE_DRAW_INDIRECT,
63 DRAW_COMMAND_TYPE_DRAW_INDEXED_INDIRECT,
65 DRAW_COMMAND_TYPE_DRAW_LAST
68 const char* getDrawCommandTypeName (DrawCommandType command)
72 case DRAW_COMMAND_TYPE_DRAW: return "draw";
73 case DRAW_COMMAND_TYPE_DRAW_INDEXED: return "draw_indexed";
74 case DRAW_COMMAND_TYPE_DRAW_INDIRECT: return "draw_indirect";
75 case DRAW_COMMAND_TYPE_DRAW_INDEXED_INDIRECT: return "draw_indexed_indirect";
76 default: DE_ASSERT(false);
81 rr::PrimitiveType mapVkPrimitiveTopology (vk::VkPrimitiveTopology primitiveTopology)
83 switch (primitiveTopology)
85 case vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST: return rr::PRIMITIVETYPE_POINTS;
86 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST: return rr::PRIMITIVETYPE_LINES;
87 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP: return rr::PRIMITIVETYPE_LINE_STRIP;
88 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST: return rr::PRIMITIVETYPE_TRIANGLES;
89 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN: return rr::PRIMITIVETYPE_TRIANGLE_FAN;
90 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP: return rr::PRIMITIVETYPE_TRIANGLE_STRIP;
91 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY: return rr::PRIMITIVETYPE_LINES_ADJACENCY;
92 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY: return rr::PRIMITIVETYPE_LINE_STRIP_ADJACENCY;
93 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY: return rr::PRIMITIVETYPE_TRIANGLES_ADJACENCY;
94 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY: return rr::PRIMITIVETYPE_TRIANGLE_STRIP_ADJACENCY;
98 return rr::PRIMITIVETYPE_LAST;
101 struct DrawParamsBase
103 std::vector<PositionColorVertex> vertices;
104 vk::VkPrimitiveTopology topology;
109 DrawParamsBase (const vk::VkPrimitiveTopology top)
114 struct IndexedParamsBase
116 std::vector<deUint32> indexes;
117 const vk::VkIndexType indexType;
119 IndexedParamsBase (const vk::VkIndexType indexT)
124 // Structs to store draw parameters
125 struct DrawParams : DrawParamsBase
127 // vkCmdDraw parameters is like a single VkDrawIndirectCommand
128 vk::VkDrawIndirectCommand params;
130 DrawParams (const vk::VkPrimitiveTopology top, const deUint32 vertexC, const deUint32 instanceC, const deUint32 firstV, const deUint32 firstI)
131 : DrawParamsBase (top)
133 params.vertexCount = vertexC;
134 params.instanceCount = instanceC;
135 params.firstVertex = firstV;
136 params.firstInstance = firstI;
140 struct DrawIndexedParams : DrawParamsBase, IndexedParamsBase
142 // vkCmdDrawIndexed parameters is like a single VkDrawIndexedIndirectCommand
143 vk::VkDrawIndexedIndirectCommand params;
145 DrawIndexedParams (const vk::VkPrimitiveTopology top, const vk::VkIndexType indexT, const deUint32 indexC, const deUint32 instanceC, const deUint32 firstIdx, const deInt32 vertexO, const deUint32 firstIns)
146 : DrawParamsBase (top)
147 , IndexedParamsBase (indexT)
149 params.indexCount = indexC;
150 params.instanceCount = instanceC;
151 params.firstIndex = firstIdx;
152 params.vertexOffset = vertexO;
153 params.firstInstance = firstIns;
157 struct DrawIndirectParams : DrawParamsBase
159 std::vector<vk::VkDrawIndirectCommand> commands;
161 DrawIndirectParams (const vk::VkPrimitiveTopology top)
162 : DrawParamsBase (top)
165 void addCommand (const deUint32 vertexC, const deUint32 instanceC, const deUint32 firstV, const deUint32 firstI)
167 vk::VkDrawIndirectCommand cmd;
168 cmd.vertexCount = vertexC;
169 cmd.instanceCount = instanceC;
170 cmd.firstVertex = firstV;
171 cmd.firstInstance = firstI;
173 commands.push_back(cmd);
177 struct DrawIndexedIndirectParams : DrawParamsBase, IndexedParamsBase
179 std::vector<vk::VkDrawIndexedIndirectCommand> commands;
181 DrawIndexedIndirectParams (const vk::VkPrimitiveTopology top, const vk::VkIndexType indexT)
182 : DrawParamsBase (top)
183 , IndexedParamsBase (indexT)
186 void addCommand (const deUint32 indexC, const deUint32 instanceC, const deUint32 firstIdx, const deInt32 vertexO, const deUint32 firstIns)
188 vk::VkDrawIndexedIndirectCommand cmd;
189 cmd.indexCount = indexC;
190 cmd.instanceCount = instanceC;
191 cmd.firstIndex = firstIdx;
192 cmd.vertexOffset = vertexO;
193 cmd.firstInstance = firstIns;
195 commands.push_back(cmd);
199 // Reference renderer shaders
200 class PassthruVertShader : public rr::VertexShader
203 PassthruVertShader (void)
204 : rr::VertexShader (2, 1)
206 m_inputs[0].type = rr::GENERICVECTYPE_FLOAT;
207 m_inputs[1].type = rr::GENERICVECTYPE_FLOAT;
208 m_outputs[0].type = rr::GENERICVECTYPE_FLOAT;
211 void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
213 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
215 packets[packetNdx]->position = rr::readVertexAttribFloat(inputs[0],
216 packets[packetNdx]->instanceNdx,
217 packets[packetNdx]->vertexNdx);
219 tcu::Vec4 color = rr::readVertexAttribFloat(inputs[1],
220 packets[packetNdx]->instanceNdx,
221 packets[packetNdx]->vertexNdx);
223 packets[packetNdx]->outputs[0] = color;
228 class PassthruFragShader : public rr::FragmentShader
231 PassthruFragShader (void)
232 : rr::FragmentShader(1, 1)
234 m_inputs[0].type = rr::GENERICVECTYPE_FLOAT;
235 m_outputs[0].type = rr::GENERICVECTYPE_FLOAT;
238 void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
240 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
242 rr::FragmentPacket& packet = packets[packetNdx];
243 for (deUint32 fragNdx = 0; fragNdx < rr::NUM_FRAGMENTS_PER_PACKET; ++fragNdx)
245 tcu::Vec4 color = rr::readVarying<float>(packet, context, 0, fragNdx);
246 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
252 inline bool imageCompare (tcu::TestLog& log, const tcu::ConstPixelBufferAccess& reference, const tcu::ConstPixelBufferAccess& result, const vk::VkPrimitiveTopology topology)
254 if (topology == vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST)
256 return tcu::intThresholdPositionDeviationCompare(
257 log, "Result", "Image comparison result", reference, result,
258 tcu::UVec4(4u), // color threshold
259 tcu::IVec3(1, 1, 0), // position deviation tolerance
260 true, // don't check the pixels at the boundary
261 tcu::COMPARE_LOG_RESULT);
264 return tcu::fuzzyCompare(log, "Result", "Image comparison result", reference, result, 0.05f, tcu::COMPARE_LOG_RESULT);
267 class DrawTestInstanceBase : public TestInstance
270 DrawTestInstanceBase (Context& context);
271 virtual ~DrawTestInstanceBase (void) = 0;
272 void initialize (const DrawParamsBase& data);
273 void initPipeline (const vk::VkDevice device);
274 void beginRenderPass (void);
276 // Specialize this function for each type
277 virtual tcu::TestStatus iterate (void) = 0;
279 // Specialize this function for each type
280 virtual void generateDrawData (void) = 0;
281 void generateRefImage (const tcu::PixelBufferAccess& access, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const;
283 DrawParamsBase m_data;
284 const vk::DeviceInterface& m_vk;
285 vk::Move<vk::VkPipeline> m_pipeline;
286 vk::Move<vk::VkPipelineLayout> m_pipelineLayout;
287 vk::VkFormat m_colorAttachmentFormat;
288 de::SharedPtr<Image> m_colorTargetImage;
289 vk::Move<vk::VkImageView> m_colorTargetView;
290 vk::Move<vk::VkRenderPass> m_renderPass;
291 vk::Move<vk::VkFramebuffer> m_framebuffer;
292 PipelineCreateInfo::VertexInputState m_vertexInputState;
293 de::SharedPtr<Buffer> m_vertexBuffer;
294 vk::Move<vk::VkCommandPool> m_cmdPool;
295 vk::Move<vk::VkCommandBuffer> m_cmdBuffer;
304 DrawTestInstanceBase::DrawTestInstanceBase (Context& context)
305 : vkt::TestInstance (context)
306 , m_vk (context.getDeviceInterface())
307 , m_colorAttachmentFormat (vk::VK_FORMAT_R8G8B8A8_UNORM)
311 DrawTestInstanceBase::~DrawTestInstanceBase (void)
315 void DrawTestInstanceBase::initialize (const DrawParamsBase& data)
319 const vk::VkDevice device = m_context.getDevice();
320 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
322 const PipelineLayoutCreateInfo pipelineLayoutCreateInfo;
323 m_pipelineLayout = vk::createPipelineLayout(m_vk, device, &pipelineLayoutCreateInfo);
325 const vk::VkExtent3D targetImageExtent = { WIDTH, HEIGHT, 1 };
326 const ImageCreateInfo targetImageCreateInfo(vk::VK_IMAGE_TYPE_2D, m_colorAttachmentFormat, targetImageExtent, 1, 1, vk::VK_SAMPLE_COUNT_1_BIT,
327 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);
329 m_colorTargetImage = Image::createAndAlloc(m_vk, device, targetImageCreateInfo, m_context.getDefaultAllocator());
331 const ImageViewCreateInfo colorTargetViewInfo(m_colorTargetImage->object(), vk::VK_IMAGE_VIEW_TYPE_2D, m_colorAttachmentFormat);
332 m_colorTargetView = vk::createImageView(m_vk, device, &colorTargetViewInfo);
334 RenderPassCreateInfo renderPassCreateInfo;
335 renderPassCreateInfo.addAttachment(AttachmentDescription(m_colorAttachmentFormat,
336 vk::VK_SAMPLE_COUNT_1_BIT,
337 vk::VK_ATTACHMENT_LOAD_OP_LOAD,
338 vk::VK_ATTACHMENT_STORE_OP_STORE,
339 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,
340 vk::VK_ATTACHMENT_STORE_OP_STORE,
341 vk::VK_IMAGE_LAYOUT_GENERAL,
342 vk::VK_IMAGE_LAYOUT_GENERAL));
344 const vk::VkAttachmentReference colorAttachmentReference =
347 vk::VK_IMAGE_LAYOUT_GENERAL
350 renderPassCreateInfo.addSubpass(SubpassDescription(vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
355 &colorAttachmentReference,
357 AttachmentReference(),
361 m_renderPass = vk::createRenderPass(m_vk, device, &renderPassCreateInfo);
363 std::vector<vk::VkImageView> colorAttachments(1);
364 colorAttachments[0] = *m_colorTargetView;
366 const FramebufferCreateInfo framebufferCreateInfo(*m_renderPass, colorAttachments, WIDTH, HEIGHT, 1);
368 m_framebuffer = vk::createFramebuffer(m_vk, device, &framebufferCreateInfo);
370 const vk::VkVertexInputBindingDescription vertexInputBindingDescription =
373 (deUint32)sizeof(tcu::Vec4) * 2,
374 vk::VK_VERTEX_INPUT_RATE_VERTEX,
377 const vk::VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
382 vk::VK_FORMAT_R32G32B32A32_SFLOAT,
388 vk::VK_FORMAT_R32G32B32A32_SFLOAT,
389 (deUint32)(sizeof(float)* 4),
393 m_vertexInputState = PipelineCreateInfo::VertexInputState(1,
394 &vertexInputBindingDescription,
396 vertexInputAttributeDescriptions);
398 const vk::VkDeviceSize dataSize = m_data.vertices.size() * sizeof(PositionColorVertex);
399 m_vertexBuffer = Buffer::createAndAlloc(m_vk, device, BufferCreateInfo(dataSize,
400 vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), m_context.getDefaultAllocator(), vk::MemoryRequirement::HostVisible);
402 deUint8* ptr = reinterpret_cast<deUint8*>(m_vertexBuffer->getBoundMemory().getHostPtr());
403 deMemcpy(ptr, &(m_data.vertices[0]), static_cast<size_t>(dataSize));
405 vk::flushMappedMemoryRange(m_vk,
407 m_vertexBuffer->getBoundMemory().getMemory(),
408 m_vertexBuffer->getBoundMemory().getOffset(),
411 const CmdPoolCreateInfo cmdPoolCreateInfo(queueFamilyIndex);
412 m_cmdPool = vk::createCommandPool(m_vk, device, &cmdPoolCreateInfo);
414 const vk::VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
416 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
417 DE_NULL, // const void* pNext;
418 *m_cmdPool, // VkCommandPool commandPool;
419 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level;
420 1u, // deUint32 bufferCount;
422 m_cmdBuffer = vk::allocateCommandBuffer(m_vk, device, &cmdBufferAllocateInfo);
424 initPipeline(device);
427 void DrawTestInstanceBase::initPipeline (const vk::VkDevice device)
429 const vk::Unique<vk::VkShaderModule> vs(createShaderModule(m_vk, device, m_context.getBinaryCollection().get("vert"), 0));
430 const vk::Unique<vk::VkShaderModule> fs(createShaderModule(m_vk, device, m_context.getBinaryCollection().get("frag"), 0));
432 const PipelineCreateInfo::ColorBlendState::Attachment vkCbAttachmentState;
434 vk::VkViewport viewport;
437 viewport.width = static_cast<float>(WIDTH);
438 viewport.height = static_cast<float>(HEIGHT);
439 viewport.minDepth = 0.0f;
440 viewport.maxDepth = 1.0f;
442 vk::VkRect2D scissor;
443 scissor.offset.x = 0;
444 scissor.offset.y = 0;
445 scissor.extent.width = WIDTH;
446 scissor.extent.height = HEIGHT;
448 PipelineCreateInfo pipelineCreateInfo(*m_pipelineLayout, *m_renderPass, 0, 0);
449 pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vs, "main", vk::VK_SHADER_STAGE_VERTEX_BIT));
450 pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*fs, "main", vk::VK_SHADER_STAGE_FRAGMENT_BIT));
451 pipelineCreateInfo.addState(PipelineCreateInfo::VertexInputState(m_vertexInputState));
452 pipelineCreateInfo.addState(PipelineCreateInfo::InputAssemblerState(m_data.topology));
453 pipelineCreateInfo.addState(PipelineCreateInfo::ColorBlendState(1, &vkCbAttachmentState));
454 pipelineCreateInfo.addState(PipelineCreateInfo::ViewportState(1, std::vector<vk::VkViewport>(1, viewport), std::vector<vk::VkRect2D>(1, scissor)));
455 pipelineCreateInfo.addState(PipelineCreateInfo::DepthStencilState());
456 pipelineCreateInfo.addState(PipelineCreateInfo::RasterizerState());
457 pipelineCreateInfo.addState(PipelineCreateInfo::MultiSampleState());
459 m_pipeline = vk::createGraphicsPipeline(m_vk, device, DE_NULL, &pipelineCreateInfo);
462 void DrawTestInstanceBase::beginRenderPass (void)
464 const vk::VkClearColorValue clearColor = { { 0.0f, 0.0f, 0.0f, 1.0f } };
465 const CmdBufferBeginInfo beginInfo;
467 m_vk.beginCommandBuffer(*m_cmdBuffer, &beginInfo);
469 initialTransitionColor2DImage(m_vk, *m_cmdBuffer, m_colorTargetImage->object(), vk::VK_IMAGE_LAYOUT_GENERAL);
471 const ImageSubresourceRange subresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT);
472 m_vk.cmdClearColorImage(*m_cmdBuffer, m_colorTargetImage->object(),
473 vk::VK_IMAGE_LAYOUT_GENERAL, &clearColor, 1, &subresourceRange);
475 const vk::VkMemoryBarrier memBarrier =
477 vk::VK_STRUCTURE_TYPE_MEMORY_BARRIER,
479 vk::VK_ACCESS_TRANSFER_WRITE_BIT,
480 vk::VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
483 m_vk.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
484 vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
485 0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL);
487 const vk::VkRect2D renderArea = { { 0, 0 }, { WIDTH, HEIGHT } };
488 const RenderPassBeginInfo renderPassBegin(*m_renderPass, *m_framebuffer, renderArea);
490 m_vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBegin, vk::VK_SUBPASS_CONTENTS_INLINE);
493 void DrawTestInstanceBase::generateRefImage (const tcu::PixelBufferAccess& access, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const
495 const PassthruVertShader vertShader;
496 const PassthruFragShader fragShader;
497 const rr::Program program (&vertShader, &fragShader);
498 const rr::MultisamplePixelBufferAccess colorBuffer = rr::MultisamplePixelBufferAccess::fromSinglesampleAccess(access);
499 const rr::RenderTarget renderTarget (colorBuffer);
500 const rr::RenderState renderState ((rr::ViewportState(colorBuffer)));
501 const rr::Renderer renderer;
503 const rr::VertexAttrib vertexAttribs[] =
505 rr::VertexAttrib(rr::VERTEXATTRIBTYPE_FLOAT, 4, sizeof(tcu::Vec4), 0, &vertices[0]),
506 rr::VertexAttrib(rr::VERTEXATTRIBTYPE_FLOAT, 4, sizeof(tcu::Vec4), 0, &colors[0])
509 renderer.draw(rr::DrawCommand(renderState,
512 DE_LENGTH_OF_ARRAY(vertexAttribs),
514 rr::PrimitiveList(mapVkPrimitiveTopology(m_data.topology), (deUint32)vertices.size(), 0)));
518 class DrawTestInstance : public DrawTestInstanceBase
521 DrawTestInstance (Context& context, const T& data);
522 virtual ~DrawTestInstance (void);
523 virtual void generateDrawData (void);
524 virtual tcu::TestStatus iterate (void);
530 DrawTestInstance<T>::DrawTestInstance (Context& context, const T& data)
531 : DrawTestInstanceBase (context)
539 DrawTestInstance<T>::~DrawTestInstance (void)
544 void DrawTestInstance<T>::generateDrawData (void)
546 DE_FATAL("Using the general case of this function is forbidden!");
550 tcu::TestStatus DrawTestInstance<T>::iterate (void)
552 DE_FATAL("Using the general case of this function is forbidden!");
553 return tcu::TestStatus::fail("");
557 class DrawTestCase : public TestCase
560 DrawTestCase (tcu::TestContext& context, const char* name, const char* desc, const T data);
561 ~DrawTestCase (void);
562 virtual void initPrograms (vk::SourceCollections& programCollection) const;
563 virtual void initShaderSources (void);
564 virtual TestInstance* createInstance (Context& context) const;
568 std::string m_vertShaderSource;
569 std::string m_fragShaderSource;
573 DrawTestCase<T>::DrawTestCase (tcu::TestContext& context, const char* name, const char* desc, const T data)
574 : vkt::TestCase (context, name, desc)
581 DrawTestCase<T>::~DrawTestCase (void)
586 void DrawTestCase<T>::initPrograms (vk::SourceCollections& programCollection) const
588 programCollection.glslSources.add("vert") << glu::VertexSource(m_vertShaderSource);
589 programCollection.glslSources.add("frag") << glu::FragmentSource(m_fragShaderSource);
593 void DrawTestCase<T>::initShaderSources (void)
595 std::stringstream vertShader;
596 vertShader << "#version 430\n"
597 << "layout(location = 0) in vec4 in_position;\n"
598 << "layout(location = 1) in vec4 in_color;\n"
599 << "layout(location = 0) out vec4 out_color;\n"
601 << "out gl_PerVertex {\n"
602 << " vec4 gl_Position;\n"
603 << " float gl_PointSize;\n"
606 << " gl_PointSize = 1.0;\n"
607 << " gl_Position = in_position;\n"
608 << " out_color = in_color;\n"
611 m_vertShaderSource = vertShader.str();
613 std::stringstream fragShader;
614 fragShader << "#version 430\n"
615 << "layout(location = 0) in vec4 in_color;\n"
616 << "layout(location = 0) out vec4 out_color;\n"
619 << " out_color = in_color;\n"
622 m_fragShaderSource = fragShader.str();
626 TestInstance* DrawTestCase<T>::createInstance (Context& context) const
628 return new DrawTestInstance<T>(context, m_data);
633 void DrawTestInstance<DrawParams>::generateDrawData (void)
635 de::Random rnd (SEED ^ m_data.params.firstVertex ^ m_data.params.vertexCount);
637 const deUint32 vectorSize = m_data.params.firstVertex + m_data.params.vertexCount;
639 // Initialize the vector
640 m_data.vertices = std::vector<PositionColorVertex>(vectorSize, PositionColorVertex(tcu::Vec4(0.0, 0.0, 0.0, 0.0), tcu::Vec4(0.0, 0.0, 0.0, 0.0)));
642 // Fill only the used indexes
643 for (deUint32 vertexIdx = m_data.params.firstVertex; vertexIdx < vectorSize; ++vertexIdx)
645 m_data.vertices[vertexIdx] = PositionColorVertex(
646 tcu::Vec4(rnd.getFloat(-1.0, 1.0), rnd.getFloat(-1.0, 1.0), 1.0, 1.0), // Coord
647 tcu::Vec4(rnd.getFloat(0.0, 1.0), rnd.getFloat(0.0, 1.0), rnd.getFloat(0.0, 1.0), rnd.getFloat(0.0, 1.0))); // Color
652 tcu::TestStatus DrawTestInstance<DrawParams>::iterate (void)
654 tcu::TestLog &log = m_context.getTestContext().getLog();
655 const vk::VkQueue queue = m_context.getUniversalQueue();
659 const vk::VkDeviceSize vertexBufferOffset = 0;
660 const vk::VkBuffer vertexBuffer = m_vertexBuffer->object();
662 m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
663 m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
664 m_vk.cmdDraw(*m_cmdBuffer, m_data.params.vertexCount, m_data.params.instanceCount, m_data.params.firstVertex, m_data.params.firstInstance);
665 m_vk.cmdEndRenderPass(*m_cmdBuffer);
666 m_vk.endCommandBuffer(*m_cmdBuffer);
668 vk::VkSubmitInfo submitInfo =
670 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
671 DE_NULL, // const void* pNext;
672 0, // deUint32 waitSemaphoreCount;
673 DE_NULL, // const VkSemaphore* pWaitSemaphores;
674 (const vk::VkPipelineStageFlags*)DE_NULL,
675 1, // deUint32 commandBufferCount;
676 &m_cmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
677 0, // deUint32 signalSemaphoreCount;
678 DE_NULL // const VkSemaphore* pSignalSemaphores;
680 VK_CHECK(m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL));
683 tcu::TextureLevel refImage (vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5 + WIDTH), (int)(0.5 + HEIGHT));
684 tcu::clear(refImage.getAccess(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
686 std::vector<tcu::Vec4> vertices;
687 std::vector<tcu::Vec4> colors;
689 for (std::vector<PositionColorVertex>::const_iterator vertex = m_data.vertices.begin() + m_data.params.firstVertex; vertex != m_data.vertices.end(); ++vertex)
691 vertices.push_back(vertex->position);
692 colors.push_back(vertex->color);
694 generateRefImage(refImage.getAccess(), vertices, colors);
696 VK_CHECK(m_vk.queueWaitIdle(queue));
698 const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
699 const tcu::ConstPixelBufferAccess renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
700 vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
702 qpTestResult res = QP_TEST_RESULT_PASS;
704 if (!imageCompare(log, refImage.getAccess(), renderedFrame, m_data.topology))
705 res = QP_TEST_RESULT_FAIL;
707 return tcu::TestStatus(res, qpGetTestResultName(res));
711 void DrawTestInstance<DrawIndexedParams>::generateDrawData (void)
713 de::Random rnd (SEED ^ m_data.params.firstIndex ^ m_data.params.indexCount);
714 const deUint32 indexSize = m_data.params.firstIndex + m_data.params.indexCount;
716 // Initialize the vector with zeros
717 m_data.indexes = std::vector<deUint32>(indexSize, 0);
719 deUint32 highestIndex = 0; // Store to highest index to calculate the vertices size
720 // Fill the indexes from firstIndex
721 for (deUint32 idx = 0; idx < m_data.params.indexCount; ++idx)
723 deUint32 vertexIdx = rnd.getInt(m_data.params.vertexOffset, INDEX_LIMIT);
724 highestIndex = (vertexIdx > highestIndex) ? vertexIdx : highestIndex;
726 m_data.indexes[m_data.params.firstIndex + idx] = vertexIdx;
729 // Fill up the vertex coordinates with zeros until the highestIndex including the vertexOffset
730 m_data.vertices = std::vector<PositionColorVertex>(m_data.params.vertexOffset + highestIndex + 1, PositionColorVertex(tcu::Vec4(0.0, 0.0, 0.0, 0.0), tcu::Vec4(0.0, 0.0, 0.0, 0.0)));
732 // Generate random vertex only where you have index pointing at
733 for (std::vector<deUint32>::const_iterator indexIt = m_data.indexes.begin() + m_data.params.firstIndex; indexIt != m_data.indexes.end(); ++indexIt)
735 // Get iterator to the vertex position with the vertexOffset
736 std::vector<PositionColorVertex>::iterator vertexIt = m_data.vertices.begin() + m_data.params.vertexOffset + *indexIt;
738 tcu::VecAccess<float, 4, 4> positionAccess = vertexIt->position.xyzw();
739 positionAccess = tcu::Vec4(rnd.getFloat(-1.0, 1.0), rnd.getFloat(-1.0, 1.0), 1.0, 1.0);
741 tcu::VecAccess<float, 4, 4> colorAccess = vertexIt->color.xyzw();
742 colorAccess = tcu::Vec4(rnd.getFloat(0.0, 1.0), rnd.getFloat(0.0, 1.0), rnd.getFloat(0.0, 1.0), rnd.getFloat(0.0, 1.0));
747 tcu::TestStatus DrawTestInstance<DrawIndexedParams>::iterate (void)
749 tcu::TestLog &log = m_context.getTestContext().getLog();
750 const vk::DeviceInterface& vk = m_context.getDeviceInterface();
751 const vk::VkDevice vkDevice = m_context.getDevice();
752 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
753 const vk::VkQueue queue = m_context.getUniversalQueue();
754 vk::Allocator& allocator = m_context.getDefaultAllocator();
758 const vk::VkDeviceSize vertexBufferOffset = 0;
759 const vk::VkBuffer vertexBuffer = m_vertexBuffer->object();
761 m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
762 m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
764 const deUint32 bufferSize = (deUint32)(m_data.indexes.size() * sizeof(deUint32));
766 vk::Move<vk::VkBuffer> indexBuffer;
768 const vk::VkBufferCreateInfo bufferCreateInfo =
770 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
771 DE_NULL, // const void* pNext;
772 0u, // VkBufferCreateFlags flags;
773 bufferSize, // VkDeviceSize size;
774 vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT, // VkBufferUsageFlags usage;
775 vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
776 1u, // deUint32 queueFamilyIndexCount;
777 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
780 indexBuffer = createBuffer(vk, vkDevice, &bufferCreateInfo);
782 de::MovePtr<vk::Allocation> indexAlloc;
784 indexAlloc = allocator.allocate(getBufferMemoryRequirements(vk, vkDevice, *indexBuffer), vk::MemoryRequirement::HostVisible);
785 VK_CHECK(vk.bindBufferMemory(vkDevice, *indexBuffer, indexAlloc->getMemory(), indexAlloc->getOffset()));
787 deMemcpy(indexAlloc->getHostPtr(), &(m_data.indexes[0]), bufferSize);
789 vk::flushMappedMemoryRange(m_vk, vkDevice, indexAlloc->getMemory(), indexAlloc->getOffset(), bufferSize);
791 m_vk.cmdBindIndexBuffer(*m_cmdBuffer, *indexBuffer, 0u, m_data.indexType);
792 m_vk.cmdDrawIndexed(*m_cmdBuffer, m_data.params.indexCount, m_data.params.instanceCount, m_data.params.firstIndex, m_data.params.vertexOffset, m_data.params.firstInstance);
793 m_vk.cmdEndRenderPass(*m_cmdBuffer);
794 m_vk.endCommandBuffer(*m_cmdBuffer);
796 vk::VkSubmitInfo submitInfo =
798 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
799 DE_NULL, // const void* pNext;
800 0, // deUint32 waitSemaphoreCount;
801 DE_NULL, // const VkSemaphore* pWaitSemaphores;
802 (const vk::VkPipelineStageFlags*)DE_NULL,
803 1, // deUint32 commandBufferCount;
804 &m_cmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
805 0, // deUint32 signalSemaphoreCount;
806 DE_NULL // const VkSemaphore* pSignalSemaphores;
808 VK_CHECK(m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL));
811 tcu::TextureLevel refImage (vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5 + WIDTH), (int)(0.5 + HEIGHT));
812 tcu::clear(refImage.getAccess(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
814 std::vector<tcu::Vec4> vertices;
815 std::vector<tcu::Vec4> colors;
817 for (std::vector<deUint32>::const_iterator it = m_data.indexes.begin() + m_data.params.firstIndex; it != m_data.indexes.end(); ++it)
819 deUint32 idx = m_data.params.vertexOffset + *it;
820 vertices.push_back(m_data.vertices[idx].position);
821 colors.push_back(m_data.vertices[idx].color);
823 generateRefImage(refImage.getAccess(), vertices, colors);
825 VK_CHECK(m_vk.queueWaitIdle(queue));
827 const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
828 const tcu::ConstPixelBufferAccess renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
829 vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
831 qpTestResult res = QP_TEST_RESULT_PASS;
833 if (!imageCompare(log, refImage.getAccess(), renderedFrame, m_data.topology))
834 res = QP_TEST_RESULT_FAIL;
836 return tcu::TestStatus(res, qpGetTestResultName(res));
840 void DrawTestInstance<DrawIndirectParams>::generateDrawData (void)
842 de::Random rnd(SEED ^ m_data.commands[0].vertexCount ^ m_data.commands[0].firstVertex);
844 deUint32 lastIndex = 0;
846 // Find the interval which will be used
847 for (std::vector<vk::VkDrawIndirectCommand>::const_iterator it = m_data.commands.begin(); it != m_data.commands.end(); ++it)
849 const deUint32 index = it->firstVertex + it->vertexCount;
850 lastIndex = (index > lastIndex) ? index : lastIndex;
853 // Initialize with zeros
854 m_data.vertices = std::vector<PositionColorVertex>(lastIndex, PositionColorVertex(tcu::Vec4(0.0, 0.0, 0.0, 0.0), tcu::Vec4(0.0, 0.0, 0.0, 0.0)));
856 // Generate random vertices only where necessary
857 for (std::vector<vk::VkDrawIndirectCommand>::const_iterator it = m_data.commands.begin(); it != m_data.commands.end(); ++it)
859 std::vector<PositionColorVertex>::iterator vertexStart = m_data.vertices.begin() + it->firstVertex;
861 for (deUint32 idx = 0; idx < it->vertexCount; ++idx)
863 std::vector<PositionColorVertex>::iterator vertexIt = vertexStart + idx;
865 tcu::VecAccess<float, 4, 4> positionAccess = vertexIt->position.xyzw();
866 positionAccess = tcu::Vec4(rnd.getFloat(-1.0, 1.0), rnd.getFloat(-1.0, 1.0), 1.0, 1.0);
868 tcu::VecAccess<float, 4, 4> colorAccess = vertexIt->color.xyzw();
869 colorAccess = tcu::Vec4(rnd.getFloat(0.0, 1.0), rnd.getFloat(0.0, 1.0), rnd.getFloat(0.0, 1.0), rnd.getFloat(0.0, 1.0));
875 tcu::TestStatus DrawTestInstance<DrawIndirectParams>::iterate (void)
877 tcu::TestLog &log = m_context.getTestContext().getLog();
878 const vk::DeviceInterface& vk = m_context.getDeviceInterface();
879 const vk::VkDevice vkDevice = m_context.getDevice();
880 vk::Allocator& allocator = m_context.getDefaultAllocator();
881 const vk::VkQueue queue = m_context.getUniversalQueue();
882 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
883 const vk::VkPhysicalDeviceFeatures features = m_context.getDeviceFeatures();
887 const vk::VkDeviceSize vertexBufferOffset = 0;
888 const vk::VkBuffer vertexBuffer = m_vertexBuffer->object();
890 m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
891 m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
893 vk::Move<vk::VkBuffer> indirectBuffer;
894 de::MovePtr<vk::Allocation> indirectAlloc;
897 const vk::VkDeviceSize indirectInfoSize = m_data.commands.size() * sizeof(vk::VkDrawIndirectCommand);
899 const vk::VkBufferCreateInfo indirectCreateInfo =
901 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
902 DE_NULL, // const void* pNext;
903 0u, // VkBufferCreateFlags flags;
904 indirectInfoSize, // VkDeviceSize size;
905 vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, // VkBufferUsageFlags usage;
906 vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
907 1u, // deUint32 queueFamilyIndexCount;
908 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
911 indirectBuffer = createBuffer(vk, vkDevice, &indirectCreateInfo);
912 indirectAlloc = allocator.allocate(getBufferMemoryRequirements(vk, vkDevice, *indirectBuffer), vk::MemoryRequirement::HostVisible);
913 VK_CHECK(vk.bindBufferMemory(vkDevice, *indirectBuffer, indirectAlloc->getMemory(), indirectAlloc->getOffset()));
915 deMemcpy(indirectAlloc->getHostPtr(), &(m_data.commands[0]), (size_t)indirectInfoSize);
917 vk::flushMappedMemoryRange(m_vk, vkDevice, indirectAlloc->getMemory(), indirectAlloc->getOffset(), indirectInfoSize);
920 // If multiDrawIndirect not supported execute single calls
921 if (m_data.commands.size() > 1 && !(features.multiDrawIndirect))
923 for (deUint32 cmdIdx = 0; cmdIdx < m_data.commands.size(); ++cmdIdx)
925 const deUint32 offset = (deUint32)(indirectAlloc->getOffset() + cmdIdx * sizeof(vk::VkDrawIndirectCommand));
926 m_vk.cmdDrawIndirect(*m_cmdBuffer, *indirectBuffer, offset, 1, sizeof(vk::VkDrawIndirectCommand));
931 m_vk.cmdDrawIndirect(*m_cmdBuffer, *indirectBuffer, indirectAlloc->getOffset(), (deUint32)m_data.commands.size(), sizeof(vk::VkDrawIndirectCommand));
934 m_vk.cmdEndRenderPass(*m_cmdBuffer);
935 m_vk.endCommandBuffer(*m_cmdBuffer);
937 vk::VkSubmitInfo submitInfo =
939 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
940 DE_NULL, // const void* pNext;
941 0, // deUint32 waitSemaphoreCount;
942 DE_NULL, // const VkSemaphore* pWaitSemaphores;
943 (const vk::VkPipelineStageFlags*)DE_NULL,
944 1, // deUint32 commandBufferCount;
945 &m_cmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
946 0, // deUint32 signalSemaphoreCount;
947 DE_NULL // const VkSemaphore* pSignalSemaphores;
949 VK_CHECK(m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL));
952 tcu::TextureLevel refImage (vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5 + WIDTH), (int)(0.5 + HEIGHT));
953 tcu::clear(refImage.getAccess(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
955 for (std::vector<vk::VkDrawIndirectCommand>::const_iterator it = m_data.commands.begin(); it != m_data.commands.end(); ++it)
957 std::vector<tcu::Vec4> vertices;
958 std::vector<tcu::Vec4> colors;
960 std::vector<PositionColorVertex>::const_iterator firstIt = m_data.vertices.begin() + it->firstVertex;
961 std::vector<PositionColorVertex>::const_iterator lastIt = firstIt + it->vertexCount;
963 for (std::vector<PositionColorVertex>::const_iterator vertex = firstIt; vertex != lastIt; ++vertex)
965 vertices.push_back(vertex->position);
966 colors.push_back(vertex->color);
968 generateRefImage(refImage.getAccess(), vertices, colors);
971 VK_CHECK(m_vk.queueWaitIdle(queue));
973 const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
974 const tcu::ConstPixelBufferAccess renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
975 vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
977 qpTestResult res = QP_TEST_RESULT_PASS;
979 if (!imageCompare(log, refImage.getAccess(), renderedFrame, m_data.topology))
980 res = QP_TEST_RESULT_FAIL;
982 return tcu::TestStatus(res, qpGetTestResultName(res));
986 void DrawTestInstance<DrawIndexedIndirectParams>::generateDrawData (void)
988 de::Random rnd (SEED ^ m_data.commands[0].firstIndex ^ m_data.commands[0].indexCount);
990 deUint32 lastIndex = 0;
992 // Get the maximum range of indexes
993 for (std::vector<vk::VkDrawIndexedIndirectCommand>::const_iterator it = m_data.commands.begin(); it != m_data.commands.end(); ++it)
995 const deUint32 index = it->firstIndex + it->indexCount;
996 lastIndex = (index > lastIndex) ? index : lastIndex;
999 // Initialize the vector with zeros
1000 m_data.indexes = std::vector<deUint32>(lastIndex, 0);
1002 deUint32 highestIndex = 0;
1004 // Generate random indexes for the ranges
1005 for (std::vector<vk::VkDrawIndexedIndirectCommand>::const_iterator it = m_data.commands.begin(); it != m_data.commands.end(); ++it)
1007 for (deUint32 idx = 0; idx < it->indexCount; ++idx)
1009 const deUint32 vertexIdx = rnd.getInt(it->vertexOffset, INDEX_LIMIT);
1010 const deUint32 maxIndex = vertexIdx + it->vertexOffset;
1012 highestIndex = (maxIndex > highestIndex) ? maxIndex : highestIndex;
1013 m_data.indexes[it->firstIndex + idx] = vertexIdx;
1017 // Initialize the vertex vector
1018 m_data.vertices = std::vector<PositionColorVertex>(highestIndex + 1, PositionColorVertex(tcu::Vec4(0.0, 0.0, 0.0, 0.0), tcu::Vec4(0.0, 0.0, 0.0, 0.0)));
1020 // Generate random vertices in the used locations
1021 for (std::vector<vk::VkDrawIndexedIndirectCommand>::const_iterator cmdIt = m_data.commands.begin(); cmdIt != m_data.commands.end(); ++cmdIt)
1023 deUint32 firstIdx = cmdIt->firstIndex;
1024 deUint32 lastIdx = firstIdx + cmdIt->indexCount;
1026 for (deUint32 idx = firstIdx; idx < lastIdx; ++idx)
1028 std::vector<PositionColorVertex>::iterator vertexIt = m_data.vertices.begin() + cmdIt->vertexOffset + m_data.indexes[idx];
1030 tcu::VecAccess<float, 4, 4> positionAccess = vertexIt->position.xyzw();
1031 positionAccess = tcu::Vec4(rnd.getFloat(-1.0, 1.0), rnd.getFloat(-1.0, 1.0), 1.0, 1.0);
1033 tcu::VecAccess<float, 4, 4> colorAccess = vertexIt->color.xyzw();
1034 colorAccess = tcu::Vec4(rnd.getFloat(0.0, 1.0), rnd.getFloat(0.0, 1.0), rnd.getFloat(0.0, 1.0), rnd.getFloat(0.0, 1.0));
1040 tcu::TestStatus DrawTestInstance<DrawIndexedIndirectParams>::iterate (void)
1042 tcu::TestLog &log = m_context.getTestContext().getLog();
1043 const vk::DeviceInterface& vk = m_context.getDeviceInterface();
1044 const vk::VkDevice vkDevice = m_context.getDevice();
1045 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1046 const vk::VkQueue queue = m_context.getUniversalQueue();
1047 vk::Allocator& allocator = m_context.getDefaultAllocator();
1048 const vk::VkPhysicalDeviceFeatures features = m_context.getDeviceFeatures();
1052 const vk::VkDeviceSize vertexBufferOffset = 0;
1053 const vk::VkBuffer vertexBuffer = m_vertexBuffer->object();
1055 m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
1056 m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
1058 vk::Move<vk::VkBuffer> indirectBuffer;
1059 de::MovePtr<vk::Allocation> indirectAlloc;
1062 const vk::VkDeviceSize indirectInfoSize = m_data.commands.size() * sizeof(vk::VkDrawIndexedIndirectCommand);
1064 const vk::VkBufferCreateInfo indirectCreateInfo =
1066 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
1067 DE_NULL, // const void* pNext;
1068 0u, // VkBufferCreateFlags flags;
1069 indirectInfoSize, // VkDeviceSize size;
1070 vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, // VkBufferUsageFlags usage;
1071 vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1072 1u, // deUint32 queueFamilyIndexCount;
1073 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
1076 indirectBuffer = createBuffer(vk, vkDevice, &indirectCreateInfo);
1077 indirectAlloc = allocator.allocate(getBufferMemoryRequirements(vk, vkDevice, *indirectBuffer), vk::MemoryRequirement::HostVisible);
1078 VK_CHECK(vk.bindBufferMemory(vkDevice, *indirectBuffer, indirectAlloc->getMemory(), indirectAlloc->getOffset()));
1080 deMemcpy(indirectAlloc->getHostPtr(), &(m_data.commands[0]), (size_t)indirectInfoSize);
1082 vk::flushMappedMemoryRange(m_vk, vkDevice, indirectAlloc->getMemory(), indirectAlloc->getOffset(), indirectInfoSize);
1085 const deUint32 bufferSize = (deUint32)(m_data.indexes.size() * sizeof(deUint32));
1087 vk::Move<vk::VkBuffer> indexBuffer;
1089 const vk::VkBufferCreateInfo bufferCreateInfo =
1091 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
1092 DE_NULL, // const void* pNext;
1093 0u, // VkBufferCreateFlags flags;
1094 bufferSize, // VkDeviceSize size;
1095 vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT, // VkBufferUsageFlags usage;
1096 vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1097 1u, // deUint32 queueFamilyIndexCount;
1098 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
1101 indexBuffer = createBuffer(vk, vkDevice, &bufferCreateInfo);
1103 de::MovePtr<vk::Allocation> indexAlloc;
1105 indexAlloc = allocator.allocate(getBufferMemoryRequirements(vk, vkDevice, *indexBuffer), vk::MemoryRequirement::HostVisible);
1106 VK_CHECK(vk.bindBufferMemory(vkDevice, *indexBuffer, indexAlloc->getMemory(), indexAlloc->getOffset()));
1108 deMemcpy(indexAlloc->getHostPtr(), &(m_data.indexes[0]), bufferSize);
1110 vk::flushMappedMemoryRange(m_vk, vkDevice, indexAlloc->getMemory(), indexAlloc->getOffset(), bufferSize);
1112 m_vk.cmdBindIndexBuffer(*m_cmdBuffer, *indexBuffer, 0u, m_data.indexType);
1114 // If multiDrawIndirect not supported execute single calls
1115 if (m_data.commands.size() > 1 && !(features.multiDrawIndirect))
1117 for (deUint32 cmdIdx = 0; cmdIdx < m_data.commands.size(); ++cmdIdx)
1119 const deUint32 offset = (deUint32)(indirectAlloc->getOffset() + cmdIdx * sizeof(vk::VkDrawIndexedIndirectCommand));
1120 m_vk.cmdDrawIndexedIndirect(*m_cmdBuffer, *indirectBuffer, offset, 1, sizeof(vk::VkDrawIndexedIndirectCommand));
1125 m_vk.cmdDrawIndexedIndirect(*m_cmdBuffer, *indirectBuffer, indirectAlloc->getOffset(), (deUint32)m_data.commands.size(), sizeof(vk::VkDrawIndexedIndirectCommand));
1128 m_vk.cmdEndRenderPass(*m_cmdBuffer);
1129 m_vk.endCommandBuffer(*m_cmdBuffer);
1131 vk::VkSubmitInfo submitInfo =
1133 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
1134 DE_NULL, // const void* pNext;
1135 0, // deUint32 waitSemaphoreCount;
1136 DE_NULL, // const VkSemaphore* pWaitSemaphores;
1137 (const vk::VkPipelineStageFlags*)DE_NULL,
1138 1, // deUint32 commandBufferCount;
1139 &m_cmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
1140 0, // deUint32 signalSemaphoreCount;
1141 DE_NULL // const VkSemaphore* pSignalSemaphores;
1143 VK_CHECK(m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL));
1146 tcu::TextureLevel refImage (vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5 + WIDTH), (int)(0.5 + HEIGHT));
1147 tcu::clear(refImage.getAccess(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
1149 for (std::vector<vk::VkDrawIndexedIndirectCommand>::const_iterator cmd = m_data.commands.begin(); cmd != m_data.commands.end(); ++cmd)
1151 std::vector<tcu::Vec4> vertices;
1152 std::vector<tcu::Vec4> colors;
1154 for (deUint32 idx = 0; idx < cmd->indexCount; ++idx)
1156 const deUint32 vertexIndex = cmd->vertexOffset + m_data.indexes[cmd->firstIndex + idx];
1157 vertices.push_back(m_data.vertices[vertexIndex].position);
1158 colors.push_back(m_data.vertices[vertexIndex].color);
1160 generateRefImage(refImage.getAccess(), vertices, colors);
1163 VK_CHECK(m_vk.queueWaitIdle(queue));
1165 const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
1166 const tcu::ConstPixelBufferAccess renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
1167 vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
1169 qpTestResult res = QP_TEST_RESULT_PASS;
1171 if (!imageCompare(log, refImage.getAccess(), renderedFrame, m_data.topology))
1172 res = QP_TEST_RESULT_FAIL;
1174 return tcu::TestStatus(res, qpGetTestResultName(res));
1177 typedef DrawTestCase<DrawParams> DrawCase;
1178 typedef DrawTestCase<DrawIndexedParams> IndexedCase;
1179 typedef DrawTestCase<DrawIndirectParams> IndirectCase;
1180 typedef DrawTestCase<DrawIndexedIndirectParams> IndexedIndirectCase;
1182 struct TestCaseParams
1184 const DrawCommandType command;
1185 const vk::VkPrimitiveTopology topology;
1187 TestCaseParams (const DrawCommandType cmd, const vk::VkPrimitiveTopology top)
1195 void populateSubGroup (tcu::TestCaseGroup* testGroup, const TestCaseParams caseParams)
1197 de::Random rnd (SEED ^ deStringHash(testGroup->getName()));
1198 tcu::TestContext& testCtx = testGroup->getTestContext();
1199 const DrawCommandType command = caseParams.command;
1200 const vk::VkPrimitiveTopology topology = caseParams.topology;
1202 for (deUint32 primitiveCountIdx = 0; primitiveCountIdx < DE_LENGTH_OF_ARRAY(PRIMITIVE_COUNT); ++primitiveCountIdx)
1204 const deUint32 primitives = PRIMITIVE_COUNT[primitiveCountIdx];
1206 deUint32 multiplier = 1;
1207 deUint32 offset = 0;
1208 // Calculated by Vulkan 23.1
1211 case vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST: break;
1212 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST: multiplier = 2; break;
1213 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP: break;
1214 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST: multiplier = 3; break;
1215 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP: break;
1216 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN: offset = 1; break;
1217 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY: multiplier = 4; offset = 1; break;
1218 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY: offset = 1; break;
1219 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY: multiplier = 6; break;
1220 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY: multiplier = 2; break;
1221 default: DE_FATAL("Unsupported topology.");
1224 const deUint32 vertexCount = multiplier * primitives + offset;
1225 std::string name = de::toString(primitives);
1229 case DRAW_COMMAND_TYPE_DRAW:
1231 deUint32 firstPrimitive = rnd.getInt(0, primitives);
1232 deUint32 firstVertex = multiplier * firstPrimitive;
1233 testGroup->addChild(new DrawCase(testCtx, name.c_str(), "vkCmdDraw testcase.",
1234 DrawParams(topology, vertexCount, 1, firstVertex, 0))
1238 case DRAW_COMMAND_TYPE_DRAW_INDEXED:
1240 deUint32 firstIndex = rnd.getInt(0, OFFSET_LIMIT);
1241 deUint32 vertexOffset = rnd.getInt(0, OFFSET_LIMIT);
1242 testGroup->addChild(new IndexedCase(testCtx, name.c_str(), "vkCmdDrawIndexed testcase.",
1243 DrawIndexedParams(topology, vk::VK_INDEX_TYPE_UINT32, vertexCount, 1, firstIndex, vertexOffset, 0))
1247 case DRAW_COMMAND_TYPE_DRAW_INDIRECT:
1249 deUint32 firstVertex = rnd.getInt(0, OFFSET_LIMIT);
1251 DrawIndirectParams params = DrawIndirectParams(topology);
1253 params.addCommand(vertexCount, 1, 0, 0);
1254 testGroup->addChild(new IndirectCase(testCtx, (name + "_single_command").c_str(), "vkCmdDrawIndirect testcase.", params));
1256 params.addCommand(vertexCount, 1, firstVertex, 0);
1257 testGroup->addChild(new IndirectCase(testCtx, (name + "_multi_command").c_str(), "vkCmdDrawIndirect testcase.", params));
1260 case DRAW_COMMAND_TYPE_DRAW_INDEXED_INDIRECT:
1262 deUint32 firstIndex = rnd.getInt(vertexCount, OFFSET_LIMIT);
1263 deUint32 vertexOffset = rnd.getInt(vertexCount, OFFSET_LIMIT);
1265 DrawIndexedIndirectParams params = DrawIndexedIndirectParams(topology, vk::VK_INDEX_TYPE_UINT32);
1266 params.addCommand(vertexCount, 1, 0, 0, 0);
1267 testGroup->addChild(new IndexedIndirectCase(testCtx, (name + "_single_command").c_str(), "vkCmdDrawIndexedIndirect testcase.", params));
1269 params.addCommand(vertexCount, 1, firstIndex, vertexOffset, 0);
1270 testGroup->addChild(new IndexedIndirectCase(testCtx, (name + "_multi_command").c_str(), "vkCmdDrawIndexedIndirect testcase.", params));
1274 DE_FATAL("Unsupported draw command.");
1279 void createTopologyGroups (tcu::TestCaseGroup* testGroup, const DrawCommandType cmdType)
1281 for (deUint32 idx = 0; idx != vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST; ++idx)
1283 const vk::VkPrimitiveTopology topology = vk::VkPrimitiveTopology(idx);
1284 const std::string groupName = de::toLower(getPrimitiveTopologyName(topology)).substr(22);
1285 addTestGroup(testGroup, groupName, "Testcases with a specific topology.", populateSubGroup, TestCaseParams(cmdType, topology));
1289 void createDrawTests (tcu::TestCaseGroup* testGroup)
1291 for (deUint32 idx = 0; idx < DRAW_COMMAND_TYPE_DRAW_LAST; ++idx)
1293 const DrawCommandType command = DrawCommandType(idx);
1294 addTestGroup(testGroup, getDrawCommandTypeName(command), "Group for testing a specific draw command.", createTopologyGroups, command);
1298 tcu::TestCaseGroup* createBasicDrawTests (tcu::TestContext& testCtx)
1300 return createTestGroup(testCtx, "basic_draw", "Basic drawing tests", createDrawTests);