1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2021 Google LLC
6 *
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
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
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.
18 *
19 *//*!
20 * \file
21 * \brief VK_EXT_primitives_generated_query Tests
22 *//*--------------------------------------------------------------------*/
23
24 #include "vktPrimitivesGeneratedQueryTests.hpp"
25
26 #include "vktTestCase.hpp"
27 #include "vktTestGroupUtil.hpp"
28
29 #include "vkCmdUtil.hpp"
30 #include "vkImageUtil.hpp"
31 #include "vkMemUtil.hpp"
32 #include "vkObjUtil.hpp"
33 #include "vkQueryUtil.hpp"
34 #include "vkTypeUtil.hpp"
35 #include "vkBarrierUtil.hpp"
36
37 #include "tcuTestLog.hpp"
38 #include "tcuTextureUtil.hpp"
39 #include "tcuImageCompare.hpp"
40
41 #include <functional>
42 #include <map>
43 #include <set>
44
45 namespace vkt
46 {
47 namespace TransformFeedback
48 {
49 namespace
50 {
51 using namespace vk;
52
53 enum
54 {
55 IMAGE_WIDTH = 64,
56 IMAGE_HEIGHT = IMAGE_WIDTH,
57 };
58
59 enum QueryReadType
60 {
61 QUERY_READ_TYPE_GET,
62 QUERY_READ_TYPE_COPY,
63
64 QUERY_READ_TYPE_LAST
65 };
66
67 enum QueryResetType
68 {
69 QUERY_RESET_TYPE_QUEUE,
70 QUERY_RESET_TYPE_HOST,
71
72 QUERY_RESET_TYPE_LAST
73 };
74
75 enum QueryResultType
76 {
77 QUERY_RESULT_TYPE_32_BIT,
78 QUERY_RESULT_TYPE_64_BIT,
79 QUERY_RESULT_TYPE_PGQ_32_XFB_64,
80 QUERY_RESULT_TYPE_PGQ_64_XFB_32,
81
82 QUERY_RESULT_TYPE_LAST
83 };
84
85 enum ShaderStage
86 {
87 SHADER_STAGE_VERTEX,
88 SHADER_STAGE_TESSELLATION_EVALUATION,
89 SHADER_STAGE_GEOMETRY,
90
91 SHADER_STAGE_LAST
92 };
93
94 enum RasterizationCase
95 {
96 RAST_CASE_DEFAULT,
97 RAST_CASE_DISCARD,
98 RAST_CASE_EMPTY_FRAG,
99 RAST_CASE_NO_ATTACHMENT,
100 RAST_CASE_COLOR_WRITE_DISABLE_STATIC,
101 RAST_CASE_COLOR_WRITE_DISABLE_DYNAMIC,
102
103 RAST_CASE_LAST
104 };
105
106 enum VertexStream
107 {
108 VERTEX_STREAM_DEFAULT = -1,
109 VERTEX_STREAM_0 = 0,
110 VERTEX_STREAM_1 = 1,
111 VERTEX_STREAM_NONE = 2,
112 };
113
114 enum CommandBufferCase
115 {
116 CMD_BUF_CASE_SINGLE_DRAW,
117 CMD_BUF_CASE_TWO_DRAWS,
118
119 CMD_BUF_CASE_LAST
120 };
121
122 enum QueryOrder
123 {
124 QUERY_ORDER_PGQ_FIRST,
125 QUERY_ORDER_XFBQ_FIRST,
126
127 QUERY_ORDER_LAST
128 };
129
130 enum OutsideDraw
131 {
132 OUTSIDE_DRAW_NONE,
133 OUTSIDE_DRAW_BEFORE,
134 OUTSIDE_DRAW_AFTER,
135
136 OUTSIDE_DRAW_LAST
137 };
138
139 struct TestParameters
140 {
141 QueryReadType queryReadType;
142 QueryResetType queryResetType;
143 QueryResultType queryResultType;
144 ShaderStage shaderStage;
145 deBool transformFeedback;
146 RasterizationCase rastCase;
147 deBool depthStencilAttachment;
148 VkPrimitiveTopology primitiveTopology;
149 VertexStream pgqStream;
150 VertexStream xfbStream;
151 CommandBufferCase cmdBufCase;
152 const uint32_t queryCount;
153 QueryOrder queryOrder;
154 OutsideDraw outsideDraw;
155 const bool availabilityBit;
156
pgqDefaultvkt::TransformFeedback::__anonaeb873c60111::TestParameters157 bool pgqDefault (void) const { return pgqStream == VERTEX_STREAM_DEFAULT; }
xfbDefaultvkt::TransformFeedback::__anonaeb873c60111::TestParameters158 bool xfbDefault (void) const { return xfbStream == VERTEX_STREAM_DEFAULT; }
pgqStreamIndexvkt::TransformFeedback::__anonaeb873c60111::TestParameters159 deUint32 pgqStreamIndex (void) const { return pgqDefault() ? 0 : static_cast<deUint32>(pgqStream); }
xfbStreamIndexvkt::TransformFeedback::__anonaeb873c60111::TestParameters160 deUint32 xfbStreamIndex (void) const { return xfbDefault() ? 0 : static_cast<deUint32>(xfbStream); }
multipleStreamsvkt::TransformFeedback::__anonaeb873c60111::TestParameters161 bool multipleStreams (void) const { return pgqStreamIndex() != xfbStreamIndex(); }
nonZeroStreamsvkt::TransformFeedback::__anonaeb873c60111::TestParameters162 bool nonZeroStreams (void) const { return (pgqStreamIndex() != 0) || (xfbStreamIndex() != 0); }
rastDiscardvkt::TransformFeedback::__anonaeb873c60111::TestParameters163 bool rastDiscard (void) const { return rastCase == RAST_CASE_DISCARD; }
colorAttachmentvkt::TransformFeedback::__anonaeb873c60111::TestParameters164 bool colorAttachment (void) const { return !rastDiscard() && rastCase != RAST_CASE_NO_ATTACHMENT; }
staticColorWriteDisablevkt::TransformFeedback::__anonaeb873c60111::TestParameters165 bool staticColorWriteDisable (void) const { return rastCase == RAST_CASE_COLOR_WRITE_DISABLE_STATIC; }
dynamicColorWriteDisablevkt::TransformFeedback::__anonaeb873c60111::TestParameters166 bool dynamicColorWriteDisable (void) const { return rastCase == RAST_CASE_COLOR_WRITE_DISABLE_DYNAMIC; }
colorWriteDisablevkt::TransformFeedback::__anonaeb873c60111::TestParameters167 bool colorWriteDisable (void) const { return staticColorWriteDisable() || dynamicColorWriteDisable(); }
168 };
169
170 enum ConcurrentTestType
171 {
172 CONCURRENT_TEST_TYPE_TWO_XFB_INSIDE_PGQ,
173 CONCURRENT_TEST_TYPE_PGQ_SECONDARY_CMD_BUFFER,
174 CONCURRENT_TEST_TYPE_PIPELINE_STATISTICS_1,
175 CONCURRENT_TEST_TYPE_PIPELINE_STATISTICS_2,
176 CONCURRENT_TEST_TYPE_PIPELINE_STATISTICS_3,
177
178 CONCURRENT_TEST_TYPE_LAST
179 };
180
181 struct ConcurrentTestParameters
182 {
183 ConcurrentTestType concurrentTestType;
184 QueryResultType queryResultType;
185 ShaderStage shaderStage;
186 VkPrimitiveTopology primitiveTopology;
187 VertexStream pgqStream;
188 VertexStream xfbStream;
189 bool indirect;
190
pgqDefaultvkt::TransformFeedback::__anonaeb873c60111::ConcurrentTestParameters191 bool pgqDefault (void) const { return pgqStream == VERTEX_STREAM_DEFAULT; }
xfbDefaultvkt::TransformFeedback::__anonaeb873c60111::ConcurrentTestParameters192 bool xfbDefault (void) const { return xfbStream == VERTEX_STREAM_DEFAULT; }
pgqStreamIndexvkt::TransformFeedback::__anonaeb873c60111::ConcurrentTestParameters193 deUint32 pgqStreamIndex (void) const { return pgqDefault() ? 0 : static_cast<deUint32>(pgqStream); }
xfbStreamIndexvkt::TransformFeedback::__anonaeb873c60111::ConcurrentTestParameters194 deUint32 xfbStreamIndex (void) const { return xfbDefault() ? 0 : static_cast<deUint32>(xfbStream); }
multipleStreamsvkt::TransformFeedback::__anonaeb873c60111::ConcurrentTestParameters195 bool multipleStreams (void) const { return pgqStreamIndex() != xfbStreamIndex(); }
nonZeroStreamsvkt::TransformFeedback::__anonaeb873c60111::ConcurrentTestParameters196 bool nonZeroStreams (void) const { return (pgqStreamIndex() != 0) || (xfbStreamIndex() != 0); }
197 };
198
199 struct TopologyInfo
200 {
201 deUint32 primitiveSize; // Size of the primitive.
202 deBool hasAdjacency; // True if topology has adjacency.
203 const char* inputString; // Layout qualifier identifier for geometry shader input.
204 const char* outputString; // Layout qualifier identifier for geometry shader output.
205 std::function<deUint64(deUint64)> getNumPrimitives; // Number of primitives generated.
206 std::function<deUint64(deUint64)> getNumVertices; // Number of vertices generated.
207 };
208
209 const std::map<VkPrimitiveTopology, TopologyInfo> topologyData =
210 {
__anonaeb873c60402() 211 { VK_PRIMITIVE_TOPOLOGY_POINT_LIST, { 1, DE_FALSE, "points", "points", [](deUint64 vtxCount) { return vtxCount; }, [](deUint64 primCount) { return primCount; } } },
__anonaeb873c60602() 212 { VK_PRIMITIVE_TOPOLOGY_LINE_LIST, { 2, DE_FALSE, "lines", "line_strip", [](deUint64 vtxCount) { return vtxCount / 2u; }, [](deUint64 primCount) { return primCount * 2u; } } },
__anonaeb873c60802() 213 { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, { 2, DE_FALSE, "lines", "line_strip", [](deUint64 vtxCount) { return vtxCount - 1u; }, [](deUint64 primCount) { return primCount + 1u; } } },
__anonaeb873c60a02() 214 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, { 3, DE_FALSE, "triangles", "triangle_strip", [](deUint64 vtxCount) { return vtxCount / 3u; }, [](deUint64 primCount) { return primCount * 3u; } } },
__anonaeb873c60c02() 215 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, { 3, DE_FALSE, "triangles", "triangle_strip", [](deUint64 vtxCount) { return vtxCount - 2u; }, [](deUint64 primCount) { return primCount + 2u; } } },
__anonaeb873c60e02() 216 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, { 3, DE_FALSE, "triangles", "triangle_strip", [](deUint64 vtxCount) { return vtxCount - 2u; }, [](deUint64 primCount) { return primCount + 2u; } } },
__anonaeb873c60f02() 217 { VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY, { 2, DE_TRUE, "lines_adjacency", "line_strip", [](deUint64 vtxCount) { return vtxCount / 4u; }, [](deUint64 primCount) { return primCount * 4u; } } },
__anonaeb873c61202() 218 { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY, { 2, DE_TRUE, "lines_adjacency", "line_strip", [](deUint64 vtxCount) { return vtxCount - 3u; }, [](deUint64 primCount) { return primCount + 3u; } } },
__anonaeb873c61402() 219 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY, { 3, DE_TRUE, "triangles_adjacency", "triangle_strip", [](deUint64 vtxCount) { return vtxCount / 6u; }, [](deUint64 primCount) { return primCount * 6u; } } },
__anonaeb873c61602() 220 { 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; } } },
__anonaeb873c61802() 221 { VK_PRIMITIVE_TOPOLOGY_PATCH_LIST, { 3, DE_FALSE, "ERROR", "ERROR", [](deUint64 vtxCount) { return vtxCount / 3u; }, [](deUint64 primCount) { return primCount * 3u; } } },
222 };
223
224 class PrimitivesGeneratedQueryTestInstance : public vkt::TestInstance
225 {
226 public:
PrimitivesGeneratedQueryTestInstance(vkt::Context & context,const TestParameters & parameters)227 PrimitivesGeneratedQueryTestInstance (vkt::Context &context, const TestParameters& parameters)
228 : vkt::TestInstance (context)
229 , m_parameters (parameters)
230 {
231 }
232
233 private:
234 tcu::TestStatus iterate (void);
235 VkFormat selectDepthStencilFormat (void);
236 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface& vk,
237 const VkDevice device,
238 const VkRenderPass renderPass);
239 void fillVertexBuffer (tcu::Vec2* vertices,
240 const deUint64 primitivesGenerated);
241 const TestParameters m_parameters;
242 };
243
iterate(void)244 tcu::TestStatus PrimitivesGeneratedQueryTestInstance::iterate (void)
245 {
246 const DeviceInterface& vk = m_context.getDeviceInterface();
247 const VkDevice device = m_context.getDevice();
248 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
249 const VkQueue queue = m_context.getUniversalQueue();
250 Allocator& allocator = m_context.getDefaultAllocator();
251
252 using ImageVec = std::vector<Move<VkImage>>;
253 using AllocVec = std::vector<de::MovePtr<Allocation>>;
254
255 const VkFormat colorFormat = m_parameters.colorAttachment() ? VK_FORMAT_R8G8B8A8_UNORM : VK_FORMAT_UNDEFINED;
256 ImageVec colorImages;
257 AllocVec colorImageAllocations;
258
259 if (m_parameters.colorAttachment())
260 {
261 const VkImageCreateInfo colorImageCreateInfo =
262 {
263 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType
264 DE_NULL, // const void* pNext
265 0u, // VkImageCreateFlags flags
266 VK_IMAGE_TYPE_2D, // VkImageType imageType
267 colorFormat, // VkFormat format
268 makeExtent3D(IMAGE_WIDTH, IMAGE_HEIGHT, 1), // VkExtent3D extent
269 1u, // deUint32 mipLevels
270 1u, // deUint32 arrayLayers
271 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
272 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling
273 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, // VkImageUsageFlags usage
274 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode
275 0u, // deUint32 queueFamilyIndexCount
276 DE_NULL, // const deUint32* pQueueFamilyIndices
277 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout
278 };
279
280 for (uint32_t queryIdx = 0u; queryIdx < m_parameters.queryCount; ++queryIdx)
281 {
282 auto colorImage = makeImage(vk, device, colorImageCreateInfo);
283 auto colorImageAllocation = bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any);
284
285 colorImages.emplace_back(colorImage);
286 colorImageAllocations.emplace_back(colorImageAllocation);
287 }
288 }
289
290 const VkFormat dsFormat = m_parameters.depthStencilAttachment ? PrimitivesGeneratedQueryTestInstance::selectDepthStencilFormat() : VK_FORMAT_UNDEFINED;
291
292 if (m_parameters.depthStencilAttachment && dsFormat == VK_FORMAT_UNDEFINED)
293 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.");
294
295 ImageVec dsImages;
296 AllocVec dsImageAllocations;
297
298 if (m_parameters.depthStencilAttachment)
299 {
300 const VkImageCreateInfo dsImageCreateInfo =
301 {
302 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType
303 DE_NULL, // const void* pNext
304 0u, // VkImageCreateFlags flags
305 VK_IMAGE_TYPE_2D, // VkImageType imageType
306 dsFormat, // VkFormat format
307 makeExtent3D(IMAGE_WIDTH, IMAGE_HEIGHT, 1), // VkExtent3D extent
308 1u, // deUint32 mipLevels
309 1u, // deUint32 arrayLayers
310 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
311 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling
312 VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, // VkImageUsageFlags usage
313 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode
314 0u, // deUint32 queueFamilyIndexCount
315 DE_NULL, // const deUint32* pQueueFamilyIndices
316 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout
317 };
318
319 for (uint32_t queryIdx = 0u; queryIdx < m_parameters.queryCount; ++queryIdx)
320 {
321 auto dsImage = makeImage(vk, device, dsImageCreateInfo);
322 auto dsImageAllocation = bindImage(vk, device, allocator, *dsImage, MemoryRequirement::Any);
323
324 dsImages.emplace_back(dsImage);
325 dsImageAllocations.emplace_back(dsImageAllocation);
326 }
327 }
328
329 const VkDeviceSize primitivesGenerated = 32;
330 const deUint32 baseMipLevel = 0;
331 const deUint32 levelCount = 1;
332 const deUint32 baseArrayLayer = 0;
333 const deUint32 layerCount = 1;
334
335 using ImageViewVec = std::vector<Move<VkImageView>>;
336
337 ImageViewVec colorImageViews;
338 ImageViewVec dsImageViews;
339
340 for (uint32_t queryIdx = 0u; queryIdx < m_parameters.queryCount; ++queryIdx)
341 {
342 if (m_parameters.colorAttachment())
343 {
344 const VkImageSubresourceRange colorSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, baseMipLevel, levelCount, baseArrayLayer, layerCount);
345 auto colorImageView = makeImageView(vk, device, *colorImages.at(queryIdx), VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange);
346 colorImageViews.emplace_back(colorImageView);
347 }
348
349 if (m_parameters.depthStencilAttachment)
350 {
351 const VkImageSubresourceRange dsSubresourceRange = makeImageSubresourceRange((VK_IMAGE_ASPECT_DEPTH_BIT | vk::VK_IMAGE_ASPECT_STENCIL_BIT), baseMipLevel, levelCount, baseArrayLayer, layerCount);
352 auto dsImageView = makeImageView(vk, device, *dsImages.at(queryIdx), VK_IMAGE_VIEW_TYPE_2D, dsFormat, dsSubresourceRange);
353 dsImageViews.emplace_back(dsImageView);
354 }
355 }
356
357 using FramebufferVec = std::vector<Move<VkFramebuffer>>;
358
359 const Unique<VkRenderPass> renderPass (makeRenderPass(vk, device, colorFormat, dsFormat, VK_ATTACHMENT_LOAD_OP_DONT_CARE));
360 const Unique<VkPipeline> pipeline (PrimitivesGeneratedQueryTestInstance::makeGraphicsPipeline(vk, device, *renderPass));
361 FramebufferVec framebuffers;
362
363 for (uint32_t queryIdx = 0u; queryIdx < m_parameters.queryCount; ++queryIdx)
364 {
365 std::vector<VkImageView> imageViews;
366
367 if (m_parameters.colorAttachment())
368 imageViews.push_back(*colorImageViews.at(queryIdx));
369
370 if (m_parameters.depthStencilAttachment)
371 imageViews.push_back(*dsImageViews.at(queryIdx));
372
373 auto framebuffer = makeFramebuffer(vk, device, *renderPass, (deUint32)imageViews.size(), imageViews.data(), IMAGE_WIDTH, IMAGE_HEIGHT);
374 framebuffers.emplace_back(framebuffer);
375 }
376
377 Move<VkBuffer> vtxBuffer;
378 de::MovePtr<Allocation> vtxBufferAlloc;
379
380 {
381 const VkBufferUsageFlags usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
382 const std::vector<deUint32> queueFamilyIndices (1, queueFamilyIndex);
383 const VkDeviceSize vtxBufferSize = topologyData.at(m_parameters.primitiveTopology).getNumVertices(primitivesGenerated) * sizeof(tcu::Vec2);
384 const VkBufferCreateInfo createInfo = makeBufferCreateInfo(vtxBufferSize, usage, queueFamilyIndices);
385
386 vtxBuffer = createBuffer(vk, device, &createInfo);
387 vtxBufferAlloc = allocator.allocate(getBufferMemoryRequirements(vk, device, *vtxBuffer), MemoryRequirement::HostVisible);
388 }
389
390 const VkCommandPoolCreateFlags cmdPoolCreateFlags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
391 const VkCommandBufferLevel cmdBufferLevel = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
392 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, cmdPoolCreateFlags, queueFamilyIndex));
393 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer(vk, device, *cmdPool, cmdBufferLevel));
394 const auto resetCmdBuffer = allocateCommandBuffer(vk, device, *cmdPool, cmdBufferLevel);
395
396 const bool pgq64 = (m_parameters.queryResultType == QUERY_RESULT_TYPE_64_BIT ||
397 m_parameters.queryResultType == QUERY_RESULT_TYPE_PGQ_64_XFB_32);
398 const bool xfb64 = (m_parameters.queryResultType == QUERY_RESULT_TYPE_64_BIT ||
399 m_parameters.queryResultType == QUERY_RESULT_TYPE_PGQ_32_XFB_64);
400 const VkQueryResultFlags availabilityFlags = (m_parameters.availabilityBit ? VK_QUERY_RESULT_WITH_AVAILABILITY_BIT : 0);
401 const size_t pgqValuesPerQuery = (m_parameters.availabilityBit ? 2 : 1);
402 const size_t xfbValuesPerQuery = (m_parameters.availabilityBit ? 3 : 2);
403 const size_t pgqResultSize = (pgq64 ? sizeof(deUint64) : sizeof(deUint32)) * pgqValuesPerQuery;
404 const size_t xfbResultSize = (xfb64 ? sizeof(deUint64) : sizeof(deUint32)) * xfbValuesPerQuery;
405 const size_t pgqResultBufferSize = pgqResultSize * m_parameters.queryCount;
406 const size_t xfbResultBufferSize = xfbResultSize * m_parameters.queryCount;
407 const VkQueryResultFlags pgqResultWidthBit = pgq64 ? VK_QUERY_RESULT_64_BIT : 0;
408 const VkQueryResultFlags xfbResultWidthBit = xfb64 ? VK_QUERY_RESULT_64_BIT : 0;
409 const VkQueryResultFlags pgqResultFlags = VK_QUERY_RESULT_WAIT_BIT | pgqResultWidthBit | availabilityFlags;
410 const VkQueryResultFlags xfbResultFlags = VK_QUERY_RESULT_WAIT_BIT | xfbResultWidthBit | availabilityFlags;
411
412 std::vector<deUint8> pgqResults (pgqResultBufferSize, 255u);
413 std::vector<deUint8> xfbResults (xfbResultBufferSize, 255u);
414
415 const VkQueryPoolCreateInfo pgqCreateInfo =
416 {
417 VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, // VkStructureType sType
418 DE_NULL, // const void* pNext
419 0u, // VkQueryPoolCreateFlags flags
420 VK_QUERY_TYPE_PRIMITIVES_GENERATED_EXT, // VkQueryType queryType
421 m_parameters.queryCount, // deUint32 queryCount
422 0u, // VkQueryPipelineStatisticFlags pipelineStatistics
423 };
424
425 const Unique<VkQueryPool> pgqPool (createQueryPool(vk, device, &pgqCreateInfo));
426 Move<VkQueryPool> xfbPool;
427
428 if (m_parameters.transformFeedback)
429 {
430 const VkQueryPoolCreateInfo xfbCreateInfo =
431 {
432 VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, // VkStructureType sType
433 DE_NULL, // const void* pNext
434 0u, // VkQueryPoolCreateFlags flags
435 VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT, // VkQueryType queryType
436 m_parameters.queryCount, // deUint32 queryCount
437 0u, // VkQueryPipelineStatisticFlags pipelineStatistics
438 };
439
440 xfbPool = createQueryPool(vk, device, &xfbCreateInfo);
441 }
442
443 Move<VkBuffer> pgqResultsBuffer;
444 Move<VkBuffer> xfbResultsBuffer;
445 de::MovePtr<Allocation> pgqResultsBufferAlloc;
446 de::MovePtr<Allocation> xfbResultsBufferAlloc;
447
448 if (m_parameters.queryReadType == QUERY_READ_TYPE_COPY)
449 {
450 const VkBufferUsageFlags usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
451 const std::vector<deUint32> queueFamilyIndices (1, queueFamilyIndex);
452 const VkBufferCreateInfo pgqBufferCreateInfo = makeBufferCreateInfo(pgqResultBufferSize, usage, queueFamilyIndices);
453
454 pgqResultsBuffer = createBuffer(vk, device, &pgqBufferCreateInfo);
455 pgqResultsBufferAlloc = allocator.allocate(getBufferMemoryRequirements(vk, device, *pgqResultsBuffer), MemoryRequirement::HostVisible);
456
457 VK_CHECK(vk.bindBufferMemory(device, *pgqResultsBuffer, pgqResultsBufferAlloc->getMemory(), pgqResultsBufferAlloc->getOffset()));
458
459 if (m_parameters.transformFeedback)
460 {
461 const VkBufferCreateInfo xfbBufferCreateInfo = makeBufferCreateInfo(xfbResultBufferSize, usage, queueFamilyIndices);
462
463 xfbResultsBuffer = createBuffer(vk, device, &xfbBufferCreateInfo);
464 xfbResultsBufferAlloc = allocator.allocate(getBufferMemoryRequirements(vk, device, *xfbResultsBuffer), MemoryRequirement::HostVisible);
465
466 VK_CHECK(vk.bindBufferMemory(device, *xfbResultsBuffer, xfbResultsBufferAlloc->getMemory(), xfbResultsBufferAlloc->getOffset()));
467 }
468 }
469
470 const VkDeviceSize primitivesWritten = primitivesGenerated - 3;
471 const VkDeviceSize verticesWritten = topologyData.at(m_parameters.primitiveTopology).getNumVertices(primitivesWritten);
472 const VkDeviceSize primitiveSize = m_parameters.nonZeroStreams() ? 1 : topologyData.at(m_parameters.primitiveTopology).primitiveSize;
473 const VkDeviceSize bytesPerVertex = 4 * sizeof(float);
474 const VkDeviceSize xfbBufferSize = primitivesWritten * primitiveSize * bytesPerVertex;
475
476 using BufferVec = std::vector<Move<VkBuffer>>;
477
478 BufferVec xfbBuffers;
479 AllocVec xfbBufferAllocs;
480
481 if (m_parameters.transformFeedback)
482 {
483 const VkBufferUsageFlags usage = VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT;
484 const std::vector<deUint32> queueFamilyIndices (1, queueFamilyIndex);
485 const VkBufferCreateInfo createInfo = makeBufferCreateInfo(xfbBufferSize, usage, queueFamilyIndices);
486
487 for (uint32_t queryIdx = 0u; queryIdx < m_parameters.queryCount; ++queryIdx)
488 {
489 auto xfbBuffer = createBuffer(vk, device, &createInfo);
490 auto xfbBufferAlloc = allocator.allocate(getBufferMemoryRequirements(vk, device, *xfbBuffer), MemoryRequirement::HostVisible);
491
492 VK_CHECK(vk.bindBufferMemory(device, *xfbBuffer, xfbBufferAlloc->getMemory(), xfbBufferAlloc->getOffset()));
493
494 xfbBuffers.emplace_back(xfbBuffer);
495 xfbBufferAllocs.emplace_back(xfbBufferAlloc);
496 }
497 }
498
499 fillVertexBuffer(static_cast<tcu::Vec2*>(vtxBufferAlloc.get()->getHostPtr()), primitivesGenerated);
500
501 VK_CHECK(vk.bindBufferMemory(device, *vtxBuffer, vtxBufferAlloc->getMemory(), vtxBufferAlloc->getOffset()));
502
503 // After query pool creation, each query must be reset before it is used.
504 //
505 // When resetting them using a queue, we will submit a separate command buffer with the reset operation and wait for it to
506 // complete. This will make sure queries are properly reset before we attempt to get results from them. This is needed because
507 // we're not going to wait for any fence when using vkGetQueryPoolResults, so there's a potential race condition with
508 // vkGetQueryPoolResults attempting to get results before queries are properly reset, which is against the spec.
509 if (m_parameters.queryResetType == QUERY_RESET_TYPE_QUEUE)
510 {
511 beginCommandBuffer(vk, *resetCmdBuffer);
512 vk.cmdResetQueryPool(*resetCmdBuffer, *pgqPool, 0u, m_parameters.queryCount);
513 if (m_parameters.transformFeedback)
514 vk.cmdResetQueryPool(*resetCmdBuffer, *xfbPool, 0u, m_parameters.queryCount);
515 endCommandBuffer(vk, *resetCmdBuffer);
516 submitCommandsAndWait(vk, device, queue, *resetCmdBuffer);
517 }
518
519 beginCommandBuffer(vk, *cmdBuffer);
520 {
521 const VkDeviceSize vertexBufferOffset = static_cast<VkDeviceSize>(0);
522
523 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
524
525 vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &vtxBuffer.get(), &vertexBufferOffset);
526
527 for (uint32_t queryIdx = 0u; queryIdx < m_parameters.queryCount; ++queryIdx)
528 {
529 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffers.at(queryIdx), makeRect2D(makeExtent2D(IMAGE_WIDTH, IMAGE_HEIGHT)));
530 {
531 const VkQueryControlFlags queryControlFlags = 0;
532
533 const deUint32 firstCounterBuffer = 0;
534 const deUint32 counterBufferCount = 0;
535 const VkBuffer* counterBuffers = DE_NULL;
536 const VkDeviceSize* counterBufferOffsets = DE_NULL;
537
538 const deUint32 vertexCount = static_cast<deUint32>(topologyData.at(m_parameters.primitiveTopology).getNumVertices(primitivesGenerated));
539 const deUint32 instanceCount = 1u;
540 const deUint32 firstVertex = 0u;
541 const deUint32 firstInstance = 0u;
542
543 if (m_parameters.dynamicColorWriteDisable())
544 {
545 const deUint32 attachmentCount = 1;
546 const VkBool32 colorWriteEnables = VK_FALSE;
547
548 vk.cmdSetColorWriteEnableEXT(*cmdBuffer, attachmentCount, &colorWriteEnables);
549 }
550
551 if (m_parameters.outsideDraw == OUTSIDE_DRAW_BEFORE)
552 vk.cmdDraw(*cmdBuffer, vertexCount, instanceCount, firstVertex, firstInstance);
553
554 if (m_parameters.queryOrder == QUERY_ORDER_PGQ_FIRST)
555 {
556 if (m_parameters.pgqDefault())
557 vk.cmdBeginQuery(*cmdBuffer, *pgqPool, queryIdx, queryControlFlags);
558 else
559 vk.cmdBeginQueryIndexedEXT(*cmdBuffer, *pgqPool, queryIdx, queryControlFlags, m_parameters.pgqStreamIndex());
560 }
561
562 if (m_parameters.transformFeedback)
563 {
564 const deUint32 firstBinding = 0;
565 const deUint32 bindingCount = 1;
566 const VkDeviceSize offset = 0;
567
568 vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, firstBinding, bindingCount, &*xfbBuffers.at(queryIdx), &offset, &xfbBufferSize);
569
570 if (m_parameters.xfbDefault())
571 vk.cmdBeginQuery(*cmdBuffer, *xfbPool, queryIdx, queryControlFlags);
572 else
573 vk.cmdBeginQueryIndexedEXT(*cmdBuffer, *xfbPool, queryIdx, queryControlFlags, m_parameters.xfbStreamIndex());
574
575 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, firstCounterBuffer, counterBufferCount, counterBuffers, counterBufferOffsets);
576 }
577
578 if (m_parameters.queryOrder != QUERY_ORDER_PGQ_FIRST)
579 {
580 if (m_parameters.pgqDefault())
581 vk.cmdBeginQuery(*cmdBuffer, *pgqPool, queryIdx, queryControlFlags);
582 else
583 vk.cmdBeginQueryIndexedEXT(*cmdBuffer, *pgqPool, queryIdx, queryControlFlags, m_parameters.pgqStreamIndex());
584 }
585
586 vk.cmdDraw(*cmdBuffer, vertexCount, instanceCount, firstVertex, firstInstance);
587
588 if (m_parameters.cmdBufCase == CMD_BUF_CASE_TWO_DRAWS)
589 vk.cmdDraw(*cmdBuffer, vertexCount, instanceCount, firstVertex, firstInstance);
590
591 if (m_parameters.pgqDefault())
592 vk.cmdEndQuery(*cmdBuffer, *pgqPool, queryIdx);
593 else
594 vk.cmdEndQueryIndexedEXT(*cmdBuffer, *pgqPool, queryIdx, m_parameters.pgqStreamIndex());
595
596 if (m_parameters.transformFeedback)
597 {
598 if (m_parameters.xfbDefault())
599 vk.cmdEndQuery(*cmdBuffer, *xfbPool, queryIdx);
600 else
601 vk.cmdEndQueryIndexedEXT(*cmdBuffer, *xfbPool, queryIdx, m_parameters.xfbStreamIndex());
602
603 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, firstCounterBuffer, counterBufferCount, counterBuffers, counterBufferOffsets);
604 }
605
606 if (m_parameters.outsideDraw == OUTSIDE_DRAW_AFTER)
607 vk.cmdDraw(*cmdBuffer, vertexCount, instanceCount, firstVertex, firstInstance);
608 }
609 endRenderPass(vk, *cmdBuffer);
610 }
611
612 if (m_parameters.queryReadType == QUERY_READ_TYPE_COPY)
613 {
614 VkBufferMemoryBarrier bufferBarrier =
615 {
616 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType
617 DE_NULL, // const void* pNext
618 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask
619 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask
620 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex
621 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex
622 *pgqResultsBuffer, // VkBuffer buffer
623 0u, // VkDeviceSize offset
624 VK_WHOLE_SIZE // VkDeviceSize size
625 };
626
627 vk.cmdCopyQueryPoolResults(*cmdBuffer, *pgqPool, 0u, m_parameters.queryCount, *pgqResultsBuffer, 0u, pgqResultSize, pgqResultFlags);
628 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL);
629
630 if (m_parameters.transformFeedback)
631 {
632 bufferBarrier.buffer = *xfbResultsBuffer;
633 vk.cmdCopyQueryPoolResults(*cmdBuffer, *xfbPool, 0u, m_parameters.queryCount, *xfbResultsBuffer, 0u, xfbResultSize, xfbResultFlags);
634 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL);
635 }
636 }
637 }
638 vk::endCommandBuffer(vk, *cmdBuffer);
639
640 // After query pool creation, each query must be reset before it is used.
641 if (m_parameters.queryResetType == QUERY_RESET_TYPE_HOST)
642 {
643 vk.resetQueryPool(device, *pgqPool, 0u, m_parameters.queryCount);
644
645 if (m_parameters.transformFeedback)
646 vk.resetQueryPool(device, *xfbPool, 0u, m_parameters.queryCount);
647 }
648
649 const auto fence = submitCommands(vk, device, queue, *cmdBuffer);
650
651 // To make it more interesting, attempt to get results with WAIT before waiting for the fence.
652 if (m_parameters.queryReadType == QUERY_READ_TYPE_GET)
653 {
654 vk.getQueryPoolResults(device, *pgqPool, 0u, m_parameters.queryCount, pgqResults.size(), pgqResults.data(), pgqResultSize, pgqResultFlags);
655
656 if (m_parameters.transformFeedback)
657 vk.getQueryPoolResults(device, *xfbPool, 0u, m_parameters.queryCount, xfbResults.size(), xfbResults.data(), xfbResultSize, xfbResultFlags);
658 }
659
660 waitForFence(vk, device, *fence);
661
662 if (m_parameters.queryReadType == QUERY_READ_TYPE_COPY)
663 {
664 invalidateAlloc(vk, device, *pgqResultsBufferAlloc);
665 deMemcpy(pgqResults.data(), pgqResultsBufferAlloc->getHostPtr(), pgqResults.size());
666
667 if (m_parameters.transformFeedback)
668 {
669 invalidateAlloc(vk, device, *xfbResultsBufferAlloc);
670 deMemcpy(xfbResults.data(), xfbResultsBufferAlloc->getHostPtr(), xfbResults.size());
671 }
672 }
673
674 // Validate counters.
675 for (uint32_t queryIdx = 0u; queryIdx < m_parameters.queryCount; ++queryIdx)
676 {
677 union QueryResults
678 {
679 deUint32 elements32[3];
680 deUint64 elements64[3];
681 };
682
683 const QueryResults* pgqCounters = reinterpret_cast<QueryResults*>(pgqResults.data() + queryIdx * pgqResultSize);
684 const QueryResults* xfbCounters = reinterpret_cast<QueryResults*>(xfbResults.data() + queryIdx * xfbResultSize);
685 const deUint64 pgqGenerated = pgq64 ? pgqCounters->elements64[0] : static_cast<deUint64>(pgqCounters->elements32[0]);
686 const deUint64 xfbWritten = xfb64 ? xfbCounters->elements64[0] : static_cast<deUint64>(xfbCounters->elements32[0]);
687 const deUint64 xfbGenerated = xfb64 ? xfbCounters->elements64[1] : static_cast<deUint64>(xfbCounters->elements32[1]);
688 const deUint32 drawCount = (m_parameters.cmdBufCase == CMD_BUF_CASE_TWO_DRAWS) ? 2u : 1u;
689 const uint64_t pgqAvailability = (m_parameters.availabilityBit ? (pgq64 ? pgqCounters->elements64[1] : static_cast<deUint64>(pgqCounters->elements32[1])) : 1);
690 const uint64_t xfbAvailability = (m_parameters.availabilityBit ? (xfb64 ? xfbCounters->elements64[2] : static_cast<deUint64>(xfbCounters->elements32[2])) : 1);
691 tcu::TestLog& log = m_context.getTestContext().getLog();
692
693 if (queryIdx == 0u)
694 {
695 log << tcu::TestLog::Message
696 << "primitivesGenerated: " << primitivesGenerated << "\n"
697 << "primitivesWritten: " << primitivesWritten << "\n"
698 << "verticesWritten: " << verticesWritten << "\n"
699 << "xfbBufferSize: " << xfbBufferSize << "\n"
700 << tcu::TestLog::EndMessage;
701 }
702
703 const std::string logPrefix = std::string("[Query ") + std::to_string(queryIdx) + "] ";
704
705 log << tcu::TestLog::Message << logPrefix << "PGQ: Generated " << pgqGenerated << tcu::TestLog::EndMessage;
706
707 if (m_parameters.transformFeedback)
708 log << tcu::TestLog::Message << logPrefix << "XFB: Written " << xfbWritten << ", generated " << xfbGenerated << tcu::TestLog::EndMessage;
709
710 if (pgqGenerated != primitivesGenerated * drawCount)
711 {
712 const std::string message = logPrefix + "pgqGenerated == " + de::toString(pgqGenerated) + ", expected " + de::toString(primitivesGenerated * drawCount);
713 return tcu::TestStatus::fail(message);
714 }
715
716 if (pgqAvailability != 1)
717 {
718 const std::string message = logPrefix + "pgqAvailability == " + de::toString(pgqAvailability) + ", expected 1";
719 return tcu::TestStatus::fail(message);
720 }
721
722 if (m_parameters.transformFeedback)
723 {
724 if (xfbGenerated != primitivesGenerated * drawCount)
725 {
726 const std::string message = logPrefix + "xfbGenerated == " + de::toString(xfbGenerated) + ", expected " + de::toString(primitivesGenerated * drawCount);
727 return tcu::TestStatus::fail(message);
728 }
729
730 if (xfbWritten != primitivesWritten)
731 {
732 const std::string message = logPrefix + "xfbWritten == " + de::toString(xfbWritten) + ", expected " + de::toString(primitivesWritten);
733 return tcu::TestStatus::fail(message);
734 }
735
736 if (xfbWritten != (primitivesGenerated - 3))
737 {
738 const std::string message = logPrefix + "xfbWritten == " + de::toString(xfbWritten) + ", expected " + de::toString(primitivesGenerated - 3);
739 return tcu::TestStatus::fail(message);
740 }
741
742 if (xfbAvailability != 1)
743 {
744 const std::string message = logPrefix + "xfbAvailability == " + de::toString(xfbAvailability) + ", expected 1";
745 return tcu::TestStatus::fail(message);
746 }
747 }
748 }
749
750 return tcu::TestStatus::pass("Counters OK");
751 }
752
selectDepthStencilFormat(void)753 VkFormat PrimitivesGeneratedQueryTestInstance::selectDepthStencilFormat (void)
754 {
755 constexpr VkFormat formats[] =
756 {
757 VK_FORMAT_D32_SFLOAT_S8_UINT,
758 VK_FORMAT_D24_UNORM_S8_UINT
759 };
760
761 const InstanceInterface& vki = m_context.getInstanceInterface();
762 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
763
764 for (VkFormat format : formats)
765 {
766 const VkFormatFeatureFlags features = getPhysicalDeviceFormatProperties(vki, physicalDevice, format).optimalTilingFeatures;
767
768 if (features & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)
769 return format;
770 }
771
772 return VK_FORMAT_UNDEFINED;
773 }
774
makeGraphicsPipeline(const DeviceInterface & vk,const VkDevice device,const VkRenderPass renderPass)775 Move<VkPipeline> PrimitivesGeneratedQueryTestInstance::makeGraphicsPipeline (const DeviceInterface& vk, const VkDevice device, const VkRenderPass renderPass)
776 {
777 const VkDescriptorSetLayout descriptorSetLayout = DE_NULL;
778 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout(vk, device, descriptorSetLayout));
779 const std::vector<VkViewport> viewports (1, makeViewport(makeExtent2D(IMAGE_WIDTH, IMAGE_HEIGHT)));
780 const std::vector<VkRect2D> scissors (1, makeRect2D(makeExtent2D(IMAGE_WIDTH, IMAGE_HEIGHT)));
781 const deUint32 subpass = 0u;
782 const deUint32 patchControlPoints = topologyData.at(VK_PRIMITIVE_TOPOLOGY_PATCH_LIST).primitiveSize;
783 const Unique<VkShaderModule> vertModule (createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
784 Move<VkShaderModule> tescModule;
785 Move<VkShaderModule> teseModule;
786 Move<VkShaderModule> geomModule;
787 Move<VkShaderModule> fragModule;
788 VkVertexInputBindingDescription bindingDescription;
789 VkVertexInputAttributeDescription attributeDescription;
790
791 if (m_parameters.shaderStage == SHADER_STAGE_TESSELLATION_EVALUATION)
792 {
793 tescModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("tesc"), 0u);
794 teseModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("tese"), 0u);
795 }
796
797 if (m_parameters.shaderStage == SHADER_STAGE_GEOMETRY)
798 geomModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("geom"), 0u);
799
800 if (!m_parameters.rastDiscard())
801 fragModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u);
802
803 bindingDescription.binding = 0;
804 bindingDescription.stride = sizeof(tcu::Vec2);
805 bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
806
807 attributeDescription.binding = 0;
808 attributeDescription.location = 0;
809 attributeDescription.format = VK_FORMAT_R32G32_SFLOAT;
810 attributeDescription.offset = 0;
811
812 const VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo =
813 {
814 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType
815 DE_NULL, // const void* pNext
816 0u, // VkPipelineVertexInputStateCreateFlags flags
817 1u, // deUint32 vertexBindingDescriptionCount
818 &bindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions
819 1u, // deUint32 vertexAttributeDescriptionCount
820 &attributeDescription, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions
821 };
822
823 const VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo =
824 {
825 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType
826 DE_NULL, // const void* pNext
827 0, // VkPipelineRasterizationStateCreateFlags flags
828 VK_FALSE, // VkBool32 depthClampEnable
829 (m_parameters.rastDiscard() ? VK_TRUE : VK_FALSE), // VkBool32 rasterizerDiscardEnable
830 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode
831 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode
832 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace
833 VK_FALSE, // VkBool32 depthBiasEnable
834 0.0f, // float depthBiasConstantFactor
835 0.0f, // float depthBiasClamp
836 0.0f, // float depthBiasSlopeFactor
837 1.0f // float lineWidth
838 };
839
840 const VkStencilOpState stencilOpState =
841 {
842 VK_STENCIL_OP_KEEP, // VkStencilOp failOp
843 VK_STENCIL_OP_KEEP, // VkStencilOp passOp
844 VK_STENCIL_OP_KEEP, // VkStencilOp depthFailOp
845 VK_COMPARE_OP_ALWAYS, // VkCompareOp compareOp
846 0xFFu, // deUint32 compareMask
847 0xFFu, // deUint32 writeMask
848 0, // deUint32 reference
849 };
850
851 const VkPipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo =
852 {
853 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType
854 DE_NULL, // const void* pNext
855 0, // VkPipelineDepthStencilStateCreateFlags flags
856 VK_TRUE, // VkBool32 depthTestEnable
857 VK_TRUE, // VkBool32 depthWriteEnable
858 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp
859 VK_FALSE, // VkBool32 depthBoundsTestEnable
860 VK_FALSE, // VkBool32 stencilTestEnable
861 stencilOpState, // VkStencilOpState front
862 stencilOpState, // VkStencilOpState back
863 0.0f, // float minDepthBounds
864 1.0f, // float maxDepthBounds
865 };
866
867 const VkBool32 colorWriteEnables = VK_FALSE;
868
869 const VkPipelineColorWriteCreateInfoEXT colorWriteCreateInfo =
870 {
871 VK_STRUCTURE_TYPE_PIPELINE_COLOR_WRITE_CREATE_INFO_EXT, // VkStructureType sType;
872 DE_NULL, // const void* pNext;
873 1, // deUint32 attachmentCount;
874 &colorWriteEnables // const VkBool32* pColorWriteEnables;
875 };
876
877 const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
878 {
879 VK_FALSE, // VkBool32 blendEnable
880 VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcColorBlendFactor
881 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor
882 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp
883 VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcAlphaBlendFactor
884 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor
885 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp
886 VK_COLOR_COMPONENT_R_BIT // VkColorComponentFlags colorWriteMask
887 | VK_COLOR_COMPONENT_G_BIT
888 | VK_COLOR_COMPONENT_B_BIT
889 | VK_COLOR_COMPONENT_A_BIT
890 };
891
892 const VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfo =
893 {
894 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType
895 &colorWriteCreateInfo, // const void* pNext
896 0, // VkPipelineColorBlendStateCreateFlags flags
897 VK_FALSE, // VkBool32 logicOpEnable
898 VK_LOGIC_OP_NO_OP, // VkLogicOp logicOp
899 1, // deUint32 attachmentCount
900 &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments
901 { 0.0f, 0.0f, 0.0f, 0.0f } // float blendConstants[4]
902 };
903
904 const VkDynamicState dynamicStates = VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT;
905
906 const VkPipelineDynamicStateCreateInfo pipelineDynamicStateCreateInfo =
907 {
908 VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType
909 DE_NULL, // const void* pNext
910 0u, // VkPipelineDynamicStateCreateFlags flags
911 1u, // deUint32 dynamicStateCount
912 &dynamicStates // const VkDynamicState* pDynamicStates
913 };
914
915 const VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfo =
916 {
917 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
918 nullptr, // const void* pNext;
919 0u, // VkPipelineMultisampleStateCreateFlags flags;
920 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
921 VK_FALSE, // VkBool32 sampleShadingEnable;
922 1.0f, // float minSampleShading;
923 nullptr, // const VkSampleMask* pSampleMask;
924 VK_FALSE, // VkBool32 alphaToCoverageEnable;
925 VK_FALSE, // VkBool32 alphaToOneEnable;
926 };
927
928 return vk::makeGraphicsPipeline(vk,
929 device,
930 *pipelineLayout,
931 *vertModule,
932 *tescModule,
933 *teseModule,
934 *geomModule,
935 *fragModule,
936 renderPass,
937 viewports,
938 scissors,
939 m_parameters.primitiveTopology,
940 subpass,
941 patchControlPoints,
942 &vertexInputStateCreateInfo,
943 &rasterizationStateCreateInfo,
944 &multisampleStateCreateInfo,
945 m_parameters.depthStencilAttachment ? &depthStencilStateCreateInfo : DE_NULL,
946 m_parameters.staticColorWriteDisable() ? &colorBlendStateCreateInfo : DE_NULL,
947 m_parameters.dynamicColorWriteDisable() ? &pipelineDynamicStateCreateInfo : DE_NULL);
948 }
949
fillVertexBuffer(tcu::Vec2 * vertices,const deUint64 primitivesGenerated)950 void PrimitivesGeneratedQueryTestInstance::fillVertexBuffer(tcu::Vec2* vertices, const deUint64 primitivesGenerated)
951 {
952 const float step = 1.0f / static_cast<float>(primitivesGenerated);
953
954 switch (m_parameters.primitiveTopology)
955 {
956 case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
957 {
958 for (deUint32 prim = 0; prim < primitivesGenerated; ++prim)
959 {
960 vertices[prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 0.0f);
961 }
962 break;
963 }
964 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
965 {
966 for (deUint32 prim = 0; prim < primitivesGenerated; ++prim)
967 {
968 vertices[2* prim + 0] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 1.0f);
969 vertices[2* prim + 1] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f);
970 }
971 break;
972 }
973 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
974 {
975 vertices[0] = tcu::Vec2(-1.0f,-1.0f);
976 vertices[1] = tcu::Vec2(-1.0f, 1.0f);
977
978 for (deUint32 prim = 1; prim < primitivesGenerated; ++prim)
979 {
980 if (prim % 2 == 0)
981 {
982 vertices[1 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 1.0f);
983 }
984 else
985 {
986 vertices[1 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f);
987 }
988 }
989 break;
990 }
991 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
992 {
993 vertices[0] = tcu::Vec2(-1.0f, 1.0f);
994 vertices[1] = tcu::Vec2(-1.0f, -1.0f);
995 vertices[2] = tcu::Vec2(-1.0f + 2.0f * step, 1.0f);
996
997 for (deUint32 prim = 1; prim < primitivesGenerated; ++prim)
998 {
999 if (prim % 2 == 0)
1000 {
1001 vertices[2 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 1.0f);
1002 }
1003 else
1004 {
1005 vertices[2 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f);
1006 }
1007 }
1008 break;
1009 }
1010 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
1011 {
1012 vertices[0] = tcu::Vec2(0.0f, -1.0f);
1013
1014 for (deUint32 prim = 0; prim < primitivesGenerated+1; ++prim)
1015 {
1016 vertices[1 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f + 2.0f * (float)prim * step);
1017 }
1018 break;
1019 }
1020 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
1021 {
1022 for (deUint32 prim = 0; prim < primitivesGenerated; ++prim)
1023 {
1024 vertices[4 * prim + 0] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 1.0f);
1025 vertices[4 * prim + 1] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 0.5f);
1026 vertices[4 * prim + 2] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -0.5f);
1027 vertices[4 * prim + 3] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f);
1028 }
1029 break;
1030 }
1031 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
1032 {
1033 vertices[0] = tcu::Vec2(-1.0f, 0.0f);
1034 vertices[1] = tcu::Vec2(-1.0f, -1.0f);
1035 vertices[2] = tcu::Vec2(-1.0f, 1.0f);
1036
1037 for (deUint32 prim = 1; prim < primitivesGenerated; ++prim)
1038 {
1039 if (prim % 2 == 0)
1040 {
1041 vertices[2 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 1.0f);
1042 }
1043 else
1044 {
1045 vertices[2 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f);
1046 }
1047 }
1048
1049 vertices[2 + primitivesGenerated] = tcu::Vec2(1.0f, 0.0f);
1050
1051 break;
1052 }
1053 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
1054 case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
1055 {
1056 for (deUint32 prim = 0; prim < primitivesGenerated; ++prim)
1057 {
1058 if (prim % 2 == 0)
1059 {
1060 vertices[3 * prim + 0] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, 1.0f);
1061 vertices[3 * prim + 1] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, -1.0f);
1062 vertices[3 * prim + 2] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, -1.0f);
1063 }
1064 else
1065 {
1066 vertices[3 * prim + 0] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, -1.0f);
1067 vertices[3 * prim + 1] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, 1.0f);
1068 vertices[3 * prim + 2] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, 1.0f);
1069 }
1070 }
1071 break;
1072 }
1073 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
1074 {
1075 for (deUint32 prim = 0; prim < primitivesGenerated; ++prim)
1076 {
1077 if (prim % 2 == 0)
1078 {
1079 vertices[6 * prim + 0] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, 1.0f);
1080 vertices[6 * prim + 1] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, 1.0f);
1081 vertices[6 * prim + 2] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, -1.0f);
1082 vertices[6 * prim + 3] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, -1.0f);
1083 vertices[6 * prim + 4] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, -1.0f);
1084 vertices[6 * prim + 5] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, -1.0f);
1085 }
1086 else
1087 {
1088 vertices[6 * prim + 0] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, -1.0f);
1089 vertices[6 * prim + 1] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, -1.0f);
1090 vertices[6 * prim + 2] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, 1.0f);
1091 vertices[6 * prim + 3] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, 1.0f);
1092 vertices[6 * prim + 4] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, 1.0f);
1093 vertices[6 * prim + 5] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, 1.0f);
1094 }
1095 }
1096 break;
1097 }
1098 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
1099 {
1100 vertices[0] = tcu::Vec2(-1.0f, 1.0f);
1101 vertices[1] = tcu::Vec2(-1.0f, 1.0f);
1102 vertices[2] = tcu::Vec2(-1.0f, -1.0f);
1103 vertices[3] = tcu::Vec2(-1.0f, -1.0f);
1104 vertices[4] = tcu::Vec2(-1.0f + 2.0f * step, 1.0f);
1105 vertices[5] = tcu::Vec2(-1.0f + 2.0f * step, 1.0f);
1106
1107 for (deUint32 prim = 1; prim < primitivesGenerated; ++prim)
1108 {
1109 if (prim % 2 == 0)
1110 {
1111 vertices[5 + prim + 0] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 1.0f);
1112 vertices[5 + prim + 1] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 1.0f);
1113 }
1114 else
1115 {
1116 vertices[5 + prim + 0] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f);
1117 vertices[5 + prim + 1] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f);
1118 }
1119 }
1120 break;
1121 }
1122 default:
1123 TCU_THROW(InternalError, "Unrecognized primitive topology");
1124 }
1125 }
1126
1127 class PrimitivesGeneratedQueryTestCase : public vkt::TestCase
1128 {
1129 public:
PrimitivesGeneratedQueryTestCase(tcu::TestContext & context,const char * name,const TestParameters & parameters)1130 PrimitivesGeneratedQueryTestCase (tcu::TestContext &context, const char *name, const TestParameters& parameters)
1131 : TestCase (context, name)
1132 , m_parameters (parameters)
1133 {
1134 }
1135
1136 private:
1137 void checkSupport (vkt::Context& context) const;
1138 void initPrograms (vk::SourceCollections& programCollection) const;
createInstance(vkt::Context & context) const1139 vkt::TestInstance* createInstance (vkt::Context& context) const { return new PrimitivesGeneratedQueryTestInstance(context, m_parameters); }
1140
1141 const TestParameters m_parameters;
1142 };
1143
checkSupport(vkt::Context & context) const1144 void PrimitivesGeneratedQueryTestCase::checkSupport (vkt::Context& context) const
1145 {
1146 context.requireDeviceFunctionality("VK_EXT_primitives_generated_query");
1147 context.requireDeviceFunctionality("VK_EXT_transform_feedback");
1148
1149 const VkPhysicalDevicePrimitivesGeneratedQueryFeaturesEXT& pgqFeatures = context.getPrimitivesGeneratedQueryFeaturesEXT();
1150 const VkPhysicalDeviceTransformFeedbackFeaturesEXT& xfbFeatures = context.getTransformFeedbackFeaturesEXT();
1151 const VkPhysicalDeviceTransformFeedbackPropertiesEXT& xfbProperties = context.getTransformFeedbackPropertiesEXT();
1152
1153 if (pgqFeatures.primitivesGeneratedQuery != VK_TRUE)
1154 TCU_THROW(NotSupportedError, "VK_QUERY_TYPE_PRIMITIVES_GENERATED_EXT not supported");
1155
1156 if (m_parameters.rastDiscard() && (pgqFeatures.primitivesGeneratedQueryWithRasterizerDiscard != VK_TRUE))
1157 TCU_THROW(NotSupportedError, "primitivesGeneratedQueryWithRasterizerDiscard not supported");
1158
1159 if (m_parameters.queryResetType == QUERY_RESET_TYPE_HOST)
1160 context.requireDeviceFunctionality("VK_EXT_host_query_reset");
1161
1162 if (m_parameters.shaderStage == SHADER_STAGE_GEOMETRY || topologyData.at(m_parameters.primitiveTopology).hasAdjacency)
1163 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
1164
1165 if (m_parameters.shaderStage == SHADER_STAGE_TESSELLATION_EVALUATION)
1166 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
1167
1168 if (m_parameters.nonZeroStreams())
1169 {
1170 const deUint32 requiredStreams = de::max(m_parameters.pgqStreamIndex(), m_parameters.xfbStreamIndex());
1171
1172 if (m_parameters.pgqStreamIndex() > 0 && pgqFeatures.primitivesGeneratedQueryWithNonZeroStreams != VK_TRUE)
1173 TCU_THROW(NotSupportedError, "primitivesGeneratedQueryWithNonZeroStreams not supported");
1174
1175 if (xfbProperties.maxTransformFeedbackStreams <= requiredStreams)
1176 TCU_THROW(NotSupportedError, "Required amount of XFB streams not supported");
1177 }
1178
1179 if (m_parameters.transformFeedback)
1180 {
1181 if (xfbFeatures.transformFeedback != VK_TRUE)
1182 TCU_THROW(NotSupportedError, "transformFeedback not supported");
1183
1184 if (xfbProperties.transformFeedbackQueries != VK_TRUE)
1185 TCU_THROW(NotSupportedError, "transformFeedbackQueries not supported");
1186 }
1187
1188 if (m_parameters.colorWriteDisable())
1189 {
1190 context.requireDeviceFunctionality("VK_EXT_color_write_enable");
1191
1192 if (context.getColorWriteEnableFeaturesEXT().colorWriteEnable != VK_TRUE)
1193 TCU_THROW(NotSupportedError, "colorWriteEnable not supported");
1194 }
1195 }
1196
initPrograms(vk::SourceCollections & programCollection) const1197 void PrimitivesGeneratedQueryTestCase::initPrograms (vk::SourceCollections& programCollection) const
1198 {
1199 // Vertex shader.
1200 {
1201 const bool vertXfb = (m_parameters.transformFeedback && m_parameters.shaderStage == SHADER_STAGE_VERTEX);
1202 std::ostringstream src;
1203
1204 src << "#version 450\n";
1205 src << "layout(location=0) in vec2 inPosition;\n";
1206
1207 if (vertXfb)
1208 src << "layout(xfb_buffer = 0, xfb_offset = 0, xfb_stride = 16, location = 0) out vec4 out0;\n";
1209
1210 src << "void main (void)\n"
1211 "{\n";
1212
1213 if (m_parameters.primitiveTopology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST && m_parameters.shaderStage == SHADER_STAGE_VERTEX)
1214 src << " gl_PointSize = 1.0;\n";
1215
1216 src << " gl_Position = vec4(inPosition, 0, 1);\n";
1217
1218 if (vertXfb)
1219 src << " out0 = vec4(42);\n";
1220
1221 src << "}\n";
1222
1223 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
1224 }
1225
1226 // Tessellation shaders.
1227 if (m_parameters.shaderStage == SHADER_STAGE_TESSELLATION_EVALUATION)
1228 {
1229 std::stringstream tescSrc;
1230 std::stringstream teseSrc;
1231
1232 tescSrc << "#version 450\n"
1233 "#extension GL_EXT_tessellation_shader : require\n"
1234 "layout(vertices = "<< topologyData.at(VK_PRIMITIVE_TOPOLOGY_PATCH_LIST).primitiveSize << ") out;\n"
1235 "void main (void)\n"
1236 "{\n"
1237 " gl_TessLevelInner[0] = 1.0;\n"
1238 " gl_TessLevelInner[1] = 1.0;\n"
1239 " gl_TessLevelOuter[0] = 1.0;\n"
1240 " gl_TessLevelOuter[1] = 1.0;\n"
1241 " gl_TessLevelOuter[2] = 1.0;\n"
1242 " gl_TessLevelOuter[3] = 1.0;\n"
1243 " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
1244 "}\n";
1245
1246 teseSrc << "#version 450\n"
1247 "#extension GL_EXT_tessellation_shader : require\n"
1248 "layout(triangles) in;\n";
1249
1250 if (m_parameters.transformFeedback)
1251 teseSrc << "layout(xfb_buffer = 0, xfb_offset = 0, location = 0) out vec4 out0;\n";
1252
1253 teseSrc << "void main (void)\n"
1254 "{\n";
1255
1256 if (m_parameters.transformFeedback)
1257 teseSrc << " out0 = vec4(42);\n";
1258
1259 teseSrc << " vec4 p0 = gl_TessCoord.x * gl_in[0].gl_Position;\n"
1260 " vec4 p1 = gl_TessCoord.y * gl_in[1].gl_Position;\n"
1261 " vec4 p2 = gl_TessCoord.z * gl_in[2].gl_Position;\n"
1262 " gl_Position = p0 + p1 + p2;\n"
1263 "}\n";
1264
1265 programCollection.glslSources.add("tesc") << glu::TessellationControlSource(tescSrc.str());
1266 programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(teseSrc.str());
1267 }
1268
1269 // Geometry shader.
1270 if (m_parameters.shaderStage == SHADER_STAGE_GEOMETRY)
1271 {
1272 const bool outputPoints = m_parameters.nonZeroStreams() || m_parameters.primitiveTopology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
1273 const char* const inputTopology = topologyData.at(m_parameters.primitiveTopology).inputString;
1274 const char* const outputTopology = outputPoints ? "points" : topologyData.at(m_parameters.primitiveTopology).outputString;
1275 const VkDeviceSize outputPrimSize = outputPoints ? 1 : topologyData.at(m_parameters.primitiveTopology).primitiveSize;
1276 const VkDeviceSize maxVertices = m_parameters.multipleStreams() ? outputPrimSize * 2 : outputPrimSize;
1277 const std::string pgqEmitCommand = m_parameters.nonZeroStreams() ? std::string("EmitStreamVertex(") + de::toString(m_parameters.pgqStreamIndex()) + ")" : "EmitVertex()";
1278 const std::string xfbEmitCommand = m_parameters.nonZeroStreams() ? std::string("EmitStreamVertex(") + de::toString(m_parameters.xfbStreamIndex()) + ")" : "EmitVertex()";
1279 const std::string pgqEndCommand = m_parameters.nonZeroStreams() ? std::string("EndStreamPrimitive(") + de::toString(m_parameters.pgqStreamIndex()) + ")" : "EndPrimitive()";
1280 const std::string xfbEndCommand = m_parameters.nonZeroStreams() ? std::string("EndStreamPrimitive(") + de::toString(m_parameters.xfbStreamIndex()) + ")" : "EndPrimitive()";
1281 std::ostringstream src;
1282
1283 src << "#version 450\n"
1284 "layout(" << inputTopology << ") in;\n"
1285 "layout(" << outputTopology << ", max_vertices = " << maxVertices << ") out;\n";
1286
1287 if (m_parameters.transformFeedback)
1288 src << "layout(xfb_buffer = 0, xfb_offset = 0, xfb_stride = 16, location = 0, stream = " << m_parameters.xfbStreamIndex() << ") out vec4 xfb;\n";
1289
1290 src << "void main (void)\n"
1291 "{\n";
1292
1293 if (outputPoints)
1294 src << " gl_PointSize = 1.0;\n";
1295
1296 if (m_parameters.transformFeedback)
1297 src << " xfb = vec4(42);\n";
1298
1299 for (VkDeviceSize i = 0; i < outputPrimSize; i++)
1300 src << " " << pgqEmitCommand << ";\n";
1301
1302 src << " " << pgqEndCommand << ";\n";
1303
1304 if (m_parameters.transformFeedback && m_parameters.multipleStreams())
1305 {
1306 for (VkDeviceSize i = 0; i < outputPrimSize; i++)
1307 src << " " << xfbEmitCommand << ";\n";
1308
1309 src << " " << xfbEndCommand << ";\n";
1310 }
1311
1312 src << "}\n";
1313
1314 programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
1315 }
1316
1317 // Fragment shader.
1318 if (!m_parameters.rastDiscard())
1319 {
1320 std::ostringstream src;
1321
1322 if (m_parameters.rastCase == RAST_CASE_EMPTY_FRAG)
1323 {
1324 src << "#version 450\n"
1325 "void main (void) {}\n";
1326 }
1327 else
1328 {
1329 src << "#version 450\n"
1330 "layout(location = 0) out vec4 out0;\n"
1331 "void main (void)\n"
1332 "{\n"
1333 " out0 = vec4(0.0, 1.0, 0.0, 1.0);\n"
1334 "}\n";
1335 }
1336
1337 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
1338 }
1339 }
1340 class ConcurrentPrimitivesGeneratedQueryTestInstance : public vkt::TestInstance
1341 {
1342 public:
ConcurrentPrimitivesGeneratedQueryTestInstance(vkt::Context & context,const ConcurrentTestParameters & parameters)1343 ConcurrentPrimitivesGeneratedQueryTestInstance (vkt::Context &context, const ConcurrentTestParameters& parameters)
1344 : vkt::TestInstance (context)
1345 , m_parameters (parameters)
1346 {}
1347
1348 private:
1349 tcu::TestStatus iterate (void);
1350 void draw (const DeviceInterface& vk, vk::VkCommandBuffer cmdBuffer, deUint32 vertexCount, vk::VkBuffer indirectBuffer);
1351 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface& vk,
1352 const VkDevice device,
1353 const VkRenderPass renderPass);
1354 void fillVertexBuffer (tcu::Vec2* vertices,
1355 const deUint64 primitivesGenerated);
1356 void copyColorImageToBuffer (const DeviceInterface& vk, VkCommandBuffer cmdBuffer, VkImage image, VkBuffer buffer);
1357
1358 const ConcurrentTestParameters m_parameters;
1359 const deUint32 m_imageWidth = 16;
1360 const deUint32 m_imageHeight = 16;
1361 const deUint32 instanceCount = 1u;
1362 const deUint32 firstVertex = 0u;
1363 const deUint32 firstInstance = 0u;
1364 };
1365
1366 // Create a render pass with an initial and final layout of VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL.
1367 // The load operation will clear the attachment.
makeConstantLayoutRenderPass(const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat)1368 Move<VkRenderPass> makeConstantLayoutRenderPass (const DeviceInterface& vk,
1369 const VkDevice device,
1370 const VkFormat colorFormat)
1371 {
1372 const auto constantLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
1373
1374 const VkAttachmentDescription colorAttachmentDescription =
1375 {
1376 0u, // VkAttachmentDescriptionFlags flags
1377 colorFormat, // VkFormat format
1378 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
1379 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp
1380 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp
1381 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp
1382 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp
1383 constantLayout, // VkImageLayout initialLayout
1384 constantLayout // VkImageLayout finalLayout
1385 };
1386
1387 const VkAttachmentReference colorAttachmentRef = makeAttachmentReference(0u, constantLayout);
1388
1389 const VkSubpassDescription subpassDescription =
1390 {
1391 0u, // VkSubpassDescriptionFlags flags
1392 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint
1393 0u, // deUint32 inputAttachmentCount
1394 nullptr, // const VkAttachmentReference* pInputAttachments
1395 1u, // deUint32 colorAttachmentCount
1396 &colorAttachmentRef, // const VkAttachmentReference* pColorAttachments
1397 nullptr, // const VkAttachmentReference* pResolveAttachments
1398 nullptr, // const VkAttachmentReference* pDepthStencilAttachment
1399 0u, // deUint32 preserveAttachmentCount
1400 nullptr // const deUint32* pPreserveAttachments
1401 };
1402
1403 const VkRenderPassCreateInfo renderPassInfo =
1404 {
1405 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType
1406 nullptr, // const void* pNext
1407 0u, // VkRenderPassCreateFlags flags
1408 1u, // deUint32 attachmentCount
1409 &colorAttachmentDescription, // const VkAttachmentDescription* pAttachments
1410 1u, // deUint32 subpassCount
1411 &subpassDescription, // const VkSubpassDescription* pSubpasses
1412 0u, // deUint32 dependencyCount
1413 nullptr // const VkSubpassDependency* pDependencies
1414 };
1415
1416 return createRenderPass(vk, device, &renderPassInfo);
1417 }
1418
1419 // Transitions the selected subresource range to color attachment optimal.
prepareColorAttachment(const DeviceInterface & vkd,const VkCommandBuffer cmdBuffer,const VkImage image,const VkImageSubresourceRange imageSRR)1420 void prepareColorAttachment (const DeviceInterface& vkd, const VkCommandBuffer cmdBuffer, const VkImage image, const VkImageSubresourceRange imageSRR)
1421 {
1422 const auto barrier = makeImageMemoryBarrier(0u, 0u, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, image, imageSRR);
1423 cmdPipelineImageMemoryBarrier(vkd, cmdBuffer, 0u, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, &barrier);
1424 }
1425
iterate(void)1426 tcu::TestStatus ConcurrentPrimitivesGeneratedQueryTestInstance::iterate (void)
1427 {
1428 const DeviceInterface& vk = m_context.getDeviceInterface();
1429 const VkDevice device = m_context.getDevice();
1430 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1431 const VkQueue queue = m_context.getUniversalQueue();
1432 Allocator& allocator = m_context.getDefaultAllocator();
1433 tcu::TestLog& log = m_context.getTestContext().getLog();
1434
1435 const VkDeviceSize primitivesGenerated = 32;
1436 const deUint32 baseMipLevel = 0;
1437 const deUint32 levelCount = 1;
1438 const deUint32 baseArrayLayer = 0;
1439 const deUint32 layerCount = 1;
1440
1441 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
1442
1443 const VkImageCreateInfo colorImageCreateInfo =
1444 {
1445 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType
1446 DE_NULL, // const void* pNext
1447 0u, // VkImageCreateFlags flags
1448 VK_IMAGE_TYPE_2D, // VkImageType imageType
1449 colorFormat, // VkFormat format
1450 makeExtent3D(m_imageWidth, m_imageHeight, 1), // VkExtent3D extent
1451 1u, // deUint32 mipLevels
1452 1u, // deUint32 arrayLayers
1453 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
1454 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling
1455 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
1456 | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage
1457 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode
1458 0u, // deUint32 queueFamilyIndexCount
1459 DE_NULL, // const deUint32* pQueueFamilyIndices
1460 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout
1461 };
1462
1463 const VkImageSubresourceRange colorSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, baseMipLevel, levelCount, baseArrayLayer, layerCount);
1464
1465 Move<VkImage> colorImage = makeImage(vk, device, colorImageCreateInfo);
1466 de::MovePtr<Allocation> colorImageAllocation = bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any);
1467 Move<VkImageView> colorImageView = makeImageView(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange);
1468
1469 // By using a constant-layout render pass, we can begin and end the render pass multiple times without layout transition hazards.
1470 const Unique<VkRenderPass> renderPass (makeConstantLayoutRenderPass(vk, device, colorFormat));
1471 const vk::VkClearValue clearColor = { { { 0.0f, 0.0f, 0.0f, 0.0f } } };
1472 const Unique<VkFramebuffer> framebuffer (makeFramebuffer(vk, device, *renderPass, *colorImageView, m_imageWidth, m_imageHeight));
1473 const Unique<VkPipeline> pipeline (ConcurrentPrimitivesGeneratedQueryTestInstance::makeGraphicsPipeline(vk, device, *renderPass));
1474
1475 const VkBufferUsageFlags usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
1476 const std::vector<deUint32> queueFamilyIndices (1, queueFamilyIndex);
1477 const VkDeviceSize vtxBufferSize = topologyData.at(m_parameters.primitiveTopology).getNumVertices(primitivesGenerated) * sizeof(tcu::Vec2);
1478 const VkBufferCreateInfo createInfo = makeBufferCreateInfo(vtxBufferSize, usage, queueFamilyIndices);
1479
1480 Move<VkBuffer> vtxBuffer = createBuffer(vk, device, &createInfo);
1481 de::MovePtr<Allocation> vtxBufferAlloc = allocator.allocate(getBufferMemoryRequirements(vk, device, *vtxBuffer), MemoryRequirement::HostVisible);
1482
1483 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1484 const Unique<VkCommandBuffer> primaryCmdBuffer (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1485 const Unique<VkCommandBuffer> secondaryCmdBuffer (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY));
1486
1487 const bool pgq64 = (m_parameters.queryResultType == QUERY_RESULT_TYPE_64_BIT ||
1488 m_parameters.queryResultType == QUERY_RESULT_TYPE_PGQ_64_XFB_32);
1489 const bool xfb64 = (m_parameters.queryResultType == QUERY_RESULT_TYPE_64_BIT ||
1490 m_parameters.queryResultType == QUERY_RESULT_TYPE_PGQ_32_XFB_64);
1491 const size_t pgqResultSize = pgq64 ? sizeof(deUint64) : sizeof(deUint32);
1492 const size_t xfbResultSize = xfb64 ? sizeof(deUint64) * 2 : sizeof(deUint32) * 2;
1493 const size_t psResultsSize = sizeof(deUint64);
1494 const VkQueryResultFlags pgqResultWidthBit = pgq64 ? VK_QUERY_RESULT_64_BIT : 0;
1495 const VkQueryResultFlags xfbResultWidthBit = xfb64 ? VK_QUERY_RESULT_64_BIT : 0;
1496 const VkQueryResultFlags psResultWidthBit = 0;
1497 const VkQueryResultFlags pgqResultFlags = VK_QUERY_RESULT_WAIT_BIT | pgqResultWidthBit;
1498 const VkQueryResultFlags xfbResultFlags = VK_QUERY_RESULT_WAIT_BIT | xfbResultWidthBit;
1499 const VkQueryResultFlags psResultFlags = VK_QUERY_RESULT_WAIT_BIT | psResultWidthBit;
1500
1501 const deUint32 pgqQueryCount = 1;
1502 const deUint32 xfbQueryCount = (m_parameters.concurrentTestType == CONCURRENT_TEST_TYPE_TWO_XFB_INSIDE_PGQ) ? 2 : 0;
1503 const deUint32 psQueryCount = (m_parameters.concurrentTestType >= CONCURRENT_TEST_TYPE_PIPELINE_STATISTICS_1) ? 1 : 0;
1504
1505 std::vector<deUint8> pgqResults (pgqResultSize, 255u);
1506 std::vector<std::vector<deUint8>> xfbResults;
1507 std::vector<std::vector<deUint8>> psqResults;
1508 if (xfbQueryCount > 0)
1509 {
1510 xfbResults.resize(xfbQueryCount);
1511 for (deUint32 i = 0; i < xfbQueryCount; ++i)
1512 xfbResults[i] = std::vector<deUint8>(xfbResultSize, 255u);
1513 }
1514 if (psQueryCount > 0)
1515 {
1516 psqResults.resize(psQueryCount);
1517 for (deUint32 i = 0; i < psQueryCount; ++i)
1518 psqResults[i] = std::vector<deUint8>(psResultsSize, 255u);
1519 }
1520
1521 const VkQueryPoolCreateInfo pgqCreateInfo =
1522 {
1523 VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, // VkStructureType sType
1524 DE_NULL, // const void* pNext
1525 0u, // VkQueryPoolCreateFlags flags
1526 VK_QUERY_TYPE_PRIMITIVES_GENERATED_EXT, // VkQueryType queryType
1527 pgqQueryCount, // deUint32 queryCount
1528 0u, // VkQueryPipelineStatisticFlags pipelineStatistics
1529 };
1530
1531 const VkQueryPoolCreateInfo xfbCreateInfo =
1532 {
1533 VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, // VkStructureType sType
1534 DE_NULL, // const void* pNext
1535 0u, // VkQueryPoolCreateFlags flags
1536 VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT, // VkQueryType queryType
1537 xfbQueryCount, // deUint32 queryCount
1538 0u, // VkQueryPipelineStatisticFlags pipelineStatistics
1539 };
1540
1541 const VkQueryPoolCreateInfo psCreateInfo =
1542 {
1543 VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, // VkStructureType sType
1544 DE_NULL, // const void* pNext
1545 0u, // VkQueryPoolCreateFlags flags
1546 VK_QUERY_TYPE_PIPELINE_STATISTICS, // VkQueryType queryType
1547 psQueryCount, // deUint32 queryCount
1548 VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_PRIMITIVES_BIT
1549 // VkQueryPipelineStatisticFlags pipelineStatistics
1550 };
1551
1552 const Move<VkQueryPool> pgqPool (createQueryPool(vk, device, &pgqCreateInfo));
1553 Move<VkQueryPool> xfbPool;
1554 Move<VkQueryPool> psqPool;
1555 if (xfbQueryCount > 0)
1556 xfbPool = createQueryPool(vk, device, &xfbCreateInfo);
1557 if (psQueryCount > 0)
1558 psqPool = createQueryPool(vk, device, &psCreateInfo);
1559
1560 const VkDeviceSize primitivesWritten = primitivesGenerated - 3;
1561 const VkDeviceSize verticesWritten = topologyData.at(m_parameters.primitiveTopology).getNumVertices(primitivesWritten);
1562 const VkDeviceSize primitiveSize = m_parameters.nonZeroStreams() ? 1 : topologyData.at(m_parameters.primitiveTopology).primitiveSize;
1563 const VkDeviceSize bytesPerVertex = 4 * sizeof(float);
1564 const VkDeviceSize xfbBufferSize = primitivesWritten * primitiveSize * bytesPerVertex;
1565 Move<VkBuffer> xfbBuffer;
1566 de::MovePtr<Allocation> xfbBufferAlloc;
1567
1568 {
1569 const VkBufferUsageFlags xfbUsage = VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT;
1570 const VkBufferCreateInfo xfbBufferCreateInfo = makeBufferCreateInfo(xfbBufferSize, xfbUsage);
1571
1572 xfbBuffer = createBuffer(vk, device, &xfbBufferCreateInfo);
1573 xfbBufferAlloc = allocator.allocate(getBufferMemoryRequirements(vk, device, *xfbBuffer), MemoryRequirement::HostVisible);
1574
1575 VK_CHECK(vk.bindBufferMemory(device, *xfbBuffer, xfbBufferAlloc->getMemory(), xfbBufferAlloc->getOffset()));
1576 }
1577
1578 fillVertexBuffer(static_cast<tcu::Vec2*>(vtxBufferAlloc.get()->getHostPtr()), primitivesGenerated);
1579
1580 VK_CHECK(vk.bindBufferMemory(device, *vtxBuffer, vtxBufferAlloc->getMemory(), vtxBufferAlloc->getOffset()));
1581
1582 const vk::VkDeviceSize colorOutputBufferSize = m_imageWidth * m_imageHeight* tcu::getPixelSize(vk::mapVkFormat(colorFormat));
1583 de::MovePtr<vk::BufferWithMemory> colorOutputBuffer = de::MovePtr<vk::BufferWithMemory>(new vk::BufferWithMemory(
1584 vk, device, allocator, makeBufferCreateInfo(colorOutputBufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT), vk::MemoryRequirement::HostVisible));
1585
1586 de::MovePtr<vk::BufferWithMemory> indirectBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(vk, device, allocator, vk::makeBufferCreateInfo(sizeof(vk::VkDrawIndirectCommand), vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT), vk::MemoryRequirement::HostVisible));;
1587
1588 const deUint32 vertexCount = static_cast<deUint32>(topologyData.at(m_parameters.primitiveTopology).getNumVertices(primitivesGenerated));
1589
1590 if (m_parameters.indirect)
1591 {
1592 const vk::Allocation& indirectAlloc = (*indirectBuffer).getAllocation();
1593 vk::VkDrawIndirectCommand* indirectDataPtr = reinterpret_cast<vk::VkDrawIndirectCommand*>(indirectAlloc.getHostPtr());
1594
1595 indirectDataPtr->vertexCount = vertexCount;
1596 indirectDataPtr->instanceCount = instanceCount;
1597 indirectDataPtr->firstVertex = firstVertex;
1598 indirectDataPtr->firstInstance = firstInstance;
1599
1600 flushAlloc(vk, device, indirectAlloc);
1601 }
1602
1603 const bool secondaryCmdBufferUsed = m_parameters.concurrentTestType == CONCURRENT_TEST_TYPE_PGQ_SECONDARY_CMD_BUFFER;
1604 const VkQueryControlFlags queryControlFlags = 0;
1605 const VkDeviceSize vertexBufferOffset = static_cast<VkDeviceSize>(0);
1606
1607 VkCommandBuffer cmdBuffer;
1608
1609 if (secondaryCmdBufferUsed)
1610 {
1611 cmdBuffer = *secondaryCmdBuffer;
1612 beginSecondaryCommandBuffer(vk, cmdBuffer, *renderPass, *framebuffer);
1613 }
1614 else
1615 {
1616 cmdBuffer = *primaryCmdBuffer;
1617 beginCommandBuffer(vk, cmdBuffer);
1618 prepareColorAttachment(vk, cmdBuffer, *colorImage, colorSubresourceRange);
1619 }
1620
1621 if (m_parameters.concurrentTestType == CONCURRENT_TEST_TYPE_PIPELINE_STATISTICS_3)
1622 {
1623 const VkCommandBufferInheritanceInfo inheritanceInfo =
1624 {
1625 VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, // VkStructureType sType;
1626 nullptr, // const void* pNext;
1627 *renderPass, // VkRenderPass renderPass;
1628 0u, // deUint32 subpass;
1629 *framebuffer, // VkFramebuffer framebuffer;
1630 VK_FALSE, // VkBool32 occlusionQueryEnable;
1631 queryControlFlags, // VkQueryControlFlags queryFlags;
1632 psCreateInfo.pipelineStatistics, // VkQueryPipelineStatisticFlags pipelineStatistics;
1633 };
1634
1635 const VkCommandBufferBeginInfo beginInfo =
1636 {
1637 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
1638 nullptr, // const void* pNext;
1639 VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, // VkCommandBufferUsageFlags flags;
1640 &inheritanceInfo, // const VkCommandBufferInheritanceInfo* pInheritanceInfo;
1641 };
1642
1643 vk.beginCommandBuffer(*secondaryCmdBuffer, &beginInfo);
1644 vk.cmdBeginQueryIndexedEXT(*secondaryCmdBuffer, *pgqPool, 0, queryControlFlags, m_parameters.pgqStreamIndex());
1645 vk.cmdBindPipeline(*secondaryCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1646 vk.cmdBindVertexBuffers(*secondaryCmdBuffer, 0, 1, &vtxBuffer.get(), &vertexBufferOffset);
1647 draw(vk, *secondaryCmdBuffer, vertexCount, indirectBuffer->get());
1648 vk.cmdEndQueryIndexedEXT(*secondaryCmdBuffer, *pgqPool, 0, m_parameters.pgqStreamIndex());
1649 vk.endCommandBuffer(*secondaryCmdBuffer);
1650 }
1651
1652 {
1653 // After query pool creation, each query must be reset before it is used.
1654 if (!secondaryCmdBufferUsed)
1655 {
1656 vk.cmdResetQueryPool(cmdBuffer, *pgqPool, 0, pgqQueryCount);
1657 if (xfbQueryCount > 0)
1658 vk.cmdResetQueryPool(cmdBuffer, *xfbPool, 0, xfbQueryCount);
1659 if (psQueryCount > 0)
1660 vk.cmdResetQueryPool(cmdBuffer, *psqPool, 0, psQueryCount);
1661 }
1662
1663 vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1664 vk.cmdBindVertexBuffers(cmdBuffer, 0, 1, &vtxBuffer.get(), &vertexBufferOffset);
1665
1666 {
1667 const deUint32 firstCounterBuffer = 0;
1668 const deUint32 counterBufferCount = 0;
1669 const VkBuffer* counterBuffers = DE_NULL;
1670 const VkDeviceSize* counterBufferOffsets = DE_NULL;
1671
1672 if (m_parameters.concurrentTestType == CONCURRENT_TEST_TYPE_TWO_XFB_INSIDE_PGQ)
1673 {
1674 beginRenderPass(vk, cmdBuffer, *renderPass, *framebuffer, makeRect2D(makeExtent2D(m_imageWidth, m_imageHeight)), clearColor);
1675
1676 // Begin PGQ
1677 vk.cmdBeginQueryIndexedEXT(cmdBuffer, *pgqPool, 0, queryControlFlags, m_parameters.pgqStreamIndex());
1678
1679 draw(vk, cmdBuffer, vertexCount, indirectBuffer->get());
1680
1681 // Begin XFBQ 1
1682 {
1683 const deUint32 firstBinding = 0;
1684 const deUint32 bindingCount = 1;
1685 const VkDeviceSize offset = 0;
1686
1687 vk.cmdBindTransformFeedbackBuffersEXT(cmdBuffer, firstBinding, bindingCount, &*xfbBuffer, &offset, &xfbBufferSize);
1688 vk.cmdBeginQueryIndexedEXT(cmdBuffer, *xfbPool, 0, queryControlFlags, m_parameters.xfbStreamIndex());
1689 vk.cmdBeginTransformFeedbackEXT(cmdBuffer, firstCounterBuffer, counterBufferCount, counterBuffers, counterBufferOffsets);
1690 }
1691
1692 draw(vk, cmdBuffer, vertexCount, indirectBuffer->get());
1693
1694 // End XFBQ 1
1695 {
1696 vk.cmdEndQueryIndexedEXT(cmdBuffer, *xfbPool, 0, m_parameters.xfbStreamIndex());
1697 vk.cmdEndTransformFeedbackEXT(cmdBuffer, firstCounterBuffer, counterBufferCount, counterBuffers, counterBufferOffsets);
1698 }
1699
1700 draw(vk, cmdBuffer, vertexCount, indirectBuffer->get());
1701
1702 // Begin XFBQ 1
1703 {
1704 const deUint32 firstBinding = 0;
1705 const deUint32 bindingCount = 1;
1706 const VkDeviceSize offset = 0;
1707
1708 vk.cmdBindTransformFeedbackBuffersEXT(cmdBuffer, firstBinding, bindingCount, &*xfbBuffer, &offset, &xfbBufferSize);
1709 vk.cmdBeginQueryIndexedEXT(cmdBuffer, *xfbPool, 1, queryControlFlags, m_parameters.xfbStreamIndex());
1710 vk.cmdBeginTransformFeedbackEXT(cmdBuffer, firstCounterBuffer, counterBufferCount, counterBuffers, counterBufferOffsets);
1711 }
1712
1713 draw(vk, cmdBuffer, vertexCount, indirectBuffer->get());
1714
1715 // End XFBQ 1
1716 {
1717 vk.cmdEndQueryIndexedEXT(cmdBuffer, *xfbPool, 1, m_parameters.xfbStreamIndex());
1718 vk.cmdEndTransformFeedbackEXT(cmdBuffer, firstCounterBuffer, counterBufferCount, counterBuffers, counterBufferOffsets);
1719 }
1720
1721 draw(vk, cmdBuffer, vertexCount, indirectBuffer->get());
1722
1723 // End PGQ
1724 vk.cmdEndQueryIndexedEXT(cmdBuffer, *pgqPool, 0, m_parameters.pgqStreamIndex());
1725
1726 endRenderPass(vk, cmdBuffer);
1727 }
1728 else if (m_parameters.concurrentTestType == CONCURRENT_TEST_TYPE_PGQ_SECONDARY_CMD_BUFFER)
1729 {
1730
1731 vk.cmdBeginQueryIndexedEXT(cmdBuffer, *pgqPool, 0, queryControlFlags, m_parameters.pgqStreamIndex());
1732 draw(vk, cmdBuffer, vertexCount, indirectBuffer->get());
1733 vk.cmdEndQueryIndexedEXT(cmdBuffer, *pgqPool, 0, m_parameters.pgqStreamIndex());
1734 }
1735 else if (m_parameters.concurrentTestType == CONCURRENT_TEST_TYPE_PIPELINE_STATISTICS_1)
1736 {
1737 vk.cmdBeginQueryIndexedEXT(cmdBuffer, *pgqPool, 0, queryControlFlags, m_parameters.pgqStreamIndex());
1738 vk.cmdBeginQuery(cmdBuffer, *psqPool, 0, queryControlFlags);
1739
1740 beginRenderPass(vk, cmdBuffer, *renderPass, *framebuffer, makeRect2D(makeExtent2D(m_imageWidth, m_imageHeight)), clearColor);
1741 draw(vk, cmdBuffer, vertexCount, indirectBuffer->get());
1742 endRenderPass(vk, cmdBuffer);
1743
1744 vk.cmdEndQueryIndexedEXT(cmdBuffer, *pgqPool, 0, m_parameters.pgqStreamIndex());
1745
1746 beginRenderPass(vk, cmdBuffer, *renderPass, *framebuffer, makeRect2D(makeExtent2D(m_imageWidth, m_imageHeight)), clearColor);
1747 draw(vk, cmdBuffer, vertexCount, indirectBuffer->get());
1748 endRenderPass(vk, cmdBuffer);
1749
1750 vk.cmdEndQuery(cmdBuffer, *psqPool, 0);
1751 }
1752 else if (m_parameters.concurrentTestType == CONCURRENT_TEST_TYPE_PIPELINE_STATISTICS_2)
1753 {
1754 vk.cmdBeginQueryIndexedEXT(cmdBuffer, *pgqPool, 0, queryControlFlags, m_parameters.pgqStreamIndex());
1755
1756 beginRenderPass(vk, cmdBuffer, *renderPass, *framebuffer, makeRect2D(makeExtent2D(m_imageWidth, m_imageHeight)), clearColor);
1757 vk.cmdBeginQuery(cmdBuffer, *psqPool, 0, queryControlFlags);
1758 draw(vk, cmdBuffer, vertexCount, indirectBuffer->get());
1759 vk.cmdEndQuery(cmdBuffer, *psqPool, 0);
1760 endRenderPass(vk, cmdBuffer);
1761
1762 beginRenderPass(vk, cmdBuffer, *renderPass, *framebuffer, makeRect2D(makeExtent2D(m_imageWidth, m_imageHeight)), clearColor);
1763 draw(vk, cmdBuffer, vertexCount, indirectBuffer->get());
1764 endRenderPass(vk, cmdBuffer);
1765
1766 vk.cmdEndQueryIndexedEXT(cmdBuffer, *pgqPool, 0, m_parameters.pgqStreamIndex());
1767 }
1768 else if (m_parameters.concurrentTestType == CONCURRENT_TEST_TYPE_PIPELINE_STATISTICS_3)
1769 {
1770 vk.cmdBeginQuery(cmdBuffer, *psqPool, 0, queryControlFlags);
1771
1772 beginRenderPass(vk, cmdBuffer, *renderPass, *framebuffer, makeRect2D(makeExtent2D(m_imageWidth, m_imageHeight)), clearColor, vk::VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
1773 vk.cmdExecuteCommands(cmdBuffer, 1u, &*secondaryCmdBuffer);
1774 endRenderPass(vk, cmdBuffer);
1775
1776 beginRenderPass(vk, cmdBuffer, *renderPass, *framebuffer, makeRect2D(makeExtent2D(m_imageWidth, m_imageHeight)), clearColor);
1777 draw(vk, cmdBuffer, vertexCount, indirectBuffer->get());
1778 endRenderPass(vk, cmdBuffer);
1779
1780 vk.cmdEndQuery(cmdBuffer, *psqPool, 0);
1781 }
1782 }
1783 }
1784
1785 if (!secondaryCmdBufferUsed)
1786 copyColorImageToBuffer(vk, cmdBuffer, *colorImage, **colorOutputBuffer);
1787
1788 vk::endCommandBuffer(vk, cmdBuffer);
1789
1790 if (secondaryCmdBufferUsed)
1791 {
1792 vk::beginCommandBuffer(vk, *primaryCmdBuffer);
1793 prepareColorAttachment(vk, *primaryCmdBuffer, *colorImage, colorSubresourceRange);
1794 vk.cmdResetQueryPool(*primaryCmdBuffer, *pgqPool, 0, pgqQueryCount);
1795 if (xfbQueryCount > 0)
1796 vk.cmdResetQueryPool(*primaryCmdBuffer, *xfbPool, 0, xfbQueryCount);
1797 if (psQueryCount > 0)
1798 vk.cmdResetQueryPool(cmdBuffer, *psqPool, 0, psQueryCount);
1799 beginRenderPass(vk, *primaryCmdBuffer, *renderPass, *framebuffer, makeRect2D(makeExtent2D(m_imageWidth, m_imageHeight)), clearColor, vk::VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
1800 vk.cmdExecuteCommands(*primaryCmdBuffer, 1u, &*secondaryCmdBuffer);
1801 endRenderPass(vk, *primaryCmdBuffer);
1802 copyColorImageToBuffer(vk, *primaryCmdBuffer, *colorImage, **colorOutputBuffer);
1803 vk::endCommandBuffer(vk, *primaryCmdBuffer);
1804 }
1805
1806 vk::submitCommandsAndWait(vk, device, queue, *primaryCmdBuffer);
1807
1808 vk.getQueryPoolResults(device, *pgqPool, 0, pgqQueryCount, pgqResults.size(), pgqResults.data(), pgqResults.size(), pgqResultFlags);
1809 for (deUint32 i = 0; i < xfbQueryCount; ++i)
1810 vk.getQueryPoolResults(device, *xfbPool, i, 1, xfbResults[i].size(), xfbResults[i].data(), xfbResults[i].size(), xfbResultFlags);
1811 for (deUint32 i = 0; i < psQueryCount; ++i)
1812 vk.getQueryPoolResults(device, *psqPool, i, 1, psqResults[i].size(), psqResults[i].data(), psqResults[i].size(), psResultFlags);
1813
1814 // Validate counters.
1815 {
1816 deUint32 pgqDrawCount = 1;
1817 if (m_parameters.concurrentTestType == CONCURRENT_TEST_TYPE_TWO_XFB_INSIDE_PGQ)
1818 pgqDrawCount = 5;
1819 else if (m_parameters.concurrentTestType == CONCURRENT_TEST_TYPE_PIPELINE_STATISTICS_2)
1820 pgqDrawCount = 2;
1821 const deUint32 totalPrimitivesGenerated = static_cast<deUint32>(primitivesGenerated * pgqDrawCount);
1822
1823 union QueryResults
1824 {
1825 deUint32 elements32[2];
1826 deUint64 elements64[2];
1827 };
1828
1829 const QueryResults* pgqCounters = reinterpret_cast<QueryResults*>(pgqResults.data());
1830 const deUint64 pgqGenerated = pgq64 ? pgqCounters->elements64[0] : static_cast<deUint64>(pgqCounters->elements32[0]);
1831 std::vector< QueryResults*> xfbCounters (xfbResults.size());
1832 std::vector<deUint64> xfbWritten (xfbResults.size());
1833 std::vector<deUint64> xfbGenerated (xfbResults.size());
1834
1835 for (deUint32 i = 0; i < xfbQueryCount; ++i)
1836 {
1837 xfbCounters[i] = reinterpret_cast<QueryResults*>(xfbResults[i].data());
1838 xfbWritten[i] = xfb64 ? xfbCounters[i]->elements64[0] : static_cast<deUint64>(xfbCounters[i]->elements32[0]);
1839 xfbGenerated[i] = xfb64 ? xfbCounters[i]->elements64[1] : static_cast<deUint64>(xfbCounters[i]->elements32[1]);
1840 }
1841
1842 log << tcu::TestLog::Message
1843 << "primitivesGenerated: " << totalPrimitivesGenerated << "\n"
1844 << "primitivesWritten: " << primitivesWritten << "\n"
1845 << "verticesWritten: " << verticesWritten << "\n"
1846 << "xfbBufferSize: " << xfbBufferSize << "\n"
1847 << tcu::TestLog::EndMessage;
1848
1849 log << tcu::TestLog::Message << "PGQ: Generated " << pgqGenerated << tcu::TestLog::EndMessage;
1850 for (deUint32 i = 0; i < (deUint32)xfbCounters.size(); ++i)
1851 log << tcu::TestLog::Message << "XFB " << i << ": Written " << xfbWritten[i] << ", generated " << xfbGenerated[i] << tcu::TestLog::EndMessage;
1852
1853 if (pgqGenerated != totalPrimitivesGenerated)
1854 {
1855 const std::string message = std::string("Total pgqGenerated == ") + de::toString(pgqGenerated) + ", expected " + de::toString(totalPrimitivesGenerated);
1856 return tcu::TestStatus::fail(message);
1857 }
1858
1859 for (deUint32 i = 0; i < (deUint32)xfbCounters.size(); ++i)
1860 {
1861 if (xfbGenerated[i] != primitivesGenerated)
1862 {
1863 const std::string message = std::string("xfbGenerated == ") + de::toString(xfbGenerated[i]) + ", expected " + de::toString(primitivesGenerated);
1864 return tcu::TestStatus::fail(message);
1865 }
1866
1867 if (xfbWritten[i] != primitivesWritten)
1868 {
1869 const std::string message = std::string("xfbWritten == ") + de::toString(xfbWritten[i]) + ", expected " + de::toString(primitivesWritten);
1870 return tcu::TestStatus::fail(message);
1871 }
1872
1873 if (xfbWritten[i] != (primitivesGenerated - 3))
1874 {
1875 const std::string message = std::string("xfbWritten == ") + de::toString(xfbWritten[i]) + ", expected " + de::toString(primitivesGenerated - 3);
1876 return tcu::TestStatus::fail(message);
1877 }
1878 }
1879
1880 if (psQueryCount > 0)
1881 {
1882
1883 const QueryResults* psqCounters = reinterpret_cast<QueryResults*>(psqResults[0].data());
1884 const deUint64 inputAssemblyPrimitives = psqCounters->elements32[0];
1885
1886 deUint32 drawCount = (m_parameters.concurrentTestType == CONCURRENT_TEST_TYPE_PIPELINE_STATISTICS_1 ||
1887 m_parameters.concurrentTestType == CONCURRENT_TEST_TYPE_PIPELINE_STATISTICS_3)
1888 ? 2 : 1;
1889
1890 if (inputAssemblyPrimitives != primitivesGenerated * drawCount)
1891 {
1892 const std::string message = std::string("input assembly primitives == ") + de::toString(inputAssemblyPrimitives) + ", expected " + de::toString(primitivesGenerated * drawCount);
1893 return tcu::TestStatus::fail(message);
1894 }
1895 }
1896 }
1897
1898 const auto tcuFormat = vk::mapVkFormat(colorFormat);
1899 const auto iWidth = static_cast<int>(m_imageWidth);
1900 const auto iHeight = static_cast<int>(m_imageHeight);
1901
1902 tcu::ConstPixelBufferAccess resultBuffer = tcu::ConstPixelBufferAccess(tcuFormat, iWidth, iHeight, 1, colorOutputBuffer->getAllocation().getHostPtr());
1903 tcu::TextureLevel referenceLevel (tcuFormat, iWidth, iHeight);
1904 const auto referenceAccess = referenceLevel.getAccess();
1905 const tcu::Vec4 bgColor (0.0f, 0.0f, 0.0f, 0.0f);
1906 const tcu::Vec4 geomColor (0.0f, 1.0f, 0.0f, 1.0f);
1907 const tcu::Vec4 threshold (0.0f, 0.0f, 0.0f, 0.0f);
1908 const int colorRow = 7;
1909
1910 tcu::clear(referenceAccess, bgColor);
1911 const auto subregion = tcu::getSubregion(referenceAccess, 0, colorRow, iWidth, 1);
1912 tcu::clear(subregion, geomColor);
1913
1914 if (!tcu::floatThresholdCompare(log, "Result", "", referenceAccess, resultBuffer, threshold, tcu::COMPARE_LOG_ON_ERROR))
1915 return tcu::TestStatus::fail("Color buffer contains unexpected results; check log for details");
1916 return tcu::TestStatus::pass("Pass");
1917 }
1918
draw(const DeviceInterface & vk,vk::VkCommandBuffer cmdBuffer,deUint32 vertexCount,vk::VkBuffer indirectBuffer)1919 void ConcurrentPrimitivesGeneratedQueryTestInstance::draw (const DeviceInterface& vk, vk::VkCommandBuffer cmdBuffer, deUint32 vertexCount, vk::VkBuffer indirectBuffer)
1920 {
1921 if (m_parameters.indirect)
1922 vk.cmdDrawIndirect(cmdBuffer, indirectBuffer, 0u, 1u, sizeof(vk::VkDrawIndirectCommand));
1923 else
1924 vk.cmdDraw(cmdBuffer, vertexCount, instanceCount, firstVertex, firstInstance);
1925 }
1926
makeGraphicsPipeline(const DeviceInterface & vk,const VkDevice device,const VkRenderPass renderPass)1927 Move<VkPipeline> ConcurrentPrimitivesGeneratedQueryTestInstance::makeGraphicsPipeline (const DeviceInterface& vk, const VkDevice device, const VkRenderPass renderPass)
1928 {
1929 const VkDescriptorSetLayout descriptorSetLayout = DE_NULL;
1930 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout(vk, device, descriptorSetLayout));
1931 const std::vector<VkViewport> viewports (1, makeViewport(makeExtent2D(m_imageWidth, m_imageHeight)));
1932 const std::vector<VkRect2D> scissors (1, makeRect2D(makeExtent2D(m_imageWidth, m_imageHeight)));
1933 const deUint32 subpass = 0u;
1934 const deUint32 patchControlPoints = topologyData.at(VK_PRIMITIVE_TOPOLOGY_PATCH_LIST).primitiveSize;
1935 const Unique<VkShaderModule> vertModule (createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
1936 Move<VkShaderModule> tescModule;
1937 Move<VkShaderModule> teseModule;
1938 Move<VkShaderModule> geomModule;
1939 Move<VkShaderModule> fragModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u);
1940 VkVertexInputBindingDescription bindingDescription;
1941 VkVertexInputAttributeDescription attributeDescription;
1942
1943 if (m_parameters.shaderStage == SHADER_STAGE_TESSELLATION_EVALUATION)
1944 {
1945 tescModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("tesc"), 0u);
1946 teseModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("tese"), 0u);
1947 }
1948
1949 if (m_parameters.shaderStage == SHADER_STAGE_GEOMETRY)
1950 geomModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("geom"), 0u);
1951
1952 bindingDescription.binding = 0;
1953 bindingDescription.stride = sizeof(tcu::Vec2);
1954 bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
1955
1956 attributeDescription.binding = 0;
1957 attributeDescription.location = 0;
1958 attributeDescription.format = VK_FORMAT_R32G32_SFLOAT;
1959 attributeDescription.offset = 0;
1960
1961 const VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo =
1962 {
1963 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType
1964 DE_NULL, // const void* pNext
1965 0u, // VkPipelineVertexInputStateCreateFlags flags
1966 1u, // deUint32 vertexBindingDescriptionCount
1967 &bindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions
1968 1u, // deUint32 vertexAttributeDescriptionCount
1969 &attributeDescription, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions
1970 };
1971
1972 const VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo =
1973 {
1974 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType
1975 DE_NULL, // const void* pNext
1976 0, // VkPipelineRasterizationStateCreateFlags flags
1977 VK_FALSE, // VkBool32 depthClampEnable
1978 VK_FALSE, // VkBool32 rasterizerDiscardEnable
1979 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode
1980 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode
1981 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace
1982 VK_FALSE, // VkBool32 depthBiasEnable
1983 0.0f, // float depthBiasConstantFactor
1984 0.0f, // float depthBiasClamp
1985 0.0f, // float depthBiasSlopeFactor
1986 1.0f // float lineWidth
1987 };
1988
1989 const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
1990 {
1991 VK_TRUE, // VkBool32 blendEnable
1992 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor
1993 VK_BLEND_FACTOR_ONE, // VkBlendFactor dstColorBlendFactor
1994 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp
1995 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor
1996 VK_BLEND_FACTOR_ONE, // VkBlendFactor dstAlphaBlendFactor
1997 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp
1998 VK_COLOR_COMPONENT_R_BIT // VkColorComponentFlags colorWriteMask
1999 | VK_COLOR_COMPONENT_G_BIT
2000 | VK_COLOR_COMPONENT_B_BIT
2001 | VK_COLOR_COMPONENT_A_BIT
2002 };
2003
2004 const VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfo =
2005 {
2006 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType
2007 DE_NULL, // const void* pNext
2008 0, // VkPipelineColorBlendStateCreateFlags flags
2009 VK_FALSE, // VkBool32 logicOpEnable
2010 VK_LOGIC_OP_NO_OP, // VkLogicOp logicOp
2011 1, // deUint32 attachmentCount
2012 &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments
2013 { 0.0f, 0.0f, 0.0f, 0.0f } // float blendConstants[4]
2014 };
2015
2016 const VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfo =
2017 {
2018 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
2019 nullptr, // const void* pNext;
2020 0u, // VkPipelineMultisampleStateCreateFlags flags;
2021 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
2022 VK_FALSE, // VkBool32 sampleShadingEnable;
2023 1.0f, // float minSampleShading;
2024 nullptr, // const VkSampleMask* pSampleMask;
2025 VK_FALSE, // VkBool32 alphaToCoverageEnable;
2026 VK_FALSE, // VkBool32 alphaToOneEnable;
2027 };
2028
2029 return vk::makeGraphicsPipeline(vk,
2030 device,
2031 *pipelineLayout,
2032 *vertModule,
2033 *tescModule,
2034 *teseModule,
2035 *geomModule,
2036 *fragModule,
2037 renderPass,
2038 viewports,
2039 scissors,
2040 m_parameters.primitiveTopology,
2041 subpass,
2042 patchControlPoints,
2043 &vertexInputStateCreateInfo,
2044 &rasterizationStateCreateInfo,
2045 &multisampleStateCreateInfo,
2046 DE_NULL,
2047 &colorBlendStateCreateInfo);
2048 }
2049
fillVertexBuffer(tcu::Vec2 * vertices,const deUint64 primitivesGenerated)2050 void ConcurrentPrimitivesGeneratedQueryTestInstance::fillVertexBuffer(tcu::Vec2* vertices, const deUint64 primitivesGenerated)
2051 {
2052 const float step = 1.0f / static_cast<float>(primitivesGenerated - 1);
2053
2054 switch (m_parameters.primitiveTopology)
2055 {
2056 case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
2057 {
2058 for (deUint32 prim = 0; prim < primitivesGenerated; ++prim)
2059 {
2060 vertices[prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 0.0f);
2061 }
2062 break;
2063 }
2064 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
2065 {
2066 for (deUint32 prim = 0; prim < primitivesGenerated; ++prim)
2067 {
2068 vertices[2* prim + 0] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 0.0f);
2069 vertices[2* prim + 1] = tcu::Vec2(-1.0f + 2.0f * (float)(prim + 1) * step, 0.0f);
2070 }
2071 break;
2072 }
2073 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
2074 {
2075 vertices[0] = tcu::Vec2(-1.0f, 0.0f);
2076 vertices[1] = tcu::Vec2(-1.0f, 0.0f);
2077
2078 for (deUint32 prim = 1; prim < primitivesGenerated; ++prim)
2079 vertices[1 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 0.0f);
2080 break;
2081 }
2082 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
2083 {
2084 vertices[0] = tcu::Vec2(-1.0f, -0.001f);
2085 vertices[1] = tcu::Vec2(-1.0f, -0.002f);
2086 vertices[2] = tcu::Vec2(-1.0f + 2.0f * step, -0.002f);
2087
2088 for (deUint32 prim = 1; prim < primitivesGenerated; ++prim)
2089 {
2090 vertices[2 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)(prim + 1) * step, (prim % 2 == 0) ? -0.002f : -0.001f);
2091 }
2092 break;
2093 }
2094 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
2095 {
2096 vertices[0] = tcu::Vec2(0.0f, -0.1f);
2097 for (deUint32 prim = 0; prim < primitivesGenerated + 1; ++prim)
2098 {
2099 vertices[1 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 0.0f);
2100 }
2101 break;
2102 }
2103 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
2104 {
2105 for (deUint32 prim = 0; prim < primitivesGenerated; ++prim)
2106 {
2107 vertices[4 * prim + 0] = tcu::Vec2(-1.0f + 2.0f * (float)(prim - 1) * step, 0.0f);
2108 vertices[4 * prim + 1] = tcu::Vec2(-1.0f + 2.0f * (float)(prim + 0) * step, 0.0f);
2109 vertices[4 * prim + 2] = tcu::Vec2(-1.0f + 2.0f * (float)(prim + 1) * step, 0.0f);
2110 vertices[4 * prim + 3] = tcu::Vec2(-1.0f + 2.0f * (float)(prim + 2) * step, 0.0f);
2111 }
2112 break;
2113 }
2114 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
2115 {
2116 vertices[0] = tcu::Vec2(-1.0f, 0.0f);
2117 vertices[1] = tcu::Vec2(-1.0f, 0.0f);
2118
2119 for (deUint32 prim = 0; prim < primitivesGenerated; ++prim)
2120 {
2121 vertices[2 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)(prim + 1) * step, 0.0f);
2122 }
2123
2124 vertices[2 + primitivesGenerated] = tcu::Vec2(1.0f, 0.0f);
2125
2126 break;
2127 }
2128 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
2129 case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
2130 {
2131 for (deUint32 prim = 0; prim < primitivesGenerated; ++prim)
2132 {
2133 vertices[3 * prim + 0] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, -0.01f);
2134 vertices[3 * prim + 1] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, 0.01f);
2135 vertices[3 * prim + 2] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, 0.0f);
2136 }
2137 break;
2138 }
2139 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
2140 {
2141 for (deUint32 prim = 0; prim < primitivesGenerated; ++prim)
2142 {
2143 vertices[6 * prim + 0] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, -0.01f);
2144 vertices[6 * prim + 1] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, -0.01f);
2145 vertices[6 * prim + 2] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, -0.02f);
2146 vertices[6 * prim + 3] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, -0.02f);
2147 vertices[6 * prim + 4] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, -0.02f);
2148 vertices[6 * prim + 5] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, -0.02f);
2149 }
2150 break;
2151 }
2152 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
2153 {
2154 // A strip of triangles, each pair of them forming a quad, crossing the image from left to right.
2155 const auto quarterRow = 2.0f / (static_cast<float>(m_imageHeight) * 4.0f); // In height.
2156 const auto threeQRow = 3.0f * quarterRow; // In height.
2157 const auto quadStep = 2.0f / (static_cast<float>(primitivesGenerated) / 2.0f); // In width.
2158 const float yCoords[2] = { -threeQRow, -quarterRow };
2159
2160 // The first two points on the left edge of the image.
2161 vertices[0] = tcu::Vec2(-1.0f, yCoords[0]);
2162 vertices[1] = tcu::Vec2(-1.0f, yCoords[0]);
2163 vertices[2] = tcu::Vec2(-1.0f, yCoords[1]);
2164 vertices[3] = tcu::Vec2(-1.0f, yCoords[1]);
2165
2166 for (uint32_t primIdx = 0u; primIdx < static_cast<uint32_t>(primitivesGenerated); ++primIdx)
2167 {
2168 const auto edgeIdx = primIdx / 2u;
2169 const auto yIDx = primIdx % 2u;
2170 const auto xCoord = -1.0f + (static_cast<float>(edgeIdx) + 1.0f) * quadStep;
2171 const auto yCoord = yCoords[yIDx];
2172 const auto vertIdx = primIdx + 2u;
2173
2174 vertices[vertIdx * 2u + 0u] = tcu::Vec2(xCoord, yCoord); // Vertex.
2175 vertices[vertIdx * 2u + 1u] = tcu::Vec2(xCoord, yCoord); // Adjacency point.
2176 }
2177 break;
2178 }
2179 default:
2180 TCU_THROW(InternalError, "Unrecognized primitive topology");
2181 }
2182 }
2183
copyColorImageToBuffer(const DeviceInterface & vk,VkCommandBuffer cmdBuffer,VkImage image,VkBuffer buffer)2184 void ConcurrentPrimitivesGeneratedQueryTestInstance::copyColorImageToBuffer (const DeviceInterface& vk, VkCommandBuffer cmdBuffer, VkImage image, VkBuffer buffer)
2185 {
2186 const VkImageSubresourceRange colorSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1);
2187 vk::VkImageMemoryBarrier postImageBarrier = vk::makeImageMemoryBarrier(vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT, vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, vk::VK_IMAGE_LAYOUT_GENERAL, image, colorSubresourceRange);
2188 vk.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0u, 0u, (const vk::VkMemoryBarrier*)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1u, &postImageBarrier);
2189 vk::VkExtent3D extent = { m_imageWidth, m_imageHeight, 1 };
2190 const auto colorSubresourceLayers = vk::makeImageSubresourceLayers(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
2191 const vk::VkBufferImageCopy colorCopyRegion = vk::makeBufferImageCopy(extent, colorSubresourceLayers);
2192 vk.cmdCopyImageToBuffer(cmdBuffer, image, vk::VK_IMAGE_LAYOUT_GENERAL, buffer, 1u, &colorCopyRegion);
2193 }
2194
2195 class ConcurrentPrimitivesGeneratedQueryTestCase : public vkt::TestCase
2196 {
2197 public:
ConcurrentPrimitivesGeneratedQueryTestCase(tcu::TestContext & context,const char * name,const ConcurrentTestParameters & parameters)2198 ConcurrentPrimitivesGeneratedQueryTestCase (tcu::TestContext &context, const char *name, const ConcurrentTestParameters& parameters)
2199 : TestCase (context, name)
2200 , m_parameters (parameters)
2201 {
2202 }
2203
2204 private:
2205 void checkSupport (vkt::Context& context) const;
2206 void initPrograms (vk::SourceCollections& programCollection) const;
createInstance(vkt::Context & context) const2207 vkt::TestInstance* createInstance (vkt::Context& context) const { return new ConcurrentPrimitivesGeneratedQueryTestInstance(context, m_parameters); }
2208
2209 const ConcurrentTestParameters m_parameters;
2210 };
2211
checkSupport(vkt::Context & context) const2212 void ConcurrentPrimitivesGeneratedQueryTestCase::checkSupport (vkt::Context& context) const
2213 {
2214 context.requireDeviceFunctionality("VK_EXT_primitives_generated_query");
2215 context.requireDeviceFunctionality("VK_EXT_transform_feedback");
2216
2217 const VkPhysicalDevicePrimitivesGeneratedQueryFeaturesEXT& pgqFeatures = context.getPrimitivesGeneratedQueryFeaturesEXT();
2218 const VkPhysicalDeviceTransformFeedbackFeaturesEXT& xfbFeatures = context.getTransformFeedbackFeaturesEXT();
2219 const VkPhysicalDeviceTransformFeedbackPropertiesEXT& xfbProperties = context.getTransformFeedbackPropertiesEXT();
2220
2221 if (pgqFeatures.primitivesGeneratedQuery != VK_TRUE)
2222 TCU_THROW(NotSupportedError, "VK_QUERY_TYPE_PRIMITIVES_GENERATED_EXT not supported");
2223
2224 if (m_parameters.shaderStage == SHADER_STAGE_GEOMETRY || topologyData.at(m_parameters.primitiveTopology).hasAdjacency)
2225 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
2226
2227 if (m_parameters.shaderStage == SHADER_STAGE_TESSELLATION_EVALUATION)
2228 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
2229
2230 if (m_parameters.nonZeroStreams())
2231 {
2232 const deUint32 requiredStreams = de::max(m_parameters.pgqStreamIndex(), m_parameters.xfbStreamIndex());
2233
2234 if (m_parameters.pgqStreamIndex() > 0 && pgqFeatures.primitivesGeneratedQueryWithNonZeroStreams != VK_TRUE)
2235 TCU_THROW(NotSupportedError, "primitivesGeneratedQueryWithNonZeroStreams not supported");
2236
2237 if (xfbProperties.maxTransformFeedbackStreams <= requiredStreams)
2238 TCU_THROW(NotSupportedError, "Required amount of XFB streams not supported");
2239 }
2240
2241 if (xfbFeatures.transformFeedback != VK_TRUE)
2242 TCU_THROW(NotSupportedError, "transformFeedback not supported");
2243
2244 if (xfbProperties.transformFeedbackQueries != VK_TRUE)
2245 TCU_THROW(NotSupportedError, "transformFeedbackQueries not supported");
2246 }
2247
initPrograms(vk::SourceCollections & programCollection) const2248 void ConcurrentPrimitivesGeneratedQueryTestCase::initPrograms (vk::SourceCollections& programCollection) const
2249 {
2250 bool transformFeedback = m_parameters.xfbStreamIndex() != VERTEX_STREAM_NONE;
2251 // Vertex shader.
2252 {
2253 const bool vertXfb = (transformFeedback && m_parameters.shaderStage == SHADER_STAGE_VERTEX);
2254 std::ostringstream src;
2255
2256 src << "#version 450\n";
2257 src << "layout(location=0) in vec2 inPosition;\n";
2258
2259 if (vertXfb)
2260 src << "layout(xfb_buffer = 0, xfb_offset = 0, xfb_stride = 16, location = 0) out vec4 out0;\n";
2261
2262 src << "void main (void)\n"
2263 "{\n";
2264
2265 if (m_parameters.primitiveTopology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST && m_parameters.shaderStage == SHADER_STAGE_VERTEX)
2266 src << " gl_PointSize = 1.0;\n";
2267
2268 src << " gl_Position = vec4(inPosition, 0, 1);\n";
2269
2270 if (vertXfb)
2271 src << " out0 = vec4(42);\n";
2272
2273 src << "}\n";
2274
2275 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
2276 }
2277
2278 // Geometry shader.
2279 if (m_parameters.shaderStage == SHADER_STAGE_GEOMETRY)
2280 {
2281 const bool outputPoints = m_parameters.nonZeroStreams() || m_parameters.primitiveTopology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
2282 const char* const inputTopology = topologyData.at(m_parameters.primitiveTopology).inputString;
2283 const char* const outputTopology = outputPoints ? "points" : topologyData.at(m_parameters.primitiveTopology).outputString;
2284 const VkDeviceSize outputPrimSize = outputPoints ? 1 : topologyData.at(m_parameters.primitiveTopology).primitiveSize;
2285 VkDeviceSize maxVertices = (transformFeedback && m_parameters.multipleStreams()) ? outputPrimSize * 2 : outputPrimSize;
2286 const bool outputZero = m_parameters.pgqStreamIndex() != 0 && (!transformFeedback || (transformFeedback && m_parameters.xfbStreamIndex() != 0));
2287 if (outputZero) maxVertices *= 2;
2288 const std::string pgqEmitCommand = m_parameters.nonZeroStreams() ? std::string("EmitStreamVertex(") + de::toString(m_parameters.pgqStreamIndex()) + ")" : "EmitVertex()";
2289 const std::string xfbEmitCommand = m_parameters.nonZeroStreams() ? std::string("EmitStreamVertex(") + de::toString(m_parameters.xfbStreamIndex()) + ")" : "EmitVertex()";
2290 const std::string pgqEndCommand = m_parameters.nonZeroStreams() ? std::string("EndStreamPrimitive(") + de::toString(m_parameters.pgqStreamIndex()) + ")" : "EndPrimitive()";
2291 const std::string xfbEndCommand = m_parameters.nonZeroStreams() ? std::string("EndStreamPrimitive(") + de::toString(m_parameters.xfbStreamIndex()) + ")" : "EndPrimitive()";
2292 std::string output;
2293
2294 if (m_parameters.primitiveTopology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY)
2295 {
2296 output =
2297 // Each point will be in the middle X and Y coordinates of each triangle.
2298 " const vec3 xCoords = vec3(gl_in[0].gl_Position.x, gl_in[2].gl_Position.x, gl_in[4].gl_Position.x);\n"
2299 " const vec3 yCoords = vec3(gl_in[0].gl_Position.y, gl_in[2].gl_Position.y, gl_in[4].gl_Position.y);\n"
2300 " const float maxX = max(max(xCoords.x, xCoords.y), xCoords.z);\n"
2301 " const float minX = min(min(xCoords.x, xCoords.y), xCoords.z);\n"
2302 " const float maxY = max(max(yCoords.x, yCoords.y), yCoords.z);\n"
2303 " const float minY = min(min(yCoords.x, yCoords.y), yCoords.z);\n"
2304 " gl_Position = vec4((maxX + minX) / 2.0, (maxY + minY) / 2.0, gl_in[0].gl_Position.z, gl_in[0].gl_Position.w);\n"
2305 ;
2306 }
2307 else if (m_parameters.primitiveTopology != VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN)
2308 output = " gl_Position = gl_in[0].gl_Position;\n";
2309 else
2310 output = " gl_Position = abs(gl_in[0].gl_Position.y) < abs(gl_in[1].gl_Position.y) ? gl_in[0].gl_Position : gl_in[1].gl_Position;\n";
2311
2312 if (outputPoints)
2313 output += " gl_PointSize = 1.0;\n";
2314
2315 std::ostringstream src;
2316
2317 src << "#version 450\n"
2318 "layout(" << inputTopology << ") in;\n"
2319 "layout(" << outputTopology << ", max_vertices = " << maxVertices << ") out;\n";
2320
2321 if (transformFeedback)
2322 src << "layout(xfb_buffer = 0, xfb_offset = 0, xfb_stride = 16, location = 0, stream = " << m_parameters.xfbStreamIndex() << ") out vec4 xfb;\n";
2323
2324 src << "void main (void)\n"
2325 "{\n";
2326
2327 if (outputZero)
2328 {
2329 src << output;
2330 src << " EmitVertex();\n";
2331 src << " EndPrimitive();\n";
2332 }
2333
2334 if (transformFeedback)
2335 src << " xfb = vec4(42);\n";
2336
2337 for (VkDeviceSize i = 0; i < outputPrimSize; i++)
2338 {
2339 if (m_parameters.pgqStreamIndex() == 0)
2340 src << output;
2341 src << " " << pgqEmitCommand << ";\n";
2342 }
2343
2344 src << " " << pgqEndCommand << ";\n";
2345
2346 if (transformFeedback && m_parameters.multipleStreams())
2347 {
2348 for (VkDeviceSize i = 0; i < outputPrimSize; i++)
2349 {
2350 if (m_parameters.xfbStreamIndex() == 0)
2351 src << output;
2352 src << " " << xfbEmitCommand << ";\n";
2353 }
2354
2355 src << " " << xfbEndCommand << ";\n";
2356 }
2357
2358 src << "}\n";
2359
2360 programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
2361 }
2362
2363 // Fragment shader.
2364 {
2365 std::ostringstream src;
2366
2367 src << "#version 450\n"
2368 "layout(location = 0) out vec4 out0;\n"
2369 "void main (void)\n"
2370 "{\n"
2371 " out0 = vec4(0.0, 1.0, 0.0, 1.0);\n"
2372 "}\n";
2373
2374 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
2375 }
2376 }
2377
testGenerator(tcu::TestCaseGroup * pgqGroup)2378 void testGenerator (tcu::TestCaseGroup* pgqGroup)
2379 {
2380 constexpr struct ReadType
2381 {
2382 QueryReadType type;
2383 const char* name;
2384 } readTypes[] =
2385 {
2386 // Tests for vkGetQueryPoolResults
2387 { QUERY_READ_TYPE_GET, "get"},
2388 // Tests for vkCmdCopyQueryPoolResults
2389 { QUERY_READ_TYPE_COPY, "copy"},
2390 };
2391 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(readTypes) == QUERY_READ_TYPE_LAST);
2392
2393 constexpr struct ResetType
2394 {
2395 QueryResetType type;
2396 const char* name;
2397 } resetTypes[] =
2398 {
2399 // Tests for vkCmdResetQueryPool
2400 { QUERY_RESET_TYPE_QUEUE, "queue_reset"},
2401 // Tests for vkResetQueryPool
2402 { QUERY_RESET_TYPE_HOST, "host_reset"},
2403 };
2404 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(resetTypes) == QUERY_RESET_TYPE_LAST);
2405
2406 constexpr struct ResultTypes
2407 {
2408 QueryResultType type;
2409 const char* name;
2410 } resultTypes[] =
2411 {
2412 // Tests for default query result size
2413 { QUERY_RESULT_TYPE_32_BIT, "32bit"},
2414 // Tests for VK_QUERY_RESULT_64_BIT
2415 { QUERY_RESULT_TYPE_64_BIT, "64bit"},
2416 // Tests for PGQ without and XFBQ with VK_QUERY_RESULT_64_BIT
2417 { QUERY_RESULT_TYPE_PGQ_32_XFB_64, "pgq_32bit_xfb_64bit"},
2418 // Tests for PGQ with and XFBQ without VK_QUERY_RESULT_64_BIT
2419 { QUERY_RESULT_TYPE_PGQ_64_XFB_32, "pgq_64bit_xfb_32bit"},
2420 };
2421 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(resultTypes) == QUERY_RESULT_TYPE_LAST);
2422
2423 constexpr struct Shader
2424 {
2425 ShaderStage stage;
2426 const char* name;
2427 } shaderStages[] =
2428 {
2429 // Vertex shader tests
2430 { SHADER_STAGE_VERTEX, "vert"},
2431 // Tessellation evaluation shader tests
2432 { SHADER_STAGE_TESSELLATION_EVALUATION, "tese"},
2433 // Geometry shader tests
2434 { SHADER_STAGE_GEOMETRY, "geom"},
2435 };
2436 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(shaderStages) == SHADER_STAGE_LAST);
2437
2438 constexpr struct TransformFeedbackState
2439 {
2440 deBool enable;
2441 const char* name;
2442 } transformFeedbackStates[] =
2443 {
2444 // Tests without transform feedback
2445 { DE_FALSE, "no_xfb"},
2446 // Tests for comparing PGQ results against transform feedback query results
2447 { DE_TRUE, "xfb"},
2448 };
2449
2450 constexpr struct RastCase
2451 {
2452 RasterizationCase type;
2453 deBool dsAttachment;
2454 const char* name;
2455 } rastCases[] =
2456 {
2457 // Tests with rasterizer discard
2458 { RAST_CASE_DISCARD, DE_FALSE, "no_rast"},
2459 // Tests without rasterizer discard
2460 { RAST_CASE_DEFAULT, DE_FALSE, "rast"},
2461 // Tests with an empty fragment shader
2462 { RAST_CASE_EMPTY_FRAG, DE_FALSE, "empty_frag"},
2463 // Tests with an attachmentless render pass
2464 { RAST_CASE_NO_ATTACHMENT, DE_FALSE, "no_attachment"},
2465 // Tests disabling color output using VkPipelineColorWriteCreateInfoEXT
2466 { RAST_CASE_COLOR_WRITE_DISABLE_STATIC, DE_FALSE, "color_write_disable_static"},
2467 // Tests disabling color output using VkPipelineColorWriteCreateInfoEXT with a depth stencil attachment
2468 { RAST_CASE_COLOR_WRITE_DISABLE_STATIC, DE_TRUE, "color_write_disable_static_ds"},
2469 // Tests disabling color output using vkCmdSetColorWriteEnableEXT
2470 { RAST_CASE_COLOR_WRITE_DISABLE_DYNAMIC, DE_FALSE, "color_write_disable_dynamic"},
2471 // Tests disabling color output using vkCmdSetColorWriteEnableEXT with a depth stencil attachment
2472 { RAST_CASE_COLOR_WRITE_DISABLE_DYNAMIC, DE_TRUE, "color_write_disable_dynamic_ds"},
2473 };
2474
2475 static const std::set<RasterizationCase> rasterizationCasesWithAvailability
2476 {
2477 RAST_CASE_DISCARD,
2478 RAST_CASE_DEFAULT,
2479 RAST_CASE_NO_ATTACHMENT,
2480 };
2481
2482 constexpr struct Topology
2483 {
2484 VkPrimitiveTopology type;
2485 const char* name;
2486 } topologies[] =
2487 {
2488 // Tests for separate point primitives
2489 { VK_PRIMITIVE_TOPOLOGY_POINT_LIST, "point_list"},
2490 // Tests for separate line primitives
2491 { VK_PRIMITIVE_TOPOLOGY_LINE_LIST, "line_list"},
2492 // Tests for connected line primitives with consecutive lines sharing a vertex
2493 { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, "line_strip"},
2494 // Tests for separate triangle primitives
2495 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, "triangle_list"},
2496 // Tests for connected triangle primitives with consecutive triangles sharing an edge
2497 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, "triangle_strip"},
2498 // Tests for connected triangle primitives with all triangles sharing a common vertex
2499 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, "triangle_fan"},
2500 // Tests for separate line primitives with adjacency
2501 { VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY, "line_list_with_adjacency"},
2502 // Tests for connected line primitives with adjacency, with consecutive primitives sharing three vertices
2503 { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY, "line_strip_with_adjacency"},
2504 // Tests for separate triangle primitives with adjacency
2505 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY, "triangle_list_with_adjacency"},
2506 // Tests for connected triangle primitives with adjacency, with consecutive triangles sharing an edge
2507 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY, "triangle_strip_with_adjacency"},
2508 // Tests for separate patch primitives
2509 { VK_PRIMITIVE_TOPOLOGY_PATCH_LIST, "patch_list"},
2510 };
2511
2512 static const std::set<VkPrimitiveTopology> topologiesWithAvailability
2513 {
2514 VK_PRIMITIVE_TOPOLOGY_LINE_LIST,
2515 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
2516 VK_PRIMITIVE_TOPOLOGY_PATCH_LIST,
2517 };
2518
2519 // Tests for vkCmdBeginQueryIndexedEXT and vkCmdEndQueryIndexedEXT.
2520 constexpr struct StreamIndex
2521 {
2522 VertexStream index;
2523 const char* name;
2524 } streamIndices[] =
2525 {
2526 { VERTEX_STREAM_DEFAULT, "default" },
2527 { VERTEX_STREAM_0, "0" },
2528 { VERTEX_STREAM_1, "1" },
2529 };
2530
2531 constexpr struct CmdBufCase
2532 {
2533 CommandBufferCase type;
2534 const char* name;
2535 } cmdBufCases[] =
2536 {
2537 // Test single draw call
2538 { CMD_BUF_CASE_SINGLE_DRAW, "single_draw"},
2539 // Test two draw calls
2540 { CMD_BUF_CASE_TWO_DRAWS, "two_draws"},
2541 };
2542 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(cmdBufCases) == CMD_BUF_CASE_LAST);
2543
2544 constexpr struct
2545 {
2546 uint32_t queryCount;
2547 const char* nameSuffix;
2548 } queryCountCases[] =
2549 {
2550 { 1u, ""},
2551 // using 2 queries
2552 { 2u, "_2_queries"},
2553 };
2554
2555 constexpr struct QueryOrderCase
2556 {
2557 QueryOrder order;
2558 const char* name;
2559 } queryOrderCases[] =
2560 {
2561 // Test starting primitives generated query first
2562 { QUERY_ORDER_PGQ_FIRST, "pqg_first"},
2563 // Test starting transform feedback query first
2564 { QUERY_ORDER_XFBQ_FIRST, "xfbq_first"},
2565 };
2566 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(queryOrderCases) == QUERY_ORDER_LAST);
2567
2568 constexpr struct OutsideDrawCase
2569 {
2570 OutsideDraw outsideDraw;
2571 const char* name;
2572 } outsideDrawCases[] =
2573 {
2574 // Test without draws outside of active queries
2575 { OUTSIDE_DRAW_NONE, "none"},
2576 // Test with draws before active queries
2577 { OUTSIDE_DRAW_BEFORE, "before"},
2578 // Test with draw after active queries
2579 { OUTSIDE_DRAW_AFTER, "after"},
2580 };
2581 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(outsideDrawCases) == OUTSIDE_DRAW_LAST);
2582
2583 tcu::TestContext& testCtx = pgqGroup->getTestContext();
2584
2585 for (const ReadType& read : readTypes)
2586 {
2587 de::MovePtr<tcu::TestCaseGroup> readGroup(new tcu::TestCaseGroup(testCtx, read.name));
2588
2589 for (const ResetType& reset : resetTypes)
2590 {
2591 de::MovePtr<tcu::TestCaseGroup> resetGroup(new tcu::TestCaseGroup(testCtx, reset.name));
2592
2593 for (const ResultTypes& result : resultTypes)
2594 {
2595 de::MovePtr<tcu::TestCaseGroup> resultGroup(new tcu::TestCaseGroup(testCtx, result.name));
2596
2597 for (const Shader& shader : shaderStages)
2598 {
2599 de::MovePtr<tcu::TestCaseGroup> shaderGroup(new tcu::TestCaseGroup(testCtx, shader.name));
2600
2601 for (const TransformFeedbackState& xfbState : transformFeedbackStates)
2602 {
2603 de::MovePtr<tcu::TestCaseGroup> xfbGroup(new tcu::TestCaseGroup(testCtx, xfbState.name));
2604
2605 // Only test multiple result types with XFB enabled.
2606 if ((result.type == QUERY_RESULT_TYPE_PGQ_32_XFB_64 || result.type == QUERY_RESULT_TYPE_PGQ_64_XFB_32) && !xfbState.enable)
2607 continue;
2608
2609 for (const RastCase& rastCase : rastCases)
2610 {
2611 de::MovePtr<tcu::TestCaseGroup> rastGroup(new tcu::TestCaseGroup(testCtx, rastCase.name));
2612
2613 // Skip uninteresting cases
2614 if ((rastCase.type > RAST_CASE_DISCARD)
2615 && ((read.type != QUERY_READ_TYPE_GET)
2616 || (reset.type != QUERY_RESET_TYPE_QUEUE)
2617 || (result.type != QUERY_RESULT_TYPE_32_BIT)))
2618 {
2619 continue;
2620 }
2621
2622 for (const Topology& topology : topologies)
2623 {
2624 de::MovePtr<tcu::TestCaseGroup> topologyGroup(new tcu::TestCaseGroup(testCtx, topology.name));
2625
2626 // Only test patch lists with tessellation shaders.
2627 if ((topology.type == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST && shader.stage != SHADER_STAGE_TESSELLATION_EVALUATION) ||
2628 ((topology.type != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST && shader.stage == SHADER_STAGE_TESSELLATION_EVALUATION)))
2629 {
2630 continue;
2631 }
2632
2633 // Only test adjacency topologies with geometry shaders.
2634 if (shader.stage != SHADER_STAGE_GEOMETRY && topologyData.at(topology.type).hasAdjacency)
2635 continue;
2636
2637 for (const StreamIndex& pgqStream : streamIndices)
2638 {
2639 for (const StreamIndex& xfbStream : streamIndices)
2640 {
2641 const std::string streamGroupName = std::string("pgq_") + pgqStream.name + (xfbState.enable ? std::string("_xfb_") + xfbStream.name : "");
2642 const bool pgqDefault = (pgqStream.index == VERTEX_STREAM_DEFAULT);
2643 const bool xfbDefault = (xfbStream.index == VERTEX_STREAM_DEFAULT);
2644 const std::string pgqDescStr = std::string("PGQ on ") + (pgqDefault ? "default " : "") + std::string("vertex stream ") + (pgqDefault ? "" : pgqStream.name);
2645 const std::string xfbDescStr = std::string("XFB on ") + (xfbDefault ? "default " : "") + std::string("vertex stream ") + (xfbDefault ? "" : xfbStream.name);
2646 const std::string streamGroupDesc = std::string("Tests for ") + pgqDescStr + (xfbState.enable ? (std::string(" and ") + xfbDescStr) : "");
2647 de::MovePtr<tcu::TestCaseGroup> streamGroup(new tcu::TestCaseGroup(testCtx, streamGroupName.c_str()));
2648
2649 // Only test nondefault vertex streams with geometry shaders.
2650 if ((pgqStream.index != VERTEX_STREAM_DEFAULT || xfbStream.index != VERTEX_STREAM_DEFAULT) && shader.stage != SHADER_STAGE_GEOMETRY)
2651 continue;
2652
2653 // Skip nondefault vertex streams for XFB when not enabled.
2654 if (!xfbState.enable && xfbStream.index != VERTEX_STREAM_DEFAULT)
2655 continue;
2656
2657 for (const CmdBufCase& cmdBufCase : cmdBufCases)
2658 {
2659 de::MovePtr<tcu::TestCaseGroup> cmdBufGroup(new tcu::TestCaseGroup(testCtx, cmdBufCase.name));
2660
2661 for (const QueryOrderCase& queryOrderCase : queryOrderCases)
2662 {
2663 if (queryOrderCase.order == QUERY_ORDER_XFBQ_FIRST && xfbState.enable == DE_FALSE)
2664 continue;
2665
2666 de::MovePtr<tcu::TestCaseGroup> queryOrderGroup(new tcu::TestCaseGroup(testCtx, queryOrderCase.name));
2667 for (const OutsideDrawCase& outSideDrawCase : outsideDrawCases)
2668 {
2669 for (const auto& countCase : queryCountCases)
2670 {
2671 for (const auto availabilityBit : { false, true})
2672 {
2673 if (availabilityBit && topologiesWithAvailability.count(topology.type) == 0)
2674 continue;
2675
2676 if (availabilityBit && rasterizationCasesWithAvailability.count(rastCase.type) == 0)
2677 continue;
2678
2679 if (availabilityBit && cmdBufCase.type != CMD_BUF_CASE_SINGLE_DRAW)
2680 continue;
2681
2682 const TestParameters parameters =
2683 {
2684 read.type, // QueryReadType queryReadType
2685 reset.type, // QueryResetType queryResetType
2686 result.type, // QueryResultType queryResultType
2687 shader.stage, // ShaderStage shaderStage
2688 xfbState.enable, // deBool transformFeedback
2689 rastCase.type, // RasterizationCase rastCase
2690 rastCase.dsAttachment, // deBool depthStencilAttachment
2691 topology.type, // VkPrimitiveTopology primitiveTopology
2692 pgqStream.index, // VertexStreamIndex pgqStreamIndex
2693 xfbStream.index, // VertexStreamIndex xfbStreamIndex
2694 cmdBufCase.type, // CommandBufferCase cmdBufCase
2695 countCase.queryCount, // const uint32_t queryCount
2696 queryOrderCase.order, // QueryOrder queryOrder
2697 outSideDrawCase.outsideDraw, // OutsideDraw outsideDraw
2698 availabilityBit, // const bool availabilityBit
2699 };
2700
2701 const auto availabilityNameSuffix = (availabilityBit ? "_with_availability" : "");
2702 const auto name = std::string(outSideDrawCase.name) + countCase.nameSuffix + availabilityNameSuffix;
2703
2704 queryOrderGroup->addChild(new PrimitivesGeneratedQueryTestCase(testCtx, name.c_str(), parameters));
2705 }
2706 }
2707 }
2708
2709 cmdBufGroup->addChild(queryOrderGroup.release());
2710 }
2711
2712 streamGroup->addChild(cmdBufGroup.release());
2713 }
2714
2715 topologyGroup->addChild(streamGroup.release());
2716 }
2717 }
2718
2719 rastGroup->addChild(topologyGroup.release());
2720 }
2721
2722 xfbGroup->addChild(rastGroup.release());
2723 }
2724
2725 shaderGroup->addChild(xfbGroup.release());
2726 }
2727
2728 resultGroup->addChild(shaderGroup.release());
2729 }
2730
2731 resetGroup->addChild(resultGroup.release());
2732 }
2733
2734 readGroup->addChild(resetGroup.release());
2735 }
2736
2737 pgqGroup->addChild(readGroup.release());
2738 }
2739
2740 constexpr struct ConcurrentTestTypeCase
2741 {
2742 ConcurrentTestType type;
2743 const char* name;
2744 }
2745 concurrentTestTypeCases[] =
2746 {
2747 { CONCURRENT_TEST_TYPE_TWO_XFB_INSIDE_PGQ, "two_xfbq_inside_pgq"},
2748 { CONCURRENT_TEST_TYPE_PGQ_SECONDARY_CMD_BUFFER, "pgq_secondary_cmd_buffers"},
2749 { CONCURRENT_TEST_TYPE_PIPELINE_STATISTICS_1, "pipeline_statistics_1"},
2750 { CONCURRENT_TEST_TYPE_PIPELINE_STATISTICS_2, "pipeline_statistics_2"},
2751 { CONCURRENT_TEST_TYPE_PIPELINE_STATISTICS_3, "pipeline_statistics_3"},
2752 };
2753 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(concurrentTestTypeCases) == CONCURRENT_TEST_TYPE_LAST);
2754
2755
2756 constexpr struct DrawTypeCase
2757 {
2758 bool indirect;
2759 const char* name;
2760 }
2761 drawTypeCases[] =
2762 {
2763 { false, "draw"},
2764 { true, "indirect"},
2765 };
2766
2767 de::MovePtr<tcu::TestCaseGroup> concurrentGroup(new tcu::TestCaseGroup(testCtx, "concurrent"));
2768
2769 for (const ConcurrentTestTypeCase& concurrentTestType : concurrentTestTypeCases)
2770 {
2771 de::MovePtr<tcu::TestCaseGroup> concurrentTypeGroup(new tcu::TestCaseGroup(testCtx, concurrentTestType.name));
2772 for (const ResultTypes& result : resultTypes)
2773 {
2774 de::MovePtr<tcu::TestCaseGroup> resultGroup(new tcu::TestCaseGroup(testCtx, result.name));
2775
2776 for (const Topology& topology : topologies)
2777 {
2778 // Testing only with geometry shaders, skip patch list
2779 if (topology.type == vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST)
2780 continue;
2781
2782 de::MovePtr<tcu::TestCaseGroup> topologyGroup(new tcu::TestCaseGroup(testCtx, topology.name));
2783
2784 for (const DrawTypeCase& draw : drawTypeCases)
2785 {
2786 VertexStream pgqStreamIndex = VERTEX_STREAM_DEFAULT;
2787 VertexStream xfbStreamIndex = VERTEX_STREAM_NONE;
2788 if (concurrentTestType.type == CONCURRENT_TEST_TYPE_TWO_XFB_INSIDE_PGQ)
2789 xfbStreamIndex = VERTEX_STREAM_1;
2790
2791 const ConcurrentTestParameters parameters =
2792 {
2793 concurrentTestType.type, // ConcurrentTestType concurrentTestType;
2794 result.type, // QueryResultType queryResultType
2795 SHADER_STAGE_GEOMETRY, // ShaderStage shaderStage
2796 topology.type, // VkPrimitiveTopology primitiveTopology
2797 pgqStreamIndex, // VertexStreamIndex pgqStreamIndex
2798 xfbStreamIndex, // VertexStreamIndex xfbStreamIndex
2799 draw.indirect, // bool indirect
2800 };
2801
2802 topologyGroup->addChild(new ConcurrentPrimitivesGeneratedQueryTestCase(testCtx, draw.name, parameters));
2803 }
2804
2805 resultGroup->addChild(topologyGroup.release());
2806 }
2807
2808 concurrentTypeGroup->addChild(resultGroup.release());
2809 }
2810
2811 concurrentGroup->addChild(concurrentTypeGroup.release());
2812 }
2813 pgqGroup->addChild(concurrentGroup.release());
2814 }
2815
2816 } // anonymous
2817
createPrimitivesGeneratedQueryTests(tcu::TestContext & testCtx)2818 tcu::TestCaseGroup* createPrimitivesGeneratedQueryTests (tcu::TestContext& testCtx)
2819 {
2820 return createTestGroup(testCtx, "primitives_generated_query", testGenerator);
2821 }
2822
2823 } // TransformFeedback
2824 } // vkt
2825