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
36 #include "tcuTestLog.hpp"
37
38 #include <functional>
39 #include <map>
40
41 namespace vkt
42 {
43 namespace TransformFeedback
44 {
45 namespace
46 {
47 using namespace vk;
48
49 enum
50 {
51 IMAGE_WIDTH = 64,
52 IMAGE_HEIGHT = IMAGE_WIDTH,
53 };
54
55 enum QueryReadType
56 {
57 QUERY_READ_TYPE_GET,
58 QUERY_READ_TYPE_COPY,
59
60 QUERY_READ_TYPE_LAST
61 };
62
63 enum QueryResetType
64 {
65 QUERY_RESET_TYPE_QUEUE,
66 QUERY_RESET_TYPE_HOST,
67
68 QUERY_RESET_TYPE_LAST
69 };
70
71 enum QueryResultType
72 {
73 QUERY_RESULT_TYPE_32_BIT,
74 QUERY_RESULT_TYPE_64_BIT,
75 QUERY_RESULT_TYPE_PGQ_32_XFB_64,
76 QUERY_RESULT_TYPE_PGQ_64_XFB_32,
77
78 QUERY_RESULT_TYPE_LAST
79 };
80
81 enum ShaderStage
82 {
83 SHADER_STAGE_VERTEX,
84 SHADER_STAGE_TESSELLATION_EVALUATION,
85 SHADER_STAGE_GEOMETRY,
86
87 SHADER_STAGE_LAST
88 };
89
90 enum RasterizationCase
91 {
92 RAST_CASE_DEFAULT,
93 RAST_CASE_DISCARD,
94 RAST_CASE_EMPTY_FRAG,
95 RAST_CASE_NO_ATTACHMENT,
96 RAST_CASE_COLOR_WRITE_DISABLE_STATIC,
97 RAST_CASE_COLOR_WRITE_DISABLE_DYNAMIC,
98
99 RAST_CASE_LAST
100 };
101
102 enum VertexStream
103 {
104 VERTEX_STREAM_DEFAULT = -1,
105 VERTEX_STREAM_0 = 0,
106 VERTEX_STREAM_1 = 1,
107 };
108
109 enum CommandBufferCase
110 {
111 CMD_BUF_CASE_SINGLE_DRAW,
112
113 CMD_BUF_CASE_LAST
114 };
115
116 struct TestParameters
117 {
118 QueryReadType queryReadType;
119 QueryResetType queryResetType;
120 QueryResultType queryResultType;
121 ShaderStage shaderStage;
122 deBool transformFeedback;
123 RasterizationCase rastCase;
124 deBool depthStencilAttachment;
125 VkPrimitiveTopology primitiveTopology;
126 VertexStream pgqStream;
127 VertexStream xfbStream;
128 CommandBufferCase cmdBufCase;
129
pgqDefaultvkt::TransformFeedback::__anone8ff03cc0111::TestParameters130 bool pgqDefault (void) const { return pgqStream == VERTEX_STREAM_DEFAULT; }
xfbDefaultvkt::TransformFeedback::__anone8ff03cc0111::TestParameters131 bool xfbDefault (void) const { return xfbStream == VERTEX_STREAM_DEFAULT; }
pgqStreamIndexvkt::TransformFeedback::__anone8ff03cc0111::TestParameters132 deUint32 pgqStreamIndex (void) const { return pgqDefault() ? 0 : static_cast<deUint32>(pgqStream); }
xfbStreamIndexvkt::TransformFeedback::__anone8ff03cc0111::TestParameters133 deUint32 xfbStreamIndex (void) const { return xfbDefault() ? 0 : static_cast<deUint32>(xfbStream); }
multipleStreamsvkt::TransformFeedback::__anone8ff03cc0111::TestParameters134 bool multipleStreams (void) const { return pgqStreamIndex() != xfbStreamIndex(); }
nonZeroStreamsvkt::TransformFeedback::__anone8ff03cc0111::TestParameters135 bool nonZeroStreams (void) const { return (pgqStreamIndex() != 0) || (xfbStreamIndex() != 0); }
rastDiscardvkt::TransformFeedback::__anone8ff03cc0111::TestParameters136 bool rastDiscard (void) const { return rastCase == RAST_CASE_DISCARD; }
colorAttachmentvkt::TransformFeedback::__anone8ff03cc0111::TestParameters137 bool colorAttachment (void) const { return !rastDiscard() && rastCase != RAST_CASE_NO_ATTACHMENT; }
staticColorWriteDisablevkt::TransformFeedback::__anone8ff03cc0111::TestParameters138 bool staticColorWriteDisable (void) const { return rastCase == RAST_CASE_COLOR_WRITE_DISABLE_STATIC; }
dynamicColorWriteDisablevkt::TransformFeedback::__anone8ff03cc0111::TestParameters139 bool dynamicColorWriteDisable (void) const { return rastCase == RAST_CASE_COLOR_WRITE_DISABLE_DYNAMIC; }
colorWriteDisablevkt::TransformFeedback::__anone8ff03cc0111::TestParameters140 bool colorWriteDisable (void) const { return staticColorWriteDisable() || dynamicColorWriteDisable(); }
141 };
142
143 struct TopologyInfo
144 {
145 deUint32 primitiveSize; // Size of the primitive.
146 deBool hasAdjacency; // True if topology has adjacency.
147 const char* inputString; // Layout qualifier identifier for geometry shader input.
148 const char* outputString; // Layout qualifier identifier for geometry shader output.
149 std::function<deUint64(deUint64)> getNumPrimitives; // Number of primitives generated.
150 std::function<deUint64(deUint64)> getNumVertices; // Number of vertices generated.
151 };
152
153 const std::map<VkPrimitiveTopology, TopologyInfo> topologyData =
154 {
__anone8ff03cc0302() 155 { VK_PRIMITIVE_TOPOLOGY_POINT_LIST, { 1, DE_FALSE, "points", "points", [](deUint64 vtxCount) { return vtxCount; }, [](deUint64 primCount) { return primCount; } } },
__anone8ff03cc0502() 156 { VK_PRIMITIVE_TOPOLOGY_LINE_LIST, { 2, DE_FALSE, "lines", "line_strip", [](deUint64 vtxCount) { return vtxCount / 2u; }, [](deUint64 primCount) { return primCount * 2u; } } },
__anone8ff03cc0802() 157 { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, { 2, DE_FALSE, "lines", "line_strip", [](deUint64 vtxCount) { return vtxCount - 1u; }, [](deUint64 primCount) { return primCount + 1u; } } },
__anone8ff03cc0a02() 158 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, { 3, DE_FALSE, "triangles", "triangle_strip", [](deUint64 vtxCount) { return vtxCount / 3u; }, [](deUint64 primCount) { return primCount * 3u; } } },
__anone8ff03cc0c02() 159 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, { 3, DE_FALSE, "triangles", "triangle_strip", [](deUint64 vtxCount) { return vtxCount - 2u; }, [](deUint64 primCount) { return primCount + 2u; } } },
__anone8ff03cc0e02() 160 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, { 3, DE_FALSE, "triangles", "triangle_strip", [](deUint64 vtxCount) { return vtxCount - 2u; }, [](deUint64 primCount) { return primCount + 2u; } } },
__anone8ff03cc1002() 161 { VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY, { 2, DE_TRUE, "lines_adjacency", "line_strip", [](deUint64 vtxCount) { return vtxCount / 4u; }, [](deUint64 primCount) { return primCount * 4u; } } },
__anone8ff03cc1102() 162 { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY, { 2, DE_TRUE, "lines_adjacency", "line_strip", [](deUint64 vtxCount) { return vtxCount - 3u; }, [](deUint64 primCount) { return primCount + 3u; } } },
__anone8ff03cc1402() 163 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY, { 3, DE_TRUE, "triangles_adjacency", "triangle_strip", [](deUint64 vtxCount) { return vtxCount / 6u; }, [](deUint64 primCount) { return primCount * 6u; } } },
__anone8ff03cc1602() 164 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY, { 3, DE_TRUE, "triangles_adjacency", "triangle_strip", [](deUint64 vtxCount) { return (vtxCount - 4u) / 2u; }, [](deUint64 primCount) { return primCount * 2u + 4; } } },
__anone8ff03cc1802() 165 { VK_PRIMITIVE_TOPOLOGY_PATCH_LIST, { 3, DE_FALSE, "ERROR", "ERROR", [](deUint64 vtxCount) { return vtxCount / 3u; }, [](deUint64 primCount) { return primCount * 3u; } } },
166 };
167
168 class PrimitivesGeneratedQueryTestInstance : public vkt::TestInstance
169 {
170 public:
PrimitivesGeneratedQueryTestInstance(vkt::Context & context,const TestParameters & parameters)171 PrimitivesGeneratedQueryTestInstance (vkt::Context &context, const TestParameters& parameters)
172 : vkt::TestInstance (context)
173 , m_parameters (parameters)
174 {
175 }
176
177 private:
178 tcu::TestStatus iterate (void);
179 VkFormat selectDepthStencilFormat (void);
180 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface& vk,
181 const VkDevice device,
182 const VkRenderPass renderPass);
183 void fillVertexBuffer (tcu::Vec2* vertices,
184 const deUint64 primitivesGenerated);
185 const TestParameters m_parameters;
186 };
187
iterate(void)188 tcu::TestStatus PrimitivesGeneratedQueryTestInstance::iterate (void)
189 {
190 const DeviceInterface& vk = m_context.getDeviceInterface();
191 const VkDevice device = m_context.getDevice();
192 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
193 const VkQueue queue = m_context.getUniversalQueue();
194 Allocator& allocator = m_context.getDefaultAllocator();
195
196 const VkFormat colorFormat = m_parameters.colorAttachment() ? VK_FORMAT_R8G8B8A8_UNORM : VK_FORMAT_UNDEFINED;
197 Move<VkImage> colorImage;
198 de::MovePtr<Allocation> colorImageAllocation;
199
200 if (m_parameters.colorAttachment())
201 {
202 const VkImageCreateInfo colorImageCreateInfo =
203 {
204 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType
205 DE_NULL, // const void* pNext
206 0u, // VkImageCreateFlags flags
207 VK_IMAGE_TYPE_2D, // VkImageType imageType
208 colorFormat, // VkFormat format
209 makeExtent3D(IMAGE_WIDTH, IMAGE_HEIGHT, 1), // VkExtent3D extent
210 1u, // deUint32 mipLevels
211 1u, // deUint32 arrayLayers
212 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
213 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling
214 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, // VkImageUsageFlags usage
215 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode
216 0u, // deUint32 queueFamilyIndexCount
217 DE_NULL, // const deUint32* pQueueFamilyIndices
218 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout
219 };
220
221 colorImage = makeImage(vk, device, colorImageCreateInfo);
222 colorImageAllocation = bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any);
223 }
224
225 const VkFormat dsFormat = m_parameters.depthStencilAttachment ? PrimitivesGeneratedQueryTestInstance::selectDepthStencilFormat() : VK_FORMAT_UNDEFINED;
226
227 if (m_parameters.depthStencilAttachment && dsFormat == VK_FORMAT_UNDEFINED)
228 return tcu::TestStatus::fail("VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT feature must be supported for at least one of VK_FORMAT_D24_UNORM_S8_UINT and VK_FORMAT_D32_SFLOAT_S8_UINT.");
229
230 Move<VkImage> dsImage;
231 de::MovePtr<Allocation> dsImageAllocation;
232
233 if (m_parameters.depthStencilAttachment)
234 {
235 const VkImageCreateInfo dsImageCreateInfo =
236 {
237 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType
238 DE_NULL, // const void* pNext
239 0u, // VkImageCreateFlags flags
240 VK_IMAGE_TYPE_2D, // VkImageType imageType
241 dsFormat, // VkFormat format
242 makeExtent3D(IMAGE_WIDTH, IMAGE_HEIGHT, 1), // VkExtent3D extent
243 1u, // deUint32 mipLevels
244 1u, // deUint32 arrayLayers
245 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
246 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling
247 VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, // VkImageUsageFlags usage
248 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode
249 0u, // deUint32 queueFamilyIndexCount
250 DE_NULL, // const deUint32* pQueueFamilyIndices
251 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout
252 };
253
254 dsImage = makeImage(vk, device, dsImageCreateInfo);
255 dsImageAllocation = bindImage(vk, device, allocator, *dsImage, MemoryRequirement::Any);
256 }
257
258 const VkDeviceSize primitivesGenerated = 32;
259 const deUint32 baseMipLevel = 0;
260 const deUint32 levelCount = 1;
261 const deUint32 baseArrayLayer = 0;
262 const deUint32 layerCount = 1;
263
264 Move<VkImageView> colorImageView;
265 Move<VkImageView> dsImageView;
266 std::vector<VkImageView> imageViews;
267
268 if (m_parameters.colorAttachment())
269 {
270 const VkImageSubresourceRange colorSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, baseMipLevel, levelCount, baseArrayLayer, layerCount);
271 colorImageView = makeImageView(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange);
272 imageViews.push_back(*colorImageView);
273 }
274
275 if (m_parameters.depthStencilAttachment)
276 {
277 const VkImageSubresourceRange dsSubresourceRange = makeImageSubresourceRange((VK_IMAGE_ASPECT_DEPTH_BIT | vk::VK_IMAGE_ASPECT_STENCIL_BIT), baseMipLevel, levelCount, baseArrayLayer, layerCount);
278 dsImageView = makeImageView(vk, device, *dsImage, VK_IMAGE_VIEW_TYPE_2D, dsFormat, dsSubresourceRange);
279 imageViews.push_back(*dsImageView);
280 }
281
282 const Unique<VkRenderPass> renderPass (makeRenderPass(vk, device, colorFormat, dsFormat, VK_ATTACHMENT_LOAD_OP_DONT_CARE));
283 const Unique<VkFramebuffer> framebuffer (makeFramebuffer(vk, device, *renderPass, (deUint32)imageViews.size(), imageViews.data(), IMAGE_WIDTH, IMAGE_HEIGHT));
284 const Unique<VkPipeline> pipeline (PrimitivesGeneratedQueryTestInstance::makeGraphicsPipeline(vk, device, *renderPass));
285 Move<VkBuffer> vtxBuffer;
286 de::MovePtr<Allocation> vtxBufferAlloc;
287
288 {
289 const VkBufferUsageFlags usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
290 const std::vector<deUint32> queueFamilyIndices (1, queueFamilyIndex);
291 const VkDeviceSize vtxBufferSize = topologyData.at(m_parameters.primitiveTopology).getNumVertices(primitivesGenerated) * sizeof(tcu::Vec2);
292 const VkBufferCreateInfo createInfo = makeBufferCreateInfo(vtxBufferSize, usage, queueFamilyIndices);
293
294 vtxBuffer = createBuffer(vk, device, &createInfo);
295 vtxBufferAlloc = allocator.allocate(getBufferMemoryRequirements(vk, device, *vtxBuffer), MemoryRequirement::HostVisible);
296 }
297
298 const VkCommandPoolCreateFlags cmdPoolCreateFlags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
299 const VkCommandBufferLevel cmdBufferLevel = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
300 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, cmdPoolCreateFlags, queueFamilyIndex));
301 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer(vk, device, *cmdPool, cmdBufferLevel));
302
303 const bool pgq64 = (m_parameters.queryResultType == QUERY_RESULT_TYPE_64_BIT ||
304 m_parameters.queryResultType == QUERY_RESULT_TYPE_PGQ_64_XFB_32);
305 const bool xfb64 = (m_parameters.queryResultType == QUERY_RESULT_TYPE_64_BIT ||
306 m_parameters.queryResultType == QUERY_RESULT_TYPE_PGQ_32_XFB_64);
307 const size_t pgqResultSize = pgq64 ? sizeof(deUint64) : sizeof(deUint32);
308 const size_t xfbResultSize = xfb64 ? sizeof(deUint64) * 2 : sizeof(deUint32) * 2;
309 const VkQueryResultFlags pgqResultWidthBit = pgq64 ? VK_QUERY_RESULT_64_BIT : 0;
310 const VkQueryResultFlags xfbResultWidthBit = xfb64 ? VK_QUERY_RESULT_64_BIT : 0;
311 const VkQueryResultFlags pgqResultFlags = VK_QUERY_RESULT_WAIT_BIT | pgqResultWidthBit;
312 const VkQueryResultFlags xfbResultFlags = VK_QUERY_RESULT_WAIT_BIT | xfbResultWidthBit;
313
314 const deUint32 queryIndex = 0;
315 const deUint32 queryCount = 1;
316
317 std::vector<deUint8> pgqResults (pgqResultSize, 255u);
318 std::vector<deUint8> xfbResults (xfbResultSize, 255u);
319
320 const VkQueryPoolCreateInfo pgqCreateInfo =
321 {
322 VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, // VkStructureType sType
323 DE_NULL, // const void* pNext
324 0u, // VkQueryPoolCreateFlags flags
325 VK_QUERY_TYPE_PRIMITIVES_GENERATED_EXT, // VkQueryType queryType
326 queryCount, // deUint32 queryCount
327 0u, // VkQueryPipelineStatisticFlags pipelineStatistics
328 };
329
330 const Unique<VkQueryPool> pgqPool (createQueryPool(vk, device, &pgqCreateInfo));
331 Move<VkQueryPool> xfbPool;
332
333 if (m_parameters.transformFeedback)
334 {
335 const VkQueryPoolCreateInfo xfbCreateInfo =
336 {
337 VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, // VkStructureType sType
338 DE_NULL, // const void* pNext
339 0u, // VkQueryPoolCreateFlags flags
340 VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT, // VkQueryType queryType
341 queryCount, // deUint32 queryCount
342 0u, // VkQueryPipelineStatisticFlags pipelineStatistics
343 };
344
345 xfbPool = createQueryPool(vk, device, &xfbCreateInfo);
346 }
347
348 Move<VkBuffer> pgqResultsBuffer;
349 Move<VkBuffer> xfbResultsBuffer;
350 de::MovePtr<Allocation> pgqResultsBufferAlloc;
351 de::MovePtr<Allocation> xfbResultsBufferAlloc;
352
353 if (m_parameters.queryReadType == QUERY_READ_TYPE_COPY)
354 {
355 const VkBufferUsageFlags usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
356 const std::vector<deUint32> queueFamilyIndices (1, queueFamilyIndex);
357 const VkBufferCreateInfo pgqBufferCreateInfo = makeBufferCreateInfo(pgqResultSize, usage, queueFamilyIndices);
358
359 pgqResultsBuffer = createBuffer(vk, device, &pgqBufferCreateInfo);
360 pgqResultsBufferAlloc = allocator.allocate(getBufferMemoryRequirements(vk, device, *pgqResultsBuffer), MemoryRequirement::HostVisible);
361
362 VK_CHECK(vk.bindBufferMemory(device, *pgqResultsBuffer, pgqResultsBufferAlloc->getMemory(), pgqResultsBufferAlloc->getOffset()));
363
364 if (m_parameters.transformFeedback)
365 {
366 const VkBufferCreateInfo xfbBufferCreateInfo = makeBufferCreateInfo(xfbResultSize, usage, queueFamilyIndices);
367
368 xfbResultsBuffer = createBuffer(vk, device, &xfbBufferCreateInfo);
369 xfbResultsBufferAlloc = allocator.allocate(getBufferMemoryRequirements(vk, device, *xfbResultsBuffer), MemoryRequirement::HostVisible);
370
371 VK_CHECK(vk.bindBufferMemory(device, *xfbResultsBuffer, xfbResultsBufferAlloc->getMemory(), xfbResultsBufferAlloc->getOffset()));
372 }
373 }
374
375 const VkDeviceSize primitivesWritten = primitivesGenerated - 3;
376 const VkDeviceSize verticesWritten = topologyData.at(m_parameters.primitiveTopology).getNumVertices(primitivesWritten);
377 const VkDeviceSize primitiveSize = m_parameters.nonZeroStreams() ? 1 : topologyData.at(m_parameters.primitiveTopology).primitiveSize;
378 const VkDeviceSize bytesPerVertex = 4 * sizeof(float);
379 const VkDeviceSize xfbBufferSize = primitivesWritten * primitiveSize * bytesPerVertex;
380 Move<VkBuffer> xfbBuffer;
381 de::MovePtr<Allocation> xfbBufferAlloc;
382
383 if (m_parameters.transformFeedback)
384 {
385 const VkBufferUsageFlags usage = VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT;
386 const std::vector<deUint32> queueFamilyIndices (1, queueFamilyIndex);
387 const VkBufferCreateInfo createInfo = makeBufferCreateInfo(xfbBufferSize, usage, queueFamilyIndices);
388
389 xfbBuffer = createBuffer(vk, device, &createInfo);
390 xfbBufferAlloc = allocator.allocate(getBufferMemoryRequirements(vk, device, *xfbBuffer), MemoryRequirement::HostVisible);
391
392 VK_CHECK(vk.bindBufferMemory(device, *xfbBuffer, xfbBufferAlloc->getMemory(), xfbBufferAlloc->getOffset()));
393 }
394
395 fillVertexBuffer(static_cast<tcu::Vec2*>(vtxBufferAlloc.get()->getHostPtr()), primitivesGenerated);
396
397 VK_CHECK(vk.bindBufferMemory(device, *vtxBuffer, vtxBufferAlloc->getMemory(), vtxBufferAlloc->getOffset()));
398
399 beginCommandBuffer(vk, *cmdBuffer);
400 {
401 const VkDeviceSize vertexBufferOffset = static_cast<VkDeviceSize>(0);
402
403 // After query pool creation, each query must be reset before it is used.
404 if (m_parameters.queryResetType == QUERY_RESET_TYPE_QUEUE)
405 {
406 vk.cmdResetQueryPool(*cmdBuffer, *pgqPool, queryIndex, queryCount);
407
408 if (m_parameters.transformFeedback)
409 vk.cmdResetQueryPool(*cmdBuffer, *xfbPool, queryIndex, queryCount);
410 }
411
412 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
413
414 vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &vtxBuffer.get(), &vertexBufferOffset);
415
416 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(makeExtent2D(IMAGE_WIDTH, IMAGE_HEIGHT)));
417 {
418 const VkQueryControlFlags queryControlFlags = 0;
419
420 if (m_parameters.pgqDefault())
421 vk.cmdBeginQuery(*cmdBuffer, *pgqPool, queryIndex, queryControlFlags);
422 else
423 vk.cmdBeginQueryIndexedEXT(*cmdBuffer, *pgqPool, queryIndex, queryControlFlags, m_parameters.pgqStreamIndex());
424
425 const deUint32 firstCounterBuffer = 0;
426 const deUint32 counterBufferCount = 0;
427 const VkBuffer* counterBuffers = DE_NULL;
428 const VkDeviceSize* counterBufferOffsets = DE_NULL;
429
430 if (m_parameters.transformFeedback)
431 {
432 const deUint32 firstBinding = 0;
433 const deUint32 bindingCount = 1;
434 const VkDeviceSize offset = 0;
435
436 vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, firstBinding, bindingCount, &*xfbBuffer, &offset, &xfbBufferSize);
437
438 if (m_parameters.xfbDefault())
439 vk.cmdBeginQuery(*cmdBuffer, *xfbPool, queryIndex, queryControlFlags);
440 else
441 vk.cmdBeginQueryIndexedEXT(*cmdBuffer, *xfbPool, queryIndex, queryControlFlags, m_parameters.xfbStreamIndex());
442
443 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, firstCounterBuffer, counterBufferCount, counterBuffers, counterBufferOffsets);
444 }
445
446 if (m_parameters.dynamicColorWriteDisable())
447 {
448 const deUint32 attachmentCount = 1;
449 const VkBool32 colorWriteEnables = VK_FALSE;
450
451 vk.cmdSetColorWriteEnableEXT(*cmdBuffer, attachmentCount, &colorWriteEnables);
452 }
453
454 const deUint32 vertexCount = static_cast<deUint32>(topologyData.at(m_parameters.primitiveTopology).getNumVertices(primitivesGenerated));
455 const deUint32 instanceCount = 1u;
456 const deUint32 firstVertex = 0u;
457 const deUint32 firstInstance = 0u;
458
459 vk.cmdDraw(*cmdBuffer, vertexCount, instanceCount, firstVertex, firstInstance);
460
461 if (m_parameters.pgqDefault())
462 vk.cmdEndQuery(*cmdBuffer, *pgqPool, queryIndex);
463 else
464 vk.cmdEndQueryIndexedEXT(*cmdBuffer, *pgqPool, queryIndex, m_parameters.pgqStreamIndex());
465
466 if (m_parameters.transformFeedback)
467 {
468 if (m_parameters.xfbDefault())
469 vk.cmdEndQuery(*cmdBuffer, *xfbPool, queryIndex);
470 else
471 vk.cmdEndQueryIndexedEXT(*cmdBuffer, *xfbPool, queryIndex, m_parameters.xfbStreamIndex());
472
473 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, firstCounterBuffer, counterBufferCount, counterBuffers, counterBufferOffsets);
474 }
475 }
476 endRenderPass(vk, *cmdBuffer);
477
478 if (m_parameters.queryReadType == QUERY_READ_TYPE_COPY)
479 {
480 VkBufferMemoryBarrier bufferBarrier =
481 {
482 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType
483 DE_NULL, // const void* pNext
484 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask
485 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask
486 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex
487 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex
488 *pgqResultsBuffer, // VkBuffer buffer
489 0u, // VkDeviceSize offset
490 VK_WHOLE_SIZE // VkDeviceSize size
491 };
492
493 vk.cmdCopyQueryPoolResults(*cmdBuffer, *pgqPool, queryIndex, queryCount, *pgqResultsBuffer, 0u, pgqResultSize, pgqResultFlags);
494 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL);
495
496 if (m_parameters.transformFeedback)
497 {
498 bufferBarrier.buffer = *xfbResultsBuffer;
499 vk.cmdCopyQueryPoolResults(*cmdBuffer, *xfbPool, queryIndex, queryCount, *xfbResultsBuffer, 0u, xfbResultSize, xfbResultFlags);
500 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL);
501 }
502 }
503 }
504 endCommandBuffer(vk, *cmdBuffer);
505
506 // After query pool creation, each query must be reset before it is used.
507 if (m_parameters.queryResetType == QUERY_RESET_TYPE_HOST)
508 {
509 vk.resetQueryPool(device, *pgqPool, queryIndex, queryCount);
510
511 if (m_parameters.transformFeedback)
512 vk.resetQueryPool(device, *xfbPool, queryIndex, queryCount);
513 }
514
515 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
516
517 if (m_parameters.queryReadType == QUERY_READ_TYPE_COPY)
518 {
519 invalidateAlloc(vk, device, *pgqResultsBufferAlloc);
520 deMemcpy(pgqResults.data(), pgqResultsBufferAlloc->getHostPtr(), pgqResults.size());
521
522 if (m_parameters.transformFeedback)
523 {
524 invalidateAlloc(vk, device, *xfbResultsBufferAlloc);
525 deMemcpy(xfbResults.data(), xfbResultsBufferAlloc->getHostPtr(), xfbResults.size());
526 }
527 }
528 else
529 {
530 vk.getQueryPoolResults(device, *pgqPool, queryIndex, queryCount, pgqResults.size(), pgqResults.data(), pgqResults.size(), pgqResultFlags);
531
532 if (m_parameters.transformFeedback)
533 vk.getQueryPoolResults(device, *xfbPool, queryIndex, queryCount, xfbResults.size(), xfbResults.data(), xfbResults.size(), xfbResultFlags);
534 }
535
536 // Validate counters.
537 {
538 union QueryResults
539 {
540 deUint32 elements32[2];
541 deUint64 elements64[2];
542 };
543
544 const QueryResults* pgqCounters = reinterpret_cast<QueryResults*>(pgqResults.data());
545 const QueryResults* xfbCounters = reinterpret_cast<QueryResults*>(xfbResults.data());
546 const deUint64 pgqGenerated = pgq64 ? pgqCounters->elements64[0] : static_cast<deUint64>(pgqCounters->elements32[0]);
547 const deUint64 xfbWritten = xfb64 ? xfbCounters->elements64[0] : static_cast<deUint64>(xfbCounters->elements32[0]);
548 const deUint64 xfbGenerated = xfb64 ? xfbCounters->elements64[1] : static_cast<deUint64>(xfbCounters->elements32[1]);
549 tcu::TestLog& log = m_context.getTestContext().getLog();
550
551 log << tcu::TestLog::Message
552 << "primitivesGenerated: " << primitivesGenerated << "\n"
553 << "primitivesWritten: " << primitivesWritten << "\n"
554 << "verticesWritten: " << verticesWritten << "\n"
555 << "xfbBufferSize: " << xfbBufferSize << "\n"
556 << tcu::TestLog::EndMessage;
557
558 log << tcu::TestLog::Message << "PGQ: Generated " << pgqGenerated << tcu::TestLog::EndMessage;
559
560 if (m_parameters.transformFeedback)
561 log << tcu::TestLog::Message << "XFB: Written " << xfbWritten << ", generated " << xfbGenerated << tcu::TestLog::EndMessage;
562
563 if (pgqGenerated != primitivesGenerated)
564 {
565 const std::string message = std::string("pgqGenerated == ") + de::toString(pgqGenerated) + ", expected " + de::toString(primitivesGenerated);
566 return tcu::TestStatus::fail(message);
567 }
568
569 if (m_parameters.transformFeedback)
570 {
571 if (xfbGenerated != primitivesGenerated)
572 {
573 const std::string message = std::string("xfbGenerated == ") + de::toString(xfbGenerated) + ", expected " + de::toString(primitivesGenerated);
574 return tcu::TestStatus::fail(message);
575 }
576
577 if (xfbWritten != primitivesWritten)
578 {
579 const std::string message = std::string("xfbWritten == ") + de::toString(xfbWritten) + ", expected " + de::toString(primitivesWritten);
580 return tcu::TestStatus::fail(message);
581 }
582 }
583 }
584
585 return tcu::TestStatus::pass("Counters OK");
586 }
587
selectDepthStencilFormat(void)588 VkFormat PrimitivesGeneratedQueryTestInstance::selectDepthStencilFormat (void)
589 {
590 constexpr VkFormat formats[] =
591 {
592 VK_FORMAT_D32_SFLOAT_S8_UINT,
593 VK_FORMAT_D24_UNORM_S8_UINT
594 };
595
596 const InstanceInterface& vki = m_context.getInstanceInterface();
597 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
598
599 for (VkFormat format : formats)
600 {
601 const VkFormatFeatureFlags features = getPhysicalDeviceFormatProperties(vki, physicalDevice, format).optimalTilingFeatures;
602
603 if (features & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)
604 return format;
605 }
606
607 return VK_FORMAT_UNDEFINED;
608 }
609
makeGraphicsPipeline(const DeviceInterface & vk,const VkDevice device,const VkRenderPass renderPass)610 Move<VkPipeline> PrimitivesGeneratedQueryTestInstance::makeGraphicsPipeline (const DeviceInterface& vk, const VkDevice device, const VkRenderPass renderPass)
611 {
612 const VkDescriptorSetLayout descriptorSetLayout = DE_NULL;
613 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout(vk, device, descriptorSetLayout));
614 const std::vector<VkViewport> viewports (1, makeViewport(makeExtent2D(IMAGE_WIDTH, IMAGE_HEIGHT)));
615 const std::vector<VkRect2D> scissors (1, makeRect2D(makeExtent2D(IMAGE_WIDTH, IMAGE_HEIGHT)));
616 const deUint32 subpass = 0u;
617 const deUint32 patchControlPoints = topologyData.at(VK_PRIMITIVE_TOPOLOGY_PATCH_LIST).primitiveSize;
618 const Unique<VkShaderModule> vertModule (createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
619 Move<VkShaderModule> tescModule;
620 Move<VkShaderModule> teseModule;
621 Move<VkShaderModule> geomModule;
622 Move<VkShaderModule> fragModule;
623 VkVertexInputBindingDescription bindingDescription;
624 VkVertexInputAttributeDescription attributeDescription;
625
626 if (m_parameters.shaderStage == SHADER_STAGE_TESSELLATION_EVALUATION)
627 {
628 tescModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("tesc"), 0u);
629 teseModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("tese"), 0u);
630 }
631
632 if (m_parameters.shaderStage == SHADER_STAGE_GEOMETRY)
633 geomModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("geom"), 0u);
634
635 if (!m_parameters.rastDiscard())
636 fragModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u);
637
638 bindingDescription.binding = 0;
639 bindingDescription.stride = sizeof(tcu::Vec2);
640 bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
641
642 attributeDescription.binding = 0;
643 attributeDescription.location = 0;
644 attributeDescription.format = VK_FORMAT_R32G32_SFLOAT;
645 attributeDescription.offset = 0;
646
647 const VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo =
648 {
649 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType
650 DE_NULL, // const void* pNext
651 0u, // VkPipelineVertexInputStateCreateFlags flags
652 1u, // deUint32 vertexBindingDescriptionCount
653 &bindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions
654 1u, // deUint32 vertexAttributeDescriptionCount
655 &attributeDescription, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions
656 };
657
658 const VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo =
659 {
660 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType
661 DE_NULL, // const void* pNext
662 0, // VkPipelineRasterizationStateCreateFlags flags
663 VK_FALSE, // VkBool32 depthClampEnable
664 (m_parameters.rastDiscard() ? VK_TRUE : VK_FALSE), // VkBool32 rasterizerDiscardEnable
665 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode
666 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode
667 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace
668 VK_FALSE, // VkBool32 depthBiasEnable
669 0.0f, // float depthBiasConstantFactor
670 0.0f, // float depthBiasClamp
671 0.0f, // float depthBiasSlopeFactor
672 1.0f // float lineWidth
673 };
674
675 const VkStencilOpState stencilOpState =
676 {
677 VK_STENCIL_OP_KEEP, // VkStencilOp failOp
678 VK_STENCIL_OP_KEEP, // VkStencilOp passOp
679 VK_STENCIL_OP_KEEP, // VkStencilOp depthFailOp
680 VK_COMPARE_OP_ALWAYS, // VkCompareOp compareOp
681 0xFFu, // deUint32 compareMask
682 0xFFu, // deUint32 writeMask
683 0, // deUint32 reference
684 };
685
686 const VkPipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo =
687 {
688 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType
689 DE_NULL, // const void* pNext
690 0, // VkPipelineDepthStencilStateCreateFlags flags
691 VK_TRUE, // VkBool32 depthTestEnable
692 VK_TRUE, // VkBool32 depthWriteEnable
693 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp
694 VK_FALSE, // VkBool32 depthBoundsTestEnable
695 VK_FALSE, // VkBool32 stencilTestEnable
696 stencilOpState, // VkStencilOpState front
697 stencilOpState, // VkStencilOpState back
698 0.0f, // float minDepthBounds
699 1.0f, // float maxDepthBounds
700 };
701
702 const VkBool32 colorWriteEnables = VK_FALSE;
703
704 const VkPipelineColorWriteCreateInfoEXT colorWriteCreateInfo =
705 {
706 VK_STRUCTURE_TYPE_PIPELINE_COLOR_WRITE_CREATE_INFO_EXT, // VkStructureType sType;
707 DE_NULL, // const void* pNext;
708 1, // deUint32 attachmentCount;
709 &colorWriteEnables // const VkBool32* pColorWriteEnables;
710 };
711
712 const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
713 {
714 VK_FALSE, // VkBool32 blendEnable
715 VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcColorBlendFactor
716 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor
717 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp
718 VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcAlphaBlendFactor
719 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor
720 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp
721 VK_COLOR_COMPONENT_R_BIT // VkColorComponentFlags colorWriteMask
722 | VK_COLOR_COMPONENT_G_BIT
723 | VK_COLOR_COMPONENT_B_BIT
724 | VK_COLOR_COMPONENT_A_BIT
725 };
726
727 const VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfo =
728 {
729 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType
730 &colorWriteCreateInfo, // const void* pNext
731 0, // VkPipelineColorBlendStateCreateFlags flags
732 VK_FALSE, // VkBool32 logicOpEnable
733 VK_LOGIC_OP_NO_OP, // VkLogicOp logicOp
734 1, // deUint32 attachmentCount
735 &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments
736 { 0.0f, 0.0f, 0.0f, 0.0f } // float blendConstants[4]
737 };
738
739 const VkDynamicState dynamicStates = VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT;
740
741 const VkPipelineDynamicStateCreateInfo pipelineDynamicStateCreateInfo =
742 {
743 VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType
744 DE_NULL, // const void* pNext
745 0u, // VkPipelineDynamicStateCreateFlags flags
746 1u, // deUint32 dynamicStateCount
747 &dynamicStates // const VkDynamicState* pDynamicStates
748 };
749
750 const VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfo =
751 {
752 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
753 nullptr, // const void* pNext;
754 0u, // VkPipelineMultisampleStateCreateFlags flags;
755 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
756 VK_FALSE, // VkBool32 sampleShadingEnable;
757 1.0f, // float minSampleShading;
758 nullptr, // const VkSampleMask* pSampleMask;
759 VK_FALSE, // VkBool32 alphaToCoverageEnable;
760 VK_FALSE, // VkBool32 alphaToOneEnable;
761 };
762
763 return vk::makeGraphicsPipeline(vk,
764 device,
765 *pipelineLayout,
766 *vertModule,
767 *tescModule,
768 *teseModule,
769 *geomModule,
770 *fragModule,
771 renderPass,
772 viewports,
773 scissors,
774 m_parameters.primitiveTopology,
775 subpass,
776 patchControlPoints,
777 &vertexInputStateCreateInfo,
778 &rasterizationStateCreateInfo,
779 &multisampleStateCreateInfo,
780 m_parameters.depthStencilAttachment ? &depthStencilStateCreateInfo : DE_NULL,
781 m_parameters.staticColorWriteDisable() ? &colorBlendStateCreateInfo : DE_NULL,
782 m_parameters.dynamicColorWriteDisable() ? &pipelineDynamicStateCreateInfo : DE_NULL);
783 }
784
fillVertexBuffer(tcu::Vec2 * vertices,const deUint64 primitivesGenerated)785 void PrimitivesGeneratedQueryTestInstance::fillVertexBuffer(tcu::Vec2* vertices, const deUint64 primitivesGenerated)
786 {
787 const float step = 1.0f / static_cast<float>(primitivesGenerated);
788
789 switch (m_parameters.primitiveTopology)
790 {
791 case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
792 {
793 for (deUint32 prim = 0; prim < primitivesGenerated; ++prim)
794 {
795 vertices[prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 0.0f);
796 }
797 break;
798 }
799 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
800 {
801 for (deUint32 prim = 0; prim < primitivesGenerated; ++prim)
802 {
803 vertices[2* prim + 0] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 1.0f);
804 vertices[2* prim + 1] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f);
805 }
806 break;
807 }
808 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
809 {
810 vertices[0] = tcu::Vec2(-1.0f,-1.0f);
811 vertices[1] = tcu::Vec2(-1.0f, 1.0f);
812
813 for (deUint32 prim = 1; prim < primitivesGenerated; ++prim)
814 {
815 if (prim % 2 == 0)
816 {
817 vertices[1 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 1.0f);
818 }
819 else
820 {
821 vertices[1 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f);
822 }
823 }
824 break;
825 }
826 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
827 {
828 vertices[0] = tcu::Vec2(-1.0f, 1.0f);
829 vertices[1] = tcu::Vec2(-1.0f, -1.0f);
830 vertices[2] = tcu::Vec2(-1.0f + 2.0f * step, 1.0f);
831
832 for (deUint32 prim = 1; prim < primitivesGenerated; ++prim)
833 {
834 if (prim % 2 == 0)
835 {
836 vertices[2 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 1.0f);
837 }
838 else
839 {
840 vertices[2 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f);
841 }
842 }
843 break;
844 }
845 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
846 {
847 vertices[0] = tcu::Vec2(0.0f, -1.0f);
848
849 for (deUint32 prim = 0; prim < primitivesGenerated+1; ++prim)
850 {
851 vertices[1 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f + 2.0f * (float)prim * step);
852 }
853 break;
854 }
855 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
856 {
857 for (deUint32 prim = 0; prim < primitivesGenerated; ++prim)
858 {
859 vertices[4 * prim + 0] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 1.0f);
860 vertices[4 * prim + 1] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 0.5f);
861 vertices[4 * prim + 2] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -0.5f);
862 vertices[4 * prim + 3] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f);
863 }
864 break;
865 }
866 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
867 {
868 vertices[0] = tcu::Vec2(-1.0f, 0.0f);
869 vertices[1] = tcu::Vec2(-1.0f, -1.0f);
870 vertices[2] = tcu::Vec2(-1.0f, 1.0f);
871
872 for (deUint32 prim = 1; prim < primitivesGenerated; ++prim)
873 {
874 if (prim % 2 == 0)
875 {
876 vertices[2 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 1.0f);
877 }
878 else
879 {
880 vertices[2 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f);
881 }
882 }
883
884 vertices[2 + primitivesGenerated] = tcu::Vec2(1.0f, 0.0f);
885
886 break;
887 }
888 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
889 case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
890 {
891 for (deUint32 prim = 0; prim < primitivesGenerated; ++prim)
892 {
893 if (prim % 2 == 0)
894 {
895 vertices[3 * prim + 0] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, 1.0f);
896 vertices[3 * prim + 1] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, -1.0f);
897 vertices[3 * prim + 2] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, -1.0f);
898 }
899 else
900 {
901 vertices[3 * prim + 0] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, -1.0f);
902 vertices[3 * prim + 1] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, 1.0f);
903 vertices[3 * prim + 2] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, 1.0f);
904 }
905 }
906 break;
907 }
908 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
909 {
910 for (deUint32 prim = 0; prim < primitivesGenerated; ++prim)
911 {
912 if (prim % 2 == 0)
913 {
914 vertices[6 * prim + 0] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, 1.0f);
915 vertices[6 * prim + 1] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, 1.0f);
916 vertices[6 * prim + 2] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, -1.0f);
917 vertices[6 * prim + 3] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, -1.0f);
918 vertices[6 * prim + 4] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, -1.0f);
919 vertices[6 * prim + 5] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, -1.0f);
920 }
921 else
922 {
923 vertices[6 * prim + 0] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, -1.0f);
924 vertices[6 * prim + 1] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, -1.0f);
925 vertices[6 * prim + 2] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, 1.0f);
926 vertices[6 * prim + 3] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, 1.0f);
927 vertices[6 * prim + 4] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, 1.0f);
928 vertices[6 * prim + 5] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, 1.0f);
929 }
930 }
931 break;
932 }
933 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
934 {
935 vertices[0] = tcu::Vec2(-1.0f, 1.0f);
936 vertices[1] = tcu::Vec2(-1.0f, 1.0f);
937 vertices[2] = tcu::Vec2(-1.0f, -1.0f);
938 vertices[3] = tcu::Vec2(-1.0f, -1.0f);
939 vertices[4] = tcu::Vec2(-1.0f + 2.0f * step, 1.0f);
940 vertices[5] = tcu::Vec2(-1.0f + 2.0f * step, 1.0f);
941
942 for (deUint32 prim = 1; prim < primitivesGenerated; ++prim)
943 {
944 if (prim % 2 == 0)
945 {
946 vertices[5 + prim + 0] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 1.0f);
947 vertices[5 + prim + 1] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 1.0f);
948 }
949 else
950 {
951 vertices[5 + prim + 0] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f);
952 vertices[5 + prim + 1] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f);
953 }
954 }
955 break;
956 }
957 default:
958 TCU_THROW(InternalError, "Unrecognized primitive topology");
959 }
960 }
961
962 class PrimitivesGeneratedQueryTestCase : public vkt::TestCase
963 {
964 public:
PrimitivesGeneratedQueryTestCase(tcu::TestContext & context,const char * name,const char * description,const TestParameters & parameters)965 PrimitivesGeneratedQueryTestCase (tcu::TestContext &context, const char *name, const char *description, const TestParameters& parameters)
966 : TestCase (context, name, description)
967 , m_parameters (parameters)
968 {
969 }
970
971 private:
972 void checkSupport (vkt::Context& context) const;
973 void initPrograms (vk::SourceCollections& programCollection) const;
createInstance(vkt::Context & context) const974 vkt::TestInstance* createInstance (vkt::Context& context) const { return new PrimitivesGeneratedQueryTestInstance(context, m_parameters); }
975
976 const TestParameters m_parameters;
977 };
978
checkSupport(vkt::Context & context) const979 void PrimitivesGeneratedQueryTestCase::checkSupport (vkt::Context& context) const
980 {
981 context.requireDeviceFunctionality("VK_EXT_primitives_generated_query");
982 context.requireDeviceFunctionality("VK_EXT_transform_feedback");
983
984 const VkPhysicalDevicePrimitivesGeneratedQueryFeaturesEXT& pgqFeatures = context.getPrimitivesGeneratedQueryFeaturesEXT();
985 const VkPhysicalDeviceTransformFeedbackFeaturesEXT& xfbFeatures = context.getTransformFeedbackFeaturesEXT();
986 const VkPhysicalDeviceTransformFeedbackPropertiesEXT& xfbProperties = context.getTransformFeedbackPropertiesEXT();
987
988 if (pgqFeatures.primitivesGeneratedQuery != VK_TRUE)
989 TCU_THROW(NotSupportedError, "VK_QUERY_TYPE_PRIMITIVES_GENERATED_EXT not supported");
990
991 if (m_parameters.rastDiscard() && (pgqFeatures.primitivesGeneratedQueryWithRasterizerDiscard != VK_TRUE))
992 TCU_THROW(NotSupportedError, "primitivesGeneratedQueryWithRasterizerDiscard not supported");
993
994 if (m_parameters.queryResetType == QUERY_RESET_TYPE_HOST)
995 context.requireDeviceFunctionality("VK_EXT_host_query_reset");
996
997 if (m_parameters.shaderStage == SHADER_STAGE_GEOMETRY || topologyData.at(m_parameters.primitiveTopology).hasAdjacency)
998 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
999
1000 if (m_parameters.shaderStage == SHADER_STAGE_TESSELLATION_EVALUATION)
1001 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
1002
1003 if (m_parameters.nonZeroStreams())
1004 {
1005 const deUint32 requiredStreams = de::max(m_parameters.pgqStreamIndex(), m_parameters.xfbStreamIndex());
1006
1007 if (m_parameters.pgqStreamIndex() > 0 && pgqFeatures.primitivesGeneratedQueryWithNonZeroStreams != VK_TRUE)
1008 TCU_THROW(NotSupportedError, "primitivesGeneratedQueryWithNonZeroStreams not supported");
1009
1010 if (xfbProperties.maxTransformFeedbackStreams <= requiredStreams)
1011 TCU_THROW(NotSupportedError, "Required amount of XFB streams not supported");
1012 }
1013
1014 if (m_parameters.transformFeedback)
1015 {
1016 if (xfbFeatures.transformFeedback != VK_TRUE)
1017 TCU_THROW(NotSupportedError, "transformFeedback not supported");
1018
1019 if (xfbProperties.transformFeedbackQueries != VK_TRUE)
1020 TCU_THROW(NotSupportedError, "transformFeedbackQueries not supported");
1021 }
1022
1023 if (m_parameters.colorWriteDisable())
1024 {
1025 context.requireDeviceFunctionality("VK_EXT_color_write_enable");
1026
1027 if (context.getColorWriteEnableFeaturesEXT().colorWriteEnable != VK_TRUE)
1028 TCU_THROW(NotSupportedError, "colorWriteEnable not supported");
1029 }
1030 }
1031
initPrograms(vk::SourceCollections & programCollection) const1032 void PrimitivesGeneratedQueryTestCase::initPrograms (vk::SourceCollections& programCollection) const
1033 {
1034 // Vertex shader.
1035 {
1036 const bool vertXfb = (m_parameters.transformFeedback && m_parameters.shaderStage == SHADER_STAGE_VERTEX);
1037 std::ostringstream src;
1038
1039 src << "#version 450\n";
1040 src << "layout(location=0) in vec2 inPosition;\n";
1041
1042 if (vertXfb)
1043 src << "layout(xfb_buffer = 0, xfb_offset = 0, xfb_stride = 16, location = 0) out vec4 out0;\n";
1044
1045 src << "void main (void)\n"
1046 "{\n";
1047
1048 if (m_parameters.primitiveTopology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST && m_parameters.shaderStage == SHADER_STAGE_VERTEX)
1049 src << " gl_PointSize = 1.0;\n";
1050
1051 src << " gl_Position = vec4(inPosition, 0, 1);\n";
1052
1053 if (vertXfb)
1054 src << " out0 = vec4(42);\n";
1055
1056 src << "}\n";
1057
1058 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
1059 }
1060
1061 // Tessellation shaders.
1062 if (m_parameters.shaderStage == SHADER_STAGE_TESSELLATION_EVALUATION)
1063 {
1064 std::stringstream tescSrc;
1065 std::stringstream teseSrc;
1066
1067 tescSrc << "#version 450\n"
1068 "#extension GL_EXT_tessellation_shader : require\n"
1069 "layout(vertices = "<< topologyData.at(VK_PRIMITIVE_TOPOLOGY_PATCH_LIST).primitiveSize << ") out;\n"
1070 "void main (void)\n"
1071 "{\n"
1072 " gl_TessLevelInner[0] = 1.0;\n"
1073 " gl_TessLevelInner[1] = 1.0;\n"
1074 " gl_TessLevelOuter[0] = 1.0;\n"
1075 " gl_TessLevelOuter[1] = 1.0;\n"
1076 " gl_TessLevelOuter[2] = 1.0;\n"
1077 " gl_TessLevelOuter[3] = 1.0;\n"
1078 " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
1079 "}\n";
1080
1081 teseSrc << "#version 450\n"
1082 "#extension GL_EXT_tessellation_shader : require\n"
1083 "layout(triangles) in;\n";
1084
1085 if (m_parameters.transformFeedback)
1086 teseSrc << "layout(xfb_buffer = 0, xfb_offset = 0, location = 0) out vec4 out0;\n";
1087
1088 teseSrc << "void main (void)\n"
1089 "{\n";
1090
1091 if (m_parameters.transformFeedback)
1092 teseSrc << " out0 = vec4(42);\n";
1093
1094 teseSrc << " vec4 p0 = gl_TessCoord.x * gl_in[0].gl_Position;\n"
1095 " vec4 p1 = gl_TessCoord.y * gl_in[1].gl_Position;\n"
1096 " vec4 p2 = gl_TessCoord.z * gl_in[2].gl_Position;\n"
1097 " gl_Position = p0 + p1 + p2;\n"
1098 "}\n";
1099
1100 programCollection.glslSources.add("tesc") << glu::TessellationControlSource(tescSrc.str());
1101 programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(teseSrc.str());
1102 }
1103
1104 // Geometry shader.
1105 if (m_parameters.shaderStage == SHADER_STAGE_GEOMETRY)
1106 {
1107 const bool outputPoints = m_parameters.nonZeroStreams() || m_parameters.primitiveTopology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
1108 const char* const inputTopology = topologyData.at(m_parameters.primitiveTopology).inputString;
1109 const char* const outputTopology = outputPoints ? "points" : topologyData.at(m_parameters.primitiveTopology).outputString;
1110 const VkDeviceSize outputPrimSize = outputPoints ? 1 : topologyData.at(m_parameters.primitiveTopology).primitiveSize;
1111 const VkDeviceSize maxVertices = m_parameters.multipleStreams() ? outputPrimSize * 2 : outputPrimSize;
1112 const std::string pgqEmitCommand = m_parameters.nonZeroStreams() ? std::string("EmitStreamVertex(") + de::toString(m_parameters.pgqStreamIndex()) + ")" : "EmitVertex()";
1113 const std::string xfbEmitCommand = m_parameters.nonZeroStreams() ? std::string("EmitStreamVertex(") + de::toString(m_parameters.xfbStreamIndex()) + ")" : "EmitVertex()";
1114 const std::string pgqEndCommand = m_parameters.nonZeroStreams() ? std::string("EndStreamPrimitive(") + de::toString(m_parameters.pgqStreamIndex()) + ")" : "EndPrimitive()";
1115 const std::string xfbEndCommand = m_parameters.nonZeroStreams() ? std::string("EndStreamPrimitive(") + de::toString(m_parameters.xfbStreamIndex()) + ")" : "EndPrimitive()";
1116 std::ostringstream src;
1117
1118 src << "#version 450\n"
1119 "layout(" << inputTopology << ") in;\n"
1120 "layout(" << outputTopology << ", max_vertices = " << maxVertices << ") out;\n";
1121
1122 if (m_parameters.transformFeedback)
1123 src << "layout(xfb_buffer = 0, xfb_offset = 0, xfb_stride = 16, location = 0, stream = " << m_parameters.xfbStreamIndex() << ") out vec4 xfb;\n";
1124
1125 src << "void main (void)\n"
1126 "{\n";
1127
1128 if (outputPoints)
1129 src << " gl_PointSize = 1.0;\n";
1130
1131 if (m_parameters.transformFeedback)
1132 src << " xfb = vec4(42);\n";
1133
1134 for (VkDeviceSize i = 0; i < outputPrimSize; i++)
1135 src << " " << pgqEmitCommand << ";\n";
1136
1137 src << " " << pgqEndCommand << ";\n";
1138
1139 if (m_parameters.transformFeedback && m_parameters.multipleStreams())
1140 {
1141 for (VkDeviceSize i = 0; i < outputPrimSize; i++)
1142 src << " " << xfbEmitCommand << ";\n";
1143
1144 src << " " << xfbEndCommand << ";\n";
1145 }
1146
1147 src << "}\n";
1148
1149 programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
1150 }
1151
1152 // Fragment shader.
1153 if (!m_parameters.rastDiscard())
1154 {
1155 std::ostringstream src;
1156
1157 if (m_parameters.rastCase == RAST_CASE_EMPTY_FRAG)
1158 {
1159 src << "#version 450\n"
1160 "void main (void) {}\n";
1161 }
1162 else
1163 {
1164 src << "#version 450\n"
1165 "layout(location = 0) out vec4 out0;\n"
1166 "void main (void)\n"
1167 "{\n"
1168 " out0 = vec4(0.0, 1.0, 0.0, 1.0);\n"
1169 "}\n";
1170 }
1171
1172 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
1173 }
1174 }
1175
testGenerator(tcu::TestCaseGroup * pgqGroup)1176 void testGenerator (tcu::TestCaseGroup* pgqGroup)
1177 {
1178 constexpr struct ReadType
1179 {
1180 QueryReadType type;
1181 const char* name;
1182 const char* desc;
1183 } readTypes[] =
1184 {
1185 { QUERY_READ_TYPE_GET, "get", "Tests for vkGetQueryPoolResults" },
1186 { QUERY_READ_TYPE_COPY, "copy", "Tests for vkCmdCopyQueryPoolResults" },
1187 };
1188 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(readTypes) == QUERY_READ_TYPE_LAST);
1189
1190 constexpr struct ResetType
1191 {
1192 QueryResetType type;
1193 const char* name;
1194 const char* desc;
1195 } resetTypes[] =
1196 {
1197 { QUERY_RESET_TYPE_QUEUE, "queue_reset", "Tests for vkCmdResetQueryPool" },
1198 { QUERY_RESET_TYPE_HOST, "host_reset", "Tests for vkResetQueryPool" },
1199 };
1200 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(resetTypes) == QUERY_RESET_TYPE_LAST);
1201
1202 constexpr struct ResultTypes
1203 {
1204 QueryResultType type;
1205 const char* name;
1206 const char* desc;
1207 } resultTypes[] =
1208 {
1209 { QUERY_RESULT_TYPE_32_BIT, "32bit", "Tests for default query result size" },
1210 { QUERY_RESULT_TYPE_64_BIT, "64bit", "Tests for VK_QUERY_RESULT_64_BIT" },
1211 { QUERY_RESULT_TYPE_PGQ_32_XFB_64, "pgq_32bit_xfb_64bit", "Tests for PGQ without and XFBQ with VK_QUERY_RESULT_64_BIT" },
1212 { QUERY_RESULT_TYPE_PGQ_64_XFB_32, "pgq_64bit_xfb_32bit", "Tests for PGQ with and XFBQ without VK_QUERY_RESULT_64_BIT" },
1213 };
1214 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(resultTypes) == QUERY_RESULT_TYPE_LAST);
1215
1216 constexpr struct Shader
1217 {
1218 ShaderStage stage;
1219 const char* name;
1220 const char* desc;
1221 } shaderStages[] =
1222 {
1223 { SHADER_STAGE_VERTEX, "vert", "Vertex shader tests" },
1224 { SHADER_STAGE_TESSELLATION_EVALUATION, "tese", "Tessellation evaluation shader tests" },
1225 { SHADER_STAGE_GEOMETRY, "geom", "Geometry shader tests" },
1226 };
1227 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(shaderStages) == SHADER_STAGE_LAST);
1228
1229 constexpr struct TransformFeedbackState
1230 {
1231 deBool enable;
1232 const char* name;
1233 const char* desc;
1234 } transformFeedbackStates[] =
1235 {
1236 { DE_FALSE, "no_xfb", "Tests without transform feedback" },
1237 { DE_TRUE, "xfb", "Tests for comparing PGQ results against transform feedback query results" },
1238 };
1239
1240 constexpr struct RastCase
1241 {
1242 RasterizationCase type;
1243 deBool dsAttachment;
1244 const char* name;
1245 const char* desc;
1246 } rastCases[] =
1247 {
1248 { RAST_CASE_DISCARD, DE_FALSE, "no_rast", "Tests with rasterizer discard" },
1249 { RAST_CASE_DEFAULT, DE_FALSE, "rast", "Tests without rasterizer discard" },
1250 { RAST_CASE_EMPTY_FRAG, DE_FALSE, "empty_frag", "Tests with an empty fragment shader" },
1251 { RAST_CASE_NO_ATTACHMENT, DE_FALSE, "no_attachment", "Tests with an attachmentless render pass" },
1252 { RAST_CASE_COLOR_WRITE_DISABLE_STATIC, DE_FALSE, "color_write_disable_static", "Tests disabling color output using VkPipelineColorWriteCreateInfoEXT" },
1253 { RAST_CASE_COLOR_WRITE_DISABLE_STATIC, DE_TRUE, "color_write_disable_static_ds", "Tests disabling color output using VkPipelineColorWriteCreateInfoEXT with a depth stencil attachment" },
1254 { RAST_CASE_COLOR_WRITE_DISABLE_DYNAMIC, DE_FALSE, "color_write_disable_dynamic", "Tests disabling color output using vkCmdSetColorWriteEnableEXT" },
1255 { RAST_CASE_COLOR_WRITE_DISABLE_DYNAMIC, DE_TRUE, "color_write_disable_dynamic_ds", "Tests disabling color output using vkCmdSetColorWriteEnableEXT with a depth stencil attachment" },
1256 };
1257
1258 constexpr struct Topology
1259 {
1260 VkPrimitiveTopology type;
1261 const char* name;
1262 const char* desc;
1263 } topologies[] =
1264 {
1265 { VK_PRIMITIVE_TOPOLOGY_POINT_LIST, "point_list", "Tests for separate point primitives" },
1266 { VK_PRIMITIVE_TOPOLOGY_LINE_LIST, "line_list", "Tests for separate line primitives" },
1267 { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, "line_strip", "Tests for connected line primitives with consecutive lines sharing a vertex" },
1268 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, "triangle_list", "Tests for separate triangle primitives" },
1269 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, "triangle_strip", "Tests for connected triangle primitives with consecutive triangles sharing an edge" },
1270 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, "triangle_fan", "Tests for connected triangle primitives with all triangles sharing a common vertex" },
1271 { VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY, "line_list_with_adjacency", "Tests for separate line primitives with adjacency" },
1272 { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY, "line_strip_with_adjacency", "Tests for connected line primitives with adjacency, with consecutive primitives sharing three vertices" },
1273 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY, "triangle_list_with_adjacency", "Tests for separate triangle primitives with adjacency" },
1274 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY, "triangle_strip_with_adjacency", "Tests for connected triangle primitives with adjacency, with consecutive triangles sharing an edge" },
1275 { VK_PRIMITIVE_TOPOLOGY_PATCH_LIST, "patch_list", "Tests for separate patch primitives" },
1276 };
1277
1278 // Tests for vkCmdBeginQueryIndexedEXT and vkCmdEndQueryIndexedEXT.
1279 constexpr struct StreamIndex
1280 {
1281 VertexStream index;
1282 const char* name;
1283 } streamIndices[] =
1284 {
1285 { VERTEX_STREAM_DEFAULT, "default" },
1286 { VERTEX_STREAM_0, "0" },
1287 { VERTEX_STREAM_1, "1" },
1288 };
1289
1290 constexpr struct CmdBufCase
1291 {
1292 CommandBufferCase type;
1293 const char* name;
1294 const char* desc;
1295 } cmdBufCases[] =
1296 {
1297 { CMD_BUF_CASE_SINGLE_DRAW, "single_draw", "Test single draw call" },
1298 };
1299 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(cmdBufCases) == CMD_BUF_CASE_LAST);
1300
1301 tcu::TestContext& testCtx = pgqGroup->getTestContext();
1302
1303 for (const ReadType& read : readTypes)
1304 {
1305 de::MovePtr<tcu::TestCaseGroup> readGroup(new tcu::TestCaseGroup(testCtx, read.name, read.desc));
1306
1307 for (const ResetType& reset : resetTypes)
1308 {
1309 de::MovePtr<tcu::TestCaseGroup> resetGroup(new tcu::TestCaseGroup(testCtx, reset.name, reset.desc));
1310
1311 for (const ResultTypes& result : resultTypes)
1312 {
1313 de::MovePtr<tcu::TestCaseGroup> resultGroup(new tcu::TestCaseGroup(testCtx, result.name, result.desc));
1314
1315 for (const Shader& shader : shaderStages)
1316 {
1317 de::MovePtr<tcu::TestCaseGroup> shaderGroup(new tcu::TestCaseGroup(testCtx, shader.name, shader.desc));
1318
1319 for (const TransformFeedbackState& xfbState : transformFeedbackStates)
1320 {
1321 de::MovePtr<tcu::TestCaseGroup> xfbGroup(new tcu::TestCaseGroup(testCtx, xfbState.name, xfbState.desc));
1322
1323 // Only test multiple result types with XFB enabled.
1324 if ((result.type == QUERY_RESULT_TYPE_PGQ_32_XFB_64 || result.type == QUERY_RESULT_TYPE_PGQ_64_XFB_32) && !xfbState.enable)
1325 continue;
1326
1327 for (const RastCase& rastCase : rastCases)
1328 {
1329 de::MovePtr<tcu::TestCaseGroup> rastGroup(new tcu::TestCaseGroup(testCtx, rastCase.name, rastCase.desc));
1330
1331 // Skip uninteresting cases
1332 if ((rastCase.type > RAST_CASE_DISCARD)
1333 && ((read.type != QUERY_READ_TYPE_GET)
1334 || (reset.type != QUERY_RESET_TYPE_QUEUE)
1335 || (result.type != QUERY_RESULT_TYPE_32_BIT)))
1336 {
1337 continue;
1338 }
1339
1340 for (const Topology& topology : topologies)
1341 {
1342 de::MovePtr<tcu::TestCaseGroup> topologyGroup(new tcu::TestCaseGroup(testCtx, topology.name, topology.desc));
1343
1344 // Only test patch lists with tessellation shaders.
1345 if ((topology.type == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST && shader.stage != SHADER_STAGE_TESSELLATION_EVALUATION) ||
1346 ((topology.type != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST && shader.stage == SHADER_STAGE_TESSELLATION_EVALUATION)))
1347 {
1348 continue;
1349 }
1350
1351 // Only test adjacency topologies with geometry shaders.
1352 if (shader.stage != SHADER_STAGE_GEOMETRY && topologyData.at(topology.type).hasAdjacency)
1353 continue;
1354
1355 for (const StreamIndex& pgqStream : streamIndices)
1356 {
1357 for (const StreamIndex& xfbStream : streamIndices)
1358 {
1359 const std::string streamGroupName = std::string("pgq_") + pgqStream.name + (xfbState.enable ? std::string("_xfb_") + xfbStream.name : "");
1360 const bool pgqDefault = (pgqStream.index == VERTEX_STREAM_DEFAULT);
1361 const bool xfbDefault = (xfbStream.index == VERTEX_STREAM_DEFAULT);
1362 const std::string pgqDescStr = std::string("PGQ on ") + (pgqDefault ? "default " : "") + std::string("vertex stream ") + (pgqDefault ? "" : pgqStream.name);
1363 const std::string xfbDescStr = std::string("XFB on ") + (xfbDefault ? "default " : "") + std::string("vertex stream ") + (xfbDefault ? "" : xfbStream.name);
1364 const std::string streamGroupDesc = std::string("Tests for ") + pgqDescStr + (xfbState.enable ? (std::string(" and ") + xfbDescStr) : "");
1365 de::MovePtr<tcu::TestCaseGroup> streamGroup(new tcu::TestCaseGroup(testCtx, streamGroupName.c_str(), streamGroupDesc.c_str()));
1366
1367 // Only test nondefault vertex streams with geometry shaders.
1368 if ((pgqStream.index != VERTEX_STREAM_DEFAULT || xfbStream.index != VERTEX_STREAM_DEFAULT) && shader.stage != SHADER_STAGE_GEOMETRY)
1369 continue;
1370
1371 // Skip nondefault vertex streams for XFB when not enabled.
1372 if (!xfbState.enable && xfbStream.index != VERTEX_STREAM_DEFAULT)
1373 continue;
1374
1375 for (const CmdBufCase& cmdBufCase : cmdBufCases)
1376 {
1377 const TestParameters parameters =
1378 {
1379 read.type, // QueryReadType queryReadType
1380 reset.type, // QueryResetType queryResetType
1381 result.type, // QueryResultType queryResultType
1382 shader.stage, // ShaderStage shaderStage
1383 xfbState.enable, // deBool transformFeedback
1384 rastCase.type, // RasterizationCase rastCase
1385 rastCase.dsAttachment, // deBool depthStencilAttachment
1386 topology.type, // VkPrimitiveTopology primitiveTopology
1387 pgqStream.index, // VertexStreamIndex pgqStreamIndex
1388 xfbStream.index, // VertexStreamIndex xfbStreamIndex
1389 cmdBufCase.type, // CommandBufferCase cmdBufCase
1390 };
1391
1392 streamGroup->addChild(new PrimitivesGeneratedQueryTestCase(testCtx, cmdBufCase.name, cmdBufCase.desc, parameters));
1393 }
1394
1395 topologyGroup->addChild(streamGroup.release());
1396 }
1397 }
1398
1399 rastGroup->addChild(topologyGroup.release());
1400 }
1401
1402 xfbGroup->addChild(rastGroup.release());
1403 }
1404
1405 shaderGroup->addChild(xfbGroup.release());
1406 }
1407
1408 resultGroup->addChild(shaderGroup.release());
1409 }
1410
1411 resetGroup->addChild(resultGroup.release());
1412 }
1413
1414 readGroup->addChild(resetGroup.release());
1415 }
1416
1417 pgqGroup->addChild(readGroup.release());
1418 }
1419 }
1420
1421 } // anonymous
1422
createPrimitivesGeneratedQueryTests(tcu::TestContext & testCtx)1423 tcu::TestCaseGroup* createPrimitivesGeneratedQueryTests (tcu::TestContext& testCtx)
1424 {
1425 return createTestGroup(testCtx, "primitives_generated_query", "Primitives Generated Query Tests", testGenerator);
1426 }
1427
1428 } // TransformFeedback
1429 } // vkt
1430