1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2018 The Khronos Group Inc.
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
21 * \brief Vulkan Transform Feedback Simple Tests
22 *//*--------------------------------------------------------------------*/
24 #include "vktTransformFeedbackSimpleTests.hpp"
25 #include "vktTestGroupUtil.hpp"
26 #include "vktTestCase.hpp"
28 #include "vkBuilderUtil.hpp"
29 #include "vkCmdUtil.hpp"
30 #include "vkImageUtil.hpp"
31 #include "vkObjUtil.hpp"
32 #include "vkQueryUtil.hpp"
33 #include "vkRefUtil.hpp"
34 #include "vkTypeUtil.hpp"
36 #include "deUniquePtr.hpp"
37 #include "deRandom.hpp"
39 #include "tcuTextureUtil.hpp"
40 #include "tcuVectorUtil.hpp"
41 #include "tcuImageCompare.hpp"
42 #include "tcuRGBA.hpp"
43 #include "tcuTestLog.hpp"
52 namespace TransformFeedback
61 #define VALIDATE_MINIMUM(A,B) if ((A) < (B)) TCU_FAIL(#A "==" + de::toString(A) + " which is less than required by specification (" + de::toString(B) + ")")
62 #define VALIDATE_BOOL(A) if (! ( (A) == VK_TRUE || (A) == VK_FALSE) ) TCU_FAIL(#A " expected to be VK_TRUE or VK_FALSE. Received " + de::toString((deUint64)(A)))
69 TEST_TYPE_XFB_POINTSIZE,
70 TEST_TYPE_XFB_CLIPDISTANCE,
71 TEST_TYPE_XFB_CULLDISTANCE,
72 TEST_TYPE_XFB_CLIP_AND_CULL,
74 TEST_TYPE_STREAMS_POINTSIZE,
75 TEST_TYPE_STREAMS_CLIPDISTANCE,
76 TEST_TYPE_STREAMS_CULLDISTANCE,
77 TEST_TYPE_MULTISTREAMS,
78 TEST_TYPE_DRAW_INDIRECT,
79 TEST_TYPE_BACKWARD_DEPENDENCY,
82 TEST_TYPE_QUERY_RESET,
89 STREAM_ID_0_NORMAL = 0,
90 STREAM_ID_0_BEGIN_QUERY_INDEXED = 1,
91 STREAM_ID_0_END_QUERY_INDEXED = 2,
101 deUint32 vertexStride;
102 StreamId0Mode streamId0Mode;
105 VkPrimitiveTopology primTopology;
110 deUint32 primSize; // The size of the on primitive.
111 std::string topologyName; // The suffix for the name of test.
112 std::function<deUint64(deUint64)> getNumPrimitives; // The number of primitives generated.
113 std::function<deUint64(deUint64)> getNumVertices; // The number of vertices generated.
116 const std::map<VkPrimitiveTopology, TopologyInfo> topologyData =
118 { VK_PRIMITIVE_TOPOLOGY_POINT_LIST , { 1, "" ,[](deUint64 vertexCount) { return vertexCount; } ,[](deUint64 primCount) { return primCount; }, } },
119 { VK_PRIMITIVE_TOPOLOGY_LINE_LIST , { 2, "line_list_" ,[](deUint64 vertexCount) { return vertexCount / 2u; } ,[](deUint64 primCount) { return primCount * 2u; }, } },
120 { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP , { 2, "line_strip_" ,[](deUint64 vertexCount) { return vertexCount - 1u; } ,[](deUint64 primCount) { return primCount + 1u; }, } },
121 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST , { 3, "triangle_list_" ,[](deUint64 vertexCount) { return vertexCount / 3u; } ,[](deUint64 primCount) { return primCount * 3u; }, } },
122 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP , { 3, "triangle_strip_" ,[](deUint64 vertexCount) { return vertexCount - 2u; } ,[](deUint64 primCount) { return primCount + 2u; }, } },
123 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN , { 3, "triangle_fan_" ,[](deUint64 vertexCount) { return vertexCount - 2u; } ,[](deUint64 primCount) { return primCount + 2u; }, } },
124 { VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY , { 2, "line_list_with_adjacency_" ,[](deUint64 vertexCount) { return vertexCount / 4u; } ,[](deUint64 primCount) { return primCount * 4u; }, } },
125 { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY , { 2, "line_strip_with_adjacency_" ,[](deUint64 vertexCount) { return vertexCount - 3u; } ,[](deUint64 primCount) { return primCount + 3u; }, } },
126 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY , { 3, "triangle_list_with_adjacency_" ,[](deUint64 vertexCount) { return vertexCount / 6u; } ,[](deUint64 primCount) { return primCount * 6u; }, } },
127 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY , { 3, "triangle_strip_with_adjacency_" ,[](deUint64 vertexCount) { return (vertexCount - 4u) / 2u; } ,[](deUint64 primCount) { return primCount * 2u + 4u; }, } },
128 { VK_PRIMITIVE_TOPOLOGY_PATCH_LIST , { 3, "patch_list_" ,[](deUint64 vertexCount) { return vertexCount / 3u; } ,[](deUint64 primCount) { return primCount * 3u; }, } },
131 struct TransformFeedbackQuery
137 const deUint32 MINIMUM_TF_BUFFER_SIZE = (1<<27);
138 const deUint32 IMAGE_SIZE = 64u;
141 inline SharedPtr<Unique<T> > makeSharedPtr(Move<T> move)
143 return SharedPtr<Unique<T> >(new Unique<T>(move));
146 Move<VkPipelineLayout> makePipelineLayout (const DeviceInterface& vk,
147 const VkDevice device)
149 const VkPushConstantRange pushConstantRanges =
151 VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlags stageFlags;
152 0u, // deUint32 offset;
153 sizeof(deUint32) // deUint32 size;
155 const VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo =
157 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
158 DE_NULL, // const void* pNext;
159 (VkPipelineLayoutCreateFlags)0, // VkPipelineLayoutCreateFlags flags;
160 0u, // deUint32 setLayoutCount;
161 DE_NULL, // const VkDescriptorSetLayout* pSetLayouts;
162 1u, // deUint32 pushConstantRangeCount;
163 &pushConstantRanges, // const VkPushConstantRange* pPushConstantRanges;
165 return createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
168 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface& vk,
169 const VkDevice device,
170 const VkPipelineLayout pipelineLayout,
171 const VkRenderPass renderPass,
172 const VkShaderModule vertexModule,
173 const VkShaderModule tessellationControlModule,
174 const VkShaderModule tessellationEvalModule,
175 const VkShaderModule geometryModule,
176 const VkShaderModule fragmendModule,
177 const VkExtent2D renderSize,
178 const deUint32 subpass,
179 const deUint32* rasterizationStreamPtr = DE_NULL,
180 const VkPrimitiveTopology topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST,
181 const bool inputVertices = false)
183 const std::vector<VkViewport> viewports (1, makeViewport(renderSize));
184 const std::vector<VkRect2D> scissors (1, makeRect2D(renderSize));
185 const VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo =
187 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType
188 DE_NULL, // const void* pNext
189 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags
190 0u, // deUint32 vertexBindingDescriptionCount
191 DE_NULL, // const VkVertexInputBindingDescription* pVertexBindingDescriptions
192 0u, // deUint32 vertexAttributeDescriptionCount
193 DE_NULL, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions
195 const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfoPtr = (inputVertices) ? DE_NULL : &vertexInputStateCreateInfo;
196 const VkBool32 disableRasterization = (fragmendModule == DE_NULL);
197 const deUint32 rasterizationStream = (rasterizationStreamPtr == DE_NULL) ? 0 : *rasterizationStreamPtr;
198 const VkPipelineRasterizationStateStreamCreateInfoEXT rasterizationStateStreamCreateInfo =
200 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_STREAM_CREATE_INFO_EXT, // VkStructureType sType;
201 DE_NULL, // const void* pNext;
202 0, // VkPipelineRasterizationStateStreamCreateFlagsEXT flags;
203 rasterizationStream // deUint32 rasterizationStream;
205 const VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo =
207 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
208 &rasterizationStateStreamCreateInfo, // const void* pNext;
209 0u, // VkPipelineRasterizationStateCreateFlags flags;
210 VK_FALSE, // VkBool32 depthClampEnable;
211 disableRasterization, // VkBool32 rasterizerDiscardEnable;
212 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
213 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode;
214 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
215 VK_FALSE, // VkBool32 depthBiasEnable;
216 0.0f, // float depthBiasConstantFactor;
217 0.0f, // float depthBiasClamp;
218 0.0f, // float depthBiasSlopeFactor;
219 1.0f // float lineWidth;
221 const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfoPtr = (rasterizationStreamPtr == DE_NULL) ? DE_NULL : &rasterizationStateCreateInfo;
223 return makeGraphicsPipeline(vk, // const DeviceInterface& vk
224 device, // const VkDevice device
225 pipelineLayout, // const VkPipelineLayout pipelineLayout
226 vertexModule, // const VkShaderModule vertexShaderModule
227 tessellationControlModule, // const VkShaderModule tessellationControlModule
228 tessellationEvalModule, // const VkShaderModule tessellationEvalModule
229 geometryModule, // const VkShaderModule geometryShaderModule
230 fragmendModule, // const VkShaderModule fragmentShaderModule
231 renderPass, // const VkRenderPass renderPass
232 viewports, // const std::vector<VkViewport>& viewports
233 scissors, // const std::vector<VkRect2D>& scissors
234 topology, // const VkPrimitiveTopology topology
235 subpass, // const deUint32 subpass
236 (tessellationEvalModule != DE_NULL) * 3u, // const deUint32 patchControlPoints
237 vertexInputStateCreateInfoPtr, // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo
238 rasterizationStateCreateInfoPtr); // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
241 VkImageCreateInfo makeImageCreateInfo (const VkImageCreateFlags flags, const VkImageType type, const VkFormat format, const VkExtent2D size, const deUint32 numLayers, const VkImageUsageFlags usage)
243 const VkExtent3D extent = { size.width, size.height, 1u };
244 const VkImageCreateInfo imageParams =
246 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
247 DE_NULL, // const void* pNext;
248 flags, // VkImageCreateFlags flags;
249 type, // VkImageType imageType;
250 format, // VkFormat format;
251 extent, // VkExtent3D extent;
252 1u, // deUint32 mipLevels;
253 numLayers, // deUint32 arrayLayers;
254 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
255 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
256 usage, // VkImageUsageFlags usage;
257 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
258 0u, // deUint32 queueFamilyIndexCount;
259 DE_NULL, // const deUint32* pQueueFamilyIndices;
260 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
265 Move<VkRenderPass> makeRenderPass (const DeviceInterface& vk,
266 const VkDevice device)
268 std::vector<VkSubpassDescription> subpassDescriptions;
269 std::vector<VkSubpassDependency> subpassDependencies;
271 const VkSubpassDescription description =
273 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags;
274 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
275 0u, // deUint32 inputAttachmentCount;
276 DE_NULL, // const VkAttachmentReference* pInputAttachments;
277 0u, // deUint32 colorAttachmentCount;
278 DE_NULL, // const VkAttachmentReference* pColorAttachments;
279 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
280 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment;
281 0, // deUint32 preserveAttachmentCount;
282 DE_NULL // const deUint32* pPreserveAttachments;
284 subpassDescriptions.push_back(description);
286 const VkSubpassDependency dependency =
288 0u, // deUint32 srcSubpass;
289 0u, // deUint32 dstSubpass;
290 VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, // VkPipelineStageFlags srcStageMask;
291 VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, // VkPipelineStageFlags dstStageMask;
292 VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT, // VkAccessFlags srcAccessMask;
293 VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT, // VkAccessFlags dstAccessMask;
294 0u // VkDependencyFlags dependencyFlags;
296 subpassDependencies.push_back(dependency);
298 const VkRenderPassCreateInfo renderPassInfo =
300 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
301 DE_NULL, // const void* pNext;
302 static_cast<VkRenderPassCreateFlags>(0u), // VkRenderPassCreateFlags flags;
303 0u, // deUint32 attachmentCount;
304 DE_NULL, // const VkAttachmentDescription* pAttachments;
305 static_cast<deUint32>(subpassDescriptions.size()), // deUint32 subpassCount;
306 &subpassDescriptions[0], // const VkSubpassDescription* pSubpasses;
307 static_cast<deUint32>(subpassDependencies.size()), // deUint32 dependencyCount;
308 subpassDependencies.size() > 0 ? &subpassDependencies[0] : DE_NULL // const VkSubpassDependency* pDependencies;
311 return createRenderPass(vk, device, &renderPassInfo);
314 VkImageMemoryBarrier makeImageMemoryBarrier (const VkAccessFlags srcAccessMask,
315 const VkAccessFlags dstAccessMask,
316 const VkImageLayout oldLayout,
317 const VkImageLayout newLayout,
319 const VkImageSubresourceRange subresourceRange)
321 const VkImageMemoryBarrier barrier =
323 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
324 DE_NULL, // const void* pNext;
325 srcAccessMask, // VkAccessFlags outputMask;
326 dstAccessMask, // VkAccessFlags inputMask;
327 oldLayout, // VkImageLayout oldLayout;
328 newLayout, // VkImageLayout newLayout;
329 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
330 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
331 image, // VkImage image;
332 subresourceRange, // VkImageSubresourceRange subresourceRange;
337 VkBufferMemoryBarrier makeBufferMemoryBarrier (const VkAccessFlags srcAccessMask,
338 const VkAccessFlags dstAccessMask,
339 const VkBuffer buffer,
340 const VkDeviceSize offset,
341 const VkDeviceSize bufferSizeBytes)
343 const VkBufferMemoryBarrier barrier =
345 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
346 DE_NULL, // const void* pNext;
347 srcAccessMask, // VkAccessFlags srcAccessMask;
348 dstAccessMask, // VkAccessFlags dstAccessMask;
349 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
350 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
351 buffer, // VkBuffer buffer;
352 offset, // VkDeviceSize offset;
353 bufferSizeBytes, // VkDeviceSize size;
358 VkMemoryBarrier makeMemoryBarrier (const VkAccessFlags srcAccessMask,
359 const VkAccessFlags dstAccessMask)
361 const VkMemoryBarrier barrier =
363 VK_STRUCTURE_TYPE_MEMORY_BARRIER, // VkStructureType sType;
364 DE_NULL, // const void* pNext;
365 srcAccessMask, // VkAccessFlags outputMask;
366 dstAccessMask, // VkAccessFlags inputMask;
371 VkQueryPoolCreateInfo makeQueryPoolCreateInfo (const deUint32 queryCountersNumber)
373 const VkQueryPoolCreateInfo queryPoolCreateInfo =
375 VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, // VkStructureType sType;
376 DE_NULL, // const void* pNext;
377 (VkQueryPoolCreateFlags)0, // VkQueryPoolCreateFlags flags;
378 VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT, // VkQueryType queryType;
379 queryCountersNumber, // deUint32 queryCount;
380 0u, // VkQueryPipelineStatisticFlags pipelineStatistics;
383 return queryPoolCreateInfo;
386 void fillBuffer (const DeviceInterface& vk, const VkDevice device, Allocation& bufferAlloc, VkDeviceSize bufferSize, const void* data, const VkDeviceSize dataSize)
388 const VkMappedMemoryRange memRange =
390 VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType;
391 DE_NULL, // const void* pNext;
392 bufferAlloc.getMemory(), // VkDeviceMemory memory;
393 bufferAlloc.getOffset(), // VkDeviceSize offset;
394 VK_WHOLE_SIZE // VkDeviceSize size;
396 std::vector<deUint8> dataVec (static_cast<deUint32>(bufferSize), 0u);
398 DE_ASSERT(bufferSize >= dataSize);
400 deMemcpy(&dataVec[0], data, static_cast<deUint32>(dataSize));
402 deMemcpy(bufferAlloc.getHostPtr(), &dataVec[0], dataVec.size());
403 VK_CHECK(vk.flushMappedMemoryRanges(device, 1u, &memRange));
406 class TransformFeedbackTestInstance : public TestInstance
409 TransformFeedbackTestInstance (Context& context, const TestParameters& parameters);
411 void validateLimits ();
412 std::vector<VkDeviceSize> generateSizesList (const size_t bufBytes, const size_t chunkCount);
413 std::vector<VkDeviceSize> generateOffsetsList (const std::vector<VkDeviceSize>& sizesList);
414 void verifyTransformFeedbackBuffer (const MovePtr<Allocation>& bufAlloc,
415 const deUint32 bufBytes);
417 const bool m_extensions;
418 const VkExtent2D m_imageExtent2D;
419 const TestParameters m_parameters;
420 VkPhysicalDeviceTransformFeedbackPropertiesEXT m_transformFeedbackProperties;
424 TransformFeedbackTestInstance::TransformFeedbackTestInstance (Context& context, const TestParameters& parameters)
425 : TestInstance (context)
426 , m_extensions (context.requireDeviceFunctionality("VK_EXT_transform_feedback"))
427 , m_imageExtent2D (makeExtent2D(IMAGE_SIZE, IMAGE_SIZE))
428 , m_parameters (parameters)
431 const VkPhysicalDeviceTransformFeedbackFeaturesEXT& transformFeedbackFeatures = m_context.getTransformFeedbackFeaturesEXT();
432 VkPhysicalDeviceProperties2 deviceProperties2;
434 if (transformFeedbackFeatures.transformFeedback == DE_FALSE)
435 TCU_THROW(NotSupportedError, "transformFeedback feature is not supported");
437 deMemset(&deviceProperties2, 0, sizeof(deviceProperties2));
438 deMemset(&m_transformFeedbackProperties, 0, sizeof(m_transformFeedbackProperties));
440 deviceProperties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
441 deviceProperties2.pNext = &m_transformFeedbackProperties;
443 m_transformFeedbackProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT;
444 m_transformFeedbackProperties.pNext = DE_NULL;
446 context.getInstanceInterface().getPhysicalDeviceProperties2(context.getPhysicalDevice(), &deviceProperties2);
450 if (m_parameters.streamId > 0 && (m_transformFeedbackProperties.transformFeedbackRasterizationStreamSelect == VK_FALSE))
451 TCU_THROW(NotSupportedError, "Implementation doesn't support streamId > 0");
454 void TransformFeedbackTestInstance::validateLimits ()
456 VALIDATE_MINIMUM(m_transformFeedbackProperties.maxTransformFeedbackBuffers, 1);
457 VALIDATE_MINIMUM(m_transformFeedbackProperties.maxTransformFeedbackBufferSize, MINIMUM_TF_BUFFER_SIZE);
458 VALIDATE_MINIMUM(m_transformFeedbackProperties.maxTransformFeedbackStreamDataSize, 512);
459 VALIDATE_MINIMUM(m_transformFeedbackProperties.maxTransformFeedbackBufferDataSize, 512);
460 VALIDATE_MINIMUM(m_transformFeedbackProperties.maxTransformFeedbackBufferDataStride, 512);
462 VALIDATE_BOOL(m_transformFeedbackProperties.transformFeedbackQueries);
463 VALIDATE_BOOL(m_transformFeedbackProperties.transformFeedbackStreamsLinesTriangles);
464 VALIDATE_BOOL(m_transformFeedbackProperties.transformFeedbackRasterizationStreamSelect);
465 VALIDATE_BOOL(m_transformFeedbackProperties.transformFeedbackDraw);
468 std::vector<VkDeviceSize> TransformFeedbackTestInstance::generateSizesList (const size_t bufBytes, const size_t chunkCount)
470 const int minChunkSlot = static_cast<int>(1);
471 const int maxChunkSlot = static_cast<int>(bufBytes / sizeof(deUint32));
472 int prevOffsetSlot = 0;
473 std::map<int, bool> offsetsSet;
474 std::vector<VkDeviceSize> result;
476 DE_ASSERT(bufBytes <= MINIMUM_TF_BUFFER_SIZE);
477 DE_ASSERT(bufBytes % sizeof(deUint32) == 0);
478 DE_ASSERT(minChunkSlot <= maxChunkSlot);
479 DE_ASSERT(chunkCount > 0);
480 // To be effective this algorithm requires that chunkCount is much less than amount of chunks possible
481 DE_ASSERT(8 * chunkCount <= static_cast<size_t>(maxChunkSlot));
483 offsetsSet[0] = true;
485 // Create a list of unique offsets first
486 for (size_t chunkNdx = 1; chunkNdx < chunkCount; ++chunkNdx)
492 chunkSlot = m_rnd.getInt(minChunkSlot, maxChunkSlot - 1);
493 } while (offsetsSet.find(chunkSlot) != offsetsSet.end());
495 offsetsSet[chunkSlot] = true;
497 offsetsSet[maxChunkSlot] = true;
499 // Calculate sizes of offsets list
500 result.reserve(chunkCount);
501 for (std::map<int, bool>::iterator mapIt = offsetsSet.begin(); mapIt != offsetsSet.end(); ++mapIt)
503 const int offsetSlot = mapIt->first;
508 DE_ASSERT(prevOffsetSlot < offsetSlot && offsetSlot > 0);
510 result.push_back(static_cast<VkDeviceSize>(static_cast<size_t>(offsetSlot - prevOffsetSlot) * sizeof(deUint32)));
512 prevOffsetSlot = offsetSlot;
515 DE_ASSERT(result.size() == chunkCount);
520 std::vector<VkDeviceSize> TransformFeedbackTestInstance::generateOffsetsList (const std::vector<VkDeviceSize>& sizesList)
522 VkDeviceSize offset = 0ull;
523 std::vector<VkDeviceSize> result;
525 result.reserve(sizesList.size());
527 for (size_t chunkNdx = 0; chunkNdx < sizesList.size(); ++chunkNdx)
529 result.push_back(offset);
531 offset += sizesList[chunkNdx];
534 DE_ASSERT(sizesList.size() == result.size());
539 void TransformFeedbackTestInstance::verifyTransformFeedbackBuffer (const MovePtr<Allocation>& bufAlloc,
540 const deUint32 bufBytes)
542 const DeviceInterface& vk = m_context.getDeviceInterface();
543 const VkDevice device = m_context.getDevice();
545 invalidateAlloc(vk, device, *bufAlloc);
547 const deUint32 numPoints = static_cast<deUint32>(bufBytes / sizeof(deUint32));
548 const deUint32* tfData = (deUint32*)bufAlloc->getHostPtr();
550 for (deUint32 i = 0; i < numPoints; ++i)
552 TCU_FAIL(std::string("Failed at item ") + de::toString(i) + " received:" + de::toString(tfData[i]) + " expected:" + de::toString(i));
555 class TransformFeedbackBasicTestInstance : public TransformFeedbackTestInstance
558 TransformFeedbackBasicTestInstance (Context& context, const TestParameters& parameters);
561 tcu::TestStatus iterate (void);
564 TransformFeedbackBasicTestInstance::TransformFeedbackBasicTestInstance (Context& context, const TestParameters& parameters)
565 : TransformFeedbackTestInstance (context, parameters)
569 tcu::TestStatus TransformFeedbackBasicTestInstance::iterate (void)
571 const DeviceInterface& vk = m_context.getDeviceInterface();
572 const VkDevice device = m_context.getDevice();
573 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
574 const VkQueue queue = m_context.getUniversalQueue();
575 Allocator& allocator = m_context.getDefaultAllocator();
577 const Unique<VkShaderModule> vertexModule (createShaderModule (vk, device, m_context.getBinaryCollection().get("vert"), 0u));
578 const Unique<VkRenderPass> renderPass (makeRenderPass (vk, device, VK_FORMAT_UNDEFINED));
579 const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, 0u, DE_NULL, m_imageExtent2D.width, m_imageExtent2D.height));
580 const Unique<VkPipelineLayout> pipelineLayout (TransformFeedback::makePipelineLayout (vk, device));
581 const Unique<VkPipeline> pipeline (makeGraphicsPipeline (vk, device, *pipelineLayout, *renderPass, *vertexModule, DE_NULL, DE_NULL, DE_NULL, DE_NULL, m_imageExtent2D, 0u, &m_parameters.streamId));
582 const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
583 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
585 const VkBufferCreateInfo tfBufCreateInfo = makeBufferCreateInfo(m_parameters.bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT);
586 const Move<VkBuffer> tfBuf = createBuffer(vk, device, &tfBufCreateInfo);
587 const MovePtr<Allocation> tfBufAllocation = allocator.allocate(getBufferMemoryRequirements(vk, device, *tfBuf), MemoryRequirement::HostVisible);
588 const VkMemoryBarrier tfMemoryBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT, VK_ACCESS_HOST_READ_BIT);
589 const std::vector<VkDeviceSize> tfBufBindingSizes = generateSizesList(m_parameters.bufferSize, m_parameters.partCount);
590 const std::vector<VkDeviceSize> tfBufBindingOffsets = generateOffsetsList(tfBufBindingSizes);
592 VK_CHECK(vk.bindBufferMemory(device, *tfBuf, tfBufAllocation->getMemory(), tfBufAllocation->getOffset()));
594 beginCommandBuffer(vk, *cmdBuffer);
596 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
598 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
600 for (deUint32 drawNdx = 0; drawNdx < m_parameters.partCount; ++drawNdx)
602 const deUint32 startValue = static_cast<deUint32>(tfBufBindingOffsets[drawNdx] / sizeof(deUint32));
603 const deUint32 numPoints = static_cast<deUint32>(tfBufBindingSizes[drawNdx] / sizeof(deUint32));
605 vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0, 1, &*tfBuf, &tfBufBindingOffsets[drawNdx], &tfBufBindingSizes[drawNdx]);
607 vk.cmdPushConstants(*cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0u, sizeof(startValue), &startValue);
609 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
611 vk.cmdDraw(*cmdBuffer, numPoints, 1u, 0u, 0u);
613 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
616 endRenderPass(vk, *cmdBuffer);
618 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &tfMemoryBarrier, 0u, DE_NULL, 0u, DE_NULL);
620 endCommandBuffer(vk, *cmdBuffer);
621 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
623 verifyTransformFeedbackBuffer(tfBufAllocation, m_parameters.bufferSize);
625 return tcu::TestStatus::pass("Pass");
628 class TransformFeedbackResumeTestInstance : public TransformFeedbackTestInstance
631 TransformFeedbackResumeTestInstance (Context& context, const TestParameters& parameters);
634 tcu::TestStatus iterate (void);
637 TransformFeedbackResumeTestInstance::TransformFeedbackResumeTestInstance (Context& context, const TestParameters& parameters)
638 : TransformFeedbackTestInstance (context, parameters)
642 tcu::TestStatus TransformFeedbackResumeTestInstance::iterate (void)
644 const DeviceInterface& vk = m_context.getDeviceInterface();
645 const VkDevice device = m_context.getDevice();
646 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
647 const VkQueue queue = m_context.getUniversalQueue();
648 Allocator& allocator = m_context.getDefaultAllocator();
650 const Unique<VkShaderModule> vertexModule (createShaderModule (vk, device, m_context.getBinaryCollection().get("vert"), 0u));
651 const Unique<VkRenderPass> renderPass (makeRenderPass (vk, device, VK_FORMAT_UNDEFINED));
652 const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, 0u, DE_NULL, m_imageExtent2D.width, m_imageExtent2D.height));
653 const Unique<VkPipelineLayout> pipelineLayout (TransformFeedback::makePipelineLayout (vk, device));
654 const Unique<VkPipeline> pipeline (makeGraphicsPipeline (vk, device, *pipelineLayout, *renderPass, *vertexModule, DE_NULL, DE_NULL, DE_NULL, DE_NULL, m_imageExtent2D, 0u, &m_parameters.streamId));
656 const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
657 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
659 const VkBufferCreateInfo tfBufCreateInfo = makeBufferCreateInfo(m_parameters.bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT);
660 const Move<VkBuffer> tfBuf = createBuffer(vk, device, &tfBufCreateInfo);
661 const MovePtr<Allocation> tfBufAllocation = allocator.allocate(getBufferMemoryRequirements(vk, device, *tfBuf), MemoryRequirement::HostVisible);
662 const VkMemoryBarrier tfMemoryBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT, VK_ACCESS_HOST_READ_BIT);
663 const std::vector<VkDeviceSize> tfBufBindingSizes = std::vector<VkDeviceSize>(1, m_parameters.bufferSize);
664 const std::vector<VkDeviceSize> tfBufBindingOffsets = std::vector<VkDeviceSize>(1, 0ull);
666 const size_t tfcBufSize = 16 * sizeof(deUint32) * m_parameters.partCount;
667 const VkBufferCreateInfo tfcBufCreateInfo = makeBufferCreateInfo(tfcBufSize, VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT);
668 const Move<VkBuffer> tfcBuf = createBuffer(vk, device, &tfcBufCreateInfo);
669 const MovePtr<Allocation> tfcBufAllocation = allocator.allocate(getBufferMemoryRequirements(vk, device, *tfcBuf), MemoryRequirement::Any);
670 const std::vector<VkDeviceSize> tfcBufBindingOffsets = generateOffsetsList(generateSizesList(tfcBufSize, m_parameters.partCount));
671 const VkBufferMemoryBarrier tfcBufBarrier = makeBufferMemoryBarrier(VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT, VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT, *tfcBuf, 0ull, VK_WHOLE_SIZE);
673 const std::vector<VkDeviceSize> chunkSizesList = generateSizesList(m_parameters.bufferSize, m_parameters.partCount);
674 const std::vector<VkDeviceSize> chunkOffsetsList = generateOffsetsList(chunkSizesList);
676 DE_ASSERT(tfBufBindingSizes.size() == 1);
677 DE_ASSERT(tfBufBindingOffsets.size() == 1);
679 VK_CHECK(vk.bindBufferMemory(device, *tfBuf, tfBufAllocation->getMemory(), tfBufAllocation->getOffset()));
680 VK_CHECK(vk.bindBufferMemory(device, *tfcBuf, tfcBufAllocation->getMemory(), tfcBufAllocation->getOffset()));
682 beginCommandBuffer(vk, *cmdBuffer);
684 for (size_t drawNdx = 0; drawNdx < m_parameters.partCount; ++drawNdx)
686 const deUint32 startValue = static_cast<deUint32>(chunkOffsetsList[drawNdx] / sizeof(deUint32));
687 const deUint32 numPoints = static_cast<deUint32>(chunkSizesList[drawNdx] / sizeof(deUint32));
688 const deUint32 countBuffersCount = (drawNdx == 0) ? 0 : 1;
690 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
693 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
695 vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0, 1, &*tfBuf, &tfBufBindingOffsets[0], &tfBufBindingSizes[0]);
697 vk.cmdPushConstants(*cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0u, sizeof(startValue), &startValue);
699 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, countBuffersCount, (drawNdx == 0) ? DE_NULL : &*tfcBuf, (drawNdx == 0) ? DE_NULL : &tfcBufBindingOffsets[drawNdx - 1]);
701 vk.cmdDraw(*cmdBuffer, numPoints, 1u, 0u, 0u);
703 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 1, &*tfcBuf, &tfcBufBindingOffsets[drawNdx]);
705 endRenderPass(vk, *cmdBuffer);
707 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, 0u, 0u, DE_NULL, 1u, &tfcBufBarrier, 0u, DE_NULL);
710 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &tfMemoryBarrier, 0u, DE_NULL, 0u, DE_NULL);
712 endCommandBuffer(vk, *cmdBuffer);
713 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
715 verifyTransformFeedbackBuffer(tfBufAllocation, m_parameters.bufferSize);
717 return tcu::TestStatus::pass("Pass");
720 class TransformFeedbackWindingOrderTestInstance : public TransformFeedbackTestInstance
723 TransformFeedbackWindingOrderTestInstance(Context& context, const TestParameters& parameters);
726 struct TopologyParameters
728 // number of vertex in primitive; 2 for line, 3 for triangle
729 deUint32 vertexPerPrimitive;
731 // pointer to function calculating number of points that
732 // will be generated for given part count
733 std::function<deUint32(deUint32)> getNumGeneratedPoints;
735 // pointer to function generating expected values; parameter is
736 // primitive index, result array with expected data for primitive vertex
737 std::function<std::vector<deUint32>(deUint32)> getExpectedValuesForPrimitive;
739 typedef const std::map<VkPrimitiveTopology, TopologyParameters> TopologyParametersMap;
742 const TopologyParametersMap& getTopologyParametersMap (void);
743 tcu::TestStatus iterate (void);
744 void verifyTransformFeedbackBuffer (const MovePtr<Allocation>& bufAlloc,
745 const deUint32 bufBytes);
748 TopologyParameters m_tParameters;
749 const bool m_requiresTesselationStage;
752 TransformFeedbackWindingOrderTestInstance::TransformFeedbackWindingOrderTestInstance(Context& context, const TestParameters& parameters)
753 : TransformFeedbackTestInstance (context, parameters)
754 , m_requiresTesselationStage(parameters.primTopology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST)
756 if (m_requiresTesselationStage && !context.getDeviceFeatures().tessellationShader)
757 throw tcu::NotSupportedError("Tessellation shader not supported");
759 TopologyParametersMap topologyParametersMap = getTopologyParametersMap();
760 DE_ASSERT(topologyParametersMap.find(parameters.primTopology) != topologyParametersMap.end());
761 m_tParameters = topologyParametersMap.at(parameters.primTopology);
764 const TransformFeedbackWindingOrderTestInstance::TopologyParametersMap& TransformFeedbackWindingOrderTestInstance::getTopologyParametersMap(void)
766 static const TopologyParametersMap topologyParametersMap =
769 VK_PRIMITIVE_TOPOLOGY_POINT_LIST,
772 [](deUint32 partCount) { return partCount; },
773 [](deUint32 i) { return std::vector<deUint32>{ i, i + 1u }; }
777 VK_PRIMITIVE_TOPOLOGY_LINE_LIST,
780 [](deUint32 partCount) { return partCount; },
781 [](deUint32 i) { return std::vector<deUint32>{ 2 * i, 2 * i + 1u }; }
785 VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,
788 [](deUint32 partCount) { return 2u * (partCount - 1); },
789 [](deUint32 i) { return std::vector<deUint32>{ i, i + 1u }; }
793 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
796 [](deUint32 partCount) { return partCount; },
797 [](deUint32 i) { return std::vector<deUint32>{ 3 * i, 3 * i + 1u, 3 * i + 2u }; }
801 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
804 [](deUint32 partCount) { return 3u * (partCount - 2); },
807 const deUint32 iMod2 = i % 2;
808 return std::vector<deUint32>{ i, i + 1 + iMod2, i + 2 - iMod2 };
813 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,
816 [](deUint32 partCount) { return partCount; },
817 [](deUint32 i) { return std::vector<deUint32>{ i + 1, i + 2, 0 }; }
821 VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY,
824 [](deUint32 partCount) { return partCount / 4u; }, // note: this cant be replaced with partCount / 2 as for partCount=6 we will get 3 instead of 2
825 [](deUint32 i) { return std::vector<deUint32>{ i + 1u, i + 2u }; }
829 VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY,
832 [](deUint32 partCount) { return 2u * (partCount - 3u); },
833 [](deUint32 i) { return std::vector<deUint32>{ i + 1u, i + 2u }; }
837 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY,
840 [](deUint32 partCount) { return partCount / 2u; },
841 [](deUint32 i) { return std::vector<deUint32>{ 6 * i, 6 * i + 2u, 6 * i + 4u }; }
845 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY,
848 [](deUint32 partCount) { return 3u * (partCount / 2u - 2u); },
851 const bool even = (0 == i % 2);
853 return std::vector<deUint32>{ 2 * i + 0, 2 * i + 2, 2 * i + 4 };
854 return std::vector<deUint32>{ 2 * i + 0, 2 * i + 4, 2 * i + 2 };
859 VK_PRIMITIVE_TOPOLOGY_PATCH_LIST,
862 [](deUint32 partCount) { return partCount * 3u; },
865 // we cant generate vertex numbers in tesselation evaluation shader;
866 // check if patch index is correct for every 9 generated vertex
867 return std::vector<deUint32>(9, i);
873 return topologyParametersMap;
876 tcu::TestStatus TransformFeedbackWindingOrderTestInstance::iterate (void)
878 DE_ASSERT(m_parameters.partCount >= 6);
880 const DeviceInterface& vk = m_context.getDeviceInterface();
881 const VkDevice device = m_context.getDevice();
882 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
883 const VkQueue queue = m_context.getUniversalQueue();
884 Allocator& allocator = m_context.getDefaultAllocator();
886 const Move<VkShaderModule> vertexModule(createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
887 Move<VkShaderModule> tescModule;
888 Move<VkShaderModule> teseModule;
889 if (m_requiresTesselationStage)
891 tescModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("tesc"), 0u);
892 teseModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("tese"), 0u);
895 const Unique<VkRenderPass> renderPass (makeRenderPass (vk, device, VK_FORMAT_UNDEFINED));
896 const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, 0u, DE_NULL, m_imageExtent2D.width, m_imageExtent2D.height));
897 const Unique<VkPipelineLayout> pipelineLayout (TransformFeedback::makePipelineLayout (vk, device));
898 const Unique<VkPipeline> pipeline (makeGraphicsPipeline (vk, device, *pipelineLayout, *renderPass,
900 m_requiresTesselationStage ? *tescModule : DE_NULL,
901 m_requiresTesselationStage ? *teseModule : DE_NULL,
904 m_imageExtent2D, 0u, DE_NULL, m_parameters.primTopology));
905 const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
906 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
907 const VkDeviceSize bufferSize = m_tParameters.getNumGeneratedPoints (m_parameters.partCount) * sizeof(deUint32);
908 const VkBufferCreateInfo tfBufCreateInfo = makeBufferCreateInfo (bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT);
909 const Move<VkBuffer> tfBuf = createBuffer (vk, device, &tfBufCreateInfo);
910 const MovePtr<Allocation> tfBufAllocation = allocator.allocate (getBufferMemoryRequirements(vk, device, *tfBuf), MemoryRequirement::HostVisible);
911 const VkMemoryBarrier tfMemoryBarrier = makeMemoryBarrier (VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT, VK_ACCESS_HOST_READ_BIT);
912 const VkDeviceSize tfBufBindingSize = bufferSize;
913 const VkDeviceSize tfBufBindingOffset = 0u;
914 const deUint32 startValue = 0u;
916 VK_CHECK(vk.bindBufferMemory(device, *tfBuf, tfBufAllocation->getMemory(), tfBufAllocation->getOffset()));
918 beginCommandBuffer(vk, *cmdBuffer);
920 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
922 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
924 vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0, 1, &*tfBuf, &tfBufBindingOffset, &tfBufBindingSize);
926 vk.cmdPushConstants(*cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0u, sizeof(startValue), &startValue);
928 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
930 vk.cmdDraw(*cmdBuffer, m_parameters.partCount, 1u, 0u, 0u);
932 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
934 endRenderPass(vk, *cmdBuffer);
936 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &tfMemoryBarrier, 0u, DE_NULL, 0u, DE_NULL);
938 endCommandBuffer(vk, *cmdBuffer);
939 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
941 verifyTransformFeedbackBuffer(tfBufAllocation, static_cast<deUint32>(bufferSize));
943 return tcu::TestStatus::pass("Pass");
946 void TransformFeedbackWindingOrderTestInstance::verifyTransformFeedbackBuffer(const MovePtr<Allocation>& bufAlloc,
947 const deUint32 bufBytes)
949 const DeviceInterface& vk = m_context.getDeviceInterface();
950 const VkDevice device = m_context.getDevice();
952 invalidateAlloc(vk, device, *bufAlloc);
954 const deUint32 numPoints = static_cast<deUint32>(bufBytes / sizeof(deUint32));
955 const deUint32 vertexPerPrimitive = m_tParameters.vertexPerPrimitive;
956 const deUint32 numPrimitives = numPoints / vertexPerPrimitive;
957 const deUint32* tfData = (deUint32*)bufAlloc->getHostPtr();
959 for (deUint32 primitiveIndex = 0; primitiveIndex < numPrimitives; ++primitiveIndex)
961 const deUint32* tfDataForPrimitive = &tfData[primitiveIndex * vertexPerPrimitive];
962 std::vector<deUint32> expectedDataForPrimitive = m_tParameters.getExpectedValuesForPrimitive(primitiveIndex);
964 // For multi - vertex primitives, all values for a given vertex are written before writing values for any other vertex.
965 // Implementations may write out any vertex within the primitive first, but all subsequent vertices for that primitive
966 // must be written out in a consistent winding order
967 bool correctWinding = true;
968 for (deUint32 combinationIndex = 0; combinationIndex < vertexPerPrimitive; combinationIndex++)
970 correctWinding = true;
971 for (deUint32 vertexIndex = 0; vertexIndex < vertexPerPrimitive; vertexIndex++)
973 correctWinding &= (tfDataForPrimitive[vertexIndex] == expectedDataForPrimitive[(combinationIndex + vertexIndex) % vertexPerPrimitive]);
975 // if data for this vertex is not correct then there
976 // is no need to check other, go to next combination
981 // no need to check other combinations, we found correct one
988 std::stringstream message;
989 message << "Failed at primitive " << primitiveIndex << " received: [";
990 for (deUint32 vertexIndex = 0; vertexIndex < vertexPerPrimitive; vertexIndex++)
991 message << de::toString(tfDataForPrimitive[vertexIndex]) << " ";
992 message << "] expected: [";
993 for (deUint32 vertexIndex = 0; vertexIndex < vertexPerPrimitive; vertexIndex++)
994 message << de::toString(expectedDataForPrimitive[vertexIndex]) << " ";
996 TCU_FAIL(message.str());
1001 class TransformFeedbackBuiltinTestInstance : public TransformFeedbackTestInstance
1004 TransformFeedbackBuiltinTestInstance (Context& context, const TestParameters& parameters);
1007 tcu::TestStatus iterate (void);
1008 void verifyTransformFeedbackBuffer (const MovePtr<Allocation>& bufAlloc, const VkDeviceSize offset, const deUint32 bufBytes);
1011 TransformFeedbackBuiltinTestInstance::TransformFeedbackBuiltinTestInstance (Context& context, const TestParameters& parameters)
1012 : TransformFeedbackTestInstance (context, parameters)
1014 const InstanceInterface& vki = m_context.getInstanceInterface();
1015 const VkPhysicalDevice physDevice = m_context.getPhysicalDevice();
1016 const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(vki, physDevice);
1018 const deUint32 tfBuffersSupported = m_transformFeedbackProperties.maxTransformFeedbackBuffers;
1019 const deUint32 tfBuffersRequired = m_parameters.partCount;
1021 if ((m_parameters.testType == TEST_TYPE_XFB_CLIPDISTANCE || m_parameters.testType == TEST_TYPE_XFB_CLIP_AND_CULL) && !features.shaderClipDistance)
1022 TCU_THROW(NotSupportedError, std::string("shaderClipDistance feature is not supported"));
1023 if ((m_parameters.testType == TEST_TYPE_XFB_CULLDISTANCE || m_parameters.testType == TEST_TYPE_XFB_CLIP_AND_CULL) && !features.shaderCullDistance)
1024 TCU_THROW(NotSupportedError, std::string("shaderCullDistance feature is not supported"));
1025 if (tfBuffersSupported < tfBuffersRequired)
1026 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBuffers=" + de::toString(tfBuffersSupported) + ", while test requires " + de::toString(tfBuffersRequired)).c_str());
1029 void TransformFeedbackBuiltinTestInstance::verifyTransformFeedbackBuffer (const MovePtr<Allocation>& bufAlloc, const VkDeviceSize offset, const deUint32 bufBytes)
1031 const DeviceInterface& vk = m_context.getDeviceInterface();
1032 const VkDevice device = m_context.getDevice();
1034 invalidateAlloc(vk, device, *bufAlloc);
1036 const deUint32 numPoints = bufBytes / static_cast<deUint32>(sizeof(float));
1037 const deUint8* tfDataBytes = (deUint8*)bufAlloc->getHostPtr();
1038 const float* tfData = (float*)&tfDataBytes[offset];
1040 for (deUint32 i = 0; i < numPoints; ++i)
1042 const deUint32 divisor = 32768u;
1043 const float epsilon = 1.0f / float(divisor);
1044 const float expected = float(i) / float(divisor);
1046 if (deAbs(tfData[i] - expected) > epsilon)
1047 TCU_FAIL(std::string("Failed at item ") + de::toString(i) + " received:" + de::toString(tfData[i]) + " expected:" + de::toString(expected));
1051 tcu::TestStatus TransformFeedbackBuiltinTestInstance::iterate (void)
1053 const DeviceInterface& vk = m_context.getDeviceInterface();
1054 const VkDevice device = m_context.getDevice();
1055 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1056 const VkQueue queue = m_context.getUniversalQueue();
1057 Allocator& allocator = m_context.getDefaultAllocator();
1059 const Unique<VkShaderModule> vertexModule (createShaderModule (vk, device, m_context.getBinaryCollection().get("vert"), 0u));
1060 const Unique<VkRenderPass> renderPass (makeRenderPass (vk, device, VK_FORMAT_UNDEFINED));
1061 const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, 0u, DE_NULL, m_imageExtent2D.width, m_imageExtent2D.height));
1062 const Unique<VkPipelineLayout> pipelineLayout (TransformFeedback::makePipelineLayout (vk, device));
1063 const Unique<VkPipeline> pipeline (makeGraphicsPipeline (vk, device, *pipelineLayout, *renderPass, *vertexModule, DE_NULL, DE_NULL, DE_NULL, DE_NULL, m_imageExtent2D, 0u, &m_parameters.streamId));
1064 const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1065 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1067 const VkDeviceSize tfBufSize = m_parameters.bufferSize * m_parameters.partCount;
1068 const VkBufferCreateInfo tfBufCreateInfo = makeBufferCreateInfo(tfBufSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT);
1069 const Move<VkBuffer> tfBuf = createBuffer(vk, device, &tfBufCreateInfo);
1070 const std::vector<VkBuffer> tfBufArray = std::vector<VkBuffer>(m_parameters.partCount, *tfBuf);
1071 const MovePtr<Allocation> tfBufAllocation = allocator.allocate(getBufferMemoryRequirements(vk, device, *tfBuf), MemoryRequirement::HostVisible);
1072 const VkMemoryBarrier tfMemoryBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT, VK_ACCESS_HOST_READ_BIT);
1073 const std::vector<VkDeviceSize> tfBufBindingSizes = std::vector<VkDeviceSize>(m_parameters.partCount, m_parameters.bufferSize);
1074 const std::vector<VkDeviceSize> tfBufBindingOffsets = generateOffsetsList(tfBufBindingSizes);
1075 const deUint32 perVertexDataSize = (m_parameters.testType == TEST_TYPE_XFB_POINTSIZE) ? static_cast<deUint32>(sizeof(float))
1076 : (m_parameters.testType == TEST_TYPE_XFB_CLIPDISTANCE) ? static_cast<deUint32>(8u * sizeof(float))
1077 : (m_parameters.testType == TEST_TYPE_XFB_CULLDISTANCE) ? static_cast<deUint32>(8u * sizeof(float))
1078 : (m_parameters.testType == TEST_TYPE_XFB_CLIP_AND_CULL) ? static_cast<deUint32>(6u * sizeof(float))
1080 const deUint32 numPoints = m_parameters.bufferSize / perVertexDataSize;
1082 VK_CHECK(vk.bindBufferMemory(device, *tfBuf, tfBufAllocation->getMemory(), tfBufAllocation->getOffset()));
1084 beginCommandBuffer(vk, *cmdBuffer);
1086 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
1088 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1090 vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0, m_parameters.partCount, &tfBufArray[0], &tfBufBindingOffsets[0], &tfBufBindingSizes[0]);
1092 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1094 vk.cmdDraw(*cmdBuffer, numPoints, 1u, 0u, 0u);
1096 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1098 endRenderPass(vk, *cmdBuffer);
1100 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &tfMemoryBarrier, 0u, DE_NULL, 0u, DE_NULL);
1102 endCommandBuffer(vk, *cmdBuffer);
1103 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1105 verifyTransformFeedbackBuffer(tfBufAllocation, tfBufBindingOffsets[m_parameters.partCount - 1], numPoints * perVertexDataSize);
1107 return tcu::TestStatus::pass("Pass");
1110 class TransformFeedbackMultistreamTestInstance : public TransformFeedbackTestInstance
1113 TransformFeedbackMultistreamTestInstance (Context& context, const TestParameters& parameters);
1116 std::vector<VkDeviceSize> generateSizesList (const size_t bufBytes, const size_t chunkCount);
1117 void verifyTransformFeedbackBuffer (const MovePtr<Allocation>& bufAlloc, const deUint32 bufBytes);
1118 tcu::TestStatus iterate (void);
1121 TransformFeedbackMultistreamTestInstance::TransformFeedbackMultistreamTestInstance (Context& context, const TestParameters& parameters)
1122 : TransformFeedbackTestInstance (context, parameters)
1124 const InstanceInterface& vki = m_context.getInstanceInterface();
1125 const VkPhysicalDevice physDevice = m_context.getPhysicalDevice();
1126 const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(vki, physDevice);
1127 const VkPhysicalDeviceTransformFeedbackFeaturesEXT& transformFeedbackFeatures = m_context.getTransformFeedbackFeaturesEXT();
1128 const deUint32 streamsSupported = m_transformFeedbackProperties.maxTransformFeedbackStreams;
1129 const deUint32 streamsRequired = m_parameters.streamId + 1;
1130 const deUint32 tfBuffersSupported = m_transformFeedbackProperties.maxTransformFeedbackBuffers;
1131 const deUint32 tfBuffersRequired = m_parameters.partCount;
1132 const deUint32 bytesPerVertex = m_parameters.bufferSize / m_parameters.partCount;
1133 const deUint32 tfStreamDataSizeSupported = m_transformFeedbackProperties.maxTransformFeedbackStreamDataSize;
1134 const deUint32 tfBufferDataSizeSupported = m_transformFeedbackProperties.maxTransformFeedbackBufferDataSize;
1135 const deUint32 tfBufferDataStrideSupported = m_transformFeedbackProperties.maxTransformFeedbackBufferDataStride;
1137 DE_ASSERT(m_parameters.partCount == 2u);
1139 if (!features.geometryShader)
1140 TCU_THROW(NotSupportedError, "Missing feature: geometryShader");
1142 if (transformFeedbackFeatures.geometryStreams == DE_FALSE)
1143 TCU_THROW(NotSupportedError, "geometryStreams feature is not supported");
1145 if (streamsSupported < streamsRequired)
1146 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackStreams=" + de::toString(streamsSupported) + ", while test requires " + de::toString(streamsRequired)).c_str());
1148 if (tfBuffersSupported < tfBuffersRequired)
1149 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBuffers=" + de::toString(tfBuffersSupported) + ", while test requires " + de::toString(tfBuffersRequired)).c_str());
1151 if (tfStreamDataSizeSupported < bytesPerVertex)
1152 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackStreamDataSize=" + de::toString(tfStreamDataSizeSupported) + ", while test requires " + de::toString(bytesPerVertex)).c_str());
1154 if (tfBufferDataSizeSupported < bytesPerVertex)
1155 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBufferDataSize=" + de::toString(tfBufferDataSizeSupported) + ", while test requires " + de::toString(bytesPerVertex)).c_str());
1157 if (tfBufferDataStrideSupported < bytesPerVertex)
1158 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBufferDataStride=" + de::toString(tfBufferDataStrideSupported) + ", while test requires " + de::toString(bytesPerVertex)).c_str());
1161 std::vector<VkDeviceSize> TransformFeedbackMultistreamTestInstance::generateSizesList (const size_t bufBytes, const size_t chunkCount)
1163 const VkDeviceSize chunkSize = bufBytes / chunkCount;
1164 std::vector<VkDeviceSize> result (chunkCount, chunkSize);
1166 DE_ASSERT(chunkSize * chunkCount == bufBytes);
1167 DE_ASSERT(bufBytes <= MINIMUM_TF_BUFFER_SIZE);
1168 DE_ASSERT(bufBytes % sizeof(deUint32) == 0);
1169 DE_ASSERT(chunkCount > 0);
1170 DE_ASSERT(result.size() == chunkCount);
1175 void TransformFeedbackMultistreamTestInstance::verifyTransformFeedbackBuffer (const MovePtr<Allocation>& bufAlloc, const deUint32 bufBytes)
1177 const DeviceInterface& vk = m_context.getDeviceInterface();
1178 const VkDevice device = m_context.getDevice();
1180 invalidateAlloc(vk, device, *bufAlloc);
1182 const deUint32 numPoints = static_cast<deUint32>(bufBytes / sizeof(deUint32));
1183 const float* tfData = (float*)bufAlloc->getHostPtr();
1185 for (deUint32 i = 0; i < numPoints; ++i)
1186 if (tfData[i] != float(i))
1187 TCU_FAIL(std::string("Failed at item ") + de::toString(float(i)) + " received:" + de::toString(tfData[i]) + " expected:" + de::toString(i));
1190 tcu::TestStatus TransformFeedbackMultistreamTestInstance::iterate (void)
1192 const DeviceInterface& vk = m_context.getDeviceInterface();
1193 const VkDevice device = m_context.getDevice();
1194 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1195 const VkQueue queue = m_context.getUniversalQueue();
1196 Allocator& allocator = m_context.getDefaultAllocator();
1198 const Unique<VkRenderPass> renderPass (makeRenderPass (vk, device, VK_FORMAT_UNDEFINED));
1200 const Unique<VkShaderModule> vertexModule (createShaderModule (vk, device, m_context.getBinaryCollection().get("vert"), 0u));
1201 const Unique<VkShaderModule> geomModule (createShaderModule (vk, device, m_context.getBinaryCollection().get("geom"), 0u));
1203 const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, 0u, DE_NULL, m_imageExtent2D.width, m_imageExtent2D.height));
1204 const Unique<VkPipelineLayout> pipelineLayout (TransformFeedback::makePipelineLayout (vk, device));
1205 const Unique<VkPipeline> pipeline (makeGraphicsPipeline (vk, device, *pipelineLayout, *renderPass, *vertexModule, DE_NULL, DE_NULL, *geomModule, DE_NULL, m_imageExtent2D, 0u, &m_parameters.streamId));
1206 const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1207 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1209 const VkBufferCreateInfo tfBufCreateInfo = makeBufferCreateInfo(m_parameters.bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT);
1210 const Move<VkBuffer> tfBuf = createBuffer(vk, device, &tfBufCreateInfo);
1211 const std::vector<VkBuffer> tfBufArray = std::vector<VkBuffer>(m_parameters.partCount, *tfBuf);
1212 const MovePtr<Allocation> tfBufAllocation = allocator.allocate(getBufferMemoryRequirements(vk, device, *tfBuf), MemoryRequirement::HostVisible);
1213 const VkMemoryBarrier tfMemoryBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT, VK_ACCESS_HOST_READ_BIT);
1214 const std::vector<VkDeviceSize> tfBufBindingSizes = generateSizesList(m_parameters.bufferSize, m_parameters.partCount);
1215 const std::vector<VkDeviceSize> tfBufBindingOffsets = generateOffsetsList(tfBufBindingSizes);
1217 VK_CHECK(vk.bindBufferMemory(device, *tfBuf, tfBufAllocation->getMemory(), tfBufAllocation->getOffset()));
1219 beginCommandBuffer(vk, *cmdBuffer);
1221 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
1223 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1225 vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0u, m_parameters.partCount, &tfBufArray[0], &tfBufBindingOffsets[0], &tfBufBindingSizes[0]);
1227 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1229 vk.cmdDraw(*cmdBuffer, 1u, 1u, 0u, 0u);
1231 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1233 endRenderPass(vk, *cmdBuffer);
1235 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &tfMemoryBarrier, 0u, DE_NULL, 0u, DE_NULL);
1237 endCommandBuffer(vk, *cmdBuffer);
1238 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1240 verifyTransformFeedbackBuffer(tfBufAllocation, m_parameters.bufferSize);
1242 return tcu::TestStatus::pass("Pass");
1245 class TransformFeedbackStreamsTestInstance : public TransformFeedbackTestInstance
1248 TransformFeedbackStreamsTestInstance (Context& context, const TestParameters& parameters);
1251 tcu::TestStatus iterate (void);
1252 bool verifyImage (const VkFormat imageFormat, const VkExtent2D& size, const void* resultData);
1255 TransformFeedbackStreamsTestInstance::TransformFeedbackStreamsTestInstance (Context& context, const TestParameters& parameters)
1256 : TransformFeedbackTestInstance (context, parameters)
1258 const InstanceInterface& vki = m_context.getInstanceInterface();
1259 const VkPhysicalDevice physDevice = m_context.getPhysicalDevice();
1260 const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(vki, physDevice);
1261 const VkPhysicalDeviceTransformFeedbackFeaturesEXT& transformFeedbackFeatures = m_context.getTransformFeedbackFeaturesEXT();
1262 const deUint32 streamsSupported = m_transformFeedbackProperties.maxTransformFeedbackStreams;
1263 const deUint32 streamsRequired = m_parameters.streamId + 1;
1264 const bool geomPointSizeRequired = m_parameters.testType == TEST_TYPE_STREAMS_POINTSIZE;
1266 if (!features.geometryShader)
1267 TCU_THROW(NotSupportedError, "Missing feature: geometryShader");
1269 if (transformFeedbackFeatures.geometryStreams == DE_FALSE)
1270 TCU_THROW(NotSupportedError, "geometryStreams feature is not supported");
1272 if (m_transformFeedbackProperties.transformFeedbackRasterizationStreamSelect == DE_FALSE)
1273 TCU_THROW(NotSupportedError, "transformFeedbackRasterizationStreamSelect feature is not supported");
1275 if (streamsSupported < streamsRequired)
1276 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackStreams=" + de::toString(streamsSupported) + ", while test requires " + de::toString(streamsRequired)).c_str());
1278 if (geomPointSizeRequired && !features.shaderTessellationAndGeometryPointSize)
1279 TCU_THROW(NotSupportedError, "shaderTessellationAndGeometryPointSize feature is not supported");
1282 bool TransformFeedbackStreamsTestInstance::verifyImage (const VkFormat imageFormat, const VkExtent2D& size, const void* resultData)
1284 const tcu::RGBA magentaRGBA (tcu::RGBA(0xFF, 0x00, 0xFF, 0xFF));
1285 const tcu::Vec4 magenta (magentaRGBA.toVec());
1286 const tcu::Vec4 black (tcu::RGBA::black().toVec());
1287 const tcu::TextureFormat textureFormat (mapVkFormat(imageFormat));
1288 const int dataSize (size.width * size.height * textureFormat.getPixelSize());
1289 tcu::TextureLevel referenceImage (textureFormat, size.width, size.height);
1290 tcu::PixelBufferAccess referenceAccess (referenceImage.getAccess());
1292 // Generate reference image
1293 if (m_parameters.testType == TEST_TYPE_STREAMS)
1295 for (int y = 0; y < referenceImage.getHeight(); ++y)
1297 const tcu::Vec4& validColor = y < referenceImage.getHeight() / 2 ? black : magenta;
1299 for (int x = 0; x < referenceImage.getWidth(); ++x)
1300 referenceAccess.setPixel(validColor, x, y);
1304 if (m_parameters.testType == TEST_TYPE_STREAMS_CLIPDISTANCE || m_parameters.testType == TEST_TYPE_STREAMS_CULLDISTANCE)
1306 for (int y = 0; y < referenceImage.getHeight(); ++y)
1307 for (int x = 0; x < referenceImage.getWidth(); ++x)
1309 const tcu::Vec4& validColor = (y >= referenceImage.getHeight() / 2) && (x >= referenceImage.getWidth() / 2) ? magenta : black;
1311 referenceAccess.setPixel(validColor, x, y);
1315 if (m_parameters.testType == TEST_TYPE_STREAMS_POINTSIZE)
1317 const int pointSize = static_cast<int>(m_parameters.pointSize);
1318 const tcu::Vec4& validColor = black;
1320 for (int y = 0; y < referenceImage.getHeight(); ++y)
1321 for (int x = 0; x < referenceImage.getWidth(); ++x)
1322 referenceAccess.setPixel(validColor, x, y);
1324 referenceAccess.setPixel(magenta, (1 + referenceImage.getWidth()) / 4 - 1, (referenceImage.getHeight() * 3) / 4 - 1);
1326 for (int y = 0; y < pointSize; ++y)
1327 for (int x = 0; x < pointSize; ++x)
1328 referenceAccess.setPixel(magenta, x + (referenceImage.getWidth() * 3) / 4 - 1, y + (referenceImage.getHeight() * 3) / 4 - 1);
1331 if (deMemCmp(resultData, referenceAccess.getDataPtr(), dataSize) != 0)
1333 const tcu::ConstPixelBufferAccess resultImage (textureFormat, size.width, size.height, 1, resultData);
1336 ok = tcu::intThresholdCompare(m_context.getTestContext().getLog(), "Image comparison", "", referenceAccess, resultImage, tcu::UVec4(1), tcu::COMPARE_LOG_RESULT);
1344 tcu::TestStatus TransformFeedbackStreamsTestInstance::iterate (void)
1346 const DeviceInterface& vk = m_context.getDeviceInterface();
1347 const VkDevice device = m_context.getDevice();
1348 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1349 const VkQueue queue = m_context.getUniversalQueue();
1350 Allocator& allocator = m_context.getDefaultAllocator();
1352 const Unique<VkRenderPass> renderPass (makeRenderPass (vk, device, VK_FORMAT_R8G8B8A8_UNORM));
1354 const Unique<VkShaderModule> vertModule (createShaderModule (vk, device, m_context.getBinaryCollection().get("vert"), 0u));
1355 const Unique<VkShaderModule> geomModule (createShaderModule (vk, device, m_context.getBinaryCollection().get("geom"), 0u));
1356 const Unique<VkShaderModule> fragModule (createShaderModule (vk, device, m_context.getBinaryCollection().get("frag"), 0u));
1358 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
1359 const VkImageUsageFlags imageUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1360 const tcu::RGBA clearColor (tcu::RGBA::black());
1361 const VkImageSubresourceRange colorSubresRange (makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u));
1362 const VkDeviceSize colorBufferSize (m_imageExtent2D.width * m_imageExtent2D.height * tcu::getPixelSize(mapVkFormat(colorFormat)));
1363 const Unique<VkImage> colorImage (makeImage (vk, device, makeImageCreateInfo(0u, VK_IMAGE_TYPE_2D, colorFormat, m_imageExtent2D, 1u, imageUsageFlags)));
1364 const UniquePtr<Allocation> colorImageAlloc (bindImage (vk, device, allocator, *colorImage, MemoryRequirement::Any));
1365 const Unique<VkImageView> colorAttachment (makeImageView (vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresRange));
1366 const Unique<VkBuffer> colorBuffer (makeBuffer (vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1367 const UniquePtr<Allocation> colorBufferAlloc (bindBuffer (vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
1369 const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, *colorAttachment, m_imageExtent2D.width, m_imageExtent2D.height));
1370 const Unique<VkPipelineLayout> pipelineLayout (TransformFeedback::makePipelineLayout (vk, device));
1371 const Unique<VkPipeline> pipeline (makeGraphicsPipeline (vk, device, *pipelineLayout, *renderPass, *vertModule, DE_NULL, DE_NULL, *geomModule, *fragModule, m_imageExtent2D, 0u, &m_parameters.streamId));
1372 const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1373 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1375 const VkImageMemoryBarrier preCopyBarrier = makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
1376 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1377 *colorImage, colorSubresRange);
1378 const VkBufferImageCopy region = makeBufferImageCopy(makeExtent3D(m_imageExtent2D.width, m_imageExtent2D.height, 1u),
1379 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u));
1380 const VkBufferMemoryBarrier postCopyBarrier = makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *colorBuffer, 0ull, VK_WHOLE_SIZE);
1382 beginCommandBuffer(vk, *cmdBuffer);
1384 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D), clearColor.toVec());
1386 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1388 vk.cmdDraw(*cmdBuffer, 2u, 1u, 0u, 0u);
1390 endRenderPass(vk, *cmdBuffer);
1392 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &preCopyBarrier);
1393 vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, ®ion);
1394 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &postCopyBarrier, DE_NULL, 0u);
1396 endCommandBuffer(vk, *cmdBuffer);
1397 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1399 if (!verifyImage(colorFormat, m_imageExtent2D, colorBufferAlloc->getHostPtr()))
1400 return tcu::TestStatus::fail("Fail");
1402 return tcu::TestStatus::pass("Pass");
1405 class TransformFeedbackIndirectDrawTestInstance : public TransformFeedbackTestInstance
1408 TransformFeedbackIndirectDrawTestInstance (Context& context, const TestParameters& parameters);
1411 tcu::TestStatus iterate (void);
1412 bool verifyImage (const VkFormat imageFormat, const VkExtent2D& size, const void* resultData);
1415 TransformFeedbackIndirectDrawTestInstance::TransformFeedbackIndirectDrawTestInstance (Context& context, const TestParameters& parameters)
1416 : TransformFeedbackTestInstance (context, parameters)
1418 const InstanceInterface& vki = m_context.getInstanceInterface();
1419 const VkPhysicalDevice physDevice = m_context.getPhysicalDevice();
1420 const VkPhysicalDeviceLimits limits = getPhysicalDeviceProperties(vki, physDevice).limits;
1421 const deUint32 tfBufferDataSizeSupported = m_transformFeedbackProperties.maxTransformFeedbackBufferDataSize;
1422 const deUint32 tfBufferDataStrideSupported = m_transformFeedbackProperties.maxTransformFeedbackBufferDataStride;
1424 if (m_transformFeedbackProperties.transformFeedbackDraw == DE_FALSE)
1425 TCU_THROW(NotSupportedError, "transformFeedbackDraw feature is not supported");
1427 if (limits.maxVertexInputBindingStride < m_parameters.vertexStride)
1428 TCU_THROW(NotSupportedError, std::string("maxVertexInputBindingStride=" + de::toString(limits.maxVertexInputBindingStride) + ", while test requires " + de::toString(m_parameters.vertexStride)).c_str());
1430 if (tfBufferDataSizeSupported < m_parameters.vertexStride)
1431 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBufferDataSize=" + de::toString(tfBufferDataSizeSupported) + ", while test requires " + de::toString(m_parameters.vertexStride)).c_str());
1433 if (tfBufferDataStrideSupported < m_parameters.vertexStride)
1434 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBufferDataStride=" + de::toString(tfBufferDataStrideSupported) + ", while test requires " + de::toString(m_parameters.vertexStride)).c_str());
1437 bool TransformFeedbackIndirectDrawTestInstance::verifyImage (const VkFormat imageFormat, const VkExtent2D& size, const void* resultData)
1439 const tcu::Vec4 white (tcu::RGBA::white().toVec());
1440 const tcu::TextureFormat textureFormat (mapVkFormat(imageFormat));
1441 const int dataSize (size.width * size.height * textureFormat.getPixelSize());
1442 tcu::TextureLevel referenceImage (textureFormat, size.width, size.height);
1443 tcu::PixelBufferAccess referenceAccess (referenceImage.getAccess());
1445 // Generate reference image
1446 for (int y = 0; y < referenceImage.getHeight(); ++y)
1447 for (int x = 0; x < referenceImage.getWidth(); ++x)
1448 referenceAccess.setPixel(white, x, y);
1450 if (deMemCmp(resultData, referenceAccess.getDataPtr(), dataSize) != 0)
1452 const tcu::ConstPixelBufferAccess resultImage (textureFormat, size.width, size.height, 1, resultData);
1455 ok = tcu::intThresholdCompare(m_context.getTestContext().getLog(), "Image comparison", "", referenceAccess, resultImage, tcu::UVec4(1), tcu::COMPARE_LOG_RESULT);
1463 tcu::TestStatus TransformFeedbackIndirectDrawTestInstance::iterate (void)
1465 const DeviceInterface& vk = m_context.getDeviceInterface();
1466 const VkDevice device = m_context.getDevice();
1467 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1468 const VkQueue queue = m_context.getUniversalQueue();
1469 Allocator& allocator = m_context.getDefaultAllocator();
1471 const Unique<VkRenderPass> renderPass (makeRenderPass (vk, device, VK_FORMAT_R8G8B8A8_UNORM));
1473 const Unique<VkShaderModule> vertModule (createShaderModule (vk, device, m_context.getBinaryCollection().get("vert"), 0u));
1474 const Unique<VkShaderModule> fragModule (createShaderModule (vk, device, m_context.getBinaryCollection().get("frag"), 0u));
1476 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
1477 const VkImageUsageFlags imageUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1478 const tcu::RGBA clearColor (tcu::RGBA::black());
1479 const VkImageSubresourceRange colorSubresRange (makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u));
1480 const VkDeviceSize colorBufferSize (m_imageExtent2D.width * m_imageExtent2D.height * tcu::getPixelSize(mapVkFormat(colorFormat)));
1481 const Unique<VkImage> colorImage (makeImage (vk, device, makeImageCreateInfo(0u, VK_IMAGE_TYPE_2D, colorFormat, m_imageExtent2D, 1u, imageUsageFlags)));
1482 const UniquePtr<Allocation> colorImageAlloc (bindImage (vk, device, allocator, *colorImage, MemoryRequirement::Any));
1483 const Unique<VkImageView> colorAttachment (makeImageView (vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresRange));
1484 const Unique<VkBuffer> colorBuffer (makeBuffer (vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1485 const UniquePtr<Allocation> colorBufferAlloc (bindBuffer (vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
1487 const deUint32 vertexCount = 6u;
1488 const VkDeviceSize vertexBufferSize = vertexCount * m_parameters.vertexStride;
1489 const VkBufferUsageFlags vertexBufferUsage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
1490 const Unique<VkBuffer> vertexBuffer (makeBuffer (vk, device, vertexBufferSize, vertexBufferUsage));
1491 const UniquePtr<Allocation> vertexBufferAlloc (bindBuffer (vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
1492 const VkDeviceSize vertexBufferOffset (0u);
1493 const float vertexBufferVals[] =
1495 -1.0f, -1.0f, 0.0f, 1.0f,
1496 -1.0f, +1.0f, 0.0f, 1.0f,
1497 +1.0f, -1.0f, 0.0f, 1.0f,
1498 -1.0f, +1.0f, 0.0f, 1.0f,
1499 +1.0f, -1.0f, 0.0f, 1.0f,
1500 +1.0f, +1.0f, 0.0f, 1.0f,
1503 const deUint32 counterBufferValue = m_parameters.vertexStride * vertexCount;
1504 const VkDeviceSize counterBufferSize = sizeof(counterBufferValue);
1505 const VkBufferUsageFlags counterBufferUsage = VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
1506 const Unique<VkBuffer> counterBuffer (makeBuffer (vk, device, counterBufferSize, counterBufferUsage));
1507 const UniquePtr<Allocation> counterBufferAlloc (bindBuffer (vk, device, allocator, *counterBuffer, MemoryRequirement::HostVisible));
1509 const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, *colorAttachment, m_imageExtent2D.width, m_imageExtent2D.height));
1510 const Unique<VkPipelineLayout> pipelineLayout (TransformFeedback::makePipelineLayout (vk, device));
1511 const Unique<VkPipeline> pipeline (makeGraphicsPipeline (vk, device, *pipelineLayout, *renderPass, *vertModule, DE_NULL, DE_NULL, DE_NULL, *fragModule, m_imageExtent2D, 0u, DE_NULL, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, true));
1512 const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1513 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1515 const VkImageMemoryBarrier preCopyBarrier = makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
1516 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1517 *colorImage, colorSubresRange);
1518 const VkBufferImageCopy region = makeBufferImageCopy(makeExtent3D(m_imageExtent2D.width, m_imageExtent2D.height, 1u),
1519 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u));
1520 const VkBufferMemoryBarrier postCopyBarrier = makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *colorBuffer, 0ull, VK_WHOLE_SIZE);
1522 fillBuffer(vk, device, *counterBufferAlloc, counterBufferSize, &counterBufferValue, counterBufferSize);
1523 fillBuffer(vk, device, *vertexBufferAlloc, vertexBufferSize, vertexBufferVals, sizeof(vertexBufferVals));
1525 beginCommandBuffer(vk, *cmdBuffer);
1527 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D), clearColor.toVec());
1529 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &*vertexBuffer, &vertexBufferOffset);
1531 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1533 vk.cmdDrawIndirectByteCountEXT(*cmdBuffer, 1u, 0u, *counterBuffer, 0u, 0u, m_parameters.vertexStride);
1535 endRenderPass(vk, *cmdBuffer);
1537 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &preCopyBarrier);
1538 vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, ®ion);
1539 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &postCopyBarrier, DE_NULL, 0u);
1541 endCommandBuffer(vk, *cmdBuffer);
1542 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1544 if (!verifyImage(colorFormat, m_imageExtent2D, colorBufferAlloc->getHostPtr()))
1545 return tcu::TestStatus::fail("Fail");
1547 return tcu::TestStatus::pass("Pass");
1550 class TransformFeedbackBackwardDependencyTestInstance : public TransformFeedbackTestInstance
1553 TransformFeedbackBackwardDependencyTestInstance (Context& context, const TestParameters& parameters);
1556 tcu::TestStatus iterate (void);
1557 std::vector<VkDeviceSize> generateSizesList (const size_t bufBytes, const size_t chunkCount);
1560 TransformFeedbackBackwardDependencyTestInstance::TransformFeedbackBackwardDependencyTestInstance (Context& context, const TestParameters& parameters)
1561 : TransformFeedbackTestInstance (context, parameters)
1563 if (m_transformFeedbackProperties.transformFeedbackDraw == DE_FALSE)
1564 TCU_THROW(NotSupportedError, "transformFeedbackDraw feature is not supported");
1567 std::vector<VkDeviceSize> TransformFeedbackBackwardDependencyTestInstance::generateSizesList (const size_t bufBytes, const size_t chunkCount)
1569 const VkDeviceSize chunkSize = bufBytes / chunkCount;
1570 std::vector<VkDeviceSize> result (chunkCount, chunkSize);
1572 DE_ASSERT(chunkSize * chunkCount == bufBytes);
1573 DE_ASSERT(bufBytes <= MINIMUM_TF_BUFFER_SIZE);
1574 DE_ASSERT(bufBytes % sizeof(deUint32) == 0);
1575 DE_ASSERT(chunkCount > 0);
1576 DE_ASSERT(result.size() == chunkCount);
1581 tcu::TestStatus TransformFeedbackBackwardDependencyTestInstance::iterate (void)
1583 const DeviceInterface& vk = m_context.getDeviceInterface();
1584 const VkDevice device = m_context.getDevice();
1585 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1586 const VkQueue queue = m_context.getUniversalQueue();
1587 Allocator& allocator = m_context.getDefaultAllocator();
1589 const Unique<VkShaderModule> vertexModule (createShaderModule (vk, device, m_context.getBinaryCollection().get("vert"), 0u));
1590 const Unique<VkRenderPass> renderPass (TransformFeedback::makeRenderPass (vk, device));
1591 const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, 0u, DE_NULL, m_imageExtent2D.width, m_imageExtent2D.height));
1592 const Unique<VkPipelineLayout> pipelineLayout (TransformFeedback::makePipelineLayout (vk, device));
1593 const Unique<VkPipeline> pipeline (makeGraphicsPipeline (vk, device, *pipelineLayout, *renderPass, *vertexModule, DE_NULL, DE_NULL, DE_NULL, DE_NULL, m_imageExtent2D, 0u));
1594 const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1595 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1597 const VkBufferCreateInfo tfBufCreateInfo = makeBufferCreateInfo(m_parameters.bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT);
1598 const Move<VkBuffer> tfBuf = createBuffer(vk, device, &tfBufCreateInfo);
1599 const MovePtr<Allocation> tfBufAllocation = allocator.allocate(getBufferMemoryRequirements(vk, device, *tfBuf), MemoryRequirement::HostVisible);
1600 const VkMemoryBarrier tfMemoryBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT, VK_ACCESS_HOST_READ_BIT);
1601 const VkDeviceSize tfBufBindingSize = m_parameters.bufferSize;
1602 const VkDeviceSize tfBufBindingOffset = 0ull;
1604 const size_t tfcBufSize = sizeof(deUint32);
1605 const VkBufferCreateInfo tfcBufCreateInfo = makeBufferCreateInfo(tfcBufSize, VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT | VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT);
1606 const Move<VkBuffer> tfcBuf = createBuffer(vk, device, &tfcBufCreateInfo);
1607 const MovePtr<Allocation> tfcBufAllocation = allocator.allocate(getBufferMemoryRequirements(vk, device, *tfcBuf), MemoryRequirement::Any);
1608 const VkDeviceSize tfcBufBindingOffset = 0ull;
1609 const VkMemoryBarrier tfcMemoryBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT, VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT);
1611 const std::vector<VkDeviceSize> chunkSizesList = generateSizesList(m_parameters.bufferSize, m_parameters.partCount);
1612 const std::vector<VkDeviceSize> chunkOffsetsList = generateOffsetsList(chunkSizesList);
1614 VK_CHECK(vk.bindBufferMemory(device, *tfBuf, tfBufAllocation->getMemory(), tfBufAllocation->getOffset()));
1615 VK_CHECK(vk.bindBufferMemory(device, *tfcBuf, tfcBufAllocation->getMemory(), tfcBufAllocation->getOffset()));
1617 DE_ASSERT(m_parameters.partCount == 2u);
1619 beginCommandBuffer(vk, *cmdBuffer);
1621 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
1623 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1625 vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0, 1, &*tfBuf, &tfBufBindingOffset, &tfBufBindingSize);
1628 const deUint32 startValue = static_cast<deUint32>(chunkOffsetsList[0] / sizeof(deUint32));
1629 const deUint32 numPoints = static_cast<deUint32>(chunkSizesList[0] / sizeof(deUint32));
1631 vk.cmdPushConstants(*cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0u, sizeof(startValue), &startValue);
1633 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1635 vk.cmdDraw(*cmdBuffer, numPoints, 1u, 0u, 0u);
1637 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 1, &*tfcBuf, m_parameters.noOffsetArray ? DE_NULL : &tfcBufBindingOffset);
1640 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, 0u, 1u, &tfcMemoryBarrier, 0u, DE_NULL, DE_NULL, 0u);
1643 const deUint32 startValue = static_cast<deUint32>(chunkOffsetsList[1] / sizeof(deUint32));
1645 vk.cmdPushConstants(*cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0u, sizeof(startValue), &startValue);
1647 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 1, &*tfcBuf, m_parameters.noOffsetArray ? DE_NULL : &tfcBufBindingOffset);
1649 vk.cmdDrawIndirectByteCountEXT(*cmdBuffer, 1u, 0u, *tfcBuf, 0u, 0u, 4u);
1651 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1655 endRenderPass(vk, *cmdBuffer);
1657 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &tfMemoryBarrier, 0u, DE_NULL, 0u, DE_NULL);
1659 endCommandBuffer(vk, *cmdBuffer);
1660 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1662 verifyTransformFeedbackBuffer(tfBufAllocation, m_parameters.bufferSize);
1664 return tcu::TestStatus::pass("Pass");
1668 class TransformFeedbackQueryTestInstance : public TransformFeedbackTestInstance
1671 TransformFeedbackQueryTestInstance (Context& context, const TestParameters& parameters);
1674 tcu::TestStatus iterate (void);
1677 TransformFeedbackQueryTestInstance::TransformFeedbackQueryTestInstance (Context& context, const TestParameters& parameters)
1678 : TransformFeedbackTestInstance (context, parameters)
1680 const InstanceInterface& vki = m_context.getInstanceInterface();
1681 const VkPhysicalDevice physDevice = m_context.getPhysicalDevice();
1682 const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(vki, physDevice);
1683 const VkPhysicalDeviceTransformFeedbackFeaturesEXT& transformFeedbackFeatures = m_context.getTransformFeedbackFeaturesEXT();
1684 const deUint32 streamsSupported = m_transformFeedbackProperties.maxTransformFeedbackStreams;
1685 const deUint32 streamsRequired = m_parameters.streamId + 1;
1687 if (!features.geometryShader)
1688 TCU_THROW(NotSupportedError, "Missing feature: geometryShader");
1690 if (streamsRequired > 1 && transformFeedbackFeatures.geometryStreams == DE_FALSE)
1691 TCU_THROW(NotSupportedError, "geometryStreams feature is not supported");
1693 if (streamsSupported < streamsRequired)
1694 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackStreams=" + de::toString(streamsSupported) + ", while test requires " + de::toString(streamsRequired)).c_str());
1696 if (m_transformFeedbackProperties.transformFeedbackQueries == DE_FALSE)
1697 TCU_THROW(NotSupportedError, "transformFeedbackQueries feature is not supported");
1699 if (m_parameters.testType == TEST_TYPE_QUERY_RESET)
1701 // Check VK_EXT_host_query_reset is supported
1702 m_context.requireDeviceFunctionality("VK_EXT_host_query_reset");
1703 if(m_context.getHostQueryResetFeatures().hostQueryReset == VK_FALSE)
1704 throw tcu::NotSupportedError(std::string("Implementation doesn't support resetting queries from the host").c_str());
1708 tcu::TestStatus TransformFeedbackQueryTestInstance::iterate (void)
1710 const DeviceInterface& vk = m_context.getDeviceInterface();
1711 const VkDevice device = m_context.getDevice();
1712 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1713 const VkQueue queue = m_context.getUniversalQueue();
1714 Allocator& allocator = m_context.getDefaultAllocator();
1716 const deUint64 overflowVertices = 3u;
1717 const deUint32 bytesPerVertex = static_cast<deUint32>(4 * sizeof(float));
1718 const deUint64 numVerticesInBuffer = m_parameters.bufferSize / bytesPerVertex;
1719 const deUint64 numVerticesToWrite = numVerticesInBuffer + overflowVertices;
1720 const Unique<VkRenderPass> renderPass (makeRenderPass (vk, device, VK_FORMAT_UNDEFINED));
1722 const Unique<VkShaderModule> vertModule (createShaderModule (vk, device, m_context.getBinaryCollection().get("vert"), 0u));
1723 const Unique<VkShaderModule> geomModule (createShaderModule (vk, device, m_context.getBinaryCollection().get("geom"), 0u));
1725 const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, 0u, DE_NULL, m_imageExtent2D.width, m_imageExtent2D.height));
1726 const Unique<VkPipelineLayout> pipelineLayout (TransformFeedback::makePipelineLayout (vk, device));
1727 const Unique<VkPipeline> pipeline (makeGraphicsPipeline (vk, device, *pipelineLayout, *renderPass, *vertModule, DE_NULL, DE_NULL, *geomModule, DE_NULL, m_imageExtent2D, 0u, &m_parameters.streamId, m_parameters.primTopology));
1728 const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1729 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1731 const deUint32 tfBufferSize = (deUint32)topologyData.at(m_parameters.primTopology).getNumPrimitives(numVerticesInBuffer) * (deUint32)topologyData.at(m_parameters.primTopology).primSize * bytesPerVertex;
1732 const VkBufferCreateInfo tfBufCreateInfo = makeBufferCreateInfo(tfBufferSize, VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT);
1733 const Move<VkBuffer> tfBuf = createBuffer(vk, device, &tfBufCreateInfo);
1734 const MovePtr<Allocation> tfBufAllocation = bindBuffer(vk, device, allocator, *tfBuf, MemoryRequirement::HostVisible);
1735 const VkDeviceSize tfBufBindingSize = tfBufferSize;
1736 const VkDeviceSize tfBufBindingOffset = 0ull;
1738 const size_t queryResultWidth = (m_parameters.query64bits ? sizeof(deUint64) : sizeof(deUint32));
1739 const vk::VkQueryControlFlags queryExtraFlags = (m_parameters.query64bits ? vk::VK_QUERY_RESULT_64_BIT : 0);
1740 const deUint32 queryCountersNumber = 1u;
1741 const deUint32 queryIndex = 0u;
1742 constexpr deUint32 queryResultElements = 2u;
1743 const deUint32 queryDataSize = static_cast<deUint32>(queryResultElements * queryResultWidth);
1744 const VkQueryPoolCreateInfo queryPoolCreateInfo = makeQueryPoolCreateInfo(queryCountersNumber);
1745 const Unique<VkQueryPool> queryPool (createQueryPool(vk, device, &queryPoolCreateInfo));
1747 Move<VkBuffer> queryPoolResultsBuffer;
1748 de::MovePtr<Allocation> queryPoolResultsBufferAlloc;
1750 tcu::TestLog& log = m_context.getTestContext().getLog();
1752 DE_ASSERT(numVerticesInBuffer * bytesPerVertex == m_parameters.bufferSize);
1754 if (m_parameters.testType == TEST_TYPE_QUERY_COPY)
1756 const VkBufferCreateInfo bufferParams =
1758 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
1759 DE_NULL, // const void* pNext;
1760 0u, // VkBufferCreateFlags flags;
1761 queryDataSize, // VkDeviceSize size;
1762 VK_BUFFER_USAGE_TRANSFER_DST_BIT, // VkBufferUsageFlags usage;
1763 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1764 1u, // deUint32 queueFamilyCount;
1765 &queueFamilyIndex // const deUint32* pQueueFamilyIndices;
1768 queryPoolResultsBuffer = createBuffer(vk, device, &bufferParams);
1769 queryPoolResultsBufferAlloc = allocator.allocate(getBufferMemoryRequirements(vk, device, *queryPoolResultsBuffer), MemoryRequirement::HostVisible);
1771 VK_CHECK(vk.bindBufferMemory(device, *queryPoolResultsBuffer, queryPoolResultsBufferAlloc->getMemory(), queryPoolResultsBufferAlloc->getOffset()));
1774 beginCommandBuffer(vk, *cmdBuffer);
1776 if (m_parameters.testType != TEST_TYPE_QUERY_RESET)
1777 vk.cmdResetQueryPool(*cmdBuffer, *queryPool, queryIndex, queryCountersNumber);
1779 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
1781 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1783 vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0u, 1u, &*tfBuf, &tfBufBindingOffset, &tfBufBindingSize);
1785 if (m_parameters.streamId == 0 && m_parameters.streamId0Mode != STREAM_ID_0_BEGIN_QUERY_INDEXED)
1786 vk.cmdBeginQuery(*cmdBuffer, *queryPool, queryIndex, 0u);
1788 vk.cmdBeginQueryIndexedEXT(*cmdBuffer, *queryPool, queryIndex, 0u, m_parameters.streamId);
1790 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1792 vk.cmdDraw(*cmdBuffer, static_cast<deUint32>(numVerticesToWrite), 1u, 0u, 0u);
1794 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1796 if (m_parameters.streamId == 0 && m_parameters.streamId0Mode != STREAM_ID_0_END_QUERY_INDEXED)
1797 vk.cmdEndQuery(*cmdBuffer, *queryPool, queryIndex);
1799 vk.cmdEndQueryIndexedEXT(*cmdBuffer, *queryPool, queryIndex, m_parameters.streamId);
1801 endRenderPass(vk, *cmdBuffer);
1803 if (m_parameters.testType == TEST_TYPE_QUERY_COPY)
1805 vk.cmdCopyQueryPoolResults(*cmdBuffer, *queryPool, queryIndex, queryCountersNumber, *queryPoolResultsBuffer, 0u, queryDataSize, (vk::VK_QUERY_RESULT_WAIT_BIT | queryExtraFlags));
1807 const VkBufferMemoryBarrier bufferBarrier =
1809 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
1810 DE_NULL, // const void* pNext;
1811 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
1812 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask;
1813 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1814 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
1815 *queryPoolResultsBuffer, // VkBuffer buffer;
1816 0ull, // VkDeviceSize offset;
1817 VK_WHOLE_SIZE // VkDeviceSize size;
1819 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL);
1823 endCommandBuffer(vk, *cmdBuffer);
1825 if (m_parameters.testType == TEST_TYPE_QUERY_RESET)
1826 vk.resetQueryPool(device, *queryPool, queryIndex, queryCountersNumber);
1827 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1832 deUint32 elements32[queryResultElements];
1833 deUint64 elements64[queryResultElements];
1836 std::vector<deUint8> queryData (queryDataSize, 0u);
1837 const Results* queryResults = reinterpret_cast<Results*>(queryData.data());
1839 if (m_parameters.testType != TEST_TYPE_QUERY_COPY)
1841 vk.getQueryPoolResults(device, *queryPool, queryIndex, queryCountersNumber, queryDataSize, queryData.data(), queryDataSize, (vk::VK_QUERY_RESULT_WAIT_BIT | queryExtraFlags));
1845 invalidateAlloc(vk, device, *queryPoolResultsBufferAlloc);
1846 deMemcpy(queryData.data(), queryPoolResultsBufferAlloc->getHostPtr(), queryData.size());
1849 // The number of primitives successfully written to the corresponding transform feedback buffer.
1850 const deUint64 numPrimitivesWritten = (m_parameters.query64bits ? queryResults->elements64[0] : queryResults->elements32[0]);
1852 // The number of primitives output to the vertex stream.
1853 const deUint64 numPrimitivesNeeded = (m_parameters.query64bits ? queryResults->elements64[1] : queryResults->elements32[1]);
1855 // Count how many primitives we should get by using selected topology.
1856 const auto primitivesInBuffer = topologyData.at(m_parameters.primTopology).getNumPrimitives(numVerticesInBuffer);
1857 const auto primitivesToWrite = topologyData.at(m_parameters.primTopology).getNumPrimitives(numVerticesToWrite);
1859 log << tcu::TestLog::Message << "Primitives Written / Expected : " << de::toString(numPrimitivesWritten) << " / " << de::toString(primitivesInBuffer) << tcu::TestLog::EndMessage;
1860 log << tcu::TestLog::Message << "Primitives Needed / Expected : " << de::toString(numPrimitivesNeeded) << " / " << de::toString(primitivesToWrite) << tcu::TestLog::EndMessage;
1862 if (numPrimitivesWritten != primitivesInBuffer)
1863 return tcu::TestStatus::fail("numPrimitivesWritten=" + de::toString(numPrimitivesWritten) + " while expected " + de::toString(primitivesInBuffer));
1865 if (numPrimitivesNeeded != primitivesToWrite)
1866 return tcu::TestStatus::fail("numPrimitivesNeeded=" + de::toString(numPrimitivesNeeded) + " while expected " + de::toString(primitivesToWrite));
1869 if (m_parameters.testType == TEST_TYPE_QUERY_RESET)
1871 constexpr deUint32 queryResetElements = queryResultElements + 1; // For the availability bit.
1875 deUint32 elements32[queryResetElements];
1876 deUint64 elements64[queryResetElements];
1879 const deUint32 queryDataAvailSize (static_cast<deUint32>(queryResetElements * queryResultWidth));
1880 std::vector<deUint8> queryData (queryDataAvailSize, 0u);
1881 Results* queryResults = reinterpret_cast<Results*>(queryData.data());
1883 // Initialize values
1884 if (m_parameters.query64bits)
1886 queryResults->elements64[0] = 1u; // numPrimitivesWritten
1887 queryResults->elements64[1] = 1u; // numPrimitivesNeeded
1888 queryResults->elements64[2] = 1u; // Availability bit
1892 queryResults->elements32[0] = 1u; // numPrimitivesWritten
1893 queryResults->elements32[1] = 1u; // numPrimitivesNeeded
1894 queryResults->elements32[2] = 1u; // Availability bit
1897 vk.resetQueryPool(device, *queryPool, queryIndex, queryCountersNumber);
1899 vk::VkResult res = vk.getQueryPoolResults(device, *queryPool, queryIndex, queryCountersNumber, queryDataAvailSize, queryData.data(), queryDataAvailSize, (vk::VK_QUERY_RESULT_WITH_AVAILABILITY_BIT | queryExtraFlags));
1900 const deUint64 numPrimitivesWritten = (m_parameters.query64bits ? queryResults->elements64[0] : queryResults->elements32[0]);
1901 const deUint64 numPrimitivesNeeded = (m_parameters.query64bits ? queryResults->elements64[1] : queryResults->elements32[1]);
1902 const deUint64 availabilityState = (m_parameters.query64bits ? queryResults->elements64[2] : queryResults->elements32[2]);
1904 /* From the Vulkan spec:
1906 * If VK_QUERY_RESULT_WAIT_BIT and VK_QUERY_RESULT_PARTIAL_BIT are both not set then no result values are written to pData
1907 * for queries that are in the unavailable state at the time of the call, and vkGetQueryPoolResults returns VK_NOT_READY.
1908 * However, availability state is still written to pData for those queries if VK_QUERY_RESULT_WITH_AVAILABILITY_BIT is set.
1910 if (res != vk::VK_NOT_READY || availabilityState != 0u)
1911 return tcu::TestStatus::fail("QueryPoolResults incorrect reset");
1912 if (numPrimitivesWritten != 1u || numPrimitivesNeeded != 1u)
1913 return tcu::TestStatus::fail("QueryPoolResults data was modified");
1917 return tcu::TestStatus::pass("Pass");
1920 class TransformFeedbackMultiQueryTestInstance : public TransformFeedbackTestInstance
1923 TransformFeedbackMultiQueryTestInstance (Context& context, const TestParameters& parameters);
1926 std::vector<VkDeviceSize> generateSizesList (const size_t bufBytes, const size_t chunkCount);
1927 void verifyTransformFeedbackBuffer (const MovePtr<Allocation>& bufAlloc, const deUint32 bufBytes, const deUint32 bufOffset, const float expected);
1928 tcu::TestStatus iterate (void);
1931 TransformFeedbackMultiQueryTestInstance::TransformFeedbackMultiQueryTestInstance (Context& context, const TestParameters& parameters)
1932 : TransformFeedbackTestInstance (context, parameters)
1934 const InstanceInterface& vki = m_context.getInstanceInterface();
1935 const VkPhysicalDevice physDevice = m_context.getPhysicalDevice();
1936 const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(vki, physDevice);
1937 const VkPhysicalDeviceTransformFeedbackFeaturesEXT& transformFeedbackFeatures = m_context.getTransformFeedbackFeaturesEXT();
1938 const deUint32 streamsSupported = m_transformFeedbackProperties.maxTransformFeedbackStreams;
1939 const deUint32 streamsRequired = m_parameters.streamId + 1;
1940 const deUint32 tfBuffersSupported = m_transformFeedbackProperties.maxTransformFeedbackBuffers;
1941 const deUint32 tfBuffersRequired = m_parameters.partCount;
1942 const deUint32 bytesPerVertex = m_parameters.bufferSize / m_parameters.partCount;
1943 const deUint32 tfStreamDataSizeSupported = m_transformFeedbackProperties.maxTransformFeedbackStreamDataSize;
1944 const deUint32 tfBufferDataSizeSupported = m_transformFeedbackProperties.maxTransformFeedbackBufferDataSize;
1945 const deUint32 tfBufferDataStrideSupported = m_transformFeedbackProperties.maxTransformFeedbackBufferDataStride;
1947 DE_ASSERT(m_parameters.partCount == 2u);
1949 if (!features.geometryShader)
1950 TCU_THROW(NotSupportedError, "Missing feature: geometryShader");
1952 if (transformFeedbackFeatures.geometryStreams == DE_FALSE)
1953 TCU_THROW(NotSupportedError, "geometryStreams feature is not supported");
1955 if (streamsSupported < streamsRequired)
1956 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackStreams=" + de::toString(streamsSupported) + ", while test requires " + de::toString(streamsRequired)).c_str());
1958 if (tfBuffersSupported < tfBuffersRequired)
1959 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBuffers=" + de::toString(tfBuffersSupported) + ", while test requires " + de::toString(tfBuffersRequired)).c_str());
1961 if (tfStreamDataSizeSupported < bytesPerVertex)
1962 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackStreamDataSize=" + de::toString(tfStreamDataSizeSupported) + ", while test requires " + de::toString(bytesPerVertex)).c_str());
1964 if (tfBufferDataSizeSupported < bytesPerVertex)
1965 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBufferDataSize=" + de::toString(tfBufferDataSizeSupported) + ", while test requires " + de::toString(bytesPerVertex)).c_str());
1967 if (tfBufferDataStrideSupported < bytesPerVertex)
1968 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBufferDataStride=" + de::toString(tfBufferDataStrideSupported) + ", while test requires " + de::toString(bytesPerVertex)).c_str());
1970 if (m_transformFeedbackProperties.transformFeedbackQueries == DE_FALSE)
1971 TCU_THROW(NotSupportedError, "transformFeedbackQueries feature is not supported");
1974 std::vector<VkDeviceSize> TransformFeedbackMultiQueryTestInstance::generateSizesList (const size_t bufBytes, const size_t chunkCount)
1976 const VkDeviceSize chunkSize = bufBytes / chunkCount;
1977 std::vector<VkDeviceSize> result (chunkCount, chunkSize);
1979 DE_ASSERT(chunkSize * chunkCount == bufBytes);
1980 DE_ASSERT(bufBytes <= MINIMUM_TF_BUFFER_SIZE);
1981 DE_ASSERT(bufBytes % sizeof(deUint32) == 0);
1982 DE_ASSERT(chunkCount > 0);
1983 DE_ASSERT(result.size() == chunkCount);
1988 void TransformFeedbackMultiQueryTestInstance::verifyTransformFeedbackBuffer (const MovePtr<Allocation>& bufAlloc, const deUint32 bufBytes, const deUint32 bufOffset, const float expected)
1990 const DeviceInterface& vk = m_context.getDeviceInterface();
1991 const VkDevice device = m_context.getDevice();
1993 invalidateAlloc(vk, device, *bufAlloc);
1995 const deUint32 numPoints = bufBytes / static_cast<deUint32>(sizeof(float));
1996 const deUint8* tfDataRaw = reinterpret_cast<const deUint8*>(bufAlloc->getHostPtr());
1997 const float* tfData = reinterpret_cast<const float*>(&tfDataRaw[bufOffset]);
1999 for (deUint32 i = 0; i < numPoints; ++i)
2000 if (tfData[i] != expected)
2001 TCU_FAIL(std::string("Failed at item ") + de::toString(i) + " received:" + de::toString(tfData[i]) + " expected:" + de::toString(expected));
2004 tcu::TestStatus TransformFeedbackMultiQueryTestInstance::iterate (void)
2006 const DeviceInterface& vk = m_context.getDeviceInterface();
2007 const VkDevice device = m_context.getDevice();
2008 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
2009 const std::vector<deUint32> queueFamilyIndices = { queueFamilyIndex };
2010 const VkQueue queue = m_context.getUniversalQueue();
2011 Allocator& allocator = m_context.getDefaultAllocator();
2013 const Unique<VkRenderPass> renderPass (makeRenderPass (vk, device, VK_FORMAT_UNDEFINED));
2015 const Unique<VkShaderModule> vertModule (createShaderModule (vk, device, m_context.getBinaryCollection().get("vert"), 0u));
2016 const Unique<VkShaderModule> geomModule (createShaderModule (vk, device, m_context.getBinaryCollection().get("geom"), 0u));
2018 const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, 0u, DE_NULL, m_imageExtent2D.width, m_imageExtent2D.height));
2019 const Unique<VkPipelineLayout> pipelineLayout (TransformFeedback::makePipelineLayout (vk, device));
2020 const Unique<VkPipeline> pipeline (makeGraphicsPipeline (vk, device, *pipelineLayout, *renderPass, *vertModule, DE_NULL, DE_NULL, *geomModule, DE_NULL, m_imageExtent2D, 0u));
2021 const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
2022 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
2024 const VkBufferCreateInfo tfBufCreateInfo = makeBufferCreateInfo(m_parameters.bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT);
2025 const Move<VkBuffer> tfBuf = createBuffer(vk, device, &tfBufCreateInfo);
2026 const std::vector<VkBuffer> tfBufArray = std::vector<VkBuffer>(m_parameters.partCount, *tfBuf);
2027 const MovePtr<Allocation> tfBufAllocation = allocator.allocate(getBufferMemoryRequirements(vk, device, *tfBuf), MemoryRequirement::HostVisible);
2028 const VkMemoryBarrier tfMemoryBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT, VK_ACCESS_HOST_READ_BIT);
2029 const std::vector<VkDeviceSize> tfBufBindingSizes = generateSizesList(m_parameters.bufferSize, m_parameters.partCount);
2030 const std::vector<VkDeviceSize> tfBufBindingOffsets = generateOffsetsList(tfBufBindingSizes);
2031 const std::vector<float> tfBufExpectedValues = { 0.5f, 0.5f + float(m_parameters.streamId) };
2032 const deUint32 maxBufferSizeBytes = static_cast<deUint32>(*std::max_element(tfBufBindingSizes.begin(), tfBufBindingSizes.end()));
2033 const deUint32 bytesPerVertex = static_cast<deUint32>(4 * sizeof(float));
2034 const deUint32 numVerticesInBuffer = maxBufferSizeBytes / bytesPerVertex;
2035 const deUint32 numDrawVertices = numVerticesInBuffer / 2;
2037 const deUint32 queryIndex = 0u;
2038 const deUint32 queryCountersNumber = 2u;
2039 const deUint32 queryStride = sizeof(TransformFeedbackQuery);
2040 const deUint32 queryDataSize = queryCountersNumber * queryStride;
2041 const VkQueryPoolCreateInfo queryPoolCreateInfo = makeQueryPoolCreateInfo(queryCountersNumber);
2042 const Unique<VkQueryPool> queryPool (createQueryPool(vk, device, &queryPoolCreateInfo));
2043 const deUint32 queryInvalidCounterValue = 999999u;
2044 std::vector<TransformFeedbackQuery> queryResultData (queryCountersNumber, TransformFeedbackQuery{ queryInvalidCounterValue, queryInvalidCounterValue });
2045 const std::vector<TransformFeedbackQuery> queryExpectedData ({ TransformFeedbackQuery{ numVerticesInBuffer, 3 * numDrawVertices }, TransformFeedbackQuery{ numDrawVertices, numDrawVertices } });
2047 const VkBufferCreateInfo queryBufferCreateInfo = makeBufferCreateInfo(queryDataSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT, queueFamilyIndices);
2048 const Move<VkBuffer> queryPoolResultsBuffer = createBuffer(vk, device, &queryBufferCreateInfo);
2049 const MovePtr<Allocation> queryPoolResultsBufferAlloc = allocator.allocate(getBufferMemoryRequirements(vk, device, *queryPoolResultsBuffer), MemoryRequirement::HostVisible);
2051 vk.resetQueryPool(device, *queryPool, queryIndex, queryCountersNumber);
2053 DE_ASSERT(queryCountersNumber == queryExpectedData.size());
2055 VK_CHECK(vk.bindBufferMemory(device, *queryPoolResultsBuffer, queryPoolResultsBufferAlloc->getMemory(), queryPoolResultsBufferAlloc->getOffset()));
2057 VK_CHECK(vk.bindBufferMemory(device, *tfBuf, tfBufAllocation->getMemory(), tfBufAllocation->getOffset()));
2059 beginCommandBuffer(vk, *cmdBuffer);
2061 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
2063 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
2065 vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0u, m_parameters.partCount, &tfBufArray[0], &tfBufBindingOffsets[0], &tfBufBindingSizes[0]);
2067 vk.cmdBeginQueryIndexedEXT(*cmdBuffer, *queryPool, queryIndex + 0, 0u, 0u);
2068 vk.cmdBeginQueryIndexedEXT(*cmdBuffer, *queryPool, queryIndex + 1, 0u, m_parameters.streamId);
2070 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
2072 vk.cmdDraw(*cmdBuffer, numDrawVertices, 1u, 0u, 0u);
2074 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
2076 vk.cmdEndQueryIndexedEXT(*cmdBuffer, *queryPool, queryIndex + 1, m_parameters.streamId);
2077 vk.cmdEndQueryIndexedEXT(*cmdBuffer, *queryPool, queryIndex + 0, 0);
2079 endRenderPass(vk, *cmdBuffer);
2081 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &tfMemoryBarrier, 0u, DE_NULL, 0u, DE_NULL);
2083 endCommandBuffer(vk, *cmdBuffer);
2084 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
2086 vk.getQueryPoolResults(device, *queryPool, queryIndex, queryCountersNumber, queryDataSize, queryResultData.data(), queryStride, (vk::VK_QUERY_RESULT_WAIT_BIT));
2088 DE_ASSERT(queryResultData.size() == queryCountersNumber && queryExpectedData.size() == queryCountersNumber);
2089 DE_ASSERT(queryCountersNumber > 0);
2091 for (size_t counterNdx = 0; counterNdx < queryCountersNumber; ++counterNdx)
2093 const TransformFeedbackQuery& result = queryResultData[counterNdx];
2094 const TransformFeedbackQuery& expected = queryExpectedData[counterNdx];
2096 DE_ASSERT(expected.written != queryInvalidCounterValue);
2097 DE_ASSERT(expected.attempts != queryInvalidCounterValue);
2099 if (result.written == queryInvalidCounterValue || result.attempts == queryInvalidCounterValue)
2100 return tcu::TestStatus::fail("Query counters read failed");
2102 if (result.written != expected.written)
2104 const std::string comment = "At counter " + de::toString(counterNdx) + " vertices written " + de::toString(result.written) + ", while expected " + de::toString(expected.written);
2106 return tcu::TestStatus::fail(comment.c_str());
2110 if (result.attempts != expected.attempts)
2112 const std::string comment = "At counter " + de::toString(counterNdx) + " attempts committed " + de::toString(result.attempts) + ", while expected " + de::toString(expected.attempts);
2114 return tcu::TestStatus::fail(comment.c_str());
2117 verifyTransformFeedbackBuffer(tfBufAllocation, bytesPerVertex * expected.written, static_cast<deUint32>(tfBufBindingOffsets[counterNdx]), tfBufExpectedValues[counterNdx]);
2120 return tcu::TestStatus::pass("Pass");
2124 class TransformFeedbackTestCase : public vkt::TestCase
2127 TransformFeedbackTestCase (tcu::TestContext &context, const char *name, const char *description, const TestParameters& parameters);
2130 vkt::TestInstance* createInstance (vkt::Context& context) const;
2131 void initPrograms (SourceCollections& programCollection) const;
2133 TestParameters m_parameters;
2136 TransformFeedbackTestCase::TransformFeedbackTestCase (tcu::TestContext &context, const char *name, const char *description, const TestParameters& parameters)
2137 : TestCase (context, name, description)
2138 , m_parameters (parameters)
2142 vkt::TestInstance* TransformFeedbackTestCase::createInstance (vkt::Context& context) const
2144 if (m_parameters.testType == TEST_TYPE_BASIC)
2145 return new TransformFeedbackBasicTestInstance(context, m_parameters);
2147 if (m_parameters.testType == TEST_TYPE_RESUME)
2148 return new TransformFeedbackResumeTestInstance(context, m_parameters);
2150 if (m_parameters.testType == TEST_TYPE_XFB_POINTSIZE)
2151 return new TransformFeedbackBuiltinTestInstance(context, m_parameters);
2153 if (m_parameters.testType == TEST_TYPE_XFB_CLIPDISTANCE)
2154 return new TransformFeedbackBuiltinTestInstance(context, m_parameters);
2156 if (m_parameters.testType == TEST_TYPE_XFB_CULLDISTANCE)
2157 return new TransformFeedbackBuiltinTestInstance(context, m_parameters);
2159 if (m_parameters.testType == TEST_TYPE_XFB_CLIP_AND_CULL)
2160 return new TransformFeedbackBuiltinTestInstance(context, m_parameters);
2162 if (m_parameters.testType == TEST_TYPE_WINDING)
2163 return new TransformFeedbackWindingOrderTestInstance(context, m_parameters);
2165 if (m_parameters.testType == TEST_TYPE_STREAMS)
2166 return new TransformFeedbackStreamsTestInstance(context, m_parameters);
2168 if (m_parameters.testType == TEST_TYPE_STREAMS_POINTSIZE)
2169 return new TransformFeedbackStreamsTestInstance(context, m_parameters);
2171 if (m_parameters.testType == TEST_TYPE_STREAMS_CLIPDISTANCE)
2172 return new TransformFeedbackStreamsTestInstance(context, m_parameters);
2174 if (m_parameters.testType == TEST_TYPE_STREAMS_CULLDISTANCE)
2175 return new TransformFeedbackStreamsTestInstance(context, m_parameters);
2177 if (m_parameters.testType == TEST_TYPE_MULTISTREAMS)
2178 return new TransformFeedbackMultistreamTestInstance(context, m_parameters);
2180 if (m_parameters.testType == TEST_TYPE_DRAW_INDIRECT)
2181 return new TransformFeedbackIndirectDrawTestInstance(context, m_parameters);
2183 if (m_parameters.testType == TEST_TYPE_BACKWARD_DEPENDENCY)
2184 return new TransformFeedbackBackwardDependencyTestInstance(context, m_parameters);
2186 if (m_parameters.testType == TEST_TYPE_QUERY_GET ||
2187 m_parameters.testType == TEST_TYPE_QUERY_COPY ||
2188 m_parameters.testType == TEST_TYPE_QUERY_RESET)
2189 return new TransformFeedbackQueryTestInstance(context, m_parameters);
2191 if (m_parameters.testType == TEST_TYPE_MULTIQUERY)
2192 return new TransformFeedbackMultiQueryTestInstance(context, m_parameters);
2194 TCU_THROW(InternalError, "Specified test type not found");
2197 void TransformFeedbackTestCase::initPrograms (SourceCollections& programCollection) const
2199 const bool vertexShaderOnly = m_parameters.testType == TEST_TYPE_BASIC
2200 || m_parameters.testType == TEST_TYPE_RESUME
2201 || m_parameters.testType == TEST_TYPE_BACKWARD_DEPENDENCY
2202 || (m_parameters.testType == TEST_TYPE_WINDING && m_parameters.primTopology != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST);
2203 const bool requiresFullPipeline = m_parameters.testType == TEST_TYPE_STREAMS
2204 || m_parameters.testType == TEST_TYPE_STREAMS_POINTSIZE
2205 || m_parameters.testType == TEST_TYPE_STREAMS_CULLDISTANCE
2206 || m_parameters.testType == TEST_TYPE_STREAMS_CLIPDISTANCE
2207 || (m_parameters.testType == TEST_TYPE_WINDING && m_parameters.primTopology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST);
2208 const bool xfbBuiltinPipeline = m_parameters.testType == TEST_TYPE_XFB_POINTSIZE
2209 || m_parameters.testType == TEST_TYPE_XFB_CLIPDISTANCE
2210 || m_parameters.testType == TEST_TYPE_XFB_CULLDISTANCE
2211 || m_parameters.testType == TEST_TYPE_XFB_CLIP_AND_CULL;
2213 if (vertexShaderOnly)
2217 std::ostringstream src;
2218 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2220 << "layout(push_constant) uniform pushConstants\n"
2225 << "layout(xfb_buffer = 0, xfb_offset = 0, xfb_stride = 4, location = 0) out uint idx_out;\n"
2227 << "void main(void)\n"
2229 << " idx_out = uInput.start + gl_VertexIndex;\n"
2232 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
2238 if (m_parameters.primTopology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST)
2242 std::ostringstream src;
2243 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2244 << "layout(push_constant) uniform pushConstants\n"
2248 << "void main(void)\n"
2251 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
2254 // Tesselation control shader
2256 std::ostringstream src;
2257 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2258 << "layout(vertices = 3) out;\n"
2259 << "void main (void)\n"
2261 << " gl_TessLevelInner[0] = 2.0;\n" // generate three triangles out of each patch
2262 << " gl_TessLevelOuter[0] = 1.0;\n"
2263 << " gl_TessLevelOuter[1] = 1.0;\n"
2264 << " gl_TessLevelOuter[2] = 1.0;\n"
2266 programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str());
2269 // Tessellation evaluation shader
2271 std::ostringstream src;
2272 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2273 << "layout(triangles, ccw) in;\n"
2274 << "layout(xfb_buffer = 0, xfb_offset = 0, xfb_stride = 4, location = 0) out uint idx_out;\n"
2276 << "void main (void)\n"
2278 << " idx_out = gl_PrimitiveID;\n" // all vertex generated from patch will have its id
2280 programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
2286 if (xfbBuiltinPipeline)
2288 const std::string outputBuiltIn = (m_parameters.testType == TEST_TYPE_XFB_POINTSIZE) ? "float gl_PointSize;\n"
2289 : (m_parameters.testType == TEST_TYPE_XFB_CLIPDISTANCE) ? "float gl_ClipDistance[8];\n"
2290 : (m_parameters.testType == TEST_TYPE_XFB_CULLDISTANCE) ? "float gl_CullDistance[8];\n"
2291 : (m_parameters.testType == TEST_TYPE_XFB_CLIP_AND_CULL) ? "float gl_CullDistance[5];\nfloat gl_ClipDistance[1];\n"
2293 const std::string operationBuiltIn = (m_parameters.testType == TEST_TYPE_XFB_POINTSIZE) ? "gl_PointSize = float(gl_VertexIndex) / 32768.0f;"
2294 : (m_parameters.testType == TEST_TYPE_XFB_CLIPDISTANCE) ? "for (int i=0; i<8; i++) gl_ClipDistance[i] = float(8 * gl_VertexIndex + i) / 32768.0f;"
2295 : (m_parameters.testType == TEST_TYPE_XFB_CULLDISTANCE) ? "for (int i=0; i<8; i++) gl_CullDistance[i] = float(8 * gl_VertexIndex + i) / 32768.0f;"
2296 : (m_parameters.testType == TEST_TYPE_XFB_CLIP_AND_CULL) ? "for (int i=0; i<5; i++) gl_CullDistance[i] = float(6 * gl_VertexIndex + i) / 32768.0f;\n"
2297 "gl_ClipDistance[0] = float(6 * gl_VertexIndex + 5) / 32768.0f;\n"
2302 std::ostringstream src;
2303 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2305 << "layout(xfb_buffer = " << m_parameters.partCount - 1 << ", xfb_offset = 0) out gl_PerVertex\n"
2310 << "void main(void)\n"
2315 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
2321 if (m_parameters.testType == TEST_TYPE_MULTISTREAMS)
2325 std::ostringstream src;
2326 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2328 << "void main(void)\n"
2332 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
2337 const deUint32 s = m_parameters.streamId;
2338 std::ostringstream src;
2342 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2344 << "layout(points) in;\n"
2346 << "layout(points, max_vertices = 32) out;\n"
2347 << "layout(stream = " << 0 << ", xfb_buffer = 0, xfb_offset = 0, xfb_stride = 16, location = 0) out vec4 out0;\n"
2348 << "layout(stream = " << s << ", xfb_buffer = 1, xfb_offset = 0, xfb_stride = 16, location = 1) out vec4 out1;\n"
2350 << "const int counts[] = int[](1, 1, 2, 4, 8);\n"
2352 << "void main(void)\n"
2357 << " // Start 1st buffer from point where 0th buffer ended\n"
2358 << " for (int i = 0; i < counts.length(); i++)\n"
2359 << " c1 = c1 + 4 * counts[i];\n"
2361 << " for (int i = 0; i < counts.length(); i++)\n"
2363 << " const int n0 = counts[i];\n"
2364 << " const int n1 = counts[counts.length() - 1 - i];\n"
2366 << " for (int j = 0; j < n0; j++)\n"
2368 << " out0 = vec4(ivec4(c0, c0 + 1, c0 + 2, c0 + 3));\n"
2369 << " c0 = c0 + 4;\n"
2370 << " EmitStreamVertex(0);\n"
2371 << " EndStreamPrimitive(0);\n"
2374 << " for (int j = 0; j < n1; j++)\n"
2376 << " out1 = vec4(ivec4(c1, c1 + 1, c1 + 2, c1 + 3));\n"
2377 << " c1 = c1 + 4;\n"
2378 << " EmitStreamVertex(" << s << ");\n"
2379 << " EndStreamPrimitive(" << s << ");\n"
2384 programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
2390 if (requiresFullPipeline)
2394 std::ostringstream src;
2395 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2397 << "void main(void)\n"
2401 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
2406 const deUint32 s = m_parameters.streamId;
2407 const bool requirePoints = (m_parameters.testType == TEST_TYPE_STREAMS_POINTSIZE || m_parameters.testType == TEST_TYPE_MULTISTREAMS);
2408 const std::string outputPrimitiveType = requirePoints ? "points" : "triangle_strip";
2409 const std::string outputBuiltIn = (m_parameters.testType == TEST_TYPE_STREAMS_POINTSIZE) ? " float gl_PointSize;\n"
2410 : (m_parameters.testType == TEST_TYPE_STREAMS_CLIPDISTANCE) ? " float gl_ClipDistance[];\n"
2411 : (m_parameters.testType == TEST_TYPE_STREAMS_CULLDISTANCE) ? " float gl_CullDistance[];\n"
2413 std::ostringstream src;
2417 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2419 << "layout(points) in;\n"
2420 << "layout(" << outputPrimitiveType << ", max_vertices = 16) out;\n"
2421 << "layout(stream = " << s << ") out;\n"
2422 << "layout(location = 0) out vec4 color;\n"
2424 << "layout(stream = " << s << ") out gl_PerVertex\n"
2426 << " vec4 gl_Position;\n"
2430 << "void main(void)\n"
2432 << " // Color constants\n"
2433 << " vec4 g = vec4(0.0, 1.0, 0.0, 1.0);\n"
2434 << " vec4 m = vec4(1.0, 0.0, 1.0, 1.0);\n"
2435 << " // Coordinate constants: leftmost column\n"
2436 << " vec4 a = vec4(-1.0,-1.0, 0.0, 1.0);\n"
2437 << " vec4 b = vec4(-1.0, 0.0, 0.0, 1.0);\n"
2438 << " vec4 c = vec4(-1.0, 1.0, 0.0, 1.0);\n"
2439 << " // Coordinate constants: middle column\n"
2440 << " vec4 i = vec4( 0.0,-1.0, 0.0, 1.0);\n"
2441 << " vec4 j = vec4( 0.0, 0.0, 0.0, 1.0);\n"
2442 << " vec4 k = vec4( 0.0, 1.0, 0.0, 1.0);\n"
2443 << " // Coordinate constants: rightmost column\n"
2444 << " vec4 x = vec4( 1.0,-1.0, 0.0, 1.0);\n"
2445 << " vec4 y = vec4( 1.0, 0.0, 0.0, 1.0);\n"
2446 << " vec4 z = vec4( 1.0, 1.0, 0.0, 1.0);\n"
2449 if (m_parameters.testType == TEST_TYPE_STREAMS)
2451 src << " if (gl_PrimitiveIDIn == 0)\n"
2453 << " color = m; gl_Position = b; EmitStreamVertex(" << s << ");\n"
2454 << " color = m; gl_Position = y; EmitStreamVertex(" << s << ");\n"
2455 << " color = m; gl_Position = c; EmitStreamVertex(" << s << ");\n"
2456 << " EndStreamPrimitive(" << s << ");\n"
2460 << " color = m; gl_Position = y; EmitStreamVertex(" << s << ");\n"
2461 << " color = m; gl_Position = c; EmitStreamVertex(" << s << ");\n"
2462 << " color = m; gl_Position = z; EmitStreamVertex(" << s << ");\n"
2463 << " EndStreamPrimitive(" << s << ");\n"
2467 if (m_parameters.testType == TEST_TYPE_STREAMS_POINTSIZE)
2469 const std::string pointSize = "gl_PointSize = " + de::toString(m_parameters.pointSize) + ".0f";
2471 src << " if (gl_PrimitiveIDIn == 0)\n"
2473 << " color = g; gl_Position = (a + j) / 2.0f; gl_PointSize = 1.0f; EmitStreamVertex(0);\n"
2474 << " EndStreamPrimitive(0);\n"
2475 << " color = m; gl_Position = (b + k) / 2.0f; gl_PointSize = 1.0f; EmitStreamVertex(" << s << ");\n"
2476 << " EndStreamPrimitive(" << s << ");\n"
2480 << " color = g; gl_Position = (j + x) / 2.0f; " << pointSize << "; EmitStreamVertex(0);\n"
2481 << " EndStreamPrimitive(0);\n"
2482 << " color = m; gl_Position = (k + y) / 2.0f; " << pointSize << "; EmitStreamVertex(" << s << ");\n"
2483 << " EndStreamPrimitive(" << s << ");\n"
2487 if (m_parameters.testType == TEST_TYPE_STREAMS_CLIPDISTANCE)
2489 src << " if (gl_PrimitiveIDIn == 0)\n"
2491 << " color = m; gl_Position = b; gl_ClipDistance[0] = -1.0; EmitStreamVertex(" << s << ");\n"
2492 << " color = m; gl_Position = c; gl_ClipDistance[0] = -1.0; EmitStreamVertex(" << s << ");\n"
2493 << " color = m; gl_Position = y; gl_ClipDistance[0] = 1.0; EmitStreamVertex(" << s << ");\n"
2494 << " EndStreamPrimitive(" << s << ");\n"
2498 << " color = m; gl_Position = y; gl_ClipDistance[0] = 1.0; EmitStreamVertex(" << s << ");\n"
2499 << " color = m; gl_Position = c; gl_ClipDistance[0] = -1.0; EmitStreamVertex(" << s << ");\n"
2500 << " color = m; gl_Position = z; gl_ClipDistance[0] = 1.0; EmitStreamVertex(" << s << ");\n"
2501 << " EndStreamPrimitive(" << s << ");\n"
2505 if (m_parameters.testType == TEST_TYPE_STREAMS_CULLDISTANCE)
2507 src << " if (gl_PrimitiveIDIn == 0)\n"
2509 << " color = m; gl_Position = b; gl_CullDistance[0] = -1.0; EmitStreamVertex(" << s << ");\n"
2510 << " color = m; gl_Position = c; gl_CullDistance[0] = -1.0; EmitStreamVertex(" << s << ");\n"
2511 << " color = m; gl_Position = j; gl_CullDistance[0] = -1.0; EmitStreamVertex(" << s << ");\n"
2512 << " EndStreamPrimitive(" << s << ");\n"
2513 << " color = m; gl_Position = j; gl_CullDistance[0] = -1.0; EmitStreamVertex(" << s << ");\n"
2514 << " color = m; gl_Position = c; gl_CullDistance[0] = -1.0; EmitStreamVertex(" << s << ");\n"
2515 << " color = m; gl_Position = k; gl_CullDistance[0] = -1.0; EmitStreamVertex(" << s << ");\n"
2516 << " EndStreamPrimitive(" << s << ");\n"
2520 << " color = m; gl_Position = j; gl_CullDistance[0] = 1.0; EmitStreamVertex(" << s << ");\n"
2521 << " color = m; gl_Position = k; gl_CullDistance[0] = 1.0; EmitStreamVertex(" << s << ");\n"
2522 << " color = m; gl_Position = y; gl_CullDistance[0] = 1.0; EmitStreamVertex(" << s << ");\n"
2523 << " EndStreamPrimitive(" << s << ");\n"
2524 << " color = m; gl_Position = y; gl_CullDistance[0] = 1.0; EmitStreamVertex(" << s << ");\n"
2525 << " color = m; gl_Position = k; gl_CullDistance[0] = 1.0; EmitStreamVertex(" << s << ");\n"
2526 << " color = m; gl_Position = z; gl_CullDistance[0] = 1.0; EmitStreamVertex(" << s << ");\n"
2527 << " EndStreamPrimitive(" << s << ");\n"
2533 programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
2538 std::ostringstream src;
2539 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2541 << "layout(location = 0) in vec4 i_color;\n"
2542 << "layout(location = 0) out vec4 o_color;\n"
2544 << "void main(void)\n"
2546 << " o_color = i_color;\n"
2549 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
2555 if (m_parameters.testType == TEST_TYPE_DRAW_INDIRECT)
2559 std::ostringstream src;
2560 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2562 << "layout(location = 0) in vec4 in_position;\n"
2564 << "void main(void)\n"
2566 << " gl_Position = in_position;\n"
2569 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
2574 std::ostringstream src;
2575 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2577 << "layout(location = 0) out vec4 o_color;\n"
2579 << "void main(void)\n"
2581 << " o_color = vec4(1.0, 1.0, 1.0, 1.0);\n"
2584 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
2590 if (m_parameters.testType == TEST_TYPE_QUERY_GET ||
2591 m_parameters.testType == TEST_TYPE_QUERY_COPY ||
2592 m_parameters.testType == TEST_TYPE_QUERY_RESET)
2594 struct TopologyShaderInfo
2597 std::string glslOut;
2598 std::string spirvIn;
2599 std::string spirvOut;
2602 const std::map<VkPrimitiveTopology, TopologyShaderInfo> primitiveNames =
2604 { VK_PRIMITIVE_TOPOLOGY_POINT_LIST , { "points" , "points" , "InputPoints" , "OutputPoints" } },
2605 { VK_PRIMITIVE_TOPOLOGY_LINE_LIST , { "lines" , "line_strip" , "InputLines" , "OutputLineStrip" } },
2606 { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP , { "lines" , "line_strip" , "InputLines" , "OutputLineStrip" } },
2607 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST , { "triangles" , "triangle_strip" , "Triangles" , "OutputTriangleStrip" } },
2608 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP , { "triangles" , "triangle_strip" , "Triangles" , "OutputTriangleStrip" } },
2609 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN , { "triangles" , "triangle_strip" , "Triangles" , "OutputTriangleStrip" } },
2610 { VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY , { "lines_adjacency" , "line_strip" , "InputLinesAdjacency" , "OutputLineStrip" } },
2611 { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY , { "lines_adjacency" , "line_strip" , "InputLinesAdjacency" , "OutputLineStrip" } },
2612 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY , { "triangles_adjacency" , "triangle_strip" , "InputTrianglesAdjacency" , "OutputTriangleStrip" } },
2613 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY , { "triangles_adjacency" , "triangle_strip" , "InputTrianglesAdjacency" , "OutputTriangleStrip" } }
2618 std::ostringstream src;
2619 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2621 << "layout(location = 0) out vec4 out0;\n"
2623 << "void main(void)\n"
2625 << " float n = 4.0 * float(gl_VertexIndex);\n"
2626 << " out0 = vec4(n + 0.0, n + 1.0, n + 2.0, n + 3.0);\n"
2629 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
2633 if (m_parameters.streamId == 0)
2635 std::ostringstream src;
2637 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2639 << "layout(" << primitiveNames.at(m_parameters.primTopology).glslIn << ") in;\n"
2640 << "layout(location = 0) in vec4 in0[];\n"
2642 << "layout(" << primitiveNames.at(m_parameters.primTopology).glslOut << ", max_vertices = " << topologyData.at(m_parameters.primTopology).primSize<< ") out;\n"
2643 << "layout(xfb_buffer = 0, xfb_offset = 0, xfb_stride = 16, location = 0) out vec4 out0;\n"
2645 << "void main(void)\n"
2648 for (deUint32 i = 0; i < topologyData.at(m_parameters.primTopology).primSize; i++)
2650 src << " out0 = in0[" << i << "];\n"
2651 << " EmitVertex();\n";
2654 src << " EndPrimitive();\n"
2657 programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
2661 const deUint32 s = m_parameters.streamId;
2662 std::ostringstream src;
2664 if (m_parameters.testType == TEST_TYPE_QUERY_GET)
2666 // The SPIR-V program below is roughly equivalent to the following GLSL code:
2669 // #extension GL_ARB_enhanced_layouts : require
2671 // layout(points) in;
2672 // layout(location = 0) in vec4 in0[];
2674 // layout(points, max_vertices = 1) out;
2675 // layout(location=0, stream=1, xfb_buffer=0, xfb_stride=16) out OutBlock {
2676 // layout(xfb_offset=0, location=0) vec4 out0;
2681 // outBlock.out0 = in0[0];
2682 // EmitStreamVertex(1);
2683 // EndStreamPrimitive(1);
2686 // However, the stream number has been parametrized and the code generated by glslang has been tuned to move the
2687 // Stream, XfbBuffer and XfbStride decorations to the structure member instead of the block. This allows us to test
2688 // transform feedback decorations on structure members as part of these basic tests.
2690 << "; Version: 1.0\n"
2691 << "; Generator: Khronos Glslang Reference Front End; 10\n"
2694 << " OpCapability Geometry\n"
2695 << " OpCapability TransformFeedback\n"
2696 << " OpCapability GeometryStreams\n"
2697 << " %1 = OpExtInstImport \"GLSL.std.450\"\n"
2698 << " OpMemoryModel Logical GLSL450\n"
2699 << " OpEntryPoint Geometry %main \"main\" %outBlock %in0\n"
2700 << " OpExecutionMode %main Xfb\n"
2701 << " OpExecutionMode %main " << primitiveNames.at(m_parameters.primTopology).spirvIn << "\n"
2702 << " OpExecutionMode %main Invocations 1\n"
2703 << " OpExecutionMode %main " << primitiveNames.at(m_parameters.primTopology).spirvOut << "\n"
2704 << " OpExecutionMode %main OutputVertices " << topologyData.at(m_parameters.primTopology).primSize << "\n"
2705 << " OpSource GLSL 450\n"
2706 << " OpSourceExtension \"GL_ARB_enhanced_layouts\"\n"
2707 << " OpName %main \"main\"\n"
2708 << " OpName %OutBlock \"OutBlock\"\n"
2709 << " OpMemberName %OutBlock 0 \"out0\"\n"
2710 << " OpName %outBlock \"outBlock\"\n"
2711 << " OpName %in0 \"in0\"\n"
2712 << " OpMemberDecorate %OutBlock 0 Location 0\n"
2713 << " OpMemberDecorate %OutBlock 0 Offset 0\n"
2714 // These Stream, XfbBuffer and XfbStride decorations have been moved to the struct member.
2715 << " OpMemberDecorate %OutBlock 0 Stream " << s << "\n"
2716 << " OpMemberDecorate %OutBlock 0 XfbBuffer 0\n"
2717 << " OpMemberDecorate %OutBlock 0 XfbStride 16\n"
2718 << " OpDecorate %OutBlock Block\n"
2719 // The decorations mentioned above were using OpDecorate and assigned to %outBlock itself here.
2720 << " OpDecorate %in0 Location 0\n"
2721 << " %void = OpTypeVoid\n"
2722 << " %3 = OpTypeFunction %void\n"
2723 << " %float = OpTypeFloat 32\n"
2724 << " %v4float = OpTypeVector %float 4\n"
2725 << " %OutBlock = OpTypeStruct %v4float\n"
2726 << "%_ptr_Output_OutBlock = OpTypePointer Output %OutBlock\n"
2727 << " %outBlock = OpVariable %_ptr_Output_OutBlock Output\n"
2728 << " %int = OpTypeInt 32 1\n"
2729 << " %int_0 = OpConstant %int 0\n";
2731 for (deUint32 i = 1; i < topologyData.at(m_parameters.primTopology).primSize + 1; i++)
2733 src << "%int_" << i << " = OpConstant %int " << i << "\n";
2736 src << " %uint = OpTypeInt 32 0\n"
2737 << " %uint_0 = OpConstant %uint " << topologyData.at(m_parameters.primTopology).primSize << "\n"
2738 << "%_arr_v4float_uint_0 = OpTypeArray %v4float %uint_0\n"
2739 << "%_ptr_Input__arr_v4float_uint_0 = OpTypePointer Input %_arr_v4float_uint_0\n"
2740 << " %in0 = OpVariable %_ptr_Input__arr_v4float_uint_0 Input\n"
2741 << "%_ptr_Input_v4float = OpTypePointer Input %v4float\n"
2742 << "%_ptr_Output_v4float = OpTypePointer Output %v4float\n"
2743 << " %streamNum = OpConstant %int " << s << "\n"
2744 << " %main = OpFunction %void None %3\n"
2745 << " %5 = OpLabel\n";
2747 for (deUint32 i = 1; i < topologyData.at(m_parameters.primTopology).primSize + 1; i++)
2749 src << "%" << i << "1 = OpAccessChain %_ptr_Input_v4float %in0 %int_" << i << "\n"
2750 << " %" << i << "2 = OpLoad %v4float %" << i << "1\n"
2751 << " %" << i << "3 = OpAccessChain %_ptr_Output_v4float %outBlock %int_0\n"
2752 << " OpStore %" << i << "3 %" << i << "2\n"
2753 << " OpEmitStreamVertex %streamNum\n";
2756 src << " OpEndStreamPrimitive %streamNum\n"
2758 << " OpFunctionEnd\n"
2761 programCollection.spirvAsmSources.add("geom") << src.str();
2765 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2767 << "layout(" << primitiveNames.at(m_parameters.primTopology).glslIn << ") in;\n"
2768 << "layout(location = 0) in vec4 in0[];\n"
2770 << "layout(" << primitiveNames.at(m_parameters.primTopology).glslOut << ", max_vertices = " << topologyData.at(m_parameters.primTopology).primSize << ") out;\n"
2771 << "layout(stream = " << s << ", xfb_buffer = 0, xfb_offset = 0, xfb_stride = 16, location = 0) out vec4 out0;\n"
2773 << "void main(void)\n"
2776 for (deUint32 i = 0; i < topologyData.at(m_parameters.primTopology).primSize; i++)
2778 src << " out0 = in0[" << i << "];\n"
2779 << " EmitStreamVertex(" << s << ");\n";
2782 src << " EndStreamPrimitive(" << s << ");\n"
2785 programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
2792 if (m_parameters.testType == TEST_TYPE_MULTIQUERY)
2796 std::ostringstream src;
2797 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2799 << "layout(location = 0) out ivec4 out0;\n"
2801 << "void main(void)\n"
2803 << " out0 = ivec4(gl_VertexIndex);\n"
2806 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
2811 const deUint32 s = m_parameters.streamId;
2812 std::ostringstream src;
2816 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2818 << "layout(points) in;\n"
2820 << "layout(points, max_vertices = 4) out;\n"
2822 << "layout(stream = " << 0 << ", xfb_buffer = 0, xfb_offset = 0, xfb_stride = 16, location = 0) out vec4 out0;\n"
2823 << "layout(stream = " << s << ", xfb_buffer = 1, xfb_offset = 0, xfb_stride = 16, location = 1) out vec4 out1;\n"
2825 << "void main(void)\n"
2827 << " const int n0 = 3;\n"
2828 << " const int n1 = 1;\n"
2829 << " const float c0 = 0.5f;\n"
2830 << " const float c1 = 0.5f + float(" << s << ");\n"
2832 << " for (int j = 0; j < n0; j++)\n"
2834 << " out0 = vec4(c0);\n"
2835 << " EmitStreamVertex(0);\n"
2836 << " EndStreamPrimitive(0);\n"
2839 << " for (int j = 0; j < n1; j++)\n"
2841 << " out1 = vec4(c1);\n"
2842 << " EmitStreamVertex(" << s << ");\n"
2843 << " EndStreamPrimitive(" << s << ");\n"
2847 programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
2853 DE_ASSERT(0 && "Unknown test");
2856 void createTransformFeedbackSimpleTests(tcu::TestCaseGroup* group)
2859 const deUint32 bufferCounts[] = { 1u, 2u, 4u, 8u };
2860 const deUint32 bufferSizes[] = { 256u, 512u, 128u * 1024u };
2861 const TestType testTypes[] = { TEST_TYPE_BASIC, TEST_TYPE_RESUME, TEST_TYPE_XFB_POINTSIZE, TEST_TYPE_XFB_CLIPDISTANCE, TEST_TYPE_XFB_CULLDISTANCE, TEST_TYPE_XFB_CLIP_AND_CULL };
2862 const std::string testTypeNames[] = { "basic", "resume", "xfb_pointsize", "xfb_clipdistance", "xfb_culldistance", "xfb_clip_and_cull" };
2864 for (deUint32 testTypesNdx = 0; testTypesNdx < DE_LENGTH_OF_ARRAY(testTypes); ++testTypesNdx)
2866 const TestType testType = testTypes[testTypesNdx];
2867 const std::string testName = testTypeNames[testTypesNdx];
2869 for (deUint32 bufferCountsNdx = 0; bufferCountsNdx < DE_LENGTH_OF_ARRAY(bufferCounts); ++bufferCountsNdx)
2871 const deUint32 partCount = bufferCounts[bufferCountsNdx];
2873 for (deUint32 bufferSizesNdx = 0; bufferSizesNdx < DE_LENGTH_OF_ARRAY(bufferSizes); ++bufferSizesNdx)
2875 const deUint32 bufferSize = bufferSizes[bufferSizesNdx];
2876 TestParameters parameters = { testType, bufferSize, partCount, 0u, 0u, 0u, STREAM_ID_0_NORMAL, false, false, VK_PRIMITIVE_TOPOLOGY_POINT_LIST };
2878 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_" + de::toString(partCount) + "_" + de::toString(bufferSize)).c_str(), "Simple Transform Feedback test", parameters));
2879 parameters.streamId0Mode = STREAM_ID_0_BEGIN_QUERY_INDEXED;
2880 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_beginqueryindexed_streamid_0_" + de::toString(partCount) + "_" + de::toString(bufferSize)).c_str(), "Simple Transform Feedback test", parameters));
2881 parameters.streamId0Mode = STREAM_ID_0_END_QUERY_INDEXED;
2882 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_endqueryindexed_streamid_0_" + de::toString(partCount) + "_" + de::toString(bufferSize)).c_str(), "Simple Transform Feedback test", parameters));
2889 const deUint32 bufferCounts[] = { 6u, 8u, 10u, 12u };
2890 const TestType testType = TEST_TYPE_WINDING;
2891 const std::string testName = "winding";
2893 for (const auto& topology : topologyData)
2895 // Note: no need to test POINT_LIST as is tested in many tests.
2896 if (topology.first == VK_PRIMITIVE_TOPOLOGY_POINT_LIST)
2899 for (deUint32 bufferCountsNdx = 0; bufferCountsNdx < DE_LENGTH_OF_ARRAY(bufferCounts); ++bufferCountsNdx)
2901 const deUint32 vertexCount = bufferCounts[bufferCountsNdx];
2903 TestParameters parameters = { testType, 0u, vertexCount, 0u, 0u, 0u, STREAM_ID_0_NORMAL, false, false, topology.first };
2905 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_" + topology.second.topologyName + de::toString(vertexCount)).c_str(), "Topology winding test", parameters));
2911 const deUint32 vertexStrides[] = { 4u, 61u, 127u, 251u, 509u };
2912 const TestType testType = TEST_TYPE_DRAW_INDIRECT;
2913 const std::string testName = "draw_indirect";
2915 for (deUint32 vertexStridesNdx = 0; vertexStridesNdx < DE_LENGTH_OF_ARRAY(vertexStrides); ++vertexStridesNdx)
2917 const deUint32 vertexStrideBytes = static_cast<deUint32>(sizeof(deUint32) * vertexStrides[vertexStridesNdx]);
2918 TestParameters parameters = { testType, 0u, 0u, 0u, 0u, vertexStrideBytes, STREAM_ID_0_NORMAL, false, false, VK_PRIMITIVE_TOPOLOGY_POINT_LIST };
2920 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_" + de::toString(vertexStrideBytes)).c_str(), "Rendering tests with various strides", parameters));
2921 parameters.streamId0Mode = STREAM_ID_0_BEGIN_QUERY_INDEXED;
2922 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_beginqueryindexed_streamid_0_" + de::toString(vertexStrideBytes)).c_str(), "Rendering tests with various strides", parameters));
2923 parameters.streamId0Mode = STREAM_ID_0_END_QUERY_INDEXED;
2924 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_endqueryindexed_streamid_0_" + de::toString(vertexStrideBytes)).c_str(), "Rendering tests with various strides", parameters));
2929 const TestType testType = TEST_TYPE_BACKWARD_DEPENDENCY;
2930 const std::string testName = "backward_dependency";
2931 TestParameters parameters = { testType, 512u, 2u, 0u, 0u, 0u, STREAM_ID_0_NORMAL, false, false, VK_PRIMITIVE_TOPOLOGY_POINT_LIST };
2933 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), testName.c_str(), "Rendering test checks backward pipeline dependency", parameters));
2934 parameters.streamId0Mode = STREAM_ID_0_BEGIN_QUERY_INDEXED;
2935 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_beginqueryindexed_streamid_0").c_str(), "Rendering test checks backward pipeline dependency", parameters));
2936 parameters.streamId0Mode = STREAM_ID_0_END_QUERY_INDEXED;
2937 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_endqueryindexed_streamid_0").c_str(), "Rendering test checks backward pipeline dependency", parameters));
2939 parameters.noOffsetArray = true;
2940 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_no_offset_array").c_str(), "Rendering test checks backward pipeline dependency (using NULL for offset array)", parameters));
2944 const deUint32 usedStreamId[] = { 0u, 1u, 3u, 6u, 14u };
2945 const deUint32 vertexCounts[] = { 6u, 61u, 127u, 251u, 509u }; // Lowest value has to be at least 6. Otherwise the triangles with adjacency can't be generated.
2946 const TestType testType = TEST_TYPE_QUERY_GET;
2947 const std::string testName = "query";
2948 const TestType testTypeCopy = TEST_TYPE_QUERY_COPY;
2949 const std::string testNameCopy = "query_copy";
2950 const TestType testTypeHostQueryReset = TEST_TYPE_QUERY_RESET;
2951 const std::string testNameHostQueryReset = "host_query_reset";
2953 for (const auto& topology : topologyData)
2955 // Currently, we don't test tessellation here.
2956 if (topology.first == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST)
2959 for (const auto& streamCounts : usedStreamId)
2961 const deUint32 streamId = streamCounts;
2963 for (const auto& numVertices : vertexCounts)
2965 for (deUint32 i = 0; i < 2; ++i)
2967 const bool query64Bits = (i == 1);
2968 const std::string widthStr = (query64Bits ? "_64bits" : "_32bits");
2970 deUint32 vertCount = numVertices;
2972 // The number of vertices in original test was 4.
2973 if (topology.first == VK_PRIMITIVE_TOPOLOGY_POINT_LIST && vertCount == 6) vertCount -= 2;
2975 // Round the number of vertices to match the used primitive topology - if necessary.
2976 const deUint32 primitiveCount = (deUint32)topology.second.getNumPrimitives(vertCount);
2977 const deUint32 vertexCount = (deUint32)topology.second.getNumVertices(primitiveCount);
2979 DE_ASSERT(vertexCount > 0);
2981 const deUint32 bytesPerVertex = static_cast<deUint32>(4 * sizeof(float));
2982 const deUint32 bufferSize = bytesPerVertex * vertexCount;
2983 TestParameters parameters = { testType, bufferSize, 0u, streamId, 0u, 0u, STREAM_ID_0_NORMAL, query64Bits, false, topology.first };
2984 const std::string fullTestName = testName + "_" + topology.second.topologyName + de::toString(streamId) + "_" + de::toString(vertexCount) + widthStr;
2985 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), fullTestName.c_str(), "Written primitives query test", parameters));
2987 const TestParameters parametersCopy = { testTypeCopy, bufferSize, 0u, streamId, 0u, 0u, STREAM_ID_0_NORMAL, query64Bits, false, topology.first };
2988 const std::string fullTestNameCopy = testNameCopy + "_" + topology.second.topologyName + de::toString(streamId) + "_" + de::toString(vertexCount) + widthStr;
2989 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), fullTestNameCopy.c_str(), "Written primitives query test", parametersCopy));
2991 const TestParameters parametersHostQueryReset = { testTypeHostQueryReset, bufferSize, 0u, streamId, 0u, 0u, STREAM_ID_0_NORMAL, query64Bits, false, topology.first };
2992 const std::string fullTestNameHostQueryReset = testNameHostQueryReset + "_" + topology.second.topologyName + de::toString(streamId) + "_" + de::toString(vertexCount) + widthStr;
2993 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), fullTestNameHostQueryReset.c_str(), "Written primitives query test", parametersHostQueryReset));
2997 std::string testNameStream0 = fullTestName;
2998 testNameStream0 += "_beginqueryindexed_streamid_0";
2999 parameters.streamId0Mode = STREAM_ID_0_BEGIN_QUERY_INDEXED;
3000 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), testNameStream0.c_str(), "Written primitives query test", parameters));
3001 testNameStream0 = fullTestName;
3002 testNameStream0 += "_endqueryindexed_streamid_0";
3003 parameters.streamId0Mode = STREAM_ID_0_END_QUERY_INDEXED;
3004 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), testNameStream0.c_str(), "Written primitives query test", parameters));
3013 void createTransformFeedbackStreamsSimpleTests (tcu::TestCaseGroup* group)
3015 const deUint32 usedStreamId[] = { 1u, 3u, 6u, 14u };
3016 const TestType testTypes[] = { TEST_TYPE_STREAMS, TEST_TYPE_STREAMS_POINTSIZE, TEST_TYPE_STREAMS_CLIPDISTANCE, TEST_TYPE_STREAMS_CULLDISTANCE };
3017 const std::string testTypeNames[] = { "streams", "streams_pointsize", "streams_clipdistance", "streams_culldistance" };
3019 for (deUint32 testTypesNdx = 0; testTypesNdx < DE_LENGTH_OF_ARRAY(testTypes); ++testTypesNdx)
3021 const TestType testType = testTypes[testTypesNdx];
3022 const std::string testName = testTypeNames[testTypesNdx];
3023 const deUint32 pointSize = (testType == TEST_TYPE_STREAMS_POINTSIZE) ? 2u : 0u;
3025 for (deUint32 streamCountsNdx = 0; streamCountsNdx < DE_LENGTH_OF_ARRAY(usedStreamId); ++streamCountsNdx)
3027 const deUint32 streamId = usedStreamId[streamCountsNdx];
3028 TestParameters parameters = { testType, 0u, 0u, streamId, pointSize, 0u, STREAM_ID_0_NORMAL, false, false, VK_PRIMITIVE_TOPOLOGY_POINT_LIST };
3030 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_" + de::toString(streamId)).c_str(), "Streams usage test", parameters));
3035 const TestType testType = TEST_TYPE_MULTISTREAMS;
3036 const std::string testName = "multistreams";
3038 for (deUint32 bufferCountsNdx = 0; bufferCountsNdx < DE_LENGTH_OF_ARRAY(usedStreamId); ++bufferCountsNdx)
3040 const deUint32 streamId = usedStreamId[bufferCountsNdx];
3041 const deUint32 streamsUsed = 2u;
3042 const deUint32 maxBytesPerVertex = 256u;
3043 const TestParameters parameters = { testType, maxBytesPerVertex * streamsUsed, streamsUsed, streamId, 0u, 0u, STREAM_ID_0_NORMAL, false, false, VK_PRIMITIVE_TOPOLOGY_POINT_LIST };
3045 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_" + de::toString(streamId)).c_str(), "Simultaneous multiple streams usage test", parameters));
3050 const TestType testType = TEST_TYPE_MULTIQUERY;
3051 const std::string testName = "multiquery";
3053 for (deUint32 bufferCountsNdx = 0; bufferCountsNdx < DE_LENGTH_OF_ARRAY(usedStreamId); ++bufferCountsNdx)
3055 const deUint32 streamId = usedStreamId[bufferCountsNdx];
3056 const deUint32 streamsUsed = 2u;
3057 const deUint32 maxBytesPerVertex = 256u;
3058 const TestParameters parameters = { testType, maxBytesPerVertex * streamsUsed, streamsUsed, streamId, 0u, 0u, STREAM_ID_0_NORMAL, false, false, VK_PRIMITIVE_TOPOLOGY_POINT_LIST };
3060 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_" + de::toString(streamId)).c_str(), "Simultaneous multiple queries usage test", parameters));
3065 void createTransformFeedbackAndStreamsSimpleTests (tcu::TestCaseGroup* group)
3067 createTransformFeedbackSimpleTests(group);
3068 createTransformFeedbackStreamsSimpleTests(group);
3072 tcu::TestCaseGroup* createTransformFeedbackSimpleTests (tcu::TestContext& testCtx)
3074 return createTestGroup(testCtx, "simple", "Transform Feedback Simple tests", createTransformFeedbackAndStreamsSimpleTests);
3077 } // TransformFeedback