1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2021 Google LLC
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
21 * \brief VK_EXT_primitives_generated_query Tests
22 *//*--------------------------------------------------------------------*/
24 #include "vktPrimitivesGeneratedQueryTests.hpp"
26 #include "vktTestCase.hpp"
27 #include "vktTestGroupUtil.hpp"
29 #include "vkCmdUtil.hpp"
30 #include "vkImageUtil.hpp"
31 #include "vkMemUtil.hpp"
32 #include "vkObjUtil.hpp"
33 #include "vkQueryUtil.hpp"
34 #include "vkTypeUtil.hpp"
36 #include "tcuTestLog.hpp"
43 namespace TransformFeedback
52 IMAGE_HEIGHT = IMAGE_WIDTH,
65 QUERY_RESET_TYPE_QUEUE,
66 QUERY_RESET_TYPE_HOST,
73 QUERY_RESULT_TYPE_32_BIT,
74 QUERY_RESULT_TYPE_64_BIT,
75 QUERY_RESULT_TYPE_PGQ_32_XFB_64,
76 QUERY_RESULT_TYPE_PGQ_64_XFB_32,
78 QUERY_RESULT_TYPE_LAST
84 SHADER_STAGE_TESSELLATION_EVALUATION,
85 SHADER_STAGE_GEOMETRY,
90 enum RasterizationCase
95 RAST_CASE_NO_ATTACHMENT,
96 RAST_CASE_COLOR_WRITE_DISABLE_STATIC,
97 RAST_CASE_COLOR_WRITE_DISABLE_DYNAMIC,
104 VERTEX_STREAM_DEFAULT = -1,
109 enum CommandBufferCase
111 CMD_BUF_CASE_SINGLE_DRAW,
116 struct TestParameters
118 QueryReadType queryReadType;
119 QueryResetType queryResetType;
120 QueryResultType queryResultType;
121 ShaderStage shaderStage;
122 deBool transformFeedback;
123 RasterizationCase rastCase;
124 deBool depthStencilAttachment;
125 VkPrimitiveTopology primitiveTopology;
126 VertexStream pgqStream;
127 VertexStream xfbStream;
128 CommandBufferCase cmdBufCase;
130 bool pgqDefault (void) const { return pgqStream == VERTEX_STREAM_DEFAULT; }
131 bool xfbDefault (void) const { return xfbStream == VERTEX_STREAM_DEFAULT; }
132 deUint32 pgqStreamIndex (void) const { return pgqDefault() ? 0 : static_cast<deUint32>(pgqStream); }
133 deUint32 xfbStreamIndex (void) const { return xfbDefault() ? 0 : static_cast<deUint32>(xfbStream); }
134 bool multipleStreams (void) const { return pgqStreamIndex() != xfbStreamIndex(); }
135 bool nonZeroStreams (void) const { return (pgqStreamIndex() != 0) || (xfbStreamIndex() != 0); }
136 bool rastDiscard (void) const { return rastCase == RAST_CASE_DISCARD; }
137 bool colorAttachment (void) const { return !rastDiscard() && rastCase != RAST_CASE_NO_ATTACHMENT; }
138 bool staticColorWriteDisable (void) const { return rastCase == RAST_CASE_COLOR_WRITE_DISABLE_STATIC; }
139 bool dynamicColorWriteDisable (void) const { return rastCase == RAST_CASE_COLOR_WRITE_DISABLE_DYNAMIC; }
140 bool colorWriteDisable (void) const { return staticColorWriteDisable() || dynamicColorWriteDisable(); }
145 deUint32 primitiveSize; // Size of the primitive.
146 deBool hasAdjacency; // True if topology has adjacency.
147 const char* inputString; // Layout qualifier identifier for geometry shader input.
148 const char* outputString; // Layout qualifier identifier for geometry shader output.
149 std::function<deUint64(deUint64)> getNumPrimitives; // Number of primitives generated.
150 std::function<deUint64(deUint64)> getNumVertices; // Number of vertices generated.
153 const std::map<VkPrimitiveTopology, TopologyInfo> topologyData =
155 { VK_PRIMITIVE_TOPOLOGY_POINT_LIST, { 1, DE_FALSE, "points", "points", [](deUint64 vtxCount) { return vtxCount; }, [](deUint64 primCount) { return primCount; } } },
156 { VK_PRIMITIVE_TOPOLOGY_LINE_LIST, { 2, DE_FALSE, "lines", "line_strip", [](deUint64 vtxCount) { return vtxCount / 2u; }, [](deUint64 primCount) { return primCount * 2u; } } },
157 { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, { 2, DE_FALSE, "lines", "line_strip", [](deUint64 vtxCount) { return vtxCount - 1u; }, [](deUint64 primCount) { return primCount + 1u; } } },
158 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, { 3, DE_FALSE, "triangles", "triangle_strip", [](deUint64 vtxCount) { return vtxCount / 3u; }, [](deUint64 primCount) { return primCount * 3u; } } },
159 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, { 3, DE_FALSE, "triangles", "triangle_strip", [](deUint64 vtxCount) { return vtxCount - 2u; }, [](deUint64 primCount) { return primCount + 2u; } } },
160 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, { 3, DE_FALSE, "triangles", "triangle_strip", [](deUint64 vtxCount) { return vtxCount - 2u; }, [](deUint64 primCount) { return primCount + 2u; } } },
161 { VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY, { 2, DE_TRUE, "lines_adjacency", "line_strip", [](deUint64 vtxCount) { return vtxCount / 4u; }, [](deUint64 primCount) { return primCount * 4u; } } },
162 { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY, { 2, DE_TRUE, "lines_adjacency", "line_strip", [](deUint64 vtxCount) { return vtxCount - 3u; }, [](deUint64 primCount) { return primCount + 3u; } } },
163 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY, { 3, DE_TRUE, "triangles_adjacency", "triangle_strip", [](deUint64 vtxCount) { return vtxCount / 6u; }, [](deUint64 primCount) { return primCount * 6u; } } },
164 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY, { 3, DE_TRUE, "triangles_adjacency", "triangle_strip", [](deUint64 vtxCount) { return (vtxCount - 4u) / 2u; }, [](deUint64 primCount) { return primCount * 2u + 4; } } },
165 { VK_PRIMITIVE_TOPOLOGY_PATCH_LIST, { 3, DE_FALSE, "ERROR", "ERROR", [](deUint64 vtxCount) { return vtxCount / 3u; }, [](deUint64 primCount) { return primCount * 3u; } } },
168 class PrimitivesGeneratedQueryTestInstance : public vkt::TestInstance
171 PrimitivesGeneratedQueryTestInstance (vkt::Context &context, const TestParameters& parameters)
172 : vkt::TestInstance (context)
173 , m_parameters (parameters)
178 tcu::TestStatus iterate (void);
179 VkFormat selectDepthStencilFormat (void);
180 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface& vk,
181 const VkDevice device,
182 const VkRenderPass renderPass);
183 void fillVertexBuffer (tcu::Vec2* vertices,
184 const deUint64 primitivesGenerated);
185 const TestParameters m_parameters;
188 tcu::TestStatus PrimitivesGeneratedQueryTestInstance::iterate (void)
190 const DeviceInterface& vk = m_context.getDeviceInterface();
191 const VkDevice device = m_context.getDevice();
192 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
193 const VkQueue queue = m_context.getUniversalQueue();
194 Allocator& allocator = m_context.getDefaultAllocator();
196 const VkFormat colorFormat = m_parameters.colorAttachment() ? VK_FORMAT_R8G8B8A8_UNORM : VK_FORMAT_UNDEFINED;
197 Move<VkImage> colorImage;
198 de::MovePtr<Allocation> colorImageAllocation;
200 if (m_parameters.colorAttachment())
202 const VkImageCreateInfo colorImageCreateInfo =
204 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType
205 DE_NULL, // const void* pNext
206 0u, // VkImageCreateFlags flags
207 VK_IMAGE_TYPE_2D, // VkImageType imageType
208 colorFormat, // VkFormat format
209 makeExtent3D(IMAGE_WIDTH, IMAGE_HEIGHT, 1), // VkExtent3D extent
210 1u, // deUint32 mipLevels
211 1u, // deUint32 arrayLayers
212 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
213 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling
214 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, // VkImageUsageFlags usage
215 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode
216 0u, // deUint32 queueFamilyIndexCount
217 DE_NULL, // const deUint32* pQueueFamilyIndices
218 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout
221 colorImage = makeImage(vk, device, colorImageCreateInfo);
222 colorImageAllocation = bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any);
225 const VkFormat dsFormat = m_parameters.depthStencilAttachment ? PrimitivesGeneratedQueryTestInstance::selectDepthStencilFormat() : VK_FORMAT_UNDEFINED;
227 if (m_parameters.depthStencilAttachment && dsFormat == VK_FORMAT_UNDEFINED)
228 return tcu::TestStatus::fail("VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT feature must be supported for at least one of VK_FORMAT_D24_UNORM_S8_UINT and VK_FORMAT_D32_SFLOAT_S8_UINT.");
230 Move<VkImage> dsImage;
231 de::MovePtr<Allocation> dsImageAllocation;
233 if (m_parameters.depthStencilAttachment)
235 const VkImageCreateInfo dsImageCreateInfo =
237 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType
238 DE_NULL, // const void* pNext
239 0u, // VkImageCreateFlags flags
240 VK_IMAGE_TYPE_2D, // VkImageType imageType
241 dsFormat, // VkFormat format
242 makeExtent3D(IMAGE_WIDTH, IMAGE_HEIGHT, 1), // VkExtent3D extent
243 1u, // deUint32 mipLevels
244 1u, // deUint32 arrayLayers
245 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
246 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling
247 VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, // VkImageUsageFlags usage
248 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode
249 0u, // deUint32 queueFamilyIndexCount
250 DE_NULL, // const deUint32* pQueueFamilyIndices
251 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout
254 dsImage = makeImage(vk, device, dsImageCreateInfo);
255 dsImageAllocation = bindImage(vk, device, allocator, *dsImage, MemoryRequirement::Any);
258 const VkDeviceSize primitivesGenerated = 32;
259 const deUint32 baseMipLevel = 0;
260 const deUint32 levelCount = 1;
261 const deUint32 baseArrayLayer = 0;
262 const deUint32 layerCount = 1;
264 Move<VkImageView> colorImageView;
265 Move<VkImageView> dsImageView;
266 std::vector<VkImageView> imageViews;
268 if (m_parameters.colorAttachment())
270 const VkImageSubresourceRange colorSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, baseMipLevel, levelCount, baseArrayLayer, layerCount);
271 colorImageView = makeImageView(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange);
272 imageViews.push_back(*colorImageView);
275 if (m_parameters.depthStencilAttachment)
277 const VkImageSubresourceRange dsSubresourceRange = makeImageSubresourceRange((VK_IMAGE_ASPECT_DEPTH_BIT | vk::VK_IMAGE_ASPECT_STENCIL_BIT), baseMipLevel, levelCount, baseArrayLayer, layerCount);
278 dsImageView = makeImageView(vk, device, *dsImage, VK_IMAGE_VIEW_TYPE_2D, dsFormat, dsSubresourceRange);
279 imageViews.push_back(*dsImageView);
282 const Unique<VkRenderPass> renderPass (makeRenderPass(vk, device, colorFormat, dsFormat, VK_ATTACHMENT_LOAD_OP_DONT_CARE));
283 const Unique<VkFramebuffer> framebuffer (makeFramebuffer(vk, device, *renderPass, (deUint32)imageViews.size(), imageViews.data(), IMAGE_WIDTH, IMAGE_HEIGHT));
284 const Unique<VkPipeline> pipeline (PrimitivesGeneratedQueryTestInstance::makeGraphicsPipeline(vk, device, *renderPass));
285 Move<VkBuffer> vtxBuffer;
286 de::MovePtr<Allocation> vtxBufferAlloc;
289 const VkBufferUsageFlags usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
290 const std::vector<deUint32> queueFamilyIndices (1, queueFamilyIndex);
291 const VkDeviceSize vtxBufferSize = topologyData.at(m_parameters.primitiveTopology).getNumVertices(primitivesGenerated) * sizeof(tcu::Vec2);
292 const VkBufferCreateInfo createInfo = makeBufferCreateInfo(vtxBufferSize, usage, queueFamilyIndices);
294 vtxBuffer = createBuffer(vk, device, &createInfo);
295 vtxBufferAlloc = allocator.allocate(getBufferMemoryRequirements(vk, device, *vtxBuffer), MemoryRequirement::HostVisible);
298 const VkCommandPoolCreateFlags cmdPoolCreateFlags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
299 const VkCommandBufferLevel cmdBufferLevel = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
300 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, cmdPoolCreateFlags, queueFamilyIndex));
301 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer(vk, device, *cmdPool, cmdBufferLevel));
303 const bool pgq64 = (m_parameters.queryResultType == QUERY_RESULT_TYPE_64_BIT ||
304 m_parameters.queryResultType == QUERY_RESULT_TYPE_PGQ_64_XFB_32);
305 const bool xfb64 = (m_parameters.queryResultType == QUERY_RESULT_TYPE_64_BIT ||
306 m_parameters.queryResultType == QUERY_RESULT_TYPE_PGQ_32_XFB_64);
307 const size_t pgqResultSize = pgq64 ? sizeof(deUint64) : sizeof(deUint32);
308 const size_t xfbResultSize = xfb64 ? sizeof(deUint64) * 2 : sizeof(deUint32) * 2;
309 const VkQueryResultFlags pgqResultWidthBit = pgq64 ? VK_QUERY_RESULT_64_BIT : 0;
310 const VkQueryResultFlags xfbResultWidthBit = xfb64 ? VK_QUERY_RESULT_64_BIT : 0;
311 const VkQueryResultFlags pgqResultFlags = VK_QUERY_RESULT_WAIT_BIT | pgqResultWidthBit;
312 const VkQueryResultFlags xfbResultFlags = VK_QUERY_RESULT_WAIT_BIT | xfbResultWidthBit;
314 const deUint32 queryIndex = 0;
315 const deUint32 queryCount = 1;
317 std::vector<deUint8> pgqResults (pgqResultSize, 255u);
318 std::vector<deUint8> xfbResults (xfbResultSize, 255u);
320 const VkQueryPoolCreateInfo pgqCreateInfo =
322 VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, // VkStructureType sType
323 DE_NULL, // const void* pNext
324 0u, // VkQueryPoolCreateFlags flags
325 VK_QUERY_TYPE_PRIMITIVES_GENERATED_EXT, // VkQueryType queryType
326 queryCount, // deUint32 queryCount
327 0u, // VkQueryPipelineStatisticFlags pipelineStatistics
330 const Unique<VkQueryPool> pgqPool (createQueryPool(vk, device, &pgqCreateInfo));
331 Move<VkQueryPool> xfbPool;
333 if (m_parameters.transformFeedback)
335 const VkQueryPoolCreateInfo xfbCreateInfo =
337 VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, // VkStructureType sType
338 DE_NULL, // const void* pNext
339 0u, // VkQueryPoolCreateFlags flags
340 VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT, // VkQueryType queryType
341 queryCount, // deUint32 queryCount
342 0u, // VkQueryPipelineStatisticFlags pipelineStatistics
345 xfbPool = createQueryPool(vk, device, &xfbCreateInfo);
348 Move<VkBuffer> pgqResultsBuffer;
349 Move<VkBuffer> xfbResultsBuffer;
350 de::MovePtr<Allocation> pgqResultsBufferAlloc;
351 de::MovePtr<Allocation> xfbResultsBufferAlloc;
353 if (m_parameters.queryReadType == QUERY_READ_TYPE_COPY)
355 const VkBufferUsageFlags usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
356 const std::vector<deUint32> queueFamilyIndices (1, queueFamilyIndex);
357 const VkBufferCreateInfo pgqBufferCreateInfo = makeBufferCreateInfo(pgqResultSize, usage, queueFamilyIndices);
359 pgqResultsBuffer = createBuffer(vk, device, &pgqBufferCreateInfo);
360 pgqResultsBufferAlloc = allocator.allocate(getBufferMemoryRequirements(vk, device, *pgqResultsBuffer), MemoryRequirement::HostVisible);
362 VK_CHECK(vk.bindBufferMemory(device, *pgqResultsBuffer, pgqResultsBufferAlloc->getMemory(), pgqResultsBufferAlloc->getOffset()));
364 if (m_parameters.transformFeedback)
366 const VkBufferCreateInfo xfbBufferCreateInfo = makeBufferCreateInfo(xfbResultSize, usage, queueFamilyIndices);
368 xfbResultsBuffer = createBuffer(vk, device, &xfbBufferCreateInfo);
369 xfbResultsBufferAlloc = allocator.allocate(getBufferMemoryRequirements(vk, device, *xfbResultsBuffer), MemoryRequirement::HostVisible);
371 VK_CHECK(vk.bindBufferMemory(device, *xfbResultsBuffer, xfbResultsBufferAlloc->getMemory(), xfbResultsBufferAlloc->getOffset()));
375 const VkDeviceSize primitivesWritten = primitivesGenerated - 3;
376 const VkDeviceSize verticesWritten = topologyData.at(m_parameters.primitiveTopology).getNumVertices(primitivesWritten);
377 const VkDeviceSize primitiveSize = m_parameters.nonZeroStreams() ? 1 : topologyData.at(m_parameters.primitiveTopology).primitiveSize;
378 const VkDeviceSize bytesPerVertex = 4 * sizeof(float);
379 const VkDeviceSize xfbBufferSize = primitivesWritten * primitiveSize * bytesPerVertex;
380 Move<VkBuffer> xfbBuffer;
381 de::MovePtr<Allocation> xfbBufferAlloc;
383 if (m_parameters.transformFeedback)
385 const VkBufferUsageFlags usage = VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT;
386 const std::vector<deUint32> queueFamilyIndices (1, queueFamilyIndex);
387 const VkBufferCreateInfo createInfo = makeBufferCreateInfo(xfbBufferSize, usage, queueFamilyIndices);
389 xfbBuffer = createBuffer(vk, device, &createInfo);
390 xfbBufferAlloc = allocator.allocate(getBufferMemoryRequirements(vk, device, *xfbBuffer), MemoryRequirement::HostVisible);
392 VK_CHECK(vk.bindBufferMemory(device, *xfbBuffer, xfbBufferAlloc->getMemory(), xfbBufferAlloc->getOffset()));
395 fillVertexBuffer(static_cast<tcu::Vec2*>(vtxBufferAlloc.get()->getHostPtr()), primitivesGenerated);
397 VK_CHECK(vk.bindBufferMemory(device, *vtxBuffer, vtxBufferAlloc->getMemory(), vtxBufferAlloc->getOffset()));
399 beginCommandBuffer(vk, *cmdBuffer);
401 const VkDeviceSize vertexBufferOffset = static_cast<VkDeviceSize>(0);
403 // After query pool creation, each query must be reset before it is used.
404 if (m_parameters.queryResetType == QUERY_RESET_TYPE_QUEUE)
406 vk.cmdResetQueryPool(*cmdBuffer, *pgqPool, queryIndex, queryCount);
408 if (m_parameters.transformFeedback)
409 vk.cmdResetQueryPool(*cmdBuffer, *xfbPool, queryIndex, queryCount);
412 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
414 vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &vtxBuffer.get(), &vertexBufferOffset);
416 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(makeExtent2D(IMAGE_WIDTH, IMAGE_HEIGHT)));
418 const VkQueryControlFlags queryControlFlags = 0;
420 if (m_parameters.pgqDefault())
421 vk.cmdBeginQuery(*cmdBuffer, *pgqPool, queryIndex, queryControlFlags);
423 vk.cmdBeginQueryIndexedEXT(*cmdBuffer, *pgqPool, queryIndex, queryControlFlags, m_parameters.pgqStreamIndex());
425 const deUint32 firstCounterBuffer = 0;
426 const deUint32 counterBufferCount = 0;
427 const VkBuffer* counterBuffers = DE_NULL;
428 const VkDeviceSize* counterBufferOffsets = DE_NULL;
430 if (m_parameters.transformFeedback)
432 const deUint32 firstBinding = 0;
433 const deUint32 bindingCount = 1;
434 const VkDeviceSize offset = 0;
436 vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, firstBinding, bindingCount, &*xfbBuffer, &offset, &xfbBufferSize);
438 if (m_parameters.xfbDefault())
439 vk.cmdBeginQuery(*cmdBuffer, *xfbPool, queryIndex, queryControlFlags);
441 vk.cmdBeginQueryIndexedEXT(*cmdBuffer, *xfbPool, queryIndex, queryControlFlags, m_parameters.xfbStreamIndex());
443 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, firstCounterBuffer, counterBufferCount, counterBuffers, counterBufferOffsets);
446 if (m_parameters.dynamicColorWriteDisable())
448 const deUint32 attachmentCount = 1;
449 const VkBool32 colorWriteEnables = VK_FALSE;
451 vk.cmdSetColorWriteEnableEXT(*cmdBuffer, attachmentCount, &colorWriteEnables);
454 const deUint32 vertexCount = static_cast<deUint32>(topologyData.at(m_parameters.primitiveTopology).getNumVertices(primitivesGenerated));
455 const deUint32 instanceCount = 1u;
456 const deUint32 firstVertex = 0u;
457 const deUint32 firstInstance = 0u;
459 vk.cmdDraw(*cmdBuffer, vertexCount, instanceCount, firstVertex, firstInstance);
461 if (m_parameters.pgqDefault())
462 vk.cmdEndQuery(*cmdBuffer, *pgqPool, queryIndex);
464 vk.cmdEndQueryIndexedEXT(*cmdBuffer, *pgqPool, queryIndex, m_parameters.pgqStreamIndex());
466 if (m_parameters.transformFeedback)
468 if (m_parameters.xfbDefault())
469 vk.cmdEndQuery(*cmdBuffer, *xfbPool, queryIndex);
471 vk.cmdEndQueryIndexedEXT(*cmdBuffer, *xfbPool, queryIndex, m_parameters.xfbStreamIndex());
473 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, firstCounterBuffer, counterBufferCount, counterBuffers, counterBufferOffsets);
476 endRenderPass(vk, *cmdBuffer);
478 if (m_parameters.queryReadType == QUERY_READ_TYPE_COPY)
480 VkBufferMemoryBarrier bufferBarrier =
482 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType
483 DE_NULL, // const void* pNext
484 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask
485 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask
486 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex
487 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex
488 *pgqResultsBuffer, // VkBuffer buffer
489 0u, // VkDeviceSize offset
490 VK_WHOLE_SIZE // VkDeviceSize size
493 vk.cmdCopyQueryPoolResults(*cmdBuffer, *pgqPool, queryIndex, queryCount, *pgqResultsBuffer, 0u, pgqResultSize, pgqResultFlags);
494 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL);
496 if (m_parameters.transformFeedback)
498 bufferBarrier.buffer = *xfbResultsBuffer;
499 vk.cmdCopyQueryPoolResults(*cmdBuffer, *xfbPool, queryIndex, queryCount, *xfbResultsBuffer, 0u, xfbResultSize, xfbResultFlags);
500 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL);
504 endCommandBuffer(vk, *cmdBuffer);
506 // After query pool creation, each query must be reset before it is used.
507 if (m_parameters.queryResetType == QUERY_RESET_TYPE_HOST)
509 vk.resetQueryPool(device, *pgqPool, queryIndex, queryCount);
511 if (m_parameters.transformFeedback)
512 vk.resetQueryPool(device, *xfbPool, queryIndex, queryCount);
515 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
517 if (m_parameters.queryReadType == QUERY_READ_TYPE_COPY)
519 invalidateAlloc(vk, device, *pgqResultsBufferAlloc);
520 deMemcpy(pgqResults.data(), pgqResultsBufferAlloc->getHostPtr(), pgqResults.size());
522 if (m_parameters.transformFeedback)
524 invalidateAlloc(vk, device, *xfbResultsBufferAlloc);
525 deMemcpy(xfbResults.data(), xfbResultsBufferAlloc->getHostPtr(), xfbResults.size());
530 vk.getQueryPoolResults(device, *pgqPool, queryIndex, queryCount, pgqResults.size(), pgqResults.data(), pgqResults.size(), pgqResultFlags);
532 if (m_parameters.transformFeedback)
533 vk.getQueryPoolResults(device, *xfbPool, queryIndex, queryCount, xfbResults.size(), xfbResults.data(), xfbResults.size(), xfbResultFlags);
536 // Validate counters.
540 deUint32 elements32[2];
541 deUint64 elements64[2];
544 const QueryResults* pgqCounters = reinterpret_cast<QueryResults*>(pgqResults.data());
545 const QueryResults* xfbCounters = reinterpret_cast<QueryResults*>(xfbResults.data());
546 const deUint64 pgqGenerated = pgq64 ? pgqCounters->elements64[0] : static_cast<deUint64>(pgqCounters->elements32[0]);
547 const deUint64 xfbWritten = xfb64 ? xfbCounters->elements64[0] : static_cast<deUint64>(xfbCounters->elements32[0]);
548 const deUint64 xfbGenerated = xfb64 ? xfbCounters->elements64[1] : static_cast<deUint64>(xfbCounters->elements32[1]);
549 tcu::TestLog& log = m_context.getTestContext().getLog();
551 log << tcu::TestLog::Message
552 << "primitivesGenerated: " << primitivesGenerated << "\n"
553 << "primitivesWritten: " << primitivesWritten << "\n"
554 << "verticesWritten: " << verticesWritten << "\n"
555 << "xfbBufferSize: " << xfbBufferSize << "\n"
556 << tcu::TestLog::EndMessage;
558 log << tcu::TestLog::Message << "PGQ: Generated " << pgqGenerated << tcu::TestLog::EndMessage;
560 if (m_parameters.transformFeedback)
561 log << tcu::TestLog::Message << "XFB: Written " << xfbWritten << ", generated " << xfbGenerated << tcu::TestLog::EndMessage;
563 if (pgqGenerated != primitivesGenerated)
565 const std::string message = std::string("pgqGenerated == ") + de::toString(pgqGenerated) + ", expected " + de::toString(primitivesGenerated);
566 return tcu::TestStatus::fail(message);
569 if (m_parameters.transformFeedback)
571 if (xfbGenerated != primitivesGenerated)
573 const std::string message = std::string("xfbGenerated == ") + de::toString(xfbGenerated) + ", expected " + de::toString(primitivesGenerated);
574 return tcu::TestStatus::fail(message);
577 if (xfbWritten != primitivesWritten)
579 const std::string message = std::string("xfbWritten == ") + de::toString(xfbWritten) + ", expected " + de::toString(primitivesWritten);
580 return tcu::TestStatus::fail(message);
585 return tcu::TestStatus::pass("Counters OK");
588 VkFormat PrimitivesGeneratedQueryTestInstance::selectDepthStencilFormat (void)
590 constexpr VkFormat formats[] =
592 VK_FORMAT_D32_SFLOAT_S8_UINT,
593 VK_FORMAT_D24_UNORM_S8_UINT
596 const InstanceInterface& vki = m_context.getInstanceInterface();
597 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
599 for (VkFormat format : formats)
601 const VkFormatFeatureFlags features = getPhysicalDeviceFormatProperties(vki, physicalDevice, format).optimalTilingFeatures;
603 if (features & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)
607 return VK_FORMAT_UNDEFINED;
610 Move<VkPipeline> PrimitivesGeneratedQueryTestInstance::makeGraphicsPipeline (const DeviceInterface& vk, const VkDevice device, const VkRenderPass renderPass)
612 const VkDescriptorSetLayout descriptorSetLayout = DE_NULL;
613 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout(vk, device, descriptorSetLayout));
614 const std::vector<VkViewport> viewports (1, makeViewport(makeExtent2D(IMAGE_WIDTH, IMAGE_HEIGHT)));
615 const std::vector<VkRect2D> scissors (1, makeRect2D(makeExtent2D(IMAGE_WIDTH, IMAGE_HEIGHT)));
616 const deUint32 subpass = 0u;
617 const deUint32 patchControlPoints = topologyData.at(VK_PRIMITIVE_TOPOLOGY_PATCH_LIST).primitiveSize;
618 const Unique<VkShaderModule> vertModule (createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
619 Move<VkShaderModule> tescModule;
620 Move<VkShaderModule> teseModule;
621 Move<VkShaderModule> geomModule;
622 Move<VkShaderModule> fragModule;
623 VkVertexInputBindingDescription bindingDescription;
624 VkVertexInputAttributeDescription attributeDescription;
626 if (m_parameters.shaderStage == SHADER_STAGE_TESSELLATION_EVALUATION)
628 tescModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("tesc"), 0u);
629 teseModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("tese"), 0u);
632 if (m_parameters.shaderStage == SHADER_STAGE_GEOMETRY)
633 geomModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("geom"), 0u);
635 if (!m_parameters.rastDiscard())
636 fragModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u);
638 bindingDescription.binding = 0;
639 bindingDescription.stride = sizeof(tcu::Vec2);
640 bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
642 attributeDescription.binding = 0;
643 attributeDescription.location = 0;
644 attributeDescription.format = VK_FORMAT_R32G32_SFLOAT;
645 attributeDescription.offset = 0;
647 const VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo =
649 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType
650 DE_NULL, // const void* pNext
651 0u, // VkPipelineVertexInputStateCreateFlags flags
652 1u, // deUint32 vertexBindingDescriptionCount
653 &bindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions
654 1u, // deUint32 vertexAttributeDescriptionCount
655 &attributeDescription, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions
658 const VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo =
660 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType
661 DE_NULL, // const void* pNext
662 0, // VkPipelineRasterizationStateCreateFlags flags
663 VK_FALSE, // VkBool32 depthClampEnable
664 (m_parameters.rastDiscard() ? VK_TRUE : VK_FALSE), // VkBool32 rasterizerDiscardEnable
665 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode
666 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode
667 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace
668 VK_FALSE, // VkBool32 depthBiasEnable
669 0.0f, // float depthBiasConstantFactor
670 0.0f, // float depthBiasClamp
671 0.0f, // float depthBiasSlopeFactor
672 1.0f // float lineWidth
675 const VkStencilOpState stencilOpState =
677 VK_STENCIL_OP_KEEP, // VkStencilOp failOp
678 VK_STENCIL_OP_KEEP, // VkStencilOp passOp
679 VK_STENCIL_OP_KEEP, // VkStencilOp depthFailOp
680 VK_COMPARE_OP_ALWAYS, // VkCompareOp compareOp
681 0xFFu, // deUint32 compareMask
682 0xFFu, // deUint32 writeMask
683 0, // deUint32 reference
686 const VkPipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo =
688 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType
689 DE_NULL, // const void* pNext
690 0, // VkPipelineDepthStencilStateCreateFlags flags
691 VK_TRUE, // VkBool32 depthTestEnable
692 VK_TRUE, // VkBool32 depthWriteEnable
693 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp
694 VK_FALSE, // VkBool32 depthBoundsTestEnable
695 VK_FALSE, // VkBool32 stencilTestEnable
696 stencilOpState, // VkStencilOpState front
697 stencilOpState, // VkStencilOpState back
698 0.0f, // float minDepthBounds
699 1.0f, // float maxDepthBounds
702 const VkBool32 colorWriteEnables = VK_FALSE;
704 const VkPipelineColorWriteCreateInfoEXT colorWriteCreateInfo =
706 VK_STRUCTURE_TYPE_PIPELINE_COLOR_WRITE_CREATE_INFO_EXT, // VkStructureType sType;
707 DE_NULL, // const void* pNext;
708 1, // deUint32 attachmentCount;
709 &colorWriteEnables // const VkBool32* pColorWriteEnables;
712 const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
714 VK_FALSE, // VkBool32 blendEnable
715 VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcColorBlendFactor
716 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor
717 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp
718 VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcAlphaBlendFactor
719 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor
720 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp
721 VK_COLOR_COMPONENT_R_BIT // VkColorComponentFlags colorWriteMask
722 | VK_COLOR_COMPONENT_G_BIT
723 | VK_COLOR_COMPONENT_B_BIT
724 | VK_COLOR_COMPONENT_A_BIT
727 const VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfo =
729 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType
730 &colorWriteCreateInfo, // const void* pNext
731 0, // VkPipelineColorBlendStateCreateFlags flags
732 VK_FALSE, // VkBool32 logicOpEnable
733 VK_LOGIC_OP_NO_OP, // VkLogicOp logicOp
734 1, // deUint32 attachmentCount
735 &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments
736 { 0.0f, 0.0f, 0.0f, 0.0f } // float blendConstants[4]
739 const VkDynamicState dynamicStates = VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT;
741 const VkPipelineDynamicStateCreateInfo pipelineDynamicStateCreateInfo =
743 VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType
744 DE_NULL, // const void* pNext
745 0u, // VkPipelineDynamicStateCreateFlags flags
746 1u, // deUint32 dynamicStateCount
747 &dynamicStates // const VkDynamicState* pDynamicStates
750 return vk::makeGraphicsPipeline(vk,
761 m_parameters.primitiveTopology,
764 &vertexInputStateCreateInfo,
765 &rasterizationStateCreateInfo,
766 DE_NULL, // multisampleStateCreateInfo
767 m_parameters.depthStencilAttachment ? &depthStencilStateCreateInfo : DE_NULL,
768 m_parameters.staticColorWriteDisable() ? &colorBlendStateCreateInfo : DE_NULL,
769 m_parameters.dynamicColorWriteDisable() ? &pipelineDynamicStateCreateInfo : DE_NULL);
772 void PrimitivesGeneratedQueryTestInstance::fillVertexBuffer(tcu::Vec2* vertices, const deUint64 primitivesGenerated)
774 const float step = 1.0f / static_cast<float>(primitivesGenerated);
776 switch (m_parameters.primitiveTopology)
778 case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
780 for (deUint32 prim = 0; prim < primitivesGenerated; ++prim)
782 vertices[prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 0.0f);
786 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
788 for (deUint32 prim = 0; prim < primitivesGenerated; ++prim)
790 vertices[2* prim + 0] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 1.0f);
791 vertices[2* prim + 1] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f);
795 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
797 vertices[0] = tcu::Vec2(-1.0f,-1.0f);
798 vertices[1] = tcu::Vec2(-1.0f, 1.0f);
800 for (deUint32 prim = 1; prim < primitivesGenerated; ++prim)
804 vertices[2 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 1.0f);
808 vertices[2 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f);
813 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
815 vertices[0] = tcu::Vec2(-1.0f, 1.0f);
816 vertices[1] = tcu::Vec2(-1.0f, -1.0f);
817 vertices[2] = tcu::Vec2(-1.0f + 2.0f * step, 1.0f);
819 for (deUint32 prim = 1; prim < primitivesGenerated; ++prim)
823 vertices[3 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 1.0f);
827 vertices[3 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f);
832 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
834 vertices[0] = tcu::Vec2(0.0f, -1.0f);
836 for (deUint32 prim = 0; prim < primitivesGenerated+1; ++prim)
838 vertices[1 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f + 2.0f * (float)prim * step);
842 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
844 for (deUint32 prim = 0; prim < primitivesGenerated; ++prim)
846 vertices[4 * prim + 0] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 1.0f);
847 vertices[4 * prim + 1] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 0.5f);
848 vertices[4 * prim + 2] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -0.5f);
849 vertices[4 * prim + 3] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f);
853 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
855 vertices[0] = tcu::Vec2(-1.0f, 0.0f);
856 vertices[1] = tcu::Vec2(-1.0f, -1.0f);
857 vertices[2] = tcu::Vec2(-1.0f, 1.0f);
859 for (deUint32 prim = 1; prim < primitivesGenerated; ++prim)
863 vertices[3 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 1.0f);
867 vertices[3 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f);
871 vertices[3 + primitivesGenerated] = tcu::Vec2(1.0f, 0.0f);
875 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
876 case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
878 for (deUint32 prim = 0; prim < primitivesGenerated; ++prim)
882 vertices[3 * prim + 0] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, 1.0f);
883 vertices[3 * prim + 1] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, -1.0f);
884 vertices[3 * prim + 2] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, -1.0f);
888 vertices[3 * prim + 0] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, -1.0f);
889 vertices[3 * prim + 1] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, 1.0f);
890 vertices[3 * prim + 2] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, 1.0f);
895 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
897 for (deUint32 prim = 0; prim < primitivesGenerated; ++prim)
901 vertices[6 * prim + 0] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, 1.0f);
902 vertices[6 * prim + 1] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, 1.0f);
903 vertices[6 * prim + 2] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, -1.0f);
904 vertices[6 * prim + 3] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, -1.0f);
905 vertices[6 * prim + 4] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, -1.0f);
906 vertices[6 * prim + 5] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, -1.0f);
910 vertices[6 * prim + 0] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, -1.0f);
911 vertices[6 * prim + 1] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, -1.0f);
912 vertices[6 * prim + 2] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, 1.0f);
913 vertices[6 * prim + 3] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, 1.0f);
914 vertices[6 * prim + 4] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, 1.0f);
915 vertices[6 * prim + 5] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, 1.0f);
920 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
922 vertices[0] = tcu::Vec2(-1.0f, 1.0f);
923 vertices[1] = tcu::Vec2(-1.0f, 1.0f);
924 vertices[2] = tcu::Vec2(-1.0f, -1.0f);
925 vertices[3] = tcu::Vec2(-1.0f, -1.0f);
926 vertices[4] = tcu::Vec2(-1.0f + 2.0f * step, 1.0f);
927 vertices[5] = tcu::Vec2(-1.0f + 2.0f * step, 1.0f);
929 for (deUint32 prim = 1; prim < primitivesGenerated; ++prim)
933 vertices[6 + prim + 0] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 1.0f);
934 vertices[6 + prim + 1] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 1.0f);
938 vertices[6 + prim + 0] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f);
939 vertices[6 + prim + 1] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f);
945 TCU_THROW(InternalError, "Unrecognized primitive topology");
949 class PrimitivesGeneratedQueryTestCase : public vkt::TestCase
952 PrimitivesGeneratedQueryTestCase (tcu::TestContext &context, const char *name, const char *description, const TestParameters& parameters)
953 : TestCase (context, name, description)
954 , m_parameters (parameters)
959 void checkSupport (vkt::Context& context) const;
960 void initPrograms (vk::SourceCollections& programCollection) const;
961 vkt::TestInstance* createInstance (vkt::Context& context) const { return new PrimitivesGeneratedQueryTestInstance(context, m_parameters); }
963 const TestParameters m_parameters;
966 void PrimitivesGeneratedQueryTestCase::checkSupport (vkt::Context& context) const
968 context.requireDeviceFunctionality("VK_EXT_primitives_generated_query");
969 context.requireDeviceFunctionality("VK_EXT_transform_feedback");
971 const VkPhysicalDevicePrimitivesGeneratedQueryFeaturesEXT& pgqFeatures = context.getPrimitivesGeneratedQueryFeaturesEXT();
972 const VkPhysicalDeviceTransformFeedbackFeaturesEXT& xfbFeatures = context.getTransformFeedbackFeaturesEXT();
973 const VkPhysicalDeviceTransformFeedbackPropertiesEXT& xfbProperties = context.getTransformFeedbackPropertiesEXT();
975 if (pgqFeatures.primitivesGeneratedQuery != VK_TRUE)
976 TCU_THROW(NotSupportedError, "VK_QUERY_TYPE_PRIMITIVES_GENERATED_EXT not supported");
978 if (m_parameters.rastDiscard() && (pgqFeatures.primitivesGeneratedQueryWithRasterizerDiscard != VK_TRUE))
979 TCU_THROW(NotSupportedError, "primitivesGeneratedQueryWithRasterizerDiscard not supported");
981 if (m_parameters.queryResetType == QUERY_RESET_TYPE_HOST)
982 context.requireDeviceFunctionality("VK_EXT_host_query_reset");
984 if (m_parameters.shaderStage == SHADER_STAGE_GEOMETRY || topologyData.at(m_parameters.primitiveTopology).hasAdjacency)
985 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
987 if (m_parameters.shaderStage == SHADER_STAGE_TESSELLATION_EVALUATION)
988 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
990 if (m_parameters.nonZeroStreams())
992 const deUint32 requiredStreams = de::max(m_parameters.pgqStreamIndex(), m_parameters.xfbStreamIndex());
994 if (m_parameters.pgqStreamIndex() > 0 && pgqFeatures.primitivesGeneratedQueryWithNonZeroStreams != VK_TRUE)
995 TCU_THROW(NotSupportedError, "primitivesGeneratedQueryWithNonZeroStreams not supported");
997 if (xfbProperties.maxTransformFeedbackStreams <= requiredStreams)
998 TCU_THROW(NotSupportedError, "Required amount of XFB streams not supported");
1001 if (m_parameters.transformFeedback)
1003 if (xfbFeatures.transformFeedback != VK_TRUE)
1004 TCU_THROW(NotSupportedError, "transformFeedback not supported");
1006 if (xfbProperties.transformFeedbackQueries != VK_TRUE)
1007 TCU_THROW(NotSupportedError, "transformFeedbackQueries not supported");
1010 if (m_parameters.colorWriteDisable())
1012 context.requireDeviceFunctionality("VK_EXT_color_write_enable");
1014 if (context.getColorWriteEnableFeaturesEXT().colorWriteEnable != VK_TRUE)
1015 TCU_THROW(NotSupportedError, "colorWriteEnable not supported");
1019 void PrimitivesGeneratedQueryTestCase::initPrograms (vk::SourceCollections& programCollection) const
1023 const bool vertXfb = (m_parameters.transformFeedback && m_parameters.shaderStage == SHADER_STAGE_VERTEX);
1024 std::ostringstream src;
1026 src << "#version 450\n";
1027 src << "layout(location=0) in vec2 inPosition;\n";
1030 src << "layout(xfb_buffer = 0, xfb_offset = 0, xfb_stride = 16, location = 0) out vec4 out0;\n";
1032 src << "void main (void)\n"
1035 if (m_parameters.primitiveTopology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST && m_parameters.shaderStage == SHADER_STAGE_VERTEX)
1036 src << " gl_PointSize = 1.0;\n";
1038 src << " gl_Position = vec4(inPosition, 0, 1);\n";
1041 src << " out0 = vec4(42);\n";
1043 src << " gl_Position = vec4(1.0f);\n";
1046 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
1049 // Tessellation shaders.
1050 if (m_parameters.shaderStage == SHADER_STAGE_TESSELLATION_EVALUATION)
1052 std::stringstream tescSrc;
1053 std::stringstream teseSrc;
1055 tescSrc << "#version 450\n"
1056 "#extension GL_EXT_tessellation_shader : require\n"
1057 "layout(vertices = "<< topologyData.at(VK_PRIMITIVE_TOPOLOGY_PATCH_LIST).primitiveSize << ") out;\n"
1058 "void main (void)\n"
1060 " gl_TessLevelInner[0] = 1.0;\n"
1061 " gl_TessLevelInner[1] = 1.0;\n"
1062 " gl_TessLevelOuter[0] = 1.0;\n"
1063 " gl_TessLevelOuter[1] = 1.0;\n"
1064 " gl_TessLevelOuter[2] = 1.0;\n"
1065 " gl_TessLevelOuter[3] = 1.0;\n"
1066 " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
1069 teseSrc << "#version 450\n"
1070 "#extension GL_EXT_tessellation_shader : require\n"
1071 "layout(triangles) in;\n";
1073 if (m_parameters.transformFeedback)
1074 teseSrc << "layout(xfb_buffer = 0, xfb_offset = 0, location = 0) out vec4 out0;\n";
1076 teseSrc << "void main (void)\n"
1079 if (m_parameters.transformFeedback)
1080 teseSrc << " out0 = vec4(42);\n";
1082 teseSrc << " vec4 p0 = gl_TessCoord.x * gl_in[0].gl_Position;\n"
1083 " vec4 p1 = gl_TessCoord.y * gl_in[1].gl_Position;\n"
1084 " vec4 p2 = gl_TessCoord.z * gl_in[2].gl_Position;\n"
1085 " gl_Position = p0 + p1 + p2;\n"
1088 programCollection.glslSources.add("tesc") << glu::TessellationControlSource(tescSrc.str());
1089 programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(teseSrc.str());
1093 if (m_parameters.shaderStage == SHADER_STAGE_GEOMETRY)
1095 const bool outputPoints = m_parameters.nonZeroStreams() || m_parameters.primitiveTopology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
1096 const char* const inputTopology = topologyData.at(m_parameters.primitiveTopology).inputString;
1097 const char* const outputTopology = outputPoints ? "points" : topologyData.at(m_parameters.primitiveTopology).outputString;
1098 const VkDeviceSize outputPrimSize = outputPoints ? 1 : topologyData.at(m_parameters.primitiveTopology).primitiveSize;
1099 const VkDeviceSize maxVertices = m_parameters.multipleStreams() ? outputPrimSize * 2 : outputPrimSize;
1100 const std::string pgqEmitCommand = m_parameters.nonZeroStreams() ? std::string("EmitStreamVertex(") + de::toString(m_parameters.pgqStreamIndex()) + ")" : "EmitVertex()";
1101 const std::string xfbEmitCommand = m_parameters.nonZeroStreams() ? std::string("EmitStreamVertex(") + de::toString(m_parameters.xfbStreamIndex()) + ")" : "EmitVertex()";
1102 const std::string pgqEndCommand = m_parameters.nonZeroStreams() ? std::string("EndStreamPrimitive(") + de::toString(m_parameters.pgqStreamIndex()) + ")" : "EndPrimitive()";
1103 const std::string xfbEndCommand = m_parameters.nonZeroStreams() ? std::string("EndStreamPrimitive(") + de::toString(m_parameters.xfbStreamIndex()) + ")" : "EndPrimitive()";
1104 std::ostringstream src;
1106 src << "#version 450\n"
1107 "layout(" << inputTopology << ") in;\n"
1108 "layout(" << outputTopology << ", max_vertices = " << maxVertices << ") out;\n";
1110 if (m_parameters.transformFeedback)
1111 src << "layout(xfb_buffer = 0, xfb_offset = 0, xfb_stride = 16, location = 0, stream = " << m_parameters.xfbStreamIndex() << ") out vec4 xfb;\n";
1113 src << "void main (void)\n"
1117 src << " gl_PointSize = 1.0;\n";
1119 if (m_parameters.transformFeedback)
1120 src << " xfb = vec4(42);\n";
1122 for (VkDeviceSize i = 0; i < outputPrimSize; i++)
1123 src << " " << pgqEmitCommand << ";\n";
1125 src << " " << pgqEndCommand << ";\n";
1127 if (m_parameters.transformFeedback && m_parameters.multipleStreams())
1129 for (VkDeviceSize i = 0; i < outputPrimSize; i++)
1130 src << " " << xfbEmitCommand << ";\n";
1132 src << " " << xfbEndCommand << ";\n";
1137 programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
1141 if (!m_parameters.rastDiscard())
1143 std::ostringstream src;
1145 if (m_parameters.rastCase == RAST_CASE_EMPTY_FRAG)
1147 src << "#version 450\n"
1148 "void main (void) {}\n";
1152 src << "#version 450\n"
1153 "layout(location = 0) out vec4 out0;\n"
1154 "void main (void)\n"
1156 " out0 = vec4(0.0, 1.0, 0.0, 1.0);\n"
1160 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
1164 void testGenerator (tcu::TestCaseGroup* pgqGroup)
1166 constexpr struct ReadType
1173 { QUERY_READ_TYPE_GET, "get", "Tests for vkGetQueryPoolResults" },
1174 { QUERY_READ_TYPE_COPY, "copy", "Tests for vkCmdCopyQueryPoolResults" },
1176 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(readTypes) == QUERY_READ_TYPE_LAST);
1178 constexpr struct ResetType
1180 QueryResetType type;
1185 { QUERY_RESET_TYPE_QUEUE, "queue_reset", "Tests for vkCmdResetQueryPool" },
1186 { QUERY_RESET_TYPE_HOST, "host_reset", "Tests for vkResetQueryPool" },
1188 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(resetTypes) == QUERY_RESET_TYPE_LAST);
1190 constexpr struct ResultTypes
1192 QueryResultType type;
1197 { QUERY_RESULT_TYPE_32_BIT, "32bit", "Tests for default query result size" },
1198 { QUERY_RESULT_TYPE_64_BIT, "64bit", "Tests for VK_QUERY_RESULT_64_BIT" },
1199 { QUERY_RESULT_TYPE_PGQ_32_XFB_64, "pgq_32bit_xfb_64bit", "Tests for PGQ without and XFBQ with VK_QUERY_RESULT_64_BIT" },
1200 { QUERY_RESULT_TYPE_PGQ_64_XFB_32, "pgq_64bit_xfb_32bit", "Tests for PGQ with and XFBQ without VK_QUERY_RESULT_64_BIT" },
1202 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(resultTypes) == QUERY_RESULT_TYPE_LAST);
1204 constexpr struct Shader
1211 { SHADER_STAGE_VERTEX, "vert", "Vertex shader tests" },
1212 { SHADER_STAGE_TESSELLATION_EVALUATION, "tese", "Tessellation evaluation shader tests" },
1213 { SHADER_STAGE_GEOMETRY, "geom", "Geometry shader tests" },
1215 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(shaderStages) == SHADER_STAGE_LAST);
1217 constexpr struct TransformFeedbackState
1222 } transformFeedbackStates[] =
1224 { DE_FALSE, "no_xfb", "Tests without transform feedback" },
1225 { DE_TRUE, "xfb", "Tests for comparing PGQ results against transform feedback query results" },
1228 constexpr struct RastCase
1230 RasterizationCase type;
1231 deBool dsAttachment;
1236 { RAST_CASE_DISCARD, DE_FALSE, "no_rast", "Tests with rasterizer discard" },
1237 { RAST_CASE_DEFAULT, DE_FALSE, "rast", "Tests without rasterizer discard" },
1238 { RAST_CASE_EMPTY_FRAG, DE_FALSE, "empty_frag", "Tests with an empty fragment shader" },
1239 { RAST_CASE_NO_ATTACHMENT, DE_FALSE, "no_attachment", "Tests with an attachmentless render pass" },
1240 { RAST_CASE_COLOR_WRITE_DISABLE_STATIC, DE_FALSE, "color_write_disable_static", "Tests disabling color output using VkPipelineColorWriteCreateInfoEXT" },
1241 { RAST_CASE_COLOR_WRITE_DISABLE_STATIC, DE_TRUE, "color_write_disable_static_ds", "Tests disabling color output using VkPipelineColorWriteCreateInfoEXT with a depth stencil attachment" },
1242 { RAST_CASE_COLOR_WRITE_DISABLE_DYNAMIC, DE_FALSE, "color_write_disable_dynamic", "Tests disabling color output using vkCmdSetColorWriteEnableEXT" },
1243 { RAST_CASE_COLOR_WRITE_DISABLE_DYNAMIC, DE_TRUE, "color_write_disable_dynamic_ds", "Tests disabling color output using vkCmdSetColorWriteEnableEXT with a depth stencil attachment" },
1246 constexpr struct Topology
1248 VkPrimitiveTopology type;
1253 { VK_PRIMITIVE_TOPOLOGY_POINT_LIST, "point_list", "Tests for separate point primitives" },
1254 { VK_PRIMITIVE_TOPOLOGY_LINE_LIST, "line_list", "Tests for separate line primitives" },
1255 { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, "line_strip", "Tests for connected line primitives with consecutive lines sharing a vertex" },
1256 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, "triangle_list", "Tests for separate triangle primitives" },
1257 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, "triangle_strip", "Tests for connected triangle primitives with consecutive triangles sharing an edge" },
1258 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, "triangle_fan", "Tests for connected triangle primitives with all triangles sharing a common vertex" },
1259 { VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY, "line_list_with_adjacency", "Tests for separate line primitives with adjacency" },
1260 { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY, "line_strip_with_adjacency", "Tests for connected line primitives with adjacency, with consecutive primitives sharing three vertices" },
1261 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY, "triangle_list_with_adjacency", "Tests for separate triangle primitives with adjacency" },
1262 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY, "triangle_strip_with_adjacency", "Tests for connected triangle primitives with adjacency, with consecutive triangles sharing an edge" },
1263 { VK_PRIMITIVE_TOPOLOGY_PATCH_LIST, "patch_list", "Tests for separate patch primitives" },
1266 // Tests for vkCmdBeginQueryIndexedEXT and vkCmdEndQueryIndexedEXT.
1267 constexpr struct StreamIndex
1273 { VERTEX_STREAM_DEFAULT, "default" },
1274 { VERTEX_STREAM_0, "0" },
1275 { VERTEX_STREAM_1, "1" },
1278 constexpr struct CmdBufCase
1280 CommandBufferCase type;
1285 { CMD_BUF_CASE_SINGLE_DRAW, "single_draw", "Test single draw call" },
1287 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(cmdBufCases) == CMD_BUF_CASE_LAST);
1289 tcu::TestContext& testCtx = pgqGroup->getTestContext();
1291 for (const ReadType& read : readTypes)
1293 tcu::TestCaseGroup* const readGroup = new tcu::TestCaseGroup(testCtx, read.name, read.desc);
1295 for (const ResetType& reset : resetTypes)
1297 tcu::TestCaseGroup* const resetGroup = new tcu::TestCaseGroup(testCtx, reset.name, reset.desc);
1299 for (const ResultTypes& result : resultTypes)
1301 tcu::TestCaseGroup* const resultGroup = new tcu::TestCaseGroup(testCtx, result.name, result.desc);
1303 for (const Shader& shader : shaderStages)
1305 tcu::TestCaseGroup* const shaderGroup = new tcu::TestCaseGroup(testCtx, shader.name, shader.desc);
1307 for (const TransformFeedbackState& xfbState : transformFeedbackStates)
1309 tcu::TestCaseGroup* const xfbGroup = new tcu::TestCaseGroup(testCtx, xfbState.name, xfbState.desc);
1311 // Only test multiple result types with XFB enabled.
1312 if ((result.type == QUERY_RESULT_TYPE_PGQ_32_XFB_64 || result.type == QUERY_RESULT_TYPE_PGQ_64_XFB_32) && !xfbState.enable)
1315 for (const RastCase& rastCase : rastCases)
1317 tcu::TestCaseGroup* const rastGroup = new tcu::TestCaseGroup(testCtx, rastCase.name, rastCase.desc);
1319 // Skip uninteresting cases
1320 if ((rastCase.type > RAST_CASE_DISCARD)
1321 && ((read.type != QUERY_READ_TYPE_GET)
1322 || (reset.type != QUERY_RESET_TYPE_QUEUE)
1323 || (result.type != QUERY_RESULT_TYPE_32_BIT)))
1328 for (const Topology& topology : topologies)
1330 tcu::TestCaseGroup* const topologyGroup = new tcu::TestCaseGroup(testCtx, topology.name, topology.desc);
1332 // Only test patch lists with tessellation shaders.
1333 if ((topology.type == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST && shader.stage != SHADER_STAGE_TESSELLATION_EVALUATION) ||
1334 ((topology.type != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST && shader.stage == SHADER_STAGE_TESSELLATION_EVALUATION)))
1339 // Only test adjacency topologies with geometry shaders.
1340 if (shader.stage != SHADER_STAGE_GEOMETRY && topologyData.at(topology.type).hasAdjacency)
1343 for (const StreamIndex& pgqStream : streamIndices)
1345 for (const StreamIndex& xfbStream : streamIndices)
1347 const std::string streamGroupName = std::string("pgq_") + pgqStream.name + (xfbState.enable ? std::string("_xfb_") + xfbStream.name : "");
1348 const bool pgqDefault = (pgqStream.index == VERTEX_STREAM_DEFAULT);
1349 const bool xfbDefault = (xfbStream.index == VERTEX_STREAM_DEFAULT);
1350 const std::string pgqDescStr = std::string("PGQ on ") + (pgqDefault ? "default " : "") + std::string("vertex stream ") + (pgqDefault ? "" : pgqStream.name);
1351 const std::string xfbDescStr = std::string("XFB on ") + (xfbDefault ? "default " : "") + std::string("vertex stream ") + (xfbDefault ? "" : xfbStream.name);
1352 const std::string streamGroupDesc = std::string("Tests for ") + pgqDescStr + (xfbState.enable ? (std::string(" and ") + xfbDescStr) : "");
1353 tcu::TestCaseGroup* const streamGroup = new tcu::TestCaseGroup(testCtx, streamGroupName.c_str(), streamGroupDesc.c_str());
1355 // Only test nondefault vertex streams with geometry shaders.
1356 if ((pgqStream.index != VERTEX_STREAM_DEFAULT || xfbStream.index != VERTEX_STREAM_DEFAULT) && shader.stage != SHADER_STAGE_GEOMETRY)
1359 // Skip nondefault vertex streams for XFB when not enabled.
1360 if (!xfbState.enable && xfbStream.index != VERTEX_STREAM_DEFAULT)
1363 for (const CmdBufCase& cmdBufCase : cmdBufCases)
1365 const TestParameters parameters =
1367 read.type, // QueryReadType queryReadType
1368 reset.type, // QueryResetType queryResetType
1369 result.type, // QueryResultType queryResultType
1370 shader.stage, // ShaderStage shaderStage
1371 xfbState.enable, // deBool transformFeedback
1372 rastCase.type, // RasterizationCase rastCase
1373 rastCase.dsAttachment, // deBool depthStencilAttachment
1374 topology.type, // VkPrimitiveTopology primitiveTopology
1375 pgqStream.index, // VertexStreamIndex pgqStreamIndex
1376 xfbStream.index, // VertexStreamIndex xfbStreamIndex
1377 cmdBufCase.type, // CommandBufferCase cmdBufCase
1380 streamGroup->addChild(new PrimitivesGeneratedQueryTestCase(testCtx, cmdBufCase.name, cmdBufCase.desc, parameters));
1383 topologyGroup->addChild(streamGroup);
1387 rastGroup->addChild(topologyGroup);
1390 xfbGroup->addChild(rastGroup);
1393 shaderGroup->addChild(xfbGroup);
1396 resultGroup->addChild(shaderGroup);
1399 resetGroup->addChild(resultGroup);
1402 readGroup->addChild(resetGroup);
1405 pgqGroup->addChild(readGroup);
1411 tcu::TestCaseGroup* createPrimitivesGeneratedQueryTests (tcu::TestContext& testCtx)
1413 return createTestGroup(testCtx, "primitives_generated_query", "Primitives Generated Query Tests", testGenerator);
1416 } // TransformFeedback