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 "vkCmdUtil.hpp"
30 #include "vkTypeUtil.hpp"
31 #include "vktTestGroupUtil.hpp"
34 #include "deRandom.hpp"
37 #include "tcuTestCase.hpp"
38 #include "tcuRGBA.hpp"
39 #include "tcuTextureUtil.hpp"
40 #include "tcuImageCompare.hpp"
41 #include "tcuVectorUtil.hpp"
43 #include "rrRenderer.hpp"
54 static const deUint32 SEED = 0xc2a39fu;
55 static const deUint32 INDEX_LIMIT = 10000;
56 // To avoid too big and mostly empty structures
57 static const deUint32 OFFSET_LIMIT = 1000;
58 // Number of primitives to draw
59 static const deUint32 PRIMITIVE_COUNT[] = {1, 3, 17, 45};
63 DRAW_COMMAND_TYPE_DRAW,
64 DRAW_COMMAND_TYPE_DRAW_INDEXED,
65 DRAW_COMMAND_TYPE_DRAW_INDIRECT,
66 DRAW_COMMAND_TYPE_DRAW_INDEXED_INDIRECT,
68 DRAW_COMMAND_TYPE_DRAW_LAST
71 const char* getDrawCommandTypeName (DrawCommandType command)
75 case DRAW_COMMAND_TYPE_DRAW: return "draw";
76 case DRAW_COMMAND_TYPE_DRAW_INDEXED: return "draw_indexed";
77 case DRAW_COMMAND_TYPE_DRAW_INDIRECT: return "draw_indirect";
78 case DRAW_COMMAND_TYPE_DRAW_INDEXED_INDIRECT: return "draw_indexed_indirect";
79 default: DE_ASSERT(false);
84 rr::PrimitiveType mapVkPrimitiveTopology (vk::VkPrimitiveTopology primitiveTopology)
86 switch (primitiveTopology)
88 case vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST: return rr::PRIMITIVETYPE_POINTS;
89 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST: return rr::PRIMITIVETYPE_LINES;
90 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP: return rr::PRIMITIVETYPE_LINE_STRIP;
91 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST: return rr::PRIMITIVETYPE_TRIANGLES;
92 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN: return rr::PRIMITIVETYPE_TRIANGLE_FAN;
93 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP: return rr::PRIMITIVETYPE_TRIANGLE_STRIP;
94 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY: return rr::PRIMITIVETYPE_LINES_ADJACENCY;
95 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY: return rr::PRIMITIVETYPE_LINE_STRIP_ADJACENCY;
96 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY: return rr::PRIMITIVETYPE_TRIANGLES_ADJACENCY;
97 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY: return rr::PRIMITIVETYPE_TRIANGLE_STRIP_ADJACENCY;
101 return rr::PRIMITIVETYPE_LAST;
104 struct DrawParamsBase
106 std::vector<PositionColorVertex> vertices;
107 vk::VkPrimitiveTopology topology;
112 DrawParamsBase (const vk::VkPrimitiveTopology top)
117 struct IndexedParamsBase
119 std::vector<deUint32> indexes;
120 const vk::VkIndexType indexType;
122 IndexedParamsBase (const vk::VkIndexType indexT)
127 // Structs to store draw parameters
128 struct DrawParams : DrawParamsBase
130 // vkCmdDraw parameters is like a single VkDrawIndirectCommand
131 vk::VkDrawIndirectCommand params;
133 DrawParams (const vk::VkPrimitiveTopology top, const deUint32 vertexC, const deUint32 instanceC, const deUint32 firstV, const deUint32 firstI)
134 : DrawParamsBase (top)
136 params.vertexCount = vertexC;
137 params.instanceCount = instanceC;
138 params.firstVertex = firstV;
139 params.firstInstance = firstI;
143 struct DrawIndexedParams : DrawParamsBase, IndexedParamsBase
145 // vkCmdDrawIndexed parameters is like a single VkDrawIndexedIndirectCommand
146 vk::VkDrawIndexedIndirectCommand params;
148 DrawIndexedParams (const vk::VkPrimitiveTopology top, const vk::VkIndexType indexT, const deUint32 indexC, const deUint32 instanceC, const deUint32 firstIdx, const deInt32 vertexO, const deUint32 firstIns)
149 : DrawParamsBase (top)
150 , IndexedParamsBase (indexT)
152 params.indexCount = indexC;
153 params.instanceCount = instanceC;
154 params.firstIndex = firstIdx;
155 params.vertexOffset = vertexO;
156 params.firstInstance = firstIns;
160 struct DrawIndirectParams : DrawParamsBase
162 std::vector<vk::VkDrawIndirectCommand> commands;
164 DrawIndirectParams (const vk::VkPrimitiveTopology top)
165 : DrawParamsBase (top)
168 void addCommand (const deUint32 vertexC, const deUint32 instanceC, const deUint32 firstV, const deUint32 firstI)
170 vk::VkDrawIndirectCommand cmd;
171 cmd.vertexCount = vertexC;
172 cmd.instanceCount = instanceC;
173 cmd.firstVertex = firstV;
174 cmd.firstInstance = firstI;
176 commands.push_back(cmd);
180 struct DrawIndexedIndirectParams : DrawParamsBase, IndexedParamsBase
182 std::vector<vk::VkDrawIndexedIndirectCommand> commands;
184 DrawIndexedIndirectParams (const vk::VkPrimitiveTopology top, const vk::VkIndexType indexT)
185 : DrawParamsBase (top)
186 , IndexedParamsBase (indexT)
189 void addCommand (const deUint32 indexC, const deUint32 instanceC, const deUint32 firstIdx, const deInt32 vertexO, const deUint32 firstIns)
191 vk::VkDrawIndexedIndirectCommand cmd;
192 cmd.indexCount = indexC;
193 cmd.instanceCount = instanceC;
194 cmd.firstIndex = firstIdx;
195 cmd.vertexOffset = vertexO;
196 cmd.firstInstance = firstIns;
198 commands.push_back(cmd);
202 // Reference renderer shaders
203 class PassthruVertShader : public rr::VertexShader
206 PassthruVertShader (void)
207 : rr::VertexShader (2, 1)
209 m_inputs[0].type = rr::GENERICVECTYPE_FLOAT;
210 m_inputs[1].type = rr::GENERICVECTYPE_FLOAT;
211 m_outputs[0].type = rr::GENERICVECTYPE_FLOAT;
214 void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
216 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
218 packets[packetNdx]->position = rr::readVertexAttribFloat(inputs[0],
219 packets[packetNdx]->instanceNdx,
220 packets[packetNdx]->vertexNdx);
222 tcu::Vec4 color = rr::readVertexAttribFloat(inputs[1],
223 packets[packetNdx]->instanceNdx,
224 packets[packetNdx]->vertexNdx);
226 packets[packetNdx]->outputs[0] = color;
231 class PassthruFragShader : public rr::FragmentShader
234 PassthruFragShader (void)
235 : rr::FragmentShader(1, 1)
237 m_inputs[0].type = rr::GENERICVECTYPE_FLOAT;
238 m_outputs[0].type = rr::GENERICVECTYPE_FLOAT;
241 void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
243 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
245 rr::FragmentPacket& packet = packets[packetNdx];
246 for (deUint32 fragNdx = 0; fragNdx < rr::NUM_FRAGMENTS_PER_PACKET; ++fragNdx)
248 tcu::Vec4 color = rr::readVarying<float>(packet, context, 0, fragNdx);
249 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
255 inline bool imageCompare (tcu::TestLog& log, const tcu::ConstPixelBufferAccess& reference, const tcu::ConstPixelBufferAccess& result, const vk::VkPrimitiveTopology topology)
257 if (topology == vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST)
259 return tcu::intThresholdPositionDeviationCompare(
260 log, "Result", "Image comparison result", reference, result,
261 tcu::UVec4(4u), // color threshold
262 tcu::IVec3(1, 1, 0), // position deviation tolerance
263 true, // don't check the pixels at the boundary
264 tcu::COMPARE_LOG_RESULT);
267 return tcu::fuzzyCompare(log, "Result", "Image comparison result", reference, result, 0.053f, tcu::COMPARE_LOG_RESULT);
270 class DrawTestInstanceBase : public TestInstance
273 DrawTestInstanceBase (Context& context);
274 virtual ~DrawTestInstanceBase (void) = 0;
275 void initialize (const DrawParamsBase& data);
276 void initPipeline (const vk::VkDevice device);
277 void beginRenderPass (void);
279 // Specialize this function for each type
280 virtual tcu::TestStatus iterate (void) = 0;
282 // Specialize this function for each type
283 virtual void generateDrawData (void) = 0;
284 void generateRefImage (const tcu::PixelBufferAccess& access, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const;
286 DrawParamsBase m_data;
287 const vk::DeviceInterface& m_vk;
288 vk::Move<vk::VkPipeline> m_pipeline;
289 vk::Move<vk::VkPipelineLayout> m_pipelineLayout;
290 vk::VkFormat m_colorAttachmentFormat;
291 de::SharedPtr<Image> m_colorTargetImage;
292 vk::Move<vk::VkImageView> m_colorTargetView;
293 vk::Move<vk::VkRenderPass> m_renderPass;
294 vk::Move<vk::VkFramebuffer> m_framebuffer;
295 PipelineCreateInfo::VertexInputState m_vertexInputState;
296 de::SharedPtr<Buffer> m_vertexBuffer;
297 vk::Move<vk::VkCommandPool> m_cmdPool;
298 vk::Move<vk::VkCommandBuffer> m_cmdBuffer;
307 DrawTestInstanceBase::DrawTestInstanceBase (Context& context)
308 : vkt::TestInstance (context)
309 , m_vk (context.getDeviceInterface())
310 , m_colorAttachmentFormat (vk::VK_FORMAT_R8G8B8A8_UNORM)
314 DrawTestInstanceBase::~DrawTestInstanceBase (void)
318 void DrawTestInstanceBase::initialize (const DrawParamsBase& data)
322 const vk::VkDevice device = m_context.getDevice();
323 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
325 const vk::VkPhysicalDeviceFeatures features = m_context.getDeviceFeatures();
327 if (features.geometryShader == VK_FALSE &&
328 (m_data.topology == vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY ||
329 m_data.topology == vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY ||
330 m_data.topology == vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY ||
331 m_data.topology == vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY)
334 TCU_THROW(NotSupportedError, "Geometry Not Supported");
337 const PipelineLayoutCreateInfo pipelineLayoutCreateInfo;
338 m_pipelineLayout = vk::createPipelineLayout(m_vk, device, &pipelineLayoutCreateInfo);
340 const vk::VkExtent3D targetImageExtent = { WIDTH, HEIGHT, 1 };
341 const ImageCreateInfo targetImageCreateInfo(vk::VK_IMAGE_TYPE_2D, m_colorAttachmentFormat, targetImageExtent, 1, 1, vk::VK_SAMPLE_COUNT_1_BIT,
342 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);
344 m_colorTargetImage = Image::createAndAlloc(m_vk, device, targetImageCreateInfo, m_context.getDefaultAllocator(), m_context.getUniversalQueueFamilyIndex());
346 const ImageViewCreateInfo colorTargetViewInfo(m_colorTargetImage->object(), vk::VK_IMAGE_VIEW_TYPE_2D, m_colorAttachmentFormat);
347 m_colorTargetView = vk::createImageView(m_vk, device, &colorTargetViewInfo);
349 RenderPassCreateInfo renderPassCreateInfo;
350 renderPassCreateInfo.addAttachment(AttachmentDescription(m_colorAttachmentFormat,
351 vk::VK_SAMPLE_COUNT_1_BIT,
352 vk::VK_ATTACHMENT_LOAD_OP_LOAD,
353 vk::VK_ATTACHMENT_STORE_OP_STORE,
354 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,
355 vk::VK_ATTACHMENT_STORE_OP_STORE,
356 vk::VK_IMAGE_LAYOUT_GENERAL,
357 vk::VK_IMAGE_LAYOUT_GENERAL));
359 const vk::VkAttachmentReference colorAttachmentReference =
362 vk::VK_IMAGE_LAYOUT_GENERAL
365 renderPassCreateInfo.addSubpass(SubpassDescription(vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
370 &colorAttachmentReference,
372 AttachmentReference(),
376 m_renderPass = vk::createRenderPass(m_vk, device, &renderPassCreateInfo);
378 std::vector<vk::VkImageView> colorAttachments(1);
379 colorAttachments[0] = *m_colorTargetView;
381 const FramebufferCreateInfo framebufferCreateInfo(*m_renderPass, colorAttachments, WIDTH, HEIGHT, 1);
383 m_framebuffer = vk::createFramebuffer(m_vk, device, &framebufferCreateInfo);
385 const vk::VkVertexInputBindingDescription vertexInputBindingDescription =
388 (deUint32)sizeof(tcu::Vec4) * 2,
389 vk::VK_VERTEX_INPUT_RATE_VERTEX,
392 const vk::VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
397 vk::VK_FORMAT_R32G32B32A32_SFLOAT,
403 vk::VK_FORMAT_R32G32B32A32_SFLOAT,
404 (deUint32)(sizeof(float)* 4),
408 m_vertexInputState = PipelineCreateInfo::VertexInputState(1,
409 &vertexInputBindingDescription,
411 vertexInputAttributeDescriptions);
413 const vk::VkDeviceSize dataSize = m_data.vertices.size() * sizeof(PositionColorVertex);
414 m_vertexBuffer = Buffer::createAndAlloc(m_vk, device, BufferCreateInfo(dataSize,
415 vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), m_context.getDefaultAllocator(), vk::MemoryRequirement::HostVisible);
417 deUint8* ptr = reinterpret_cast<deUint8*>(m_vertexBuffer->getBoundMemory().getHostPtr());
418 deMemcpy(ptr, &(m_data.vertices[0]), static_cast<size_t>(dataSize));
420 vk::flushAlloc(m_vk, device, m_vertexBuffer->getBoundMemory());
422 const CmdPoolCreateInfo cmdPoolCreateInfo(queueFamilyIndex);
423 m_cmdPool = vk::createCommandPool(m_vk, device, &cmdPoolCreateInfo);
424 m_cmdBuffer = vk::allocateCommandBuffer(m_vk, device, *m_cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
426 initPipeline(device);
429 void DrawTestInstanceBase::initPipeline (const vk::VkDevice device)
431 const vk::Unique<vk::VkShaderModule> vs(createShaderModule(m_vk, device, m_context.getBinaryCollection().get("vert"), 0));
432 const vk::Unique<vk::VkShaderModule> fs(createShaderModule(m_vk, device, m_context.getBinaryCollection().get("frag"), 0));
434 const PipelineCreateInfo::ColorBlendState::Attachment vkCbAttachmentState;
436 vk::VkViewport viewport = vk::makeViewport(WIDTH, HEIGHT);
437 vk::VkRect2D scissor = vk::makeRect2D(WIDTH, HEIGHT);
439 PipelineCreateInfo pipelineCreateInfo(*m_pipelineLayout, *m_renderPass, 0, 0);
440 pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vs, "main", vk::VK_SHADER_STAGE_VERTEX_BIT));
441 pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*fs, "main", vk::VK_SHADER_STAGE_FRAGMENT_BIT));
442 pipelineCreateInfo.addState(PipelineCreateInfo::VertexInputState(m_vertexInputState));
443 pipelineCreateInfo.addState(PipelineCreateInfo::InputAssemblerState(m_data.topology));
444 pipelineCreateInfo.addState(PipelineCreateInfo::ColorBlendState(1, &vkCbAttachmentState));
445 pipelineCreateInfo.addState(PipelineCreateInfo::ViewportState(1, std::vector<vk::VkViewport>(1, viewport), std::vector<vk::VkRect2D>(1, scissor)));
446 pipelineCreateInfo.addState(PipelineCreateInfo::DepthStencilState());
447 pipelineCreateInfo.addState(PipelineCreateInfo::RasterizerState());
448 pipelineCreateInfo.addState(PipelineCreateInfo::MultiSampleState());
450 m_pipeline = vk::createGraphicsPipeline(m_vk, device, DE_NULL, &pipelineCreateInfo);
453 void DrawTestInstanceBase::beginRenderPass (void)
455 const vk::VkClearColorValue clearColor = { { 0.0f, 0.0f, 0.0f, 1.0f } };
457 beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
459 initialTransitionColor2DImage(m_vk, *m_cmdBuffer, m_colorTargetImage->object(), vk::VK_IMAGE_LAYOUT_GENERAL,
460 vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT);
462 const ImageSubresourceRange subresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT);
463 m_vk.cmdClearColorImage(*m_cmdBuffer, m_colorTargetImage->object(),
464 vk::VK_IMAGE_LAYOUT_GENERAL, &clearColor, 1, &subresourceRange);
466 const vk::VkMemoryBarrier memBarrier =
468 vk::VK_STRUCTURE_TYPE_MEMORY_BARRIER,
470 vk::VK_ACCESS_TRANSFER_WRITE_BIT,
471 vk::VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
474 m_vk.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
475 vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
476 0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL);
478 const vk::VkRect2D renderArea = vk::makeRect2D(WIDTH, HEIGHT);
480 vk::beginRenderPass(m_vk, *m_cmdBuffer, *m_renderPass, *m_framebuffer, renderArea, tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
483 void DrawTestInstanceBase::generateRefImage (const tcu::PixelBufferAccess& access, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const
485 const PassthruVertShader vertShader;
486 const PassthruFragShader fragShader;
487 const rr::Program program (&vertShader, &fragShader);
488 const rr::MultisamplePixelBufferAccess colorBuffer = rr::MultisamplePixelBufferAccess::fromSinglesampleAccess(access);
489 const rr::RenderTarget renderTarget (colorBuffer);
490 const rr::RenderState renderState ((rr::ViewportState(colorBuffer)));
491 const rr::Renderer renderer;
493 const rr::VertexAttrib vertexAttribs[] =
495 rr::VertexAttrib(rr::VERTEXATTRIBTYPE_FLOAT, 4, sizeof(tcu::Vec4), 0, &vertices[0]),
496 rr::VertexAttrib(rr::VERTEXATTRIBTYPE_FLOAT, 4, sizeof(tcu::Vec4), 0, &colors[0])
499 renderer.draw(rr::DrawCommand(renderState,
502 DE_LENGTH_OF_ARRAY(vertexAttribs),
504 rr::PrimitiveList(mapVkPrimitiveTopology(m_data.topology), (deUint32)vertices.size(), 0)));
508 class DrawTestInstance : public DrawTestInstanceBase
511 DrawTestInstance (Context& context, const T& data);
512 virtual ~DrawTestInstance (void);
513 virtual void generateDrawData (void);
514 virtual tcu::TestStatus iterate (void);
520 DrawTestInstance<T>::DrawTestInstance (Context& context, const T& data)
521 : DrawTestInstanceBase (context)
529 DrawTestInstance<T>::~DrawTestInstance (void)
534 void DrawTestInstance<T>::generateDrawData (void)
536 DE_FATAL("Using the general case of this function is forbidden!");
540 tcu::TestStatus DrawTestInstance<T>::iterate (void)
542 DE_FATAL("Using the general case of this function is forbidden!");
543 return tcu::TestStatus::fail("");
547 class DrawTestCase : public TestCase
550 DrawTestCase (tcu::TestContext& context, const char* name, const char* desc, const T data);
551 ~DrawTestCase (void);
552 virtual void initPrograms (vk::SourceCollections& programCollection) const;
553 virtual void initShaderSources (void);
554 virtual TestInstance* createInstance (Context& context) const;
558 std::string m_vertShaderSource;
559 std::string m_fragShaderSource;
563 DrawTestCase<T>::DrawTestCase (tcu::TestContext& context, const char* name, const char* desc, const T data)
564 : vkt::TestCase (context, name, desc)
571 DrawTestCase<T>::~DrawTestCase (void)
576 void DrawTestCase<T>::initPrograms (vk::SourceCollections& programCollection) const
578 programCollection.glslSources.add("vert") << glu::VertexSource(m_vertShaderSource);
579 programCollection.glslSources.add("frag") << glu::FragmentSource(m_fragShaderSource);
583 void DrawTestCase<T>::initShaderSources (void)
585 std::stringstream vertShader;
586 vertShader << "#version 430\n"
587 << "layout(location = 0) in vec4 in_position;\n"
588 << "layout(location = 1) in vec4 in_color;\n"
589 << "layout(location = 0) out vec4 out_color;\n"
591 << "out gl_PerVertex {\n"
592 << " vec4 gl_Position;\n"
593 << " float gl_PointSize;\n"
596 << " gl_PointSize = 1.0;\n"
597 << " gl_Position = in_position;\n"
598 << " out_color = in_color;\n"
601 m_vertShaderSource = vertShader.str();
603 std::stringstream fragShader;
604 fragShader << "#version 430\n"
605 << "layout(location = 0) in vec4 in_color;\n"
606 << "layout(location = 0) out vec4 out_color;\n"
609 << " out_color = in_color;\n"
612 m_fragShaderSource = fragShader.str();
616 TestInstance* DrawTestCase<T>::createInstance (Context& context) const
618 return new DrawTestInstance<T>(context, m_data);
623 void DrawTestInstance<DrawParams>::generateDrawData (void)
625 de::Random rnd (SEED ^ m_data.params.firstVertex ^ m_data.params.vertexCount);
627 const deUint32 vectorSize = m_data.params.firstVertex + m_data.params.vertexCount;
629 // Initialize the vector
630 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)));
632 // Fill only the used indexes
633 for (deUint32 vertexIdx = m_data.params.firstVertex; vertexIdx < vectorSize; ++vertexIdx)
635 const float f0 = rnd.getFloat(-1.0f, 1.0f);
636 const float f1 = rnd.getFloat(-1.0f, 1.0f);
638 m_data.vertices[vertexIdx] = PositionColorVertex(
639 tcu::Vec4(f0, f1, 1.0f, 1.0f), // Coord
640 tcu::randomVec4(rnd)); // Color
645 tcu::TestStatus DrawTestInstance<DrawParams>::iterate (void)
647 tcu::TestLog &log = m_context.getTestContext().getLog();
648 const vk::VkQueue queue = m_context.getUniversalQueue();
649 const vk::VkDevice device = m_context.getDevice();
653 const vk::VkDeviceSize vertexBufferOffset = 0;
654 const vk::VkBuffer vertexBuffer = m_vertexBuffer->object();
656 m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
657 m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
658 m_vk.cmdDraw(*m_cmdBuffer, m_data.params.vertexCount, m_data.params.instanceCount, m_data.params.firstVertex, m_data.params.firstInstance);
659 endRenderPass(m_vk, *m_cmdBuffer);
660 endCommandBuffer(m_vk, *m_cmdBuffer);
662 submitCommandsAndWait(m_vk, device, queue, m_cmdBuffer.get());
665 tcu::TextureLevel refImage (vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5 + WIDTH), (int)(0.5 + HEIGHT));
666 tcu::clear(refImage.getAccess(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
668 std::vector<tcu::Vec4> vertices;
669 std::vector<tcu::Vec4> colors;
671 for (std::vector<PositionColorVertex>::const_iterator vertex = m_data.vertices.begin() + m_data.params.firstVertex; vertex != m_data.vertices.end(); ++vertex)
673 vertices.push_back(vertex->position);
674 colors.push_back(vertex->color);
676 generateRefImage(refImage.getAccess(), vertices, colors);
678 const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
679 const tcu::ConstPixelBufferAccess renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
680 vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
682 qpTestResult res = QP_TEST_RESULT_PASS;
684 if (!imageCompare(log, refImage.getAccess(), renderedFrame, m_data.topology))
685 res = QP_TEST_RESULT_FAIL;
687 return tcu::TestStatus(res, qpGetTestResultName(res));
691 void DrawTestInstance<DrawIndexedParams>::generateDrawData (void)
693 de::Random rnd (SEED ^ m_data.params.firstIndex ^ m_data.params.indexCount);
694 const deUint32 indexSize = m_data.params.firstIndex + m_data.params.indexCount;
696 // Initialize the vector with zeros
697 m_data.indexes = std::vector<deUint32>(indexSize, 0);
699 deUint32 highestIndex = 0; // Store to highest index to calculate the vertices size
700 // Fill the indexes from firstIndex
701 for (deUint32 idx = 0; idx < m_data.params.indexCount; ++idx)
703 deUint32 vertexIdx = rnd.getInt(m_data.params.vertexOffset, INDEX_LIMIT);
704 highestIndex = (vertexIdx > highestIndex) ? vertexIdx : highestIndex;
706 m_data.indexes[m_data.params.firstIndex + idx] = vertexIdx;
709 // Fill up the vertex coordinates with zeros until the highestIndex including the vertexOffset
710 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)));
712 // Generate random vertex only where you have index pointing at
713 for (std::vector<deUint32>::const_iterator indexIt = m_data.indexes.begin() + m_data.params.firstIndex; indexIt != m_data.indexes.end(); ++indexIt)
715 // Get iterator to the vertex position with the vertexOffset
716 std::vector<PositionColorVertex>::iterator vertexIt = m_data.vertices.begin() + m_data.params.vertexOffset + *indexIt;
718 tcu::VecAccess<float, 4, 4> positionAccess = vertexIt->position.xyzw();
719 const float f0 = rnd.getFloat(-1.0f, 1.0f);
720 const float f1 = rnd.getFloat(-1.0f, 1.0f);
721 positionAccess = tcu::Vec4(f0, f1, 1.0f, 1.0f);
723 tcu::VecAccess<float, 4, 4> colorAccess = vertexIt->color.xyzw();
724 colorAccess = tcu::randomVec4(rnd);
729 tcu::TestStatus DrawTestInstance<DrawIndexedParams>::iterate (void)
731 tcu::TestLog &log = m_context.getTestContext().getLog();
732 const vk::DeviceInterface& vk = m_context.getDeviceInterface();
733 const vk::VkDevice vkDevice = m_context.getDevice();
734 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
735 const vk::VkQueue queue = m_context.getUniversalQueue();
736 vk::Allocator& allocator = m_context.getDefaultAllocator();
740 const vk::VkDeviceSize vertexBufferOffset = 0;
741 const vk::VkBuffer vertexBuffer = m_vertexBuffer->object();
743 m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
744 m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
746 const deUint32 bufferSize = (deUint32)(m_data.indexes.size() * sizeof(deUint32));
748 vk::Move<vk::VkBuffer> indexBuffer;
750 const vk::VkBufferCreateInfo bufferCreateInfo =
752 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
753 DE_NULL, // const void* pNext;
754 0u, // VkBufferCreateFlags flags;
755 bufferSize, // VkDeviceSize size;
756 vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT, // VkBufferUsageFlags usage;
757 vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
758 1u, // deUint32 queueFamilyIndexCount;
759 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
762 indexBuffer = createBuffer(vk, vkDevice, &bufferCreateInfo);
764 de::MovePtr<vk::Allocation> indexAlloc;
766 indexAlloc = allocator.allocate(getBufferMemoryRequirements(vk, vkDevice, *indexBuffer), vk::MemoryRequirement::HostVisible);
767 VK_CHECK(vk.bindBufferMemory(vkDevice, *indexBuffer, indexAlloc->getMemory(), indexAlloc->getOffset()));
769 deMemcpy(indexAlloc->getHostPtr(), &(m_data.indexes[0]), bufferSize);
771 vk::flushAlloc(m_vk, vkDevice, *indexAlloc);
773 m_vk.cmdBindIndexBuffer(*m_cmdBuffer, *indexBuffer, 0u, m_data.indexType);
774 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);
775 endRenderPass(m_vk, *m_cmdBuffer);
776 endCommandBuffer(m_vk, *m_cmdBuffer);
778 submitCommandsAndWait(m_vk, vkDevice, queue, m_cmdBuffer.get());
781 tcu::TextureLevel refImage (vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5 + WIDTH), (int)(0.5 + HEIGHT));
782 tcu::clear(refImage.getAccess(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
784 std::vector<tcu::Vec4> vertices;
785 std::vector<tcu::Vec4> colors;
787 for (std::vector<deUint32>::const_iterator it = m_data.indexes.begin() + m_data.params.firstIndex; it != m_data.indexes.end(); ++it)
789 deUint32 idx = m_data.params.vertexOffset + *it;
790 vertices.push_back(m_data.vertices[idx].position);
791 colors.push_back(m_data.vertices[idx].color);
793 generateRefImage(refImage.getAccess(), vertices, colors);
795 const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
796 const tcu::ConstPixelBufferAccess renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
797 vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
799 qpTestResult res = QP_TEST_RESULT_PASS;
801 if (!imageCompare(log, refImage.getAccess(), renderedFrame, m_data.topology))
802 res = QP_TEST_RESULT_FAIL;
804 return tcu::TestStatus(res, qpGetTestResultName(res));
808 void DrawTestInstance<DrawIndirectParams>::generateDrawData (void)
810 de::Random rnd(SEED ^ m_data.commands[0].vertexCount ^ m_data.commands[0].firstVertex);
812 deUint32 lastIndex = 0;
814 // Find the interval which will be used
815 for (std::vector<vk::VkDrawIndirectCommand>::const_iterator it = m_data.commands.begin(); it != m_data.commands.end(); ++it)
817 const deUint32 index = it->firstVertex + it->vertexCount;
818 lastIndex = (index > lastIndex) ? index : lastIndex;
821 // Initialize with zeros
822 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)));
824 // Generate random vertices only where necessary
825 for (std::vector<vk::VkDrawIndirectCommand>::const_iterator it = m_data.commands.begin(); it != m_data.commands.end(); ++it)
827 std::vector<PositionColorVertex>::iterator vertexStart = m_data.vertices.begin() + it->firstVertex;
829 for (deUint32 idx = 0; idx < it->vertexCount; ++idx)
831 std::vector<PositionColorVertex>::iterator vertexIt = vertexStart + idx;
833 tcu::VecAccess<float, 4, 4> positionAccess = vertexIt->position.xyzw();
834 const float f0 = rnd.getFloat(-1.0f, 1.0f);
835 const float f1 = rnd.getFloat(-1.0f, 1.0f);
836 positionAccess = tcu::Vec4(f0, f1, 1.0f, 1.0f);
838 tcu::VecAccess<float, 4, 4> colorAccess = vertexIt->color.xyzw();
839 colorAccess = tcu::randomVec4(rnd);
845 tcu::TestStatus DrawTestInstance<DrawIndirectParams>::iterate (void)
847 tcu::TestLog &log = m_context.getTestContext().getLog();
848 const vk::DeviceInterface& vk = m_context.getDeviceInterface();
849 const vk::VkDevice vkDevice = m_context.getDevice();
850 vk::Allocator& allocator = m_context.getDefaultAllocator();
851 const vk::VkQueue queue = m_context.getUniversalQueue();
852 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
853 const vk::VkPhysicalDeviceFeatures features = m_context.getDeviceFeatures();
857 const vk::VkDeviceSize vertexBufferOffset = 0;
858 const vk::VkBuffer vertexBuffer = m_vertexBuffer->object();
860 m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
861 m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
863 vk::Move<vk::VkBuffer> indirectBuffer;
864 de::MovePtr<vk::Allocation> indirectAlloc;
867 const vk::VkDeviceSize indirectInfoSize = m_data.commands.size() * sizeof(vk::VkDrawIndirectCommand);
869 const vk::VkBufferCreateInfo indirectCreateInfo =
871 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
872 DE_NULL, // const void* pNext;
873 0u, // VkBufferCreateFlags flags;
874 indirectInfoSize, // VkDeviceSize size;
875 vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, // VkBufferUsageFlags usage;
876 vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
877 1u, // deUint32 queueFamilyIndexCount;
878 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
881 indirectBuffer = createBuffer(vk, vkDevice, &indirectCreateInfo);
882 indirectAlloc = allocator.allocate(getBufferMemoryRequirements(vk, vkDevice, *indirectBuffer), vk::MemoryRequirement::HostVisible);
883 VK_CHECK(vk.bindBufferMemory(vkDevice, *indirectBuffer, indirectAlloc->getMemory(), indirectAlloc->getOffset()));
885 deMemcpy(indirectAlloc->getHostPtr(), &(m_data.commands[0]), (size_t)indirectInfoSize);
887 vk::flushAlloc(m_vk, vkDevice, *indirectAlloc);
890 // If multiDrawIndirect not supported execute single calls
891 if (m_data.commands.size() > 1 && !(features.multiDrawIndirect))
893 for (deUint32 cmdIdx = 0; cmdIdx < m_data.commands.size(); ++cmdIdx)
895 const deUint32 offset = (deUint32)(indirectAlloc->getOffset() + cmdIdx * sizeof(vk::VkDrawIndirectCommand));
896 m_vk.cmdDrawIndirect(*m_cmdBuffer, *indirectBuffer, offset, 1, sizeof(vk::VkDrawIndirectCommand));
901 m_vk.cmdDrawIndirect(*m_cmdBuffer, *indirectBuffer, indirectAlloc->getOffset(), (deUint32)m_data.commands.size(), sizeof(vk::VkDrawIndirectCommand));
904 endRenderPass(m_vk, *m_cmdBuffer);
905 endCommandBuffer(m_vk, *m_cmdBuffer);
907 submitCommandsAndWait(m_vk, vkDevice, queue, m_cmdBuffer.get());
910 tcu::TextureLevel refImage (vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5 + WIDTH), (int)(0.5 + HEIGHT));
911 tcu::clear(refImage.getAccess(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
913 for (std::vector<vk::VkDrawIndirectCommand>::const_iterator it = m_data.commands.begin(); it != m_data.commands.end(); ++it)
915 std::vector<tcu::Vec4> vertices;
916 std::vector<tcu::Vec4> colors;
918 std::vector<PositionColorVertex>::const_iterator firstIt = m_data.vertices.begin() + it->firstVertex;
919 std::vector<PositionColorVertex>::const_iterator lastIt = firstIt + it->vertexCount;
921 for (std::vector<PositionColorVertex>::const_iterator vertex = firstIt; vertex != lastIt; ++vertex)
923 vertices.push_back(vertex->position);
924 colors.push_back(vertex->color);
926 generateRefImage(refImage.getAccess(), vertices, colors);
929 const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
930 const tcu::ConstPixelBufferAccess renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
931 vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
933 qpTestResult res = QP_TEST_RESULT_PASS;
935 if (!imageCompare(log, refImage.getAccess(), renderedFrame, m_data.topology))
936 res = QP_TEST_RESULT_FAIL;
938 return tcu::TestStatus(res, qpGetTestResultName(res));
942 void DrawTestInstance<DrawIndexedIndirectParams>::generateDrawData (void)
944 de::Random rnd (SEED ^ m_data.commands[0].firstIndex ^ m_data.commands[0].indexCount);
946 deUint32 lastIndex = 0;
948 // Get the maximum range of indexes
949 for (std::vector<vk::VkDrawIndexedIndirectCommand>::const_iterator it = m_data.commands.begin(); it != m_data.commands.end(); ++it)
951 const deUint32 index = it->firstIndex + it->indexCount;
952 lastIndex = (index > lastIndex) ? index : lastIndex;
955 // Initialize the vector with zeros
956 m_data.indexes = std::vector<deUint32>(lastIndex, 0);
958 deUint32 highestIndex = 0;
960 // Generate random indexes for the ranges
961 for (std::vector<vk::VkDrawIndexedIndirectCommand>::const_iterator it = m_data.commands.begin(); it != m_data.commands.end(); ++it)
963 for (deUint32 idx = 0; idx < it->indexCount; ++idx)
965 const deUint32 vertexIdx = rnd.getInt(it->vertexOffset, INDEX_LIMIT);
966 const deUint32 maxIndex = vertexIdx + it->vertexOffset;
968 highestIndex = (maxIndex > highestIndex) ? maxIndex : highestIndex;
969 m_data.indexes[it->firstIndex + idx] = vertexIdx;
973 // Initialize the vertex vector
974 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)));
976 // Generate random vertices in the used locations
977 for (std::vector<vk::VkDrawIndexedIndirectCommand>::const_iterator cmdIt = m_data.commands.begin(); cmdIt != m_data.commands.end(); ++cmdIt)
979 deUint32 firstIdx = cmdIt->firstIndex;
980 deUint32 lastIdx = firstIdx + cmdIt->indexCount;
982 for (deUint32 idx = firstIdx; idx < lastIdx; ++idx)
984 std::vector<PositionColorVertex>::iterator vertexIt = m_data.vertices.begin() + cmdIt->vertexOffset + m_data.indexes[idx];
986 tcu::VecAccess<float, 4, 4> positionAccess = vertexIt->position.xyzw();
987 const float f0 = rnd.getFloat(-1.0f, 1.0f);
988 const float f1 = rnd.getFloat(-1.0f, 1.0f);
989 positionAccess = tcu::Vec4(f0, f1, 1.0f, 1.0f);
991 tcu::VecAccess<float, 4, 4> colorAccess = vertexIt->color.xyzw();
992 colorAccess = tcu::randomVec4(rnd);
998 tcu::TestStatus DrawTestInstance<DrawIndexedIndirectParams>::iterate (void)
1000 tcu::TestLog &log = m_context.getTestContext().getLog();
1001 const vk::DeviceInterface& vk = m_context.getDeviceInterface();
1002 const vk::VkDevice vkDevice = m_context.getDevice();
1003 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1004 const vk::VkQueue queue = m_context.getUniversalQueue();
1005 vk::Allocator& allocator = m_context.getDefaultAllocator();
1006 const vk::VkPhysicalDeviceFeatures features = m_context.getDeviceFeatures();
1010 const vk::VkDeviceSize vertexBufferOffset = 0;
1011 const vk::VkBuffer vertexBuffer = m_vertexBuffer->object();
1013 m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
1014 m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
1016 vk::Move<vk::VkBuffer> indirectBuffer;
1017 de::MovePtr<vk::Allocation> indirectAlloc;
1020 const vk::VkDeviceSize indirectInfoSize = m_data.commands.size() * sizeof(vk::VkDrawIndexedIndirectCommand);
1022 const vk::VkBufferCreateInfo indirectCreateInfo =
1024 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
1025 DE_NULL, // const void* pNext;
1026 0u, // VkBufferCreateFlags flags;
1027 indirectInfoSize, // VkDeviceSize size;
1028 vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, // VkBufferUsageFlags usage;
1029 vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1030 1u, // deUint32 queueFamilyIndexCount;
1031 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
1034 indirectBuffer = createBuffer(vk, vkDevice, &indirectCreateInfo);
1035 indirectAlloc = allocator.allocate(getBufferMemoryRequirements(vk, vkDevice, *indirectBuffer), vk::MemoryRequirement::HostVisible);
1036 VK_CHECK(vk.bindBufferMemory(vkDevice, *indirectBuffer, indirectAlloc->getMemory(), indirectAlloc->getOffset()));
1038 deMemcpy(indirectAlloc->getHostPtr(), &(m_data.commands[0]), (size_t)indirectInfoSize);
1040 vk::flushAlloc(m_vk, vkDevice, *indirectAlloc);
1043 const deUint32 bufferSize = (deUint32)(m_data.indexes.size() * sizeof(deUint32));
1045 vk::Move<vk::VkBuffer> indexBuffer;
1047 const vk::VkBufferCreateInfo bufferCreateInfo =
1049 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
1050 DE_NULL, // const void* pNext;
1051 0u, // VkBufferCreateFlags flags;
1052 bufferSize, // VkDeviceSize size;
1053 vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT, // VkBufferUsageFlags usage;
1054 vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1055 1u, // deUint32 queueFamilyIndexCount;
1056 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
1059 indexBuffer = createBuffer(vk, vkDevice, &bufferCreateInfo);
1061 de::MovePtr<vk::Allocation> indexAlloc;
1063 indexAlloc = allocator.allocate(getBufferMemoryRequirements(vk, vkDevice, *indexBuffer), vk::MemoryRequirement::HostVisible);
1064 VK_CHECK(vk.bindBufferMemory(vkDevice, *indexBuffer, indexAlloc->getMemory(), indexAlloc->getOffset()));
1066 deMemcpy(indexAlloc->getHostPtr(), &(m_data.indexes[0]), bufferSize);
1068 vk::flushAlloc(m_vk, vkDevice, *indexAlloc);
1070 m_vk.cmdBindIndexBuffer(*m_cmdBuffer, *indexBuffer, 0u, m_data.indexType);
1072 // If multiDrawIndirect not supported execute single calls
1073 if (m_data.commands.size() > 1 && !(features.multiDrawIndirect))
1075 for (deUint32 cmdIdx = 0; cmdIdx < m_data.commands.size(); ++cmdIdx)
1077 const deUint32 offset = (deUint32)(indirectAlloc->getOffset() + cmdIdx * sizeof(vk::VkDrawIndexedIndirectCommand));
1078 m_vk.cmdDrawIndexedIndirect(*m_cmdBuffer, *indirectBuffer, offset, 1, sizeof(vk::VkDrawIndexedIndirectCommand));
1083 m_vk.cmdDrawIndexedIndirect(*m_cmdBuffer, *indirectBuffer, indirectAlloc->getOffset(), (deUint32)m_data.commands.size(), sizeof(vk::VkDrawIndexedIndirectCommand));
1086 endRenderPass(m_vk, *m_cmdBuffer);
1087 endCommandBuffer(m_vk, *m_cmdBuffer);
1089 submitCommandsAndWait(m_vk, vkDevice, queue, m_cmdBuffer.get());
1092 tcu::TextureLevel refImage (vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5 + WIDTH), (int)(0.5 + HEIGHT));
1093 tcu::clear(refImage.getAccess(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
1095 for (std::vector<vk::VkDrawIndexedIndirectCommand>::const_iterator cmd = m_data.commands.begin(); cmd != m_data.commands.end(); ++cmd)
1097 std::vector<tcu::Vec4> vertices;
1098 std::vector<tcu::Vec4> colors;
1100 for (deUint32 idx = 0; idx < cmd->indexCount; ++idx)
1102 const deUint32 vertexIndex = cmd->vertexOffset + m_data.indexes[cmd->firstIndex + idx];
1103 vertices.push_back(m_data.vertices[vertexIndex].position);
1104 colors.push_back(m_data.vertices[vertexIndex].color);
1106 generateRefImage(refImage.getAccess(), vertices, colors);
1109 const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
1110 const tcu::ConstPixelBufferAccess renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
1111 vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
1113 qpTestResult res = QP_TEST_RESULT_PASS;
1115 if (!imageCompare(log, refImage.getAccess(), renderedFrame, m_data.topology))
1116 res = QP_TEST_RESULT_FAIL;
1118 return tcu::TestStatus(res, qpGetTestResultName(res));
1121 typedef DrawTestCase<DrawParams> DrawCase;
1122 typedef DrawTestCase<DrawIndexedParams> IndexedCase;
1123 typedef DrawTestCase<DrawIndirectParams> IndirectCase;
1124 typedef DrawTestCase<DrawIndexedIndirectParams> IndexedIndirectCase;
1126 struct TestCaseParams
1128 const DrawCommandType command;
1129 const vk::VkPrimitiveTopology topology;
1131 TestCaseParams (const DrawCommandType cmd, const vk::VkPrimitiveTopology top)
1139 void populateSubGroup (tcu::TestCaseGroup* testGroup, const TestCaseParams caseParams)
1141 de::Random rnd (SEED ^ deStringHash(testGroup->getName()));
1142 tcu::TestContext& testCtx = testGroup->getTestContext();
1143 const DrawCommandType command = caseParams.command;
1144 const vk::VkPrimitiveTopology topology = caseParams.topology;
1146 for (deUint32 primitiveCountIdx = 0; primitiveCountIdx < DE_LENGTH_OF_ARRAY(PRIMITIVE_COUNT); ++primitiveCountIdx)
1148 const deUint32 primitives = PRIMITIVE_COUNT[primitiveCountIdx];
1150 deUint32 multiplier = 1;
1151 deUint32 offset = 0;
1152 // Calculated by Vulkan 23.1
1155 case vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST: break;
1156 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST: multiplier = 2; break;
1157 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP: break;
1158 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST: multiplier = 3; break;
1159 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP: break;
1160 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN: offset = 1; break;
1161 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY: multiplier = 4; offset = 1; break;
1162 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY: offset = 1; break;
1163 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY: multiplier = 6; break;
1164 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY: multiplier = 2; break;
1165 default: DE_FATAL("Unsupported topology.");
1168 const deUint32 vertexCount = multiplier * primitives + offset;
1169 std::string name = de::toString(primitives);
1173 case DRAW_COMMAND_TYPE_DRAW:
1175 deUint32 firstPrimitive = rnd.getInt(0, primitives);
1176 deUint32 firstVertex = multiplier * firstPrimitive;
1177 testGroup->addChild(new DrawCase(testCtx, name.c_str(), "vkCmdDraw testcase.",
1178 DrawParams(topology, vertexCount, 1, firstVertex, 0))
1182 case DRAW_COMMAND_TYPE_DRAW_INDEXED:
1184 deUint32 firstIndex = rnd.getInt(0, OFFSET_LIMIT);
1185 deUint32 vertexOffset = rnd.getInt(0, OFFSET_LIMIT);
1186 testGroup->addChild(new IndexedCase(testCtx, name.c_str(), "vkCmdDrawIndexed testcase.",
1187 DrawIndexedParams(topology, vk::VK_INDEX_TYPE_UINT32, vertexCount, 1, firstIndex, vertexOffset, 0))
1191 case DRAW_COMMAND_TYPE_DRAW_INDIRECT:
1193 deUint32 firstVertex = rnd.getInt(0, OFFSET_LIMIT);
1195 DrawIndirectParams params = DrawIndirectParams(topology);
1197 params.addCommand(vertexCount, 1, 0, 0);
1198 testGroup->addChild(new IndirectCase(testCtx, (name + "_single_command").c_str(), "vkCmdDrawIndirect testcase.", params));
1200 params.addCommand(vertexCount, 1, firstVertex, 0);
1201 testGroup->addChild(new IndirectCase(testCtx, (name + "_multi_command").c_str(), "vkCmdDrawIndirect testcase.", params));
1204 case DRAW_COMMAND_TYPE_DRAW_INDEXED_INDIRECT:
1206 deUint32 firstIndex = rnd.getInt(vertexCount, OFFSET_LIMIT);
1207 deUint32 vertexOffset = rnd.getInt(vertexCount, OFFSET_LIMIT);
1209 DrawIndexedIndirectParams params = DrawIndexedIndirectParams(topology, vk::VK_INDEX_TYPE_UINT32);
1210 params.addCommand(vertexCount, 1, 0, 0, 0);
1211 testGroup->addChild(new IndexedIndirectCase(testCtx, (name + "_single_command").c_str(), "vkCmdDrawIndexedIndirect testcase.", params));
1213 params.addCommand(vertexCount, 1, firstIndex, vertexOffset, 0);
1214 testGroup->addChild(new IndexedIndirectCase(testCtx, (name + "_multi_command").c_str(), "vkCmdDrawIndexedIndirect testcase.", params));
1218 DE_FATAL("Unsupported draw command.");
1223 void createTopologyGroups (tcu::TestCaseGroup* testGroup, const DrawCommandType cmdType)
1225 for (deUint32 idx = 0; idx != vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST; ++idx)
1227 const vk::VkPrimitiveTopology topology = vk::VkPrimitiveTopology(idx);
1228 const std::string groupName = de::toLower(getPrimitiveTopologyName(topology)).substr(22);
1229 addTestGroup(testGroup, groupName, "Testcases with a specific topology.", populateSubGroup, TestCaseParams(cmdType, topology));
1233 void createDrawTests (tcu::TestCaseGroup* testGroup)
1235 for (deUint32 idx = 0; idx < DRAW_COMMAND_TYPE_DRAW_LAST; ++idx)
1237 const DrawCommandType command = DrawCommandType(idx);
1238 addTestGroup(testGroup, getDrawCommandTypeName(command), "Group for testing a specific draw command.", createTopologyGroups, command);
1242 tcu::TestCaseGroup* createBasicDrawTests (tcu::TestContext& testCtx)
1244 return createTestGroup(testCtx, "basic_draw", "Basic drawing tests", createDrawTests);