1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2018 The Khronos Group Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Vulkan Transform Feedback Simple Tests
22 *//*--------------------------------------------------------------------*/
23
24 #include "vktTransformFeedbackSimpleTests.hpp"
25 #include "vktTestGroupUtil.hpp"
26 #include "vktTestCase.hpp"
27
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"
35
36 #include "deUniquePtr.hpp"
37 #include "deRandom.hpp"
38
39 #include "tcuTextureUtil.hpp"
40 #include "tcuVectorUtil.hpp"
41 #include "tcuImageCompare.hpp"
42 #include "tcuRGBA.hpp"
43 #include "tcuTestLog.hpp"
44
45 #include <iostream>
46 #include <functional>
47 #include <set>
48 #include <algorithm>
49
50 namespace vkt
51 {
52 namespace TransformFeedback
53 {
54 namespace
55 {
56 using namespace vk;
57 using de::MovePtr;
58 using de::UniquePtr;
59 using de::SharedPtr;
60
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)))
63
64 enum TestType
65 {
66 TEST_TYPE_BASIC,
67 TEST_TYPE_RESUME,
68 TEST_TYPE_STREAMS,
69 TEST_TYPE_XFB_POINTSIZE,
70 TEST_TYPE_XFB_CLIPDISTANCE,
71 TEST_TYPE_XFB_CULLDISTANCE,
72 TEST_TYPE_XFB_CLIP_AND_CULL,
73 TEST_TYPE_WINDING,
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,
80 TEST_TYPE_QUERY_GET,
81 TEST_TYPE_QUERY_COPY,
82 TEST_TYPE_QUERY_RESET,
83 TEST_TYPE_MULTIQUERY,
84 TEST_TYPE_LAST
85 };
86
87 enum StreamId0Mode
88 {
89 STREAM_ID_0_NORMAL = 0,
90 STREAM_ID_0_BEGIN_QUERY_INDEXED = 1,
91 STREAM_ID_0_END_QUERY_INDEXED = 2,
92 };
93
94 struct TestParameters
95 {
96 TestType testType;
97 deUint32 bufferSize;
98 deUint32 partCount;
99 deUint32 streamId;
100 deUint32 pointSize;
101 deUint32 vertexStride;
102 StreamId0Mode streamId0Mode;
103 bool query64bits;
104 bool noOffsetArray;
105 VkPrimitiveTopology primTopology;
106 };
107
108 struct TopologyInfo
109 {
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.
114 };
115
116 const std::map<VkPrimitiveTopology, TopologyInfo> topologyData =
117 {
__anon987238010202() 118 { VK_PRIMITIVE_TOPOLOGY_POINT_LIST , { 1, "" ,[](deUint64 vertexCount) { return vertexCount; } ,[](deUint64 primCount) { return primCount; }, } },
__anon987238010402() 119 { VK_PRIMITIVE_TOPOLOGY_LINE_LIST , { 2, "line_list_" ,[](deUint64 vertexCount) { return vertexCount / 2u; } ,[](deUint64 primCount) { return primCount * 2u; }, } },
__anon987238010602() 120 { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP , { 2, "line_strip_" ,[](deUint64 vertexCount) { return vertexCount - 1u; } ,[](deUint64 primCount) { return primCount + 1u; }, } },
__anon987238010802() 121 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST , { 3, "triangle_list_" ,[](deUint64 vertexCount) { return vertexCount / 3u; } ,[](deUint64 primCount) { return primCount * 3u; }, } },
__anon987238010b02() 122 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP , { 3, "triangle_strip_" ,[](deUint64 vertexCount) { return vertexCount - 2u; } ,[](deUint64 primCount) { return primCount + 2u; }, } },
__anon987238010c02() 123 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN , { 3, "triangle_fan_" ,[](deUint64 vertexCount) { return vertexCount - 2u; } ,[](deUint64 primCount) { return primCount + 2u; }, } },
__anon987238010f02() 124 { VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY , { 2, "line_list_with_adjacency_" ,[](deUint64 vertexCount) { return vertexCount / 4u; } ,[](deUint64 primCount) { return primCount * 4u; }, } },
__anon987238011002() 125 { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY , { 2, "line_strip_with_adjacency_" ,[](deUint64 vertexCount) { return vertexCount - 3u; } ,[](deUint64 primCount) { return primCount + 3u; }, } },
__anon987238011302() 126 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY , { 3, "triangle_list_with_adjacency_" ,[](deUint64 vertexCount) { return vertexCount / 6u; } ,[](deUint64 primCount) { return primCount * 6u; }, } },
__anon987238011402() 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; }, } },
__anon987238011702() 128 { VK_PRIMITIVE_TOPOLOGY_PATCH_LIST , { 3, "patch_list_" ,[](deUint64 vertexCount) { return vertexCount / 3u; } ,[](deUint64 primCount) { return primCount * 3u; }, } },
129 };
130
131 struct TransformFeedbackQuery
132 {
133 deUint32 written;
134 deUint32 attempts;
135 };
136
137 const deUint32 MINIMUM_TF_BUFFER_SIZE = (1<<27);
138 const deUint32 IMAGE_SIZE = 64u;
139
140 template<typename T>
makeSharedPtr(Move<T> move)141 inline SharedPtr<Unique<T> > makeSharedPtr(Move<T> move)
142 {
143 return SharedPtr<Unique<T> >(new Unique<T>(move));
144 }
145
makePipelineLayout(const DeviceInterface & vk,const VkDevice device)146 Move<VkPipelineLayout> makePipelineLayout (const DeviceInterface& vk,
147 const VkDevice device)
148 {
149 const VkPushConstantRange pushConstantRanges =
150 {
151 VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlags stageFlags;
152 0u, // deUint32 offset;
153 sizeof(deUint32) // deUint32 size;
154 };
155 const VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo =
156 {
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;
164 };
165 return createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
166 }
167
makeGraphicsPipeline(const DeviceInterface & vk,const VkDevice device,const VkPipelineLayout pipelineLayout,const VkRenderPass renderPass,const VkShaderModule vertexModule,const VkShaderModule tessellationControlModule,const VkShaderModule tessellationEvalModule,const VkShaderModule geometryModule,const VkShaderModule fragmendModule,const VkExtent2D renderSize,const deUint32 subpass,const deUint32 * rasterizationStreamPtr=DE_NULL,const VkPrimitiveTopology topology=VK_PRIMITIVE_TOPOLOGY_POINT_LIST,const bool inputVertices=false)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)
182 {
183 const std::vector<VkViewport> viewports (1, makeViewport(renderSize));
184 const std::vector<VkRect2D> scissors (1, makeRect2D(renderSize));
185 const VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo =
186 {
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
194 };
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 =
199 {
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;
204 };
205 const VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo =
206 {
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;
220 };
221 const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfoPtr = (rasterizationStreamPtr == DE_NULL) ? DE_NULL : &rasterizationStateCreateInfo;
222
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
239 }
240
makeImageCreateInfo(const VkImageCreateFlags flags,const VkImageType type,const VkFormat format,const VkExtent2D size,const deUint32 numLayers,const VkImageUsageFlags usage)241 VkImageCreateInfo makeImageCreateInfo (const VkImageCreateFlags flags, const VkImageType type, const VkFormat format, const VkExtent2D size, const deUint32 numLayers, const VkImageUsageFlags usage)
242 {
243 const VkExtent3D extent = { size.width, size.height, 1u };
244 const VkImageCreateInfo imageParams =
245 {
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;
261 };
262 return imageParams;
263 }
264
makeRenderPass(const DeviceInterface & vk,const VkDevice device)265 Move<VkRenderPass> makeRenderPass (const DeviceInterface& vk,
266 const VkDevice device)
267 {
268 std::vector<VkSubpassDescription> subpassDescriptions;
269 std::vector<VkSubpassDependency> subpassDependencies;
270
271 const VkSubpassDescription description =
272 {
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;
283 };
284 subpassDescriptions.push_back(description);
285
286 const VkSubpassDependency dependency =
287 {
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;
295 };
296 subpassDependencies.push_back(dependency);
297
298 const VkRenderPassCreateInfo renderPassInfo =
299 {
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;
309 };
310
311 return createRenderPass(vk, device, &renderPassInfo);
312 }
313
makeImageMemoryBarrier(const VkAccessFlags srcAccessMask,const VkAccessFlags dstAccessMask,const VkImageLayout oldLayout,const VkImageLayout newLayout,const VkImage image,const VkImageSubresourceRange subresourceRange)314 VkImageMemoryBarrier makeImageMemoryBarrier (const VkAccessFlags srcAccessMask,
315 const VkAccessFlags dstAccessMask,
316 const VkImageLayout oldLayout,
317 const VkImageLayout newLayout,
318 const VkImage image,
319 const VkImageSubresourceRange subresourceRange)
320 {
321 const VkImageMemoryBarrier barrier =
322 {
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;
333 };
334 return barrier;
335 }
336
makeBufferMemoryBarrier(const VkAccessFlags srcAccessMask,const VkAccessFlags dstAccessMask,const VkBuffer buffer,const VkDeviceSize offset,const VkDeviceSize bufferSizeBytes)337 VkBufferMemoryBarrier makeBufferMemoryBarrier (const VkAccessFlags srcAccessMask,
338 const VkAccessFlags dstAccessMask,
339 const VkBuffer buffer,
340 const VkDeviceSize offset,
341 const VkDeviceSize bufferSizeBytes)
342 {
343 const VkBufferMemoryBarrier barrier =
344 {
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;
354 };
355 return barrier;
356 }
357
makeMemoryBarrier(const VkAccessFlags srcAccessMask,const VkAccessFlags dstAccessMask)358 VkMemoryBarrier makeMemoryBarrier (const VkAccessFlags srcAccessMask,
359 const VkAccessFlags dstAccessMask)
360 {
361 const VkMemoryBarrier barrier =
362 {
363 VK_STRUCTURE_TYPE_MEMORY_BARRIER, // VkStructureType sType;
364 DE_NULL, // const void* pNext;
365 srcAccessMask, // VkAccessFlags outputMask;
366 dstAccessMask, // VkAccessFlags inputMask;
367 };
368 return barrier;
369 }
370
makeQueryPoolCreateInfo(const deUint32 queryCountersNumber)371 VkQueryPoolCreateInfo makeQueryPoolCreateInfo (const deUint32 queryCountersNumber)
372 {
373 const VkQueryPoolCreateInfo queryPoolCreateInfo =
374 {
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;
381 };
382
383 return queryPoolCreateInfo;
384 }
385
fillBuffer(const DeviceInterface & vk,const VkDevice device,Allocation & bufferAlloc,VkDeviceSize bufferSize,const void * data,const VkDeviceSize dataSize)386 void fillBuffer (const DeviceInterface& vk, const VkDevice device, Allocation& bufferAlloc, VkDeviceSize bufferSize, const void* data, const VkDeviceSize dataSize)
387 {
388 const VkMappedMemoryRange memRange =
389 {
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;
395 };
396 std::vector<deUint8> dataVec (static_cast<deUint32>(bufferSize), 0u);
397
398 DE_ASSERT(bufferSize >= dataSize);
399
400 deMemcpy(&dataVec[0], data, static_cast<deUint32>(dataSize));
401
402 deMemcpy(bufferAlloc.getHostPtr(), &dataVec[0], dataVec.size());
403 VK_CHECK(vk.flushMappedMemoryRanges(device, 1u, &memRange));
404 }
405
406 class TransformFeedbackTestInstance : public TestInstance
407 {
408 public:
409 TransformFeedbackTestInstance (Context& context, const TestParameters& parameters);
410 protected:
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);
416
417 const bool m_extensions;
418 const VkExtent2D m_imageExtent2D;
419 const TestParameters m_parameters;
420 VkPhysicalDeviceTransformFeedbackPropertiesEXT m_transformFeedbackProperties;
421 de::Random m_rnd;
422 };
423
TransformFeedbackTestInstance(Context & context,const TestParameters & parameters)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)
429 , m_rnd (0)
430 {
431 const VkPhysicalDeviceTransformFeedbackFeaturesEXT& transformFeedbackFeatures = m_context.getTransformFeedbackFeaturesEXT();
432 VkPhysicalDeviceProperties2 deviceProperties2;
433
434 if (transformFeedbackFeatures.transformFeedback == DE_FALSE)
435 TCU_THROW(NotSupportedError, "transformFeedback feature is not supported");
436
437 deMemset(&deviceProperties2, 0, sizeof(deviceProperties2));
438 deMemset(&m_transformFeedbackProperties, 0, sizeof(m_transformFeedbackProperties));
439
440 deviceProperties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
441 deviceProperties2.pNext = &m_transformFeedbackProperties;
442
443 m_transformFeedbackProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT;
444 m_transformFeedbackProperties.pNext = DE_NULL;
445
446 context.getInstanceInterface().getPhysicalDeviceProperties2(context.getPhysicalDevice(), &deviceProperties2);
447
448 validateLimits();
449
450 if (m_parameters.streamId > 0 && (m_transformFeedbackProperties.transformFeedbackRasterizationStreamSelect == VK_FALSE))
451 TCU_THROW(NotSupportedError, "Implementation doesn't support streamId > 0");
452 }
453
validateLimits()454 void TransformFeedbackTestInstance::validateLimits ()
455 {
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);
461
462 VALIDATE_BOOL(m_transformFeedbackProperties.transformFeedbackQueries);
463 VALIDATE_BOOL(m_transformFeedbackProperties.transformFeedbackStreamsLinesTriangles);
464 VALIDATE_BOOL(m_transformFeedbackProperties.transformFeedbackRasterizationStreamSelect);
465 VALIDATE_BOOL(m_transformFeedbackProperties.transformFeedbackDraw);
466 }
467
generateSizesList(const size_t bufBytes,const size_t chunkCount)468 std::vector<VkDeviceSize> TransformFeedbackTestInstance::generateSizesList (const size_t bufBytes, const size_t chunkCount)
469 {
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;
475
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));
482
483 offsetsSet[0] = true;
484
485 // Create a list of unique offsets first
486 for (size_t chunkNdx = 1; chunkNdx < chunkCount; ++chunkNdx)
487 {
488 int chunkSlot;
489
490 do
491 {
492 chunkSlot = m_rnd.getInt(minChunkSlot, maxChunkSlot - 1);
493 } while (offsetsSet.find(chunkSlot) != offsetsSet.end());
494
495 offsetsSet[chunkSlot] = true;
496 }
497 offsetsSet[maxChunkSlot] = true;
498
499 // Calculate sizes of offsets list
500 result.reserve(chunkCount);
501 for (std::map<int, bool>::iterator mapIt = offsetsSet.begin(); mapIt != offsetsSet.end(); ++mapIt)
502 {
503 const int offsetSlot = mapIt->first;
504
505 if (offsetSlot == 0)
506 continue;
507
508 DE_ASSERT(prevOffsetSlot < offsetSlot && offsetSlot > 0);
509
510 result.push_back(static_cast<VkDeviceSize>(static_cast<size_t>(offsetSlot - prevOffsetSlot) * sizeof(deUint32)));
511
512 prevOffsetSlot = offsetSlot;
513 }
514
515 DE_ASSERT(result.size() == chunkCount);
516
517 return result;
518 }
519
generateOffsetsList(const std::vector<VkDeviceSize> & sizesList)520 std::vector<VkDeviceSize> TransformFeedbackTestInstance::generateOffsetsList (const std::vector<VkDeviceSize>& sizesList)
521 {
522 VkDeviceSize offset = 0ull;
523 std::vector<VkDeviceSize> result;
524
525 result.reserve(sizesList.size());
526
527 for (size_t chunkNdx = 0; chunkNdx < sizesList.size(); ++chunkNdx)
528 {
529 result.push_back(offset);
530
531 offset += sizesList[chunkNdx];
532 }
533
534 DE_ASSERT(sizesList.size() == result.size());
535
536 return result;
537 }
538
verifyTransformFeedbackBuffer(const MovePtr<Allocation> & bufAlloc,const deUint32 bufBytes)539 void TransformFeedbackTestInstance::verifyTransformFeedbackBuffer (const MovePtr<Allocation>& bufAlloc,
540 const deUint32 bufBytes)
541 {
542 const DeviceInterface& vk = m_context.getDeviceInterface();
543 const VkDevice device = m_context.getDevice();
544
545 invalidateAlloc(vk, device, *bufAlloc);
546
547 const deUint32 numPoints = static_cast<deUint32>(bufBytes / sizeof(deUint32));
548 const deUint32* tfData = (deUint32*)bufAlloc->getHostPtr();
549
550 for (deUint32 i = 0; i < numPoints; ++i)
551 if (tfData[i] != i)
552 TCU_FAIL(std::string("Failed at item ") + de::toString(i) + " received:" + de::toString(tfData[i]) + " expected:" + de::toString(i));
553 }
554
555 class TransformFeedbackBasicTestInstance : public TransformFeedbackTestInstance
556 {
557 public:
558 TransformFeedbackBasicTestInstance (Context& context, const TestParameters& parameters);
559
560 protected:
561 tcu::TestStatus iterate (void);
562 };
563
TransformFeedbackBasicTestInstance(Context & context,const TestParameters & parameters)564 TransformFeedbackBasicTestInstance::TransformFeedbackBasicTestInstance (Context& context, const TestParameters& parameters)
565 : TransformFeedbackTestInstance (context, parameters)
566 {
567 }
568
iterate(void)569 tcu::TestStatus TransformFeedbackBasicTestInstance::iterate (void)
570 {
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();
576
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));
584
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);
591
592 VK_CHECK(vk.bindBufferMemory(device, *tfBuf, tfBufAllocation->getMemory(), tfBufAllocation->getOffset()));
593
594 beginCommandBuffer(vk, *cmdBuffer);
595 {
596 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
597 {
598 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
599
600 for (deUint32 drawNdx = 0; drawNdx < m_parameters.partCount; ++drawNdx)
601 {
602 const deUint32 startValue = static_cast<deUint32>(tfBufBindingOffsets[drawNdx] / sizeof(deUint32));
603 const deUint32 numPoints = static_cast<deUint32>(tfBufBindingSizes[drawNdx] / sizeof(deUint32));
604
605 vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0, 1, &*tfBuf, &tfBufBindingOffsets[drawNdx], &tfBufBindingSizes[drawNdx]);
606
607 vk.cmdPushConstants(*cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0u, sizeof(startValue), &startValue);
608
609 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
610 {
611 vk.cmdDraw(*cmdBuffer, numPoints, 1u, 0u, 0u);
612 }
613 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
614 }
615 }
616 endRenderPass(vk, *cmdBuffer);
617
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);
619 }
620 endCommandBuffer(vk, *cmdBuffer);
621 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
622
623 verifyTransformFeedbackBuffer(tfBufAllocation, m_parameters.bufferSize);
624
625 return tcu::TestStatus::pass("Pass");
626 }
627
628 class TransformFeedbackResumeTestInstance : public TransformFeedbackTestInstance
629 {
630 public:
631 TransformFeedbackResumeTestInstance (Context& context, const TestParameters& parameters);
632
633 protected:
634 tcu::TestStatus iterate (void);
635 };
636
TransformFeedbackResumeTestInstance(Context & context,const TestParameters & parameters)637 TransformFeedbackResumeTestInstance::TransformFeedbackResumeTestInstance (Context& context, const TestParameters& parameters)
638 : TransformFeedbackTestInstance (context, parameters)
639 {
640 }
641
iterate(void)642 tcu::TestStatus TransformFeedbackResumeTestInstance::iterate (void)
643 {
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();
649
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));
655
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));
658
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);
665
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);
672
673 const std::vector<VkDeviceSize> chunkSizesList = generateSizesList(m_parameters.bufferSize, m_parameters.partCount);
674 const std::vector<VkDeviceSize> chunkOffsetsList = generateOffsetsList(chunkSizesList);
675
676 DE_ASSERT(tfBufBindingSizes.size() == 1);
677 DE_ASSERT(tfBufBindingOffsets.size() == 1);
678
679 VK_CHECK(vk.bindBufferMemory(device, *tfBuf, tfBufAllocation->getMemory(), tfBufAllocation->getOffset()));
680 VK_CHECK(vk.bindBufferMemory(device, *tfcBuf, tfcBufAllocation->getMemory(), tfcBufAllocation->getOffset()));
681
682 beginCommandBuffer(vk, *cmdBuffer);
683 {
684 for (size_t drawNdx = 0; drawNdx < m_parameters.partCount; ++drawNdx)
685 {
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;
689
690 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
691 {
692
693 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
694
695 vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0, 1, &*tfBuf, &tfBufBindingOffsets[0], &tfBufBindingSizes[0]);
696
697 vk.cmdPushConstants(*cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0u, sizeof(startValue), &startValue);
698
699 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, countBuffersCount, (drawNdx == 0) ? DE_NULL : &*tfcBuf, (drawNdx == 0) ? DE_NULL : &tfcBufBindingOffsets[drawNdx - 1]);
700 {
701 vk.cmdDraw(*cmdBuffer, numPoints, 1u, 0u, 0u);
702 }
703 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 1, &*tfcBuf, &tfcBufBindingOffsets[drawNdx]);
704 }
705 endRenderPass(vk, *cmdBuffer);
706
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);
708 }
709
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);
711 }
712 endCommandBuffer(vk, *cmdBuffer);
713 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
714
715 verifyTransformFeedbackBuffer(tfBufAllocation, m_parameters.bufferSize);
716
717 return tcu::TestStatus::pass("Pass");
718 }
719
720 class TransformFeedbackWindingOrderTestInstance : public TransformFeedbackTestInstance
721 {
722 public:
723 TransformFeedbackWindingOrderTestInstance(Context& context, const TestParameters& parameters);
724
725 protected:
726 struct TopologyParameters
727 {
728 // number of vertex in primitive; 2 for line, 3 for triangle
729 deUint32 vertexPerPrimitive;
730
731 // pointer to function calculating number of points that
732 // will be generated for given part count
733 std::function<deUint32(deUint32)> getNumGeneratedPoints;
734
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;
738 };
739 typedef const std::map<VkPrimitiveTopology, TopologyParameters> TopologyParametersMap;
740
741 protected:
742 const TopologyParametersMap& getTopologyParametersMap (void);
743 tcu::TestStatus iterate (void);
744 void verifyTransformFeedbackBuffer (const MovePtr<Allocation>& bufAlloc,
745 const deUint32 bufBytes);
746
747 private:
748 TopologyParameters m_tParameters;
749 const bool m_requiresTesselationStage;
750 };
751
TransformFeedbackWindingOrderTestInstance(Context & context,const TestParameters & parameters)752 TransformFeedbackWindingOrderTestInstance::TransformFeedbackWindingOrderTestInstance(Context& context, const TestParameters& parameters)
753 : TransformFeedbackTestInstance (context, parameters)
754 , m_requiresTesselationStage(parameters.primTopology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST)
755 {
756 if (m_requiresTesselationStage && !context.getDeviceFeatures().tessellationShader)
757 throw tcu::NotSupportedError("Tessellation shader not supported");
758
759 TopologyParametersMap topologyParametersMap = getTopologyParametersMap();
760 DE_ASSERT(topologyParametersMap.find(parameters.primTopology) != topologyParametersMap.end());
761 m_tParameters = topologyParametersMap.at(parameters.primTopology);
762 }
763
getTopologyParametersMap(void)764 const TransformFeedbackWindingOrderTestInstance::TopologyParametersMap& TransformFeedbackWindingOrderTestInstance::getTopologyParametersMap(void)
765 {
766 static const TopologyParametersMap topologyParametersMap =
767 {
768 {
769 VK_PRIMITIVE_TOPOLOGY_POINT_LIST,
770 {
771 1u,
772 [](deUint32 partCount) { return partCount; },
773 [](deUint32 i) { return std::vector<deUint32>{ i, i + 1u }; }
774 }
775 },
776 {
777 VK_PRIMITIVE_TOPOLOGY_LINE_LIST,
778 {
779 2u,
780 [](deUint32 partCount) { return partCount; },
781 [](deUint32 i) { return std::vector<deUint32>{ 2 * i, 2 * i + 1u }; }
782 }
783 },
784 {
785 VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,
786 {
787 2u,
788 [](deUint32 partCount) { return 2u * (partCount - 1); },
789 [](deUint32 i) { return std::vector<deUint32>{ i, i + 1u }; }
790 }
791 },
792 {
793 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
794 {
795 3u,
796 [](deUint32 partCount) { return partCount; },
797 [](deUint32 i) { return std::vector<deUint32>{ 3 * i, 3 * i + 1u, 3 * i + 2u }; }
798 }
799 },
800 {
801 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
802 {
803 3u,
804 [](deUint32 partCount) { return 3u * (partCount - 2); },
805 [](deUint32 i)
806 {
807 const deUint32 iMod2 = i % 2;
808 return std::vector<deUint32>{ i, i + 1 + iMod2, i + 2 - iMod2 };
809 }
810 }
811 },
812 {
813 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,
814 {
815 3u,
816 [](deUint32 partCount) { return partCount; },
817 [](deUint32 i) { return std::vector<deUint32>{ i + 1, i + 2, 0 }; }
818 }
819 },
820 {
821 VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY,
822 {
823 2u,
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 }; }
826 }
827 },
828 {
829 VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY,
830 {
831 2u,
832 [](deUint32 partCount) { return 2u * (partCount - 3u); },
833 [](deUint32 i) { return std::vector<deUint32>{ i + 1u, i + 2u }; }
834 }
835 },
836 {
837 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY,
838 {
839 3u,
840 [](deUint32 partCount) { return partCount / 2u; },
841 [](deUint32 i) { return std::vector<deUint32>{ 6 * i, 6 * i + 2u, 6 * i + 4u }; }
842 }
843 },
844 {
845 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY,
846 {
847 3u,
848 [](deUint32 partCount) { return 3u * (partCount / 2u - 2u); },
849 [](deUint32 i)
850 {
851 const bool even = (0 == i % 2);
852 if (even)
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 };
855 }
856 }
857 },
858 {
859 VK_PRIMITIVE_TOPOLOGY_PATCH_LIST,
860 {
861 9u,
862 [](deUint32 partCount) { return partCount * 3u; },
863 [](deUint32 i)
864 {
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);
868 }
869 }
870 }
871 };
872
873 return topologyParametersMap;
874 }
875
iterate(void)876 tcu::TestStatus TransformFeedbackWindingOrderTestInstance::iterate (void)
877 {
878 DE_ASSERT(m_parameters.partCount >= 6);
879
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();
885
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)
890 {
891 tescModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("tesc"), 0u);
892 teseModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("tese"), 0u);
893 }
894
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,
899 *vertexModule,
900 m_requiresTesselationStage ? *tescModule : DE_NULL,
901 m_requiresTesselationStage ? *teseModule : DE_NULL,
902 DE_NULL,
903 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;
915
916 VK_CHECK(vk.bindBufferMemory(device, *tfBuf, tfBufAllocation->getMemory(), tfBufAllocation->getOffset()));
917
918 beginCommandBuffer(vk, *cmdBuffer);
919 {
920 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
921 {
922 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
923
924 vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0, 1, &*tfBuf, &tfBufBindingOffset, &tfBufBindingSize);
925
926 vk.cmdPushConstants(*cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0u, sizeof(startValue), &startValue);
927
928 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
929 {
930 vk.cmdDraw(*cmdBuffer, m_parameters.partCount, 1u, 0u, 0u);
931 }
932 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
933 }
934 endRenderPass(vk, *cmdBuffer);
935
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);
937 }
938 endCommandBuffer(vk, *cmdBuffer);
939 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
940
941 verifyTransformFeedbackBuffer(tfBufAllocation, static_cast<deUint32>(bufferSize));
942
943 return tcu::TestStatus::pass("Pass");
944 }
945
verifyTransformFeedbackBuffer(const MovePtr<Allocation> & bufAlloc,const deUint32 bufBytes)946 void TransformFeedbackWindingOrderTestInstance::verifyTransformFeedbackBuffer(const MovePtr<Allocation>& bufAlloc,
947 const deUint32 bufBytes)
948 {
949 const DeviceInterface& vk = m_context.getDeviceInterface();
950 const VkDevice device = m_context.getDevice();
951
952 invalidateAlloc(vk, device, *bufAlloc);
953
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();
958
959 for (deUint32 primitiveIndex = 0; primitiveIndex < numPrimitives; ++primitiveIndex)
960 {
961 const deUint32* tfDataForPrimitive = &tfData[primitiveIndex * vertexPerPrimitive];
962 std::vector<deUint32> expectedDataForPrimitive = m_tParameters.getExpectedValuesForPrimitive(primitiveIndex);
963
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++)
969 {
970 correctWinding = true;
971 for (deUint32 vertexIndex = 0; vertexIndex < vertexPerPrimitive; vertexIndex++)
972 {
973 correctWinding &= (tfDataForPrimitive[vertexIndex] == expectedDataForPrimitive[(combinationIndex + vertexIndex) % vertexPerPrimitive]);
974
975 // if data for this vertex is not correct then there
976 // is no need to check other, go to next combination
977 if (!correctWinding)
978 break;
979 }
980
981 // no need to check other combinations, we found correct one
982 if (correctWinding)
983 break;
984 }
985
986 if (!correctWinding)
987 {
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]) << " ";
995 message << "]";
996 TCU_FAIL(message.str());
997 }
998 }
999 }
1000
1001 class TransformFeedbackBuiltinTestInstance : public TransformFeedbackTestInstance
1002 {
1003 public:
1004 TransformFeedbackBuiltinTestInstance (Context& context, const TestParameters& parameters);
1005
1006 protected:
1007 tcu::TestStatus iterate (void);
1008 void verifyTransformFeedbackBuffer (const MovePtr<Allocation>& bufAlloc, const VkDeviceSize offset, const deUint32 bufBytes);
1009 };
1010
TransformFeedbackBuiltinTestInstance(Context & context,const TestParameters & parameters)1011 TransformFeedbackBuiltinTestInstance::TransformFeedbackBuiltinTestInstance (Context& context, const TestParameters& parameters)
1012 : TransformFeedbackTestInstance (context, parameters)
1013 {
1014 const InstanceInterface& vki = m_context.getInstanceInterface();
1015 const VkPhysicalDevice physDevice = m_context.getPhysicalDevice();
1016 const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(vki, physDevice);
1017
1018 const deUint32 tfBuffersSupported = m_transformFeedbackProperties.maxTransformFeedbackBuffers;
1019 const deUint32 tfBuffersRequired = m_parameters.partCount;
1020
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());
1027 }
1028
verifyTransformFeedbackBuffer(const MovePtr<Allocation> & bufAlloc,const VkDeviceSize offset,const deUint32 bufBytes)1029 void TransformFeedbackBuiltinTestInstance::verifyTransformFeedbackBuffer (const MovePtr<Allocation>& bufAlloc, const VkDeviceSize offset, const deUint32 bufBytes)
1030 {
1031 const DeviceInterface& vk = m_context.getDeviceInterface();
1032 const VkDevice device = m_context.getDevice();
1033
1034 invalidateAlloc(vk, device, *bufAlloc);
1035
1036 const deUint32 numPoints = bufBytes / static_cast<deUint32>(sizeof(float));
1037 const deUint8* tfDataBytes = (deUint8*)bufAlloc->getHostPtr();
1038 const float* tfData = (float*)&tfDataBytes[offset];
1039
1040 for (deUint32 i = 0; i < numPoints; ++i)
1041 {
1042 const deUint32 divisor = 32768u;
1043 const float epsilon = 1.0f / float(divisor);
1044 const float expected = float(i) / float(divisor);
1045
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));
1048 }
1049 }
1050
iterate(void)1051 tcu::TestStatus TransformFeedbackBuiltinTestInstance::iterate (void)
1052 {
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();
1058
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));
1066
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))
1079 : 0u;
1080 const deUint32 numPoints = m_parameters.bufferSize / perVertexDataSize;
1081
1082 VK_CHECK(vk.bindBufferMemory(device, *tfBuf, tfBufAllocation->getMemory(), tfBufAllocation->getOffset()));
1083
1084 beginCommandBuffer(vk, *cmdBuffer);
1085 {
1086 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
1087 {
1088 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1089
1090 vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0, m_parameters.partCount, &tfBufArray[0], &tfBufBindingOffsets[0], &tfBufBindingSizes[0]);
1091
1092 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1093 {
1094 vk.cmdDraw(*cmdBuffer, numPoints, 1u, 0u, 0u);
1095 }
1096 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1097 }
1098 endRenderPass(vk, *cmdBuffer);
1099
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);
1101 }
1102 endCommandBuffer(vk, *cmdBuffer);
1103 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1104
1105 verifyTransformFeedbackBuffer(tfBufAllocation, tfBufBindingOffsets[m_parameters.partCount - 1], numPoints * perVertexDataSize);
1106
1107 return tcu::TestStatus::pass("Pass");
1108 }
1109
1110 class TransformFeedbackMultistreamTestInstance : public TransformFeedbackTestInstance
1111 {
1112 public:
1113 TransformFeedbackMultistreamTestInstance (Context& context, const TestParameters& parameters);
1114
1115 protected:
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);
1119 };
1120
TransformFeedbackMultistreamTestInstance(Context & context,const TestParameters & parameters)1121 TransformFeedbackMultistreamTestInstance::TransformFeedbackMultistreamTestInstance (Context& context, const TestParameters& parameters)
1122 : TransformFeedbackTestInstance (context, parameters)
1123 {
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;
1136
1137 DE_ASSERT(m_parameters.partCount == 2u);
1138
1139 if (!features.geometryShader)
1140 TCU_THROW(NotSupportedError, "Missing feature: geometryShader");
1141
1142 if (transformFeedbackFeatures.geometryStreams == DE_FALSE)
1143 TCU_THROW(NotSupportedError, "geometryStreams feature is not supported");
1144
1145 if (streamsSupported < streamsRequired)
1146 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackStreams=" + de::toString(streamsSupported) + ", while test requires " + de::toString(streamsRequired)).c_str());
1147
1148 if (tfBuffersSupported < tfBuffersRequired)
1149 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBuffers=" + de::toString(tfBuffersSupported) + ", while test requires " + de::toString(tfBuffersRequired)).c_str());
1150
1151 if (tfStreamDataSizeSupported < bytesPerVertex)
1152 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackStreamDataSize=" + de::toString(tfStreamDataSizeSupported) + ", while test requires " + de::toString(bytesPerVertex)).c_str());
1153
1154 if (tfBufferDataSizeSupported < bytesPerVertex)
1155 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBufferDataSize=" + de::toString(tfBufferDataSizeSupported) + ", while test requires " + de::toString(bytesPerVertex)).c_str());
1156
1157 if (tfBufferDataStrideSupported < bytesPerVertex)
1158 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBufferDataStride=" + de::toString(tfBufferDataStrideSupported) + ", while test requires " + de::toString(bytesPerVertex)).c_str());
1159 }
1160
generateSizesList(const size_t bufBytes,const size_t chunkCount)1161 std::vector<VkDeviceSize> TransformFeedbackMultistreamTestInstance::generateSizesList (const size_t bufBytes, const size_t chunkCount)
1162 {
1163 const VkDeviceSize chunkSize = bufBytes / chunkCount;
1164 std::vector<VkDeviceSize> result (chunkCount, chunkSize);
1165
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);
1171
1172 return result;
1173 }
1174
verifyTransformFeedbackBuffer(const MovePtr<Allocation> & bufAlloc,const deUint32 bufBytes)1175 void TransformFeedbackMultistreamTestInstance::verifyTransformFeedbackBuffer (const MovePtr<Allocation>& bufAlloc, const deUint32 bufBytes)
1176 {
1177 const DeviceInterface& vk = m_context.getDeviceInterface();
1178 const VkDevice device = m_context.getDevice();
1179
1180 invalidateAlloc(vk, device, *bufAlloc);
1181
1182 const deUint32 numPoints = static_cast<deUint32>(bufBytes / sizeof(deUint32));
1183 const float* tfData = (float*)bufAlloc->getHostPtr();
1184
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));
1188 }
1189
iterate(void)1190 tcu::TestStatus TransformFeedbackMultistreamTestInstance::iterate (void)
1191 {
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();
1197
1198 const Unique<VkRenderPass> renderPass (makeRenderPass (vk, device, VK_FORMAT_UNDEFINED));
1199
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));
1202
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));
1208
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);
1216
1217 VK_CHECK(vk.bindBufferMemory(device, *tfBuf, tfBufAllocation->getMemory(), tfBufAllocation->getOffset()));
1218
1219 beginCommandBuffer(vk, *cmdBuffer);
1220 {
1221 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
1222 {
1223 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1224
1225 vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0u, m_parameters.partCount, &tfBufArray[0], &tfBufBindingOffsets[0], &tfBufBindingSizes[0]);
1226
1227 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1228 {
1229 vk.cmdDraw(*cmdBuffer, 1u, 1u, 0u, 0u);
1230 }
1231 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1232 }
1233 endRenderPass(vk, *cmdBuffer);
1234
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);
1236 }
1237 endCommandBuffer(vk, *cmdBuffer);
1238 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1239
1240 verifyTransformFeedbackBuffer(tfBufAllocation, m_parameters.bufferSize);
1241
1242 return tcu::TestStatus::pass("Pass");
1243 }
1244
1245 class TransformFeedbackStreamsTestInstance : public TransformFeedbackTestInstance
1246 {
1247 public:
1248 TransformFeedbackStreamsTestInstance (Context& context, const TestParameters& parameters);
1249
1250 protected:
1251 tcu::TestStatus iterate (void);
1252 bool verifyImage (const VkFormat imageFormat, const VkExtent2D& size, const void* resultData);
1253 };
1254
TransformFeedbackStreamsTestInstance(Context & context,const TestParameters & parameters)1255 TransformFeedbackStreamsTestInstance::TransformFeedbackStreamsTestInstance (Context& context, const TestParameters& parameters)
1256 : TransformFeedbackTestInstance (context, parameters)
1257 {
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;
1265
1266 if (!features.geometryShader)
1267 TCU_THROW(NotSupportedError, "Missing feature: geometryShader");
1268
1269 if (transformFeedbackFeatures.geometryStreams == DE_FALSE)
1270 TCU_THROW(NotSupportedError, "geometryStreams feature is not supported");
1271
1272 if (m_transformFeedbackProperties.transformFeedbackRasterizationStreamSelect == DE_FALSE)
1273 TCU_THROW(NotSupportedError, "transformFeedbackRasterizationStreamSelect feature is not supported");
1274
1275 if (streamsSupported < streamsRequired)
1276 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackStreams=" + de::toString(streamsSupported) + ", while test requires " + de::toString(streamsRequired)).c_str());
1277
1278 if (geomPointSizeRequired && !features.shaderTessellationAndGeometryPointSize)
1279 TCU_THROW(NotSupportedError, "shaderTessellationAndGeometryPointSize feature is not supported");
1280 }
1281
verifyImage(const VkFormat imageFormat,const VkExtent2D & size,const void * resultData)1282 bool TransformFeedbackStreamsTestInstance::verifyImage (const VkFormat imageFormat, const VkExtent2D& size, const void* resultData)
1283 {
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());
1291
1292 // Generate reference image
1293 if (m_parameters.testType == TEST_TYPE_STREAMS)
1294 {
1295 for (int y = 0; y < referenceImage.getHeight(); ++y)
1296 {
1297 const tcu::Vec4& validColor = y < referenceImage.getHeight() / 2 ? black : magenta;
1298
1299 for (int x = 0; x < referenceImage.getWidth(); ++x)
1300 referenceAccess.setPixel(validColor, x, y);
1301 }
1302 }
1303
1304 if (m_parameters.testType == TEST_TYPE_STREAMS_CLIPDISTANCE || m_parameters.testType == TEST_TYPE_STREAMS_CULLDISTANCE)
1305 {
1306 for (int y = 0; y < referenceImage.getHeight(); ++y)
1307 for (int x = 0; x < referenceImage.getWidth(); ++x)
1308 {
1309 const tcu::Vec4& validColor = (y >= referenceImage.getHeight() / 2) && (x >= referenceImage.getWidth() / 2) ? magenta : black;
1310
1311 referenceAccess.setPixel(validColor, x, y);
1312 }
1313 }
1314
1315 if (m_parameters.testType == TEST_TYPE_STREAMS_POINTSIZE)
1316 {
1317 const int pointSize = static_cast<int>(m_parameters.pointSize);
1318 const tcu::Vec4& validColor = black;
1319
1320 for (int y = 0; y < referenceImage.getHeight(); ++y)
1321 for (int x = 0; x < referenceImage.getWidth(); ++x)
1322 referenceAccess.setPixel(validColor, x, y);
1323
1324 referenceAccess.setPixel(magenta, (1 + referenceImage.getWidth()) / 4 - 1, (referenceImage.getHeight() * 3) / 4 - 1);
1325
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);
1329 }
1330
1331 if (deMemCmp(resultData, referenceAccess.getDataPtr(), dataSize) != 0)
1332 {
1333 const tcu::ConstPixelBufferAccess resultImage (textureFormat, size.width, size.height, 1, resultData);
1334 bool ok;
1335
1336 ok = tcu::intThresholdCompare(m_context.getTestContext().getLog(), "Image comparison", "", referenceAccess, resultImage, tcu::UVec4(1), tcu::COMPARE_LOG_RESULT);
1337
1338 return ok;
1339 }
1340
1341 return true;
1342 }
1343
iterate(void)1344 tcu::TestStatus TransformFeedbackStreamsTestInstance::iterate (void)
1345 {
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();
1351
1352 const Unique<VkRenderPass> renderPass (makeRenderPass (vk, device, VK_FORMAT_R8G8B8A8_UNORM));
1353
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));
1357
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));
1368
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));
1374
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);
1381
1382 beginCommandBuffer(vk, *cmdBuffer);
1383 {
1384 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D), clearColor.toVec());
1385 {
1386 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1387
1388 vk.cmdDraw(*cmdBuffer, 2u, 1u, 0u, 0u);
1389 }
1390 endRenderPass(vk, *cmdBuffer);
1391
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);
1395 }
1396 endCommandBuffer(vk, *cmdBuffer);
1397 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1398
1399 if (!verifyImage(colorFormat, m_imageExtent2D, colorBufferAlloc->getHostPtr()))
1400 return tcu::TestStatus::fail("Fail");
1401
1402 return tcu::TestStatus::pass("Pass");
1403 }
1404
1405 class TransformFeedbackIndirectDrawTestInstance : public TransformFeedbackTestInstance
1406 {
1407 public:
1408 TransformFeedbackIndirectDrawTestInstance (Context& context, const TestParameters& parameters);
1409
1410 protected:
1411 tcu::TestStatus iterate (void);
1412 bool verifyImage (const VkFormat imageFormat, const VkExtent2D& size, const void* resultData);
1413 };
1414
TransformFeedbackIndirectDrawTestInstance(Context & context,const TestParameters & parameters)1415 TransformFeedbackIndirectDrawTestInstance::TransformFeedbackIndirectDrawTestInstance (Context& context, const TestParameters& parameters)
1416 : TransformFeedbackTestInstance (context, parameters)
1417 {
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;
1423
1424 if (m_transformFeedbackProperties.transformFeedbackDraw == DE_FALSE)
1425 TCU_THROW(NotSupportedError, "transformFeedbackDraw feature is not supported");
1426
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());
1429
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());
1432
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());
1435 }
1436
verifyImage(const VkFormat imageFormat,const VkExtent2D & size,const void * resultData)1437 bool TransformFeedbackIndirectDrawTestInstance::verifyImage (const VkFormat imageFormat, const VkExtent2D& size, const void* resultData)
1438 {
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());
1444
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);
1449
1450 if (deMemCmp(resultData, referenceAccess.getDataPtr(), dataSize) != 0)
1451 {
1452 const tcu::ConstPixelBufferAccess resultImage (textureFormat, size.width, size.height, 1, resultData);
1453 bool ok;
1454
1455 ok = tcu::intThresholdCompare(m_context.getTestContext().getLog(), "Image comparison", "", referenceAccess, resultImage, tcu::UVec4(1), tcu::COMPARE_LOG_RESULT);
1456
1457 return ok;
1458 }
1459
1460 return true;
1461 }
1462
iterate(void)1463 tcu::TestStatus TransformFeedbackIndirectDrawTestInstance::iterate (void)
1464 {
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();
1470
1471 const Unique<VkRenderPass> renderPass (makeRenderPass (vk, device, VK_FORMAT_R8G8B8A8_UNORM));
1472
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));
1475
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));
1486
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[] =
1494 {
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,
1501 };
1502
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));
1508
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));
1514
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);
1521
1522 fillBuffer(vk, device, *counterBufferAlloc, counterBufferSize, &counterBufferValue, counterBufferSize);
1523 fillBuffer(vk, device, *vertexBufferAlloc, vertexBufferSize, vertexBufferVals, sizeof(vertexBufferVals));
1524
1525 beginCommandBuffer(vk, *cmdBuffer);
1526 {
1527 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D), clearColor.toVec());
1528 {
1529 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &*vertexBuffer, &vertexBufferOffset);
1530
1531 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1532
1533 vk.cmdDrawIndirectByteCountEXT(*cmdBuffer, 1u, 0u, *counterBuffer, 0u, 0u, m_parameters.vertexStride);
1534 }
1535 endRenderPass(vk, *cmdBuffer);
1536
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);
1540 }
1541 endCommandBuffer(vk, *cmdBuffer);
1542 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1543
1544 if (!verifyImage(colorFormat, m_imageExtent2D, colorBufferAlloc->getHostPtr()))
1545 return tcu::TestStatus::fail("Fail");
1546
1547 return tcu::TestStatus::pass("Pass");
1548 }
1549
1550 class TransformFeedbackBackwardDependencyTestInstance : public TransformFeedbackTestInstance
1551 {
1552 public:
1553 TransformFeedbackBackwardDependencyTestInstance (Context& context, const TestParameters& parameters);
1554
1555 protected:
1556 tcu::TestStatus iterate (void);
1557 std::vector<VkDeviceSize> generateSizesList (const size_t bufBytes, const size_t chunkCount);
1558 };
1559
TransformFeedbackBackwardDependencyTestInstance(Context & context,const TestParameters & parameters)1560 TransformFeedbackBackwardDependencyTestInstance::TransformFeedbackBackwardDependencyTestInstance (Context& context, const TestParameters& parameters)
1561 : TransformFeedbackTestInstance (context, parameters)
1562 {
1563 if (m_transformFeedbackProperties.transformFeedbackDraw == DE_FALSE)
1564 TCU_THROW(NotSupportedError, "transformFeedbackDraw feature is not supported");
1565 }
1566
generateSizesList(const size_t bufBytes,const size_t chunkCount)1567 std::vector<VkDeviceSize> TransformFeedbackBackwardDependencyTestInstance::generateSizesList (const size_t bufBytes, const size_t chunkCount)
1568 {
1569 const VkDeviceSize chunkSize = bufBytes / chunkCount;
1570 std::vector<VkDeviceSize> result (chunkCount, chunkSize);
1571
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);
1577
1578 return result;
1579 }
1580
iterate(void)1581 tcu::TestStatus TransformFeedbackBackwardDependencyTestInstance::iterate (void)
1582 {
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();
1588
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));
1596
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;
1603
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);
1610
1611 const std::vector<VkDeviceSize> chunkSizesList = generateSizesList(m_parameters.bufferSize, m_parameters.partCount);
1612 const std::vector<VkDeviceSize> chunkOffsetsList = generateOffsetsList(chunkSizesList);
1613
1614 VK_CHECK(vk.bindBufferMemory(device, *tfBuf, tfBufAllocation->getMemory(), tfBufAllocation->getOffset()));
1615 VK_CHECK(vk.bindBufferMemory(device, *tfcBuf, tfcBufAllocation->getMemory(), tfcBufAllocation->getOffset()));
1616
1617 DE_ASSERT(m_parameters.partCount == 2u);
1618
1619 beginCommandBuffer(vk, *cmdBuffer);
1620 {
1621 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
1622 {
1623 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1624
1625 vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0, 1, &*tfBuf, &tfBufBindingOffset, &tfBufBindingSize);
1626
1627 {
1628 const deUint32 startValue = static_cast<deUint32>(chunkOffsetsList[0] / sizeof(deUint32));
1629 const deUint32 numPoints = static_cast<deUint32>(chunkSizesList[0] / sizeof(deUint32));
1630
1631 vk.cmdPushConstants(*cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0u, sizeof(startValue), &startValue);
1632
1633 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1634 {
1635 vk.cmdDraw(*cmdBuffer, numPoints, 1u, 0u, 0u);
1636 }
1637 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 1, &*tfcBuf, m_parameters.noOffsetArray ? DE_NULL : &tfcBufBindingOffset);
1638 }
1639
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);
1641
1642 {
1643 const deUint32 startValue = static_cast<deUint32>(chunkOffsetsList[1] / sizeof(deUint32));
1644
1645 vk.cmdPushConstants(*cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0u, sizeof(startValue), &startValue);
1646
1647 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 1, &*tfcBuf, m_parameters.noOffsetArray ? DE_NULL : &tfcBufBindingOffset);
1648 {
1649 vk.cmdDrawIndirectByteCountEXT(*cmdBuffer, 1u, 0u, *tfcBuf, 0u, 0u, 4u);
1650 }
1651 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1652 }
1653
1654 }
1655 endRenderPass(vk, *cmdBuffer);
1656
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);
1658 }
1659 endCommandBuffer(vk, *cmdBuffer);
1660 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1661
1662 verifyTransformFeedbackBuffer(tfBufAllocation, m_parameters.bufferSize);
1663
1664 return tcu::TestStatus::pass("Pass");
1665 }
1666
1667
1668 class TransformFeedbackQueryTestInstance : public TransformFeedbackTestInstance
1669 {
1670 public:
1671 TransformFeedbackQueryTestInstance (Context& context, const TestParameters& parameters);
1672
1673 protected:
1674 tcu::TestStatus iterate (void);
1675 };
1676
TransformFeedbackQueryTestInstance(Context & context,const TestParameters & parameters)1677 TransformFeedbackQueryTestInstance::TransformFeedbackQueryTestInstance (Context& context, const TestParameters& parameters)
1678 : TransformFeedbackTestInstance (context, parameters)
1679 {
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;
1686
1687 if (!features.geometryShader)
1688 TCU_THROW(NotSupportedError, "Missing feature: geometryShader");
1689
1690 if (streamsRequired > 1 && transformFeedbackFeatures.geometryStreams == DE_FALSE)
1691 TCU_THROW(NotSupportedError, "geometryStreams feature is not supported");
1692
1693 if (streamsSupported < streamsRequired)
1694 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackStreams=" + de::toString(streamsSupported) + ", while test requires " + de::toString(streamsRequired)).c_str());
1695
1696 if (m_transformFeedbackProperties.transformFeedbackQueries == DE_FALSE)
1697 TCU_THROW(NotSupportedError, "transformFeedbackQueries feature is not supported");
1698
1699 if (m_parameters.testType == TEST_TYPE_QUERY_RESET)
1700 {
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());
1705 }
1706 }
1707
iterate(void)1708 tcu::TestStatus TransformFeedbackQueryTestInstance::iterate (void)
1709 {
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();
1715
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));
1721
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));
1724
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));
1730
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;
1737
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));
1746
1747 Move<VkBuffer> queryPoolResultsBuffer;
1748 de::MovePtr<Allocation> queryPoolResultsBufferAlloc;
1749
1750 tcu::TestLog& log = m_context.getTestContext().getLog();
1751
1752 DE_ASSERT(numVerticesInBuffer * bytesPerVertex == m_parameters.bufferSize);
1753
1754 if (m_parameters.testType == TEST_TYPE_QUERY_COPY)
1755 {
1756 const VkBufferCreateInfo bufferParams =
1757 {
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;
1766 };
1767
1768 queryPoolResultsBuffer = createBuffer(vk, device, &bufferParams);
1769 queryPoolResultsBufferAlloc = allocator.allocate(getBufferMemoryRequirements(vk, device, *queryPoolResultsBuffer), MemoryRequirement::HostVisible);
1770
1771 VK_CHECK(vk.bindBufferMemory(device, *queryPoolResultsBuffer, queryPoolResultsBufferAlloc->getMemory(), queryPoolResultsBufferAlloc->getOffset()));
1772 }
1773
1774 beginCommandBuffer(vk, *cmdBuffer);
1775 {
1776 if (m_parameters.testType != TEST_TYPE_QUERY_RESET)
1777 vk.cmdResetQueryPool(*cmdBuffer, *queryPool, queryIndex, queryCountersNumber);
1778
1779 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
1780 {
1781 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1782
1783 vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0u, 1u, &*tfBuf, &tfBufBindingOffset, &tfBufBindingSize);
1784
1785 if (m_parameters.streamId == 0 && m_parameters.streamId0Mode != STREAM_ID_0_BEGIN_QUERY_INDEXED)
1786 vk.cmdBeginQuery(*cmdBuffer, *queryPool, queryIndex, 0u);
1787 else
1788 vk.cmdBeginQueryIndexedEXT(*cmdBuffer, *queryPool, queryIndex, 0u, m_parameters.streamId);
1789 {
1790 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1791 {
1792 vk.cmdDraw(*cmdBuffer, static_cast<deUint32>(numVerticesToWrite), 1u, 0u, 0u);
1793 }
1794 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1795 }
1796 if (m_parameters.streamId == 0 && m_parameters.streamId0Mode != STREAM_ID_0_END_QUERY_INDEXED)
1797 vk.cmdEndQuery(*cmdBuffer, *queryPool, queryIndex);
1798 else
1799 vk.cmdEndQueryIndexedEXT(*cmdBuffer, *queryPool, queryIndex, m_parameters.streamId);
1800 }
1801 endRenderPass(vk, *cmdBuffer);
1802
1803 if (m_parameters.testType == TEST_TYPE_QUERY_COPY)
1804 {
1805 vk.cmdCopyQueryPoolResults(*cmdBuffer, *queryPool, queryIndex, queryCountersNumber, *queryPoolResultsBuffer, 0u, queryDataSize, (vk::VK_QUERY_RESULT_WAIT_BIT | queryExtraFlags));
1806
1807 const VkBufferMemoryBarrier bufferBarrier =
1808 {
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;
1818 };
1819 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL);
1820 }
1821
1822 }
1823 endCommandBuffer(vk, *cmdBuffer);
1824
1825 if (m_parameters.testType == TEST_TYPE_QUERY_RESET)
1826 vk.resetQueryPool(device, *queryPool, queryIndex, queryCountersNumber);
1827 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1828
1829 {
1830 union Results
1831 {
1832 deUint32 elements32[queryResultElements];
1833 deUint64 elements64[queryResultElements];
1834 };
1835
1836 std::vector<deUint8> queryData (queryDataSize, 0u);
1837 const Results* queryResults = reinterpret_cast<Results*>(queryData.data());
1838
1839 if (m_parameters.testType != TEST_TYPE_QUERY_COPY)
1840 {
1841 vk.getQueryPoolResults(device, *queryPool, queryIndex, queryCountersNumber, queryDataSize, queryData.data(), queryDataSize, (vk::VK_QUERY_RESULT_WAIT_BIT | queryExtraFlags));
1842 }
1843 else
1844 {
1845 invalidateAlloc(vk, device, *queryPoolResultsBufferAlloc);
1846 deMemcpy(queryData.data(), queryPoolResultsBufferAlloc->getHostPtr(), queryData.size());
1847 }
1848
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]);
1851
1852 // The number of primitives output to the vertex stream.
1853 const deUint64 numPrimitivesNeeded = (m_parameters.query64bits ? queryResults->elements64[1] : queryResults->elements32[1]);
1854
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);
1858
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;
1861
1862 if (numPrimitivesWritten != primitivesInBuffer)
1863 return tcu::TestStatus::fail("numPrimitivesWritten=" + de::toString(numPrimitivesWritten) + " while expected " + de::toString(primitivesInBuffer));
1864
1865 if (numPrimitivesNeeded != primitivesToWrite)
1866 return tcu::TestStatus::fail("numPrimitivesNeeded=" + de::toString(numPrimitivesNeeded) + " while expected " + de::toString(primitivesToWrite));
1867 }
1868
1869 if (m_parameters.testType == TEST_TYPE_QUERY_RESET)
1870 {
1871 constexpr deUint32 queryResetElements = queryResultElements + 1; // For the availability bit.
1872
1873 union Results
1874 {
1875 deUint32 elements32[queryResetElements];
1876 deUint64 elements64[queryResetElements];
1877 };
1878
1879 const deUint32 queryDataAvailSize (static_cast<deUint32>(queryResetElements * queryResultWidth));
1880 std::vector<deUint8> queryData (queryDataAvailSize, 0u);
1881 Results* queryResults = reinterpret_cast<Results*>(queryData.data());
1882
1883 // Initialize values
1884 if (m_parameters.query64bits)
1885 {
1886 queryResults->elements64[0] = 1u; // numPrimitivesWritten
1887 queryResults->elements64[1] = 1u; // numPrimitivesNeeded
1888 queryResults->elements64[2] = 1u; // Availability bit
1889 }
1890 else
1891 {
1892 queryResults->elements32[0] = 1u; // numPrimitivesWritten
1893 queryResults->elements32[1] = 1u; // numPrimitivesNeeded
1894 queryResults->elements32[2] = 1u; // Availability bit
1895 }
1896
1897 vk.resetQueryPool(device, *queryPool, queryIndex, queryCountersNumber);
1898
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]);
1903
1904 /* From the Vulkan spec:
1905 *
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.
1909 */
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");
1914
1915 }
1916
1917 return tcu::TestStatus::pass("Pass");
1918 }
1919
1920 class TransformFeedbackMultiQueryTestInstance : public TransformFeedbackTestInstance
1921 {
1922 public:
1923 TransformFeedbackMultiQueryTestInstance (Context& context, const TestParameters& parameters);
1924
1925 protected:
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);
1929 };
1930
TransformFeedbackMultiQueryTestInstance(Context & context,const TestParameters & parameters)1931 TransformFeedbackMultiQueryTestInstance::TransformFeedbackMultiQueryTestInstance (Context& context, const TestParameters& parameters)
1932 : TransformFeedbackTestInstance (context, parameters)
1933 {
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;
1946
1947 DE_ASSERT(m_parameters.partCount == 2u);
1948
1949 if (!features.geometryShader)
1950 TCU_THROW(NotSupportedError, "Missing feature: geometryShader");
1951
1952 if (transformFeedbackFeatures.geometryStreams == DE_FALSE)
1953 TCU_THROW(NotSupportedError, "geometryStreams feature is not supported");
1954
1955 if (streamsSupported < streamsRequired)
1956 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackStreams=" + de::toString(streamsSupported) + ", while test requires " + de::toString(streamsRequired)).c_str());
1957
1958 if (tfBuffersSupported < tfBuffersRequired)
1959 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBuffers=" + de::toString(tfBuffersSupported) + ", while test requires " + de::toString(tfBuffersRequired)).c_str());
1960
1961 if (tfStreamDataSizeSupported < bytesPerVertex)
1962 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackStreamDataSize=" + de::toString(tfStreamDataSizeSupported) + ", while test requires " + de::toString(bytesPerVertex)).c_str());
1963
1964 if (tfBufferDataSizeSupported < bytesPerVertex)
1965 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBufferDataSize=" + de::toString(tfBufferDataSizeSupported) + ", while test requires " + de::toString(bytesPerVertex)).c_str());
1966
1967 if (tfBufferDataStrideSupported < bytesPerVertex)
1968 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBufferDataStride=" + de::toString(tfBufferDataStrideSupported) + ", while test requires " + de::toString(bytesPerVertex)).c_str());
1969
1970 if (m_transformFeedbackProperties.transformFeedbackQueries == DE_FALSE)
1971 TCU_THROW(NotSupportedError, "transformFeedbackQueries feature is not supported");
1972 }
1973
generateSizesList(const size_t bufBytes,const size_t chunkCount)1974 std::vector<VkDeviceSize> TransformFeedbackMultiQueryTestInstance::generateSizesList (const size_t bufBytes, const size_t chunkCount)
1975 {
1976 const VkDeviceSize chunkSize = bufBytes / chunkCount;
1977 std::vector<VkDeviceSize> result (chunkCount, chunkSize);
1978
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);
1984
1985 return result;
1986 }
1987
verifyTransformFeedbackBuffer(const MovePtr<Allocation> & bufAlloc,const deUint32 bufBytes,const deUint32 bufOffset,const float expected)1988 void TransformFeedbackMultiQueryTestInstance::verifyTransformFeedbackBuffer (const MovePtr<Allocation>& bufAlloc, const deUint32 bufBytes, const deUint32 bufOffset, const float expected)
1989 {
1990 const DeviceInterface& vk = m_context.getDeviceInterface();
1991 const VkDevice device = m_context.getDevice();
1992
1993 invalidateAlloc(vk, device, *bufAlloc);
1994
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]);
1998
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));
2002 }
2003
iterate(void)2004 tcu::TestStatus TransformFeedbackMultiQueryTestInstance::iterate (void)
2005 {
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();
2012
2013 const Unique<VkRenderPass> renderPass (makeRenderPass (vk, device, VK_FORMAT_UNDEFINED));
2014
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));
2017
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));
2023
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;
2036
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 } });
2046
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);
2050
2051 DE_ASSERT(queryCountersNumber == queryExpectedData.size());
2052
2053 VK_CHECK(vk.bindBufferMemory(device, *queryPoolResultsBuffer, queryPoolResultsBufferAlloc->getMemory(), queryPoolResultsBufferAlloc->getOffset()));
2054
2055 VK_CHECK(vk.bindBufferMemory(device, *tfBuf, tfBufAllocation->getMemory(), tfBufAllocation->getOffset()));
2056
2057 beginCommandBuffer(vk, *cmdBuffer);
2058 {
2059 vk.cmdResetQueryPool(*cmdBuffer, *queryPool, queryIndex, queryCountersNumber);
2060
2061 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
2062 {
2063 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
2064
2065 vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0u, m_parameters.partCount, &tfBufArray[0], &tfBufBindingOffsets[0], &tfBufBindingSizes[0]);
2066
2067 vk.cmdBeginQueryIndexedEXT(*cmdBuffer, *queryPool, queryIndex + 0, 0u, 0u);
2068 vk.cmdBeginQueryIndexedEXT(*cmdBuffer, *queryPool, queryIndex + 1, 0u, m_parameters.streamId);
2069 {
2070 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
2071 {
2072 vk.cmdDraw(*cmdBuffer, numDrawVertices, 1u, 0u, 0u);
2073 }
2074 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
2075 }
2076 vk.cmdEndQueryIndexedEXT(*cmdBuffer, *queryPool, queryIndex + 1, m_parameters.streamId);
2077 vk.cmdEndQueryIndexedEXT(*cmdBuffer, *queryPool, queryIndex + 0, 0);
2078 }
2079 endRenderPass(vk, *cmdBuffer);
2080
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);
2082 }
2083 endCommandBuffer(vk, *cmdBuffer);
2084 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
2085
2086 vk.getQueryPoolResults(device, *queryPool, queryIndex, queryCountersNumber, queryDataSize, queryResultData.data(), queryStride, (vk::VK_QUERY_RESULT_WAIT_BIT));
2087
2088 DE_ASSERT(queryResultData.size() == queryCountersNumber && queryExpectedData.size() == queryCountersNumber);
2089 DE_ASSERT(queryCountersNumber > 0);
2090
2091 for (size_t counterNdx = 0; counterNdx < queryCountersNumber; ++counterNdx)
2092 {
2093 const TransformFeedbackQuery& result = queryResultData[counterNdx];
2094 const TransformFeedbackQuery& expected = queryExpectedData[counterNdx];
2095
2096 DE_ASSERT(expected.written != queryInvalidCounterValue);
2097 DE_ASSERT(expected.attempts != queryInvalidCounterValue);
2098
2099 if (result.written == queryInvalidCounterValue || result.attempts == queryInvalidCounterValue)
2100 return tcu::TestStatus::fail("Query counters read failed");
2101
2102 if (result.written != expected.written)
2103 {
2104 const std::string comment = "At counter " + de::toString(counterNdx) + " vertices written " + de::toString(result.written) + ", while expected " + de::toString(expected.written);
2105
2106 return tcu::TestStatus::fail(comment.c_str());
2107 }
2108
2109
2110 if (result.attempts != expected.attempts)
2111 {
2112 const std::string comment = "At counter " + de::toString(counterNdx) + " attempts committed " + de::toString(result.attempts) + ", while expected " + de::toString(expected.attempts);
2113
2114 return tcu::TestStatus::fail(comment.c_str());
2115 }
2116
2117 verifyTransformFeedbackBuffer(tfBufAllocation, bytesPerVertex * expected.written, static_cast<deUint32>(tfBufBindingOffsets[counterNdx]), tfBufExpectedValues[counterNdx]);
2118 }
2119
2120 return tcu::TestStatus::pass("Pass");
2121 }
2122
2123
2124 class TransformFeedbackTestCase : public vkt::TestCase
2125 {
2126 public:
2127 TransformFeedbackTestCase (tcu::TestContext &context, const char *name, const char *description, const TestParameters& parameters);
2128
2129 protected:
2130 vkt::TestInstance* createInstance (vkt::Context& context) const;
2131 void initPrograms (SourceCollections& programCollection) const;
2132
2133 TestParameters m_parameters;
2134 };
2135
TransformFeedbackTestCase(tcu::TestContext & context,const char * name,const char * description,const TestParameters & 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)
2139 {
2140 }
2141
createInstance(vkt::Context & context) const2142 vkt::TestInstance* TransformFeedbackTestCase::createInstance (vkt::Context& context) const
2143 {
2144 if (m_parameters.testType == TEST_TYPE_BASIC)
2145 return new TransformFeedbackBasicTestInstance(context, m_parameters);
2146
2147 if (m_parameters.testType == TEST_TYPE_RESUME)
2148 return new TransformFeedbackResumeTestInstance(context, m_parameters);
2149
2150 if (m_parameters.testType == TEST_TYPE_XFB_POINTSIZE)
2151 return new TransformFeedbackBuiltinTestInstance(context, m_parameters);
2152
2153 if (m_parameters.testType == TEST_TYPE_XFB_CLIPDISTANCE)
2154 return new TransformFeedbackBuiltinTestInstance(context, m_parameters);
2155
2156 if (m_parameters.testType == TEST_TYPE_XFB_CULLDISTANCE)
2157 return new TransformFeedbackBuiltinTestInstance(context, m_parameters);
2158
2159 if (m_parameters.testType == TEST_TYPE_XFB_CLIP_AND_CULL)
2160 return new TransformFeedbackBuiltinTestInstance(context, m_parameters);
2161
2162 if (m_parameters.testType == TEST_TYPE_WINDING)
2163 return new TransformFeedbackWindingOrderTestInstance(context, m_parameters);
2164
2165 if (m_parameters.testType == TEST_TYPE_STREAMS)
2166 return new TransformFeedbackStreamsTestInstance(context, m_parameters);
2167
2168 if (m_parameters.testType == TEST_TYPE_STREAMS_POINTSIZE)
2169 return new TransformFeedbackStreamsTestInstance(context, m_parameters);
2170
2171 if (m_parameters.testType == TEST_TYPE_STREAMS_CLIPDISTANCE)
2172 return new TransformFeedbackStreamsTestInstance(context, m_parameters);
2173
2174 if (m_parameters.testType == TEST_TYPE_STREAMS_CULLDISTANCE)
2175 return new TransformFeedbackStreamsTestInstance(context, m_parameters);
2176
2177 if (m_parameters.testType == TEST_TYPE_MULTISTREAMS)
2178 return new TransformFeedbackMultistreamTestInstance(context, m_parameters);
2179
2180 if (m_parameters.testType == TEST_TYPE_DRAW_INDIRECT)
2181 return new TransformFeedbackIndirectDrawTestInstance(context, m_parameters);
2182
2183 if (m_parameters.testType == TEST_TYPE_BACKWARD_DEPENDENCY)
2184 return new TransformFeedbackBackwardDependencyTestInstance(context, m_parameters);
2185
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);
2190
2191 if (m_parameters.testType == TEST_TYPE_MULTIQUERY)
2192 return new TransformFeedbackMultiQueryTestInstance(context, m_parameters);
2193
2194 TCU_THROW(InternalError, "Specified test type not found");
2195 }
2196
initPrograms(SourceCollections & programCollection) const2197 void TransformFeedbackTestCase::initPrograms (SourceCollections& programCollection) const
2198 {
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;
2212
2213 if (vertexShaderOnly)
2214 {
2215 // Vertex shader
2216 {
2217 std::ostringstream src;
2218 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2219 << "\n"
2220 << "layout(push_constant) uniform pushConstants\n"
2221 << "{\n"
2222 << " uint start;\n"
2223 << "} uInput;\n"
2224 << "\n"
2225 << "layout(xfb_buffer = 0, xfb_offset = 0, xfb_stride = 4, location = 0) out uint idx_out;\n"
2226 << "\n"
2227 << "void main(void)\n"
2228 << "{\n"
2229 << " idx_out = uInput.start + gl_VertexIndex;\n"
2230 << "}\n";
2231
2232 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
2233 }
2234
2235 return;
2236 }
2237
2238 if (m_parameters.primTopology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST)
2239 {
2240 // Vertex shader
2241 {
2242 std::ostringstream src;
2243 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2244 << "layout(push_constant) uniform pushConstants\n"
2245 << "{\n"
2246 << " uint start;\n"
2247 << "} uInput;\n"
2248 << "void main(void)\n"
2249 << "{\n"
2250 << "}\n";
2251 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
2252 }
2253
2254 // Tesselation control shader
2255 {
2256 std::ostringstream src;
2257 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2258 << "layout(vertices = 3) out;\n"
2259 << "void main (void)\n"
2260 << "{\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"
2265 << "}\n";
2266 programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str());
2267 }
2268
2269 // Tessellation evaluation shader
2270 {
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"
2275 << "\n"
2276 << "void main (void)\n"
2277 << "{\n"
2278 << " idx_out = gl_PrimitiveID;\n" // all vertex generated from patch will have its id
2279 << "}\n";
2280 programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
2281 }
2282
2283 return;
2284 }
2285
2286 if (xfbBuiltinPipeline)
2287 {
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"
2292 : "";
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"
2298 : "";
2299
2300 // Vertex shader
2301 {
2302 std::ostringstream src;
2303 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2304 << "\n"
2305 << "layout(xfb_buffer = " << m_parameters.partCount - 1 << ", xfb_offset = 0) out gl_PerVertex\n"
2306 << "{\n"
2307 << outputBuiltIn
2308 << "};\n"
2309 << "\n"
2310 << "void main(void)\n"
2311 << "{\n"
2312 << operationBuiltIn
2313 << "}\n";
2314
2315 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
2316 }
2317
2318 return;
2319 }
2320
2321 if (m_parameters.testType == TEST_TYPE_MULTISTREAMS)
2322 {
2323 // vertex shader
2324 {
2325 std::ostringstream src;
2326 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2327 << "\n"
2328 << "void main(void)\n"
2329 << "{\n"
2330 << "}\n";
2331
2332 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
2333 }
2334
2335 // geometry shader
2336 {
2337 const deUint32 s = m_parameters.streamId;
2338 std::ostringstream src;
2339
2340 DE_ASSERT(s != 0);
2341
2342 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2343 << "\n"
2344 << "layout(points) in;\n"
2345 << "\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"
2349 << "\n"
2350 << "const int counts[] = int[](1, 1, 2, 4, 8);\n"
2351 << "\n"
2352 << "void main(void)\n"
2353 << "{\n"
2354 << " int c0 = 0;\n"
2355 << " int c1 = 0;\n"
2356 << "\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"
2360 << "\n"
2361 << " for (int i = 0; i < counts.length(); i++)\n"
2362 << " {\n"
2363 << " const int n0 = counts[i];\n"
2364 << " const int n1 = counts[counts.length() - 1 - i];\n"
2365 << "\n"
2366 << " for (int j = 0; j < n0; j++)\n"
2367 << " {\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"
2372 << " }\n"
2373 << "\n"
2374 << " for (int j = 0; j < n1; j++)\n"
2375 << " {\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"
2380 << " }\n"
2381 << " }\n"
2382 << "}\n";
2383
2384 programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
2385 }
2386
2387 return;
2388 }
2389
2390 if (requiresFullPipeline)
2391 {
2392 // vertex shader
2393 {
2394 std::ostringstream src;
2395 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2396 << "\n"
2397 << "void main(void)\n"
2398 << "{\n"
2399 << "}\n";
2400
2401 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
2402 }
2403
2404 // geometry shader
2405 {
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"
2412 : "";
2413 std::ostringstream src;
2414
2415 DE_ASSERT(s != 0);
2416
2417 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2418 << "\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"
2423 << "\n"
2424 << "layout(stream = " << s << ") out gl_PerVertex\n"
2425 << "{\n"
2426 << " vec4 gl_Position;\n"
2427 << outputBuiltIn
2428 << "};\n"
2429 << "\n"
2430 << "void main(void)\n"
2431 << "{\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"
2447 << "\n";
2448
2449 if (m_parameters.testType == TEST_TYPE_STREAMS)
2450 {
2451 src << " if (gl_PrimitiveIDIn == 0)\n"
2452 << " {\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"
2457 << " }\n"
2458 << " else\n"
2459 << " {\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"
2464 << " }\n";
2465 }
2466
2467 if (m_parameters.testType == TEST_TYPE_STREAMS_POINTSIZE)
2468 {
2469 const std::string pointSize = "gl_PointSize = " + de::toString(m_parameters.pointSize) + ".0f";
2470
2471 src << " if (gl_PrimitiveIDIn == 0)\n"
2472 << " {\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"
2477 << " }\n"
2478 << " else\n"
2479 << " {\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"
2484 << " }\n";
2485 }
2486
2487 if (m_parameters.testType == TEST_TYPE_STREAMS_CLIPDISTANCE)
2488 {
2489 src << " if (gl_PrimitiveIDIn == 0)\n"
2490 << " {\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"
2495 << " }\n"
2496 << " else\n"
2497 << " {\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"
2502 << " }\n";
2503 }
2504
2505 if (m_parameters.testType == TEST_TYPE_STREAMS_CULLDISTANCE)
2506 {
2507 src << " if (gl_PrimitiveIDIn == 0)\n"
2508 << " {\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"
2517 << " }\n"
2518 << " else\n"
2519 << " {\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"
2528 << " }\n";
2529 }
2530
2531 src << "}\n";
2532
2533 programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
2534 }
2535
2536 // Fragment shader
2537 {
2538 std::ostringstream src;
2539 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2540 << "\n"
2541 << "layout(location = 0) in vec4 i_color;\n"
2542 << "layout(location = 0) out vec4 o_color;\n"
2543 << "\n"
2544 << "void main(void)\n"
2545 << "{\n"
2546 << " o_color = i_color;\n"
2547 << "}\n";
2548
2549 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
2550 }
2551
2552 return;
2553 }
2554
2555 if (m_parameters.testType == TEST_TYPE_DRAW_INDIRECT)
2556 {
2557 // vertex shader
2558 {
2559 std::ostringstream src;
2560 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2561 << "\n"
2562 << "layout(location = 0) in vec4 in_position;\n"
2563 << "\n"
2564 << "void main(void)\n"
2565 << "{\n"
2566 << " gl_Position = in_position;\n"
2567 << "}\n";
2568
2569 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
2570 }
2571
2572 // Fragment shader
2573 {
2574 std::ostringstream src;
2575 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2576 << "\n"
2577 << "layout(location = 0) out vec4 o_color;\n"
2578 << "\n"
2579 << "void main(void)\n"
2580 << "{\n"
2581 << " o_color = vec4(1.0, 1.0, 1.0, 1.0);\n"
2582 << "}\n";
2583
2584 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
2585 }
2586
2587 return;
2588 }
2589
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)
2593 {
2594 struct TopologyShaderInfo
2595 {
2596 std::string glslIn;
2597 std::string glslOut;
2598 std::string spirvIn;
2599 std::string spirvOut;
2600 };
2601
2602 const std::map<VkPrimitiveTopology, TopologyShaderInfo> primitiveNames =
2603 {
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" } }
2614 };
2615
2616 // Vertex shader
2617 {
2618 std::ostringstream src;
2619 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2620 << "\n"
2621 << "layout(location = 0) out vec4 out0;\n"
2622 << "\n"
2623 << "void main(void)\n"
2624 << "{\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"
2627 << "}\n";
2628
2629 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
2630 }
2631
2632 // geometry shader
2633 if (m_parameters.streamId == 0)
2634 {
2635 std::ostringstream src;
2636
2637 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2638 << "\n"
2639 << "layout(" << primitiveNames.at(m_parameters.primTopology).glslIn << ") in;\n"
2640 << "layout(location = 0) in vec4 in0[];\n"
2641 << "\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"
2644 << "\n"
2645 << "void main(void)\n"
2646 << "{\n";
2647
2648 for (deUint32 i = 0; i < topologyData.at(m_parameters.primTopology).primSize; i++)
2649 {
2650 src << " out0 = in0[" << i << "];\n"
2651 << " EmitVertex();\n";
2652 }
2653
2654 src << " EndPrimitive();\n"
2655 << "}\n";
2656
2657 programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
2658 }
2659 else
2660 {
2661 const deUint32 s = m_parameters.streamId;
2662 std::ostringstream src;
2663
2664 if (m_parameters.testType == TEST_TYPE_QUERY_GET)
2665 {
2666 // The SPIR-V program below is roughly equivalent to the following GLSL code:
2667 //
2668 // #version 450
2669 // #extension GL_ARB_enhanced_layouts : require
2670 //
2671 // layout(points) in;
2672 // layout(location = 0) in vec4 in0[];
2673 //
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;
2677 // } outBlock;
2678 //
2679 // void main(void)
2680 // {
2681 // outBlock.out0 = in0[0];
2682 // EmitStreamVertex(1);
2683 // EndStreamPrimitive(1);
2684 // }
2685 //
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.
2689 src << "; SPIR-V\n"
2690 << "; Version: 1.0\n"
2691 << "; Generator: Khronos Glslang Reference Front End; 10\n"
2692 << "; Bound: 64\n"
2693 << "; Schema: 0\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";
2730
2731 for (deUint32 i = 1; i < topologyData.at(m_parameters.primTopology).primSize + 1; i++)
2732 {
2733 src << "%int_" << i << " = OpConstant %int " << i << "\n";
2734 }
2735
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";
2746
2747 for (deUint32 i = 1; i < topologyData.at(m_parameters.primTopology).primSize + 1; i++)
2748 {
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";
2754 }
2755
2756 src << " OpEndStreamPrimitive %streamNum\n"
2757 << " OpReturn\n"
2758 << " OpFunctionEnd\n"
2759 ;
2760
2761 programCollection.spirvAsmSources.add("geom") << src.str();
2762 }
2763 else
2764 {
2765 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2766 << "\n"
2767 << "layout(" << primitiveNames.at(m_parameters.primTopology).glslIn << ") in;\n"
2768 << "layout(location = 0) in vec4 in0[];\n"
2769 << "\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"
2772 << "\n"
2773 << "void main(void)\n"
2774 << "{\n";
2775
2776 for (deUint32 i = 0; i < topologyData.at(m_parameters.primTopology).primSize; i++)
2777 {
2778 src << " out0 = in0[" << i << "];\n"
2779 << " EmitStreamVertex(" << s << ");\n";
2780 }
2781
2782 src << " EndStreamPrimitive(" << s << ");\n"
2783 << "}\n";
2784
2785 programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
2786 }
2787 }
2788
2789 return;
2790 }
2791
2792 if (m_parameters.testType == TEST_TYPE_MULTIQUERY)
2793 {
2794 // vertex shader
2795 {
2796 std::ostringstream src;
2797 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2798 << "\n"
2799 << "layout(location = 0) out ivec4 out0;\n"
2800 << "\n"
2801 << "void main(void)\n"
2802 << "{\n"
2803 << " out0 = ivec4(gl_VertexIndex);\n"
2804 << "}\n";
2805
2806 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
2807 }
2808
2809 // geometry shader
2810 {
2811 const deUint32 s = m_parameters.streamId;
2812 std::ostringstream src;
2813
2814 DE_ASSERT(s != 0);
2815
2816 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2817 << "\n"
2818 << "layout(points) in;\n"
2819 << "\n"
2820 << "layout(points, max_vertices = 4) out;\n"
2821 << "\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"
2824 << "\n"
2825 << "void main(void)\n"
2826 << "{\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"
2831 << "\n"
2832 << " for (int j = 0; j < n0; j++)\n"
2833 << " {\n"
2834 << " out0 = vec4(c0);\n"
2835 << " EmitStreamVertex(0);\n"
2836 << " EndStreamPrimitive(0);\n"
2837 << " }\n"
2838 << "\n"
2839 << " for (int j = 0; j < n1; j++)\n"
2840 << " {\n"
2841 << " out1 = vec4(c1);\n"
2842 << " EmitStreamVertex(" << s << ");\n"
2843 << " EndStreamPrimitive(" << s << ");\n"
2844 << " }\n"
2845 << "}\n";
2846
2847 programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
2848 }
2849
2850 return;
2851 }
2852
2853 DE_ASSERT(0 && "Unknown test");
2854 }
2855
createTransformFeedbackSimpleTests(tcu::TestCaseGroup * group)2856 void createTransformFeedbackSimpleTests(tcu::TestCaseGroup* group)
2857 {
2858 {
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" };
2863
2864 for (deUint32 testTypesNdx = 0; testTypesNdx < DE_LENGTH_OF_ARRAY(testTypes); ++testTypesNdx)
2865 {
2866 const TestType testType = testTypes[testTypesNdx];
2867 const std::string testName = testTypeNames[testTypesNdx];
2868
2869 for (deUint32 bufferCountsNdx = 0; bufferCountsNdx < DE_LENGTH_OF_ARRAY(bufferCounts); ++bufferCountsNdx)
2870 {
2871 const deUint32 partCount = bufferCounts[bufferCountsNdx];
2872
2873 for (deUint32 bufferSizesNdx = 0; bufferSizesNdx < DE_LENGTH_OF_ARRAY(bufferSizes); ++bufferSizesNdx)
2874 {
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 };
2877
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));
2883 }
2884 }
2885 }
2886 }
2887
2888 {
2889 const deUint32 bufferCounts[] = { 6u, 8u, 10u, 12u };
2890 const TestType testType = TEST_TYPE_WINDING;
2891 const std::string testName = "winding";
2892
2893 for (const auto& topology : topologyData)
2894 {
2895 // Note: no need to test POINT_LIST as is tested in many tests.
2896 if (topology.first == VK_PRIMITIVE_TOPOLOGY_POINT_LIST)
2897 continue;
2898
2899 for (deUint32 bufferCountsNdx = 0; bufferCountsNdx < DE_LENGTH_OF_ARRAY(bufferCounts); ++bufferCountsNdx)
2900 {
2901 const deUint32 vertexCount = bufferCounts[bufferCountsNdx];
2902
2903 TestParameters parameters = { testType, 0u, vertexCount, 0u, 0u, 0u, STREAM_ID_0_NORMAL, false, false, topology.first };
2904
2905 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_" + topology.second.topologyName + de::toString(vertexCount)).c_str(), "Topology winding test", parameters));
2906 }
2907 }
2908 }
2909
2910 {
2911 const deUint32 vertexStrides[] = { 4u, 61u, 127u, 251u, 509u };
2912 const TestType testType = TEST_TYPE_DRAW_INDIRECT;
2913 const std::string testName = "draw_indirect";
2914
2915 for (deUint32 vertexStridesNdx = 0; vertexStridesNdx < DE_LENGTH_OF_ARRAY(vertexStrides); ++vertexStridesNdx)
2916 {
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 };
2919
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));
2925 }
2926 }
2927
2928 {
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 };
2932
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));
2938
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));
2941 }
2942
2943 {
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";
2952
2953 for (const auto& topology : topologyData)
2954 {
2955 // Currently, we don't test tessellation here.
2956 if (topology.first == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST)
2957 continue;
2958
2959 for (const auto& streamCounts : usedStreamId)
2960 {
2961 const deUint32 streamId = streamCounts;
2962
2963 for (const auto& numVertices : vertexCounts)
2964 {
2965 for (deUint32 i = 0; i < 2; ++i)
2966 {
2967 const bool query64Bits = (i == 1);
2968 const std::string widthStr = (query64Bits ? "_64bits" : "_32bits");
2969
2970 deUint32 vertCount = numVertices;
2971
2972 // The number of vertices in original test was 4.
2973 if (topology.first == VK_PRIMITIVE_TOPOLOGY_POINT_LIST && vertCount == 6) vertCount -= 2;
2974
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);
2978
2979 DE_ASSERT(vertexCount > 0);
2980
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));
2986
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));
2990
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));
2994
2995 if (streamId == 0)
2996 {
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));
3005 }
3006 }
3007 }
3008 }
3009 }
3010 }
3011 }
3012
createTransformFeedbackStreamsSimpleTests(tcu::TestCaseGroup * group)3013 void createTransformFeedbackStreamsSimpleTests (tcu::TestCaseGroup* group)
3014 {
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" };
3018
3019 for (deUint32 testTypesNdx = 0; testTypesNdx < DE_LENGTH_OF_ARRAY(testTypes); ++testTypesNdx)
3020 {
3021 const TestType testType = testTypes[testTypesNdx];
3022 const std::string testName = testTypeNames[testTypesNdx];
3023 const deUint32 pointSize = (testType == TEST_TYPE_STREAMS_POINTSIZE) ? 2u : 0u;
3024
3025 for (deUint32 streamCountsNdx = 0; streamCountsNdx < DE_LENGTH_OF_ARRAY(usedStreamId); ++streamCountsNdx)
3026 {
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 };
3029
3030 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_" + de::toString(streamId)).c_str(), "Streams usage test", parameters));
3031 }
3032 }
3033
3034 {
3035 const TestType testType = TEST_TYPE_MULTISTREAMS;
3036 const std::string testName = "multistreams";
3037
3038 for (deUint32 bufferCountsNdx = 0; bufferCountsNdx < DE_LENGTH_OF_ARRAY(usedStreamId); ++bufferCountsNdx)
3039 {
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 };
3044
3045 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_" + de::toString(streamId)).c_str(), "Simultaneous multiple streams usage test", parameters));
3046 }
3047 }
3048
3049 {
3050 const TestType testType = TEST_TYPE_MULTIQUERY;
3051 const std::string testName = "multiquery";
3052
3053 for (deUint32 bufferCountsNdx = 0; bufferCountsNdx < DE_LENGTH_OF_ARRAY(usedStreamId); ++bufferCountsNdx)
3054 {
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 };
3059
3060 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_" + de::toString(streamId)).c_str(), "Simultaneous multiple queries usage test", parameters));
3061 }
3062 }
3063 }
3064
createTransformFeedbackAndStreamsSimpleTests(tcu::TestCaseGroup * group)3065 void createTransformFeedbackAndStreamsSimpleTests (tcu::TestCaseGroup* group)
3066 {
3067 createTransformFeedbackSimpleTests(group);
3068 createTransformFeedbackStreamsSimpleTests(group);
3069 }
3070 } // anonymous
3071
createTransformFeedbackSimpleTests(tcu::TestContext & testCtx)3072 tcu::TestCaseGroup* createTransformFeedbackSimpleTests (tcu::TestContext& testCtx)
3073 {
3074 return createTestGroup(testCtx, "simple", "Transform Feedback Simple tests", createTransformFeedbackAndStreamsSimpleTests);
3075 }
3076
3077 } // TransformFeedback
3078 } // vkt
3079