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 #include "tcuCommandLine.hpp"
45
46 #include <iostream>
47 #include <functional>
48 #include <set>
49 #include <algorithm>
50
51 namespace vkt
52 {
53 namespace TransformFeedback
54 {
55 namespace
56 {
57 using namespace vk;
58 using de::MovePtr;
59 using de::UniquePtr;
60 using de::SharedPtr;
61
62 #define VALIDATE_MINIMUM(A,B) if ((A) < (B)) TCU_FAIL(#A "==" + de::toString(A) + " which is less than required by specification (" + de::toString(B) + ")")
63 #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)))
64
65 const deUint32 INVOCATION_COUNT = 8u;
66 const std::vector<deUint32> LINES_LIST { 2, 6, 3 };
67 const std::vector<deUint32> TRIANGLES_LIST { 3, 8, 6, 5, 4 };
68
69 enum TestType
70 {
71 TEST_TYPE_BASIC,
72 TEST_TYPE_RESUME,
73 TEST_TYPE_STREAMS,
74 TEST_TYPE_XFB_POINTSIZE,
75 TEST_TYPE_XFB_CLIPDISTANCE,
76 TEST_TYPE_XFB_CULLDISTANCE,
77 TEST_TYPE_XFB_CLIP_AND_CULL,
78 TEST_TYPE_WINDING,
79 TEST_TYPE_STREAMS_POINTSIZE,
80 TEST_TYPE_STREAMS_CLIPDISTANCE,
81 TEST_TYPE_STREAMS_CULLDISTANCE,
82 TEST_TYPE_MULTISTREAMS,
83 TEST_TYPE_DRAW_INDIRECT,
84 TEST_TYPE_BACKWARD_DEPENDENCY,
85 TEST_TYPE_QUERY_GET,
86 TEST_TYPE_QUERY_COPY,
87 TEST_TYPE_QUERY_COPY_STRIDE_ZERO,
88 TEST_TYPE_QUERY_RESET,
89 TEST_TYPE_MULTIQUERY,
90 TEST_TYPE_DEPTH_CLIP_CONTROL_VERTEX,
91 TEST_TYPE_DEPTH_CLIP_CONTROL_GEOMETRY,
92 TEST_TYPE_DEPTH_CLIP_CONTROL_TESE,
93 TEST_TYPE_LINES_TRIANGLES,
94 TEST_TYPE_LAST
95 };
96
97 enum StreamId0Mode
98 {
99 STREAM_ID_0_NORMAL = 0,
100 STREAM_ID_0_BEGIN_QUERY_INDEXED = 1,
101 STREAM_ID_0_END_QUERY_INDEXED = 2,
102 };
103
104 struct TestParameters
105 {
106 TestType testType;
107 deUint32 bufferSize;
108 deUint32 partCount;
109 deUint32 streamId;
110 deUint32 pointSize;
111 deUint32 vertexStride;
112 StreamId0Mode streamId0Mode;
113 bool query64bits;
114 bool noOffsetArray;
115 bool requireRastStreamSelect;
116 bool omitShaderWrite;
117 VkPrimitiveTopology primTopology;
118 };
119
120 struct TopologyInfo
121 {
122 deUint32 primSize; // The size of the on primitive.
123 std::string topologyName; // The suffix for the name of test.
124 std::function<deUint64(deUint64)> getNumPrimitives; // The number of primitives generated.
125 std::function<deUint64(deUint64)> getNumVertices; // The number of vertices generated.
126 };
127
128 const std::map<VkPrimitiveTopology, TopologyInfo> topologyData =
129 {
__anond6854b9f0202() 130 { VK_PRIMITIVE_TOPOLOGY_POINT_LIST , { 1, "" ,[](deUint64 vertexCount) { return vertexCount; } ,[](deUint64 primCount) { return primCount; }, } },
__anond6854b9f0402() 131 { VK_PRIMITIVE_TOPOLOGY_LINE_LIST , { 2, "line_list_" ,[](deUint64 vertexCount) { return vertexCount / 2u; } ,[](deUint64 primCount) { return primCount * 2u; }, } },
__anond6854b9f0602() 132 { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP , { 2, "line_strip_" ,[](deUint64 vertexCount) { return vertexCount - 1u; } ,[](deUint64 primCount) { return primCount + 1u; }, } },
__anond6854b9f0802() 133 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST , { 3, "triangle_list_" ,[](deUint64 vertexCount) { return vertexCount / 3u; } ,[](deUint64 primCount) { return primCount * 3u; }, } },
__anond6854b9f0b02() 134 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP , { 3, "triangle_strip_" ,[](deUint64 vertexCount) { return vertexCount - 2u; } ,[](deUint64 primCount) { return primCount + 2u; }, } },
__anond6854b9f0d02() 135 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN , { 3, "triangle_fan_" ,[](deUint64 vertexCount) { return vertexCount - 2u; } ,[](deUint64 primCount) { return primCount + 2u; }, } },
__anond6854b9f0f02() 136 { VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY , { 2, "line_list_with_adjacency_" ,[](deUint64 vertexCount) { return vertexCount / 4u; } ,[](deUint64 primCount) { return primCount * 4u; }, } },
__anond6854b9f1002() 137 { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY , { 2, "line_strip_with_adjacency_" ,[](deUint64 vertexCount) { return vertexCount - 3u; } ,[](deUint64 primCount) { return primCount + 3u; }, } },
__anond6854b9f1302() 138 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY , { 3, "triangle_list_with_adjacency_" ,[](deUint64 vertexCount) { return vertexCount / 6u; } ,[](deUint64 primCount) { return primCount * 6u; }, } },
__anond6854b9f1502() 139 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY , { 3, "triangle_strip_with_adjacency_" ,[](deUint64 vertexCount) { return (vertexCount - 4u) / 2u; } ,[](deUint64 primCount) { return primCount * 2u + 4u; }, } },
__anond6854b9f1702() 140 { VK_PRIMITIVE_TOPOLOGY_PATCH_LIST , { 3, "patch_list_" ,[](deUint64 vertexCount) { return vertexCount / 3u; } ,[](deUint64 primCount) { return primCount * 3u; }, } },
141 };
142
143 struct TransformFeedbackQuery
144 {
145 deUint32 written;
146 deUint32 attempts;
147 };
148
149 const deUint32 MINIMUM_TF_BUFFER_SIZE = (1<<27);
150 const deUint32 IMAGE_SIZE = 64u;
151
152 template<typename T>
makeSharedPtr(Move<T> move)153 inline SharedPtr<Unique<T> > makeSharedPtr(Move<T> move)
154 {
155 return SharedPtr<Unique<T> >(new Unique<T>(move));
156 }
157
158 template<typename T>
getInvalidatedHostPtr(const DeviceInterface & vk,const VkDevice device,Allocation & bufAlloc)159 const T* getInvalidatedHostPtr (const DeviceInterface& vk, const VkDevice device, Allocation& bufAlloc)
160 {
161 invalidateAlloc(vk, device, bufAlloc);
162
163 return static_cast<T*>(bufAlloc.getHostPtr());
164 }
165
makePipelineLayout(const DeviceInterface & vk,const VkDevice device)166 Move<VkPipelineLayout> makePipelineLayout (const DeviceInterface& vk,
167 const VkDevice device)
168 {
169 const VkPushConstantRange pushConstantRanges =
170 {
171 VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlags stageFlags;
172 0u, // deUint32 offset;
173 sizeof(deUint32) // deUint32 size;
174 };
175 const VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo =
176 {
177 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
178 DE_NULL, // const void* pNext;
179 (VkPipelineLayoutCreateFlags)0, // VkPipelineLayoutCreateFlags flags;
180 0u, // deUint32 setLayoutCount;
181 DE_NULL, // const VkDescriptorSetLayout* pSetLayouts;
182 1u, // deUint32 pushConstantRangeCount;
183 &pushConstantRanges, // const VkPushConstantRange* pPushConstantRanges;
184 };
185 return createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
186 }
187
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 fragmentModule,const VkExtent2D renderSize,const deUint32 subpass,const deUint32 * rasterizationStreamPtr=DE_NULL,const VkPrimitiveTopology topology=VK_PRIMITIVE_TOPOLOGY_POINT_LIST,const bool inputVertices=false,const bool depthClipControl=false)188 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface& vk,
189 const VkDevice device,
190 const VkPipelineLayout pipelineLayout,
191 const VkRenderPass renderPass,
192 const VkShaderModule vertexModule,
193 const VkShaderModule tessellationControlModule,
194 const VkShaderModule tessellationEvalModule,
195 const VkShaderModule geometryModule,
196 const VkShaderModule fragmentModule,
197 const VkExtent2D renderSize,
198 const deUint32 subpass,
199 const deUint32* rasterizationStreamPtr = DE_NULL,
200 const VkPrimitiveTopology topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST,
201 const bool inputVertices = false,
202 const bool depthClipControl = false)
203 {
204 VkViewport viewport = makeViewport(renderSize);
205 VkRect2D scissor = makeRect2D(renderSize);
206
207 const VkPipelineViewportDepthClipControlCreateInfoEXT depthClipControlCreateInfo =
208 {
209 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_DEPTH_CLIP_CONTROL_CREATE_INFO_EXT, // VkStructureType sType;
210 DE_NULL, // const void* pNext;
211 VK_TRUE, // VkBool32 negativeOneToOne;
212 };
213
214 const VkPipelineViewportStateCreateInfo viewportStateCreateInfo =
215 {
216 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType
217 depthClipControl ? &depthClipControlCreateInfo : DE_NULL, // const void* pNext
218 (VkPipelineViewportStateCreateFlags)0, // VkPipelineViewportStateCreateFlags flags
219 1u, // deUint32 viewportCount
220 &viewport, // const VkViewport* pViewports
221 1u, // deUint32 scissorCount
222 &scissor // const VkRect2D* pScissors
223 };
224
225 const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo =
226 {
227 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType
228 DE_NULL, // const void* pNext
229 0u, // VkPipelineInputAssemblyStateCreateFlags flags
230 topology, // VkPrimitiveTopology topology
231 VK_FALSE // VkBool32 primitiveRestartEnable
232 };
233
234 const VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo =
235 {
236 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType
237 DE_NULL, // const void* pNext
238 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags
239 0u, // deUint32 vertexBindingDescriptionCount
240 DE_NULL, // const VkVertexInputBindingDescription* pVertexBindingDescriptions
241 0u, // deUint32 vertexAttributeDescriptionCount
242 DE_NULL, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions
243 };
244
245 const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfoPtr = (inputVertices) ? DE_NULL : &vertexInputStateCreateInfo;
246 const VkBool32 disableRasterization = (fragmentModule == DE_NULL);
247 const deUint32 rasterizationStream = (rasterizationStreamPtr == DE_NULL) ? 0 : *rasterizationStreamPtr;
248
249 const VkPipelineRasterizationStateStreamCreateInfoEXT rasterizationStateStreamCreateInfo =
250 {
251 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_STREAM_CREATE_INFO_EXT, // VkStructureType sType;
252 DE_NULL, // const void* pNext;
253 0, // VkPipelineRasterizationStateStreamCreateFlagsEXT flags;
254 rasterizationStream // deUint32 rasterizationStream;
255 };
256
257 const VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo =
258 {
259 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType
260 &rasterizationStateStreamCreateInfo, // const void* pNext
261 0u, // VkPipelineRasterizationStateCreateFlags flags
262 VK_FALSE, // VkBool32 depthClampEnable
263 disableRasterization, // VkBool32 rasterizerDiscardEnable
264 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode
265 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode
266 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace
267 VK_FALSE, // VkBool32 depthBiasEnable
268 0.0f, // float depthBiasConstantFactor
269 0.0f, // float depthBiasClamp
270 0.0f, // float depthBiasSlopeFactor
271 1.0f // float lineWidth
272 };
273
274 const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfoPtr = (rasterizationStreamPtr == DE_NULL) ? DE_NULL : &rasterizationStateCreateInfo;
275
276 const VkPipelineTessellationStateCreateInfo tessStateCreateInfo =
277 {
278 VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, // VkStructureType sType
279 DE_NULL, // const void* pNext
280 0u, // VkPipelineTessellationStateCreateFlags flags
281 3u // deUint32 patchControlPoints
282 };
283
284 return makeGraphicsPipeline(vk, // const DeviceInterface& vk
285 device, // const VkDevice device
286 pipelineLayout, // const VkPipelineLayout pipelineLayout
287 vertexModule, // const VkShaderModule vertexShaderModule
288 tessellationControlModule, // const VkShaderModule tessellationControlModule
289 tessellationEvalModule, // const VkShaderModule tessellationEvalModule
290 geometryModule, // const VkShaderModule geometryShaderModule
291 fragmentModule, // const VkShaderModule fragmentShaderModule
292 renderPass, // const VkRenderPass renderPass
293 subpass, // const deUint32 subpass
294 vertexInputStateCreateInfoPtr, // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo
295 &inputAssemblyStateCreateInfo, // const VkPipelineInputAssemblyStateCreateInfo* inputAssemblyStateCreateInfo
296 &tessStateCreateInfo, // const VkPipelineTessellationStateCreateInfo* tessStateCreateInfo
297 &viewportStateCreateInfo, // const VkPipelineViewportStateCreateInfo* viewportStateCreateInfo
298 rasterizationStateCreateInfoPtr); // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
299 }
300
makeImageCreateInfo(const VkImageCreateFlags flags,const VkImageType type,const VkFormat format,const VkExtent2D size,const deUint32 numLayers,const VkImageUsageFlags usage)301 VkImageCreateInfo makeImageCreateInfo (const VkImageCreateFlags flags, const VkImageType type, const VkFormat format, const VkExtent2D size, const deUint32 numLayers, const VkImageUsageFlags usage)
302 {
303 const VkExtent3D extent = { size.width, size.height, 1u };
304 const VkImageCreateInfo imageParams =
305 {
306 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
307 DE_NULL, // const void* pNext;
308 flags, // VkImageCreateFlags flags;
309 type, // VkImageType imageType;
310 format, // VkFormat format;
311 extent, // VkExtent3D extent;
312 1u, // deUint32 mipLevels;
313 numLayers, // deUint32 arrayLayers;
314 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
315 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
316 usage, // VkImageUsageFlags usage;
317 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
318 0u, // deUint32 queueFamilyIndexCount;
319 DE_NULL, // const deUint32* pQueueFamilyIndices;
320 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
321 };
322 return imageParams;
323 }
324
makeRenderPass(const DeviceInterface & vk,const VkDevice device)325 Move<VkRenderPass> makeRenderPass (const DeviceInterface& vk,
326 const VkDevice device)
327 {
328 std::vector<VkSubpassDescription> subpassDescriptions;
329 std::vector<VkSubpassDependency> subpassDependencies;
330
331 const VkSubpassDescription description =
332 {
333 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags;
334 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
335 0u, // deUint32 inputAttachmentCount;
336 DE_NULL, // const VkAttachmentReference* pInputAttachments;
337 0u, // deUint32 colorAttachmentCount;
338 DE_NULL, // const VkAttachmentReference* pColorAttachments;
339 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
340 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment;
341 0, // deUint32 preserveAttachmentCount;
342 DE_NULL // const deUint32* pPreserveAttachments;
343 };
344 subpassDescriptions.push_back(description);
345
346 const VkSubpassDependency dependency =
347 {
348 0u, // deUint32 srcSubpass;
349 0u, // deUint32 dstSubpass;
350 VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, // VkPipelineStageFlags srcStageMask;
351 VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, // VkPipelineStageFlags dstStageMask;
352 VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT, // VkAccessFlags srcAccessMask;
353 VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT, // VkAccessFlags dstAccessMask;
354 0u // VkDependencyFlags dependencyFlags;
355 };
356 subpassDependencies.push_back(dependency);
357
358 const VkRenderPassCreateInfo renderPassInfo =
359 {
360 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
361 DE_NULL, // const void* pNext;
362 static_cast<VkRenderPassCreateFlags>(0u), // VkRenderPassCreateFlags flags;
363 0u, // deUint32 attachmentCount;
364 DE_NULL, // const VkAttachmentDescription* pAttachments;
365 static_cast<deUint32>(subpassDescriptions.size()), // deUint32 subpassCount;
366 &subpassDescriptions[0], // const VkSubpassDescription* pSubpasses;
367 static_cast<deUint32>(subpassDependencies.size()), // deUint32 dependencyCount;
368 subpassDependencies.size() > 0 ? &subpassDependencies[0] : DE_NULL // const VkSubpassDependency* pDependencies;
369 };
370
371 return createRenderPass(vk, device, &renderPassInfo);
372 }
373
makeImageMemoryBarrier(const VkAccessFlags srcAccessMask,const VkAccessFlags dstAccessMask,const VkImageLayout oldLayout,const VkImageLayout newLayout,const VkImage image,const VkImageSubresourceRange subresourceRange)374 VkImageMemoryBarrier makeImageMemoryBarrier (const VkAccessFlags srcAccessMask,
375 const VkAccessFlags dstAccessMask,
376 const VkImageLayout oldLayout,
377 const VkImageLayout newLayout,
378 const VkImage image,
379 const VkImageSubresourceRange subresourceRange)
380 {
381 const VkImageMemoryBarrier barrier =
382 {
383 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
384 DE_NULL, // const void* pNext;
385 srcAccessMask, // VkAccessFlags outputMask;
386 dstAccessMask, // VkAccessFlags inputMask;
387 oldLayout, // VkImageLayout oldLayout;
388 newLayout, // VkImageLayout newLayout;
389 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
390 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
391 image, // VkImage image;
392 subresourceRange, // VkImageSubresourceRange subresourceRange;
393 };
394 return barrier;
395 }
396
makeBufferMemoryBarrier(const VkAccessFlags srcAccessMask,const VkAccessFlags dstAccessMask,const VkBuffer buffer,const VkDeviceSize offset,const VkDeviceSize bufferSizeBytes)397 VkBufferMemoryBarrier makeBufferMemoryBarrier (const VkAccessFlags srcAccessMask,
398 const VkAccessFlags dstAccessMask,
399 const VkBuffer buffer,
400 const VkDeviceSize offset,
401 const VkDeviceSize bufferSizeBytes)
402 {
403 const VkBufferMemoryBarrier barrier =
404 {
405 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
406 DE_NULL, // const void* pNext;
407 srcAccessMask, // VkAccessFlags srcAccessMask;
408 dstAccessMask, // VkAccessFlags dstAccessMask;
409 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
410 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
411 buffer, // VkBuffer buffer;
412 offset, // VkDeviceSize offset;
413 bufferSizeBytes, // VkDeviceSize size;
414 };
415 return barrier;
416 }
417
makeMemoryBarrier(const VkAccessFlags srcAccessMask,const VkAccessFlags dstAccessMask)418 VkMemoryBarrier makeMemoryBarrier (const VkAccessFlags srcAccessMask,
419 const VkAccessFlags dstAccessMask)
420 {
421 const VkMemoryBarrier barrier =
422 {
423 VK_STRUCTURE_TYPE_MEMORY_BARRIER, // VkStructureType sType;
424 DE_NULL, // const void* pNext;
425 srcAccessMask, // VkAccessFlags outputMask;
426 dstAccessMask, // VkAccessFlags inputMask;
427 };
428 return barrier;
429 }
430
makeQueryPoolCreateInfo(const deUint32 queryCountersNumber)431 VkQueryPoolCreateInfo makeQueryPoolCreateInfo (const deUint32 queryCountersNumber)
432 {
433 const VkQueryPoolCreateInfo queryPoolCreateInfo =
434 {
435 VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, // VkStructureType sType;
436 DE_NULL, // const void* pNext;
437 (VkQueryPoolCreateFlags)0, // VkQueryPoolCreateFlags flags;
438 VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT, // VkQueryType queryType;
439 queryCountersNumber, // deUint32 queryCount;
440 0u, // VkQueryPipelineStatisticFlags pipelineStatistics;
441 };
442
443 return queryPoolCreateInfo;
444 }
445
fillBuffer(const DeviceInterface & vk,const VkDevice device,Allocation & bufferAlloc,VkDeviceSize bufferSize,const void * data,const VkDeviceSize dataSize)446 void fillBuffer (const DeviceInterface& vk, const VkDevice device, Allocation& bufferAlloc, VkDeviceSize bufferSize, const void* data, const VkDeviceSize dataSize)
447 {
448 const VkMappedMemoryRange memRange =
449 {
450 VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType;
451 DE_NULL, // const void* pNext;
452 bufferAlloc.getMemory(), // VkDeviceMemory memory;
453 bufferAlloc.getOffset(), // VkDeviceSize offset;
454 VK_WHOLE_SIZE // VkDeviceSize size;
455 };
456 std::vector<deUint8> dataVec (static_cast<deUint32>(bufferSize), 0u);
457
458 DE_ASSERT(bufferSize >= dataSize);
459
460 deMemcpy(&dataVec[0], data, static_cast<deUint32>(dataSize));
461
462 deMemcpy(bufferAlloc.getHostPtr(), &dataVec[0], dataVec.size());
463 VK_CHECK(vk.flushMappedMemoryRanges(device, 1u, &memRange));
464 }
465
destripedLineCount(const std::vector<deUint32> & lineStripeSizesList)466 deUint32 destripedLineCount (const std::vector<deUint32>& lineStripeSizesList)
467 {
468 deUint32 result = 0;
469
470 DE_ASSERT(!lineStripeSizesList.empty());
471
472 for (auto x : lineStripeSizesList)
473 result += x > 1 ? x - 1 : 0;
474
475 return result;
476 }
477
destripedTriangleCount(const std::vector<deUint32> & triangleStripeSizesList)478 deUint32 destripedTriangleCount (const std::vector<deUint32>& triangleStripeSizesList)
479 {
480 deUint32 result = 0;
481
482 DE_ASSERT(!triangleStripeSizesList.empty());
483
484 for (auto x : triangleStripeSizesList)
485 result += x > 2 ? x - 2 : 0;
486
487 return result;
488 }
489
490 class TransformFeedbackTestInstance : public TestInstance
491 {
492 public:
493 TransformFeedbackTestInstance (Context& context, const TestParameters& parameters);
494 protected:
495 void validateLimits ();
496 std::vector<VkDeviceSize> generateSizesList (const size_t bufBytes, const size_t chunkCount);
497 std::vector<VkDeviceSize> generateOffsetsList (const std::vector<VkDeviceSize>& sizesList);
498 void verifyTransformFeedbackBuffer (const MovePtr<Allocation>& bufAlloc,
499 const deUint32 bufBytes);
500
501 const VkExtent2D m_imageExtent2D;
502 const TestParameters m_parameters;
503 VkPhysicalDeviceTransformFeedbackPropertiesEXT m_transformFeedbackProperties;
504 de::Random m_rnd;
505 };
506
TransformFeedbackTestInstance(Context & context,const TestParameters & parameters)507 TransformFeedbackTestInstance::TransformFeedbackTestInstance (Context& context, const TestParameters& parameters)
508 : TestInstance (context)
509 , m_imageExtent2D (makeExtent2D(IMAGE_SIZE, IMAGE_SIZE))
510 , m_parameters (parameters)
511 , m_rnd (context.getTestContext().getCommandLine().getBaseSeed())
512 {
513 VkPhysicalDeviceProperties2 deviceProperties2;
514
515 deMemset(&deviceProperties2, 0, sizeof(deviceProperties2));
516 deMemset(&m_transformFeedbackProperties, 0, sizeof(m_transformFeedbackProperties));
517
518 deviceProperties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
519 deviceProperties2.pNext = &m_transformFeedbackProperties;
520
521 m_transformFeedbackProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT;
522 m_transformFeedbackProperties.pNext = DE_NULL;
523
524 context.getInstanceInterface().getPhysicalDeviceProperties2(context.getPhysicalDevice(), &deviceProperties2);
525
526 validateLimits();
527 }
528
validateLimits()529 void TransformFeedbackTestInstance::validateLimits ()
530 {
531 VALIDATE_MINIMUM(m_transformFeedbackProperties.maxTransformFeedbackBuffers, 1);
532 VALIDATE_MINIMUM(m_transformFeedbackProperties.maxTransformFeedbackBufferSize, MINIMUM_TF_BUFFER_SIZE);
533 VALIDATE_MINIMUM(m_transformFeedbackProperties.maxTransformFeedbackStreamDataSize, 512);
534 VALIDATE_MINIMUM(m_transformFeedbackProperties.maxTransformFeedbackBufferDataSize, 512);
535 VALIDATE_MINIMUM(m_transformFeedbackProperties.maxTransformFeedbackBufferDataStride, 512);
536
537 VALIDATE_BOOL(m_transformFeedbackProperties.transformFeedbackQueries);
538 VALIDATE_BOOL(m_transformFeedbackProperties.transformFeedbackStreamsLinesTriangles);
539 VALIDATE_BOOL(m_transformFeedbackProperties.transformFeedbackRasterizationStreamSelect);
540 VALIDATE_BOOL(m_transformFeedbackProperties.transformFeedbackDraw);
541 }
542
generateSizesList(const size_t bufBytes,const size_t chunkCount)543 std::vector<VkDeviceSize> TransformFeedbackTestInstance::generateSizesList (const size_t bufBytes, const size_t chunkCount)
544 {
545 const int minChunkSlot = static_cast<int>(1);
546 const int maxChunkSlot = static_cast<int>(bufBytes / sizeof(deUint32));
547 int prevOffsetSlot = 0;
548 std::map<int, bool> offsetsSet;
549 std::vector<VkDeviceSize> result;
550
551 DE_ASSERT(bufBytes <= MINIMUM_TF_BUFFER_SIZE);
552 DE_ASSERT(bufBytes % sizeof(deUint32) == 0);
553 DE_ASSERT(minChunkSlot <= maxChunkSlot);
554 DE_ASSERT(chunkCount > 0);
555 // To be effective this algorithm requires that chunkCount is much less than amount of chunks possible
556 DE_ASSERT(8 * chunkCount <= static_cast<size_t>(maxChunkSlot));
557
558 offsetsSet[0] = true;
559
560 // Create a list of unique offsets first
561 for (size_t chunkNdx = 1; chunkNdx < chunkCount; ++chunkNdx)
562 {
563 int chunkSlot;
564
565 do
566 {
567 chunkSlot = m_rnd.getInt(minChunkSlot, maxChunkSlot - 1);
568 } while (offsetsSet.find(chunkSlot) != offsetsSet.end());
569
570 offsetsSet[chunkSlot] = true;
571 }
572 offsetsSet[maxChunkSlot] = true;
573
574 // Calculate sizes of offsets list
575 result.reserve(chunkCount);
576 for (std::map<int, bool>::iterator mapIt = offsetsSet.begin(); mapIt != offsetsSet.end(); ++mapIt)
577 {
578 const int offsetSlot = mapIt->first;
579
580 if (offsetSlot == 0)
581 continue;
582
583 DE_ASSERT(prevOffsetSlot < offsetSlot && offsetSlot > 0);
584
585 result.push_back(static_cast<VkDeviceSize>(static_cast<size_t>(offsetSlot - prevOffsetSlot) * sizeof(deUint32)));
586
587 prevOffsetSlot = offsetSlot;
588 }
589
590 DE_ASSERT(result.size() == chunkCount);
591
592 return result;
593 }
594
generateOffsetsList(const std::vector<VkDeviceSize> & sizesList)595 std::vector<VkDeviceSize> TransformFeedbackTestInstance::generateOffsetsList (const std::vector<VkDeviceSize>& sizesList)
596 {
597 VkDeviceSize offset = 0ull;
598 std::vector<VkDeviceSize> result;
599
600 result.reserve(sizesList.size());
601
602 for (size_t chunkNdx = 0; chunkNdx < sizesList.size(); ++chunkNdx)
603 {
604 result.push_back(offset);
605
606 offset += sizesList[chunkNdx];
607 }
608
609 DE_ASSERT(sizesList.size() == result.size());
610
611 return result;
612 }
613
verifyTransformFeedbackBuffer(const MovePtr<Allocation> & bufAlloc,const deUint32 bufBytes)614 void TransformFeedbackTestInstance::verifyTransformFeedbackBuffer (const MovePtr<Allocation>& bufAlloc,
615 const deUint32 bufBytes)
616 {
617 const DeviceInterface& vk = m_context.getDeviceInterface();
618 const VkDevice device = m_context.getDevice();
619 const deUint32 numPoints = static_cast<deUint32>(bufBytes / sizeof(deUint32));
620 const deUint32* tfData = getInvalidatedHostPtr<deUint32>(vk, device, *bufAlloc);
621
622 for (deUint32 i = 0; i < numPoints; ++i)
623 if (tfData[i] != i)
624 TCU_FAIL(std::string("Failed at item ") + de::toString(i) + " received:" + de::toString(tfData[i]) + " expected:" + de::toString(i));
625 }
626
627 class TransformFeedbackBasicTestInstance : public TransformFeedbackTestInstance
628 {
629 public:
630 TransformFeedbackBasicTestInstance (Context& context, const TestParameters& parameters);
631
632 protected:
633 tcu::TestStatus iterate (void);
634 };
635
TransformFeedbackBasicTestInstance(Context & context,const TestParameters & parameters)636 TransformFeedbackBasicTestInstance::TransformFeedbackBasicTestInstance (Context& context, const TestParameters& parameters)
637 : TransformFeedbackTestInstance (context, parameters)
638 {
639 }
640
iterate(void)641 tcu::TestStatus TransformFeedbackBasicTestInstance::iterate (void)
642 {
643 const DeviceInterface& vk = m_context.getDeviceInterface();
644 const VkDevice device = m_context.getDevice();
645 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
646 const VkQueue queue = m_context.getUniversalQueue();
647 Allocator& allocator = m_context.getDefaultAllocator();
648
649 const Unique<VkShaderModule> vertexModule (createShaderModule (vk, device, m_context.getBinaryCollection().get("vert"), 0u));
650 const Unique<VkRenderPass> renderPass (makeRenderPass (vk, device, VK_FORMAT_UNDEFINED));
651 const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, 0u, DE_NULL, m_imageExtent2D.width, m_imageExtent2D.height));
652 const Unique<VkPipelineLayout> pipelineLayout (TransformFeedback::makePipelineLayout (vk, device));
653 const Unique<VkPipeline> pipeline (makeGraphicsPipeline (vk, device, *pipelineLayout, *renderPass, *vertexModule, DE_NULL, DE_NULL, DE_NULL, DE_NULL, m_imageExtent2D, 0u, &m_parameters.streamId));
654 const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
655 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
656
657 const VkBufferCreateInfo tfBufCreateInfo = makeBufferCreateInfo(m_parameters.bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT);
658 const Move<VkBuffer> tfBuf = createBuffer(vk, device, &tfBufCreateInfo);
659 const MovePtr<Allocation> tfBufAllocation = allocator.allocate(getBufferMemoryRequirements(vk, device, *tfBuf), MemoryRequirement::HostVisible);
660 const VkMemoryBarrier tfMemoryBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT, VK_ACCESS_HOST_READ_BIT);
661 const std::vector<VkDeviceSize> tfBufBindingSizes = generateSizesList(m_parameters.bufferSize, m_parameters.partCount);
662 const std::vector<VkDeviceSize> tfBufBindingOffsets = generateOffsetsList(tfBufBindingSizes);
663
664 VK_CHECK(vk.bindBufferMemory(device, *tfBuf, tfBufAllocation->getMemory(), tfBufAllocation->getOffset()));
665
666 beginCommandBuffer(vk, *cmdBuffer);
667 {
668 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
669 {
670 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
671
672 for (deUint32 drawNdx = 0; drawNdx < m_parameters.partCount; ++drawNdx)
673 {
674 const deUint32 startValue = static_cast<deUint32>(tfBufBindingOffsets[drawNdx] / sizeof(deUint32));
675 const deUint32 numPoints = static_cast<deUint32>(tfBufBindingSizes[drawNdx] / sizeof(deUint32));
676
677 vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0, 1, &*tfBuf, &tfBufBindingOffsets[drawNdx], &tfBufBindingSizes[drawNdx]);
678
679 vk.cmdPushConstants(*cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0u, sizeof(startValue), &startValue);
680
681 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
682 {
683 vk.cmdDraw(*cmdBuffer, numPoints, 1u, 0u, 0u);
684 }
685 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
686 }
687 }
688 endRenderPass(vk, *cmdBuffer);
689
690 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &tfMemoryBarrier, 0u, DE_NULL, 0u, DE_NULL);
691 }
692 endCommandBuffer(vk, *cmdBuffer);
693 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
694
695 verifyTransformFeedbackBuffer(tfBufAllocation, m_parameters.bufferSize);
696
697 return tcu::TestStatus::pass("Pass");
698 }
699
700 class TransformFeedbackResumeTestInstance : public TransformFeedbackTestInstance
701 {
702 public:
703 TransformFeedbackResumeTestInstance (Context& context, const TestParameters& parameters);
704
705 protected:
706 tcu::TestStatus iterate (void);
707 };
708
TransformFeedbackResumeTestInstance(Context & context,const TestParameters & parameters)709 TransformFeedbackResumeTestInstance::TransformFeedbackResumeTestInstance (Context& context, const TestParameters& parameters)
710 : TransformFeedbackTestInstance (context, parameters)
711 {
712 }
713
iterate(void)714 tcu::TestStatus TransformFeedbackResumeTestInstance::iterate (void)
715 {
716 const DeviceInterface& vk = m_context.getDeviceInterface();
717 const VkDevice device = m_context.getDevice();
718 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
719 const VkQueue queue = m_context.getUniversalQueue();
720 Allocator& allocator = m_context.getDefaultAllocator();
721
722 const Unique<VkShaderModule> vertexModule (createShaderModule (vk, device, m_context.getBinaryCollection().get("vert"), 0u));
723 const Unique<VkRenderPass> renderPass (makeRenderPass (vk, device, VK_FORMAT_UNDEFINED));
724 const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, 0u, DE_NULL, m_imageExtent2D.width, m_imageExtent2D.height));
725 const Unique<VkPipelineLayout> pipelineLayout (TransformFeedback::makePipelineLayout (vk, device));
726 const Unique<VkPipeline> pipeline (makeGraphicsPipeline (vk, device, *pipelineLayout, *renderPass, *vertexModule, DE_NULL, DE_NULL, DE_NULL, DE_NULL, m_imageExtent2D, 0u, &m_parameters.streamId));
727
728 const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
729 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
730
731 const VkBufferCreateInfo tfBufCreateInfo = makeBufferCreateInfo(m_parameters.bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT);
732 const Move<VkBuffer> tfBuf = createBuffer(vk, device, &tfBufCreateInfo);
733 const MovePtr<Allocation> tfBufAllocation = allocator.allocate(getBufferMemoryRequirements(vk, device, *tfBuf), MemoryRequirement::HostVisible);
734 const VkMemoryBarrier tfMemoryBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT, VK_ACCESS_HOST_READ_BIT);
735 const std::vector<VkDeviceSize> tfBufBindingSizes = std::vector<VkDeviceSize>(1, m_parameters.bufferSize);
736 const std::vector<VkDeviceSize> tfBufBindingOffsets = std::vector<VkDeviceSize>(1, 0ull);
737
738 const size_t tfcBufSize = 16 * sizeof(deUint32) * m_parameters.partCount;
739 const VkBufferCreateInfo tfcBufCreateInfo = makeBufferCreateInfo(tfcBufSize, VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT);
740 const Move<VkBuffer> tfcBuf = createBuffer(vk, device, &tfcBufCreateInfo);
741 const MovePtr<Allocation> tfcBufAllocation = allocator.allocate(getBufferMemoryRequirements(vk, device, *tfcBuf), MemoryRequirement::Any);
742 const std::vector<VkDeviceSize> tfcBufBindingOffsets = generateOffsetsList(generateSizesList(tfcBufSize, m_parameters.partCount));
743 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);
744
745 const std::vector<VkDeviceSize> chunkSizesList = generateSizesList(m_parameters.bufferSize, m_parameters.partCount);
746 const std::vector<VkDeviceSize> chunkOffsetsList = generateOffsetsList(chunkSizesList);
747
748 DE_ASSERT(tfBufBindingSizes.size() == 1);
749 DE_ASSERT(tfBufBindingOffsets.size() == 1);
750
751 VK_CHECK(vk.bindBufferMemory(device, *tfBuf, tfBufAllocation->getMemory(), tfBufAllocation->getOffset()));
752 VK_CHECK(vk.bindBufferMemory(device, *tfcBuf, tfcBufAllocation->getMemory(), tfcBufAllocation->getOffset()));
753
754 beginCommandBuffer(vk, *cmdBuffer);
755 {
756 for (size_t drawNdx = 0; drawNdx < m_parameters.partCount; ++drawNdx)
757 {
758 const deUint32 startValue = static_cast<deUint32>(chunkOffsetsList[drawNdx] / sizeof(deUint32));
759 const deUint32 numPoints = static_cast<deUint32>(chunkSizesList[drawNdx] / sizeof(deUint32));
760 const deUint32 countBuffersCount = (drawNdx == 0) ? 0 : 1;
761
762 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
763 {
764
765 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
766
767 vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0, 1, &*tfBuf, &tfBufBindingOffsets[0], &tfBufBindingSizes[0]);
768
769 vk.cmdPushConstants(*cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0u, sizeof(startValue), &startValue);
770
771 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, countBuffersCount, (drawNdx == 0) ? DE_NULL : &*tfcBuf, (drawNdx == 0) ? DE_NULL : &tfcBufBindingOffsets[drawNdx - 1]);
772 {
773 vk.cmdDraw(*cmdBuffer, numPoints, 1u, 0u, 0u);
774 }
775 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 1, &*tfcBuf, &tfcBufBindingOffsets[drawNdx]);
776 }
777 endRenderPass(vk, *cmdBuffer);
778
779 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);
780 }
781
782 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &tfMemoryBarrier, 0u, DE_NULL, 0u, DE_NULL);
783 }
784 endCommandBuffer(vk, *cmdBuffer);
785 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
786
787 verifyTransformFeedbackBuffer(tfBufAllocation, m_parameters.bufferSize);
788
789 return tcu::TestStatus::pass("Pass");
790 }
791
792 class TransformFeedbackWindingOrderTestInstance : public TransformFeedbackTestInstance
793 {
794 public:
795 TransformFeedbackWindingOrderTestInstance(Context& context, const TestParameters& parameters);
796
797 protected:
798 struct TopologyParameters
799 {
800 // number of vertex in primitive; 2 for line, 3 for triangle
801 deUint32 vertexPerPrimitive;
802
803 // pointer to function calculating number of points that
804 // will be generated for given part count
805 std::function<deUint32(deUint32)> getNumGeneratedPoints;
806
807 // pointer to function generating expected values; parameter is
808 // primitive index, result array with expected data for primitive vertex
809 std::function<std::vector<deUint32>(deUint32)> getExpectedValuesForPrimitive;
810 };
811 typedef const std::map<VkPrimitiveTopology, TopologyParameters> TopologyParametersMap;
812
813 protected:
814 const TopologyParametersMap& getTopologyParametersMap (void);
815 tcu::TestStatus iterate (void);
816 void verifyTransformFeedbackBuffer (const MovePtr<Allocation>& bufAlloc,
817 const deUint32 bufBytes);
818
819 private:
820 TopologyParameters m_tParameters;
821 const bool m_requiresTesselationStage;
822 };
823
TransformFeedbackWindingOrderTestInstance(Context & context,const TestParameters & parameters)824 TransformFeedbackWindingOrderTestInstance::TransformFeedbackWindingOrderTestInstance(Context& context, const TestParameters& parameters)
825 : TransformFeedbackTestInstance (context, parameters)
826 , m_requiresTesselationStage(parameters.primTopology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST)
827 {
828 if (m_requiresTesselationStage && !context.getDeviceFeatures().tessellationShader)
829 throw tcu::NotSupportedError("Tessellation shader not supported");
830
831 TopologyParametersMap topologyParametersMap = getTopologyParametersMap();
832 DE_ASSERT(topologyParametersMap.find(parameters.primTopology) != topologyParametersMap.end());
833 m_tParameters = topologyParametersMap.at(parameters.primTopology);
834 }
835
getTopologyParametersMap(void)836 const TransformFeedbackWindingOrderTestInstance::TopologyParametersMap& TransformFeedbackWindingOrderTestInstance::getTopologyParametersMap(void)
837 {
838 static const TopologyParametersMap topologyParametersMap =
839 {
840 {
841 VK_PRIMITIVE_TOPOLOGY_POINT_LIST,
842 {
843 1u,
844 [](deUint32 partCount) { return partCount; },
845 [](deUint32 i) { return std::vector<deUint32>{ i, i + 1u }; }
846 }
847 },
848 {
849 VK_PRIMITIVE_TOPOLOGY_LINE_LIST,
850 {
851 2u,
852 [](deUint32 partCount) { return partCount; },
853 [](deUint32 i) { return std::vector<deUint32>{ 2 * i, 2 * i + 1u }; }
854 }
855 },
856 {
857 VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,
858 {
859 2u,
860 [](deUint32 partCount) { return 2u * (partCount - 1); },
861 [](deUint32 i) { return std::vector<deUint32>{ i, i + 1u }; }
862 }
863 },
864 {
865 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
866 {
867 3u,
868 [](deUint32 partCount) { return partCount; },
869 [](deUint32 i) { return std::vector<deUint32>{ 3 * i, 3 * i + 1u, 3 * i + 2u }; }
870 }
871 },
872 {
873 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
874 {
875 3u,
876 [](deUint32 partCount) { return 3u * (partCount - 2); },
877 [](deUint32 i)
878 {
879 const deUint32 iMod2 = i % 2;
880 return std::vector<deUint32>{ i, i + 1 + iMod2, i + 2 - iMod2 };
881 }
882 }
883 },
884 {
885 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,
886 {
887 3u,
888 [](deUint32 partCount) { return partCount; },
889 [](deUint32 i) { return std::vector<deUint32>{ i + 1, i + 2, 0 }; }
890 }
891 },
892 {
893 VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY,
894 {
895 2u,
896 [](deUint32 partCount) { return partCount / 4u; }, // note: this cant be replaced with partCount / 2 as for partCount=6 we will get 3 instead of 2
897 [](deUint32 i) { return std::vector<deUint32>{ i + 1u, i + 2u }; }
898 }
899 },
900 {
901 VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY,
902 {
903 2u,
904 [](deUint32 partCount) { return 2u * (partCount - 3u); },
905 [](deUint32 i) { return std::vector<deUint32>{ i + 1u, i + 2u }; }
906 }
907 },
908 {
909 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY,
910 {
911 3u,
912 [](deUint32 partCount) { return partCount / 2u; },
913 [](deUint32 i) { return std::vector<deUint32>{ 6 * i, 6 * i + 2u, 6 * i + 4u }; }
914 }
915 },
916 {
917 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY,
918 {
919 3u,
920 [](deUint32 partCount) { return 3u * (partCount / 2u - 2u); },
921 [](deUint32 i)
922 {
923 const bool even = (0 == i % 2);
924 if (even)
925 return std::vector<deUint32>{ 2 * i + 0, 2 * i + 2, 2 * i + 4 };
926 return std::vector<deUint32>{ 2 * i + 0, 2 * i + 4, 2 * i + 2 };
927 }
928 }
929 },
930 {
931 VK_PRIMITIVE_TOPOLOGY_PATCH_LIST,
932 {
933 9u,
934 [](deUint32 partCount) { return partCount * 3u; },
935 [](deUint32 i)
936 {
937 // we cant generate vertex numbers in tesselation evaluation shader;
938 // check if patch index is correct for every 9 generated vertex
939 return std::vector<deUint32>(9, i);
940 }
941 }
942 }
943 };
944
945 return topologyParametersMap;
946 }
947
iterate(void)948 tcu::TestStatus TransformFeedbackWindingOrderTestInstance::iterate (void)
949 {
950 DE_ASSERT(m_parameters.partCount >= 6);
951
952 const DeviceInterface& vk = m_context.getDeviceInterface();
953 const VkDevice device = m_context.getDevice();
954 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
955 const VkQueue queue = m_context.getUniversalQueue();
956 Allocator& allocator = m_context.getDefaultAllocator();
957
958 const Move<VkShaderModule> vertexModule(createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
959 Move<VkShaderModule> tescModule;
960 Move<VkShaderModule> teseModule;
961 if (m_requiresTesselationStage)
962 {
963 tescModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("tesc"), 0u);
964 teseModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("tese"), 0u);
965 }
966
967 const Unique<VkRenderPass> renderPass (makeRenderPass (vk, device, VK_FORMAT_UNDEFINED));
968 const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, 0u, DE_NULL, m_imageExtent2D.width, m_imageExtent2D.height));
969 const Unique<VkPipelineLayout> pipelineLayout (TransformFeedback::makePipelineLayout (vk, device));
970 const Unique<VkPipeline> pipeline (makeGraphicsPipeline (vk, device, *pipelineLayout, *renderPass,
971 *vertexModule,
972 m_requiresTesselationStage ? *tescModule : DE_NULL,
973 m_requiresTesselationStage ? *teseModule : DE_NULL,
974 DE_NULL,
975 DE_NULL,
976 m_imageExtent2D, 0u, DE_NULL, m_parameters.primTopology));
977 const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
978 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
979 const VkDeviceSize bufferSize = m_tParameters.getNumGeneratedPoints (m_parameters.partCount) * sizeof(deUint32);
980 const VkBufferCreateInfo tfBufCreateInfo = makeBufferCreateInfo (bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT);
981 const Move<VkBuffer> tfBuf = createBuffer (vk, device, &tfBufCreateInfo);
982 const MovePtr<Allocation> tfBufAllocation = allocator.allocate (getBufferMemoryRequirements(vk, device, *tfBuf), MemoryRequirement::HostVisible);
983 const VkMemoryBarrier tfMemoryBarrier = makeMemoryBarrier (VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT, VK_ACCESS_HOST_READ_BIT);
984 const VkDeviceSize tfBufBindingSize = bufferSize;
985 const VkDeviceSize tfBufBindingOffset = 0u;
986 const deUint32 startValue = 0u;
987
988 VK_CHECK(vk.bindBufferMemory(device, *tfBuf, tfBufAllocation->getMemory(), tfBufAllocation->getOffset()));
989
990 beginCommandBuffer(vk, *cmdBuffer);
991 {
992 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
993 {
994 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
995
996 vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0, 1, &*tfBuf, &tfBufBindingOffset, &tfBufBindingSize);
997
998 vk.cmdPushConstants(*cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0u, sizeof(startValue), &startValue);
999
1000 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1001 {
1002 vk.cmdDraw(*cmdBuffer, m_parameters.partCount, 1u, 0u, 0u);
1003 }
1004 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1005 }
1006 endRenderPass(vk, *cmdBuffer);
1007
1008 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &tfMemoryBarrier, 0u, DE_NULL, 0u, DE_NULL);
1009 }
1010 endCommandBuffer(vk, *cmdBuffer);
1011 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1012
1013 verifyTransformFeedbackBuffer(tfBufAllocation, static_cast<deUint32>(bufferSize));
1014
1015 return tcu::TestStatus::pass("Pass");
1016 }
1017
verifyTransformFeedbackBuffer(const MovePtr<Allocation> & bufAlloc,const deUint32 bufBytes)1018 void TransformFeedbackWindingOrderTestInstance::verifyTransformFeedbackBuffer (const MovePtr<Allocation>& bufAlloc,
1019 const deUint32 bufBytes)
1020 {
1021 const DeviceInterface& vk = m_context.getDeviceInterface();
1022 const VkDevice device = m_context.getDevice();
1023 const deUint32 numPoints = static_cast<deUint32>(bufBytes / sizeof(deUint32));
1024 const deUint32 vertexPerPrimitive = m_tParameters.vertexPerPrimitive;
1025 const deUint32 numPrimitives = numPoints / vertexPerPrimitive;
1026 const deUint32* tfData = getInvalidatedHostPtr<deUint32>(vk, device, *bufAlloc);
1027
1028 for (deUint32 primitiveIndex = 0; primitiveIndex < numPrimitives; ++primitiveIndex)
1029 {
1030 const deUint32* tfDataForPrimitive = &tfData[primitiveIndex * vertexPerPrimitive];
1031 std::vector<deUint32> expectedDataForPrimitive = m_tParameters.getExpectedValuesForPrimitive(primitiveIndex);
1032
1033 // For multi - vertex primitives, all values for a given vertex are written before writing values for any other vertex.
1034 // Implementations may write out any vertex within the primitive first, but all subsequent vertices for that primitive
1035 // must be written out in a consistent winding order
1036 bool correctWinding = true;
1037 for (deUint32 combinationIndex = 0; combinationIndex < vertexPerPrimitive; combinationIndex++)
1038 {
1039 correctWinding = true;
1040 for (deUint32 vertexIndex = 0; vertexIndex < vertexPerPrimitive; vertexIndex++)
1041 {
1042 correctWinding &= (tfDataForPrimitive[vertexIndex] == expectedDataForPrimitive[(combinationIndex + vertexIndex) % vertexPerPrimitive]);
1043
1044 // if data for this vertex is not correct then there
1045 // is no need to check other, go to next combination
1046 if (!correctWinding)
1047 break;
1048 }
1049
1050 // no need to check other combinations, we found correct one
1051 if (correctWinding)
1052 break;
1053 }
1054
1055 if (!correctWinding)
1056 {
1057 std::stringstream message;
1058 message << "Failed at primitive " << primitiveIndex << " received: [";
1059 for (deUint32 vertexIndex = 0; vertexIndex < vertexPerPrimitive; vertexIndex++)
1060 message << de::toString(tfDataForPrimitive[vertexIndex]) << " ";
1061 message << "] expected: [";
1062 for (deUint32 vertexIndex = 0; vertexIndex < vertexPerPrimitive; vertexIndex++)
1063 message << de::toString(expectedDataForPrimitive[vertexIndex]) << " ";
1064 message << "]";
1065 TCU_FAIL(message.str());
1066 }
1067 }
1068 }
1069
1070 class TransformFeedbackBuiltinTestInstance : public TransformFeedbackTestInstance
1071 {
1072 public:
1073 TransformFeedbackBuiltinTestInstance (Context& context, const TestParameters& parameters);
1074
1075 protected:
1076 tcu::TestStatus iterate (void);
1077 void verifyTransformFeedbackBuffer (const MovePtr<Allocation>& bufAlloc, const VkDeviceSize offset, const deUint32 bufBytes);
1078 };
1079
TransformFeedbackBuiltinTestInstance(Context & context,const TestParameters & parameters)1080 TransformFeedbackBuiltinTestInstance::TransformFeedbackBuiltinTestInstance (Context& context, const TestParameters& parameters)
1081 : TransformFeedbackTestInstance (context, parameters)
1082 {
1083 const InstanceInterface& vki = m_context.getInstanceInterface();
1084 const VkPhysicalDevice physDevice = m_context.getPhysicalDevice();
1085 const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(vki, physDevice);
1086
1087 const deUint32 tfBuffersSupported = m_transformFeedbackProperties.maxTransformFeedbackBuffers;
1088 const deUint32 tfBuffersRequired = m_parameters.partCount;
1089
1090 if ((m_parameters.testType == TEST_TYPE_XFB_CLIPDISTANCE || m_parameters.testType == TEST_TYPE_XFB_CLIP_AND_CULL) && !features.shaderClipDistance)
1091 TCU_THROW(NotSupportedError, std::string("shaderClipDistance feature is not supported"));
1092 if ((m_parameters.testType == TEST_TYPE_XFB_CULLDISTANCE || m_parameters.testType == TEST_TYPE_XFB_CLIP_AND_CULL) && !features.shaderCullDistance)
1093 TCU_THROW(NotSupportedError, std::string("shaderCullDistance feature is not supported"));
1094 if (tfBuffersSupported < tfBuffersRequired)
1095 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBuffers=" + de::toString(tfBuffersSupported) + ", while test requires " + de::toString(tfBuffersRequired)).c_str());
1096 }
1097
verifyTransformFeedbackBuffer(const MovePtr<Allocation> & bufAlloc,const VkDeviceSize offset,const deUint32 bufBytes)1098 void TransformFeedbackBuiltinTestInstance::verifyTransformFeedbackBuffer (const MovePtr<Allocation>& bufAlloc, const VkDeviceSize offset, const deUint32 bufBytes)
1099 {
1100 const DeviceInterface& vk = m_context.getDeviceInterface();
1101 const VkDevice device = m_context.getDevice();
1102 const deUint32 numPoints = bufBytes / static_cast<deUint32>(sizeof(float));
1103 const deUint8* tfDataBytes = getInvalidatedHostPtr<deUint8>(vk, device, *bufAlloc);
1104 const float* tfData = (float*)&tfDataBytes[offset];
1105
1106 for (deUint32 i = 0; i < numPoints; ++i)
1107 {
1108 const deUint32 divisor = 32768u;
1109 const float epsilon = 1.0f / float(divisor);
1110 const float expected = float(i) / float(divisor);
1111
1112 if (deAbs(tfData[i] - expected) > epsilon)
1113 TCU_FAIL(std::string("Failed at item ") + de::toString(i) + " received:" + de::toString(tfData[i]) + " expected:" + de::toString(expected));
1114 }
1115 }
1116
iterate(void)1117 tcu::TestStatus TransformFeedbackBuiltinTestInstance::iterate (void)
1118 {
1119 const DeviceInterface& vk = m_context.getDeviceInterface();
1120 const VkDevice device = m_context.getDevice();
1121 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1122 const VkQueue queue = m_context.getUniversalQueue();
1123 Allocator& allocator = m_context.getDefaultAllocator();
1124
1125 const Unique<VkShaderModule> vertexModule (createShaderModule (vk, device, m_context.getBinaryCollection().get("vert"), 0u));
1126 const Unique<VkRenderPass> renderPass (makeRenderPass (vk, device, VK_FORMAT_UNDEFINED));
1127 const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, 0u, DE_NULL, m_imageExtent2D.width, m_imageExtent2D.height));
1128 const Unique<VkPipelineLayout> pipelineLayout (TransformFeedback::makePipelineLayout (vk, device));
1129 const Unique<VkPipeline> pipeline (makeGraphicsPipeline (vk, device, *pipelineLayout, *renderPass, *vertexModule, DE_NULL, DE_NULL, DE_NULL, DE_NULL, m_imageExtent2D, 0u, &m_parameters.streamId));
1130 const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1131 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1132
1133 const VkDeviceSize tfBufSize = m_parameters.bufferSize * m_parameters.partCount;
1134 const VkBufferCreateInfo tfBufCreateInfo = makeBufferCreateInfo(tfBufSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT);
1135 const Move<VkBuffer> tfBuf = createBuffer(vk, device, &tfBufCreateInfo);
1136 const std::vector<VkBuffer> tfBufArray = std::vector<VkBuffer>(m_parameters.partCount, *tfBuf);
1137 const MovePtr<Allocation> tfBufAllocation = allocator.allocate(getBufferMemoryRequirements(vk, device, *tfBuf), MemoryRequirement::HostVisible);
1138 const VkMemoryBarrier tfMemoryBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT, VK_ACCESS_HOST_READ_BIT);
1139 const std::vector<VkDeviceSize> tfBufBindingSizes = std::vector<VkDeviceSize>(m_parameters.partCount, m_parameters.bufferSize);
1140 const std::vector<VkDeviceSize> tfBufBindingOffsets = generateOffsetsList(tfBufBindingSizes);
1141 const deUint32 perVertexDataSize = (m_parameters.testType == TEST_TYPE_XFB_POINTSIZE) ? static_cast<deUint32>(sizeof(float))
1142 : (m_parameters.testType == TEST_TYPE_XFB_CLIPDISTANCE) ? static_cast<deUint32>(8u * sizeof(float))
1143 : (m_parameters.testType == TEST_TYPE_XFB_CULLDISTANCE) ? static_cast<deUint32>(8u * sizeof(float))
1144 : (m_parameters.testType == TEST_TYPE_XFB_CLIP_AND_CULL) ? static_cast<deUint32>(6u * sizeof(float))
1145 : 0u;
1146 const deUint32 numPoints = m_parameters.bufferSize / perVertexDataSize;
1147
1148 VK_CHECK(vk.bindBufferMemory(device, *tfBuf, tfBufAllocation->getMemory(), tfBufAllocation->getOffset()));
1149
1150 beginCommandBuffer(vk, *cmdBuffer);
1151 {
1152 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
1153 {
1154 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1155
1156 vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0, m_parameters.partCount, &tfBufArray[0], &tfBufBindingOffsets[0], &tfBufBindingSizes[0]);
1157
1158 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1159 {
1160 vk.cmdDraw(*cmdBuffer, numPoints, 1u, 0u, 0u);
1161 }
1162 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1163 }
1164 endRenderPass(vk, *cmdBuffer);
1165
1166 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &tfMemoryBarrier, 0u, DE_NULL, 0u, DE_NULL);
1167 }
1168 endCommandBuffer(vk, *cmdBuffer);
1169 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1170
1171 verifyTransformFeedbackBuffer(tfBufAllocation, tfBufBindingOffsets[m_parameters.partCount - 1], numPoints * perVertexDataSize);
1172
1173 return tcu::TestStatus::pass("Pass");
1174 }
1175
1176 class TransformFeedbackDepthClipControlTestInstance : public TransformFeedbackTestInstance
1177 {
1178 public:
1179 TransformFeedbackDepthClipControlTestInstance (Context& context, const TestParameters& parameters);
1180
1181 protected:
1182 tcu::TestStatus iterate (void);
1183 void verifyTransformFeedbackBuffer (const MovePtr<Allocation>& bufAlloc, const VkDeviceSize offset, const deUint32 bufBytes);
1184 };
1185
TransformFeedbackDepthClipControlTestInstance(Context & context,const TestParameters & parameters)1186 TransformFeedbackDepthClipControlTestInstance::TransformFeedbackDepthClipControlTestInstance (Context& context, const TestParameters& parameters)
1187 : TransformFeedbackTestInstance (context, parameters)
1188 {
1189 const InstanceInterface& vki = m_context.getInstanceInterface();
1190 const VkPhysicalDevice physDevice = m_context.getPhysicalDevice();
1191 const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(vki, physDevice);
1192
1193 const deUint32 tfBuffersSupported = m_transformFeedbackProperties.maxTransformFeedbackBuffers;
1194 const deUint32 tfBuffersRequired = m_parameters.partCount;
1195
1196 if (!context.isDeviceFunctionalitySupported("VK_EXT_depth_clip_control"))
1197 TCU_THROW(NotSupportedError, "VK_EXT_depth_clip_control is not supported");
1198
1199 if (parameters.testType == TEST_TYPE_DEPTH_CLIP_CONTROL_GEOMETRY && !features.geometryShader)
1200 TCU_THROW(NotSupportedError, "Geometry shader not supported");
1201
1202 if (parameters.testType == TEST_TYPE_DEPTH_CLIP_CONTROL_TESE && !features.tessellationShader)
1203 TCU_THROW(NotSupportedError, "Tessellation shader not supported");
1204
1205 if (tfBuffersSupported < tfBuffersRequired)
1206 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBuffers=" + de::toString(tfBuffersSupported) + ", while test requires " + de::toString(tfBuffersRequired)).c_str());
1207 }
1208
verifyTransformFeedbackBuffer(const MovePtr<Allocation> & bufAlloc,const VkDeviceSize offset,const deUint32 bufBytes)1209 void TransformFeedbackDepthClipControlTestInstance::verifyTransformFeedbackBuffer (const MovePtr<Allocation>& bufAlloc, const VkDeviceSize offset, const deUint32 bufBytes)
1210 {
1211 const DeviceInterface& vk = m_context.getDeviceInterface();
1212 const VkDevice device = m_context.getDevice();
1213 const deUint32 numVertices = bufBytes / static_cast<deUint32>(sizeof(float) * 4);
1214 const deUint8* tfDataBytes = getInvalidatedHostPtr<deUint8>(vk, device, *bufAlloc);
1215 const float* tfData = (float*)&tfDataBytes[offset];
1216 std::vector<float> result;
1217
1218 // We only care about the depth (z) value.
1219 for (deUint32 i = 0; i < numVertices; i++)
1220 result.push_back(tfData[i * 4 + 2]);
1221
1222 // Tessellation generates triangles whose vertex data might be written into
1223 // transform feedback buffer in a different order than generated by the vertex
1224 // shader. Sort the values here to allow comparison.
1225 if (m_parameters.testType == TEST_TYPE_DEPTH_CLIP_CONTROL_TESE)
1226 {
1227 std::sort(result.begin(), result.end());
1228 }
1229
1230 // Verify the vertex depth values match with the ones written by the shader.
1231 for (deUint32 i = 0; i < numVertices; i++)
1232 {
1233 const float expected = (float)i / 3.0f - 1.0f;
1234 const float epsilon = 0.0001f;
1235
1236 if (deAbs(result[i] - expected) > epsilon)
1237 TCU_FAIL(std::string("Failed at vertex ") + de::toString(i) + " depth. Received:" + de::toString(result[i]) + " expected:" + de::toString(expected));
1238 }
1239 }
1240
iterate(void)1241 tcu::TestStatus TransformFeedbackDepthClipControlTestInstance::iterate (void)
1242 {
1243 const DeviceInterface& vk = m_context.getDeviceInterface();
1244 const VkDevice device = m_context.getDevice();
1245 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1246 const VkQueue queue = m_context.getUniversalQueue();
1247 Allocator& allocator = m_context.getDefaultAllocator();
1248
1249 const Unique<VkShaderModule> vertexModule (createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
1250 Move<VkShaderModule> geomModule;
1251 Move<VkShaderModule> tescModule;
1252 Move<VkShaderModule> teseModule;
1253 const bool hasGeomShader = m_parameters.testType == TEST_TYPE_DEPTH_CLIP_CONTROL_GEOMETRY;
1254 const bool hasTessellation = m_parameters.testType == TEST_TYPE_DEPTH_CLIP_CONTROL_TESE;
1255
1256 if (hasGeomShader)
1257 geomModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("geom"), 0u);
1258
1259 if (hasTessellation)
1260 {
1261 tescModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("tesc"), 0u);
1262 teseModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("tese"), 0u);
1263 }
1264
1265 const Unique<VkRenderPass> renderPass (makeRenderPass(vk, device, VK_FORMAT_UNDEFINED));
1266 const Unique<VkFramebuffer> framebuffer (makeFramebuffer(vk, device, *renderPass, 0u, DE_NULL, m_imageExtent2D.width, m_imageExtent2D.height));
1267 const Unique<VkPipelineLayout> pipelineLayout (TransformFeedback::makePipelineLayout (vk, device));
1268 const Unique<VkPipeline> pipeline (makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, hasTessellation ? *tescModule : DE_NULL, hasTessellation ? *teseModule : DE_NULL, hasGeomShader ? *geomModule : DE_NULL, DE_NULL, m_imageExtent2D, 0u, &m_parameters.streamId, m_parameters.primTopology, false, true));
1269 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1270 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1271 const VkDeviceSize tfBufSize = m_parameters.bufferSize * m_parameters.partCount;
1272 const VkBufferCreateInfo tfBufCreateInfo = makeBufferCreateInfo(tfBufSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT);
1273 const Move<VkBuffer> tfBuf = createBuffer(vk, device, &tfBufCreateInfo);
1274 const std::vector<VkBuffer> tfBufArray = std::vector<VkBuffer>(m_parameters.partCount, *tfBuf);
1275 const MovePtr<Allocation> tfBufAllocation = allocator.allocate(getBufferMemoryRequirements(vk, device, *tfBuf), MemoryRequirement::HostVisible);
1276 const VkMemoryBarrier tfMemoryBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT, VK_ACCESS_HOST_READ_BIT);
1277 const std::vector<VkDeviceSize> tfBufBindingSizes = std::vector<VkDeviceSize>(m_parameters.partCount, m_parameters.bufferSize);
1278 const std::vector<VkDeviceSize> tfBufBindingOffsets = generateOffsetsList(tfBufBindingSizes);
1279 const deUint32 perVertexDataSize = static_cast<deUint32>(4u * sizeof(float));
1280 const deUint32 numVertices = m_parameters.bufferSize / perVertexDataSize;
1281
1282 VK_CHECK(vk.bindBufferMemory(device, *tfBuf, tfBufAllocation->getMemory(), tfBufAllocation->getOffset()));
1283
1284 beginCommandBuffer(vk, *cmdBuffer);
1285 {
1286 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
1287 {
1288 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1289
1290 vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0, m_parameters.partCount, &tfBufArray[0], &tfBufBindingOffsets[0], &tfBufBindingSizes[0]);
1291
1292 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1293 {
1294 vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
1295 }
1296 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1297 }
1298 endRenderPass(vk, *cmdBuffer);
1299
1300 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &tfMemoryBarrier, 0u, DE_NULL, 0u, DE_NULL);
1301 }
1302 endCommandBuffer(vk, *cmdBuffer);
1303 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1304
1305 verifyTransformFeedbackBuffer(tfBufAllocation, tfBufBindingOffsets[m_parameters.partCount - 1], m_parameters.bufferSize);
1306
1307 return tcu::TestStatus::pass("Pass");
1308 }
1309
1310 class TransformFeedbackMultistreamTestInstance : public TransformFeedbackTestInstance
1311 {
1312 public:
1313 TransformFeedbackMultistreamTestInstance (Context& context, const TestParameters& parameters);
1314
1315 protected:
1316 std::vector<VkDeviceSize> generateSizesList (const size_t bufBytes, const size_t chunkCount);
1317 void verifyTransformFeedbackBuffer (const MovePtr<Allocation>& bufAlloc, const deUint32 bufBytes);
1318 tcu::TestStatus iterate (void);
1319 };
1320
TransformFeedbackMultistreamTestInstance(Context & context,const TestParameters & parameters)1321 TransformFeedbackMultistreamTestInstance::TransformFeedbackMultistreamTestInstance (Context& context, const TestParameters& parameters)
1322 : TransformFeedbackTestInstance (context, parameters)
1323 {
1324 const InstanceInterface& vki = m_context.getInstanceInterface();
1325 const VkPhysicalDevice physDevice = m_context.getPhysicalDevice();
1326 const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(vki, physDevice);
1327 const VkPhysicalDeviceTransformFeedbackFeaturesEXT& transformFeedbackFeatures = m_context.getTransformFeedbackFeaturesEXT();
1328 const deUint32 streamsSupported = m_transformFeedbackProperties.maxTransformFeedbackStreams;
1329 const deUint32 streamsRequired = m_parameters.streamId + 1;
1330 const deUint32 tfBuffersSupported = m_transformFeedbackProperties.maxTransformFeedbackBuffers;
1331 const deUint32 tfBuffersRequired = m_parameters.partCount;
1332 const deUint32 bytesPerVertex = m_parameters.bufferSize / m_parameters.partCount;
1333 const deUint32 tfStreamDataSizeSupported = m_transformFeedbackProperties.maxTransformFeedbackStreamDataSize;
1334 const deUint32 tfBufferDataSizeSupported = m_transformFeedbackProperties.maxTransformFeedbackBufferDataSize;
1335 const deUint32 tfBufferDataStrideSupported = m_transformFeedbackProperties.maxTransformFeedbackBufferDataStride;
1336
1337 DE_ASSERT(m_parameters.partCount == 2u);
1338
1339 if (!features.geometryShader)
1340 TCU_THROW(NotSupportedError, "Missing feature: geometryShader");
1341
1342 if (transformFeedbackFeatures.geometryStreams == DE_FALSE)
1343 TCU_THROW(NotSupportedError, "geometryStreams feature is not supported");
1344
1345 if (streamsSupported < streamsRequired)
1346 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackStreams=" + de::toString(streamsSupported) + ", while test requires " + de::toString(streamsRequired)).c_str());
1347
1348 if (tfBuffersSupported < tfBuffersRequired)
1349 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBuffers=" + de::toString(tfBuffersSupported) + ", while test requires " + de::toString(tfBuffersRequired)).c_str());
1350
1351 if (tfStreamDataSizeSupported < bytesPerVertex)
1352 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackStreamDataSize=" + de::toString(tfStreamDataSizeSupported) + ", while test requires " + de::toString(bytesPerVertex)).c_str());
1353
1354 if (tfBufferDataSizeSupported < bytesPerVertex)
1355 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBufferDataSize=" + de::toString(tfBufferDataSizeSupported) + ", while test requires " + de::toString(bytesPerVertex)).c_str());
1356
1357 if (tfBufferDataStrideSupported < bytesPerVertex)
1358 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBufferDataStride=" + de::toString(tfBufferDataStrideSupported) + ", while test requires " + de::toString(bytesPerVertex)).c_str());
1359 }
1360
generateSizesList(const size_t bufBytes,const size_t chunkCount)1361 std::vector<VkDeviceSize> TransformFeedbackMultistreamTestInstance::generateSizesList (const size_t bufBytes, const size_t chunkCount)
1362 {
1363 const VkDeviceSize chunkSize = bufBytes / chunkCount;
1364 std::vector<VkDeviceSize> result (chunkCount, chunkSize);
1365
1366 DE_ASSERT(chunkSize * chunkCount == bufBytes);
1367 DE_ASSERT(bufBytes <= MINIMUM_TF_BUFFER_SIZE);
1368 DE_ASSERT(bufBytes % sizeof(deUint32) == 0);
1369 DE_ASSERT(chunkCount > 0);
1370 DE_ASSERT(result.size() == chunkCount);
1371
1372 return result;
1373 }
1374
verifyTransformFeedbackBuffer(const MovePtr<Allocation> & bufAlloc,const deUint32 bufBytes)1375 void TransformFeedbackMultistreamTestInstance::verifyTransformFeedbackBuffer (const MovePtr<Allocation>& bufAlloc, const deUint32 bufBytes)
1376 {
1377 const DeviceInterface& vk = m_context.getDeviceInterface();
1378 const VkDevice device = m_context.getDevice();
1379 const deUint32 numPoints = static_cast<deUint32>(bufBytes / sizeof(deUint32));
1380 const float* tfData = getInvalidatedHostPtr<float>(vk, device, *bufAlloc);
1381
1382 for (deUint32 i = 0; i < numPoints; ++i)
1383 if (tfData[i] != float(i))
1384 TCU_FAIL(std::string("Failed at item ") + de::toString(float(i)) + " received:" + de::toString(tfData[i]) + " expected:" + de::toString(i));
1385 }
1386
iterate(void)1387 tcu::TestStatus TransformFeedbackMultistreamTestInstance::iterate (void)
1388 {
1389 const DeviceInterface& vk = m_context.getDeviceInterface();
1390 const VkDevice device = m_context.getDevice();
1391 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1392 const VkQueue queue = m_context.getUniversalQueue();
1393 Allocator& allocator = m_context.getDefaultAllocator();
1394
1395 const Unique<VkRenderPass> renderPass (makeRenderPass (vk, device, VK_FORMAT_UNDEFINED));
1396
1397 const Unique<VkShaderModule> vertexModule (createShaderModule (vk, device, m_context.getBinaryCollection().get("vert"), 0u));
1398 const Unique<VkShaderModule> geomModule (createShaderModule (vk, device, m_context.getBinaryCollection().get("geom"), 0u));
1399
1400 const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, 0u, DE_NULL, m_imageExtent2D.width, m_imageExtent2D.height));
1401 const Unique<VkPipelineLayout> pipelineLayout (TransformFeedback::makePipelineLayout (vk, device));
1402 const Unique<VkPipeline> pipeline (makeGraphicsPipeline (vk, device, *pipelineLayout, *renderPass, *vertexModule, DE_NULL, DE_NULL, *geomModule, DE_NULL, m_imageExtent2D, 0u, &m_parameters.streamId));
1403 const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1404 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1405
1406 const VkBufferCreateInfo tfBufCreateInfo = makeBufferCreateInfo(m_parameters.bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT);
1407 const Move<VkBuffer> tfBuf = createBuffer(vk, device, &tfBufCreateInfo);
1408 const std::vector<VkBuffer> tfBufArray = std::vector<VkBuffer>(m_parameters.partCount, *tfBuf);
1409 const MovePtr<Allocation> tfBufAllocation = allocator.allocate(getBufferMemoryRequirements(vk, device, *tfBuf), MemoryRequirement::HostVisible);
1410 const VkMemoryBarrier tfMemoryBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT, VK_ACCESS_HOST_READ_BIT);
1411 const std::vector<VkDeviceSize> tfBufBindingSizes = generateSizesList(m_parameters.bufferSize, m_parameters.partCount);
1412 const std::vector<VkDeviceSize> tfBufBindingOffsets = generateOffsetsList(tfBufBindingSizes);
1413
1414 VK_CHECK(vk.bindBufferMemory(device, *tfBuf, tfBufAllocation->getMemory(), tfBufAllocation->getOffset()));
1415
1416 beginCommandBuffer(vk, *cmdBuffer);
1417 {
1418 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
1419 {
1420 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1421
1422 vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0u, m_parameters.partCount, &tfBufArray[0], &tfBufBindingOffsets[0], &tfBufBindingSizes[0]);
1423
1424 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1425 {
1426 vk.cmdDraw(*cmdBuffer, 1u, 1u, 0u, 0u);
1427 }
1428 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1429 }
1430 endRenderPass(vk, *cmdBuffer);
1431
1432 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &tfMemoryBarrier, 0u, DE_NULL, 0u, DE_NULL);
1433 }
1434 endCommandBuffer(vk, *cmdBuffer);
1435 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1436
1437 verifyTransformFeedbackBuffer(tfBufAllocation, m_parameters.bufferSize);
1438
1439 return tcu::TestStatus::pass("Pass");
1440 }
1441
1442 class TransformFeedbackStreamsTestInstance : public TransformFeedbackTestInstance
1443 {
1444 public:
1445 TransformFeedbackStreamsTestInstance (Context& context, const TestParameters& parameters);
1446
1447 protected:
1448 tcu::TestStatus iterate (void);
1449 bool verifyImage (const VkFormat imageFormat, const VkExtent2D& size, const void* resultData);
1450 };
1451
TransformFeedbackStreamsTestInstance(Context & context,const TestParameters & parameters)1452 TransformFeedbackStreamsTestInstance::TransformFeedbackStreamsTestInstance (Context& context, const TestParameters& parameters)
1453 : TransformFeedbackTestInstance (context, parameters)
1454 {
1455 const InstanceInterface& vki = m_context.getInstanceInterface();
1456 const VkPhysicalDevice physDevice = m_context.getPhysicalDevice();
1457 const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(vki, physDevice);
1458 const VkPhysicalDeviceTransformFeedbackFeaturesEXT& transformFeedbackFeatures = m_context.getTransformFeedbackFeaturesEXT();
1459 const deUint32 streamsSupported = m_transformFeedbackProperties.maxTransformFeedbackStreams;
1460 const deUint32 streamsRequired = m_parameters.streamId + 1;
1461 const bool geomPointSizeRequired = m_parameters.testType == TEST_TYPE_STREAMS_POINTSIZE;
1462
1463 if (!features.geometryShader)
1464 TCU_THROW(NotSupportedError, "Missing feature: geometryShader");
1465
1466 if (transformFeedbackFeatures.geometryStreams == DE_FALSE)
1467 TCU_THROW(NotSupportedError, "geometryStreams feature is not supported");
1468
1469 if (streamsSupported < streamsRequired)
1470 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackStreams=" + de::toString(streamsSupported) + ", while test requires " + de::toString(streamsRequired)).c_str());
1471
1472 if (geomPointSizeRequired && !features.shaderTessellationAndGeometryPointSize)
1473 TCU_THROW(NotSupportedError, "shaderTessellationAndGeometryPointSize feature is not supported");
1474 }
1475
verifyImage(const VkFormat imageFormat,const VkExtent2D & size,const void * resultData)1476 bool TransformFeedbackStreamsTestInstance::verifyImage (const VkFormat imageFormat, const VkExtent2D& size, const void* resultData)
1477 {
1478 const tcu::RGBA magentaRGBA (tcu::RGBA(0xFF, 0x00, 0xFF, 0xFF));
1479 const tcu::Vec4 magenta (magentaRGBA.toVec());
1480 const tcu::Vec4 black (tcu::RGBA::black().toVec());
1481 const tcu::TextureFormat textureFormat (mapVkFormat(imageFormat));
1482 const int dataSize (size.width * size.height * textureFormat.getPixelSize());
1483 tcu::TextureLevel referenceImage (textureFormat, size.width, size.height);
1484 tcu::PixelBufferAccess referenceAccess (referenceImage.getAccess());
1485
1486 // Generate reference image
1487 if (m_parameters.testType == TEST_TYPE_STREAMS)
1488 {
1489 for (int y = 0; y < referenceImage.getHeight(); ++y)
1490 {
1491 const tcu::Vec4& validColor = y < referenceImage.getHeight() / 2 ? black : magenta;
1492
1493 for (int x = 0; x < referenceImage.getWidth(); ++x)
1494 referenceAccess.setPixel(validColor, x, y);
1495 }
1496 }
1497
1498 if (m_parameters.testType == TEST_TYPE_STREAMS_CLIPDISTANCE || m_parameters.testType == TEST_TYPE_STREAMS_CULLDISTANCE)
1499 {
1500 for (int y = 0; y < referenceImage.getHeight(); ++y)
1501 for (int x = 0; x < referenceImage.getWidth(); ++x)
1502 {
1503 const tcu::Vec4& validColor = (y >= referenceImage.getHeight() / 2) && (x >= referenceImage.getWidth() / 2) ? magenta : black;
1504
1505 referenceAccess.setPixel(validColor, x, y);
1506 }
1507 }
1508
1509 if (m_parameters.testType == TEST_TYPE_STREAMS_POINTSIZE)
1510 {
1511 const int pointSize = static_cast<int>(m_parameters.pointSize);
1512 const tcu::Vec4& validColor = black;
1513
1514 for (int y = 0; y < referenceImage.getHeight(); ++y)
1515 for (int x = 0; x < referenceImage.getWidth(); ++x)
1516 referenceAccess.setPixel(validColor, x, y);
1517
1518 referenceAccess.setPixel(magenta, (1 + referenceImage.getWidth()) / 4 - 1, (referenceImage.getHeight() * 3) / 4 - 1);
1519
1520 for (int y = 0; y < pointSize; ++y)
1521 for (int x = 0; x < pointSize; ++x)
1522 referenceAccess.setPixel(magenta, x + (referenceImage.getWidth() * 3) / 4 - 1, y + (referenceImage.getHeight() * 3) / 4 - 1);
1523 }
1524
1525 if (deMemCmp(resultData, referenceAccess.getDataPtr(), dataSize) != 0)
1526 {
1527 const tcu::ConstPixelBufferAccess resultImage (textureFormat, size.width, size.height, 1, resultData);
1528 bool ok;
1529
1530 ok = tcu::intThresholdCompare(m_context.getTestContext().getLog(), "Image comparison", "", referenceAccess, resultImage, tcu::UVec4(1), tcu::COMPARE_LOG_RESULT);
1531
1532 return ok;
1533 }
1534
1535 return true;
1536 }
1537
iterate(void)1538 tcu::TestStatus TransformFeedbackStreamsTestInstance::iterate (void)
1539 {
1540 const DeviceInterface& vk = m_context.getDeviceInterface();
1541 const VkDevice device = m_context.getDevice();
1542 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1543 const VkQueue queue = m_context.getUniversalQueue();
1544 Allocator& allocator = m_context.getDefaultAllocator();
1545
1546 const Unique<VkRenderPass> renderPass (makeRenderPass (vk, device, VK_FORMAT_R8G8B8A8_UNORM));
1547
1548 const Unique<VkShaderModule> vertModule (createShaderModule (vk, device, m_context.getBinaryCollection().get("vert"), 0u));
1549 const Unique<VkShaderModule> geomModule (createShaderModule (vk, device, m_context.getBinaryCollection().get("geom"), 0u));
1550 const Unique<VkShaderModule> fragModule (createShaderModule (vk, device, m_context.getBinaryCollection().get("frag"), 0u));
1551
1552 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
1553 const VkImageUsageFlags imageUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1554 const tcu::RGBA clearColor (tcu::RGBA::black());
1555 const VkImageSubresourceRange colorSubresRange (makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u));
1556 const VkDeviceSize colorBufferSize (m_imageExtent2D.width * m_imageExtent2D.height * tcu::getPixelSize(mapVkFormat(colorFormat)));
1557 const Unique<VkImage> colorImage (makeImage (vk, device, makeImageCreateInfo(0u, VK_IMAGE_TYPE_2D, colorFormat, m_imageExtent2D, 1u, imageUsageFlags)));
1558 const UniquePtr<Allocation> colorImageAlloc (bindImage (vk, device, allocator, *colorImage, MemoryRequirement::Any));
1559 const Unique<VkImageView> colorAttachment (makeImageView (vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresRange));
1560 const Unique<VkBuffer> colorBuffer (makeBuffer (vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1561 const UniquePtr<Allocation> colorBufferAlloc (bindBuffer (vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
1562
1563 const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, *colorAttachment, m_imageExtent2D.width, m_imageExtent2D.height));
1564 const Unique<VkPipelineLayout> pipelineLayout (TransformFeedback::makePipelineLayout (vk, device));
1565 const Unique<VkPipeline> pipeline (makeGraphicsPipeline (vk, device, *pipelineLayout, *renderPass, *vertModule, DE_NULL, DE_NULL, *geomModule, *fragModule, m_imageExtent2D, 0u, &m_parameters.streamId));
1566 const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1567 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1568
1569 const VkImageMemoryBarrier preCopyBarrier = makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
1570 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1571 *colorImage, colorSubresRange);
1572 const VkBufferImageCopy region = makeBufferImageCopy(makeExtent3D(m_imageExtent2D.width, m_imageExtent2D.height, 1u),
1573 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u));
1574 const VkBufferMemoryBarrier postCopyBarrier = makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *colorBuffer, 0ull, VK_WHOLE_SIZE);
1575
1576 beginCommandBuffer(vk, *cmdBuffer);
1577 {
1578 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D), clearColor.toVec());
1579 {
1580 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1581
1582 vk.cmdDraw(*cmdBuffer, 2u, 1u, 0u, 0u);
1583 }
1584 endRenderPass(vk, *cmdBuffer);
1585
1586 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &preCopyBarrier);
1587 vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, ®ion);
1588 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &postCopyBarrier, DE_NULL, 0u);
1589
1590 invalidateAlloc(vk, device, *colorBufferAlloc);
1591 }
1592 endCommandBuffer(vk, *cmdBuffer);
1593 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1594
1595 if (!verifyImage(colorFormat, m_imageExtent2D, colorBufferAlloc->getHostPtr()))
1596 return tcu::TestStatus::fail("Fail");
1597
1598 return tcu::TestStatus::pass("Pass");
1599 }
1600
1601 class TransformFeedbackIndirectDrawTestInstance : public TransformFeedbackTestInstance
1602 {
1603 public:
1604 TransformFeedbackIndirectDrawTestInstance (Context& context, const TestParameters& parameters);
1605
1606 protected:
1607 tcu::TestStatus iterate (void);
1608 bool verifyImage (const VkFormat imageFormat, const VkExtent2D& size, const void* resultData);
1609 };
1610
TransformFeedbackIndirectDrawTestInstance(Context & context,const TestParameters & parameters)1611 TransformFeedbackIndirectDrawTestInstance::TransformFeedbackIndirectDrawTestInstance (Context& context, const TestParameters& parameters)
1612 : TransformFeedbackTestInstance (context, parameters)
1613 {
1614 const InstanceInterface& vki = m_context.getInstanceInterface();
1615 const VkPhysicalDevice physDevice = m_context.getPhysicalDevice();
1616 const VkPhysicalDeviceLimits limits = getPhysicalDeviceProperties(vki, physDevice).limits;
1617 const deUint32 tfBufferDataSizeSupported = m_transformFeedbackProperties.maxTransformFeedbackBufferDataSize;
1618 const deUint32 tfBufferDataStrideSupported = m_transformFeedbackProperties.maxTransformFeedbackBufferDataStride;
1619
1620 if (m_transformFeedbackProperties.transformFeedbackDraw == DE_FALSE)
1621 TCU_THROW(NotSupportedError, "transformFeedbackDraw feature is not supported");
1622
1623 if (limits.maxVertexInputBindingStride < m_parameters.vertexStride)
1624 TCU_THROW(NotSupportedError, std::string("maxVertexInputBindingStride=" + de::toString(limits.maxVertexInputBindingStride) + ", while test requires " + de::toString(m_parameters.vertexStride)).c_str());
1625
1626 if (tfBufferDataSizeSupported < m_parameters.vertexStride)
1627 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBufferDataSize=" + de::toString(tfBufferDataSizeSupported) + ", while test requires " + de::toString(m_parameters.vertexStride)).c_str());
1628
1629 if (tfBufferDataStrideSupported < m_parameters.vertexStride)
1630 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBufferDataStride=" + de::toString(tfBufferDataStrideSupported) + ", while test requires " + de::toString(m_parameters.vertexStride)).c_str());
1631 }
1632
verifyImage(const VkFormat imageFormat,const VkExtent2D & size,const void * resultData)1633 bool TransformFeedbackIndirectDrawTestInstance::verifyImage (const VkFormat imageFormat, const VkExtent2D& size, const void* resultData)
1634 {
1635 const tcu::Vec4 white (tcu::RGBA::white().toVec());
1636 const tcu::TextureFormat textureFormat (mapVkFormat(imageFormat));
1637 const int dataSize (size.width * size.height * textureFormat.getPixelSize());
1638 tcu::TextureLevel referenceImage (textureFormat, size.width, size.height);
1639 tcu::PixelBufferAccess referenceAccess (referenceImage.getAccess());
1640
1641 // Generate reference image
1642 for (int y = 0; y < referenceImage.getHeight(); ++y)
1643 for (int x = 0; x < referenceImage.getWidth(); ++x)
1644 referenceAccess.setPixel(white, x, y);
1645
1646 if (deMemCmp(resultData, referenceAccess.getDataPtr(), dataSize) != 0)
1647 {
1648 const tcu::ConstPixelBufferAccess resultImage (textureFormat, size.width, size.height, 1, resultData);
1649 bool ok;
1650
1651 ok = tcu::intThresholdCompare(m_context.getTestContext().getLog(), "Image comparison", "", referenceAccess, resultImage, tcu::UVec4(1), tcu::COMPARE_LOG_RESULT);
1652
1653 return ok;
1654 }
1655
1656 return true;
1657 }
1658
iterate(void)1659 tcu::TestStatus TransformFeedbackIndirectDrawTestInstance::iterate (void)
1660 {
1661 const DeviceInterface& vk = m_context.getDeviceInterface();
1662 const VkDevice device = m_context.getDevice();
1663 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1664 const VkQueue queue = m_context.getUniversalQueue();
1665 Allocator& allocator = m_context.getDefaultAllocator();
1666
1667 const Unique<VkRenderPass> renderPass (makeRenderPass (vk, device, VK_FORMAT_R8G8B8A8_UNORM));
1668
1669 const Unique<VkShaderModule> vertModule (createShaderModule (vk, device, m_context.getBinaryCollection().get("vert"), 0u));
1670 const Unique<VkShaderModule> fragModule (createShaderModule (vk, device, m_context.getBinaryCollection().get("frag"), 0u));
1671
1672 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
1673 const VkImageUsageFlags imageUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1674 const tcu::RGBA clearColor (tcu::RGBA::black());
1675 const VkImageSubresourceRange colorSubresRange (makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u));
1676 const VkDeviceSize colorBufferSize (m_imageExtent2D.width * m_imageExtent2D.height * tcu::getPixelSize(mapVkFormat(colorFormat)));
1677 const Unique<VkImage> colorImage (makeImage (vk, device, makeImageCreateInfo(0u, VK_IMAGE_TYPE_2D, colorFormat, m_imageExtent2D, 1u, imageUsageFlags)));
1678 const UniquePtr<Allocation> colorImageAlloc (bindImage (vk, device, allocator, *colorImage, MemoryRequirement::Any));
1679 const Unique<VkImageView> colorAttachment (makeImageView (vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresRange));
1680 const Unique<VkBuffer> colorBuffer (makeBuffer (vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1681 const UniquePtr<Allocation> colorBufferAlloc (bindBuffer (vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
1682
1683 const deUint32 vertexCount = 6u;
1684 const VkDeviceSize vertexBufferSize = vertexCount * m_parameters.vertexStride;
1685 const VkBufferUsageFlags vertexBufferUsage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
1686 const Unique<VkBuffer> vertexBuffer (makeBuffer (vk, device, vertexBufferSize, vertexBufferUsage));
1687 const UniquePtr<Allocation> vertexBufferAlloc (bindBuffer (vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
1688 const VkDeviceSize vertexBufferOffset (0u);
1689 const float vertexBufferVals[] =
1690 {
1691 -1.0f, -1.0f, 0.0f, 1.0f,
1692 -1.0f, +1.0f, 0.0f, 1.0f,
1693 +1.0f, -1.0f, 0.0f, 1.0f,
1694 -1.0f, +1.0f, 0.0f, 1.0f,
1695 +1.0f, -1.0f, 0.0f, 1.0f,
1696 +1.0f, +1.0f, 0.0f, 1.0f,
1697 };
1698
1699 const deUint32 counterBufferValue = m_parameters.vertexStride * vertexCount;
1700 const VkDeviceSize counterBufferSize = sizeof(counterBufferValue);
1701 const VkBufferUsageFlags counterBufferUsage = VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
1702 const Unique<VkBuffer> counterBuffer (makeBuffer (vk, device, counterBufferSize, counterBufferUsage));
1703 const UniquePtr<Allocation> counterBufferAlloc (bindBuffer (vk, device, allocator, *counterBuffer, MemoryRequirement::HostVisible));
1704
1705 const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, *colorAttachment, m_imageExtent2D.width, m_imageExtent2D.height));
1706 const Unique<VkPipelineLayout> pipelineLayout (TransformFeedback::makePipelineLayout (vk, device));
1707 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));
1708 const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1709 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1710
1711 const VkImageMemoryBarrier preCopyBarrier = makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
1712 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1713 *colorImage, colorSubresRange);
1714 const VkBufferImageCopy region = makeBufferImageCopy(makeExtent3D(m_imageExtent2D.width, m_imageExtent2D.height, 1u),
1715 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u));
1716 const VkBufferMemoryBarrier postCopyBarrier = makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *colorBuffer, 0ull, VK_WHOLE_SIZE);
1717
1718 fillBuffer(vk, device, *counterBufferAlloc, counterBufferSize, &counterBufferValue, counterBufferSize);
1719 fillBuffer(vk, device, *vertexBufferAlloc, vertexBufferSize, vertexBufferVals, sizeof(vertexBufferVals));
1720
1721 beginCommandBuffer(vk, *cmdBuffer);
1722 {
1723 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D), clearColor.toVec());
1724 {
1725 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &*vertexBuffer, &vertexBufferOffset);
1726
1727 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1728
1729 vk.cmdDrawIndirectByteCountEXT(*cmdBuffer, 1u, 0u, *counterBuffer, 0u, 0u, m_parameters.vertexStride);
1730 }
1731 endRenderPass(vk, *cmdBuffer);
1732
1733 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &preCopyBarrier);
1734 vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, ®ion);
1735 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &postCopyBarrier, DE_NULL, 0u);
1736
1737 invalidateAlloc(vk, device, *colorBufferAlloc);
1738 }
1739 endCommandBuffer(vk, *cmdBuffer);
1740 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1741
1742 if (!verifyImage(colorFormat, m_imageExtent2D, colorBufferAlloc->getHostPtr()))
1743 return tcu::TestStatus::fail("Fail");
1744
1745 return tcu::TestStatus::pass("Pass");
1746 }
1747
1748 class TransformFeedbackBackwardDependencyTestInstance : public TransformFeedbackTestInstance
1749 {
1750 public:
1751 TransformFeedbackBackwardDependencyTestInstance (Context& context, const TestParameters& parameters);
1752
1753 protected:
1754 tcu::TestStatus iterate (void);
1755 std::vector<VkDeviceSize> generateSizesList (const size_t bufBytes, const size_t chunkCount);
1756 };
1757
TransformFeedbackBackwardDependencyTestInstance(Context & context,const TestParameters & parameters)1758 TransformFeedbackBackwardDependencyTestInstance::TransformFeedbackBackwardDependencyTestInstance (Context& context, const TestParameters& parameters)
1759 : TransformFeedbackTestInstance (context, parameters)
1760 {
1761 if (m_transformFeedbackProperties.transformFeedbackDraw == DE_FALSE)
1762 TCU_THROW(NotSupportedError, "transformFeedbackDraw feature is not supported");
1763 }
1764
generateSizesList(const size_t bufBytes,const size_t chunkCount)1765 std::vector<VkDeviceSize> TransformFeedbackBackwardDependencyTestInstance::generateSizesList (const size_t bufBytes, const size_t chunkCount)
1766 {
1767 const VkDeviceSize chunkSize = bufBytes / chunkCount;
1768 std::vector<VkDeviceSize> result (chunkCount, chunkSize);
1769
1770 DE_ASSERT(chunkSize * chunkCount == bufBytes);
1771 DE_ASSERT(bufBytes <= MINIMUM_TF_BUFFER_SIZE);
1772 DE_ASSERT(bufBytes % sizeof(deUint32) == 0);
1773 DE_ASSERT(chunkCount > 0);
1774 DE_ASSERT(result.size() == chunkCount);
1775
1776 return result;
1777 }
1778
iterate(void)1779 tcu::TestStatus TransformFeedbackBackwardDependencyTestInstance::iterate (void)
1780 {
1781 const DeviceInterface& vk = m_context.getDeviceInterface();
1782 const VkDevice device = m_context.getDevice();
1783 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1784 const VkQueue queue = m_context.getUniversalQueue();
1785 Allocator& allocator = m_context.getDefaultAllocator();
1786
1787 const Unique<VkShaderModule> vertexModule (createShaderModule (vk, device, m_context.getBinaryCollection().get("vert"), 0u));
1788 const Unique<VkRenderPass> renderPass (TransformFeedback::makeRenderPass (vk, device));
1789 const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, 0u, DE_NULL, m_imageExtent2D.width, m_imageExtent2D.height));
1790 const Unique<VkPipelineLayout> pipelineLayout (TransformFeedback::makePipelineLayout (vk, device));
1791 const Unique<VkPipeline> pipeline (makeGraphicsPipeline (vk, device, *pipelineLayout, *renderPass, *vertexModule, DE_NULL, DE_NULL, DE_NULL, DE_NULL, m_imageExtent2D, 0u));
1792 const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1793 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1794
1795 const VkBufferCreateInfo tfBufCreateInfo = makeBufferCreateInfo(m_parameters.bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT);
1796 const Move<VkBuffer> tfBuf = createBuffer(vk, device, &tfBufCreateInfo);
1797 const MovePtr<Allocation> tfBufAllocation = allocator.allocate(getBufferMemoryRequirements(vk, device, *tfBuf), MemoryRequirement::HostVisible);
1798 const VkMemoryBarrier tfMemoryBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT, VK_ACCESS_HOST_READ_BIT);
1799 const VkDeviceSize tfBufBindingSize = m_parameters.bufferSize;
1800 const VkDeviceSize tfBufBindingOffset = 0ull;
1801
1802 const size_t tfcBufSize = sizeof(deUint32);
1803 const VkBufferCreateInfo tfcBufCreateInfo = makeBufferCreateInfo(tfcBufSize, VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT | VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT);
1804 const Move<VkBuffer> tfcBuf = createBuffer(vk, device, &tfcBufCreateInfo);
1805 const MovePtr<Allocation> tfcBufAllocation = allocator.allocate(getBufferMemoryRequirements(vk, device, *tfcBuf), MemoryRequirement::Any);
1806 const VkDeviceSize tfcBufBindingOffset = 0ull;
1807 const VkMemoryBarrier tfcMemoryBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT, VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT);
1808
1809 const std::vector<VkDeviceSize> chunkSizesList = generateSizesList(m_parameters.bufferSize, m_parameters.partCount);
1810 const std::vector<VkDeviceSize> chunkOffsetsList = generateOffsetsList(chunkSizesList);
1811
1812 VK_CHECK(vk.bindBufferMemory(device, *tfBuf, tfBufAllocation->getMemory(), tfBufAllocation->getOffset()));
1813 VK_CHECK(vk.bindBufferMemory(device, *tfcBuf, tfcBufAllocation->getMemory(), tfcBufAllocation->getOffset()));
1814
1815 DE_ASSERT(m_parameters.partCount == 2u);
1816
1817 beginCommandBuffer(vk, *cmdBuffer);
1818 {
1819 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
1820 {
1821 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1822
1823 vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0, 1, &*tfBuf, &tfBufBindingOffset, &tfBufBindingSize);
1824
1825 {
1826 const deUint32 startValue = static_cast<deUint32>(chunkOffsetsList[0] / sizeof(deUint32));
1827 const deUint32 numPoints = static_cast<deUint32>(chunkSizesList[0] / sizeof(deUint32));
1828
1829 vk.cmdPushConstants(*cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0u, sizeof(startValue), &startValue);
1830
1831 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1832 {
1833 vk.cmdDraw(*cmdBuffer, numPoints, 1u, 0u, 0u);
1834 }
1835 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 1, &*tfcBuf, m_parameters.noOffsetArray ? DE_NULL : &tfcBufBindingOffset);
1836 }
1837
1838 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);
1839
1840 {
1841 const deUint32 startValue = static_cast<deUint32>(chunkOffsetsList[1] / sizeof(deUint32));
1842
1843 vk.cmdPushConstants(*cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0u, sizeof(startValue), &startValue);
1844
1845 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 1, &*tfcBuf, m_parameters.noOffsetArray ? DE_NULL : &tfcBufBindingOffset);
1846 {
1847 vk.cmdDrawIndirectByteCountEXT(*cmdBuffer, 1u, 0u, *tfcBuf, 0u, 0u, 4u);
1848 }
1849 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1850 }
1851
1852 }
1853 endRenderPass(vk, *cmdBuffer);
1854
1855 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &tfMemoryBarrier, 0u, DE_NULL, 0u, DE_NULL);
1856 }
1857 endCommandBuffer(vk, *cmdBuffer);
1858 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1859
1860 verifyTransformFeedbackBuffer(tfBufAllocation, m_parameters.bufferSize);
1861
1862 return tcu::TestStatus::pass("Pass");
1863 }
1864
1865
1866 class TransformFeedbackQueryTestInstance : public TransformFeedbackTestInstance
1867 {
1868 public:
1869 TransformFeedbackQueryTestInstance (Context& context, const TestParameters& parameters);
1870
1871 protected:
1872 tcu::TestStatus iterate (void);
1873 };
1874
TransformFeedbackQueryTestInstance(Context & context,const TestParameters & parameters)1875 TransformFeedbackQueryTestInstance::TransformFeedbackQueryTestInstance (Context& context, const TestParameters& parameters)
1876 : TransformFeedbackTestInstance (context, parameters)
1877 {
1878 const InstanceInterface& vki = m_context.getInstanceInterface();
1879 const VkPhysicalDevice physDevice = m_context.getPhysicalDevice();
1880 const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(vki, physDevice);
1881 const VkPhysicalDeviceTransformFeedbackFeaturesEXT& transformFeedbackFeatures = m_context.getTransformFeedbackFeaturesEXT();
1882 const deUint32 streamsSupported = m_transformFeedbackProperties.maxTransformFeedbackStreams;
1883 const deUint32 streamsRequired = m_parameters.streamId + 1;
1884
1885 if (!features.geometryShader)
1886 TCU_THROW(NotSupportedError, "Missing feature: geometryShader");
1887
1888 if (streamsRequired > 1 && transformFeedbackFeatures.geometryStreams == DE_FALSE)
1889 TCU_THROW(NotSupportedError, "geometryStreams feature is not supported");
1890
1891 if (streamsSupported < streamsRequired)
1892 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackStreams=" + de::toString(streamsSupported) + ", while test requires " + de::toString(streamsRequired)).c_str());
1893
1894 if (m_transformFeedbackProperties.transformFeedbackQueries == DE_FALSE)
1895 TCU_THROW(NotSupportedError, "transformFeedbackQueries feature is not supported");
1896
1897 if (m_parameters.testType == TEST_TYPE_QUERY_RESET)
1898 {
1899 // Check VK_EXT_host_query_reset is supported
1900 m_context.requireDeviceFunctionality("VK_EXT_host_query_reset");
1901 if(m_context.getHostQueryResetFeatures().hostQueryReset == VK_FALSE)
1902 throw tcu::NotSupportedError(std::string("Implementation doesn't support resetting queries from the host").c_str());
1903 }
1904 }
1905
iterate(void)1906 tcu::TestStatus TransformFeedbackQueryTestInstance::iterate (void)
1907 {
1908 const DeviceInterface& vk = m_context.getDeviceInterface();
1909 const VkDevice device = m_context.getDevice();
1910 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1911 const VkQueue queue = m_context.getUniversalQueue();
1912 Allocator& allocator = m_context.getDefaultAllocator();
1913
1914 const deUint64 overflowVertices = 3u;
1915 const deUint32 bytesPerVertex = static_cast<deUint32>(4 * sizeof(float));
1916 const deUint64 numVerticesInBuffer = m_parameters.bufferSize / bytesPerVertex;
1917 const deUint64 numVerticesToWrite = numVerticesInBuffer + overflowVertices;
1918 const Unique<VkRenderPass> renderPass (makeRenderPass (vk, device, VK_FORMAT_UNDEFINED));
1919
1920 const Unique<VkShaderModule> vertModule (createShaderModule (vk, device, m_context.getBinaryCollection().get("vert"), 0u));
1921 const Unique<VkShaderModule> geomModule (createShaderModule (vk, device, m_context.getBinaryCollection().get("geom"), 0u));
1922
1923 const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, 0u, DE_NULL, m_imageExtent2D.width, m_imageExtent2D.height));
1924 const Unique<VkPipelineLayout> pipelineLayout (TransformFeedback::makePipelineLayout (vk, device));
1925 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));
1926 const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1927 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1928
1929 const deUint32 tfBufferSize = (deUint32)topologyData.at(m_parameters.primTopology).getNumPrimitives(numVerticesInBuffer) * (deUint32)topologyData.at(m_parameters.primTopology).primSize * bytesPerVertex;
1930 const VkBufferCreateInfo tfBufCreateInfo = makeBufferCreateInfo(tfBufferSize, VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT);
1931 const Move<VkBuffer> tfBuf = createBuffer(vk, device, &tfBufCreateInfo);
1932 const MovePtr<Allocation> tfBufAllocation = bindBuffer(vk, device, allocator, *tfBuf, MemoryRequirement::HostVisible);
1933 const VkDeviceSize tfBufBindingSize = tfBufferSize;
1934 const VkDeviceSize tfBufBindingOffset = 0ull;
1935
1936 const size_t queryResultWidth = (m_parameters.query64bits ? sizeof(deUint64) : sizeof(deUint32));
1937 const vk::VkQueryControlFlags queryExtraFlags = (m_parameters.query64bits ? vk::VK_QUERY_RESULT_64_BIT : 0);
1938 const deUint32 queryCountersNumber = 1u;
1939 const deUint32 queryIndex = 0u;
1940 constexpr deUint32 queryResultElements = 2u;
1941 const deUint32 queryDataSize = static_cast<deUint32>(queryResultElements * queryResultWidth);
1942 const VkQueryPoolCreateInfo queryPoolCreateInfo = makeQueryPoolCreateInfo(queryCountersNumber);
1943 const Unique<VkQueryPool> queryPool (createQueryPool(vk, device, &queryPoolCreateInfo));
1944
1945 Move<VkBuffer> queryPoolResultsBuffer;
1946 de::MovePtr<Allocation> queryPoolResultsBufferAlloc;
1947
1948 tcu::TestLog& log = m_context.getTestContext().getLog();
1949
1950 DE_ASSERT(numVerticesInBuffer * bytesPerVertex == m_parameters.bufferSize);
1951
1952 if (m_parameters.testType == TEST_TYPE_QUERY_COPY || m_parameters.testType == TEST_TYPE_QUERY_COPY_STRIDE_ZERO)
1953 {
1954 const VkBufferCreateInfo bufferParams =
1955 {
1956 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
1957 DE_NULL, // const void* pNext;
1958 0u, // VkBufferCreateFlags flags;
1959 queryDataSize, // VkDeviceSize size;
1960 VK_BUFFER_USAGE_TRANSFER_DST_BIT, // VkBufferUsageFlags usage;
1961 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1962 1u, // deUint32 queueFamilyCount;
1963 &queueFamilyIndex // const deUint32* pQueueFamilyIndices;
1964 };
1965
1966 queryPoolResultsBuffer = createBuffer(vk, device, &bufferParams);
1967 queryPoolResultsBufferAlloc = allocator.allocate(getBufferMemoryRequirements(vk, device, *queryPoolResultsBuffer), MemoryRequirement::HostVisible);
1968
1969 VK_CHECK(vk.bindBufferMemory(device, *queryPoolResultsBuffer, queryPoolResultsBufferAlloc->getMemory(), queryPoolResultsBufferAlloc->getOffset()));
1970 }
1971
1972 beginCommandBuffer(vk, *cmdBuffer);
1973 {
1974 if (m_parameters.testType != TEST_TYPE_QUERY_RESET)
1975 vk.cmdResetQueryPool(*cmdBuffer, *queryPool, queryIndex, queryCountersNumber);
1976
1977 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
1978 {
1979 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1980
1981 vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0u, 1u, &*tfBuf, &tfBufBindingOffset, &tfBufBindingSize);
1982
1983 if (m_parameters.streamId == 0 && m_parameters.streamId0Mode != STREAM_ID_0_BEGIN_QUERY_INDEXED)
1984 vk.cmdBeginQuery(*cmdBuffer, *queryPool, queryIndex, 0u);
1985 else
1986 vk.cmdBeginQueryIndexedEXT(*cmdBuffer, *queryPool, queryIndex, 0u, m_parameters.streamId);
1987 {
1988 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1989 {
1990 vk.cmdDraw(*cmdBuffer, static_cast<deUint32>(numVerticesToWrite), 1u, 0u, 0u);
1991 }
1992 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1993 }
1994 if (m_parameters.streamId == 0 && m_parameters.streamId0Mode != STREAM_ID_0_END_QUERY_INDEXED)
1995 vk.cmdEndQuery(*cmdBuffer, *queryPool, queryIndex);
1996 else
1997 vk.cmdEndQueryIndexedEXT(*cmdBuffer, *queryPool, queryIndex, m_parameters.streamId);
1998 }
1999 endRenderPass(vk, *cmdBuffer);
2000
2001 if (m_parameters.testType == TEST_TYPE_QUERY_COPY || m_parameters.testType == TEST_TYPE_QUERY_COPY_STRIDE_ZERO)
2002 {
2003 VkDeviceSize copyStride = queryDataSize;
2004 if (queryCountersNumber == 1u && m_parameters.testType == TEST_TYPE_QUERY_COPY_STRIDE_ZERO)
2005 copyStride = 0;
2006 vk.cmdCopyQueryPoolResults(*cmdBuffer, *queryPool, queryIndex, queryCountersNumber, *queryPoolResultsBuffer, 0u, copyStride, (vk::VK_QUERY_RESULT_WAIT_BIT | queryExtraFlags));
2007
2008 const VkBufferMemoryBarrier bufferBarrier =
2009 {
2010 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
2011 DE_NULL, // const void* pNext;
2012 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
2013 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask;
2014 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
2015 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
2016 *queryPoolResultsBuffer, // VkBuffer buffer;
2017 0ull, // VkDeviceSize offset;
2018 VK_WHOLE_SIZE // VkDeviceSize size;
2019 };
2020 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL);
2021 }
2022
2023 }
2024 endCommandBuffer(vk, *cmdBuffer);
2025
2026 if (m_parameters.testType == TEST_TYPE_QUERY_RESET)
2027 vk.resetQueryPool(device, *queryPool, queryIndex, queryCountersNumber);
2028 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
2029
2030 {
2031 union Results
2032 {
2033 deUint32 elements32[queryResultElements];
2034 deUint64 elements64[queryResultElements];
2035 };
2036
2037 std::vector<deUint8> queryData (queryDataSize, 0u);
2038 const Results* queryResults = reinterpret_cast<Results*>(queryData.data());
2039
2040 if (m_parameters.testType != TEST_TYPE_QUERY_COPY && m_parameters.testType != TEST_TYPE_QUERY_COPY_STRIDE_ZERO)
2041 {
2042 vk.getQueryPoolResults(device, *queryPool, queryIndex, queryCountersNumber, queryDataSize, queryData.data(), queryDataSize, (vk::VK_QUERY_RESULT_WAIT_BIT | queryExtraFlags));
2043 }
2044 else
2045 {
2046 invalidateAlloc(vk, device, *queryPoolResultsBufferAlloc);
2047 deMemcpy(queryData.data(), queryPoolResultsBufferAlloc->getHostPtr(), queryData.size());
2048 }
2049
2050 // The number of primitives successfully written to the corresponding transform feedback buffer.
2051 const deUint64 numPrimitivesWritten = (m_parameters.query64bits ? queryResults->elements64[0] : queryResults->elements32[0]);
2052
2053 // The number of primitives output to the vertex stream.
2054 const deUint64 numPrimitivesNeeded = (m_parameters.query64bits ? queryResults->elements64[1] : queryResults->elements32[1]);
2055
2056 // Count how many primitives we should get by using selected topology.
2057 const auto primitivesInBuffer = topologyData.at(m_parameters.primTopology).getNumPrimitives(numVerticesInBuffer);
2058 const auto primitivesToWrite = topologyData.at(m_parameters.primTopology).getNumPrimitives(numVerticesToWrite);
2059
2060 log << tcu::TestLog::Message << "Primitives Written / Expected : " << de::toString(numPrimitivesWritten) << " / " << de::toString(primitivesInBuffer) << tcu::TestLog::EndMessage;
2061 log << tcu::TestLog::Message << "Primitives Needed / Expected : " << de::toString(numPrimitivesNeeded) << " / " << de::toString(primitivesToWrite) << tcu::TestLog::EndMessage;
2062
2063 if (numPrimitivesWritten != primitivesInBuffer)
2064 return tcu::TestStatus::fail("numPrimitivesWritten=" + de::toString(numPrimitivesWritten) + " while expected " + de::toString(primitivesInBuffer));
2065
2066 if (numPrimitivesNeeded != primitivesToWrite)
2067 return tcu::TestStatus::fail("numPrimitivesNeeded=" + de::toString(numPrimitivesNeeded) + " while expected " + de::toString(primitivesToWrite));
2068 }
2069
2070 if (m_parameters.testType == TEST_TYPE_QUERY_RESET)
2071 {
2072 constexpr deUint32 queryResetElements = queryResultElements + 1; // For the availability bit.
2073
2074 union Results
2075 {
2076 deUint32 elements32[queryResetElements];
2077 deUint64 elements64[queryResetElements];
2078 };
2079
2080 const deUint32 queryDataAvailSize (static_cast<deUint32>(queryResetElements * queryResultWidth));
2081 std::vector<deUint8> queryData (queryDataAvailSize, 0u);
2082 Results* queryResults = reinterpret_cast<Results*>(queryData.data());
2083
2084 // Initialize values
2085 if (m_parameters.query64bits)
2086 {
2087 queryResults->elements64[0] = 1u; // numPrimitivesWritten
2088 queryResults->elements64[1] = 1u; // numPrimitivesNeeded
2089 queryResults->elements64[2] = 1u; // Availability bit
2090 }
2091 else
2092 {
2093 queryResults->elements32[0] = 1u; // numPrimitivesWritten
2094 queryResults->elements32[1] = 1u; // numPrimitivesNeeded
2095 queryResults->elements32[2] = 1u; // Availability bit
2096 }
2097
2098 vk.resetQueryPool(device, *queryPool, queryIndex, queryCountersNumber);
2099
2100 vk::VkResult res = vk.getQueryPoolResults(device, *queryPool, queryIndex, queryCountersNumber, queryDataAvailSize, queryData.data(), queryDataAvailSize, (vk::VK_QUERY_RESULT_WITH_AVAILABILITY_BIT | queryExtraFlags));
2101 const deUint64 numPrimitivesWritten = (m_parameters.query64bits ? queryResults->elements64[0] : queryResults->elements32[0]);
2102 const deUint64 numPrimitivesNeeded = (m_parameters.query64bits ? queryResults->elements64[1] : queryResults->elements32[1]);
2103 const deUint64 availabilityState = (m_parameters.query64bits ? queryResults->elements64[2] : queryResults->elements32[2]);
2104
2105 /* From the Vulkan spec:
2106 *
2107 * If VK_QUERY_RESULT_WAIT_BIT and VK_QUERY_RESULT_PARTIAL_BIT are both not set then no result values are written to pData
2108 * for queries that are in the unavailable state at the time of the call, and vkGetQueryPoolResults returns VK_NOT_READY.
2109 * However, availability state is still written to pData for those queries if VK_QUERY_RESULT_WITH_AVAILABILITY_BIT is set.
2110 */
2111 if (res != vk::VK_NOT_READY || availabilityState != 0u)
2112 return tcu::TestStatus::fail("QueryPoolResults incorrect reset");
2113 if (numPrimitivesWritten != 1u || numPrimitivesNeeded != 1u)
2114 return tcu::TestStatus::fail("QueryPoolResults data was modified");
2115
2116 }
2117
2118 return tcu::TestStatus::pass("Pass");
2119 }
2120
2121 class TransformFeedbackMultiQueryTestInstance : public TransformFeedbackTestInstance
2122 {
2123 public:
2124 TransformFeedbackMultiQueryTestInstance (Context& context, const TestParameters& parameters);
2125
2126 protected:
2127 std::vector<VkDeviceSize> generateSizesList (const size_t bufBytes, const size_t chunkCount);
2128 void verifyTransformFeedbackBuffer (const MovePtr<Allocation>& bufAlloc, const deUint32 bufBytes, const deUint32 bufOffset, const float expected);
2129 tcu::TestStatus iterate (void);
2130 };
2131
TransformFeedbackMultiQueryTestInstance(Context & context,const TestParameters & parameters)2132 TransformFeedbackMultiQueryTestInstance::TransformFeedbackMultiQueryTestInstance (Context& context, const TestParameters& parameters)
2133 : TransformFeedbackTestInstance (context, parameters)
2134 {
2135 const InstanceInterface& vki = m_context.getInstanceInterface();
2136 const VkPhysicalDevice physDevice = m_context.getPhysicalDevice();
2137 const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(vki, physDevice);
2138 const VkPhysicalDeviceTransformFeedbackFeaturesEXT& transformFeedbackFeatures = m_context.getTransformFeedbackFeaturesEXT();
2139 const deUint32 streamsSupported = m_transformFeedbackProperties.maxTransformFeedbackStreams;
2140 const deUint32 streamsRequired = m_parameters.streamId + 1;
2141 const deUint32 tfBuffersSupported = m_transformFeedbackProperties.maxTransformFeedbackBuffers;
2142 const deUint32 tfBuffersRequired = m_parameters.partCount;
2143 const deUint32 bytesPerVertex = m_parameters.bufferSize / m_parameters.partCount;
2144 const deUint32 tfStreamDataSizeSupported = m_transformFeedbackProperties.maxTransformFeedbackStreamDataSize;
2145 const deUint32 tfBufferDataSizeSupported = m_transformFeedbackProperties.maxTransformFeedbackBufferDataSize;
2146 const deUint32 tfBufferDataStrideSupported = m_transformFeedbackProperties.maxTransformFeedbackBufferDataStride;
2147
2148 DE_ASSERT(m_parameters.partCount == 2u);
2149
2150 if (!features.geometryShader)
2151 TCU_THROW(NotSupportedError, "Missing feature: geometryShader");
2152
2153 if (transformFeedbackFeatures.geometryStreams == DE_FALSE)
2154 TCU_THROW(NotSupportedError, "geometryStreams feature is not supported");
2155
2156 if (streamsSupported < streamsRequired)
2157 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackStreams=" + de::toString(streamsSupported) + ", while test requires " + de::toString(streamsRequired)).c_str());
2158
2159 if (tfBuffersSupported < tfBuffersRequired)
2160 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBuffers=" + de::toString(tfBuffersSupported) + ", while test requires " + de::toString(tfBuffersRequired)).c_str());
2161
2162 if (tfStreamDataSizeSupported < bytesPerVertex)
2163 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackStreamDataSize=" + de::toString(tfStreamDataSizeSupported) + ", while test requires " + de::toString(bytesPerVertex)).c_str());
2164
2165 if (tfBufferDataSizeSupported < bytesPerVertex)
2166 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBufferDataSize=" + de::toString(tfBufferDataSizeSupported) + ", while test requires " + de::toString(bytesPerVertex)).c_str());
2167
2168 if (tfBufferDataStrideSupported < bytesPerVertex)
2169 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBufferDataStride=" + de::toString(tfBufferDataStrideSupported) + ", while test requires " + de::toString(bytesPerVertex)).c_str());
2170
2171 if (m_transformFeedbackProperties.transformFeedbackQueries == DE_FALSE)
2172 TCU_THROW(NotSupportedError, "transformFeedbackQueries feature is not supported");
2173 }
2174
generateSizesList(const size_t bufBytes,const size_t chunkCount)2175 std::vector<VkDeviceSize> TransformFeedbackMultiQueryTestInstance::generateSizesList (const size_t bufBytes, const size_t chunkCount)
2176 {
2177 const VkDeviceSize chunkSize = bufBytes / chunkCount;
2178 std::vector<VkDeviceSize> result (chunkCount, chunkSize);
2179
2180 DE_ASSERT(chunkSize * chunkCount == bufBytes);
2181 DE_ASSERT(bufBytes <= MINIMUM_TF_BUFFER_SIZE);
2182 DE_ASSERT(bufBytes % sizeof(deUint32) == 0);
2183 DE_ASSERT(chunkCount > 0);
2184 DE_ASSERT(result.size() == chunkCount);
2185
2186 return result;
2187 }
2188
verifyTransformFeedbackBuffer(const MovePtr<Allocation> & bufAlloc,const deUint32 bufBytes,const deUint32 bufOffset,const float expected)2189 void TransformFeedbackMultiQueryTestInstance::verifyTransformFeedbackBuffer (const MovePtr<Allocation>& bufAlloc, const deUint32 bufBytes, const deUint32 bufOffset, const float expected)
2190 {
2191 const DeviceInterface& vk = m_context.getDeviceInterface();
2192 const VkDevice device = m_context.getDevice();
2193 const deUint32 numPoints = bufBytes / static_cast<deUint32>(sizeof(float));
2194 const deUint8* tfDataRaw = getInvalidatedHostPtr<deUint8>(vk, device, *bufAlloc);
2195 const float* tfData = reinterpret_cast<const float*>(&tfDataRaw[bufOffset]);
2196
2197 for (deUint32 i = 0; i < numPoints; ++i)
2198 if (tfData[i] != expected)
2199 TCU_FAIL(std::string("Failed at item ") + de::toString(i) + " received:" + de::toString(tfData[i]) + " expected:" + de::toString(expected));
2200 }
2201
iterate(void)2202 tcu::TestStatus TransformFeedbackMultiQueryTestInstance::iterate (void)
2203 {
2204 const DeviceInterface& vk = m_context.getDeviceInterface();
2205 const VkDevice device = m_context.getDevice();
2206 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
2207 const std::vector<deUint32> queueFamilyIndices = { queueFamilyIndex };
2208 const VkQueue queue = m_context.getUniversalQueue();
2209 Allocator& allocator = m_context.getDefaultAllocator();
2210
2211 const Unique<VkRenderPass> renderPass (makeRenderPass (vk, device, VK_FORMAT_UNDEFINED));
2212
2213 const Unique<VkShaderModule> vertModule (createShaderModule (vk, device, m_context.getBinaryCollection().get("vert"), 0u));
2214 const Unique<VkShaderModule> geomModule (createShaderModule (vk, device, m_context.getBinaryCollection().get("geom"), 0u));
2215
2216 const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, 0u, DE_NULL, m_imageExtent2D.width, m_imageExtent2D.height));
2217 const Unique<VkPipelineLayout> pipelineLayout (TransformFeedback::makePipelineLayout (vk, device));
2218 const Unique<VkPipeline> pipeline (makeGraphicsPipeline (vk, device, *pipelineLayout, *renderPass, *vertModule, DE_NULL, DE_NULL, *geomModule, DE_NULL, m_imageExtent2D, 0u));
2219 const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
2220 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
2221
2222 const VkBufferCreateInfo tfBufCreateInfo = makeBufferCreateInfo(m_parameters.bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT);
2223 const Move<VkBuffer> tfBuf = createBuffer(vk, device, &tfBufCreateInfo);
2224 const std::vector<VkBuffer> tfBufArray = std::vector<VkBuffer>(m_parameters.partCount, *tfBuf);
2225 const MovePtr<Allocation> tfBufAllocation = allocator.allocate(getBufferMemoryRequirements(vk, device, *tfBuf), MemoryRequirement::HostVisible);
2226 const VkMemoryBarrier tfMemoryBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT, VK_ACCESS_HOST_READ_BIT);
2227 const std::vector<VkDeviceSize> tfBufBindingSizes = generateSizesList(m_parameters.bufferSize, m_parameters.partCount);
2228 const std::vector<VkDeviceSize> tfBufBindingOffsets = generateOffsetsList(tfBufBindingSizes);
2229 const std::vector<float> tfBufExpectedValues = { 0.5f, 0.5f + float(m_parameters.streamId) };
2230 const deUint32 maxBufferSizeBytes = static_cast<deUint32>(*std::max_element(tfBufBindingSizes.begin(), tfBufBindingSizes.end()));
2231 const deUint32 bytesPerVertex = static_cast<deUint32>(4 * sizeof(float));
2232 const deUint32 numVerticesInBuffer = maxBufferSizeBytes / bytesPerVertex;
2233 const deUint32 numDrawVertices = numVerticesInBuffer / 2;
2234
2235 const deUint32 queryIndex = 0u;
2236 const deUint32 queryCountersNumber = 2u;
2237 const deUint32 queryStride = sizeof(TransformFeedbackQuery);
2238 const deUint32 queryDataSize = queryCountersNumber * queryStride;
2239 const VkQueryPoolCreateInfo queryPoolCreateInfo = makeQueryPoolCreateInfo(queryCountersNumber);
2240 const Unique<VkQueryPool> queryPool (createQueryPool(vk, device, &queryPoolCreateInfo));
2241 const deUint32 queryInvalidCounterValue = 999999u;
2242 std::vector<TransformFeedbackQuery> queryResultData (queryCountersNumber, TransformFeedbackQuery{ queryInvalidCounterValue, queryInvalidCounterValue });
2243 const std::vector<TransformFeedbackQuery> queryExpectedData ({ TransformFeedbackQuery{ numVerticesInBuffer, 3 * numDrawVertices }, TransformFeedbackQuery{ numDrawVertices, numDrawVertices } });
2244
2245 const VkBufferCreateInfo queryBufferCreateInfo = makeBufferCreateInfo(queryDataSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT, queueFamilyIndices);
2246 const Move<VkBuffer> queryPoolResultsBuffer = createBuffer(vk, device, &queryBufferCreateInfo);
2247 const MovePtr<Allocation> queryPoolResultsBufferAlloc = allocator.allocate(getBufferMemoryRequirements(vk, device, *queryPoolResultsBuffer), MemoryRequirement::HostVisible);
2248
2249 DE_ASSERT(queryCountersNumber == queryExpectedData.size());
2250
2251 VK_CHECK(vk.bindBufferMemory(device, *queryPoolResultsBuffer, queryPoolResultsBufferAlloc->getMemory(), queryPoolResultsBufferAlloc->getOffset()));
2252
2253 VK_CHECK(vk.bindBufferMemory(device, *tfBuf, tfBufAllocation->getMemory(), tfBufAllocation->getOffset()));
2254
2255 beginCommandBuffer(vk, *cmdBuffer);
2256 {
2257 vk.cmdResetQueryPool(*cmdBuffer, *queryPool, queryIndex, queryCountersNumber);
2258
2259 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
2260 {
2261 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
2262
2263 vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0u, m_parameters.partCount, &tfBufArray[0], &tfBufBindingOffsets[0], &tfBufBindingSizes[0]);
2264
2265 vk.cmdBeginQueryIndexedEXT(*cmdBuffer, *queryPool, queryIndex + 0, 0u, 0u);
2266 vk.cmdBeginQueryIndexedEXT(*cmdBuffer, *queryPool, queryIndex + 1, 0u, m_parameters.streamId);
2267 {
2268 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
2269 {
2270 vk.cmdDraw(*cmdBuffer, numDrawVertices, 1u, 0u, 0u);
2271 }
2272 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
2273 }
2274 vk.cmdEndQueryIndexedEXT(*cmdBuffer, *queryPool, queryIndex + 1, m_parameters.streamId);
2275 vk.cmdEndQueryIndexedEXT(*cmdBuffer, *queryPool, queryIndex + 0, 0);
2276 }
2277 endRenderPass(vk, *cmdBuffer);
2278
2279 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &tfMemoryBarrier, 0u, DE_NULL, 0u, DE_NULL);
2280 }
2281 endCommandBuffer(vk, *cmdBuffer);
2282 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
2283
2284 vk.getQueryPoolResults(device, *queryPool, queryIndex, queryCountersNumber, queryDataSize, queryResultData.data(), queryStride, (vk::VK_QUERY_RESULT_WAIT_BIT));
2285
2286 DE_ASSERT(queryResultData.size() == queryCountersNumber && queryExpectedData.size() == queryCountersNumber);
2287 DE_ASSERT(queryCountersNumber > 0);
2288
2289 for (size_t counterNdx = 0; counterNdx < queryCountersNumber; ++counterNdx)
2290 {
2291 const TransformFeedbackQuery& result = queryResultData[counterNdx];
2292 const TransformFeedbackQuery& expected = queryExpectedData[counterNdx];
2293
2294 DE_ASSERT(expected.written != queryInvalidCounterValue);
2295 DE_ASSERT(expected.attempts != queryInvalidCounterValue);
2296
2297 if (result.written == queryInvalidCounterValue || result.attempts == queryInvalidCounterValue)
2298 return tcu::TestStatus::fail("Query counters read failed");
2299
2300 if (result.written != expected.written)
2301 {
2302 const std::string comment = "At counter " + de::toString(counterNdx) + " vertices written " + de::toString(result.written) + ", while expected " + de::toString(expected.written);
2303
2304 return tcu::TestStatus::fail(comment.c_str());
2305 }
2306
2307
2308 if (result.attempts != expected.attempts)
2309 {
2310 const std::string comment = "At counter " + de::toString(counterNdx) + " attempts committed " + de::toString(result.attempts) + ", while expected " + de::toString(expected.attempts);
2311
2312 return tcu::TestStatus::fail(comment.c_str());
2313 }
2314
2315 if (counterNdx == 0 && !m_parameters.omitShaderWrite)
2316 verifyTransformFeedbackBuffer(tfBufAllocation, bytesPerVertex * expected.written, static_cast<deUint32>(tfBufBindingOffsets[counterNdx]), tfBufExpectedValues[counterNdx]);
2317 }
2318
2319 return tcu::TestStatus::pass("Pass");
2320 }
2321
2322
2323 class TransformFeedbackLinesOrTrianglesTestInstance : public TransformFeedbackTestInstance
2324 {
2325 public:
2326 TransformFeedbackLinesOrTrianglesTestInstance (Context& context, const TestParameters& parameters);
2327
2328 protected:
2329 std::vector<VkDeviceSize> generateSizesList (const size_t bufBytes, const size_t chunkCount);
2330 void verifyTransformFeedbackBufferLines (const MovePtr<Allocation>& bufAlloc,
2331 const deUint32 bufBytes,
2332 const std::vector<deUint32>& primitives,
2333 const deUint32 invocationCount,
2334 const deUint32 partCount);
2335 void verifyTransformFeedbackBufferTriangles (const MovePtr<Allocation>& bufAlloc,
2336 const deUint32 bufBytes,
2337 const std::vector<deUint32>& primitives,
2338 const deUint32 invocationCount,
2339 const deUint32 partCount);
2340 tcu::TestStatus iterate (void);
2341 };
2342
TransformFeedbackLinesOrTrianglesTestInstance(Context & context,const TestParameters & parameters)2343 TransformFeedbackLinesOrTrianglesTestInstance::TransformFeedbackLinesOrTrianglesTestInstance (Context& context, const TestParameters& parameters)
2344 : TransformFeedbackTestInstance (context, parameters)
2345 {
2346 const InstanceInterface& vki = m_context.getInstanceInterface();
2347 const VkPhysicalDevice physDevice = m_context.getPhysicalDevice();
2348 const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(vki, physDevice);
2349 const VkPhysicalDeviceTransformFeedbackFeaturesEXT& transformFeedbackFeatures = m_context.getTransformFeedbackFeaturesEXT();
2350 const deUint32 streamsSupported = m_transformFeedbackProperties.maxTransformFeedbackStreams;
2351 const deUint32 streamsRequired = m_parameters.streamId + 1;
2352 const deUint32 tfBuffersSupported = m_transformFeedbackProperties.maxTransformFeedbackBuffers;
2353 const deUint32 tfBuffersRequired = m_parameters.partCount;
2354
2355 DE_ASSERT(m_parameters.partCount == 2u);
2356
2357 if (m_transformFeedbackProperties.transformFeedbackStreamsLinesTriangles == DE_FALSE)
2358 TCU_THROW(NotSupportedError, "transformFeedbackStreamsLinesTriangles required");
2359
2360 if (!features.geometryShader)
2361 TCU_THROW(NotSupportedError, "Missing feature: geometryShader");
2362
2363 if (transformFeedbackFeatures.geometryStreams == DE_FALSE)
2364 TCU_THROW(NotSupportedError, "geometryStreams feature is not supported");
2365
2366 if (streamsSupported < streamsRequired)
2367 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackStreams=" + de::toString(streamsSupported) + ", while test requires " + de::toString(streamsRequired)).c_str());
2368
2369 if (tfBuffersSupported < tfBuffersRequired)
2370 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBuffers=" + de::toString(tfBuffersSupported) + ", while test requires " + de::toString(tfBuffersRequired)).c_str());
2371 }
2372
generateSizesList(const size_t bufBytes,const size_t chunkCount)2373 std::vector<VkDeviceSize> TransformFeedbackLinesOrTrianglesTestInstance::generateSizesList (const size_t bufBytes, const size_t chunkCount)
2374 {
2375 const VkDeviceSize chunkSize = bufBytes / chunkCount;
2376 std::vector<VkDeviceSize> result (chunkCount, chunkSize);
2377
2378 DE_ASSERT(chunkSize * chunkCount == bufBytes);
2379 DE_ASSERT(bufBytes <= MINIMUM_TF_BUFFER_SIZE);
2380 DE_ASSERT(bufBytes % sizeof(deUint32) == 0);
2381 DE_ASSERT(chunkCount > 0);
2382 DE_ASSERT(result.size() == chunkCount);
2383
2384 return result;
2385 }
2386
verifyTransformFeedbackBufferLines(const MovePtr<Allocation> & bufAlloc,const deUint32 bufBytes,const std::vector<deUint32> & primitives,const deUint32 invocationCount,const deUint32 partCount)2387 void TransformFeedbackLinesOrTrianglesTestInstance::verifyTransformFeedbackBufferLines (const MovePtr<Allocation>& bufAlloc,
2388 const deUint32 bufBytes,
2389 const std::vector<deUint32>& primitives,
2390 const deUint32 invocationCount,
2391 const deUint32 partCount)
2392 {
2393 const DeviceInterface& vk = m_context.getDeviceInterface();
2394 const VkDevice device = m_context.getDevice();
2395 const tcu::Vec4* tfData = getInvalidatedHostPtr<tcu::Vec4>(vk, device, *bufAlloc);
2396 const deUint32 stripeCount = static_cast<deUint32>(primitives.size());
2397 const deUint32 vertexCount = 2 * destripedLineCount(primitives) * invocationCount * partCount;
2398 const deUint32 numPoints = static_cast<deUint32>(bufBytes / sizeof(tcu::Vec4));
2399 deUint32 n = 0;
2400 std::vector<tcu::Vec4> reference;
2401
2402 reference.reserve(vertexCount);
2403
2404 for (deUint32 partNdx = 0; partNdx < partCount; ++partNdx)
2405 {
2406 for (deUint32 invocationNdx = 0; invocationNdx < invocationCount; ++invocationNdx)
2407 {
2408 for (deUint32 stripeNdx = 0; stripeNdx < stripeCount; ++stripeNdx)
2409 {
2410 const deUint32 stripeVertexCount = primitives[stripeNdx];
2411
2412 for (deUint32 vertexNdx = 0; vertexNdx < stripeVertexCount; ++vertexNdx)
2413 {
2414 const bool firstOrLast = vertexNdx == 0 || vertexNdx == stripeVertexCount - 1;
2415 const tcu::Vec4 v (float(n++), float(invocationNdx), float(stripeNdx), float(vertexNdx));
2416
2417 reference.push_back(v);
2418
2419 if (!firstOrLast)
2420 reference.push_back(v);
2421 }
2422 }
2423 }
2424 }
2425
2426 DE_ASSERT(reference.size() == numPoints);
2427
2428 for (deUint32 i = 0; i < numPoints; ++i)
2429 {
2430 if (tfData[i] != reference[i])
2431 {
2432 tcu::TestLog& log = m_context.getTestContext().getLog();
2433 std::stringstream err;
2434 std::stringstream css;
2435
2436 err << "Failed at item " << i
2437 << " received:" << tfData[i]
2438 << " expected:" << reference[i];
2439
2440 for (deUint32 j = 0; j < numPoints; ++j)
2441 css << j << ": " << tfData[j] << (i == j ? " <= fail" : "") <<std::endl;
2442
2443 log << tcu::TestLog::Message << css.str() << tcu::TestLog::EndMessage;
2444
2445 TCU_FAIL(err.str());
2446 }
2447 }
2448 }
2449
verifyTransformFeedbackBufferTriangles(const MovePtr<Allocation> & bufAlloc,const deUint32 bufBytes,const std::vector<deUint32> & primitives,const deUint32 invocationCount,const deUint32 partCount)2450 void TransformFeedbackLinesOrTrianglesTestInstance::verifyTransformFeedbackBufferTriangles (const MovePtr<Allocation>& bufAlloc,
2451 const deUint32 bufBytes,
2452 const std::vector<deUint32>& primitives,
2453 const deUint32 invocationCount,
2454 const deUint32 partCount)
2455 {
2456 const DeviceInterface& vk = m_context.getDeviceInterface();
2457 const VkDevice device = m_context.getDevice();
2458 const tcu::Vec4* tfData = getInvalidatedHostPtr<tcu::Vec4>(vk, device, *bufAlloc);
2459 const deUint32 stripeCount = static_cast<deUint32>(primitives.size());
2460 const deUint32 vertexCount = 3 * destripedLineCount(primitives) * invocationCount * partCount;
2461 const deUint32 numPoints = static_cast<deUint32>(bufBytes / sizeof(tcu::Vec4));
2462 deUint32 n = 0;
2463 std::vector<tcu::Vec4> reference;
2464
2465 reference.reserve(vertexCount);
2466
2467 for (deUint32 partNdx = 0; partNdx < partCount; ++partNdx)
2468 {
2469 for (deUint32 invocationNdx = 0; invocationNdx < invocationCount; ++invocationNdx)
2470 {
2471 for (deUint32 stripeNdx = 0; stripeNdx < stripeCount; ++stripeNdx)
2472 {
2473 const deUint32 stripeVertexCount = primitives[stripeNdx];
2474 const deUint32 trianglesCount = stripeVertexCount - 2;
2475 std::vector<tcu::Vec4> stripe (stripeVertexCount);
2476
2477 for (deUint32 vertexNdx = 0; vertexNdx < stripeVertexCount; ++vertexNdx)
2478 stripe[vertexNdx] = tcu::Vec4(float(n++), float(invocationNdx), float(stripeNdx), float(vertexNdx));
2479
2480 for (deUint32 triangleNdx = 0; triangleNdx < trianglesCount; ++triangleNdx)
2481 {
2482 if (triangleNdx % 2 == 0)
2483 {
2484 reference.push_back(stripe[triangleNdx + 0]);
2485 reference.push_back(stripe[triangleNdx + 1]);
2486 reference.push_back(stripe[triangleNdx + 2]);
2487 }
2488 else
2489 {
2490 reference.push_back(stripe[triangleNdx + 0]);
2491 reference.push_back(stripe[triangleNdx + 2]);
2492 reference.push_back(stripe[triangleNdx + 1]);
2493 }
2494 }
2495 }
2496 }
2497 }
2498
2499 DE_ASSERT(reference.size() == numPoints);
2500
2501 for (deUint32 i = 0; i < numPoints; ++i)
2502 {
2503 if (tfData[i] != reference[i])
2504 {
2505 tcu::TestLog& log = m_context.getTestContext().getLog();
2506 std::stringstream err;
2507 std::stringstream css;
2508
2509 err << "Failed at item " << i
2510 << " received:" << tfData[i]
2511 << " expected:" << reference[i];
2512
2513 for (deUint32 j = 0; j < numPoints; ++j)
2514 css << j << ": " << tfData[j] << (i == j ? " <= fail" : "") <<std::endl;
2515
2516 log << tcu::TestLog::Message << css.str() << tcu::TestLog::EndMessage;
2517
2518 TCU_FAIL(err.str());
2519 }
2520 }
2521 }
2522
iterate(void)2523 tcu::TestStatus TransformFeedbackLinesOrTrianglesTestInstance::iterate (void)
2524 {
2525 const DeviceInterface& vk = m_context.getDeviceInterface();
2526 const VkDevice device = m_context.getDevice();
2527 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
2528 const VkQueue queue = m_context.getUniversalQueue();
2529 Allocator& allocator = m_context.getDefaultAllocator();
2530
2531 const Unique<VkRenderPass> renderPass (makeRenderPass (vk, device, VK_FORMAT_UNDEFINED));
2532
2533 const Unique<VkShaderModule> vertexModule (createShaderModule (vk, device, m_context.getBinaryCollection().get("vert"), 0u));
2534 const Unique<VkShaderModule> geomModule (createShaderModule (vk, device, m_context.getBinaryCollection().get("geom"), 0u));
2535
2536 const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, 0u, DE_NULL, m_imageExtent2D.width, m_imageExtent2D.height));
2537 const Unique<VkPipelineLayout> pipelineLayout (TransformFeedback::makePipelineLayout (vk, device));
2538 const Unique<VkPipeline> pipeline (makeGraphicsPipeline (vk, device, *pipelineLayout, *renderPass, *vertexModule, DE_NULL, DE_NULL, *geomModule, DE_NULL, m_imageExtent2D, 0u, &m_parameters.streamId));
2539 const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
2540 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
2541
2542 const deUint32 tfBufferSize = m_parameters.bufferSize;
2543 const VkBufferCreateInfo tfBufCreateInfo = makeBufferCreateInfo(tfBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT);
2544 const Move<VkBuffer> tfBuf = createBuffer(vk, device, &tfBufCreateInfo);
2545 const std::vector<VkBuffer> tfBufArray = std::vector<VkBuffer>(m_parameters.partCount, *tfBuf);
2546 const MovePtr<Allocation> tfBufAllocation = allocator.allocate(getBufferMemoryRequirements(vk, device, *tfBuf), MemoryRequirement::HostVisible);
2547 const VkMemoryBarrier tfMemoryBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT, VK_ACCESS_HOST_READ_BIT);
2548 const std::vector<VkDeviceSize> tfBufBindingSizes = generateSizesList(tfBufferSize, m_parameters.partCount);
2549 const std::vector<VkDeviceSize> tfBufBindingOffsets = generateOffsetsList(tfBufBindingSizes);
2550
2551 VK_CHECK(vk.bindBufferMemory(device, *tfBuf, tfBufAllocation->getMemory(), tfBufAllocation->getOffset()));
2552
2553 beginCommandBuffer(vk, *cmdBuffer);
2554 {
2555 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
2556 {
2557 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
2558
2559 vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0u, m_parameters.partCount, &tfBufArray[0], &tfBufBindingOffsets[0], &tfBufBindingSizes[0]);
2560
2561 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
2562 {
2563 vk.cmdDraw(*cmdBuffer, INVOCATION_COUNT, 1u, 0u, 0u);
2564 }
2565 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
2566 }
2567 endRenderPass(vk, *cmdBuffer);
2568
2569 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &tfMemoryBarrier, 0u, DE_NULL, 0u, DE_NULL);
2570 }
2571 endCommandBuffer(vk, *cmdBuffer);
2572 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
2573
2574 switch (m_parameters.primTopology)
2575 {
2576 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP: verifyTransformFeedbackBufferLines(tfBufAllocation, tfBufferSize, LINES_LIST, INVOCATION_COUNT, m_parameters.partCount); break;
2577 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP: verifyTransformFeedbackBufferTriangles(tfBufAllocation, tfBufferSize, TRIANGLES_LIST, INVOCATION_COUNT, m_parameters.partCount); break;
2578 default: TCU_THROW(InternalError, "Unknown topology");
2579 }
2580
2581 return tcu::TestStatus::pass("Pass");
2582 }
2583
2584 class TransformFeedbackTestCase : public vkt::TestCase
2585 {
2586 public:
2587 TransformFeedbackTestCase (tcu::TestContext &context, const char *name, const char *description, const TestParameters& parameters);
2588
2589 protected:
2590 vkt::TestInstance* createInstance (vkt::Context& context) const;
2591 void initPrograms (SourceCollections& programCollection) const;
2592 virtual void checkSupport (Context& context) const;
2593
2594 TestParameters m_parameters;
2595 };
2596
TransformFeedbackTestCase(tcu::TestContext & context,const char * name,const char * description,const TestParameters & parameters)2597 TransformFeedbackTestCase::TransformFeedbackTestCase (tcu::TestContext &context, const char *name, const char *description, const TestParameters& parameters)
2598 : TestCase (context, name, description)
2599 , m_parameters (parameters)
2600 {
2601 }
2602
vectorToString(const std::vector<deUint32> & v)2603 std::string vectorToString (const std::vector<deUint32>& v)
2604 {
2605 std::ostringstream css;
2606
2607 DE_ASSERT(!v.empty());
2608
2609 for (auto x: v)
2610 css << x << ",";
2611
2612 return css.str().substr(0, css.str().size() - 1);
2613 }
2614
createInstance(vkt::Context & context) const2615 vkt::TestInstance* TransformFeedbackTestCase::createInstance (vkt::Context& context) const
2616 {
2617 if (m_parameters.testType == TEST_TYPE_BASIC)
2618 return new TransformFeedbackBasicTestInstance(context, m_parameters);
2619
2620 if (m_parameters.testType == TEST_TYPE_RESUME)
2621 return new TransformFeedbackResumeTestInstance(context, m_parameters);
2622
2623 if (m_parameters.testType == TEST_TYPE_XFB_POINTSIZE)
2624 return new TransformFeedbackBuiltinTestInstance(context, m_parameters);
2625
2626 if (m_parameters.testType == TEST_TYPE_XFB_CLIPDISTANCE)
2627 return new TransformFeedbackBuiltinTestInstance(context, m_parameters);
2628
2629 if (m_parameters.testType == TEST_TYPE_XFB_CULLDISTANCE)
2630 return new TransformFeedbackBuiltinTestInstance(context, m_parameters);
2631
2632 if (m_parameters.testType == TEST_TYPE_XFB_CLIP_AND_CULL)
2633 return new TransformFeedbackBuiltinTestInstance(context, m_parameters);
2634
2635 if (m_parameters.testType == TEST_TYPE_WINDING)
2636 return new TransformFeedbackWindingOrderTestInstance(context, m_parameters);
2637
2638 if (m_parameters.testType == TEST_TYPE_STREAMS)
2639 return new TransformFeedbackStreamsTestInstance(context, m_parameters);
2640
2641 if (m_parameters.testType == TEST_TYPE_STREAMS_POINTSIZE)
2642 return new TransformFeedbackStreamsTestInstance(context, m_parameters);
2643
2644 if (m_parameters.testType == TEST_TYPE_STREAMS_CLIPDISTANCE)
2645 return new TransformFeedbackStreamsTestInstance(context, m_parameters);
2646
2647 if (m_parameters.testType == TEST_TYPE_STREAMS_CULLDISTANCE)
2648 return new TransformFeedbackStreamsTestInstance(context, m_parameters);
2649
2650 if (m_parameters.testType == TEST_TYPE_MULTISTREAMS)
2651 return new TransformFeedbackMultistreamTestInstance(context, m_parameters);
2652
2653 if (m_parameters.testType == TEST_TYPE_DRAW_INDIRECT)
2654 return new TransformFeedbackIndirectDrawTestInstance(context, m_parameters);
2655
2656 if (m_parameters.testType == TEST_TYPE_BACKWARD_DEPENDENCY)
2657 return new TransformFeedbackBackwardDependencyTestInstance(context, m_parameters);
2658
2659 if (m_parameters.testType == TEST_TYPE_QUERY_GET ||
2660 m_parameters.testType == TEST_TYPE_QUERY_COPY ||
2661 m_parameters.testType == TEST_TYPE_QUERY_COPY_STRIDE_ZERO ||
2662 m_parameters.testType == TEST_TYPE_QUERY_RESET)
2663 return new TransformFeedbackQueryTestInstance(context, m_parameters);
2664
2665 if (m_parameters.testType == TEST_TYPE_MULTIQUERY)
2666 return new TransformFeedbackMultiQueryTestInstance(context, m_parameters);
2667
2668 if (m_parameters.testType == TEST_TYPE_DEPTH_CLIP_CONTROL_VERTEX ||
2669 m_parameters.testType == TEST_TYPE_DEPTH_CLIP_CONTROL_GEOMETRY ||
2670 m_parameters.testType == TEST_TYPE_DEPTH_CLIP_CONTROL_TESE)
2671 return new TransformFeedbackDepthClipControlTestInstance(context, m_parameters);
2672
2673 if (m_parameters.testType == TEST_TYPE_LINES_TRIANGLES)
2674 return new TransformFeedbackLinesOrTrianglesTestInstance(context, m_parameters);
2675
2676 TCU_THROW(InternalError, "Specified test type not found");
2677 }
2678
checkSupport(Context & context) const2679 void TransformFeedbackTestCase::checkSupport (Context& context) const
2680 {
2681 context.requireDeviceFunctionality("VK_EXT_transform_feedback");
2682
2683 if (context.getTransformFeedbackFeaturesEXT().transformFeedback == VK_FALSE)
2684 TCU_THROW(NotSupportedError, "transformFeedback feature is not supported");
2685
2686 // transformFeedbackRasterizationStreamSelect is required when vertex streams other than zero are rasterized
2687 if (m_parameters.requireRastStreamSelect && (context.getTransformFeedbackPropertiesEXT().transformFeedbackRasterizationStreamSelect == VK_FALSE) && (m_parameters.streamId > 0))
2688 TCU_THROW(NotSupportedError, "transformFeedbackRasterizationStreamSelect property is not supported");
2689 }
2690
initPrograms(SourceCollections & programCollection) const2691 void TransformFeedbackTestCase::initPrograms (SourceCollections& programCollection) const
2692 {
2693 const bool vertexShaderOnly = m_parameters.testType == TEST_TYPE_BASIC
2694 || m_parameters.testType == TEST_TYPE_RESUME
2695 || m_parameters.testType == TEST_TYPE_BACKWARD_DEPENDENCY
2696 || (m_parameters.testType == TEST_TYPE_WINDING && m_parameters.primTopology != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST);
2697 const bool requiresFullPipeline = m_parameters.testType == TEST_TYPE_STREAMS
2698 || m_parameters.testType == TEST_TYPE_STREAMS_POINTSIZE
2699 || m_parameters.testType == TEST_TYPE_STREAMS_CULLDISTANCE
2700 || m_parameters.testType == TEST_TYPE_STREAMS_CLIPDISTANCE
2701 || (m_parameters.testType == TEST_TYPE_WINDING && m_parameters.primTopology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST);
2702 const bool xfbBuiltinPipeline = m_parameters.testType == TEST_TYPE_XFB_POINTSIZE
2703 || m_parameters.testType == TEST_TYPE_XFB_CLIPDISTANCE
2704 || m_parameters.testType == TEST_TYPE_XFB_CULLDISTANCE
2705 || m_parameters.testType == TEST_TYPE_XFB_CLIP_AND_CULL;
2706
2707 if (m_parameters.testType == TEST_TYPE_DEPTH_CLIP_CONTROL_VERTEX)
2708 {
2709 // Vertex shader
2710 {
2711 std::ostringstream src;
2712 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2713 << "\n"
2714 << "layout(xfb_buffer = 0, xfb_offset = 0) out gl_PerVertex\n"
2715 << "{\n"
2716 << " vec4 gl_Position;\n"
2717 << "};\n"
2718 << "\n"
2719 << "void main(void)\n"
2720 << "{\n"
2721 << " gl_Position = vec4(1.0, 1.0, float(gl_VertexIndex) / 3.0 - 1.0, 1.0);\n"
2722 << "}\n";
2723
2724 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
2725 }
2726
2727 return;
2728 }
2729
2730 if (m_parameters.testType == TEST_TYPE_DEPTH_CLIP_CONTROL_GEOMETRY)
2731 {
2732 // Vertex shader
2733 {
2734 std::ostringstream src;
2735 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2736 << "\n"
2737 << "void main(void)\n"
2738 << "{\n"
2739 << " gl_Position = vec4(1.0, 1.0, float(gl_VertexIndex) / 3.0 - 1.0, 1.0);\n"
2740 << "}\n";
2741
2742 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
2743 }
2744
2745 // Geometry shader
2746 {
2747 std::ostringstream src;
2748 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2749 << "\n"
2750 << "layout(points) in;\n"
2751 << "layout(points, max_vertices = 1) out;\n"
2752 << "layout(xfb_buffer = 0, xfb_offset = 0) out gl_PerVertex\n"
2753 << "{\n"
2754 << " vec4 gl_Position;\n"
2755 << "};\n"
2756 << "\n"
2757 << "void main(void)\n"
2758 << "{\n"
2759 << " gl_Position = gl_in[0].gl_Position;\n"
2760 << " EmitVertex();\n"
2761 << " EndPrimitive();\n"
2762 << "}\n";
2763
2764 programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
2765 }
2766
2767 return;
2768 }
2769
2770 if (m_parameters.testType == TEST_TYPE_DEPTH_CLIP_CONTROL_TESE)
2771 {
2772 // Vertex shader
2773 {
2774 std::ostringstream src;
2775 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2776 << "\n"
2777 << "void main(void)\n"
2778 << "{\n"
2779 << " gl_Position = vec4(1.0, 1.0, float(gl_VertexIndex) / 3.0 - 1.0, 1.0);\n"
2780 << "}\n";
2781
2782 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
2783 }
2784
2785 // Tesselation control shader
2786 {
2787 std::ostringstream src;
2788 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2789 << "layout(vertices = 3) out;\n"
2790 << "void main (void)\n"
2791 << "{\n"
2792 << " gl_TessLevelInner[0] = 0.0;\n"
2793 << " gl_TessLevelOuter[0] = 1.0;\n"
2794 << " gl_TessLevelOuter[1] = 1.0;\n"
2795 << " gl_TessLevelOuter[2] = 1.0;\n"
2796 << " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
2797 << "}\n";
2798 programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str());
2799 }
2800
2801 // Tessellation evaluation shader
2802 {
2803 std::ostringstream src;
2804 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2805 << "layout(triangles, ccw) in;\n"
2806 << "layout(xfb_buffer = 0, xfb_offset = 0) out gl_PerVertex\n"
2807 << "{\n"
2808 << " vec4 gl_Position;\n"
2809 << "};\n"
2810 << "\n"
2811 << "void main (void)\n"
2812 << "{\n"
2813 << " vec4 p0 = gl_TessCoord.x * gl_in[0].gl_Position;\n"
2814 << " vec4 p1 = gl_TessCoord.y * gl_in[1].gl_Position;\n"
2815 << " vec4 p2 = gl_TessCoord.z * gl_in[2].gl_Position;\n"
2816 << " gl_Position = p0 + p1 + p2;\n"
2817 << "}\n";
2818 programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
2819 }
2820
2821 return;
2822 }
2823
2824 if (vertexShaderOnly)
2825 {
2826 // Vertex shader
2827 {
2828 std::ostringstream src;
2829 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2830 << "\n"
2831 << "layout(push_constant) uniform pushConstants\n"
2832 << "{\n"
2833 << " uint start;\n"
2834 << "} uInput;\n"
2835 << "\n"
2836 << "layout(xfb_buffer = 0, xfb_offset = 0, xfb_stride = 4, location = 0) out uint idx_out;\n"
2837 << "\n"
2838 << "void main(void)\n"
2839 << "{\n"
2840 << " idx_out = uInput.start + gl_VertexIndex;\n"
2841 << "}\n";
2842
2843 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
2844 }
2845
2846 return;
2847 }
2848
2849 if (m_parameters.primTopology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST)
2850 {
2851 // Vertex shader
2852 {
2853 std::ostringstream src;
2854 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2855 << "layout(push_constant) uniform pushConstants\n"
2856 << "{\n"
2857 << " uint start;\n"
2858 << "} uInput;\n"
2859 << "void main(void)\n"
2860 << "{\n"
2861 << "}\n";
2862 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
2863 }
2864
2865 // Tesselation control shader
2866 {
2867 std::ostringstream src;
2868 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2869 << "layout(vertices = 3) out;\n"
2870 << "void main (void)\n"
2871 << "{\n"
2872 << " gl_TessLevelInner[0] = 2.0;\n" // generate three triangles out of each patch
2873 << " gl_TessLevelOuter[0] = 1.0;\n"
2874 << " gl_TessLevelOuter[1] = 1.0;\n"
2875 << " gl_TessLevelOuter[2] = 1.0;\n"
2876 << "}\n";
2877 programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str());
2878 }
2879
2880 // Tessellation evaluation shader
2881 {
2882 std::ostringstream src;
2883 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2884 << "layout(triangles, ccw) in;\n"
2885 << "layout(xfb_buffer = 0, xfb_offset = 0, xfb_stride = 4, location = 0) out uint idx_out;\n"
2886 << "\n"
2887 << "void main (void)\n"
2888 << "{\n"
2889 << " idx_out = gl_PrimitiveID;\n" // all vertex generated from patch will have its id
2890 << "}\n";
2891 programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
2892 }
2893
2894 return;
2895 }
2896
2897 if (xfbBuiltinPipeline)
2898 {
2899 const std::string outputBuiltIn = (m_parameters.testType == TEST_TYPE_XFB_POINTSIZE) ? "float gl_PointSize;\n"
2900 : (m_parameters.testType == TEST_TYPE_XFB_CLIPDISTANCE) ? "float gl_ClipDistance[8];\n"
2901 : (m_parameters.testType == TEST_TYPE_XFB_CULLDISTANCE) ? "float gl_CullDistance[8];\n"
2902 : (m_parameters.testType == TEST_TYPE_XFB_CLIP_AND_CULL) ? "float gl_CullDistance[5];\nfloat gl_ClipDistance[1];\n"
2903 : "";
2904 const std::string operationBuiltIn = (m_parameters.testType == TEST_TYPE_XFB_POINTSIZE) ? "gl_PointSize = float(gl_VertexIndex) / 32768.0f;"
2905 : (m_parameters.testType == TEST_TYPE_XFB_CLIPDISTANCE) ? "for (int i=0; i<8; i++) gl_ClipDistance[i] = float(8 * gl_VertexIndex + i) / 32768.0f;"
2906 : (m_parameters.testType == TEST_TYPE_XFB_CULLDISTANCE) ? "for (int i=0; i<8; i++) gl_CullDistance[i] = float(8 * gl_VertexIndex + i) / 32768.0f;"
2907 : (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"
2908 "gl_ClipDistance[0] = float(6 * gl_VertexIndex + 5) / 32768.0f;\n"
2909 : "";
2910
2911 // Vertex shader
2912 {
2913 std::ostringstream src;
2914 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2915 << "\n"
2916 << "layout(xfb_buffer = " << m_parameters.partCount - 1 << ", xfb_offset = 0) out gl_PerVertex\n"
2917 << "{\n"
2918 << outputBuiltIn
2919 << "};\n"
2920 << "\n"
2921 << "void main(void)\n"
2922 << "{\n"
2923 << operationBuiltIn
2924 << "}\n";
2925
2926 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
2927 }
2928
2929 return;
2930 }
2931
2932 if (m_parameters.testType == TEST_TYPE_MULTISTREAMS)
2933 {
2934 // vertex shader
2935 {
2936 std::ostringstream src;
2937 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2938 << "\n"
2939 << "void main(void)\n"
2940 << "{\n"
2941 << "}\n";
2942
2943 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
2944 }
2945
2946 // geometry shader
2947 {
2948 const deUint32 s = m_parameters.streamId;
2949 std::ostringstream src;
2950
2951 DE_ASSERT(s != 0);
2952
2953 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2954 << "\n"
2955 << "layout(points) in;\n"
2956 << "\n"
2957 << "layout(points, max_vertices = 32) out;\n"
2958 << "layout(stream = " << 0 << ", xfb_buffer = 0, xfb_offset = 0, xfb_stride = 16, location = 0) out vec4 out0;\n"
2959 << "layout(stream = " << s << ", xfb_buffer = 1, xfb_offset = 0, xfb_stride = 16, location = 1) out vec4 out1;\n"
2960 << "\n"
2961 << "const int counts[] = int[](1, 1, 2, 4, 8);\n"
2962 << "\n"
2963 << "void main(void)\n"
2964 << "{\n"
2965 << " int c0 = 0;\n"
2966 << " int c1 = 0;\n"
2967 << "\n"
2968 << " // Start 1st buffer from point where 0th buffer ended\n"
2969 << " for (int i = 0; i < counts.length(); i++)\n"
2970 << " c1 = c1 + 4 * counts[i];\n"
2971 << "\n"
2972 << " for (int i = 0; i < counts.length(); i++)\n"
2973 << " {\n"
2974 << " const int n0 = counts[i];\n"
2975 << " const int n1 = counts[counts.length() - 1 - i];\n"
2976 << "\n"
2977 << " for (int j = 0; j < n0; j++)\n"
2978 << " {\n"
2979 << " out0 = vec4(ivec4(c0, c0 + 1, c0 + 2, c0 + 3));\n"
2980 << " c0 = c0 + 4;\n"
2981 << " EmitStreamVertex(0);\n"
2982 << " EndStreamPrimitive(0);\n"
2983 << " }\n"
2984 << "\n"
2985 << " for (int j = 0; j < n1; j++)\n"
2986 << " {\n"
2987 << " out1 = vec4(ivec4(c1, c1 + 1, c1 + 2, c1 + 3));\n"
2988 << " c1 = c1 + 4;\n"
2989 << " EmitStreamVertex(" << s << ");\n"
2990 << " EndStreamPrimitive(" << s << ");\n"
2991 << " }\n"
2992 << " }\n"
2993 << "}\n";
2994
2995 programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
2996 }
2997
2998 return;
2999 }
3000
3001 if (requiresFullPipeline)
3002 {
3003 // vertex shader
3004 {
3005 std::ostringstream src;
3006 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
3007 << "\n"
3008 << "void main(void)\n"
3009 << "{\n"
3010 << "}\n";
3011
3012 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
3013 }
3014
3015 // geometry shader
3016 {
3017 const deUint32 s = m_parameters.streamId;
3018 const bool requirePoints = (m_parameters.testType == TEST_TYPE_STREAMS_POINTSIZE || m_parameters.testType == TEST_TYPE_MULTISTREAMS);
3019 const std::string outputPrimitiveType = requirePoints ? "points" : "triangle_strip";
3020 const std::string outputBuiltIn = (m_parameters.testType == TEST_TYPE_STREAMS_POINTSIZE) ? " float gl_PointSize;\n"
3021 : (m_parameters.testType == TEST_TYPE_STREAMS_CLIPDISTANCE) ? " float gl_ClipDistance[];\n"
3022 : (m_parameters.testType == TEST_TYPE_STREAMS_CULLDISTANCE) ? " float gl_CullDistance[];\n"
3023 : "";
3024 std::ostringstream src;
3025
3026 DE_ASSERT(s != 0);
3027
3028 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
3029 << "\n"
3030 << "layout(points) in;\n"
3031 << "layout(" << outputPrimitiveType << ", max_vertices = 16) out;\n"
3032 << "layout(stream = " << s << ") out;\n"
3033 << "layout(location = 0) out vec4 color;\n"
3034 << "\n"
3035 << "layout(stream = " << s << ") out gl_PerVertex\n"
3036 << "{\n"
3037 << " vec4 gl_Position;\n"
3038 << outputBuiltIn
3039 << "};\n"
3040 << "\n"
3041 << "void main(void)\n"
3042 << "{\n"
3043 << " // Color constants\n"
3044 << " vec4 g = vec4(0.0, 1.0, 0.0, 1.0);\n"
3045 << " vec4 m = vec4(1.0, 0.0, 1.0, 1.0);\n"
3046 << " // Coordinate constants: leftmost column\n"
3047 << " vec4 a = vec4(-1.0,-1.0, 0.0, 1.0);\n"
3048 << " vec4 b = vec4(-1.0, 0.0, 0.0, 1.0);\n"
3049 << " vec4 c = vec4(-1.0, 1.0, 0.0, 1.0);\n"
3050 << " // Coordinate constants: middle column\n"
3051 << " vec4 i = vec4( 0.0,-1.0, 0.0, 1.0);\n"
3052 << " vec4 j = vec4( 0.0, 0.0, 0.0, 1.0);\n"
3053 << " vec4 k = vec4( 0.0, 1.0, 0.0, 1.0);\n"
3054 << " // Coordinate constants: rightmost column\n"
3055 << " vec4 x = vec4( 1.0,-1.0, 0.0, 1.0);\n"
3056 << " vec4 y = vec4( 1.0, 0.0, 0.0, 1.0);\n"
3057 << " vec4 z = vec4( 1.0, 1.0, 0.0, 1.0);\n"
3058 << "\n";
3059
3060 if (m_parameters.testType == TEST_TYPE_STREAMS)
3061 {
3062 src << " if (gl_PrimitiveIDIn == 0)\n"
3063 << " {\n"
3064 << " color = m; gl_Position = b; EmitStreamVertex(" << s << ");\n"
3065 << " color = m; gl_Position = y; EmitStreamVertex(" << s << ");\n"
3066 << " color = m; gl_Position = c; EmitStreamVertex(" << s << ");\n"
3067 << " EndStreamPrimitive(" << s << ");\n"
3068 << " }\n"
3069 << " else\n"
3070 << " {\n"
3071 << " color = m; gl_Position = y; EmitStreamVertex(" << s << ");\n"
3072 << " color = m; gl_Position = c; EmitStreamVertex(" << s << ");\n"
3073 << " color = m; gl_Position = z; EmitStreamVertex(" << s << ");\n"
3074 << " EndStreamPrimitive(" << s << ");\n"
3075 << " }\n";
3076 }
3077
3078 if (m_parameters.testType == TEST_TYPE_STREAMS_POINTSIZE)
3079 {
3080 const std::string pointSize = "gl_PointSize = " + de::toString(m_parameters.pointSize) + ".0f";
3081
3082 src << " if (gl_PrimitiveIDIn == 0)\n"
3083 << " {\n"
3084 << " color = g; gl_Position = (a + j) / 2.0f; gl_PointSize = 1.0f; EmitStreamVertex(0);\n"
3085 << " EndStreamPrimitive(0);\n"
3086 << " color = m; gl_Position = (b + k) / 2.0f; gl_PointSize = 1.0f; EmitStreamVertex(" << s << ");\n"
3087 << " EndStreamPrimitive(" << s << ");\n"
3088 << " }\n"
3089 << " else\n"
3090 << " {\n"
3091 << " color = g; gl_Position = (j + x) / 2.0f; " << pointSize << "; EmitStreamVertex(0);\n"
3092 << " EndStreamPrimitive(0);\n"
3093 << " color = m; gl_Position = (k + y) / 2.0f; " << pointSize << "; EmitStreamVertex(" << s << ");\n"
3094 << " EndStreamPrimitive(" << s << ");\n"
3095 << " }\n";
3096 }
3097
3098 if (m_parameters.testType == TEST_TYPE_STREAMS_CLIPDISTANCE)
3099 {
3100 src << " if (gl_PrimitiveIDIn == 0)\n"
3101 << " {\n"
3102 << " color = m; gl_Position = b; gl_ClipDistance[0] = -1.0; EmitStreamVertex(" << s << ");\n"
3103 << " color = m; gl_Position = c; gl_ClipDistance[0] = -1.0; EmitStreamVertex(" << s << ");\n"
3104 << " color = m; gl_Position = y; gl_ClipDistance[0] = 1.0; EmitStreamVertex(" << s << ");\n"
3105 << " EndStreamPrimitive(" << s << ");\n"
3106 << " }\n"
3107 << " else\n"
3108 << " {\n"
3109 << " color = m; gl_Position = y; gl_ClipDistance[0] = 1.0; EmitStreamVertex(" << s << ");\n"
3110 << " color = m; gl_Position = c; gl_ClipDistance[0] = -1.0; EmitStreamVertex(" << s << ");\n"
3111 << " color = m; gl_Position = z; gl_ClipDistance[0] = 1.0; EmitStreamVertex(" << s << ");\n"
3112 << " EndStreamPrimitive(" << s << ");\n"
3113 << " }\n";
3114 }
3115
3116 if (m_parameters.testType == TEST_TYPE_STREAMS_CULLDISTANCE)
3117 {
3118 src << " if (gl_PrimitiveIDIn == 0)\n"
3119 << " {\n"
3120 << " color = m; gl_Position = b; gl_CullDistance[0] = -1.0; EmitStreamVertex(" << s << ");\n"
3121 << " color = m; gl_Position = c; gl_CullDistance[0] = -1.0; EmitStreamVertex(" << s << ");\n"
3122 << " color = m; gl_Position = j; gl_CullDistance[0] = -1.0; EmitStreamVertex(" << s << ");\n"
3123 << " EndStreamPrimitive(" << s << ");\n"
3124 << " color = m; gl_Position = j; gl_CullDistance[0] = -1.0; EmitStreamVertex(" << s << ");\n"
3125 << " color = m; gl_Position = c; gl_CullDistance[0] = -1.0; EmitStreamVertex(" << s << ");\n"
3126 << " color = m; gl_Position = k; gl_CullDistance[0] = -1.0; EmitStreamVertex(" << s << ");\n"
3127 << " EndStreamPrimitive(" << s << ");\n"
3128 << " }\n"
3129 << " else\n"
3130 << " {\n"
3131 << " color = m; gl_Position = j; gl_CullDistance[0] = 1.0; EmitStreamVertex(" << s << ");\n"
3132 << " color = m; gl_Position = k; gl_CullDistance[0] = 1.0; EmitStreamVertex(" << s << ");\n"
3133 << " color = m; gl_Position = y; gl_CullDistance[0] = 1.0; EmitStreamVertex(" << s << ");\n"
3134 << " EndStreamPrimitive(" << s << ");\n"
3135 << " color = m; gl_Position = y; gl_CullDistance[0] = 1.0; EmitStreamVertex(" << s << ");\n"
3136 << " color = m; gl_Position = k; gl_CullDistance[0] = 1.0; EmitStreamVertex(" << s << ");\n"
3137 << " color = m; gl_Position = z; gl_CullDistance[0] = 1.0; EmitStreamVertex(" << s << ");\n"
3138 << " EndStreamPrimitive(" << s << ");\n"
3139 << " }\n";
3140 }
3141
3142 src << "}\n";
3143
3144 programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
3145 }
3146
3147 // Fragment shader
3148 {
3149 std::ostringstream src;
3150 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
3151 << "\n"
3152 << "layout(location = 0) in vec4 i_color;\n"
3153 << "layout(location = 0) out vec4 o_color;\n"
3154 << "\n"
3155 << "void main(void)\n"
3156 << "{\n"
3157 << " o_color = i_color;\n"
3158 << "}\n";
3159
3160 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
3161 }
3162
3163 return;
3164 }
3165
3166 if (m_parameters.testType == TEST_TYPE_DRAW_INDIRECT)
3167 {
3168 // vertex shader
3169 {
3170 std::ostringstream src;
3171 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
3172 << "\n"
3173 << "layout(location = 0) in vec4 in_position;\n"
3174 << "\n"
3175 << "void main(void)\n"
3176 << "{\n"
3177 << " gl_Position = in_position;\n"
3178 << "}\n";
3179
3180 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
3181 }
3182
3183 // Fragment shader
3184 {
3185 std::ostringstream src;
3186 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
3187 << "\n"
3188 << "layout(location = 0) out vec4 o_color;\n"
3189 << "\n"
3190 << "void main(void)\n"
3191 << "{\n"
3192 << " o_color = vec4(1.0, 1.0, 1.0, 1.0);\n"
3193 << "}\n";
3194
3195 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
3196 }
3197
3198 return;
3199 }
3200
3201 if (m_parameters.testType == TEST_TYPE_QUERY_GET ||
3202 m_parameters.testType == TEST_TYPE_QUERY_COPY ||
3203 m_parameters.testType == TEST_TYPE_QUERY_COPY_STRIDE_ZERO ||
3204 m_parameters.testType == TEST_TYPE_QUERY_RESET)
3205 {
3206 struct TopologyShaderInfo
3207 {
3208 std::string glslIn;
3209 std::string glslOut;
3210 std::string spirvIn;
3211 std::string spirvOut;
3212 };
3213
3214 const std::map<VkPrimitiveTopology, TopologyShaderInfo> primitiveNames =
3215 {
3216 { VK_PRIMITIVE_TOPOLOGY_POINT_LIST , { "points" , "points" , "InputPoints" , "OutputPoints" } },
3217 { VK_PRIMITIVE_TOPOLOGY_LINE_LIST , { "lines" , "line_strip" , "InputLines" , "OutputLineStrip" } },
3218 { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP , { "lines" , "line_strip" , "InputLines" , "OutputLineStrip" } },
3219 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST , { "triangles" , "triangle_strip" , "Triangles" , "OutputTriangleStrip" } },
3220 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP , { "triangles" , "triangle_strip" , "Triangles" , "OutputTriangleStrip" } },
3221 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN , { "triangles" , "triangle_strip" , "Triangles" , "OutputTriangleStrip" } },
3222 { VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY , { "lines_adjacency" , "line_strip" , "InputLinesAdjacency" , "OutputLineStrip" } },
3223 { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY , { "lines_adjacency" , "line_strip" , "InputLinesAdjacency" , "OutputLineStrip" } },
3224 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY , { "triangles_adjacency" , "triangle_strip" , "InputTrianglesAdjacency" , "OutputTriangleStrip" } },
3225 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY , { "triangles_adjacency" , "triangle_strip" , "InputTrianglesAdjacency" , "OutputTriangleStrip" } }
3226 };
3227
3228 // Vertex shader
3229 {
3230 std::ostringstream src;
3231 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
3232 << "\n"
3233 << "layout(location = 0) out vec4 out0;\n"
3234 << "\n"
3235 << "void main(void)\n"
3236 << "{\n"
3237 << " float n = 4.0 * float(gl_VertexIndex);\n"
3238 << " out0 = vec4(n + 0.0, n + 1.0, n + 2.0, n + 3.0);\n"
3239 << "}\n";
3240
3241 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
3242 }
3243
3244 // geometry shader
3245 if (m_parameters.streamId == 0)
3246 {
3247 std::ostringstream src;
3248
3249 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
3250 << "\n"
3251 << "layout(" << primitiveNames.at(m_parameters.primTopology).glslIn << ") in;\n"
3252 << "layout(location = 0) in vec4 in0[];\n"
3253 << "\n"
3254 << "layout(" << primitiveNames.at(m_parameters.primTopology).glslOut << ", max_vertices = " << topologyData.at(m_parameters.primTopology).primSize<< ") out;\n"
3255 << "layout(xfb_buffer = 0, xfb_offset = 0, xfb_stride = 16, location = 0) out vec4 out0;\n"
3256 << "\n"
3257 << "void main(void)\n"
3258 << "{\n";
3259
3260 for (deUint32 i = 0; i < topologyData.at(m_parameters.primTopology).primSize; i++)
3261 {
3262 if (!m_parameters.omitShaderWrite)
3263 src << " out0 = in0[" << i << "];\n";
3264 src << " EmitVertex();\n";
3265 }
3266
3267 src << " EndPrimitive();\n"
3268 << "}\n";
3269
3270 programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
3271 }
3272 else
3273 {
3274 const deUint32 s = m_parameters.streamId;
3275 std::ostringstream src;
3276
3277 if (m_parameters.testType == TEST_TYPE_QUERY_GET)
3278 {
3279 // The SPIR-V program below is roughly equivalent to the following GLSL code:
3280 //
3281 // #version 450
3282 // #extension GL_ARB_enhanced_layouts : require
3283 //
3284 // layout(points) in;
3285 // layout(location = 0) in vec4 in0[];
3286 //
3287 // layout(points, max_vertices = 1) out;
3288 // layout(location=0, stream=1, xfb_buffer=0, xfb_stride=16) out OutBlock {
3289 // layout(xfb_offset=0, location=0) vec4 out0;
3290 // } outBlock;
3291 //
3292 // void main(void)
3293 // {
3294 // outBlock.out0 = in0[0];
3295 // EmitStreamVertex(1);
3296 // EndStreamPrimitive(1);
3297 // }
3298 //
3299 // However, the stream number has been parametrized and the code generated by glslang has been tuned to move the
3300 // Stream, XfbBuffer and XfbStride decorations to the structure member instead of the block. This allows us to test
3301 // transform feedback decorations on structure members as part of these basic tests.
3302 src << "; SPIR-V\n"
3303 << "; Version: 1.0\n"
3304 << "; Generator: Khronos Glslang Reference Front End; 10\n"
3305 << "; Bound: 64\n"
3306 << "; Schema: 0\n"
3307 << " OpCapability Geometry\n"
3308 << " OpCapability TransformFeedback\n"
3309 << " OpCapability GeometryStreams\n"
3310 << " %1 = OpExtInstImport \"GLSL.std.450\"\n"
3311 << " OpMemoryModel Logical GLSL450\n"
3312 << " OpEntryPoint Geometry %main \"main\" %outBlock %in0\n"
3313 << " OpExecutionMode %main Xfb\n"
3314 << " OpExecutionMode %main " << primitiveNames.at(m_parameters.primTopology).spirvIn << "\n"
3315 << " OpExecutionMode %main Invocations 1\n"
3316 << " OpExecutionMode %main " << primitiveNames.at(m_parameters.primTopology).spirvOut << "\n"
3317 << " OpExecutionMode %main OutputVertices " << topologyData.at(m_parameters.primTopology).primSize << "\n"
3318 << " OpSource GLSL 450\n"
3319 << " OpSourceExtension \"GL_ARB_enhanced_layouts\"\n"
3320 << " OpName %main \"main\"\n"
3321 << " OpName %OutBlock \"OutBlock\"\n"
3322 << " OpMemberName %OutBlock 0 \"out0\"\n"
3323 << " OpName %outBlock \"outBlock\"\n"
3324 << " OpName %in0 \"in0\"\n"
3325 << " OpMemberDecorate %OutBlock 0 Location 0\n"
3326 << " OpMemberDecorate %OutBlock 0 Offset 0\n"
3327 // These Stream, XfbBuffer and XfbStride decorations have been moved to the struct member.
3328 << " OpMemberDecorate %OutBlock 0 Stream " << s << "\n"
3329 << " OpMemberDecorate %OutBlock 0 XfbBuffer 0\n"
3330 << " OpMemberDecorate %OutBlock 0 XfbStride 16\n"
3331 << " OpDecorate %OutBlock Block\n"
3332 // The decorations mentioned above were using OpDecorate and assigned to %outBlock itself here.
3333 << " OpDecorate %in0 Location 0\n"
3334 << " %void = OpTypeVoid\n"
3335 << " %3 = OpTypeFunction %void\n"
3336 << " %float = OpTypeFloat 32\n"
3337 << " %v4float = OpTypeVector %float 4\n"
3338 << " %OutBlock = OpTypeStruct %v4float\n"
3339 << "%_ptr_Output_OutBlock = OpTypePointer Output %OutBlock\n"
3340 << " %outBlock = OpVariable %_ptr_Output_OutBlock Output\n"
3341 << " %int = OpTypeInt 32 1\n"
3342 << " %int_0 = OpConstant %int 0\n";
3343
3344 for (deUint32 i = 1; i < topologyData.at(m_parameters.primTopology).primSize + 1; i++)
3345 {
3346 src << "%int_" << i << " = OpConstant %int " << i << "\n";
3347 }
3348
3349 src << " %uint = OpTypeInt 32 0\n"
3350 << " %uint_0 = OpConstant %uint " << topologyData.at(m_parameters.primTopology).primSize << "\n"
3351 << "%_arr_v4float_uint_0 = OpTypeArray %v4float %uint_0\n"
3352 << "%_ptr_Input__arr_v4float_uint_0 = OpTypePointer Input %_arr_v4float_uint_0\n"
3353 << " %in0 = OpVariable %_ptr_Input__arr_v4float_uint_0 Input\n"
3354 << "%_ptr_Input_v4float = OpTypePointer Input %v4float\n"
3355 << "%_ptr_Output_v4float = OpTypePointer Output %v4float\n"
3356 << " %streamNum = OpConstant %int " << s << "\n"
3357 << " %main = OpFunction %void None %3\n"
3358 << " %5 = OpLabel\n";
3359
3360 for (deUint32 i = 1; i < topologyData.at(m_parameters.primTopology).primSize + 1; i++)
3361 {
3362 src << "%" << i << "1 = OpAccessChain %_ptr_Input_v4float %in0 %int_" << i << "\n"
3363 << " %" << i << "2 = OpLoad %v4float %" << i << "1\n"
3364 << " %" << i << "3 = OpAccessChain %_ptr_Output_v4float %outBlock %int_0\n"
3365 << " OpStore %" << i << "3 %" << i << "2\n"
3366 << " OpEmitStreamVertex %streamNum\n";
3367 }
3368
3369 src << " OpEndStreamPrimitive %streamNum\n"
3370 << " OpReturn\n"
3371 << " OpFunctionEnd\n"
3372 ;
3373
3374 programCollection.spirvAsmSources.add("geom") << src.str();
3375 }
3376 else
3377 {
3378 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
3379 << "\n"
3380 << "layout(" << primitiveNames.at(m_parameters.primTopology).glslIn << ") in;\n"
3381 << "layout(location = 0) in vec4 in0[];\n"
3382 << "\n"
3383 << "layout(" << primitiveNames.at(m_parameters.primTopology).glslOut << ", max_vertices = " << topologyData.at(m_parameters.primTopology).primSize << ") out;\n"
3384 << "layout(stream = " << s << ", xfb_buffer = 0, xfb_offset = 0, xfb_stride = 16, location = 0) out vec4 out0;\n"
3385 << "\n"
3386 << "void main(void)\n"
3387 << "{\n";
3388
3389 for (deUint32 i = 0; i < topologyData.at(m_parameters.primTopology).primSize; i++)
3390 {
3391 src << " out0 = in0[" << i << "];\n"
3392 << " EmitStreamVertex(" << s << ");\n";
3393 }
3394
3395 src << " EndStreamPrimitive(" << s << ");\n"
3396 << "}\n";
3397
3398 programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
3399 }
3400 }
3401
3402 return;
3403 }
3404
3405 if (m_parameters.testType == TEST_TYPE_MULTIQUERY)
3406 {
3407 // vertex shader
3408 {
3409 std::ostringstream src;
3410 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
3411 << "\n"
3412 << "layout(location = 0) out ivec4 out0;\n"
3413 << "\n"
3414 << "void main(void)\n"
3415 << "{\n"
3416 << " out0 = ivec4(gl_VertexIndex);\n"
3417 << "}\n";
3418
3419 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
3420 }
3421
3422 // geometry shader
3423 {
3424 const deUint32 s = m_parameters.streamId;
3425 std::ostringstream src;
3426
3427 DE_ASSERT(s != 0);
3428
3429 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
3430 << "\n"
3431 << "layout(points) in;\n"
3432 << "\n"
3433 << "layout(points, max_vertices = 4) out;\n"
3434 << "\n"
3435 << "layout(stream = " << 0 << ", xfb_buffer = 0, xfb_offset = 0, xfb_stride = 16, location = 0) out vec4 out0;\n"
3436 << "layout(stream = " << s << ", xfb_buffer = 1, xfb_offset = 0, xfb_stride = 16, location = 1) out vec4 out1;\n"
3437 << "\n"
3438 << "void main(void)\n"
3439 << "{\n"
3440 << " const int n0 = 3;\n"
3441 << " const int n1 = 1;\n"
3442 << " const float c0 = 0.5f;\n"
3443 << " const float c1 = 0.5f + float(" << s << ");\n"
3444 << "\n"
3445 << " for (int j = 0; j < n0; j++)\n"
3446 << " {\n";
3447
3448 if (!m_parameters.omitShaderWrite)
3449 src << " out0 = vec4(c0);\n";
3450
3451 src << " EmitStreamVertex(0);\n"
3452 << " EndStreamPrimitive(0);\n"
3453 << " }\n"
3454 << "\n"
3455 << " for (int j = 0; j < n1; j++)\n"
3456 << " {\n"
3457 << " out1 = vec4(c1);\n"
3458 << " EmitStreamVertex(" << s << ");\n"
3459 << " EndStreamPrimitive(" << s << ");\n"
3460 << " }\n"
3461 << "}\n";
3462
3463 programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
3464 }
3465
3466 return;
3467 }
3468
3469 if (m_parameters.testType == TEST_TYPE_LINES_TRIANGLES)
3470 {
3471 // vertex shader
3472 {
3473 std::ostringstream src;
3474 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
3475 << "\n"
3476 << "void main(void)\n"
3477 << "{\n"
3478 << "}\n";
3479
3480 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
3481 }
3482
3483 // geometry shader
3484 {
3485 const deUint32 s = m_parameters.streamId;
3486 const bool line = isPrimitiveTopologyLine(m_parameters.primTopology);
3487 const bool tri = isPrimitiveTopologyTriangle(m_parameters.primTopology);
3488 const std::string p = line ? std::string("line_strip")
3489 : tri ? std::string("triangle_strip")
3490 : std::string("");
3491 const std::string vertexCount = line ? vectorToString(LINES_LIST)
3492 : tri ? vectorToString(TRIANGLES_LIST)
3493 : std::string("");
3494 std::ostringstream src;
3495
3496 DE_ASSERT(s != 0);
3497
3498 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
3499 << "\n"
3500 << "layout(points) in;\n"
3501 << "\n"
3502 << "layout(" << p << ", max_vertices = 256) out;\n"
3503 << "layout(stream = " << 0 << ", xfb_buffer = 0, xfb_offset = 0, xfb_stride = 16, location = 0) out vec4 out0;\n"
3504 << "layout(stream = " << s << ", xfb_buffer = 1, xfb_offset = 0, xfb_stride = 16, location = 1) out vec4 out1;\n"
3505 << "\n"
3506 << "const int vertices_in_primitive[] = int[](" << vertexCount << ");\n"
3507 << "\n"
3508 << "int num_vertices_in_primitives()\n"
3509 << "{\n"
3510 << " int c = 0;\n"
3511 << "\n"
3512 << " for (int i = 0; i < vertices_in_primitive.length(); i++)\n"
3513 << " c = c + vertices_in_primitive[i];\n"
3514 << "\n"
3515 << " return c;\n"
3516 << "}\n"
3517 << "\n"
3518 << "void main(void)\n"
3519 << "{\n"
3520 << " int vc = num_vertices_in_primitives();\n"
3521 << " int c0 = vc * gl_PrimitiveIDIn;\n"
3522 << " int c1 = vc * (" << INVOCATION_COUNT << " + gl_PrimitiveIDIn);\n"
3523 << "\n"
3524 << " for (int i = 0; i < vertices_in_primitive.length(); i++)\n"
3525 << " {\n"
3526 << " const int n = vertices_in_primitive[i];\n"
3527 << "\n"
3528 << " for (int j = 0; j < n; j++)\n"
3529 << " {\n"
3530 << " out0 = vec4(ivec4(c0, gl_PrimitiveIDIn, i, j));\n"
3531 << " c0 = c0 + 1;\n"
3532 << " EmitStreamVertex(0);\n"
3533 << "\n"
3534 << " out1 = vec4(ivec4(c1, gl_PrimitiveIDIn, i, j));\n"
3535 << " c1 = c1 + 1;\n"
3536 << " EmitStreamVertex(" << s << ");\n"
3537 << " }\n"
3538 << "\n"
3539 << " EndStreamPrimitive(0);\n"
3540 << " EndStreamPrimitive(" << s << ");\n"
3541 << " }\n"
3542 << "}\n";
3543
3544 programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
3545 }
3546
3547 return;
3548 }
3549
3550 DE_ASSERT(0 && "Unknown test");
3551 }
3552
createTransformFeedbackSimpleTests(tcu::TestCaseGroup * group)3553 void createTransformFeedbackSimpleTests(tcu::TestCaseGroup* group)
3554 {
3555 {
3556 const deUint32 bufferCounts[] = { 1u, 2u, 4u, 8u };
3557 const deUint32 bufferSizes[] = { 256u, 512u, 128u * 1024u };
3558 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 };
3559 const std::string testTypeNames[] = { "basic", "resume", "xfb_pointsize", "xfb_clipdistance", "xfb_culldistance", "xfb_clip_and_cull" };
3560
3561 for (deUint32 testTypesNdx = 0; testTypesNdx < DE_LENGTH_OF_ARRAY(testTypes); ++testTypesNdx)
3562 {
3563 const TestType testType = testTypes[testTypesNdx];
3564 const std::string testName = testTypeNames[testTypesNdx];
3565
3566 for (deUint32 bufferCountsNdx = 0; bufferCountsNdx < DE_LENGTH_OF_ARRAY(bufferCounts); ++bufferCountsNdx)
3567 {
3568 const deUint32 partCount = bufferCounts[bufferCountsNdx];
3569
3570 for (deUint32 bufferSizesNdx = 0; bufferSizesNdx < DE_LENGTH_OF_ARRAY(bufferSizes); ++bufferSizesNdx)
3571 {
3572 const deUint32 bufferSize = bufferSizes[bufferSizesNdx];
3573 TestParameters parameters = { testType, bufferSize, partCount, 0u, 0u, 0u, STREAM_ID_0_NORMAL, false, false, true, false, VK_PRIMITIVE_TOPOLOGY_POINT_LIST };
3574
3575 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_" + de::toString(partCount) + "_" + de::toString(bufferSize)).c_str(), "Simple Transform Feedback test", parameters));
3576 parameters.streamId0Mode = STREAM_ID_0_BEGIN_QUERY_INDEXED;
3577 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_beginqueryindexed_streamid_0_" + de::toString(partCount) + "_" + de::toString(bufferSize)).c_str(), "Simple Transform Feedback test", parameters));
3578 parameters.streamId0Mode = STREAM_ID_0_END_QUERY_INDEXED;
3579 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_endqueryindexed_streamid_0_" + de::toString(partCount) + "_" + de::toString(bufferSize)).c_str(), "Simple Transform Feedback test", parameters));
3580 }
3581 }
3582 }
3583 }
3584
3585 {
3586 const deUint32 bufferCounts[] = { 6u, 8u, 10u, 12u };
3587 const TestType testType = TEST_TYPE_WINDING;
3588 const std::string testName = "winding";
3589
3590 for (const auto& topology : topologyData)
3591 {
3592 // Note: no need to test POINT_LIST as is tested in many tests.
3593 if (topology.first == VK_PRIMITIVE_TOPOLOGY_POINT_LIST)
3594 continue;
3595
3596 for (deUint32 bufferCountsNdx = 0; bufferCountsNdx < DE_LENGTH_OF_ARRAY(bufferCounts); ++bufferCountsNdx)
3597 {
3598 const deUint32 vertexCount = bufferCounts[bufferCountsNdx];
3599
3600 TestParameters parameters = { testType, 0u, vertexCount, 0u, 0u, 0u, STREAM_ID_0_NORMAL, false, false, false, false, topology.first };
3601
3602 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_" + topology.second.topologyName + de::toString(vertexCount)).c_str(), "Topology winding test", parameters));
3603 }
3604 }
3605 }
3606
3607 {
3608 const deUint32 vertexStrides[] = { 4u, 61u, 127u, 251u, 509u };
3609 const TestType testType = TEST_TYPE_DRAW_INDIRECT;
3610 const std::string testName = "draw_indirect";
3611
3612 for (deUint32 vertexStridesNdx = 0; vertexStridesNdx < DE_LENGTH_OF_ARRAY(vertexStrides); ++vertexStridesNdx)
3613 {
3614 const deUint32 vertexStrideBytes = static_cast<deUint32>(sizeof(deUint32) * vertexStrides[vertexStridesNdx]);
3615 TestParameters parameters = { testType, 0u, 0u, 0u, 0u, vertexStrideBytes, STREAM_ID_0_NORMAL, false, false, false, false, VK_PRIMITIVE_TOPOLOGY_POINT_LIST };
3616
3617 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_" + de::toString(vertexStrideBytes)).c_str(), "Rendering tests with various strides", parameters));
3618 parameters.streamId0Mode = STREAM_ID_0_BEGIN_QUERY_INDEXED;
3619 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_beginqueryindexed_streamid_0_" + de::toString(vertexStrideBytes)).c_str(), "Rendering tests with various strides", parameters));
3620 parameters.streamId0Mode = STREAM_ID_0_END_QUERY_INDEXED;
3621 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_endqueryindexed_streamid_0_" + de::toString(vertexStrideBytes)).c_str(), "Rendering tests with various strides", parameters));
3622 }
3623 }
3624
3625 {
3626 const TestType testType = TEST_TYPE_BACKWARD_DEPENDENCY;
3627 const std::string testName = "backward_dependency";
3628 TestParameters parameters = { testType, 512u, 2u, 0u, 0u, 0u, STREAM_ID_0_NORMAL, false, false, false, false, VK_PRIMITIVE_TOPOLOGY_POINT_LIST };
3629
3630 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), testName.c_str(), "Rendering test checks backward pipeline dependency", parameters));
3631 parameters.streamId0Mode = STREAM_ID_0_BEGIN_QUERY_INDEXED;
3632 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_beginqueryindexed_streamid_0").c_str(), "Rendering test checks backward pipeline dependency", parameters));
3633 parameters.streamId0Mode = STREAM_ID_0_END_QUERY_INDEXED;
3634 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_endqueryindexed_streamid_0").c_str(), "Rendering test checks backward pipeline dependency", parameters));
3635
3636 parameters.noOffsetArray = true;
3637 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_no_offset_array").c_str(), "Rendering test checks backward pipeline dependency (using NULL for offset array)", parameters));
3638 }
3639
3640 {
3641 const deUint32 usedStreamId[] = { 0u, 1u, 3u, 6u, 14u };
3642 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.
3643 const TestType testType = TEST_TYPE_QUERY_GET;
3644 const std::string testName = "query";
3645 const TestType testTypeCopy[] = { TEST_TYPE_QUERY_COPY, TEST_TYPE_QUERY_COPY_STRIDE_ZERO };
3646 const std::string testNameCopy[] = { "query_copy", "query_copy_stride_zero" };
3647 const TestType testTypeHostQueryReset = TEST_TYPE_QUERY_RESET;
3648 const std::string testNameHostQueryReset = "host_query_reset";
3649
3650 for (const auto& topology : topologyData)
3651 {
3652 // Currently, we don't test tessellation here.
3653 if (topology.first == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST)
3654 continue;
3655
3656 for (const auto& streamCounts : usedStreamId)
3657 {
3658 const deUint32 streamId = streamCounts;
3659
3660 for (const auto& numVertices : vertexCounts)
3661 {
3662 for (deUint32 i = 0; i < 2; ++i)
3663 {
3664 const bool query64Bits = (i == 1);
3665 const std::string widthStr = (query64Bits ? "_64bits" : "_32bits");
3666
3667 deUint32 vertCount = numVertices;
3668
3669 // The number of vertices in original test was 4.
3670 if (topology.first == VK_PRIMITIVE_TOPOLOGY_POINT_LIST && vertCount == 6) vertCount -= 2;
3671
3672 // Round the number of vertices to match the used primitive topology - if necessary.
3673 const deUint32 primitiveCount = (deUint32)topology.second.getNumPrimitives(vertCount);
3674 const deUint32 vertexCount = (deUint32)topology.second.getNumVertices(primitiveCount);
3675
3676 DE_ASSERT(vertexCount > 0);
3677
3678 const deUint32 bytesPerVertex = static_cast<deUint32>(4 * sizeof(float));
3679 const deUint32 bufferSize = bytesPerVertex * vertexCount;
3680 TestParameters parameters = { testType, bufferSize, 0u, streamId, 0u, 0u, STREAM_ID_0_NORMAL, query64Bits, false, true, false, topology.first };
3681 const std::string fullTestName = testName + "_" + topology.second.topologyName + de::toString(streamId) + "_" + de::toString(vertexCount) + widthStr;
3682 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), fullTestName.c_str(), "Written primitives query test", parameters));
3683
3684 TestParameters omitParameters = { testType, bufferSize, 0u, streamId, 0u, 0u, STREAM_ID_0_NORMAL, query64Bits, false, true, true, topology.first };
3685 const std::string omitTestName = testName + "_omit_write_" + topology.second.topologyName + de::toString(streamId) + "_" + de::toString(vertexCount) + widthStr;
3686 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), omitTestName.c_str(), "Written primitives query test", omitParameters));
3687
3688 for (deUint32 testTypeCopyNdx = 0; testTypeCopyNdx < DE_LENGTH_OF_ARRAY(testTypeCopy); testTypeCopyNdx++)
3689 {
3690 const TestParameters parametersCopy = { testTypeCopy[testTypeCopyNdx], bufferSize, 0u, streamId, 0u, 0u, STREAM_ID_0_NORMAL, query64Bits, false, true, false, topology.first };
3691 const std::string fullTestNameCopy = testNameCopy[testTypeCopyNdx] + "_" + topology.second.topologyName + de::toString(streamId) + "_" + de::toString(vertexCount) + widthStr;
3692 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), fullTestNameCopy.c_str(), "Written primitives query test", parametersCopy));
3693 }
3694
3695 const TestParameters parametersHostQueryReset = { testTypeHostQueryReset, bufferSize, 0u, streamId, 0u, 0u, STREAM_ID_0_NORMAL, query64Bits, false, true, false, topology.first };
3696 const std::string fullTestNameHostQueryReset = testNameHostQueryReset + "_" + topology.second.topologyName + de::toString(streamId) + "_" + de::toString(vertexCount) + widthStr;
3697 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), fullTestNameHostQueryReset.c_str(), "Written primitives query test", parametersHostQueryReset));
3698
3699 if (streamId == 0)
3700 {
3701 std::string testNameStream0 = fullTestName;
3702 testNameStream0 += "_beginqueryindexed_streamid_0";
3703 parameters.streamId0Mode = STREAM_ID_0_BEGIN_QUERY_INDEXED;
3704 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), testNameStream0.c_str(), "Written primitives query test", parameters));
3705 testNameStream0 = fullTestName;
3706 testNameStream0 += "_endqueryindexed_streamid_0";
3707 parameters.streamId0Mode = STREAM_ID_0_END_QUERY_INDEXED;
3708 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), testNameStream0.c_str(), "Written primitives query test", parameters));
3709 }
3710 }
3711 }
3712 }
3713 }
3714 }
3715
3716 // Depth clip control tests.
3717 {
3718 TestParameters parameters = { TEST_TYPE_DEPTH_CLIP_CONTROL_VERTEX, 96, 1u, 0u, 0u, 0u, STREAM_ID_0_NORMAL, false, false, true, false, VK_PRIMITIVE_TOPOLOGY_POINT_LIST };
3719
3720 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), "depth_clip_control_vertex", "", parameters));
3721 }
3722 {
3723 TestParameters parameters = { TEST_TYPE_DEPTH_CLIP_CONTROL_GEOMETRY, 96, 1u, 0u, 0u, 0u, STREAM_ID_0_NORMAL, false, false, true, false, VK_PRIMITIVE_TOPOLOGY_POINT_LIST };
3724
3725 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), "depth_clip_control_geometry", "", parameters));
3726 }
3727 {
3728 TestParameters parameters = { TEST_TYPE_DEPTH_CLIP_CONTROL_TESE, 96, 1u, 0u, 0u, 0u, STREAM_ID_0_NORMAL, false, false, true, false, VK_PRIMITIVE_TOPOLOGY_PATCH_LIST };
3729
3730 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), "depth_clip_control_tese", "", parameters));
3731 }
3732
3733 {
3734 const deUint32 usedStreamId[] = { 1u, 3u, 6u, 14u };
3735 const TestType testType = TEST_TYPE_LINES_TRIANGLES;
3736 const std::string testName = "lines_or_triangles";
3737
3738 for (const auto& topology : topologyData)
3739 {
3740 const deUint32 outputVertexCount = (topology.first == VK_PRIMITIVE_TOPOLOGY_LINE_STRIP) ? 2 * destripedLineCount(LINES_LIST)
3741 : (topology.first == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP) ? 3 * destripedTriangleCount(TRIANGLES_LIST)
3742 : 0;
3743
3744 if (outputVertexCount == 0)
3745 continue;
3746
3747 for (const auto& streamId : usedStreamId)
3748 {
3749 const deUint32 partCount = 2u;
3750 const deUint32 bytesPerVertex = static_cast<deUint32>(sizeof(tcu::Vec4));
3751 const deUint32 bufferSize = partCount * INVOCATION_COUNT * outputVertexCount * bytesPerVertex;
3752 const std::string fullTestName = testName + "_" + topology.second.topologyName + de::toString(streamId);
3753 const TestParameters parameters =
3754 {
3755 testType, // TestType testType;
3756 bufferSize, // deUint32 bufferSize;
3757 partCount, // deUint32 partCount;
3758 streamId, // deUint32 streamId;
3759 0u, // deUint32 pointSize;
3760 0u, // deUint32 vertexStride;
3761 STREAM_ID_0_NORMAL, // StreamId0Mode streamId0Mode;
3762 false, // bool query64bits;
3763 false, // bool noOffsetArray;
3764 true, // bool requireRastStreamSelect;
3765 false, // bool omitShaderWrite;
3766 topology.first // VkPrimitiveTopology primTopology;
3767 };
3768
3769 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), fullTestName.c_str(), "", parameters));
3770 }
3771 }
3772 }
3773 }
3774
createTransformFeedbackStreamsSimpleTests(tcu::TestCaseGroup * group)3775 void createTransformFeedbackStreamsSimpleTests (tcu::TestCaseGroup* group)
3776 {
3777 const deUint32 usedStreamId[] = { 1u, 3u, 6u, 14u };
3778 const TestType testTypes[] = { TEST_TYPE_STREAMS, TEST_TYPE_STREAMS_POINTSIZE, TEST_TYPE_STREAMS_CLIPDISTANCE, TEST_TYPE_STREAMS_CULLDISTANCE };
3779 const std::string testTypeNames[] = { "streams", "streams_pointsize", "streams_clipdistance", "streams_culldistance" };
3780
3781 for (deUint32 testTypesNdx = 0; testTypesNdx < DE_LENGTH_OF_ARRAY(testTypes); ++testTypesNdx)
3782 {
3783 const TestType testType = testTypes[testTypesNdx];
3784 const std::string testName = testTypeNames[testTypesNdx];
3785 const deUint32 pointSize = (testType == TEST_TYPE_STREAMS_POINTSIZE) ? 2u : 0u;
3786
3787 for (deUint32 streamCountsNdx = 0; streamCountsNdx < DE_LENGTH_OF_ARRAY(usedStreamId); ++streamCountsNdx)
3788 {
3789 const deUint32 streamId = usedStreamId[streamCountsNdx];
3790 TestParameters parameters = { testType, 0u, 0u, streamId, pointSize, 0u, STREAM_ID_0_NORMAL, false, false, true, false, VK_PRIMITIVE_TOPOLOGY_POINT_LIST };
3791
3792 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_" + de::toString(streamId)).c_str(), "Streams usage test", parameters));
3793 }
3794 }
3795
3796 {
3797 const TestType testType = TEST_TYPE_MULTISTREAMS;
3798 const std::string testName = "multistreams";
3799
3800 for (deUint32 bufferCountsNdx = 0; bufferCountsNdx < DE_LENGTH_OF_ARRAY(usedStreamId); ++bufferCountsNdx)
3801 {
3802 const deUint32 streamId = usedStreamId[bufferCountsNdx];
3803 const deUint32 streamsUsed = 2u;
3804 const deUint32 maxBytesPerVertex = 256u;
3805 const TestParameters parameters = { testType, maxBytesPerVertex * streamsUsed, streamsUsed, streamId, 0u, 0u, STREAM_ID_0_NORMAL, false, false, true, false, VK_PRIMITIVE_TOPOLOGY_POINT_LIST };
3806
3807 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_" + de::toString(streamId)).c_str(), "Simultaneous multiple streams usage test", parameters));
3808 }
3809 }
3810
3811 {
3812 const TestType testType = TEST_TYPE_MULTIQUERY;
3813 const std::string testName = "multiquery";
3814
3815 for (deUint32 bufferCountsNdx = 0; bufferCountsNdx < DE_LENGTH_OF_ARRAY(usedStreamId); ++bufferCountsNdx)
3816 {
3817 const deUint32 streamId = usedStreamId[bufferCountsNdx];
3818 const deUint32 streamsUsed = 2u;
3819 const deUint32 maxBytesPerVertex = 256u;
3820 const TestParameters parameters = { testType, maxBytesPerVertex * streamsUsed, streamsUsed, streamId, 0u, 0u, STREAM_ID_0_NORMAL, false, false, false, false, VK_PRIMITIVE_TOPOLOGY_POINT_LIST };
3821 const TestParameters writeOmitParameters = { testType, maxBytesPerVertex * streamsUsed, streamsUsed, streamId, 0u, 0u, STREAM_ID_0_NORMAL, false, false, false, true, VK_PRIMITIVE_TOPOLOGY_POINT_LIST };
3822
3823 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_" + de::toString(streamId)).c_str(), "Simultaneous multiple queries usage test", parameters));
3824 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_omit_write_" + de::toString(streamId)).c_str(), "Simultaneous multiple queries usage test", writeOmitParameters));
3825 }
3826 }
3827 }
3828
createTransformFeedbackAndStreamsSimpleTests(tcu::TestCaseGroup * group)3829 void createTransformFeedbackAndStreamsSimpleTests (tcu::TestCaseGroup* group)
3830 {
3831 createTransformFeedbackSimpleTests(group);
3832 createTransformFeedbackStreamsSimpleTests(group);
3833 }
3834 } // anonymous
3835
createTransformFeedbackSimpleTests(tcu::TestContext & testCtx)3836 tcu::TestCaseGroup* createTransformFeedbackSimpleTests (tcu::TestContext& testCtx)
3837 {
3838 return createTestGroup(testCtx, "simple", "Transform Feedback Simple tests", createTransformFeedbackAndStreamsSimpleTests);
3839 }
3840
3841 } // TransformFeedback
3842 } // vkt
3843