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 "vkCmdUtil.hpp"
29 #include "vkImageUtil.hpp"
30 #include "vkObjUtil.hpp"
31 #include "vkQueryUtil.hpp"
32 #include "vkRefUtil.hpp"
33 #include "vkTypeUtil.hpp"
34
35 #include "deUniquePtr.hpp"
36 #include "deRandom.hpp"
37
38 #include "tcuTextureUtil.hpp"
39 #include "tcuVectorUtil.hpp"
40 #include "tcuImageCompare.hpp"
41 #include "tcuRGBA.hpp"
42 #include "tcuTestLog.hpp"
43 #include "tcuCommandLine.hpp"
44
45 #include <iostream>
46 #include <functional>
47 #include <set>
48 #include <algorithm>
49 #include <limits>
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_MULTISTREAMS_SAME_LOCATION,
84 TEST_TYPE_DRAW_INDIRECT,
85 TEST_TYPE_DRAW_INDIRECT_MULTIVIEW,
86 TEST_TYPE_BACKWARD_DEPENDENCY,
87 TEST_TYPE_BACKWARD_DEPENDENCY_INDIRECT,
88 TEST_TYPE_QUERY_GET,
89 TEST_TYPE_QUERY_COPY,
90 TEST_TYPE_QUERY_COPY_STRIDE_ZERO,
91 TEST_TYPE_QUERY_RESET,
92 TEST_TYPE_MULTIQUERY,
93 TEST_TYPE_DEPTH_CLIP_CONTROL_VERTEX,
94 TEST_TYPE_DEPTH_CLIP_CONTROL_GEOMETRY,
95 TEST_TYPE_DEPTH_CLIP_CONTROL_TESE,
96 TEST_TYPE_LINES_TRIANGLES,
97 TEST_TYPE_DRAW_OUTSIDE,
98 TEST_TYPE_HOLES_VERTEX,
99 TEST_TYPE_HOLES_GEOMETRY,
100 TEST_TYPE_LAST
101 };
102
103 enum StreamId0Mode
104 {
105 STREAM_ID_0_NORMAL = 0,
106 STREAM_ID_0_BEGIN_QUERY_INDEXED = 1,
107 STREAM_ID_0_END_QUERY_INDEXED = 2,
108 };
109
110 struct TestParameters
111 {
112 TestType testType;
113 deUint32 bufferSize;
114 deUint32 partCount;
115 deUint32 streamId;
116 deUint32 pointSize;
117 deUint32 vertexStride;
118 StreamId0Mode streamId0Mode;
119 bool query64bits;
120 bool noOffsetArray;
121 bool requireRastStreamSelect;
122 bool omitShaderWrite;
123 bool useMaintenance5;
124 VkPrimitiveTopology primTopology;
125 bool queryResultWithAvailability;
126 };
127
128 struct TopologyInfo
129 {
130 deUint32 primSize; // The size of the on primitive.
131 std::string topologyName; // The suffix for the name of test.
132 std::function<deUint64(deUint64)> getNumPrimitives; // The number of primitives generated.
133 std::function<deUint64(deUint64)> getNumVertices; // The number of vertices generated.
134 };
135
136 const std::map<VkPrimitiveTopology, TopologyInfo> topologyData =
137 {
138 { VK_PRIMITIVE_TOPOLOGY_POINT_LIST , { 1, "" ,[](deUint64 vertexCount) { return vertexCount; } ,[](deUint64 primCount) { return primCount; }, } },
139 { VK_PRIMITIVE_TOPOLOGY_LINE_LIST , { 2, "line_list_" ,[](deUint64 vertexCount) { return vertexCount / 2u; } ,[](deUint64 primCount) { return primCount * 2u; }, } },
140 { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP , { 2, "line_strip_" ,[](deUint64 vertexCount) { return vertexCount - 1u; } ,[](deUint64 primCount) { return primCount + 1u; }, } },
141 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST , { 3, "triangle_list_" ,[](deUint64 vertexCount) { return vertexCount / 3u; } ,[](deUint64 primCount) { return primCount * 3u; }, } },
142 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP , { 3, "triangle_strip_" ,[](deUint64 vertexCount) { return vertexCount - 2u; } ,[](deUint64 primCount) { return primCount + 2u; }, } },
143 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN , { 3, "triangle_fan_" ,[](deUint64 vertexCount) { return vertexCount - 2u; } ,[](deUint64 primCount) { return primCount + 2u; }, } },
144 { VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY , { 2, "line_list_with_adjacency_" ,[](deUint64 vertexCount) { return vertexCount / 4u; } ,[](deUint64 primCount) { return primCount * 4u; }, } },
145 { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY , { 2, "line_strip_with_adjacency_" ,[](deUint64 vertexCount) { return vertexCount - 3u; } ,[](deUint64 primCount) { return primCount + 3u; }, } },
146 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY , { 3, "triangle_list_with_adjacency_" ,[](deUint64 vertexCount) { return vertexCount / 6u; } ,[](deUint64 primCount) { return primCount * 6u; }, } },
147 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY , { 3, "triangle_strip_with_adjacency_" ,[](deUint64 vertexCount) { return (vertexCount - 4u) / 2u; } ,[](deUint64 primCount) { return primCount * 2u + 4u; }, } },
148 { VK_PRIMITIVE_TOPOLOGY_PATCH_LIST , { 3, "patch_list_" ,[](deUint64 vertexCount) { return vertexCount / 3u; } ,[](deUint64 primCount) { return primCount * 3u; }, } },
149 };
150
151 struct TransformFeedbackQuery
152 {
153 deUint32 written;
154 deUint32 attempts;
155 };
156
157 const deUint32 MINIMUM_TF_BUFFER_SIZE = (1<<27);
158 const deUint32 IMAGE_SIZE = 64u;
159
160 template<typename T>
makeSharedPtr(Move<T> move)161 inline SharedPtr<Unique<T> > makeSharedPtr(Move<T> move)
162 {
163 return SharedPtr<Unique<T> >(new Unique<T>(move));
164 }
165
166 template<typename T>
getInvalidatedHostPtr(const DeviceInterface& vk, const VkDevice device, Allocation& bufAlloc)167 const T* getInvalidatedHostPtr (const DeviceInterface& vk, const VkDevice device, Allocation& bufAlloc)
168 {
169 invalidateAlloc(vk, device, bufAlloc);
170
171 return static_cast<T*>(bufAlloc.getHostPtr());
172 }
173
makePipelineLayout(const DeviceInterface& vk, const VkDevice device, const uint32_t pcSize = sizeof(uint32_t))174 Move<VkPipelineLayout> makePipelineLayout (const DeviceInterface& vk,
175 const VkDevice device,
176 const uint32_t pcSize = sizeof(uint32_t))
177 {
178 const VkPushConstantRange pushConstantRanges =
179 {
180 VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlags stageFlags;
181 0u, // deUint32 offset;
182 pcSize, // deUint32 size;
183 };
184 const VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo =
185 {
186 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
187 DE_NULL, // const void* pNext;
188 (VkPipelineLayoutCreateFlags)0, // VkPipelineLayoutCreateFlags flags;
189 0u, // deUint32 setLayoutCount;
190 DE_NULL, // const VkDescriptorSetLayout* pSetLayouts;
191 1u, // deUint32 pushConstantRangeCount;
192 &pushConstantRanges, // const VkPushConstantRange* pPushConstantRanges;
193 };
194 return createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
195 }
196
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)197 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface& vk,
198 const VkDevice device,
199 const VkPipelineLayout pipelineLayout,
200 const VkRenderPass renderPass,
201 const VkShaderModule vertexModule,
202 const VkShaderModule tessellationControlModule,
203 const VkShaderModule tessellationEvalModule,
204 const VkShaderModule geometryModule,
205 const VkShaderModule fragmentModule,
206 const VkExtent2D renderSize,
207 const deUint32 subpass,
208 const deUint32* rasterizationStreamPtr = DE_NULL,
209 const VkPrimitiveTopology topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST,
210 const bool inputVertices = false,
211 const bool depthClipControl = false)
212 {
213 VkViewport viewport = makeViewport(renderSize);
214 VkRect2D scissor = makeRect2D(renderSize);
215
216 const VkPipelineViewportDepthClipControlCreateInfoEXT depthClipControlCreateInfo =
217 {
218 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_DEPTH_CLIP_CONTROL_CREATE_INFO_EXT, // VkStructureType sType;
219 DE_NULL, // const void* pNext;
220 VK_TRUE, // VkBool32 negativeOneToOne;
221 };
222
223 const VkPipelineViewportStateCreateInfo viewportStateCreateInfo =
224 {
225 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType
226 depthClipControl ? &depthClipControlCreateInfo : DE_NULL, // const void* pNext
227 (VkPipelineViewportStateCreateFlags)0, // VkPipelineViewportStateCreateFlags flags
228 1u, // deUint32 viewportCount
229 &viewport, // const VkViewport* pViewports
230 1u, // deUint32 scissorCount
231 &scissor // const VkRect2D* pScissors
232 };
233
234 const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo =
235 {
236 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType
237 DE_NULL, // const void* pNext
238 0u, // VkPipelineInputAssemblyStateCreateFlags flags
239 topology, // VkPrimitiveTopology topology
240 VK_FALSE // VkBool32 primitiveRestartEnable
241 };
242
243 const VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo =
244 {
245 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType
246 DE_NULL, // const void* pNext
247 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags
248 0u, // deUint32 vertexBindingDescriptionCount
249 DE_NULL, // const VkVertexInputBindingDescription* pVertexBindingDescriptions
250 0u, // deUint32 vertexAttributeDescriptionCount
251 DE_NULL, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions
252 };
253
254 const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfoPtr = (inputVertices) ? DE_NULL : &vertexInputStateCreateInfo;
255 const VkBool32 disableRasterization = (fragmentModule == DE_NULL);
256 const deUint32 rasterizationStream = (rasterizationStreamPtr == DE_NULL) ? 0 : *rasterizationStreamPtr;
257
258 const VkPipelineRasterizationStateStreamCreateInfoEXT rasterizationStateStreamCreateInfo =
259 {
260 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_STREAM_CREATE_INFO_EXT, // VkStructureType sType;
261 DE_NULL, // const void* pNext;
262 0, // VkPipelineRasterizationStateStreamCreateFlagsEXT flags;
263 rasterizationStream // deUint32 rasterizationStream;
264 };
265
266 const VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo =
267 {
268 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType
269 &rasterizationStateStreamCreateInfo, // const void* pNext
270 0u, // VkPipelineRasterizationStateCreateFlags flags
271 VK_FALSE, // VkBool32 depthClampEnable
272 disableRasterization, // VkBool32 rasterizerDiscardEnable
273 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode
274 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode
275 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace
276 VK_FALSE, // VkBool32 depthBiasEnable
277 0.0f, // float depthBiasConstantFactor
278 0.0f, // float depthBiasClamp
279 0.0f, // float depthBiasSlopeFactor
280 1.0f // float lineWidth
281 };
282
283 const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfoPtr = (rasterizationStreamPtr == DE_NULL) ? DE_NULL : &rasterizationStateCreateInfo;
284
285 const VkPipelineTessellationStateCreateInfo tessStateCreateInfo =
286 {
287 VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, // VkStructureType sType
288 DE_NULL, // const void* pNext
289 0u, // VkPipelineTessellationStateCreateFlags flags
290 3u // deUint32 patchControlPoints
291 };
292
293 return makeGraphicsPipeline(vk, // const DeviceInterface& vk
294 device, // const VkDevice device
295 pipelineLayout, // const VkPipelineLayout pipelineLayout
296 vertexModule, // const VkShaderModule vertexShaderModule
297 tessellationControlModule, // const VkShaderModule tessellationControlModule
298 tessellationEvalModule, // const VkShaderModule tessellationEvalModule
299 geometryModule, // const VkShaderModule geometryShaderModule
300 fragmentModule, // const VkShaderModule fragmentShaderModule
301 renderPass, // const VkRenderPass renderPass
302 subpass, // const deUint32 subpass
303 vertexInputStateCreateInfoPtr, // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo
304 &inputAssemblyStateCreateInfo, // const VkPipelineInputAssemblyStateCreateInfo* inputAssemblyStateCreateInfo
305 &tessStateCreateInfo, // const VkPipelineTessellationStateCreateInfo* tessStateCreateInfo
306 &viewportStateCreateInfo, // const VkPipelineViewportStateCreateInfo* viewportStateCreateInfo
307 rasterizationStateCreateInfoPtr); // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
308 }
309
makeImageCreateInfo(const VkImageCreateFlags flags, const VkImageType type, const VkFormat format, const VkExtent2D size, const deUint32 numLayers, const VkImageUsageFlags usage)310 VkImageCreateInfo makeImageCreateInfo (const VkImageCreateFlags flags, const VkImageType type, const VkFormat format, const VkExtent2D size, const deUint32 numLayers, const VkImageUsageFlags usage)
311 {
312 const VkExtent3D extent = { size.width, size.height, 1u };
313 const VkImageCreateInfo imageParams =
314 {
315 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
316 DE_NULL, // const void* pNext;
317 flags, // VkImageCreateFlags flags;
318 type, // VkImageType imageType;
319 format, // VkFormat format;
320 extent, // VkExtent3D extent;
321 1u, // deUint32 mipLevels;
322 numLayers, // deUint32 arrayLayers;
323 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
324 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
325 usage, // VkImageUsageFlags usage;
326 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
327 0u, // deUint32 queueFamilyIndexCount;
328 DE_NULL, // const deUint32* pQueueFamilyIndices;
329 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
330 };
331 return imageParams;
332 }
333
makeCustomRenderPass(const DeviceInterface& vk, const VkDevice device, const VkFormat format = VK_FORMAT_UNDEFINED)334 Move<VkRenderPass> makeCustomRenderPass (const DeviceInterface& vk,
335 const VkDevice device,
336 const VkFormat format = VK_FORMAT_UNDEFINED)
337 {
338 std::vector<VkSubpassDescription> subpassDescriptions;
339 std::vector<VkSubpassDependency> subpassDependencies;
340 const bool hasColorAtt = (format != VK_FORMAT_UNDEFINED);
341
342 std::vector<VkAttachmentDescription> attachmentDescs;
343 std::vector<VkAttachmentReference> attachmentRefs;
344
345 if (hasColorAtt)
346 {
347 attachmentDescs.push_back(makeAttachmentDescription(
348 0u,
349 format,
350 VK_SAMPLE_COUNT_1_BIT,
351 VK_ATTACHMENT_LOAD_OP_CLEAR,
352 VK_ATTACHMENT_STORE_OP_STORE,
353 VK_ATTACHMENT_LOAD_OP_DONT_CARE,
354 VK_ATTACHMENT_STORE_OP_DONT_CARE,
355 VK_IMAGE_LAYOUT_UNDEFINED,
356 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
357 attachmentRefs.push_back(makeAttachmentReference(0u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
358 }
359
360 const VkSubpassDescription description =
361 {
362 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags;
363 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
364 0u, // deUint32 inputAttachmentCount;
365 nullptr, // const VkAttachmentReference* pInputAttachments;
366 de::sizeU32(attachmentRefs), // deUint32 colorAttachmentCount;
367 de::dataOrNull(attachmentRefs), // const VkAttachmentReference* pColorAttachments;
368 nullptr, // const VkAttachmentReference* pResolveAttachments;
369 nullptr, // const VkAttachmentReference* pDepthStencilAttachment;
370 0u, // deUint32 preserveAttachmentCount;
371 nullptr, // const deUint32* pPreserveAttachments;
372 };
373 subpassDescriptions.push_back(description);
374
375 const VkSubpassDependency dependency =
376 {
377 0u, // deUint32 srcSubpass;
378 0u, // deUint32 dstSubpass;
379 VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, // VkPipelineStageFlags srcStageMask;
380 VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, // VkPipelineStageFlags dstStageMask;
381 VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT, // VkAccessFlags srcAccessMask;
382 VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT, // VkAccessFlags dstAccessMask;
383 0u // VkDependencyFlags dependencyFlags;
384 };
385 subpassDependencies.push_back(dependency);
386
387 const VkRenderPassCreateInfo renderPassInfo =
388 {
389 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
390 nullptr, // const void* pNext;
391 static_cast<VkRenderPassCreateFlags>(0u), // VkRenderPassCreateFlags flags;
392 de::sizeU32(attachmentDescs), // deUint32 attachmentCount;
393 de::dataOrNull(attachmentDescs), // const VkAttachmentDescription* pAttachments;
394 de::sizeU32(subpassDescriptions), // deUint32 subpassCount;
395 de::dataOrNull(subpassDescriptions), // const VkSubpassDescription* pSubpasses;
396 de::sizeU32(subpassDependencies), // deUint32 dependencyCount;
397 de::dataOrNull(subpassDependencies), // const VkSubpassDependency* pDependencies;
398 };
399
400 return createRenderPass(vk, device, &renderPassInfo);
401 }
402
makeImageMemoryBarrier(const VkAccessFlags srcAccessMask, const VkAccessFlags dstAccessMask, const VkImageLayout oldLayout, const VkImageLayout newLayout, const VkImage image, const VkImageSubresourceRange subresourceRange)403 VkImageMemoryBarrier makeImageMemoryBarrier (const VkAccessFlags srcAccessMask,
404 const VkAccessFlags dstAccessMask,
405 const VkImageLayout oldLayout,
406 const VkImageLayout newLayout,
407 const VkImage image,
408 const VkImageSubresourceRange subresourceRange)
409 {
410 const VkImageMemoryBarrier barrier =
411 {
412 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
413 DE_NULL, // const void* pNext;
414 srcAccessMask, // VkAccessFlags outputMask;
415 dstAccessMask, // VkAccessFlags inputMask;
416 oldLayout, // VkImageLayout oldLayout;
417 newLayout, // VkImageLayout newLayout;
418 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
419 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
420 image, // VkImage image;
421 subresourceRange, // VkImageSubresourceRange subresourceRange;
422 };
423 return barrier;
424 }
425
makeBufferMemoryBarrier(const VkAccessFlags srcAccessMask, const VkAccessFlags dstAccessMask, const VkBuffer buffer, const VkDeviceSize offset, const VkDeviceSize bufferSizeBytes)426 VkBufferMemoryBarrier makeBufferMemoryBarrier (const VkAccessFlags srcAccessMask,
427 const VkAccessFlags dstAccessMask,
428 const VkBuffer buffer,
429 const VkDeviceSize offset,
430 const VkDeviceSize bufferSizeBytes)
431 {
432 const VkBufferMemoryBarrier barrier =
433 {
434 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
435 DE_NULL, // const void* pNext;
436 srcAccessMask, // VkAccessFlags srcAccessMask;
437 dstAccessMask, // VkAccessFlags dstAccessMask;
438 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
439 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
440 buffer, // VkBuffer buffer;
441 offset, // VkDeviceSize offset;
442 bufferSizeBytes, // VkDeviceSize size;
443 };
444 return barrier;
445 }
446
makeMemoryBarrier(const VkAccessFlags srcAccessMask, const VkAccessFlags dstAccessMask)447 VkMemoryBarrier makeMemoryBarrier (const VkAccessFlags srcAccessMask,
448 const VkAccessFlags dstAccessMask)
449 {
450 const VkMemoryBarrier barrier =
451 {
452 VK_STRUCTURE_TYPE_MEMORY_BARRIER, // VkStructureType sType;
453 DE_NULL, // const void* pNext;
454 srcAccessMask, // VkAccessFlags outputMask;
455 dstAccessMask, // VkAccessFlags inputMask;
456 };
457 return barrier;
458 }
459
makeQueryPoolCreateInfo(const deUint32 queryCountersNumber)460 VkQueryPoolCreateInfo makeQueryPoolCreateInfo (const deUint32 queryCountersNumber)
461 {
462 const VkQueryPoolCreateInfo queryPoolCreateInfo =
463 {
464 VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, // VkStructureType sType;
465 DE_NULL, // const void* pNext;
466 (VkQueryPoolCreateFlags)0, // VkQueryPoolCreateFlags flags;
467 VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT, // VkQueryType queryType;
468 queryCountersNumber, // deUint32 queryCount;
469 0u, // VkQueryPipelineStatisticFlags pipelineStatistics;
470 };
471
472 return queryPoolCreateInfo;
473 }
474
fillBuffer(const DeviceInterface& vk, const VkDevice device, Allocation& bufferAlloc, VkDeviceSize bufferSize, const void* data, const VkDeviceSize dataSize)475 void fillBuffer (const DeviceInterface& vk, const VkDevice device, Allocation& bufferAlloc, VkDeviceSize bufferSize, const void* data, const VkDeviceSize dataSize)
476 {
477 const VkMappedMemoryRange memRange =
478 {
479 VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType;
480 DE_NULL, // const void* pNext;
481 bufferAlloc.getMemory(), // VkDeviceMemory memory;
482 bufferAlloc.getOffset(), // VkDeviceSize offset;
483 VK_WHOLE_SIZE // VkDeviceSize size;
484 };
485 std::vector<deUint8> dataVec (static_cast<deUint32>(bufferSize), 0u);
486
487 DE_ASSERT(bufferSize >= dataSize);
488
489 deMemcpy(&dataVec[0], data, static_cast<deUint32>(dataSize));
490
491 deMemcpy(bufferAlloc.getHostPtr(), &dataVec[0], dataVec.size());
492 VK_CHECK(vk.flushMappedMemoryRanges(device, 1u, &memRange));
493 }
494
destripedLineCount(const std::vector<deUint32>& lineStripeSizesList)495 deUint32 destripedLineCount (const std::vector<deUint32>& lineStripeSizesList)
496 {
497 deUint32 result = 0;
498
499 DE_ASSERT(!lineStripeSizesList.empty());
500
501 for (auto x : lineStripeSizesList)
502 result += x > 1 ? x - 1 : 0;
503
504 return result;
505 }
506
destripedTriangleCount(const std::vector<deUint32>& triangleStripeSizesList)507 deUint32 destripedTriangleCount (const std::vector<deUint32>& triangleStripeSizesList)
508 {
509 deUint32 result = 0;
510
511 DE_ASSERT(!triangleStripeSizesList.empty());
512
513 for (auto x : triangleStripeSizesList)
514 result += x > 2 ? x - 2 : 0;
515
516 return result;
517 }
518
519 class TransformFeedbackTestInstance : public TestInstance
520 {
521 public:
522 TransformFeedbackTestInstance (Context& context, const TestParameters& parameters);
523 protected:
524 void validateLimits ();
525 std::vector<VkDeviceSize> generateSizesList (const size_t bufBytes, const size_t chunkCount);
526 std::vector<VkDeviceSize> generateOffsetsList (const std::vector<VkDeviceSize>& sizesList);
527 void verifyTransformFeedbackBuffer (const MovePtr<Allocation>& bufAlloc,
528 const deUint32 bufBytes);
529
530 const VkExtent2D m_imageExtent2D;
531 const TestParameters m_parameters;
532 VkPhysicalDeviceTransformFeedbackPropertiesEXT m_transformFeedbackProperties;
533 de::Random m_rnd;
534 };
535
TransformFeedbackTestInstance(Context& context, const TestParameters& parameters)536 TransformFeedbackTestInstance::TransformFeedbackTestInstance (Context& context, const TestParameters& parameters)
537 : TestInstance (context)
538 , m_imageExtent2D (makeExtent2D(IMAGE_SIZE, IMAGE_SIZE))
539 , m_parameters (parameters)
540 , m_rnd (context.getTestContext().getCommandLine().getBaseSeed())
541 {
542 VkPhysicalDeviceProperties2 deviceProperties2;
543
544 deMemset(&deviceProperties2, 0, sizeof(deviceProperties2));
545 deMemset(&m_transformFeedbackProperties, 0, sizeof(m_transformFeedbackProperties));
546
547 deviceProperties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
548 deviceProperties2.pNext = &m_transformFeedbackProperties;
549
550 m_transformFeedbackProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT;
551 m_transformFeedbackProperties.pNext = DE_NULL;
552
553 context.getInstanceInterface().getPhysicalDeviceProperties2(context.getPhysicalDevice(), &deviceProperties2);
554
555 validateLimits();
556 }
557
validateLimits()558 void TransformFeedbackTestInstance::validateLimits ()
559 {
560 VALIDATE_MINIMUM(m_transformFeedbackProperties.maxTransformFeedbackBuffers, 1);
561 VALIDATE_MINIMUM(m_transformFeedbackProperties.maxTransformFeedbackBufferSize, MINIMUM_TF_BUFFER_SIZE);
562 VALIDATE_MINIMUM(m_transformFeedbackProperties.maxTransformFeedbackStreamDataSize, 512);
563 VALIDATE_MINIMUM(m_transformFeedbackProperties.maxTransformFeedbackBufferDataSize, 512);
564 VALIDATE_MINIMUM(m_transformFeedbackProperties.maxTransformFeedbackBufferDataStride, 512);
565
566 VALIDATE_BOOL(m_transformFeedbackProperties.transformFeedbackQueries);
567 VALIDATE_BOOL(m_transformFeedbackProperties.transformFeedbackStreamsLinesTriangles);
568 VALIDATE_BOOL(m_transformFeedbackProperties.transformFeedbackRasterizationStreamSelect);
569 VALIDATE_BOOL(m_transformFeedbackProperties.transformFeedbackDraw);
570 }
571
generateSizesList(const size_t bufBytes, const size_t chunkCount)572 std::vector<VkDeviceSize> TransformFeedbackTestInstance::generateSizesList (const size_t bufBytes, const size_t chunkCount)
573 {
574 const int minChunkSlot = static_cast<int>(1);
575 const int maxChunkSlot = static_cast<int>(bufBytes / sizeof(deUint32));
576 int prevOffsetSlot = 0;
577 std::map<int, bool> offsetsSet;
578 std::vector<VkDeviceSize> result;
579
580 DE_ASSERT(bufBytes <= MINIMUM_TF_BUFFER_SIZE);
581 DE_ASSERT(bufBytes % sizeof(deUint32) == 0);
582 DE_ASSERT(minChunkSlot <= maxChunkSlot);
583 DE_ASSERT(chunkCount > 0);
584 // To be effective this algorithm requires that chunkCount is much less than amount of chunks possible
585 DE_ASSERT(8 * chunkCount <= static_cast<size_t>(maxChunkSlot));
586
587 offsetsSet[0] = true;
588
589 // Create a list of unique offsets first
590 for (size_t chunkNdx = 1; chunkNdx < chunkCount; ++chunkNdx)
591 {
592 int chunkSlot;
593
594 do
595 {
596 chunkSlot = m_rnd.getInt(minChunkSlot, maxChunkSlot - 1);
597 } while (offsetsSet.find(chunkSlot) != offsetsSet.end());
598
599 offsetsSet[chunkSlot] = true;
600 }
601 offsetsSet[maxChunkSlot] = true;
602
603 // Calculate sizes of offsets list
604 result.reserve(chunkCount);
605 for (std::map<int, bool>::iterator mapIt = offsetsSet.begin(); mapIt != offsetsSet.end(); ++mapIt)
606 {
607 const int offsetSlot = mapIt->first;
608
609 if (offsetSlot == 0)
610 continue;
611
612 DE_ASSERT(prevOffsetSlot < offsetSlot && offsetSlot > 0);
613
614 result.push_back(static_cast<VkDeviceSize>(static_cast<size_t>(offsetSlot - prevOffsetSlot) * sizeof(deUint32)));
615
616 prevOffsetSlot = offsetSlot;
617 }
618
619 DE_ASSERT(result.size() == chunkCount);
620
621 return result;
622 }
623
generateOffsetsList(const std::vector<VkDeviceSize>& sizesList)624 std::vector<VkDeviceSize> TransformFeedbackTestInstance::generateOffsetsList (const std::vector<VkDeviceSize>& sizesList)
625 {
626 VkDeviceSize offset = 0ull;
627 std::vector<VkDeviceSize> result;
628
629 result.reserve(sizesList.size());
630
631 for (size_t chunkNdx = 0; chunkNdx < sizesList.size(); ++chunkNdx)
632 {
633 result.push_back(offset);
634
635 offset += sizesList[chunkNdx];
636 }
637
638 DE_ASSERT(sizesList.size() == result.size());
639
640 return result;
641 }
642
verifyTransformFeedbackBuffer(const MovePtr<Allocation>& bufAlloc, const deUint32 bufBytes)643 void TransformFeedbackTestInstance::verifyTransformFeedbackBuffer (const MovePtr<Allocation>& bufAlloc,
644 const deUint32 bufBytes)
645 {
646 const DeviceInterface& vk = m_context.getDeviceInterface();
647 const VkDevice device = m_context.getDevice();
648 const deUint32 numPoints = static_cast<deUint32>(bufBytes / sizeof(deUint32));
649 const deUint32* tfData = getInvalidatedHostPtr<deUint32>(vk, device, *bufAlloc);
650
651 for (deUint32 i = 0; i < numPoints; ++i)
652 if (tfData[i] != i)
653 TCU_FAIL(std::string("Failed at item ") + de::toString(i) + " received:" + de::toString(tfData[i]) + " expected:" + de::toString(i));
654 }
655
656 class TransformFeedbackBasicTestInstance : public TransformFeedbackTestInstance
657 {
658 public:
659 TransformFeedbackBasicTestInstance (Context& context, const TestParameters& parameters);
660
661 protected:
662 tcu::TestStatus iterate (void);
663 };
664
TransformFeedbackBasicTestInstance(Context& context, const TestParameters& parameters)665 TransformFeedbackBasicTestInstance::TransformFeedbackBasicTestInstance (Context& context, const TestParameters& parameters)
666 : TransformFeedbackTestInstance (context, parameters)
667 {
668 }
669
iterate(void)670 tcu::TestStatus TransformFeedbackBasicTestInstance::iterate (void)
671 {
672 const DeviceInterface& vk = m_context.getDeviceInterface();
673 const VkDevice device = m_context.getDevice();
674 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
675 const VkQueue queue = m_context.getUniversalQueue();
676 Allocator& allocator = m_context.getDefaultAllocator();
677
678 const Unique<VkShaderModule> vertexModule (createShaderModule (vk, device, m_context.getBinaryCollection().get("vert"), 0u));
679 const Unique<VkRenderPass> renderPass (makeRenderPass (vk, device, VK_FORMAT_UNDEFINED));
680 const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, 0u, DE_NULL, m_imageExtent2D.width, m_imageExtent2D.height));
681 const Unique<VkPipelineLayout> pipelineLayout (TransformFeedback::makePipelineLayout (vk, device));
682 const Unique<VkPipeline> pipeline (makeGraphicsPipeline (vk, device, *pipelineLayout, *renderPass, *vertexModule, DE_NULL, DE_NULL, DE_NULL, DE_NULL, m_imageExtent2D, 0u, &m_parameters.streamId));
683 const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
684 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
685
686 const VkBufferCreateInfo tfBufCreateInfo = makeBufferCreateInfo(m_parameters.bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT);
687 const Move<VkBuffer> tfBuf = createBuffer(vk, device, &tfBufCreateInfo);
688 const MovePtr<Allocation> tfBufAllocation = allocator.allocate(getBufferMemoryRequirements(vk, device, *tfBuf), MemoryRequirement::HostVisible);
689 const VkMemoryBarrier tfMemoryBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT, VK_ACCESS_HOST_READ_BIT);
690 const std::vector<VkDeviceSize> tfBufBindingSizes = generateSizesList(m_parameters.bufferSize, m_parameters.partCount);
691 const std::vector<VkDeviceSize> tfBufBindingOffsets = generateOffsetsList(tfBufBindingSizes);
692
693 VK_CHECK(vk.bindBufferMemory(device, *tfBuf, tfBufAllocation->getMemory(), tfBufAllocation->getOffset()));
694
695 beginCommandBuffer(vk, *cmdBuffer);
696 {
697 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
698 {
699 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
700
701 for (deUint32 drawNdx = 0; drawNdx < m_parameters.partCount; ++drawNdx)
702 {
703 const deUint32 startValue = static_cast<deUint32>(tfBufBindingOffsets[drawNdx] / sizeof(deUint32));
704 const deUint32 numPoints = static_cast<deUint32>(tfBufBindingSizes[drawNdx] / sizeof(deUint32));
705
706 vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0, 1, &*tfBuf, &tfBufBindingOffsets[drawNdx], &tfBufBindingSizes[drawNdx]);
707
708 vk.cmdPushConstants(*cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0u, sizeof(startValue), &startValue);
709
710 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
711 {
712 vk.cmdDraw(*cmdBuffer, numPoints, 1u, 0u, 0u);
713 }
714 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
715 }
716 }
717 endRenderPass(vk, *cmdBuffer);
718
719 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &tfMemoryBarrier, 0u, DE_NULL, 0u, DE_NULL);
720 }
721 endCommandBuffer(vk, *cmdBuffer);
722 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
723
724 verifyTransformFeedbackBuffer(tfBufAllocation, m_parameters.bufferSize);
725
726 return tcu::TestStatus::pass("Pass");
727 }
728
729 class TransformFeedbackResumeTestInstance : public TransformFeedbackTestInstance
730 {
731 public:
732 TransformFeedbackResumeTestInstance (Context& context, const TestParameters& parameters);
733
734 protected:
735 tcu::TestStatus iterate (void);
736 };
737
TransformFeedbackResumeTestInstance(Context& context, const TestParameters& parameters)738 TransformFeedbackResumeTestInstance::TransformFeedbackResumeTestInstance (Context& context, const TestParameters& parameters)
739 : TransformFeedbackTestInstance (context, parameters)
740 {
741 }
742
iterate(void)743 tcu::TestStatus TransformFeedbackResumeTestInstance::iterate (void)
744 {
745 const DeviceInterface& vk = m_context.getDeviceInterface();
746 const VkDevice device = m_context.getDevice();
747 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
748 const VkQueue queue = m_context.getUniversalQueue();
749 Allocator& allocator = m_context.getDefaultAllocator();
750
751 const Unique<VkShaderModule> vertexModule (createShaderModule (vk, device, m_context.getBinaryCollection().get("vert"), 0u));
752 const Unique<VkRenderPass> renderPass (makeRenderPass (vk, device, VK_FORMAT_UNDEFINED));
753 const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, 0u, DE_NULL, m_imageExtent2D.width, m_imageExtent2D.height));
754 const Unique<VkPipelineLayout> pipelineLayout (TransformFeedback::makePipelineLayout (vk, device));
755 const Unique<VkPipeline> pipeline (makeGraphicsPipeline (vk, device, *pipelineLayout, *renderPass, *vertexModule, DE_NULL, DE_NULL, DE_NULL, DE_NULL, m_imageExtent2D, 0u, &m_parameters.streamId));
756
757 const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
758 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
759
760 VkBufferCreateInfo tfBufCreateInfo = makeBufferCreateInfo(m_parameters.bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT);
761
762 #ifndef CTS_USES_VULKANSC
763 vk::VkBufferUsageFlags2CreateInfoKHR bufferUsageFlags2 = vk::initVulkanStructure();
764 if (m_parameters.useMaintenance5)
765 {
766 bufferUsageFlags2.usage = (VkBufferUsageFlagBits2KHR)tfBufCreateInfo.usage;
767 tfBufCreateInfo.pNext = &bufferUsageFlags2;
768 tfBufCreateInfo.usage = 0;
769 }
770 #endif // CTS_USES_VULKANSC
771
772 const Move<VkBuffer> tfBuf = createBuffer(vk, device, &tfBufCreateInfo);
773 const MovePtr<Allocation> tfBufAllocation = allocator.allocate(getBufferMemoryRequirements(vk, device, *tfBuf), MemoryRequirement::HostVisible);
774 const VkMemoryBarrier tfMemoryBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT, VK_ACCESS_HOST_READ_BIT);
775 const std::vector<VkDeviceSize> tfBufBindingSizes = std::vector<VkDeviceSize>(1, m_parameters.bufferSize);
776 const std::vector<VkDeviceSize> tfBufBindingOffsets = std::vector<VkDeviceSize>(1, 0ull);
777
778 const size_t tfcBufSize = 16 * sizeof(deUint32) * m_parameters.partCount;
779 VkBufferCreateInfo tfcBufCreateInfo = makeBufferCreateInfo(tfcBufSize, VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT);
780
781 #ifndef CTS_USES_VULKANSC
782 if (m_parameters.useMaintenance5)
783 {
784 bufferUsageFlags2.usage = (VkBufferUsageFlagBits2KHR)tfcBufCreateInfo.usage;
785 tfcBufCreateInfo.pNext = &bufferUsageFlags2;
786 tfcBufCreateInfo.usage = 0;
787 }
788 #endif // CTS_USES_VULKANSC
789
790 const Move<VkBuffer> tfcBuf = createBuffer(vk, device, &tfcBufCreateInfo);
791 const MovePtr<Allocation> tfcBufAllocation = allocator.allocate(getBufferMemoryRequirements(vk, device, *tfcBuf), MemoryRequirement::Any);
792 const std::vector<VkDeviceSize> tfcBufBindingOffsets = generateOffsetsList(generateSizesList(tfcBufSize, m_parameters.partCount));
793 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);
794
795 const std::vector<VkDeviceSize> chunkSizesList = generateSizesList(m_parameters.bufferSize, m_parameters.partCount);
796 const std::vector<VkDeviceSize> chunkOffsetsList = generateOffsetsList(chunkSizesList);
797
798 DE_ASSERT(tfBufBindingSizes.size() == 1);
799 DE_ASSERT(tfBufBindingOffsets.size() == 1);
800
801 VK_CHECK(vk.bindBufferMemory(device, *tfBuf, tfBufAllocation->getMemory(), tfBufAllocation->getOffset()));
802 VK_CHECK(vk.bindBufferMemory(device, *tfcBuf, tfcBufAllocation->getMemory(), tfcBufAllocation->getOffset()));
803
804 beginCommandBuffer(vk, *cmdBuffer);
805 {
806 for (size_t drawNdx = 0; drawNdx < m_parameters.partCount; ++drawNdx)
807 {
808 const deUint32 startValue = static_cast<deUint32>(chunkOffsetsList[drawNdx] / sizeof(deUint32));
809 const deUint32 numPoints = static_cast<deUint32>(chunkSizesList[drawNdx] / sizeof(deUint32));
810 const deUint32 countBuffersCount = (drawNdx == 0) ? 0 : 1;
811
812 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
813 {
814
815 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
816
817 vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0, 1, &*tfBuf, &tfBufBindingOffsets[0], &tfBufBindingSizes[0]);
818
819 vk.cmdPushConstants(*cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0u, sizeof(startValue), &startValue);
820
821 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, countBuffersCount, (drawNdx == 0) ? DE_NULL : &*tfcBuf, (drawNdx == 0) ? DE_NULL : &tfcBufBindingOffsets[drawNdx - 1]);
822 {
823 vk.cmdDraw(*cmdBuffer, numPoints, 1u, 0u, 0u);
824 }
825 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 1, &*tfcBuf, &tfcBufBindingOffsets[drawNdx]);
826 }
827 endRenderPass(vk, *cmdBuffer);
828
829 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);
830 }
831
832 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &tfMemoryBarrier, 0u, DE_NULL, 0u, DE_NULL);
833 }
834 endCommandBuffer(vk, *cmdBuffer);
835 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
836
837 verifyTransformFeedbackBuffer(tfBufAllocation, m_parameters.bufferSize);
838
839 return tcu::TestStatus::pass("Pass");
840 }
841
842 class TransformFeedbackWindingOrderTestInstance : public TransformFeedbackTestInstance
843 {
844 public:
845 TransformFeedbackWindingOrderTestInstance(Context& context, const TestParameters& parameters);
846
847 protected:
848 struct TopologyParameters
849 {
850 // number of vertex in primitive; 2 for line, 3 for triangle
851 deUint32 vertexPerPrimitive;
852
853 // pointer to function calculating number of points that
854 // will be generated for given part count
855 std::function<deUint32(deUint32)> getNumGeneratedPoints;
856
857 // pointer to function generating expected values; parameter is
858 // primitive index, result array with expected data for primitive vertex
859 std::function<std::vector<deUint32>(deUint32)> getExpectedValuesForPrimitive;
860 };
861 typedef const std::map<VkPrimitiveTopology, TopologyParameters> TopologyParametersMap;
862
863 protected:
864 const TopologyParametersMap& getTopologyParametersMap (void);
865 tcu::TestStatus iterate (void);
866 void verifyTransformFeedbackBuffer (const MovePtr<Allocation>& bufAlloc,
867 const deUint32 bufBytes);
868
869 private:
870 TopologyParameters m_tParameters;
871 const bool m_requiresTesselationStage;
872 };
873
TransformFeedbackWindingOrderTestInstance(Context& context, const TestParameters& parameters)874 TransformFeedbackWindingOrderTestInstance::TransformFeedbackWindingOrderTestInstance(Context& context, const TestParameters& parameters)
875 : TransformFeedbackTestInstance (context, parameters)
876 , m_requiresTesselationStage(parameters.primTopology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST)
877 {
878 if (m_requiresTesselationStage && !context.getDeviceFeatures().tessellationShader)
879 throw tcu::NotSupportedError("Tessellation shader not supported");
880
881 TopologyParametersMap topologyParametersMap = getTopologyParametersMap();
882 DE_ASSERT(topologyParametersMap.find(parameters.primTopology) != topologyParametersMap.end());
883 m_tParameters = topologyParametersMap.at(parameters.primTopology);
884 }
885
getTopologyParametersMap(void)886 const TransformFeedbackWindingOrderTestInstance::TopologyParametersMap& TransformFeedbackWindingOrderTestInstance::getTopologyParametersMap(void)
887 {
888 static const TopologyParametersMap topologyParametersMap =
889 {
890 {
891 VK_PRIMITIVE_TOPOLOGY_POINT_LIST,
892 {
893 1u,
894 [](deUint32 partCount) { return partCount; },
895 [](deUint32 i) { return std::vector<deUint32>{ i, i + 1u }; }
896 }
897 },
898 {
899 VK_PRIMITIVE_TOPOLOGY_LINE_LIST,
900 {
901 2u,
902 [](deUint32 partCount) { return partCount; },
903 [](deUint32 i) { return std::vector<deUint32>{ 2 * i, 2 * i + 1u }; }
904 }
905 },
906 {
907 VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,
908 {
909 2u,
910 [](deUint32 partCount) { return 2u * (partCount - 1); },
911 [](deUint32 i) { return std::vector<deUint32>{ i, i + 1u }; }
912 }
913 },
914 {
915 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
916 {
917 3u,
918 [](deUint32 partCount) { return partCount; },
919 [](deUint32 i) { return std::vector<deUint32>{ 3 * i, 3 * i + 1u, 3 * i + 2u }; }
920 }
921 },
922 {
923 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
924 {
925 3u,
926 [](deUint32 partCount) { return 3u * (partCount - 2); },
927 [](deUint32 i)
928 {
929 const deUint32 iMod2 = i % 2;
930 return std::vector<deUint32>{ i, i + 1 + iMod2, i + 2 - iMod2 };
931 }
932 }
933 },
934 {
935 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,
936 {
937 3u,
938 [](deUint32 partCount) { return partCount; },
939 [](deUint32 i) { return std::vector<deUint32>{ i + 1, i + 2, 0 }; }
940 }
941 },
942 {
943 VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY,
944 {
945 2u,
946 [](deUint32 partCount) { return partCount / 4u; }, // note: this cant be replaced with partCount / 2 as for partCount=6 we will get 3 instead of 2
947 [](deUint32 i) { return std::vector<deUint32>{ i + 1u, i + 2u }; }
948 }
949 },
950 {
951 VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY,
952 {
953 2u,
954 [](deUint32 partCount) { return 2u * (partCount - 3u); },
955 [](deUint32 i) { return std::vector<deUint32>{ i + 1u, i + 2u }; }
956 }
957 },
958 {
959 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY,
960 {
961 3u,
962 [](deUint32 partCount) { return partCount / 2u; },
963 [](deUint32 i) { return std::vector<deUint32>{ 6 * i, 6 * i + 2u, 6 * i + 4u }; }
964 }
965 },
966 {
967 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY,
968 {
969 3u,
970 [](deUint32 partCount) { return 3u * (partCount / 2u - 2u); },
971 [](deUint32 i)
972 {
973 const bool even = (0 == i % 2);
974 if (even)
975 return std::vector<deUint32>{ 2 * i + 0, 2 * i + 2, 2 * i + 4 };
976 return std::vector<deUint32>{ 2 * i + 0, 2 * i + 4, 2 * i + 2 };
977 }
978 }
979 },
980 {
981 VK_PRIMITIVE_TOPOLOGY_PATCH_LIST,
982 {
983 9u,
984 [](deUint32 partCount) { return partCount * 3u; },
985 [](deUint32 i)
986 {
987 // we cant generate vertex numbers in tesselation evaluation shader;
988 // check if patch index is correct for every 9 generated vertex
989 return std::vector<deUint32>(9, i);
990 }
991 }
992 }
993 };
994
995 return topologyParametersMap;
996 }
997
iterate(void)998 tcu::TestStatus TransformFeedbackWindingOrderTestInstance::iterate (void)
999 {
1000 DE_ASSERT(m_parameters.partCount >= 6);
1001
1002 const DeviceInterface& vk = m_context.getDeviceInterface();
1003 const VkDevice device = m_context.getDevice();
1004 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1005 const VkQueue queue = m_context.getUniversalQueue();
1006 Allocator& allocator = m_context.getDefaultAllocator();
1007
1008 const Move<VkShaderModule> vertexModule(createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
1009 Move<VkShaderModule> tescModule;
1010 Move<VkShaderModule> teseModule;
1011 if (m_requiresTesselationStage)
1012 {
1013 tescModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("tesc"), 0u);
1014 teseModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("tese"), 0u);
1015 }
1016
1017 const Unique<VkRenderPass> renderPass (makeRenderPass (vk, device, VK_FORMAT_UNDEFINED));
1018 const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, 0u, DE_NULL, m_imageExtent2D.width, m_imageExtent2D.height));
1019 const Unique<VkPipelineLayout> pipelineLayout (TransformFeedback::makePipelineLayout (vk, device));
1020 const Unique<VkPipeline> pipeline (makeGraphicsPipeline (vk, device, *pipelineLayout, *renderPass,
1021 *vertexModule,
1022 m_requiresTesselationStage ? *tescModule : DE_NULL,
1023 m_requiresTesselationStage ? *teseModule : DE_NULL,
1024 DE_NULL,
1025 DE_NULL,
1026 m_imageExtent2D, 0u, DE_NULL, m_parameters.primTopology));
1027 const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1028 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1029 const VkDeviceSize bufferSize = m_tParameters.getNumGeneratedPoints (m_parameters.partCount) * sizeof(deUint32);
1030 const VkBufferCreateInfo tfBufCreateInfo = makeBufferCreateInfo (bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT);
1031 const Move<VkBuffer> tfBuf = createBuffer (vk, device, &tfBufCreateInfo);
1032 const MovePtr<Allocation> tfBufAllocation = allocator.allocate (getBufferMemoryRequirements(vk, device, *tfBuf), MemoryRequirement::HostVisible);
1033 const VkMemoryBarrier tfMemoryBarrier = makeMemoryBarrier (VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT, VK_ACCESS_HOST_READ_BIT);
1034 const VkDeviceSize tfBufBindingSize = bufferSize;
1035 const VkDeviceSize tfBufBindingOffset = 0u;
1036 const deUint32 startValue = 0u;
1037
1038 VK_CHECK(vk.bindBufferMemory(device, *tfBuf, tfBufAllocation->getMemory(), tfBufAllocation->getOffset()));
1039
1040 beginCommandBuffer(vk, *cmdBuffer);
1041 {
1042 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
1043 {
1044 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1045
1046 vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0, 1, &*tfBuf, &tfBufBindingOffset, &tfBufBindingSize);
1047
1048 vk.cmdPushConstants(*cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0u, sizeof(startValue), &startValue);
1049
1050 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1051 {
1052 vk.cmdDraw(*cmdBuffer, m_parameters.partCount, 1u, 0u, 0u);
1053 }
1054 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1055 }
1056 endRenderPass(vk, *cmdBuffer);
1057
1058 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &tfMemoryBarrier, 0u, DE_NULL, 0u, DE_NULL);
1059 }
1060 endCommandBuffer(vk, *cmdBuffer);
1061 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1062
1063 verifyTransformFeedbackBuffer(tfBufAllocation, static_cast<deUint32>(bufferSize));
1064
1065 return tcu::TestStatus::pass("Pass");
1066 }
1067
1068 template <typename T, int Size>
operator >(const tcu::Vector<T, Size>& a, const tcu::Vector<T, Size>& b)1069 bool operator>(const tcu::Vector<T, Size>& a, const tcu::Vector<T, Size>& b)
1070 {
1071 return tcu::boolAny(tcu::greaterThan(a, b));
1072 }
1073
1074 template <typename T, int Size>
elemAbsDiff(const tcu::Vector<T, Size>& a, const tcu::Vector<T, Size>& b)1075 tcu::Vector<T, Size> elemAbsDiff (const tcu::Vector<T, Size>& a, const tcu::Vector<T, Size>& b)
1076 {
1077 return tcu::absDiff(a, b);
1078 }
1079
elemAbsDiff(uint32_t a, uint32_t b)1080 uint32_t elemAbsDiff (uint32_t a, uint32_t b)
1081 {
1082 if (a > b)
1083 return a - b;
1084 return b - a;
1085 }
1086
1087 template <typename T>
verifyVertexDataWithWinding(const std::vector<T>& reference, const T* result, const size_t vertexCount, const size_t verticesPerPrimitive, const T& threshold)1088 std::vector<std::string> verifyVertexDataWithWinding (const std::vector<T>& reference, const T* result, const size_t vertexCount, const size_t verticesPerPrimitive, const T& threshold)
1089 {
1090 //DE_ASSERT(vertexCount % verticesPerPrimitive == 0);
1091 //DE_ASSERT(reference.size() == vertexCount);
1092 const size_t primitiveCount = vertexCount / verticesPerPrimitive;
1093
1094 std::vector<std::string> errors;
1095
1096 for (size_t primIdx = 0; primIdx < primitiveCount; ++primIdx)
1097 {
1098 const auto pastVertexCount = verticesPerPrimitive * primIdx;
1099 const T* resultPrim = result + pastVertexCount;
1100 const T* referencePrim = &reference.at(pastVertexCount);
1101 bool primitiveOK = false;
1102
1103 // Vertices must be in the same winding order, but the first vertex may vary. We test every rotation below.
1104 // E.g. vertices 0 1 2 could be stored as 0 1 2, 2 0 1 or 1 2 0.
1105 for (size_t firstVertex = 0; firstVertex < verticesPerPrimitive; ++firstVertex)
1106 {
1107 bool match = true;
1108 for (size_t vertIdx = 0; vertIdx < verticesPerPrimitive; ++vertIdx)
1109 {
1110 const auto& refVertex = referencePrim[(firstVertex + vertIdx) % verticesPerPrimitive]; // Rotation.
1111 const auto& resVertex = resultPrim[vertIdx];
1112
1113 if (elemAbsDiff(refVertex, resVertex) > threshold)
1114 {
1115 match = false;
1116 break;
1117 }
1118 }
1119
1120 if (match)
1121 {
1122 primitiveOK = true;
1123 break;
1124 }
1125 }
1126
1127 if (!primitiveOK)
1128 {
1129 // Log error.
1130 std::ostringstream err;
1131 err << "Primitive " << primIdx << " failed: expected rotation of [";
1132 for (size_t i = 0; i < verticesPerPrimitive; ++i)
1133 err << ((i > 0) ? ", " : "") << referencePrim[i];
1134 err << "] but found [";
1135 for (size_t i = 0; i < verticesPerPrimitive; ++i)
1136 err << ((i > 0) ? ", " : "") << resultPrim[i];
1137 err << "]; threshold: " << threshold;
1138 errors.push_back(err.str());
1139 }
1140 }
1141
1142 return errors;
1143 }
1144
checkErrorVec(tcu::TestLog& log, const std::vector<std::string>& errors)1145 void checkErrorVec (tcu::TestLog& log, const std::vector<std::string>& errors)
1146 {
1147 if (!errors.empty())
1148 {
1149 for (const auto& err : errors)
1150 log << tcu::TestLog::Message << err << tcu::TestLog::EndMessage;
1151 TCU_FAIL("Vertex data verification failed; check log for details");
1152 }
1153 }
1154
verifyTransformFeedbackBuffer(const MovePtr<Allocation>& bufAlloc, const deUint32 bufBytes)1155 void TransformFeedbackWindingOrderTestInstance::verifyTransformFeedbackBuffer (const MovePtr<Allocation>& bufAlloc,
1156 const deUint32 bufBytes)
1157 {
1158 const DeviceInterface& vk = m_context.getDeviceInterface();
1159 const VkDevice device = m_context.getDevice();
1160 const deUint32 numPoints = static_cast<deUint32>(bufBytes / sizeof(deUint32));
1161 const deUint32 vertexPerPrimitive = m_tParameters.vertexPerPrimitive;
1162 const deUint32 numPrimitives = numPoints / vertexPerPrimitive;
1163 const deUint32* tfData = getInvalidatedHostPtr<deUint32>(vk, device, *bufAlloc);
1164
1165 std::vector<uint32_t> referenceValues;
1166 referenceValues.reserve(numPrimitives * vertexPerPrimitive);
1167
1168 for (uint32_t primIdx = 0; primIdx < numPrimitives; ++primIdx)
1169 {
1170 const auto expectedValues = m_tParameters.getExpectedValuesForPrimitive(primIdx);
1171 for (const auto& value : expectedValues)
1172 referenceValues.push_back(value);
1173 }
1174
1175 const auto errors = verifyVertexDataWithWinding(referenceValues, tfData, numPoints, vertexPerPrimitive, 0u/*threshold*/);
1176 checkErrorVec(m_context.getTestContext().getLog(), errors);
1177 }
1178
1179 class TransformFeedbackBuiltinTestInstance : public TransformFeedbackTestInstance
1180 {
1181 public:
1182 TransformFeedbackBuiltinTestInstance (Context& context, const TestParameters& parameters);
1183
1184 protected:
1185 tcu::TestStatus iterate (void);
1186 void verifyTransformFeedbackBuffer (const MovePtr<Allocation>& bufAlloc, const VkDeviceSize offset, const deUint32 bufBytes);
1187 };
1188
TransformFeedbackBuiltinTestInstance(Context& context, const TestParameters& parameters)1189 TransformFeedbackBuiltinTestInstance::TransformFeedbackBuiltinTestInstance (Context& context, const TestParameters& parameters)
1190 : TransformFeedbackTestInstance (context, parameters)
1191 {
1192 const InstanceInterface& vki = m_context.getInstanceInterface();
1193 const VkPhysicalDevice physDevice = m_context.getPhysicalDevice();
1194 const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(vki, physDevice);
1195
1196 const deUint32 tfBuffersSupported = m_transformFeedbackProperties.maxTransformFeedbackBuffers;
1197 const deUint32 tfBuffersRequired = m_parameters.partCount;
1198
1199 if ((m_parameters.testType == TEST_TYPE_XFB_CLIPDISTANCE || m_parameters.testType == TEST_TYPE_XFB_CLIP_AND_CULL) && !features.shaderClipDistance)
1200 TCU_THROW(NotSupportedError, std::string("shaderClipDistance feature is not supported"));
1201 if ((m_parameters.testType == TEST_TYPE_XFB_CULLDISTANCE || m_parameters.testType == TEST_TYPE_XFB_CLIP_AND_CULL) && !features.shaderCullDistance)
1202 TCU_THROW(NotSupportedError, std::string("shaderCullDistance feature is not supported"));
1203 if (tfBuffersSupported < tfBuffersRequired)
1204 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBuffers=" + de::toString(tfBuffersSupported) + ", while test requires " + de::toString(tfBuffersRequired)).c_str());
1205 }
1206
verifyTransformFeedbackBuffer(const MovePtr<Allocation>& bufAlloc, const VkDeviceSize offset, const deUint32 bufBytes)1207 void TransformFeedbackBuiltinTestInstance::verifyTransformFeedbackBuffer (const MovePtr<Allocation>& bufAlloc, const VkDeviceSize offset, const deUint32 bufBytes)
1208 {
1209 const DeviceInterface& vk = m_context.getDeviceInterface();
1210 const VkDevice device = m_context.getDevice();
1211 const deUint32 numPoints = bufBytes / static_cast<deUint32>(sizeof(float));
1212 const deUint8* tfDataBytes = getInvalidatedHostPtr<deUint8>(vk, device, *bufAlloc);
1213 const float* tfData = (float*)&tfDataBytes[offset];
1214
1215 for (deUint32 i = 0; i < numPoints; ++i)
1216 {
1217 const deUint32 divisor = 32768u;
1218 const float epsilon = 1.0f / float(divisor);
1219 const float expected = float(i) / float(divisor);
1220
1221 if (deAbs(tfData[i] - expected) > epsilon)
1222 TCU_FAIL(std::string("Failed at item ") + de::toString(i) + " received:" + de::toString(tfData[i]) + " expected:" + de::toString(expected));
1223 }
1224 }
1225
iterate(void)1226 tcu::TestStatus TransformFeedbackBuiltinTestInstance::iterate (void)
1227 {
1228 const DeviceInterface& vk = m_context.getDeviceInterface();
1229 const VkDevice device = m_context.getDevice();
1230 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1231 const VkQueue queue = m_context.getUniversalQueue();
1232 Allocator& allocator = m_context.getDefaultAllocator();
1233
1234 const Unique<VkShaderModule> vertexModule (createShaderModule (vk, device, m_context.getBinaryCollection().get("vert"), 0u));
1235 const Unique<VkRenderPass> renderPass (makeRenderPass (vk, device, VK_FORMAT_UNDEFINED));
1236 const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, 0u, DE_NULL, m_imageExtent2D.width, m_imageExtent2D.height));
1237 const Unique<VkPipelineLayout> pipelineLayout (TransformFeedback::makePipelineLayout (vk, device));
1238 const Unique<VkPipeline> pipeline (makeGraphicsPipeline (vk, device, *pipelineLayout, *renderPass, *vertexModule, DE_NULL, DE_NULL, DE_NULL, DE_NULL, m_imageExtent2D, 0u, &m_parameters.streamId));
1239 const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1240 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1241
1242 const VkDeviceSize tfBufSize = m_parameters.bufferSize * m_parameters.partCount;
1243 const VkBufferCreateInfo tfBufCreateInfo = makeBufferCreateInfo(tfBufSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT);
1244 const Move<VkBuffer> tfBuf = createBuffer(vk, device, &tfBufCreateInfo);
1245 const std::vector<VkBuffer> tfBufArray = std::vector<VkBuffer>(m_parameters.partCount, *tfBuf);
1246 const MovePtr<Allocation> tfBufAllocation = allocator.allocate(getBufferMemoryRequirements(vk, device, *tfBuf), MemoryRequirement::HostVisible);
1247 const VkMemoryBarrier tfMemoryBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT, VK_ACCESS_HOST_READ_BIT);
1248 const std::vector<VkDeviceSize> tfBufBindingSizes = std::vector<VkDeviceSize>(m_parameters.partCount, m_parameters.bufferSize);
1249 const std::vector<VkDeviceSize> tfBufBindingOffsets = generateOffsetsList(tfBufBindingSizes);
1250 const deUint32 perVertexDataSize = (m_parameters.testType == TEST_TYPE_XFB_POINTSIZE) ? static_cast<deUint32>(sizeof(float))
1251 : (m_parameters.testType == TEST_TYPE_XFB_CLIPDISTANCE) ? static_cast<deUint32>(8u * sizeof(float))
1252 : (m_parameters.testType == TEST_TYPE_XFB_CULLDISTANCE) ? static_cast<deUint32>(8u * sizeof(float))
1253 : (m_parameters.testType == TEST_TYPE_XFB_CLIP_AND_CULL) ? static_cast<deUint32>(6u * sizeof(float))
1254 : 0u;
1255 const deUint32 numPoints = m_parameters.bufferSize / perVertexDataSize;
1256
1257 VK_CHECK(vk.bindBufferMemory(device, *tfBuf, tfBufAllocation->getMemory(), tfBufAllocation->getOffset()));
1258
1259 beginCommandBuffer(vk, *cmdBuffer);
1260 {
1261 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
1262 {
1263 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1264
1265 vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0, m_parameters.partCount, &tfBufArray[0], &tfBufBindingOffsets[0], &tfBufBindingSizes[0]);
1266
1267 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1268 {
1269 vk.cmdDraw(*cmdBuffer, numPoints, 1u, 0u, 0u);
1270 }
1271 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1272 }
1273 endRenderPass(vk, *cmdBuffer);
1274
1275 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &tfMemoryBarrier, 0u, DE_NULL, 0u, DE_NULL);
1276 }
1277 endCommandBuffer(vk, *cmdBuffer);
1278 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1279
1280 verifyTransformFeedbackBuffer(tfBufAllocation, tfBufBindingOffsets[m_parameters.partCount - 1], numPoints * perVertexDataSize);
1281
1282 return tcu::TestStatus::pass("Pass");
1283 }
1284
1285 class TransformFeedbackDepthClipControlTestInstance : public TransformFeedbackTestInstance
1286 {
1287 public:
1288 TransformFeedbackDepthClipControlTestInstance (Context& context, const TestParameters& parameters);
1289
1290 protected:
1291 tcu::TestStatus iterate (void);
1292 void verifyTransformFeedbackBuffer (const MovePtr<Allocation>& bufAlloc, const VkDeviceSize offset, const deUint32 bufBytes);
1293 };
1294
TransformFeedbackDepthClipControlTestInstance(Context& context, const TestParameters& parameters)1295 TransformFeedbackDepthClipControlTestInstance::TransformFeedbackDepthClipControlTestInstance (Context& context, const TestParameters& parameters)
1296 : TransformFeedbackTestInstance (context, parameters)
1297 {
1298 const InstanceInterface& vki = m_context.getInstanceInterface();
1299 const VkPhysicalDevice physDevice = m_context.getPhysicalDevice();
1300 const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(vki, physDevice);
1301
1302 const deUint32 tfBuffersSupported = m_transformFeedbackProperties.maxTransformFeedbackBuffers;
1303 const deUint32 tfBuffersRequired = m_parameters.partCount;
1304
1305 if (!context.isDeviceFunctionalitySupported("VK_EXT_depth_clip_control"))
1306 TCU_THROW(NotSupportedError, "VK_EXT_depth_clip_control is not supported");
1307
1308 if (parameters.testType == TEST_TYPE_DEPTH_CLIP_CONTROL_GEOMETRY && !features.geometryShader)
1309 TCU_THROW(NotSupportedError, "Geometry shader not supported");
1310
1311 if (parameters.testType == TEST_TYPE_DEPTH_CLIP_CONTROL_TESE && !features.tessellationShader)
1312 TCU_THROW(NotSupportedError, "Tessellation shader not supported");
1313
1314 if (tfBuffersSupported < tfBuffersRequired)
1315 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBuffers=" + de::toString(tfBuffersSupported) + ", while test requires " + de::toString(tfBuffersRequired)).c_str());
1316 }
1317
verifyTransformFeedbackBuffer(const MovePtr<Allocation>& bufAlloc, const VkDeviceSize offset, const deUint32 bufBytes)1318 void TransformFeedbackDepthClipControlTestInstance::verifyTransformFeedbackBuffer (const MovePtr<Allocation>& bufAlloc, const VkDeviceSize offset, const deUint32 bufBytes)
1319 {
1320 const DeviceInterface& vk = m_context.getDeviceInterface();
1321 const VkDevice device = m_context.getDevice();
1322 const deUint32 numVertices = bufBytes / static_cast<deUint32>(sizeof(float) * 4);
1323 const deUint8* tfDataBytes = getInvalidatedHostPtr<deUint8>(vk, device, *bufAlloc);
1324 const float* tfData = (float*)&tfDataBytes[offset];
1325 std::vector<float> result;
1326
1327 // We only care about the depth (z) value.
1328 for (deUint32 i = 0; i < numVertices; i++)
1329 result.push_back(tfData[i * 4 + 2]);
1330
1331 // Tessellation generates triangles whose vertex data might be written into
1332 // transform feedback buffer in a different order than generated by the vertex
1333 // shader. Sort the values here to allow comparison.
1334 if (m_parameters.testType == TEST_TYPE_DEPTH_CLIP_CONTROL_TESE)
1335 {
1336 std::sort(result.begin(), result.end());
1337 }
1338
1339 // Verify the vertex depth values match with the ones written by the shader.
1340 for (deUint32 i = 0; i < numVertices; i++)
1341 {
1342 const float expected = (float)i / 3.0f - 1.0f;
1343 const float epsilon = 0.0001f;
1344
1345 if (deAbs(result[i] - expected) > epsilon)
1346 TCU_FAIL(std::string("Failed at vertex ") + de::toString(i) + " depth. Received:" + de::toString(result[i]) + " expected:" + de::toString(expected));
1347 }
1348 }
1349
iterate(void)1350 tcu::TestStatus TransformFeedbackDepthClipControlTestInstance::iterate (void)
1351 {
1352 const DeviceInterface& vk = m_context.getDeviceInterface();
1353 const VkDevice device = m_context.getDevice();
1354 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1355 const VkQueue queue = m_context.getUniversalQueue();
1356 Allocator& allocator = m_context.getDefaultAllocator();
1357
1358 const Unique<VkShaderModule> vertexModule (createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
1359 Move<VkShaderModule> geomModule;
1360 Move<VkShaderModule> tescModule;
1361 Move<VkShaderModule> teseModule;
1362 const bool hasGeomShader = m_parameters.testType == TEST_TYPE_DEPTH_CLIP_CONTROL_GEOMETRY;
1363 const bool hasTessellation = m_parameters.testType == TEST_TYPE_DEPTH_CLIP_CONTROL_TESE;
1364
1365 if (hasGeomShader)
1366 geomModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("geom"), 0u);
1367
1368 if (hasTessellation)
1369 {
1370 tescModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("tesc"), 0u);
1371 teseModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("tese"), 0u);
1372 }
1373
1374 const Unique<VkRenderPass> renderPass (makeRenderPass(vk, device, VK_FORMAT_UNDEFINED));
1375 const Unique<VkFramebuffer> framebuffer (makeFramebuffer(vk, device, *renderPass, 0u, DE_NULL, m_imageExtent2D.width, m_imageExtent2D.height));
1376 const Unique<VkPipelineLayout> pipelineLayout (TransformFeedback::makePipelineLayout (vk, device));
1377 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));
1378 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1379 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1380 const VkDeviceSize tfBufSize = m_parameters.bufferSize * m_parameters.partCount;
1381 const VkBufferCreateInfo tfBufCreateInfo = makeBufferCreateInfo(tfBufSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT);
1382 const Move<VkBuffer> tfBuf = createBuffer(vk, device, &tfBufCreateInfo);
1383 const std::vector<VkBuffer> tfBufArray = std::vector<VkBuffer>(m_parameters.partCount, *tfBuf);
1384 const MovePtr<Allocation> tfBufAllocation = allocator.allocate(getBufferMemoryRequirements(vk, device, *tfBuf), MemoryRequirement::HostVisible);
1385 const VkMemoryBarrier tfMemoryBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT, VK_ACCESS_HOST_READ_BIT);
1386 const std::vector<VkDeviceSize> tfBufBindingSizes = std::vector<VkDeviceSize>(m_parameters.partCount, m_parameters.bufferSize);
1387 const std::vector<VkDeviceSize> tfBufBindingOffsets = generateOffsetsList(tfBufBindingSizes);
1388 const deUint32 perVertexDataSize = static_cast<deUint32>(4u * sizeof(float));
1389 const deUint32 numVertices = m_parameters.bufferSize / perVertexDataSize;
1390
1391 VK_CHECK(vk.bindBufferMemory(device, *tfBuf, tfBufAllocation->getMemory(), tfBufAllocation->getOffset()));
1392
1393 beginCommandBuffer(vk, *cmdBuffer);
1394 {
1395 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
1396 {
1397 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1398
1399 vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0, m_parameters.partCount, &tfBufArray[0], &tfBufBindingOffsets[0], &tfBufBindingSizes[0]);
1400
1401 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1402 {
1403 vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
1404 }
1405 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1406 }
1407 endRenderPass(vk, *cmdBuffer);
1408
1409 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &tfMemoryBarrier, 0u, DE_NULL, 0u, DE_NULL);
1410 }
1411 endCommandBuffer(vk, *cmdBuffer);
1412 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1413
1414 verifyTransformFeedbackBuffer(tfBufAllocation, tfBufBindingOffsets[m_parameters.partCount - 1], m_parameters.bufferSize);
1415
1416 return tcu::TestStatus::pass("Pass");
1417 }
1418
1419 class TransformFeedbackMultistreamTestInstance : public TransformFeedbackTestInstance
1420 {
1421 public:
1422 TransformFeedbackMultistreamTestInstance (Context& context, const TestParameters& parameters);
1423
1424 protected:
1425 std::vector<VkDeviceSize> generateSizesList (const size_t bufBytes, const size_t chunkCount);
1426 void verifyTransformFeedbackBuffer (const MovePtr<Allocation>& bufAlloc, const deUint32 bufBytes);
1427 tcu::TestStatus iterate (void);
1428 };
1429
TransformFeedbackMultistreamTestInstance(Context& context, const TestParameters& parameters)1430 TransformFeedbackMultistreamTestInstance::TransformFeedbackMultistreamTestInstance (Context& context, const TestParameters& parameters)
1431 : TransformFeedbackTestInstance (context, parameters)
1432 {
1433 const InstanceInterface& vki = m_context.getInstanceInterface();
1434 const VkPhysicalDevice physDevice = m_context.getPhysicalDevice();
1435 const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(vki, physDevice);
1436 const VkPhysicalDeviceTransformFeedbackFeaturesEXT& transformFeedbackFeatures = m_context.getTransformFeedbackFeaturesEXT();
1437 const deUint32 streamsSupported = m_transformFeedbackProperties.maxTransformFeedbackStreams;
1438 const deUint32 streamsRequired = m_parameters.streamId + 1;
1439 const deUint32 tfBuffersSupported = m_transformFeedbackProperties.maxTransformFeedbackBuffers;
1440 const deUint32 tfBuffersRequired = m_parameters.partCount;
1441 const deUint32 bytesPerVertex = m_parameters.bufferSize / m_parameters.partCount;
1442 const deUint32 tfStreamDataSizeSupported = m_transformFeedbackProperties.maxTransformFeedbackStreamDataSize;
1443 const deUint32 tfBufferDataSizeSupported = m_transformFeedbackProperties.maxTransformFeedbackBufferDataSize;
1444 const deUint32 tfBufferDataStrideSupported = m_transformFeedbackProperties.maxTransformFeedbackBufferDataStride;
1445
1446 DE_ASSERT(m_parameters.partCount == 2u);
1447
1448 if (!features.geometryShader)
1449 TCU_THROW(NotSupportedError, "Missing feature: geometryShader");
1450
1451 if (transformFeedbackFeatures.geometryStreams == DE_FALSE)
1452 TCU_THROW(NotSupportedError, "geometryStreams feature is not supported");
1453
1454 if (streamsSupported < streamsRequired)
1455 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackStreams=" + de::toString(streamsSupported) + ", while test requires " + de::toString(streamsRequired)).c_str());
1456
1457 if (tfBuffersSupported < tfBuffersRequired)
1458 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBuffers=" + de::toString(tfBuffersSupported) + ", while test requires " + de::toString(tfBuffersRequired)).c_str());
1459
1460 if (tfStreamDataSizeSupported < bytesPerVertex)
1461 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackStreamDataSize=" + de::toString(tfStreamDataSizeSupported) + ", while test requires " + de::toString(bytesPerVertex)).c_str());
1462
1463 if (tfBufferDataSizeSupported < bytesPerVertex)
1464 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBufferDataSize=" + de::toString(tfBufferDataSizeSupported) + ", while test requires " + de::toString(bytesPerVertex)).c_str());
1465
1466 if (tfBufferDataStrideSupported < bytesPerVertex)
1467 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBufferDataStride=" + de::toString(tfBufferDataStrideSupported) + ", while test requires " + de::toString(bytesPerVertex)).c_str());
1468 }
1469
generateSizesList(const size_t bufBytes, const size_t chunkCount)1470 std::vector<VkDeviceSize> TransformFeedbackMultistreamTestInstance::generateSizesList (const size_t bufBytes, const size_t chunkCount)
1471 {
1472 const VkDeviceSize chunkSize = bufBytes / chunkCount;
1473 std::vector<VkDeviceSize> result (chunkCount, chunkSize);
1474
1475 DE_ASSERT(chunkSize * chunkCount == bufBytes);
1476 DE_ASSERT(bufBytes <= MINIMUM_TF_BUFFER_SIZE);
1477 DE_ASSERT(bufBytes % sizeof(deUint32) == 0);
1478 DE_ASSERT(chunkCount > 0);
1479 DE_ASSERT(result.size() == chunkCount);
1480
1481 return result;
1482 }
1483
verifyTransformFeedbackBuffer(const MovePtr<Allocation>& bufAlloc, const deUint32 bufBytes)1484 void TransformFeedbackMultistreamTestInstance::verifyTransformFeedbackBuffer (const MovePtr<Allocation>& bufAlloc, const deUint32 bufBytes)
1485 {
1486 const DeviceInterface& vk = m_context.getDeviceInterface();
1487 const VkDevice device = m_context.getDevice();
1488 const deUint32 numPoints = static_cast<deUint32>(bufBytes / sizeof(deUint32));
1489 const float* tfData = getInvalidatedHostPtr<float>(vk, device, *bufAlloc);
1490
1491 for (deUint32 i = 0; i < numPoints; ++i)
1492 if (tfData[i] != float(i))
1493 TCU_FAIL(std::string("Failed at item ") + de::toString(float(i)) + " received:" + de::toString(tfData[i]) + " expected:" + de::toString(i));
1494 }
1495
iterate(void)1496 tcu::TestStatus TransformFeedbackMultistreamTestInstance::iterate (void)
1497 {
1498 const DeviceInterface& vk = m_context.getDeviceInterface();
1499 const VkDevice device = m_context.getDevice();
1500 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1501 const VkQueue queue = m_context.getUniversalQueue();
1502 Allocator& allocator = m_context.getDefaultAllocator();
1503
1504 const Unique<VkRenderPass> renderPass (makeRenderPass (vk, device, VK_FORMAT_UNDEFINED));
1505
1506 const Unique<VkShaderModule> vertexModule (createShaderModule (vk, device, m_context.getBinaryCollection().get("vert"), 0u));
1507 const Unique<VkShaderModule> geomModule (createShaderModule (vk, device, m_context.getBinaryCollection().get("geom"), 0u));
1508
1509 const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, 0u, DE_NULL, m_imageExtent2D.width, m_imageExtent2D.height));
1510 const Unique<VkPipelineLayout> pipelineLayout (TransformFeedback::makePipelineLayout (vk, device));
1511 const Unique<VkPipeline> pipeline (makeGraphicsPipeline (vk, device, *pipelineLayout, *renderPass, *vertexModule, DE_NULL, DE_NULL, *geomModule, DE_NULL, m_imageExtent2D, 0u));
1512 const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1513 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1514
1515 const VkBufferCreateInfo tfBufCreateInfo = makeBufferCreateInfo(m_parameters.bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT);
1516 const Move<VkBuffer> tfBuf = createBuffer(vk, device, &tfBufCreateInfo);
1517 const std::vector<VkBuffer> tfBufArray = std::vector<VkBuffer>(m_parameters.partCount, *tfBuf);
1518 const MovePtr<Allocation> tfBufAllocation = allocator.allocate(getBufferMemoryRequirements(vk, device, *tfBuf), MemoryRequirement::HostVisible);
1519 const VkMemoryBarrier tfMemoryBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT, VK_ACCESS_HOST_READ_BIT);
1520 const std::vector<VkDeviceSize> tfBufBindingSizes = generateSizesList(m_parameters.bufferSize, m_parameters.partCount);
1521 const std::vector<VkDeviceSize> tfBufBindingOffsets = generateOffsetsList(tfBufBindingSizes);
1522
1523 VK_CHECK(vk.bindBufferMemory(device, *tfBuf, tfBufAllocation->getMemory(), tfBufAllocation->getOffset()));
1524
1525 beginCommandBuffer(vk, *cmdBuffer);
1526 {
1527 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
1528 {
1529 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1530
1531 vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0u, m_parameters.partCount, &tfBufArray[0], &tfBufBindingOffsets[0], &tfBufBindingSizes[0]);
1532
1533 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1534 {
1535 vk.cmdDraw(*cmdBuffer, 1u, 1u, 0u, 0u);
1536 }
1537 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1538 }
1539 endRenderPass(vk, *cmdBuffer);
1540
1541 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &tfMemoryBarrier, 0u, DE_NULL, 0u, DE_NULL);
1542 }
1543 endCommandBuffer(vk, *cmdBuffer);
1544 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1545
1546 verifyTransformFeedbackBuffer(tfBufAllocation, m_parameters.bufferSize);
1547
1548 return tcu::TestStatus::pass("Pass");
1549 }
1550
1551 class TransformFeedbackMultistreamSameLocationTestInstance final : public TransformFeedbackTestInstance
1552 {
1553 public:
1554 TransformFeedbackMultistreamSameLocationTestInstance(Context& context, const TestParameters& parameters);
1555 protected:
1556 tcu::TestStatus iterate (void) override;
1557 void verifyTransformFeedbackBuffer (const MovePtr<Allocation>& bufAlloc, deUint32 bufBytes);
1558 };
1559
verifyTransformFeedbackBuffer(const MovePtr<Allocation>& bufAlloc, const deUint32 bufBytes)1560 void TransformFeedbackMultistreamSameLocationTestInstance::verifyTransformFeedbackBuffer (const MovePtr<Allocation>& bufAlloc, const deUint32 bufBytes)
1561 {
1562 const DeviceInterface& vk = m_context.getDeviceInterface();
1563 const VkDevice device = m_context.getDevice();
1564 const auto numPoints = static_cast<deUint32>(bufBytes / sizeof(deUint32));
1565 const auto* tuData = getInvalidatedHostPtr<deUint32>(vk, device, *bufAlloc);
1566
1567 for (deUint32 i = 0; i < numPoints; ++i)
1568 if (tuData[i] != i*2 - ((i / 16) == 0 ? 0 : 31))
1569 TCU_FAIL(std::string("Failed at item ") + de::toString(i) + " received:" + de::toString(tuData[i]) + " expected:" + de::toString(i));
1570
1571 return;
1572 }
1573
TransformFeedbackMultistreamSameLocationTestInstance(Context& context, const TestParameters& parameters)1574 TransformFeedbackMultistreamSameLocationTestInstance::TransformFeedbackMultistreamSameLocationTestInstance(Context& context, const TestParameters& parameters)
1575 : TransformFeedbackTestInstance (context, parameters)
1576 {
1577 const InstanceInterface& vki = m_context.getInstanceInterface();
1578 const VkPhysicalDevice physDevice = m_context.getPhysicalDevice();
1579 const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(vki, physDevice);
1580 const VkPhysicalDeviceTransformFeedbackFeaturesEXT& transformFeedbackFeatures = m_context.getTransformFeedbackFeaturesEXT();
1581 const deUint32 streamsSupported = m_transformFeedbackProperties.maxTransformFeedbackStreams;
1582 const deUint32 streamsRequired = m_parameters.streamId + 1;
1583 const deUint32 tfBuffersSupported = m_transformFeedbackProperties.maxTransformFeedbackBuffers;
1584 const deUint32 tfBuffersRequired = 1;
1585 const deUint32 bytesPerVertex = 4;
1586 const deUint32 tfStreamDataSizeSupported = m_transformFeedbackProperties.maxTransformFeedbackStreamDataSize;
1587 const deUint32 tfBufferDataSizeSupported = m_transformFeedbackProperties.maxTransformFeedbackBufferDataSize;
1588 const deUint32 tfBufferDataStrideSupported = m_transformFeedbackProperties.maxTransformFeedbackBufferDataStride;
1589
1590 if (!features.geometryShader)
1591 TCU_THROW(NotSupportedError, "Missing feature: geometryShader");
1592
1593 if (transformFeedbackFeatures.geometryStreams == DE_FALSE)
1594 TCU_THROW(NotSupportedError, "geometryStreams feature is not supported");
1595
1596 if (streamsSupported < streamsRequired)
1597 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackStreams=" + de::toString(streamsSupported) + ", while test requires " + de::toString(streamsRequired)).c_str());
1598
1599 if (tfBuffersSupported < tfBuffersRequired)
1600 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBuffers=" + de::toString(tfBuffersSupported) + ", while test requires " + de::toString(tfBuffersRequired)).c_str());
1601
1602 if (tfStreamDataSizeSupported < bytesPerVertex)
1603 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackStreamDataSize=" + de::toString(tfStreamDataSizeSupported) + ", while test requires " + de::toString(bytesPerVertex)).c_str());
1604
1605 if (tfBufferDataSizeSupported < bytesPerVertex)
1606 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBufferDataSize=" + de::toString(tfBufferDataSizeSupported) + ", while test requires " + de::toString(bytesPerVertex)).c_str());
1607
1608 if (tfBufferDataStrideSupported < bytesPerVertex)
1609 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBufferDataStride=" + de::toString(tfBufferDataStrideSupported) + ", while test requires " + de::toString(bytesPerVertex)).c_str());
1610 }
1611
iterate(void)1612 tcu::TestStatus TransformFeedbackMultistreamSameLocationTestInstance::iterate (void)
1613 {
1614 const DeviceInterface& vk = m_context.getDeviceInterface();
1615 const VkDevice device = m_context.getDevice();
1616 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1617 const VkQueue queue = m_context.getUniversalQueue();
1618 Allocator& allocator = m_context.getDefaultAllocator();
1619
1620 const Unique<VkRenderPass> renderPass (makeRenderPass (vk, device, VK_FORMAT_UNDEFINED));
1621
1622 const Unique<VkShaderModule> vertexModule (createShaderModule (vk, device, m_context.getBinaryCollection().get("vert"), 0u));
1623 const Unique<VkShaderModule> geomModule (createShaderModule (vk, device, m_context.getBinaryCollection().get("geom"), 0u));
1624
1625 const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, 0u, DE_NULL, m_imageExtent2D.width, m_imageExtent2D.height));
1626 const Unique<VkPipelineLayout> pipelineLayout (TransformFeedback::makePipelineLayout (vk, device));
1627 const Unique<VkPipeline> pipeline (makeGraphicsPipeline (vk, device, *pipelineLayout, *renderPass, *vertexModule, DE_NULL, DE_NULL, *geomModule, DE_NULL, m_imageExtent2D, 0u));
1628 const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1629 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1630
1631 const VkBufferCreateInfo tfBufCreateInfo = makeBufferCreateInfo(m_parameters.bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT);
1632 const Move<VkBuffer> tfBuf = createBuffer(vk, device, &tfBufCreateInfo);
1633 const std::vector<VkBuffer> tfBufArray = std::vector<VkBuffer>(m_parameters.partCount, *tfBuf);
1634 const MovePtr<Allocation> tfBufAllocation = allocator.allocate(getBufferMemoryRequirements(vk, device, *tfBuf), MemoryRequirement::HostVisible);
1635 const VkMemoryBarrier tfMemoryBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT, VK_ACCESS_HOST_READ_BIT);
1636 const std::vector<VkDeviceSize> tfBufBindingSizes = { m_parameters.bufferSize / 2, m_parameters.bufferSize / 2 };
1637 const std::vector<VkDeviceSize> tfBufBindingOffsets = { 0, m_parameters.bufferSize / 2 };
1638
1639 VK_CHECK(vk.bindBufferMemory(device, *tfBuf, tfBufAllocation->getMemory(), tfBufAllocation->getOffset()));
1640
1641 beginCommandBuffer(vk, *cmdBuffer);
1642 {
1643 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
1644 {
1645 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1646
1647 vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0u, m_parameters.partCount, &tfBufArray[0], &tfBufBindingOffsets[0], &tfBufBindingSizes[0]);
1648
1649 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1650 {
1651 vk.cmdDraw(*cmdBuffer, 16u, 1u, 0u, 0u);
1652 }
1653 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1654 }
1655 endRenderPass(vk, *cmdBuffer);
1656
1657 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &tfMemoryBarrier, 0u, DE_NULL, 0u, DE_NULL);
1658 }
1659 endCommandBuffer(vk, *cmdBuffer);
1660 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1661
1662 verifyTransformFeedbackBuffer(tfBufAllocation, m_parameters.bufferSize);
1663
1664 return tcu::TestStatus::pass("Pass");
1665 }
1666
1667 class TransformFeedbackStreamsTestInstance : public TransformFeedbackTestInstance
1668 {
1669 public:
1670 TransformFeedbackStreamsTestInstance (Context& context, const TestParameters& parameters);
1671
1672 protected:
1673 tcu::TestStatus iterate (void);
1674 bool verifyImage (const VkFormat imageFormat, const VkExtent2D& size, const void* resultData);
1675 };
1676
TransformFeedbackStreamsTestInstance(Context& context, const TestParameters& parameters)1677 TransformFeedbackStreamsTestInstance::TransformFeedbackStreamsTestInstance (Context& context, const TestParameters& parameters)
1678 : TransformFeedbackTestInstance (context, parameters)
1679 {
1680 const InstanceInterface& vki = m_context.getInstanceInterface();
1681 const VkPhysicalDevice physDevice = m_context.getPhysicalDevice();
1682 const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(vki, physDevice);
1683 const VkPhysicalDeviceTransformFeedbackFeaturesEXT& transformFeedbackFeatures = m_context.getTransformFeedbackFeaturesEXT();
1684 const deUint32 streamsSupported = m_transformFeedbackProperties.maxTransformFeedbackStreams;
1685 const deUint32 streamsRequired = m_parameters.streamId + 1;
1686 const bool geomPointSizeRequired = m_parameters.testType == TEST_TYPE_STREAMS_POINTSIZE;
1687
1688 if (!features.geometryShader)
1689 TCU_THROW(NotSupportedError, "Missing feature: geometryShader");
1690
1691 if (transformFeedbackFeatures.geometryStreams == DE_FALSE)
1692 TCU_THROW(NotSupportedError, "geometryStreams feature is not supported");
1693
1694 if (streamsSupported < streamsRequired)
1695 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackStreams=" + de::toString(streamsSupported) + ", while test requires " + de::toString(streamsRequired)).c_str());
1696
1697 if (geomPointSizeRequired && !features.shaderTessellationAndGeometryPointSize)
1698 TCU_THROW(NotSupportedError, "shaderTessellationAndGeometryPointSize feature is not supported");
1699 }
1700
verifyImage(const VkFormat imageFormat, const VkExtent2D& size, const void* resultData)1701 bool TransformFeedbackStreamsTestInstance::verifyImage (const VkFormat imageFormat, const VkExtent2D& size, const void* resultData)
1702 {
1703 const tcu::RGBA magentaRGBA (tcu::RGBA(0xFF, 0x00, 0xFF, 0xFF));
1704 const tcu::Vec4 magenta (magentaRGBA.toVec());
1705 const tcu::Vec4 black (tcu::RGBA::black().toVec());
1706 const tcu::TextureFormat textureFormat (mapVkFormat(imageFormat));
1707 const int dataSize (size.width * size.height * textureFormat.getPixelSize());
1708 tcu::TextureLevel referenceImage (textureFormat, size.width, size.height);
1709 tcu::PixelBufferAccess referenceAccess (referenceImage.getAccess());
1710
1711 // Generate reference image
1712 if (m_parameters.testType == TEST_TYPE_STREAMS)
1713 {
1714 for (int y = 0; y < referenceImage.getHeight(); ++y)
1715 {
1716 const tcu::Vec4& validColor = y < referenceImage.getHeight() / 2 ? black : magenta;
1717
1718 for (int x = 0; x < referenceImage.getWidth(); ++x)
1719 referenceAccess.setPixel(validColor, x, y);
1720 }
1721 }
1722
1723 if (m_parameters.testType == TEST_TYPE_STREAMS_CLIPDISTANCE || m_parameters.testType == TEST_TYPE_STREAMS_CULLDISTANCE)
1724 {
1725 for (int y = 0; y < referenceImage.getHeight(); ++y)
1726 for (int x = 0; x < referenceImage.getWidth(); ++x)
1727 {
1728 const tcu::Vec4& validColor = (y >= referenceImage.getHeight() / 2) && (x >= referenceImage.getWidth() / 2) ? magenta : black;
1729
1730 referenceAccess.setPixel(validColor, x, y);
1731 }
1732 }
1733
1734 if (m_parameters.testType == TEST_TYPE_STREAMS_POINTSIZE)
1735 {
1736 const int pointSize = static_cast<int>(m_parameters.pointSize);
1737 const tcu::Vec4& validColor = black;
1738
1739 for (int y = 0; y < referenceImage.getHeight(); ++y)
1740 for (int x = 0; x < referenceImage.getWidth(); ++x)
1741 referenceAccess.setPixel(validColor, x, y);
1742
1743 referenceAccess.setPixel(magenta, (1 + referenceImage.getWidth()) / 4 - 1, (referenceImage.getHeight() * 3) / 4 - 1);
1744
1745 for (int y = 0; y < pointSize; ++y)
1746 for (int x = 0; x < pointSize; ++x)
1747 referenceAccess.setPixel(magenta, x + (referenceImage.getWidth() * 3) / 4 - 1, y + (referenceImage.getHeight() * 3) / 4 - 1);
1748 }
1749
1750 if (deMemCmp(resultData, referenceAccess.getDataPtr(), dataSize) != 0)
1751 {
1752 const tcu::ConstPixelBufferAccess resultImage (textureFormat, size.width, size.height, 1, resultData);
1753 bool ok;
1754
1755 ok = tcu::intThresholdCompare(m_context.getTestContext().getLog(), "Image comparison", "", referenceAccess, resultImage, tcu::UVec4(1), tcu::COMPARE_LOG_RESULT);
1756
1757 return ok;
1758 }
1759
1760 return true;
1761 }
1762
1763 tcu::TestStatus TransformFeedbackStreamsTestInstance::iterate (void)
1764 {
1765 const DeviceInterface& vk = m_context.getDeviceInterface();
1766 const VkDevice device = m_context.getDevice();
1767 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1768 const VkQueue queue = m_context.getUniversalQueue();
1769 Allocator& allocator = m_context.getDefaultAllocator();
1770
1771 const Unique<VkRenderPass> renderPass (makeRenderPass (vk, device, VK_FORMAT_R8G8B8A8_UNORM));
1772
1773 const Unique<VkShaderModule> vertModule (createShaderModule (vk, device, m_context.getBinaryCollection().get("vert"), 0u));
1774 const Unique<VkShaderModule> geomModule (createShaderModule (vk, device, m_context.getBinaryCollection().get("geom"), 0u));
1775 const Unique<VkShaderModule> fragModule (createShaderModule (vk, device, m_context.getBinaryCollection().get("frag"), 0u));
1776
1777 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
1778 const VkImageUsageFlags imageUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1779 const tcu::RGBA clearColor (tcu::RGBA::black());
1780 const VkImageSubresourceRange colorSubresRange (makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u));
1781 const VkDeviceSize colorBufferSize (m_imageExtent2D.width * m_imageExtent2D.height * tcu::getPixelSize(mapVkFormat(colorFormat)));
1782 const Unique<VkImage> colorImage (makeImage (vk, device, makeImageCreateInfo(0u, VK_IMAGE_TYPE_2D, colorFormat, m_imageExtent2D, 1u, imageUsageFlags)));
1783 const UniquePtr<Allocation> colorImageAlloc (bindImage (vk, device, allocator, *colorImage, MemoryRequirement::Any));
1784 const Unique<VkImageView> colorAttachment (makeImageView (vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresRange));
1785 const Unique<VkBuffer> colorBuffer (makeBuffer (vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1786 const UniquePtr<Allocation> colorBufferAlloc (bindBuffer (vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
1787
1788 const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, *colorAttachment, m_imageExtent2D.width, m_imageExtent2D.height));
1789 const Unique<VkPipelineLayout> pipelineLayout (TransformFeedback::makePipelineLayout (vk, device));
1790 const Unique<VkPipeline> pipeline (makeGraphicsPipeline (vk, device, *pipelineLayout, *renderPass, *vertModule, DE_NULL, DE_NULL, *geomModule, *fragModule, m_imageExtent2D, 0u, &m_parameters.streamId));
1791 const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1792 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1793
1794 const VkImageMemoryBarrier preCopyBarrier = makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
1795 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1796 *colorImage, colorSubresRange);
1797 const VkBufferImageCopy region = makeBufferImageCopy(makeExtent3D(m_imageExtent2D.width, m_imageExtent2D.height, 1u),
1798 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u));
1799 const VkBufferMemoryBarrier postCopyBarrier = makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *colorBuffer, 0ull, VK_WHOLE_SIZE);
1800
1801 beginCommandBuffer(vk, *cmdBuffer);
1802 {
1803 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D), clearColor.toVec());
1804 {
1805 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1806
1807 vk.cmdDraw(*cmdBuffer, 2u, 1u, 0u, 0u);
1808 }
1809 endRenderPass(vk, *cmdBuffer);
1810
1811 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &preCopyBarrier);
1812 vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, ®ion);
1813 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &postCopyBarrier, DE_NULL, 0u);
1814
1815 invalidateAlloc(vk, device, *colorBufferAlloc);
1816 }
1817 endCommandBuffer(vk, *cmdBuffer);
1818 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1819
1820 if (!verifyImage(colorFormat, m_imageExtent2D, colorBufferAlloc->getHostPtr()))
1821 return tcu::TestStatus::fail("Fail");
1822
1823 return tcu::TestStatus::pass("Pass");
1824 }
1825
1826 class TransformFeedbackIndirectDrawTestInstance : public TransformFeedbackTestInstance
1827 {
1828 public:
1829 TransformFeedbackIndirectDrawTestInstance (Context& context, const TestParameters& parameters, bool multiview);
1830
1831 protected:
1832 tcu::TestStatus iterate (void);
1833 bool verifyImage (const VkFormat imageFormat, const VkExtent2D& size, const void* resultData, uint32_t layerIdx = std::numeric_limits<uint32_t>::max());
1834
1835 const bool m_multiview;
1836 };
1837
1838 TransformFeedbackIndirectDrawTestInstance::TransformFeedbackIndirectDrawTestInstance (Context& context, const TestParameters& parameters, bool multiview)
1839 : TransformFeedbackTestInstance (context, parameters)
1840 , m_multiview (multiview)
1841 {
1842 const InstanceInterface& vki = m_context.getInstanceInterface();
1843 const VkPhysicalDevice physDevice = m_context.getPhysicalDevice();
1844 const VkPhysicalDeviceLimits limits = getPhysicalDeviceProperties(vki, physDevice).limits;
1845 const deUint32 tfBufferDataSizeSupported = m_transformFeedbackProperties.maxTransformFeedbackBufferDataSize;
1846 const deUint32 tfBufferDataStrideSupported = m_transformFeedbackProperties.maxTransformFeedbackBufferDataStride;
1847
1848 if (m_transformFeedbackProperties.transformFeedbackDraw == DE_FALSE)
1849 TCU_THROW(NotSupportedError, "transformFeedbackDraw feature is not supported");
1850
1851 if (limits.maxVertexInputBindingStride < m_parameters.vertexStride)
1852 TCU_THROW(NotSupportedError, std::string("maxVertexInputBindingStride=" + de::toString(limits.maxVertexInputBindingStride) + ", while test requires " + de::toString(m_parameters.vertexStride)).c_str());
1853
1854 if (tfBufferDataSizeSupported < m_parameters.vertexStride)
1855 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBufferDataSize=" + de::toString(tfBufferDataSizeSupported) + ", while test requires " + de::toString(m_parameters.vertexStride)).c_str());
1856
1857 if (tfBufferDataStrideSupported < m_parameters.vertexStride)
1858 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBufferDataStride=" + de::toString(tfBufferDataStrideSupported) + ", while test requires " + de::toString(m_parameters.vertexStride)).c_str());
1859 }
1860
1861 bool TransformFeedbackIndirectDrawTestInstance::verifyImage (const VkFormat imageFormat, const VkExtent2D& size, const void* resultData, uint32_t layerIdx)
1862 {
1863 const tcu::Vec4 white (tcu::RGBA::white().toVec());
1864 const tcu::TextureFormat textureFormat (mapVkFormat(imageFormat));
1865 const int dataSize (size.width * size.height * textureFormat.getPixelSize());
1866 tcu::TextureLevel referenceImage (textureFormat, size.width, size.height);
1867 tcu::PixelBufferAccess referenceAccess (referenceImage.getAccess());
1868 const bool isMultilayer = (layerIdx != std::numeric_limits<uint32_t>::max());
1869 const std::string setName = "Image comparison" + (isMultilayer ? " (layer " + std::to_string(layerIdx) + ")" : std::string());
1870
1871 // Generate reference image
1872 for (int y = 0; y < referenceImage.getHeight(); ++y)
1873 for (int x = 0; x < referenceImage.getWidth(); ++x)
1874 referenceAccess.setPixel(white, x, y);
1875
1876 if (deMemCmp(resultData, referenceAccess.getDataPtr(), dataSize) != 0)
1877 {
1878 const tcu::ConstPixelBufferAccess resultImage (textureFormat, size.width, size.height, 1, resultData);
1879 bool ok;
1880
1881 ok = tcu::intThresholdCompare(m_context.getTestContext().getLog(), setName.c_str(), "", referenceAccess, resultImage, tcu::UVec4(1), tcu::COMPARE_LOG_RESULT);
1882
1883 return ok;
1884 }
1885
1886 return true;
1887 }
1888
1889 tcu::TestStatus TransformFeedbackIndirectDrawTestInstance::iterate (void)
1890 {
1891 const DeviceInterface& vk = m_context.getDeviceInterface();
1892 const VkDevice device = m_context.getDevice();
1893 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1894 const VkQueue queue = m_context.getUniversalQueue();
1895 Allocator& allocator = m_context.getDefaultAllocator();
1896 const uint32_t layerCount = (m_multiview ? 2u : 1u);
1897 const auto colorViewType = (layerCount > 1u ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D);
1898
1899 // Only used for multiview.
1900 const std::vector<uint32_t> subpassViewMasks { ((1u << layerCount) - 1u) };
1901
1902 const VkRenderPassMultiviewCreateInfo multiviewCreateInfo =
1903 {
1904 VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO, // VkStructureType sType;
1905 nullptr, // const void* pNext;
1906 de::sizeU32(subpassViewMasks), // uint32_t subpassCount;
1907 de::dataOrNull(subpassViewMasks), // const uint32_t* pViewMasks;
1908 0u, // uint32_t dependencyCount;
1909 nullptr, // const int32_t* pViewOffsets;
1910 de::sizeU32(subpassViewMasks), // uint32_t correlationMaskCount;
1911 de::dataOrNull(subpassViewMasks), // const uint32_t* pCorrelationMasks;
1912 };
1913
1914 const Unique<VkRenderPass> renderPass (makeRenderPass (vk,
1915 device,
1916 VK_FORMAT_R8G8B8A8_UNORM,
1917 VK_FORMAT_UNDEFINED,
1918 VK_ATTACHMENT_LOAD_OP_CLEAR,
1919 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1920 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
1921 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1922 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
1923 nullptr,
1924 (m_multiview ? &multiviewCreateInfo : nullptr)));
1925
1926 const Unique<VkShaderModule> vertModule (createShaderModule (vk, device, m_context.getBinaryCollection().get("vert"), 0u));
1927 const Unique<VkShaderModule> fragModule (createShaderModule (vk, device, m_context.getBinaryCollection().get("frag"), 0u));
1928
1929 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
1930 const VkImageUsageFlags imageUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1931 const tcu::RGBA clearColor (tcu::RGBA::black());
1932 const VkImageSubresourceRange colorSubresRange (makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, layerCount));
1933 const VkDeviceSize layerSize (m_imageExtent2D.width * m_imageExtent2D.height * static_cast<uint32_t>(tcu::getPixelSize(mapVkFormat(colorFormat))));
1934 const VkDeviceSize colorBufferSize (layerSize * layerCount);
1935 const Unique<VkImage> colorImage (makeImage (vk, device, makeImageCreateInfo(0u, VK_IMAGE_TYPE_2D, colorFormat, m_imageExtent2D, layerCount, imageUsageFlags)));
1936 const UniquePtr<Allocation> colorImageAlloc (bindImage (vk, device, allocator, *colorImage, MemoryRequirement::Any));
1937 const Unique<VkImageView> colorAttachment (makeImageView (vk, device, *colorImage, colorViewType, colorFormat, colorSubresRange));
1938 const Unique<VkBuffer> colorBuffer (makeBuffer (vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1939 const UniquePtr<Allocation> colorBufferAlloc (bindBuffer (vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
1940
1941 const deUint32 vertexCount = 6u;
1942 const VkDeviceSize vertexBufferSize = vertexCount * m_parameters.vertexStride;
1943 const VkBufferUsageFlags vertexBufferUsage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
1944 const Unique<VkBuffer> vertexBuffer (makeBuffer (vk, device, vertexBufferSize, vertexBufferUsage));
1945 const UniquePtr<Allocation> vertexBufferAlloc (bindBuffer (vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
1946 const VkDeviceSize vertexBufferOffset (0u);
1947 const float vertexBufferVals[] =
1948 {
1949 -1.0f, -1.0f, 0.0f, 1.0f,
1950 -1.0f, +1.0f, 0.0f, 1.0f,
1951 +1.0f, -1.0f, 0.0f, 1.0f,
1952 -1.0f, +1.0f, 0.0f, 1.0f,
1953 +1.0f, -1.0f, 0.0f, 1.0f,
1954 +1.0f, +1.0f, 0.0f, 1.0f,
1955 };
1956
1957 const deUint32 counterBufferValue = m_parameters.vertexStride * vertexCount;
1958 const VkDeviceSize counterBufferSize = sizeof(counterBufferValue);
1959 const VkBufferUsageFlags counterBufferUsage = VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
1960 const Unique<VkBuffer> counterBuffer (makeBuffer (vk, device, counterBufferSize, counterBufferUsage));
1961 const UniquePtr<Allocation> counterBufferAlloc (bindBuffer (vk, device, allocator, *counterBuffer, MemoryRequirement::HostVisible));
1962
1963 // Note: for multiview the framebuffer layer count is also 1.
1964 const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, *colorAttachment, m_imageExtent2D.width, m_imageExtent2D.height));
1965 const Unique<VkPipelineLayout> pipelineLayout (TransformFeedback::makePipelineLayout (vk, device));
1966 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));
1967 const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1968 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1969
1970 const VkImageMemoryBarrier preCopyBarrier = makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
1971 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1972 *colorImage, colorSubresRange);
1973 const VkBufferImageCopy region = makeBufferImageCopy(makeExtent3D(m_imageExtent2D.width, m_imageExtent2D.height, 1u),
1974 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, layerCount));
1975 const VkBufferMemoryBarrier postCopyBarrier = makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *colorBuffer, 0ull, VK_WHOLE_SIZE);
1976
1977 fillBuffer(vk, device, *counterBufferAlloc, counterBufferSize, &counterBufferValue, counterBufferSize);
1978 fillBuffer(vk, device, *vertexBufferAlloc, vertexBufferSize, vertexBufferVals, sizeof(vertexBufferVals));
1979
1980 beginCommandBuffer(vk, *cmdBuffer);
1981 {
1982 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D), clearColor.toVec());
1983 {
1984 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &*vertexBuffer, &vertexBufferOffset);
1985
1986 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1987
1988 vk.cmdDrawIndirectByteCountEXT(*cmdBuffer, 1u, 0u, *counterBuffer, 0u, 0u, m_parameters.vertexStride);
1989 }
1990 endRenderPass(vk, *cmdBuffer);
1991
1992 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &preCopyBarrier);
1993 vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, ®ion);
1994 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &postCopyBarrier, DE_NULL, 0u);
1995
1996 invalidateAlloc(vk, device, *colorBufferAlloc);
1997 }
1998 endCommandBuffer(vk, *cmdBuffer);
1999 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
2000
2001 bool fail = false;
2002 for (uint32_t layerIdx = 0u; layerIdx < layerCount; ++layerIdx)
2003 {
2004 const auto dataPtr = reinterpret_cast<uint8_t*>(colorBufferAlloc->getHostPtr()) + layerIdx * layerSize;
2005 if (!verifyImage(colorFormat, m_imageExtent2D, dataPtr))
2006 fail = true;
2007 }
2008
2009 if (fail)
2010 return tcu::TestStatus::fail("Fail; check log for details");
2011
2012 return tcu::TestStatus::pass("Pass");
2013 }
2014
2015 class TransformFeedbackBackwardDependencyTestInstance : public TransformFeedbackTestInstance
2016 {
2017 public:
2018 TransformFeedbackBackwardDependencyTestInstance (Context& context, const TestParameters& parameters);
2019
2020 protected:
2021 tcu::TestStatus iterate (void);
2022 std::vector<VkDeviceSize> generateSizesList (const size_t bufBytes, const size_t chunkCount);
2023 };
2024
2025 TransformFeedbackBackwardDependencyTestInstance::TransformFeedbackBackwardDependencyTestInstance (Context& context, const TestParameters& parameters)
2026 : TransformFeedbackTestInstance (context, parameters)
2027 {
2028 if (m_transformFeedbackProperties.transformFeedbackDraw == DE_FALSE)
2029 TCU_THROW(NotSupportedError, "transformFeedbackDraw feature is not supported");
2030 }
2031
2032 std::vector<VkDeviceSize> TransformFeedbackBackwardDependencyTestInstance::generateSizesList (const size_t bufBytes, const size_t chunkCount)
2033 {
2034 const VkDeviceSize chunkSize = bufBytes / chunkCount;
2035 std::vector<VkDeviceSize> result (chunkCount, chunkSize);
2036
2037 DE_ASSERT(chunkSize * chunkCount == bufBytes);
2038 DE_ASSERT(bufBytes <= MINIMUM_TF_BUFFER_SIZE);
2039 DE_ASSERT(bufBytes % sizeof(deUint32) == 0);
2040 DE_ASSERT(chunkCount > 0);
2041 DE_ASSERT(result.size() == chunkCount);
2042
2043 return result;
2044 }
2045
2046 tcu::TestStatus TransformFeedbackBackwardDependencyTestInstance::iterate (void)
2047 {
2048 const DeviceInterface& vk = m_context.getDeviceInterface();
2049 const VkDevice device = m_context.getDevice();
2050 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
2051 const VkQueue queue = m_context.getUniversalQueue();
2052 Allocator& allocator = m_context.getDefaultAllocator();
2053
2054 const std::vector<VkDeviceSize> chunkSizesList = generateSizesList(m_parameters.bufferSize, m_parameters.partCount);
2055 const std::vector<VkDeviceSize> chunkOffsetsList = generateOffsetsList(chunkSizesList);
2056
2057 const uint32_t numPoints = static_cast<uint32_t>(chunkSizesList[0] / sizeof(uint32_t));
2058 const bool indirectDraw = (m_parameters.testType == TEST_TYPE_BACKWARD_DEPENDENCY_INDIRECT);
2059
2060 // Color buffer.
2061 const tcu::IVec3 fbExtent (static_cast<int>(numPoints), 1, 1);
2062 const auto vkExtent = makeExtent3D(fbExtent);
2063 const std::vector<VkViewport> viewports (1u, makeViewport(vkExtent));
2064 const std::vector<VkRect2D> scissors (1u, makeRect2D(vkExtent));
2065
2066 const auto colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
2067 const auto colorUsage = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
2068 const tcu::Vec4 clearColor (0.0f, 0.0f, 0.0f, 1.0f);
2069 const tcu::Vec4 geomColor (0.0f, 0.0f, 1.0f, 1.0f); // Must match frag shader.
2070 ImageWithBuffer colorBuffer (vk, device, allocator, vkExtent, colorFormat, colorUsage, VK_IMAGE_TYPE_2D);
2071
2072 // Must match vertex shader.
2073 struct PushConstants
2074 {
2075 uint32_t startValue;
2076 float width;
2077 float posY;
2078 };
2079
2080 const auto pcSize = static_cast<uint32_t>(sizeof(PushConstants));
2081 const Unique<VkShaderModule> vertexModule (createShaderModule (vk, device, m_context.getBinaryCollection().get("vert"), 0u));
2082 const Unique<VkShaderModule> fragModule (createShaderModule (vk, device, m_context.getBinaryCollection().get("frag"), 0u));
2083 const Unique<VkRenderPass> renderPass (TransformFeedback::makeCustomRenderPass(vk, device, colorFormat));
2084 const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, colorBuffer.getImageView(), vkExtent.width, vkExtent.height));
2085 const Unique<VkPipelineLayout> pipelineLayout (TransformFeedback::makePipelineLayout (vk, device, pcSize));
2086 const Unique<VkPipeline> pipeline (makeGraphicsPipeline (vk, device, *pipelineLayout, *renderPass, *vertexModule, DE_NULL, DE_NULL, DE_NULL, *fragModule, makeExtent2D(vkExtent.width, vkExtent.height), 0u));
2087 const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
2088 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
2089
2090 const VkBufferCreateInfo tfBufCreateInfo = makeBufferCreateInfo(m_parameters.bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT);
2091 const Move<VkBuffer> tfBuf = createBuffer(vk, device, &tfBufCreateInfo);
2092 const MovePtr<Allocation> tfBufAllocation = allocator.allocate(getBufferMemoryRequirements(vk, device, *tfBuf), MemoryRequirement::HostVisible);
2093 const VkMemoryBarrier tfMemoryBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT, VK_ACCESS_HOST_READ_BIT);
2094 const VkDeviceSize tfBufBindingSize = m_parameters.bufferSize;
2095 const VkDeviceSize tfBufBindingOffset = 0ull;
2096
2097 const size_t tfcBufSize = sizeof(deUint32);
2098 const VkBufferCreateInfo tfcBufCreateInfo = makeBufferCreateInfo(tfcBufSize, VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT | VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT);
2099 const Move<VkBuffer> tfcBuf = createBuffer(vk, device, &tfcBufCreateInfo);
2100 const MovePtr<Allocation> tfcBufAllocation = allocator.allocate(getBufferMemoryRequirements(vk, device, *tfcBuf), MemoryRequirement::Any);
2101 const VkDeviceSize tfcBufBindingOffset = 0ull;
2102 const VkMemoryBarrier tfcMemoryBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT, VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT);
2103
2104 using BufferWithMemoryPtr = std::unique_ptr<BufferWithMemory>;
2105 BufferWithMemoryPtr indirectBuffer;
2106 VkDeviceSize indirectBufferSize;
2107 VkBufferCreateInfo indirectBufferInfo;
2108 std::vector<VkDrawIndirectCommand> indirectCommands;
2109 const auto indirectStructSize = static_cast<uint32_t>(sizeof(decltype(indirectCommands)::value_type));
2110 const auto indirectStride = indirectStructSize * 2u; // See below.
2111
2112 VK_CHECK(vk.bindBufferMemory(device, *tfBuf, tfBufAllocation->getMemory(), tfBufAllocation->getOffset()));
2113 VK_CHECK(vk.bindBufferMemory(device, *tfcBuf, tfcBufAllocation->getMemory(), tfcBufAllocation->getOffset()));
2114
2115 DE_ASSERT(m_parameters.partCount == 2u);
2116
2117 if (indirectDraw)
2118 {
2119 // Prepare indirect commands. The first entry will be used as the count.
2120 // Each subsequent indirect command will be padded with an unused structure.
2121 indirectCommands.reserve(numPoints + 1u);
2122 indirectCommands.push_back(VkDrawIndirectCommand{numPoints, 0u, 0u, 0u});
2123
2124 for (uint32_t drawIdx = 0u; drawIdx < numPoints; ++drawIdx)
2125 {
2126 indirectCommands.push_back(VkDrawIndirectCommand{1u, 1u, drawIdx, 0u});
2127 indirectCommands.push_back(VkDrawIndirectCommand{0u, 0u, 0u, 0u});
2128 }
2129
2130 indirectBufferSize = static_cast<VkDeviceSize>(de::dataSize(indirectCommands));
2131 indirectBufferInfo = makeBufferCreateInfo(indirectBufferSize, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT);
2132
2133 indirectBuffer.reset(new BufferWithMemory(vk, device, allocator, indirectBufferInfo, MemoryRequirement::HostVisible));
2134 auto& indirectBufferAlloc = indirectBuffer->getAllocation();
2135 void* indirectBufferData = indirectBufferAlloc.getHostPtr();
2136
2137 deMemcpy(indirectBufferData, de::dataOrNull(indirectCommands), de::dataSize(indirectCommands));
2138 flushAlloc(vk, device, indirectBufferAlloc);
2139 }
2140
2141 beginCommandBuffer(vk, *cmdBuffer);
2142 {
2143 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, scissors.at(0u), clearColor);
2144 {
2145 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
2146
2147 vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0, 1, &*tfBuf, &tfBufBindingOffset, &tfBufBindingSize);
2148
2149 {
2150 const uint32_t startValue = static_cast<uint32_t>(chunkOffsetsList[0] / sizeof(uint32_t));
2151 const PushConstants pcData
2152 {
2153 startValue,
2154 static_cast<float>(vkExtent.width),
2155 static_cast<float>(10.0f), // Push the points offscreen.
2156 };
2157
2158 vk.cmdPushConstants(*cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0u, pcSize, &pcData);
2159
2160 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
2161 {
2162 if (indirectDraw)
2163 vk.cmdDrawIndirectCount(*cmdBuffer, indirectBuffer->get(), indirectStructSize, indirectBuffer->get(), 0u, numPoints, indirectStride);
2164 else
2165 vk.cmdDraw(*cmdBuffer, numPoints, 1u, 0u, 0u);
2166 }
2167 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 1, &*tfcBuf, m_parameters.noOffsetArray ? DE_NULL : &tfcBufBindingOffset);
2168 }
2169
2170 if (indirectDraw)
2171 {
2172 // This should be a no-op but allows us to reset the indirect draw counter in case it could influence the follow-up indirect draw.
2173 vk.cmdDrawIndirectCount(*cmdBuffer, indirectBuffer->get(), indirectStructSize, indirectBuffer->get(), 0u, 0u/*no draws*/, indirectStride);
2174 }
2175
2176 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);
2177
2178 {
2179 const uint32_t startValue = static_cast<deUint32>(chunkOffsetsList[1] / sizeof(deUint32));
2180 const PushConstants pcData
2181 {
2182 startValue,
2183 static_cast<float>(vkExtent.width),
2184 static_cast<float>(0.0f), // Points onscreen in this second draw.
2185 };
2186
2187 vk.cmdPushConstants(*cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0u, pcSize, &pcData);
2188
2189 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 1, &*tfcBuf, m_parameters.noOffsetArray ? DE_NULL : &tfcBufBindingOffset);
2190 {
2191 vk.cmdDrawIndirectByteCountEXT(*cmdBuffer, 1u, 0u, *tfcBuf, 0u, 0u, 4u);
2192 }
2193 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
2194 }
2195
2196 }
2197 endRenderPass(vk, *cmdBuffer);
2198
2199 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &tfMemoryBarrier, 0u, DE_NULL, 0u, DE_NULL);
2200 }
2201 copyImageToBuffer(vk, *cmdBuffer, colorBuffer.getImage(), colorBuffer.getBuffer(), fbExtent.swizzle(0, 1));
2202 endCommandBuffer(vk, *cmdBuffer);
2203 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
2204
2205 verifyTransformFeedbackBuffer(tfBufAllocation, m_parameters.bufferSize);
2206
2207 // Verify color buffer, to check vkCmdDrawIndirectByteCountEXT worked.
2208 const auto tcuFormat = mapVkFormat(colorFormat);
2209 tcu::TextureLevel refLevel (tcuFormat, fbExtent.x(), fbExtent.y());
2210 const auto refAccess = refLevel.getAccess();
2211 const auto resAlloc = colorBuffer.getBufferAllocation();
2212 tcu::ConstPixelBufferAccess resAccess (tcuFormat, fbExtent, resAlloc.getHostPtr());
2213 auto& log = m_context.getTestContext().getLog();
2214 const tcu::Vec4 threshold (0.0f, 0.0f, 0.0f, 0.0f);
2215
2216 tcu::clear(refAccess, geomColor);
2217 invalidateAlloc(vk, device, resAlloc);
2218
2219 if (!tcu::floatThresholdCompare(log, "Result", "", refAccess, resAccess, threshold, tcu::COMPARE_LOG_ON_ERROR))
2220 return tcu::TestStatus::fail("Color buffer contains unexpected results; check log for details");
2221
2222 return tcu::TestStatus::pass("Pass");
2223 }
2224
2225
2226 class TransformFeedbackQueryTestInstance : public TransformFeedbackTestInstance
2227 {
2228 public:
2229 TransformFeedbackQueryTestInstance (Context& context, const TestParameters& parameters);
2230
2231 protected:
2232 tcu::TestStatus iterate (void);
2233 };
2234
2235 TransformFeedbackQueryTestInstance::TransformFeedbackQueryTestInstance (Context& context, const TestParameters& parameters)
2236 : TransformFeedbackTestInstance (context, parameters)
2237 {
2238 const InstanceInterface& vki = m_context.getInstanceInterface();
2239 const VkPhysicalDevice physDevice = m_context.getPhysicalDevice();
2240 const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(vki, physDevice);
2241 const VkPhysicalDeviceTransformFeedbackFeaturesEXT& transformFeedbackFeatures = m_context.getTransformFeedbackFeaturesEXT();
2242 const deUint32 streamsSupported = m_transformFeedbackProperties.maxTransformFeedbackStreams;
2243 const deUint32 streamsRequired = m_parameters.streamId + 1;
2244
2245 if (!features.geometryShader)
2246 TCU_THROW(NotSupportedError, "Missing feature: geometryShader");
2247
2248 if (streamsRequired > 1 && transformFeedbackFeatures.geometryStreams == DE_FALSE)
2249 TCU_THROW(NotSupportedError, "geometryStreams feature is not supported");
2250
2251 if (streamsSupported < streamsRequired)
2252 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackStreams=" + de::toString(streamsSupported) + ", while test requires " + de::toString(streamsRequired)).c_str());
2253
2254 if (m_transformFeedbackProperties.transformFeedbackQueries == DE_FALSE)
2255 TCU_THROW(NotSupportedError, "transformFeedbackQueries feature is not supported");
2256
2257 if (m_parameters.testType == TEST_TYPE_QUERY_RESET)
2258 {
2259 // Check VK_EXT_host_query_reset is supported
2260 m_context.requireDeviceFunctionality("VK_EXT_host_query_reset");
2261 if(m_context.getHostQueryResetFeatures().hostQueryReset == VK_FALSE)
2262 throw tcu::NotSupportedError(std::string("Implementation doesn't support resetting queries from the host").c_str());
2263 }
2264 }
2265
2266 tcu::TestStatus TransformFeedbackQueryTestInstance::iterate (void)
2267 {
2268 const DeviceInterface& vk = m_context.getDeviceInterface();
2269 const VkDevice device = m_context.getDevice();
2270 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
2271 const VkQueue queue = m_context.getUniversalQueue();
2272 Allocator& allocator = m_context.getDefaultAllocator();
2273
2274 const deUint64 overflowVertices = 3u;
2275 const deUint32 bytesPerVertex = static_cast<deUint32>(4 * sizeof(float));
2276 const deUint64 numVerticesInBuffer = m_parameters.bufferSize / bytesPerVertex;
2277 const deUint64 numVerticesToWrite = numVerticesInBuffer + overflowVertices;
2278 const Unique<VkRenderPass> renderPass (makeRenderPass (vk, device, VK_FORMAT_UNDEFINED));
2279
2280 const Unique<VkShaderModule> vertModule (createShaderModule (vk, device, m_context.getBinaryCollection().get("vert"), 0u));
2281 const Unique<VkShaderModule> geomModule (createShaderModule (vk, device, m_context.getBinaryCollection().get("geom"), 0u));
2282
2283 const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, 0u, DE_NULL, m_imageExtent2D.width, m_imageExtent2D.height));
2284 const Unique<VkPipelineLayout> pipelineLayout (TransformFeedback::makePipelineLayout (vk, device));
2285 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));
2286 const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
2287 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
2288
2289 const deUint32 tfBufferSize = (deUint32)topologyData.at(m_parameters.primTopology).getNumPrimitives(numVerticesInBuffer) * (deUint32)topologyData.at(m_parameters.primTopology).primSize * bytesPerVertex;
2290 const VkBufferCreateInfo tfBufCreateInfo = makeBufferCreateInfo(tfBufferSize, VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT);
2291 const Move<VkBuffer> tfBuf = createBuffer(vk, device, &tfBufCreateInfo);
2292 const MovePtr<Allocation> tfBufAllocation = bindBuffer(vk, device, allocator, *tfBuf, MemoryRequirement::HostVisible);
2293 const VkDeviceSize tfBufBindingSize = tfBufferSize;
2294 const VkDeviceSize tfBufBindingOffset = 0ull;
2295
2296 const size_t queryResultWidth = (m_parameters.query64bits ? sizeof(deUint64) : sizeof(deUint32));
2297 const vk::VkQueryControlFlags queryExtraFlags = (m_parameters.query64bits ? vk::VK_QUERY_RESULT_64_BIT : 0);
2298 const deUint32 queryCountersNumber = 1u;
2299 const deUint32 queryIndex = 0u;
2300 constexpr deUint32 queryResultElements = 2u;
2301 const deUint32 queryDataSize = static_cast<deUint32>(queryResultElements * queryResultWidth) + (m_parameters.queryResultWithAvailability ? (deUint32)queryResultWidth : 0u);
2302 const VkQueryPoolCreateInfo queryPoolCreateInfo = makeQueryPoolCreateInfo(queryCountersNumber);
2303 const Unique<VkQueryPool> queryPool (createQueryPool(vk, device, &queryPoolCreateInfo));
2304
2305 const VkQueryResultFlagBits queryWait = m_parameters.queryResultWithAvailability ? VK_QUERY_RESULT_WITH_AVAILABILITY_BIT : VK_QUERY_RESULT_WAIT_BIT;
2306
2307 Move<VkBuffer> queryPoolResultsBuffer;
2308 de::MovePtr<Allocation> queryPoolResultsBufferAlloc;
2309
2310 tcu::TestLog& log = m_context.getTestContext().getLog();
2311
2312 DE_ASSERT(numVerticesInBuffer * bytesPerVertex == m_parameters.bufferSize);
2313
2314 if (m_parameters.testType == TEST_TYPE_QUERY_COPY || m_parameters.testType == TEST_TYPE_QUERY_COPY_STRIDE_ZERO)
2315 {
2316 const VkBufferCreateInfo bufferParams =
2317 {
2318 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
2319 DE_NULL, // const void* pNext;
2320 0u, // VkBufferCreateFlags flags;
2321 queryDataSize, // VkDeviceSize size;
2322 VK_BUFFER_USAGE_TRANSFER_DST_BIT, // VkBufferUsageFlags usage;
2323 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
2324 1u, // deUint32 queueFamilyCount;
2325 &queueFamilyIndex // const deUint32* pQueueFamilyIndices;
2326 };
2327
2328 queryPoolResultsBuffer = createBuffer(vk, device, &bufferParams);
2329 queryPoolResultsBufferAlloc = allocator.allocate(getBufferMemoryRequirements(vk, device, *queryPoolResultsBuffer), MemoryRequirement::HostVisible);
2330
2331 VK_CHECK(vk.bindBufferMemory(device, *queryPoolResultsBuffer, queryPoolResultsBufferAlloc->getMemory(), queryPoolResultsBufferAlloc->getOffset()));
2332 }
2333
2334 beginCommandBuffer(vk, *cmdBuffer);
2335 {
2336 if (m_parameters.testType != TEST_TYPE_QUERY_RESET)
2337 vk.cmdResetQueryPool(*cmdBuffer, *queryPool, queryIndex, queryCountersNumber);
2338
2339 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
2340 {
2341 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
2342
2343 vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0u, 1u, &*tfBuf, &tfBufBindingOffset, &tfBufBindingSize);
2344
2345 if (m_parameters.streamId == 0 && m_parameters.streamId0Mode != STREAM_ID_0_BEGIN_QUERY_INDEXED)
2346 vk.cmdBeginQuery(*cmdBuffer, *queryPool, queryIndex, 0u);
2347 else
2348 vk.cmdBeginQueryIndexedEXT(*cmdBuffer, *queryPool, queryIndex, 0u, m_parameters.streamId);
2349 {
2350 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
2351 {
2352 vk.cmdDraw(*cmdBuffer, static_cast<deUint32>(numVerticesToWrite), 1u, 0u, 0u);
2353 }
2354 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
2355 }
2356 if (m_parameters.streamId == 0 && m_parameters.streamId0Mode != STREAM_ID_0_END_QUERY_INDEXED)
2357 vk.cmdEndQuery(*cmdBuffer, *queryPool, queryIndex);
2358 else
2359 vk.cmdEndQueryIndexedEXT(*cmdBuffer, *queryPool, queryIndex, m_parameters.streamId);
2360 }
2361 endRenderPass(vk, *cmdBuffer);
2362
2363 if (m_parameters.testType == TEST_TYPE_QUERY_COPY || m_parameters.testType == TEST_TYPE_QUERY_COPY_STRIDE_ZERO)
2364 {
2365 VkDeviceSize copyStride = queryDataSize;
2366 if (queryCountersNumber == 1u && m_parameters.testType == TEST_TYPE_QUERY_COPY_STRIDE_ZERO)
2367 copyStride = 0;
2368
2369 vk.cmdCopyQueryPoolResults(*cmdBuffer, *queryPool, queryIndex, queryCountersNumber, *queryPoolResultsBuffer, 0u, copyStride, (queryWait | queryExtraFlags));
2370
2371 const VkBufferMemoryBarrier bufferBarrier =
2372 {
2373 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
2374 DE_NULL, // const void* pNext;
2375 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
2376 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask;
2377 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
2378 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
2379 *queryPoolResultsBuffer, // VkBuffer buffer;
2380 0ull, // VkDeviceSize offset;
2381 VK_WHOLE_SIZE // VkDeviceSize size;
2382 };
2383 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL);
2384 }
2385
2386 }
2387 endCommandBuffer(vk, *cmdBuffer);
2388
2389 if (m_parameters.testType == TEST_TYPE_QUERY_RESET)
2390 vk.resetQueryPool(device, *queryPool, queryIndex, queryCountersNumber);
2391 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
2392
2393 {
2394 union Results
2395 {
2396 deUint32 elements32[queryResultElements];
2397 deUint64 elements64[queryResultElements];
2398 };
2399
2400 std::vector<deUint8> queryData (queryDataSize, 0u);
2401 const Results* queryResults = reinterpret_cast<Results*>(queryData.data());
2402
2403 if (m_parameters.testType != TEST_TYPE_QUERY_COPY && m_parameters.testType != TEST_TYPE_QUERY_COPY_STRIDE_ZERO)
2404 {
2405 vk.getQueryPoolResults(device, *queryPool, queryIndex, queryCountersNumber, queryDataSize, queryData.data(), queryDataSize, (queryWait | queryExtraFlags));
2406 }
2407 else
2408 {
2409 invalidateAlloc(vk, device, *queryPoolResultsBufferAlloc);
2410 deMemcpy(queryData.data(), queryPoolResultsBufferAlloc->getHostPtr(), queryData.size());
2411 }
2412
2413 // Query results not available
2414 if (*reinterpret_cast<deUint32*>(&queryData[queryDataSize - queryResultWidth]) == 0)
2415 return tcu::TestStatus::pass("Pass");
2416
2417 // The number of primitives successfully written to the corresponding transform feedback buffer.
2418 const deUint64 numPrimitivesWritten = (m_parameters.query64bits ? queryResults->elements64[0] : queryResults->elements32[0]);
2419
2420 // The number of primitives output to the vertex stream.
2421 const deUint64 numPrimitivesNeeded = (m_parameters.query64bits ? queryResults->elements64[1] : queryResults->elements32[1]);
2422
2423 // Count how many primitives we should get by using selected topology.
2424 const auto primitivesInBuffer = topologyData.at(m_parameters.primTopology).getNumPrimitives(numVerticesInBuffer);
2425 const auto primitivesToWrite = topologyData.at(m_parameters.primTopology).getNumPrimitives(numVerticesToWrite);
2426
2427 log << tcu::TestLog::Message << "Primitives Written / Expected : " << de::toString(numPrimitivesWritten) << " / " << de::toString(primitivesInBuffer) << tcu::TestLog::EndMessage;
2428 log << tcu::TestLog::Message << "Primitives Needed / Expected : " << de::toString(numPrimitivesNeeded) << " / " << de::toString(primitivesToWrite) << tcu::TestLog::EndMessage;
2429
2430 if (numPrimitivesWritten != primitivesInBuffer)
2431 return tcu::TestStatus::fail("numPrimitivesWritten=" + de::toString(numPrimitivesWritten) + " while expected " + de::toString(primitivesInBuffer));
2432
2433 if (numPrimitivesNeeded != primitivesToWrite)
2434 return tcu::TestStatus::fail("numPrimitivesNeeded=" + de::toString(numPrimitivesNeeded) + " while expected " + de::toString(primitivesToWrite));
2435 }
2436
2437 if (m_parameters.testType == TEST_TYPE_QUERY_RESET)
2438 {
2439 constexpr deUint32 queryResetElements = queryResultElements + 1; // For the availability bit.
2440
2441 union Results
2442 {
2443 deUint32 elements32[queryResetElements];
2444 deUint64 elements64[queryResetElements];
2445 };
2446
2447 const deUint32 queryDataAvailSize (static_cast<deUint32>(queryResetElements * queryResultWidth));
2448 std::vector<deUint8> queryData (queryDataAvailSize, 0u);
2449 Results* queryResults = reinterpret_cast<Results*>(queryData.data());
2450
2451 // Initialize values
2452 if (m_parameters.query64bits)
2453 {
2454 queryResults->elements64[0] = 1u; // numPrimitivesWritten
2455 queryResults->elements64[1] = 1u; // numPrimitivesNeeded
2456 queryResults->elements64[2] = 1u; // Availability bit
2457 }
2458 else
2459 {
2460 queryResults->elements32[0] = 1u; // numPrimitivesWritten
2461 queryResults->elements32[1] = 1u; // numPrimitivesNeeded
2462 queryResults->elements32[2] = 1u; // Availability bit
2463 }
2464
2465 vk.resetQueryPool(device, *queryPool, queryIndex, queryCountersNumber);
2466
2467 vk::VkResult res = vk.getQueryPoolResults(device, *queryPool, queryIndex, queryCountersNumber, queryDataAvailSize, queryData.data(), queryDataAvailSize, (vk::VK_QUERY_RESULT_WITH_AVAILABILITY_BIT | queryExtraFlags));
2468 const deUint64 numPrimitivesWritten = (m_parameters.query64bits ? queryResults->elements64[0] : queryResults->elements32[0]);
2469 const deUint64 numPrimitivesNeeded = (m_parameters.query64bits ? queryResults->elements64[1] : queryResults->elements32[1]);
2470 const deUint64 availabilityState = (m_parameters.query64bits ? queryResults->elements64[2] : queryResults->elements32[2]);
2471
2472 /* From the Vulkan spec:
2473 *
2474 * If VK_QUERY_RESULT_WAIT_BIT and VK_QUERY_RESULT_PARTIAL_BIT are both not set then no result values are written to pData
2475 * for queries that are in the unavailable state at the time of the call, and vkGetQueryPoolResults returns VK_NOT_READY.
2476 * However, availability state is still written to pData for those queries if VK_QUERY_RESULT_WITH_AVAILABILITY_BIT is set.
2477 */
2478 if (res != vk::VK_NOT_READY || availabilityState != 0u)
2479 return tcu::TestStatus::fail("QueryPoolResults incorrect reset");
2480 if (numPrimitivesWritten != 1u || numPrimitivesNeeded != 1u)
2481 return tcu::TestStatus::fail("QueryPoolResults data was modified");
2482
2483 }
2484
2485 return tcu::TestStatus::pass("Pass");
2486 }
2487
2488 class TransformFeedbackMultiQueryTestInstance : public TransformFeedbackTestInstance
2489 {
2490 public:
2491 TransformFeedbackMultiQueryTestInstance (Context& context, const TestParameters& parameters);
2492
2493 protected:
2494 std::vector<VkDeviceSize> generateSizesList (const size_t bufBytes, const size_t chunkCount);
2495 void verifyTransformFeedbackBuffer (const MovePtr<Allocation>& bufAlloc, const deUint32 bufBytes, const deUint32 bufOffset, const float expected);
2496 tcu::TestStatus iterate (void);
2497 };
2498
TransformFeedbackMultiQueryTestInstance(Context& context, const TestParameters& parameters)2499 TransformFeedbackMultiQueryTestInstance::TransformFeedbackMultiQueryTestInstance (Context& context, const TestParameters& parameters)
2500 : TransformFeedbackTestInstance (context, parameters)
2501 {
2502 const InstanceInterface& vki = m_context.getInstanceInterface();
2503 const VkPhysicalDevice physDevice = m_context.getPhysicalDevice();
2504 const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(vki, physDevice);
2505 const VkPhysicalDeviceTransformFeedbackFeaturesEXT& transformFeedbackFeatures = m_context.getTransformFeedbackFeaturesEXT();
2506 const deUint32 streamsSupported = m_transformFeedbackProperties.maxTransformFeedbackStreams;
2507 const deUint32 streamsRequired = m_parameters.streamId + 1;
2508 const deUint32 tfBuffersSupported = m_transformFeedbackProperties.maxTransformFeedbackBuffers;
2509 const deUint32 tfBuffersRequired = m_parameters.partCount;
2510 const deUint32 bytesPerVertex = m_parameters.bufferSize / m_parameters.partCount;
2511 const deUint32 tfStreamDataSizeSupported = m_transformFeedbackProperties.maxTransformFeedbackStreamDataSize;
2512 const deUint32 tfBufferDataSizeSupported = m_transformFeedbackProperties.maxTransformFeedbackBufferDataSize;
2513 const deUint32 tfBufferDataStrideSupported = m_transformFeedbackProperties.maxTransformFeedbackBufferDataStride;
2514
2515 DE_ASSERT(m_parameters.partCount == 2u);
2516
2517 if (!features.geometryShader)
2518 TCU_THROW(NotSupportedError, "Missing feature: geometryShader");
2519
2520 if (transformFeedbackFeatures.geometryStreams == DE_FALSE)
2521 TCU_THROW(NotSupportedError, "geometryStreams feature is not supported");
2522
2523 if (streamsSupported < streamsRequired)
2524 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackStreams=" + de::toString(streamsSupported) + ", while test requires " + de::toString(streamsRequired)).c_str());
2525
2526 if (tfBuffersSupported < tfBuffersRequired)
2527 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBuffers=" + de::toString(tfBuffersSupported) + ", while test requires " + de::toString(tfBuffersRequired)).c_str());
2528
2529 if (tfStreamDataSizeSupported < bytesPerVertex)
2530 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackStreamDataSize=" + de::toString(tfStreamDataSizeSupported) + ", while test requires " + de::toString(bytesPerVertex)).c_str());
2531
2532 if (tfBufferDataSizeSupported < bytesPerVertex)
2533 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBufferDataSize=" + de::toString(tfBufferDataSizeSupported) + ", while test requires " + de::toString(bytesPerVertex)).c_str());
2534
2535 if (tfBufferDataStrideSupported < bytesPerVertex)
2536 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBufferDataStride=" + de::toString(tfBufferDataStrideSupported) + ", while test requires " + de::toString(bytesPerVertex)).c_str());
2537
2538 if (m_transformFeedbackProperties.transformFeedbackQueries == DE_FALSE)
2539 TCU_THROW(NotSupportedError, "transformFeedbackQueries feature is not supported");
2540 }
2541
generateSizesList(const size_t bufBytes, const size_t chunkCount)2542 std::vector<VkDeviceSize> TransformFeedbackMultiQueryTestInstance::generateSizesList (const size_t bufBytes, const size_t chunkCount)
2543 {
2544 const VkDeviceSize chunkSize = bufBytes / chunkCount;
2545 std::vector<VkDeviceSize> result (chunkCount, chunkSize);
2546
2547 DE_ASSERT(chunkSize * chunkCount == bufBytes);
2548 DE_ASSERT(bufBytes <= MINIMUM_TF_BUFFER_SIZE);
2549 DE_ASSERT(bufBytes % sizeof(deUint32) == 0);
2550 DE_ASSERT(chunkCount > 0);
2551 DE_ASSERT(result.size() == chunkCount);
2552
2553 return result;
2554 }
2555
verifyTransformFeedbackBuffer(const MovePtr<Allocation>& bufAlloc, const deUint32 bufBytes, const deUint32 bufOffset, const float expected)2556 void TransformFeedbackMultiQueryTestInstance::verifyTransformFeedbackBuffer (const MovePtr<Allocation>& bufAlloc, const deUint32 bufBytes, const deUint32 bufOffset, const float expected)
2557 {
2558 const DeviceInterface& vk = m_context.getDeviceInterface();
2559 const VkDevice device = m_context.getDevice();
2560 const deUint32 numPoints = bufBytes / static_cast<deUint32>(sizeof(float));
2561 const deUint8* tfDataRaw = getInvalidatedHostPtr<deUint8>(vk, device, *bufAlloc);
2562 const float* tfData = reinterpret_cast<const float*>(&tfDataRaw[bufOffset]);
2563
2564 for (deUint32 i = 0; i < numPoints; ++i)
2565 if (tfData[i] != expected)
2566 TCU_FAIL(std::string("Failed at item ") + de::toString(i) + " received:" + de::toString(tfData[i]) + " expected:" + de::toString(expected));
2567 }
2568
iterate(void)2569 tcu::TestStatus TransformFeedbackMultiQueryTestInstance::iterate (void)
2570 {
2571 const DeviceInterface& vk = m_context.getDeviceInterface();
2572 const VkDevice device = m_context.getDevice();
2573 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
2574 const std::vector<deUint32> queueFamilyIndices = { queueFamilyIndex };
2575 const VkQueue queue = m_context.getUniversalQueue();
2576 Allocator& allocator = m_context.getDefaultAllocator();
2577
2578 const Unique<VkRenderPass> renderPass (makeRenderPass (vk, device, VK_FORMAT_UNDEFINED));
2579
2580 const Unique<VkShaderModule> vertModule (createShaderModule (vk, device, m_context.getBinaryCollection().get("vert"), 0u));
2581 const Unique<VkShaderModule> geomModule (createShaderModule (vk, device, m_context.getBinaryCollection().get("geom"), 0u));
2582
2583 const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, 0u, DE_NULL, m_imageExtent2D.width, m_imageExtent2D.height));
2584 const Unique<VkPipelineLayout> pipelineLayout (TransformFeedback::makePipelineLayout (vk, device));
2585 const Unique<VkPipeline> pipeline (makeGraphicsPipeline (vk, device, *pipelineLayout, *renderPass, *vertModule, DE_NULL, DE_NULL, *geomModule, DE_NULL, m_imageExtent2D, 0u));
2586 const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
2587 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
2588
2589 const VkBufferCreateInfo tfBufCreateInfo = makeBufferCreateInfo(m_parameters.bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT);
2590 const Move<VkBuffer> tfBuf = createBuffer(vk, device, &tfBufCreateInfo);
2591 const std::vector<VkBuffer> tfBufArray = std::vector<VkBuffer>(m_parameters.partCount, *tfBuf);
2592 const MovePtr<Allocation> tfBufAllocation = allocator.allocate(getBufferMemoryRequirements(vk, device, *tfBuf), MemoryRequirement::HostVisible);
2593 const VkMemoryBarrier tfMemoryBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT, VK_ACCESS_HOST_READ_BIT);
2594 const std::vector<VkDeviceSize> tfBufBindingSizes = generateSizesList(m_parameters.bufferSize, m_parameters.partCount);
2595 const std::vector<VkDeviceSize> tfBufBindingOffsets = generateOffsetsList(tfBufBindingSizes);
2596 const std::vector<float> tfBufExpectedValues = { 0.5f, 0.5f + float(m_parameters.streamId) };
2597 const deUint32 maxBufferSizeBytes = static_cast<deUint32>(*std::max_element(tfBufBindingSizes.begin(), tfBufBindingSizes.end()));
2598 const deUint32 bytesPerVertex = static_cast<deUint32>(4 * sizeof(float));
2599 const deUint32 numVerticesInBuffer = maxBufferSizeBytes / bytesPerVertex;
2600 const deUint32 numDrawVertices = numVerticesInBuffer / 2;
2601
2602 const deUint32 queryIndex = 0u;
2603 const deUint32 queryCountersNumber = 2u;
2604 const deUint32 queryStride = sizeof(TransformFeedbackQuery);
2605 const deUint32 queryDataSize = queryCountersNumber * queryStride;
2606 const VkQueryPoolCreateInfo queryPoolCreateInfo = makeQueryPoolCreateInfo(queryCountersNumber);
2607 const Unique<VkQueryPool> queryPool (createQueryPool(vk, device, &queryPoolCreateInfo));
2608 const deUint32 queryInvalidCounterValue = 999999u;
2609 std::vector<TransformFeedbackQuery> queryResultData (queryCountersNumber, TransformFeedbackQuery{ queryInvalidCounterValue, queryInvalidCounterValue });
2610 const std::vector<TransformFeedbackQuery> queryExpectedData ({ TransformFeedbackQuery{ numVerticesInBuffer, 3 * numDrawVertices }, TransformFeedbackQuery{ numDrawVertices, numDrawVertices } });
2611
2612 const VkBufferCreateInfo queryBufferCreateInfo = makeBufferCreateInfo(queryDataSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT, queueFamilyIndices);
2613 const Move<VkBuffer> queryPoolResultsBuffer = createBuffer(vk, device, &queryBufferCreateInfo);
2614 const MovePtr<Allocation> queryPoolResultsBufferAlloc = allocator.allocate(getBufferMemoryRequirements(vk, device, *queryPoolResultsBuffer), MemoryRequirement::HostVisible);
2615
2616 DE_ASSERT(queryCountersNumber == queryExpectedData.size());
2617
2618 VK_CHECK(vk.bindBufferMemory(device, *queryPoolResultsBuffer, queryPoolResultsBufferAlloc->getMemory(), queryPoolResultsBufferAlloc->getOffset()));
2619
2620 VK_CHECK(vk.bindBufferMemory(device, *tfBuf, tfBufAllocation->getMemory(), tfBufAllocation->getOffset()));
2621
2622 beginCommandBuffer(vk, *cmdBuffer);
2623 {
2624 vk.cmdResetQueryPool(*cmdBuffer, *queryPool, queryIndex, queryCountersNumber);
2625
2626 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
2627 {
2628 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
2629
2630 vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0u, m_parameters.partCount, &tfBufArray[0], &tfBufBindingOffsets[0], &tfBufBindingSizes[0]);
2631
2632 vk.cmdBeginQueryIndexedEXT(*cmdBuffer, *queryPool, queryIndex + 0, 0u, 0u);
2633 vk.cmdBeginQueryIndexedEXT(*cmdBuffer, *queryPool, queryIndex + 1, 0u, m_parameters.streamId);
2634 {
2635 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
2636 {
2637 vk.cmdDraw(*cmdBuffer, numDrawVertices, 1u, 0u, 0u);
2638 }
2639 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
2640 }
2641 vk.cmdEndQueryIndexedEXT(*cmdBuffer, *queryPool, queryIndex + 1, m_parameters.streamId);
2642 vk.cmdEndQueryIndexedEXT(*cmdBuffer, *queryPool, queryIndex + 0, 0);
2643 }
2644 endRenderPass(vk, *cmdBuffer);
2645
2646 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &tfMemoryBarrier, 0u, DE_NULL, 0u, DE_NULL);
2647 }
2648 endCommandBuffer(vk, *cmdBuffer);
2649 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
2650
2651 vk.getQueryPoolResults(device, *queryPool, queryIndex, queryCountersNumber, queryDataSize, queryResultData.data(), queryStride, (vk::VK_QUERY_RESULT_WAIT_BIT));
2652
2653 DE_ASSERT(queryResultData.size() == queryCountersNumber && queryExpectedData.size() == queryCountersNumber);
2654 DE_ASSERT(queryCountersNumber > 0);
2655
2656 for (size_t counterNdx = 0; counterNdx < queryCountersNumber; ++counterNdx)
2657 {
2658 const TransformFeedbackQuery& result = queryResultData[counterNdx];
2659 const TransformFeedbackQuery& expected = queryExpectedData[counterNdx];
2660
2661 DE_ASSERT(expected.written != queryInvalidCounterValue);
2662 DE_ASSERT(expected.attempts != queryInvalidCounterValue);
2663
2664 if (result.written == queryInvalidCounterValue || result.attempts == queryInvalidCounterValue)
2665 return tcu::TestStatus::fail("Query counters read failed");
2666
2667 if (result.written != expected.written)
2668 {
2669 const std::string comment = "At counter " + de::toString(counterNdx) + " vertices written " + de::toString(result.written) + ", while expected " + de::toString(expected.written);
2670
2671 return tcu::TestStatus::fail(comment.c_str());
2672 }
2673
2674
2675 if (result.attempts != expected.attempts)
2676 {
2677 const std::string comment = "At counter " + de::toString(counterNdx) + " attempts committed " + de::toString(result.attempts) + ", while expected " + de::toString(expected.attempts);
2678
2679 return tcu::TestStatus::fail(comment.c_str());
2680 }
2681
2682 if (counterNdx == 0 && !m_parameters.omitShaderWrite)
2683 verifyTransformFeedbackBuffer(tfBufAllocation, bytesPerVertex * expected.written, static_cast<deUint32>(tfBufBindingOffsets[counterNdx]), tfBufExpectedValues[counterNdx]);
2684 }
2685
2686 return tcu::TestStatus::pass("Pass");
2687 }
2688
2689
2690 class TransformFeedbackLinesOrTrianglesTestInstance : public TransformFeedbackTestInstance
2691 {
2692 public:
2693 TransformFeedbackLinesOrTrianglesTestInstance (Context& context, const TestParameters& parameters);
2694
2695 protected:
2696 std::vector<VkDeviceSize> generateSizesList (const size_t bufBytes, const size_t chunkCount);
2697 void verifyTransformFeedbackBufferLines (const MovePtr<Allocation>& bufAlloc,
2698 const deUint32 bufBytes,
2699 const std::vector<deUint32>& primitives,
2700 const deUint32 invocationCount,
2701 const deUint32 partCount);
2702 void verifyTransformFeedbackBufferTriangles (const MovePtr<Allocation>& bufAlloc,
2703 const deUint32 bufBytes,
2704 const std::vector<deUint32>& primitives,
2705 const deUint32 invocationCount,
2706 const deUint32 partCount);
2707 tcu::TestStatus iterate (void);
2708 };
2709
TransformFeedbackLinesOrTrianglesTestInstance(Context& context, const TestParameters& parameters)2710 TransformFeedbackLinesOrTrianglesTestInstance::TransformFeedbackLinesOrTrianglesTestInstance (Context& context, const TestParameters& parameters)
2711 : TransformFeedbackTestInstance (context, parameters)
2712 {
2713 const InstanceInterface& vki = m_context.getInstanceInterface();
2714 const VkPhysicalDevice physDevice = m_context.getPhysicalDevice();
2715 const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(vki, physDevice);
2716 const VkPhysicalDeviceTransformFeedbackFeaturesEXT& transformFeedbackFeatures = m_context.getTransformFeedbackFeaturesEXT();
2717 const deUint32 streamsSupported = m_transformFeedbackProperties.maxTransformFeedbackStreams;
2718 const deUint32 streamsRequired = m_parameters.streamId + 1;
2719 const deUint32 tfBuffersSupported = m_transformFeedbackProperties.maxTransformFeedbackBuffers;
2720 const deUint32 tfBuffersRequired = m_parameters.partCount;
2721
2722 DE_ASSERT(m_parameters.partCount == 2u);
2723
2724 if (m_transformFeedbackProperties.transformFeedbackStreamsLinesTriangles == DE_FALSE)
2725 TCU_THROW(NotSupportedError, "transformFeedbackStreamsLinesTriangles required");
2726
2727 if (!features.geometryShader)
2728 TCU_THROW(NotSupportedError, "Missing feature: geometryShader");
2729
2730 if (transformFeedbackFeatures.geometryStreams == DE_FALSE)
2731 TCU_THROW(NotSupportedError, "geometryStreams feature is not supported");
2732
2733 if (streamsSupported < streamsRequired)
2734 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackStreams=" + de::toString(streamsSupported) + ", while test requires " + de::toString(streamsRequired)).c_str());
2735
2736 if (tfBuffersSupported < tfBuffersRequired)
2737 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBuffers=" + de::toString(tfBuffersSupported) + ", while test requires " + de::toString(tfBuffersRequired)).c_str());
2738 }
2739
generateSizesList(const size_t bufBytes, const size_t chunkCount)2740 std::vector<VkDeviceSize> TransformFeedbackLinesOrTrianglesTestInstance::generateSizesList (const size_t bufBytes, const size_t chunkCount)
2741 {
2742 const VkDeviceSize chunkSize = bufBytes / chunkCount;
2743 std::vector<VkDeviceSize> result (chunkCount, chunkSize);
2744
2745 DE_ASSERT(chunkSize * chunkCount == bufBytes);
2746 DE_ASSERT(bufBytes <= MINIMUM_TF_BUFFER_SIZE);
2747 DE_ASSERT(bufBytes % sizeof(deUint32) == 0);
2748 DE_ASSERT(chunkCount > 0);
2749 DE_ASSERT(result.size() == chunkCount);
2750
2751 return result;
2752 }
2753
verifyTransformFeedbackBufferLines(const MovePtr<Allocation>& bufAlloc, const deUint32 bufBytes, const std::vector<deUint32>& primitives, const deUint32 invocationCount, const deUint32 partCount)2754 void TransformFeedbackLinesOrTrianglesTestInstance::verifyTransformFeedbackBufferLines (const MovePtr<Allocation>& bufAlloc,
2755 const deUint32 bufBytes,
2756 const std::vector<deUint32>& primitives,
2757 const deUint32 invocationCount,
2758 const deUint32 partCount)
2759 {
2760 const DeviceInterface& vk = m_context.getDeviceInterface();
2761 const VkDevice device = m_context.getDevice();
2762 const tcu::Vec4* tfData = getInvalidatedHostPtr<tcu::Vec4>(vk, device, *bufAlloc);
2763 const deUint32 stripeCount = static_cast<deUint32>(primitives.size());
2764 const deUint32 vertexCount = 2 * destripedLineCount(primitives) * invocationCount * partCount;
2765 const deUint32 numPoints = static_cast<deUint32>(bufBytes / sizeof(tcu::Vec4));
2766 deUint32 n = 0;
2767 std::vector<tcu::Vec4> reference;
2768
2769 reference.reserve(vertexCount);
2770
2771 for (deUint32 partNdx = 0; partNdx < partCount; ++partNdx)
2772 {
2773 for (deUint32 invocationNdx = 0; invocationNdx < invocationCount; ++invocationNdx)
2774 {
2775 for (deUint32 stripeNdx = 0; stripeNdx < stripeCount; ++stripeNdx)
2776 {
2777 const deUint32 stripeVertexCount = primitives[stripeNdx];
2778
2779 for (deUint32 vertexNdx = 0; vertexNdx < stripeVertexCount; ++vertexNdx)
2780 {
2781 const bool firstOrLast = vertexNdx == 0 || vertexNdx == stripeVertexCount - 1;
2782 const tcu::Vec4 v (float(n++), float(invocationNdx), float(stripeNdx), float(vertexNdx));
2783
2784 reference.push_back(v);
2785
2786 if (!firstOrLast)
2787 reference.push_back(v);
2788 }
2789 }
2790 }
2791 }
2792
2793 DE_ASSERT(reference.size() == numPoints);
2794
2795 const tcu::Vec4 threshold (0.0001f, 0.0001f, 0.0001f, 0.0001f);
2796 const auto errors = verifyVertexDataWithWinding(reference, tfData, numPoints, 2u, threshold);
2797 checkErrorVec(m_context.getTestContext().getLog(), errors);
2798 }
2799
verifyTransformFeedbackBufferTriangles(const MovePtr<Allocation>& bufAlloc, const deUint32 bufBytes, const std::vector<deUint32>& primitives, const deUint32 invocationCount, const deUint32 partCount)2800 void TransformFeedbackLinesOrTrianglesTestInstance::verifyTransformFeedbackBufferTriangles (const MovePtr<Allocation>& bufAlloc,
2801 const deUint32 bufBytes,
2802 const std::vector<deUint32>& primitives,
2803 const deUint32 invocationCount,
2804 const deUint32 partCount)
2805 {
2806 const DeviceInterface& vk = m_context.getDeviceInterface();
2807 const VkDevice device = m_context.getDevice();
2808 const tcu::Vec4* tfData = getInvalidatedHostPtr<tcu::Vec4>(vk, device, *bufAlloc);
2809 const deUint32 stripeCount = static_cast<deUint32>(primitives.size());
2810 const deUint32 vertexCount = 3 * destripedLineCount(primitives) * invocationCount * partCount;
2811 const deUint32 numPoints = static_cast<deUint32>(bufBytes / sizeof(tcu::Vec4));
2812 deUint32 n = 0;
2813 std::vector<tcu::Vec4> reference;
2814
2815 reference.reserve(vertexCount);
2816
2817 for (deUint32 partNdx = 0; partNdx < partCount; ++partNdx)
2818 {
2819 for (deUint32 invocationNdx = 0; invocationNdx < invocationCount; ++invocationNdx)
2820 {
2821 for (deUint32 stripeNdx = 0; stripeNdx < stripeCount; ++stripeNdx)
2822 {
2823 const deUint32 stripeVertexCount = primitives[stripeNdx];
2824 const deUint32 trianglesCount = stripeVertexCount - 2;
2825 std::vector<tcu::Vec4> stripe (stripeVertexCount);
2826
2827 for (deUint32 vertexNdx = 0; vertexNdx < stripeVertexCount; ++vertexNdx)
2828 stripe[vertexNdx] = tcu::Vec4(float(n++), float(invocationNdx), float(stripeNdx), float(vertexNdx));
2829
2830 for (deUint32 triangleNdx = 0; triangleNdx < trianglesCount; ++triangleNdx)
2831 {
2832 if (triangleNdx % 2 == 0)
2833 {
2834 reference.push_back(stripe[triangleNdx + 0]);
2835 reference.push_back(stripe[triangleNdx + 1]);
2836 reference.push_back(stripe[triangleNdx + 2]);
2837 }
2838 else
2839 {
2840 reference.push_back(stripe[triangleNdx + 0]);
2841 reference.push_back(stripe[triangleNdx + 2]);
2842 reference.push_back(stripe[triangleNdx + 1]);
2843 }
2844 }
2845 }
2846 }
2847 }
2848
2849 DE_ASSERT(reference.size() == numPoints);
2850
2851 const tcu::Vec4 threshold (0.0001f, 0.0001f, 0.0001f, 0.0001f);
2852 const auto errors = verifyVertexDataWithWinding(reference, tfData, numPoints, 3u, threshold);
2853 checkErrorVec(m_context.getTestContext().getLog(), errors);
2854 }
2855
iterate(void)2856 tcu::TestStatus TransformFeedbackLinesOrTrianglesTestInstance::iterate (void)
2857 {
2858 const DeviceInterface& vk = m_context.getDeviceInterface();
2859 const VkDevice device = m_context.getDevice();
2860 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
2861 const VkQueue queue = m_context.getUniversalQueue();
2862 Allocator& allocator = m_context.getDefaultAllocator();
2863
2864 const Unique<VkRenderPass> renderPass (makeRenderPass (vk, device, VK_FORMAT_UNDEFINED));
2865
2866 const Unique<VkShaderModule> vertexModule (createShaderModule (vk, device, m_context.getBinaryCollection().get("vert"), 0u));
2867 const Unique<VkShaderModule> geomModule (createShaderModule (vk, device, m_context.getBinaryCollection().get("geom"), 0u));
2868
2869 const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, 0u, DE_NULL, m_imageExtent2D.width, m_imageExtent2D.height));
2870 const Unique<VkPipelineLayout> pipelineLayout (TransformFeedback::makePipelineLayout (vk, device));
2871 const Unique<VkPipeline> pipeline (makeGraphicsPipeline (vk, device, *pipelineLayout, *renderPass, *vertexModule, DE_NULL, DE_NULL, *geomModule, DE_NULL, m_imageExtent2D, 0u, &m_parameters.streamId));
2872 const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
2873 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
2874
2875 const deUint32 tfBufferSize = m_parameters.bufferSize;
2876 const VkBufferCreateInfo tfBufCreateInfo = makeBufferCreateInfo(tfBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT);
2877 const Move<VkBuffer> tfBuf = createBuffer(vk, device, &tfBufCreateInfo);
2878 const std::vector<VkBuffer> tfBufArray = std::vector<VkBuffer>(m_parameters.partCount, *tfBuf);
2879 const MovePtr<Allocation> tfBufAllocation = allocator.allocate(getBufferMemoryRequirements(vk, device, *tfBuf), MemoryRequirement::HostVisible);
2880 const VkMemoryBarrier tfMemoryBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT, VK_ACCESS_HOST_READ_BIT);
2881 const std::vector<VkDeviceSize> tfBufBindingSizes = generateSizesList(tfBufferSize, m_parameters.partCount);
2882 const std::vector<VkDeviceSize> tfBufBindingOffsets = generateOffsetsList(tfBufBindingSizes);
2883
2884 VK_CHECK(vk.bindBufferMemory(device, *tfBuf, tfBufAllocation->getMemory(), tfBufAllocation->getOffset()));
2885
2886 beginCommandBuffer(vk, *cmdBuffer);
2887 {
2888 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
2889 {
2890 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
2891
2892 vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0u, m_parameters.partCount, &tfBufArray[0], &tfBufBindingOffsets[0], &tfBufBindingSizes[0]);
2893
2894 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
2895 {
2896 vk.cmdDraw(*cmdBuffer, INVOCATION_COUNT, 1u, 0u, 0u);
2897 }
2898 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
2899 }
2900 endRenderPass(vk, *cmdBuffer);
2901
2902 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &tfMemoryBarrier, 0u, DE_NULL, 0u, DE_NULL);
2903 }
2904 endCommandBuffer(vk, *cmdBuffer);
2905 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
2906
2907 switch (m_parameters.primTopology)
2908 {
2909 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP: verifyTransformFeedbackBufferLines(tfBufAllocation, tfBufferSize, LINES_LIST, INVOCATION_COUNT, m_parameters.partCount); break;
2910 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP: verifyTransformFeedbackBufferTriangles(tfBufAllocation, tfBufferSize, TRIANGLES_LIST, INVOCATION_COUNT, m_parameters.partCount); break;
2911 default: TCU_THROW(InternalError, "Unknown topology");
2912 }
2913
2914 return tcu::TestStatus::pass("Pass");
2915 }
2916
2917 class TransformFeedbackDrawOutsideTestInstance : public TransformFeedbackTestInstance
2918 {
2919 public:
2920 TransformFeedbackDrawOutsideTestInstance (Context& context, const TestParameters& parameters);
2921
2922 protected:
2923 tcu::TestStatus iterate (void);
2924 };
2925
TransformFeedbackDrawOutsideTestInstance(Context& context, const TestParameters& parameters)2926 TransformFeedbackDrawOutsideTestInstance::TransformFeedbackDrawOutsideTestInstance(Context& context, const TestParameters& parameters)
2927 : TransformFeedbackTestInstance (context, parameters)
2928 {
2929 }
2930
iterate(void)2931 tcu::TestStatus TransformFeedbackDrawOutsideTestInstance::iterate (void)
2932 {
2933 const DeviceInterface& vk = m_context.getDeviceInterface();
2934 const VkDevice device = m_context.getDevice();
2935 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
2936 const VkQueue queue = m_context.getUniversalQueue();
2937 Allocator& allocator = m_context.getDefaultAllocator();
2938
2939 const Unique<VkShaderModule> vertexModule1 (createShaderModule (vk, device, m_context.getBinaryCollection().get("vert"), 0u));
2940 const Unique<VkShaderModule> vertexModule2 (createShaderModule (vk, device, m_context.getBinaryCollection().get("vert2"), 0u));
2941 const Unique<VkRenderPass> renderPass (makeRenderPass (vk, device, VK_FORMAT_UNDEFINED));
2942 const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, 0u, DE_NULL, m_imageExtent2D.width, m_imageExtent2D.height));
2943 const Unique<VkPipelineLayout> pipelineLayout (TransformFeedback::makePipelineLayout (vk, device));
2944 const Unique<VkPipeline> pipeline1 (makeGraphicsPipeline (vk, device, *pipelineLayout, *renderPass, *vertexModule1, DE_NULL, DE_NULL, DE_NULL, DE_NULL, m_imageExtent2D, 0u, &m_parameters.streamId));
2945 const Unique<VkPipeline> pipeline2 (makeGraphicsPipeline (vk, device, *pipelineLayout, *renderPass, *vertexModule2, DE_NULL, DE_NULL, DE_NULL, DE_NULL, m_imageExtent2D, 0u, &m_parameters.streamId));
2946 const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
2947 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
2948
2949 const VkBufferCreateInfo tfBufCreateInfo = makeBufferCreateInfo(m_parameters.bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT);
2950 const Move<VkBuffer> tfBuf = createBuffer(vk, device, &tfBufCreateInfo);
2951 const MovePtr<Allocation> tfBufAllocation = allocator.allocate(getBufferMemoryRequirements(vk, device, *tfBuf), MemoryRequirement::HostVisible);
2952 const VkMemoryBarrier tfMemoryBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT, VK_ACCESS_HOST_READ_BIT);
2953 const std::vector<VkDeviceSize> tfBufBindingSizes = generateSizesList(m_parameters.bufferSize, m_parameters.partCount);
2954 const std::vector<VkDeviceSize> tfBufBindingOffsets = generateOffsetsList(tfBufBindingSizes);
2955
2956 VK_CHECK(vk.bindBufferMemory(device, *tfBuf, tfBufAllocation->getMemory(), tfBufAllocation->getOffset()));
2957
2958 beginCommandBuffer(vk, *cmdBuffer);
2959 {
2960 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
2961 {
2962 for (deUint32 i = 0; i < 2; ++i)
2963 {
2964 if (i == 0)
2965 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline1);
2966 else
2967 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline2);
2968
2969 for (deUint32 drawNdx = 0; drawNdx < m_parameters.partCount; ++drawNdx)
2970 {
2971 const deUint32 startValue = static_cast<deUint32>(tfBufBindingOffsets[drawNdx] / sizeof(deUint32));
2972 const deUint32 numPoints = static_cast<deUint32>(tfBufBindingSizes[drawNdx] / sizeof(deUint32));
2973
2974 vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0, 1, &*tfBuf, &tfBufBindingOffsets[drawNdx], &tfBufBindingSizes[drawNdx]);
2975
2976 vk.cmdPushConstants(*cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0u, sizeof(startValue), &startValue);
2977
2978 if (i == 0)
2979 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
2980 {
2981 vk.cmdDraw(*cmdBuffer, numPoints, 1u, 0u, 0u);
2982 }
2983 if (i == 0)
2984 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
2985 }
2986 }
2987 }
2988 endRenderPass(vk, *cmdBuffer);
2989
2990 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &tfMemoryBarrier, 0u, DE_NULL, 0u, DE_NULL);
2991 }
2992 endCommandBuffer(vk, *cmdBuffer);
2993 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
2994
2995 verifyTransformFeedbackBuffer(tfBufAllocation, m_parameters.bufferSize);
2996
2997 return tcu::TestStatus::pass("Pass");
2998 }
2999
3000 class TransformFeedbackHolesInstance : public vkt::TestInstance
3001 {
3002 public:
TransformFeedbackHolesInstance(Context& context, const bool extraDraw)3003 TransformFeedbackHolesInstance (Context& context, const bool extraDraw)
3004 : vkt::TestInstance (context)
3005 , m_extraDraw (extraDraw)
3006 {}
~TransformFeedbackHolesInstance(void)3007 ~TransformFeedbackHolesInstance (void) {}
3008
3009 tcu::TestStatus iterate (void) override;
3010
3011 protected:
3012 const bool m_extraDraw;
3013 };
3014
iterate(void)3015 tcu::TestStatus TransformFeedbackHolesInstance::iterate (void)
3016 {
3017 const auto& ctx = m_context.getContextCommonData();
3018 const tcu::IVec3 fbExtent (1, 1, 1);
3019 const auto vkExtent = makeExtent3D(fbExtent);
3020 const auto fbFormat = VK_FORMAT_R8G8B8A8_UNORM;
3021 const auto tcuFormat = mapVkFormat(fbFormat);
3022 const auto fbUsage = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
3023 const tcu::Vec4 clearColor (0.0f, 0.0f, 0.0f, 1.0f);
3024 const tcu::Vec4 geomColor (0.0f, 0.0f, 1.0f, 1.0f); // Must match frag shader values.
3025 const tcu::Vec4 threshold (0.0f, 0.0f, 0.0f, 0.0f); // When using 0 and 1 only, we expect exact results.
3026 const auto bindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
3027 const auto& binaries = m_context.getBinaryCollection();
3028 const bool hasGeom = binaries.contains("geom");
3029 const auto dataStages = (hasGeom ? VK_SHADER_STAGE_GEOMETRY_BIT : VK_SHADER_STAGE_VERTEX_BIT);
3030 const auto xfbCompCount = 3u; // Per vertex.
3031 const auto xfbChunkSize = xfbCompCount * sizeof(float); // Per vertex, in bytes.
3032 const auto totalDraws = (m_extraDraw ? 2u : 1u);
3033
3034 // Color buffer with verification buffer.
3035 ImageWithBuffer colorBuffer (
3036 ctx.vkd,
3037 ctx.device,
3038 ctx.allocator,
3039 vkExtent,
3040 fbFormat,
3041 fbUsage,
3042 VK_IMAGE_TYPE_2D);
3043
3044 // Vertices.
3045 const std::vector<tcu::Vec4> vertices { tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f) };
3046
3047 // Vertex buffer.
3048 const auto vbSize = static_cast<VkDeviceSize>(de::dataSize(vertices));
3049 const auto vbInfo = makeBufferCreateInfo(vbSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
3050 BufferWithMemory vertexBuffer (ctx.vkd, ctx.device, ctx.allocator, vbInfo, MemoryRequirement::HostVisible);
3051 const auto vbAlloc = vertexBuffer.getAllocation();
3052 void* vbData = vbAlloc.getHostPtr();
3053 const auto vbOffset = static_cast<VkDeviceSize>(0);
3054
3055 deMemcpy(vbData, de::dataOrNull(vertices), de::dataSize(vertices));
3056 flushAlloc(ctx.vkd, ctx.device, vbAlloc);
3057
3058 // XFB buffer. When using an extra draw, leave space for a possible second draw (NB: but it should not be recorded, see below).
3059 const auto xfbSizeFactor = static_cast<VkDeviceSize>(totalDraws);
3060 const auto xfbBufferSize = static_cast<VkDeviceSize>(xfbChunkSize * vertices.size()) * xfbSizeFactor;
3061 const auto xfbBufferInfo = makeBufferCreateInfo(xfbBufferSize, VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT);
3062 BufferWithMemory xfbBuffer (ctx.vkd, ctx.device, ctx.allocator, xfbBufferInfo, MemoryRequirement::HostVisible);
3063 const auto xfbBufferAlloc = xfbBuffer.getAllocation();
3064 void* xfbBufferData = xfbBufferAlloc.getHostPtr();
3065 const auto xfbBufferOffset = static_cast<VkDeviceSize>(0);
3066
3067 deMemset(xfbBufferData, 0, static_cast<size_t>(xfbBufferSize));
3068 flushAlloc(ctx.vkd, ctx.device, xfbBufferAlloc);
3069
3070 // Push constants.
3071 const tcu::Vec3 pcData { 10.0, 20.0, 30.0 }; // Must match the expected values in the frag shader.
3072 const auto pcSize = static_cast<uint32_t>(sizeof(pcData));
3073 const auto pcRange = makePushConstantRange(dataStages, 0u, pcSize);
3074
3075 const auto pipelineLayout = makePipelineLayout(ctx.vkd, ctx.device, VK_NULL_HANDLE, &pcRange);
3076 const auto renderPass = makeRenderPass(ctx.vkd, ctx.device, fbFormat);
3077 const auto framebuffer = makeFramebuffer(ctx.vkd, ctx.device, *renderPass, colorBuffer.getImageView(), vkExtent.width, vkExtent.height);
3078
3079 // Modules.
3080 const auto vertModule = createShaderModule(ctx.vkd, ctx.device, binaries.get("vert"));
3081 const auto geomModule = (hasGeom ? createShaderModule(ctx.vkd, ctx.device, binaries.get("geom")) : Move<VkShaderModule>());
3082 const auto fragModule = createShaderModule(ctx.vkd, ctx.device, binaries.get("frag"));
3083
3084 const std::vector<VkViewport> viewports (1u, makeViewport(vkExtent));
3085 const std::vector<VkRect2D> scissors (1u, makeRect2D(vkExtent));
3086
3087 const auto pipeline = makeGraphicsPipeline(ctx.vkd, ctx.device, *pipelineLayout,
3088 *vertModule, VK_NULL_HANDLE, VK_NULL_HANDLE, *geomModule, *fragModule,
3089 *renderPass, viewports, scissors, VK_PRIMITIVE_TOPOLOGY_POINT_LIST);
3090
3091 CommandPoolWithBuffer cmd (ctx.vkd, ctx.device, ctx.qfIndex);
3092 const auto cmdBuffer = *cmd.cmdBuffer;
3093
3094 beginCommandBuffer(ctx.vkd, cmdBuffer);
3095 beginRenderPass(ctx.vkd, cmdBuffer, *renderPass, *framebuffer, scissors.at(0u), clearColor);
3096 ctx.vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vbOffset);
3097 ctx.vkd.cmdBindPipeline(cmdBuffer, bindPoint, *pipeline);
3098 ctx.vkd.cmdPushConstants(cmdBuffer, *pipelineLayout, dataStages, 0u, pcSize, &pcData);
3099 ctx.vkd.cmdBindTransformFeedbackBuffersEXT(cmdBuffer, 0u, 1u, &xfbBuffer.get(), &xfbBufferOffset, &xfbBufferSize);
3100 ctx.vkd.cmdBeginTransformFeedbackEXT(cmdBuffer, 0u, 0u, nullptr, nullptr);
3101 ctx.vkd.cmdDraw(cmdBuffer, de::sizeU32(vertices), 1u, 0u, 0u);
3102 ctx.vkd.cmdEndTransformFeedbackEXT(cmdBuffer, 0u, 0u, nullptr, nullptr);
3103 if (m_extraDraw)
3104 {
3105 // When m_extraDraw is true, record a new draw outside the transform feedback section. The XFB buffer will have enough space
3106 // to record this draw, but it should not be recorded, obviously, so the values in the buffer should stay zero. We are also
3107 // avoiding any state changes between both draws.
3108 ctx.vkd.cmdDraw(cmdBuffer, de::sizeU32(vertices), 1u, 0u, 0u);
3109 }
3110 endRenderPass(ctx.vkd, cmdBuffer);
3111 const auto xfbBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT, VK_ACCESS_HOST_READ_BIT);
3112 ctx.vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &xfbBarrier, 0u, nullptr, 0u, nullptr);
3113 copyImageToBuffer(ctx.vkd, cmdBuffer, colorBuffer.getImage(), colorBuffer.getBuffer(),
3114 fbExtent.swizzle(0, 1), VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 1u,
3115 VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_ASPECT_COLOR_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
3116 endCommandBuffer(ctx.vkd, cmdBuffer);
3117 submitCommandsAndWait(ctx.vkd, ctx.device, ctx.queue, cmdBuffer);
3118
3119 // Verify color output.
3120 invalidateAlloc(ctx.vkd, ctx.device, colorBuffer.getBufferAllocation());
3121 tcu::PixelBufferAccess resultAccess (tcuFormat, fbExtent, colorBuffer.getBufferAllocation().getHostPtr());
3122
3123 tcu::TextureLevel referenceLevel (tcuFormat, fbExtent.x(), fbExtent.y());
3124 auto referenceAccess = referenceLevel.getAccess();
3125 tcu::clear(referenceAccess, geomColor);
3126
3127 auto& log = m_context.getTestContext().getLog();
3128 if (!tcu::floatThresholdCompare(log, "Result", "", referenceAccess, resultAccess, threshold, tcu::COMPARE_LOG_ON_ERROR))
3129 return tcu::TestStatus::fail("Unexpected color in result buffer; check log for details");
3130
3131 // Verify XFB buffer.
3132 const tcu::Vec3 refRecordedValues { pcData.x(), 0.0f, pcData.z() }; // Per-vertex, must match vert/geom shader, note Y is not saved.
3133 const tcu::Vec3 refEmptyValues { 0.0f, 0.0f, 0.0f }; // For empty areas of the XFB buffer.
3134 const auto dataPtr = reinterpret_cast<const char*>(xfbBufferData);
3135
3136 for (uint32_t drawIdx = 0u; drawIdx < totalDraws; ++drawIdx)
3137 {
3138 const auto& refValues = ((drawIdx > 0u) ? refEmptyValues : refRecordedValues);
3139 for (size_t vertIdx = 0u; vertIdx < vertices.size(); ++vertIdx)
3140 {
3141 const auto vertexDataPtr = dataPtr + (vertIdx * xfbChunkSize) + (drawIdx * vertices.size() * xfbChunkSize);
3142 tcu::Vec3 vertValues (0.0f, 0.0f, 0.0f);
3143 deMemcpy(&vertValues, vertexDataPtr, sizeof(vertValues));
3144
3145 if (vertValues != refValues)
3146 {
3147 std::ostringstream msg;
3148 msg << "Invalid data found for vertex " << vertIdx << ": expected " << refRecordedValues << " and found " << vertValues;
3149 TCU_FAIL(msg.str());
3150 }
3151 }
3152 }
3153
3154 return tcu::TestStatus::pass("Pass");
3155 }
3156
3157 class TransformFeedbackTestCase : public vkt::TestCase
3158 {
3159 public:
3160 TransformFeedbackTestCase (tcu::TestContext &context, const char *name, const TestParameters& parameters);
3161
3162 protected:
3163 vkt::TestInstance* createInstance (vkt::Context& context) const;
3164 void initPrograms (SourceCollections& programCollection) const;
3165 virtual void checkSupport (Context& context) const;
3166
3167 TestParameters m_parameters;
3168 };
3169
TransformFeedbackTestCase(tcu::TestContext &context, const char *name, const TestParameters& parameters)3170 TransformFeedbackTestCase::TransformFeedbackTestCase (tcu::TestContext &context, const char *name, const TestParameters& parameters)
3171 : TestCase (context, name)
3172 , m_parameters (parameters)
3173 {
3174 }
3175
vectorToString(const std::vector<deUint32>& v)3176 std::string vectorToString (const std::vector<deUint32>& v)
3177 {
3178 std::ostringstream css;
3179
3180 DE_ASSERT(!v.empty());
3181
3182 for (auto x: v)
3183 css << x << ",";
3184
3185 return css.str().substr(0, css.str().size() - 1);
3186 }
3187
createInstance(vkt::Context& context) const3188 vkt::TestInstance* TransformFeedbackTestCase::createInstance (vkt::Context& context) const
3189 {
3190 if (m_parameters.testType == TEST_TYPE_BASIC)
3191 return new TransformFeedbackBasicTestInstance(context, m_parameters);
3192
3193 if (m_parameters.testType == TEST_TYPE_RESUME)
3194 return new TransformFeedbackResumeTestInstance(context, m_parameters);
3195
3196 if (m_parameters.testType == TEST_TYPE_XFB_POINTSIZE)
3197 return new TransformFeedbackBuiltinTestInstance(context, m_parameters);
3198
3199 if (m_parameters.testType == TEST_TYPE_XFB_CLIPDISTANCE)
3200 return new TransformFeedbackBuiltinTestInstance(context, m_parameters);
3201
3202 if (m_parameters.testType == TEST_TYPE_XFB_CULLDISTANCE)
3203 return new TransformFeedbackBuiltinTestInstance(context, m_parameters);
3204
3205 if (m_parameters.testType == TEST_TYPE_XFB_CLIP_AND_CULL)
3206 return new TransformFeedbackBuiltinTestInstance(context, m_parameters);
3207
3208 if (m_parameters.testType == TEST_TYPE_WINDING)
3209 return new TransformFeedbackWindingOrderTestInstance(context, m_parameters);
3210
3211 if (m_parameters.testType == TEST_TYPE_STREAMS)
3212 return new TransformFeedbackStreamsTestInstance(context, m_parameters);
3213
3214 if (m_parameters.testType == TEST_TYPE_STREAMS_POINTSIZE)
3215 return new TransformFeedbackStreamsTestInstance(context, m_parameters);
3216
3217 if (m_parameters.testType == TEST_TYPE_STREAMS_CLIPDISTANCE)
3218 return new TransformFeedbackStreamsTestInstance(context, m_parameters);
3219
3220 if (m_parameters.testType == TEST_TYPE_STREAMS_CULLDISTANCE)
3221 return new TransformFeedbackStreamsTestInstance(context, m_parameters);
3222
3223 if (m_parameters.testType == TEST_TYPE_MULTISTREAMS)
3224 return new TransformFeedbackMultistreamTestInstance(context, m_parameters);
3225
3226 if (m_parameters.testType == TEST_TYPE_MULTISTREAMS_SAME_LOCATION)
3227 return new TransformFeedbackMultistreamSameLocationTestInstance(context, m_parameters);
3228
3229 if (m_parameters.testType == TEST_TYPE_DRAW_INDIRECT)
3230 return new TransformFeedbackIndirectDrawTestInstance(context, m_parameters, false);
3231
3232 if (m_parameters.testType == TEST_TYPE_DRAW_INDIRECT_MULTIVIEW)
3233 return new TransformFeedbackIndirectDrawTestInstance(context, m_parameters, true);
3234
3235 if (m_parameters.testType == TEST_TYPE_BACKWARD_DEPENDENCY || m_parameters.testType == TEST_TYPE_BACKWARD_DEPENDENCY_INDIRECT)
3236 return new TransformFeedbackBackwardDependencyTestInstance(context, m_parameters);
3237
3238 if (m_parameters.testType == TEST_TYPE_QUERY_GET ||
3239 m_parameters.testType == TEST_TYPE_QUERY_COPY ||
3240 m_parameters.testType == TEST_TYPE_QUERY_COPY_STRIDE_ZERO ||
3241 m_parameters.testType == TEST_TYPE_QUERY_RESET)
3242 return new TransformFeedbackQueryTestInstance(context, m_parameters);
3243
3244 if (m_parameters.testType == TEST_TYPE_MULTIQUERY)
3245 return new TransformFeedbackMultiQueryTestInstance(context, m_parameters);
3246
3247 if (m_parameters.testType == TEST_TYPE_DEPTH_CLIP_CONTROL_VERTEX ||
3248 m_parameters.testType == TEST_TYPE_DEPTH_CLIP_CONTROL_GEOMETRY ||
3249 m_parameters.testType == TEST_TYPE_DEPTH_CLIP_CONTROL_TESE)
3250 return new TransformFeedbackDepthClipControlTestInstance(context, m_parameters);
3251
3252 if (m_parameters.testType == TEST_TYPE_LINES_TRIANGLES)
3253 return new TransformFeedbackLinesOrTrianglesTestInstance(context, m_parameters);
3254
3255 if (m_parameters.testType == TEST_TYPE_DRAW_OUTSIDE)
3256 return new TransformFeedbackDrawOutsideTestInstance(context, m_parameters);
3257
3258 if (m_parameters.testType == TEST_TYPE_HOLES_VERTEX || m_parameters.testType == TEST_TYPE_HOLES_GEOMETRY)
3259 {
3260 // We repurpose partCount to indicate somehow the number of draws.
3261 const bool extraDraw = (m_parameters.partCount > 1u);
3262 return new TransformFeedbackHolesInstance (context, extraDraw);
3263 }
3264
3265 TCU_THROW(InternalError, "Specified test type not found");
3266 }
3267
checkSupport(Context& context) const3268 void TransformFeedbackTestCase::checkSupport (Context& context) const
3269 {
3270 context.requireDeviceFunctionality("VK_EXT_transform_feedback");
3271
3272 if (context.getTransformFeedbackFeaturesEXT().transformFeedback == VK_FALSE)
3273 TCU_THROW(NotSupportedError, "transformFeedback feature is not supported");
3274
3275 if (m_parameters.useMaintenance5)
3276 context.requireDeviceFunctionality("VK_KHR_maintenance5");
3277
3278 // transformFeedbackRasterizationStreamSelect is required when vertex streams other than zero are rasterized
3279 if (m_parameters.requireRastStreamSelect && (context.getTransformFeedbackPropertiesEXT().transformFeedbackRasterizationStreamSelect == VK_FALSE) && (m_parameters.streamId > 0))
3280 TCU_THROW(NotSupportedError, "transformFeedbackRasterizationStreamSelect property is not supported");
3281
3282 if (m_parameters.testType == TEST_TYPE_DRAW_INDIRECT_MULTIVIEW)
3283 {
3284 const auto& features = context.getMultiviewFeatures();
3285 if (!features.multiview)
3286 TCU_THROW(NotSupportedError, "multiview not supported");
3287 }
3288
3289 if (m_parameters.testType == TEST_TYPE_BACKWARD_DEPENDENCY_INDIRECT)
3290 context.requireDeviceFunctionality("VK_KHR_draw_indirect_count");
3291
3292 if (m_parameters.testType == TEST_TYPE_HOLES_GEOMETRY)
3293 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
3294 }
3295
initPrograms(SourceCollections& programCollection) const3296 void TransformFeedbackTestCase::initPrograms (SourceCollections& programCollection) const
3297 {
3298 const bool backwardDependency = (m_parameters.testType == TEST_TYPE_BACKWARD_DEPENDENCY
3299 || m_parameters.testType == TEST_TYPE_BACKWARD_DEPENDENCY_INDIRECT);
3300 const bool vertexShaderOnly = m_parameters.testType == TEST_TYPE_BASIC
3301 || m_parameters.testType == TEST_TYPE_RESUME
3302 || (m_parameters.testType == TEST_TYPE_WINDING && m_parameters.primTopology != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST);
3303 const bool requiresFullPipeline = m_parameters.testType == TEST_TYPE_STREAMS
3304 || m_parameters.testType == TEST_TYPE_STREAMS_POINTSIZE
3305 || m_parameters.testType == TEST_TYPE_STREAMS_CULLDISTANCE
3306 || m_parameters.testType == TEST_TYPE_STREAMS_CLIPDISTANCE
3307 || (m_parameters.testType == TEST_TYPE_WINDING && m_parameters.primTopology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST);
3308 const bool xfbBuiltinPipeline = m_parameters.testType == TEST_TYPE_XFB_POINTSIZE
3309 || m_parameters.testType == TEST_TYPE_XFB_CLIPDISTANCE
3310 || m_parameters.testType == TEST_TYPE_XFB_CULLDISTANCE
3311 || m_parameters.testType == TEST_TYPE_XFB_CLIP_AND_CULL;
3312
3313 if (m_parameters.testType == TEST_TYPE_DEPTH_CLIP_CONTROL_VERTEX)
3314 {
3315 // Vertex shader
3316 {
3317 std::ostringstream src;
3318 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
3319 << "\n"
3320 << "layout(xfb_buffer = 0, xfb_offset = 0) out gl_PerVertex\n"
3321 << "{\n"
3322 << " vec4 gl_Position;\n"
3323 << "};\n"
3324 << "\n"
3325 << "void main(void)\n"
3326 << "{\n"
3327 << " gl_Position = vec4(1.0, 1.0, float(gl_VertexIndex) / 3.0 - 1.0, 1.0);\n"
3328 << "}\n";
3329
3330 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
3331 }
3332
3333 return;
3334 }
3335
3336 if (m_parameters.testType == TEST_TYPE_DEPTH_CLIP_CONTROL_GEOMETRY)
3337 {
3338 // Vertex shader
3339 {
3340 std::ostringstream src;
3341 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
3342 << "\n"
3343 << "void main(void)\n"
3344 << "{\n"
3345 << " gl_Position = vec4(1.0, 1.0, float(gl_VertexIndex) / 3.0 - 1.0, 1.0);\n"
3346 << "}\n";
3347
3348 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
3349 }
3350
3351 // Geometry shader
3352 {
3353 std::ostringstream src;
3354 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
3355 << "\n"
3356 << "layout(points) in;\n"
3357 << "layout(points, max_vertices = 1) out;\n"
3358 << "layout(xfb_buffer = 0, xfb_offset = 0) out gl_PerVertex\n"
3359 << "{\n"
3360 << " vec4 gl_Position;\n"
3361 << "};\n"
3362 << "\n"
3363 << "void main(void)\n"
3364 << "{\n"
3365 << " gl_Position = gl_in[0].gl_Position;\n"
3366 << " EmitVertex();\n"
3367 << " EndPrimitive();\n"
3368 << "}\n";
3369
3370 programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
3371 }
3372
3373 return;
3374 }
3375
3376 if (m_parameters.testType == TEST_TYPE_DEPTH_CLIP_CONTROL_TESE)
3377 {
3378 // Vertex shader
3379 {
3380 std::ostringstream src;
3381 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
3382 << "\n"
3383 << "void main(void)\n"
3384 << "{\n"
3385 << " gl_Position = vec4(1.0, 1.0, float(gl_VertexIndex) / 3.0 - 1.0, 1.0);\n"
3386 << "}\n";
3387
3388 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
3389 }
3390
3391 // Tesselation control shader
3392 {
3393 std::ostringstream src;
3394 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
3395 << "layout(vertices = 3) out;\n"
3396 << "void main (void)\n"
3397 << "{\n"
3398 << " gl_TessLevelInner[0] = 0.0;\n"
3399 << " gl_TessLevelOuter[0] = 1.0;\n"
3400 << " gl_TessLevelOuter[1] = 1.0;\n"
3401 << " gl_TessLevelOuter[2] = 1.0;\n"
3402 << " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
3403 << "}\n";
3404 programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str());
3405 }
3406
3407 // Tessellation evaluation shader
3408 {
3409 std::ostringstream src;
3410 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
3411 << "layout(triangles, ccw) in;\n"
3412 << "layout(xfb_buffer = 0, xfb_offset = 0) out gl_PerVertex\n"
3413 << "{\n"
3414 << " vec4 gl_Position;\n"
3415 << "};\n"
3416 << "\n"
3417 << "void main (void)\n"
3418 << "{\n"
3419 << " vec4 p0 = gl_TessCoord.x * gl_in[0].gl_Position;\n"
3420 << " vec4 p1 = gl_TessCoord.y * gl_in[1].gl_Position;\n"
3421 << " vec4 p2 = gl_TessCoord.z * gl_in[2].gl_Position;\n"
3422 << " gl_Position = p0 + p1 + p2;\n"
3423 << "}\n";
3424 programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
3425 }
3426
3427 return;
3428 }
3429
3430 if (vertexShaderOnly)
3431 {
3432 // Vertex shader
3433 {
3434 std::ostringstream src;
3435 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
3436 << "\n"
3437 << "layout(push_constant) uniform pushConstants\n"
3438 << "{\n"
3439 << " uint start;\n"
3440 << "} uInput;\n"
3441 << "\n"
3442 << "layout(xfb_buffer = 0, xfb_offset = 0, xfb_stride = 4, location = 0) out uint idx_out;\n"
3443 << "\n"
3444 << "void main(void)\n"
3445 << "{\n"
3446 << " idx_out = uInput.start + gl_VertexIndex;\n"
3447 << "}\n";
3448
3449 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
3450 }
3451
3452 return;
3453 }
3454
3455 if (backwardDependency)
3456 {
3457 // Vertex shader.
3458 {
3459 std::ostringstream src;
3460 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
3461 << "\n"
3462 << "layout(push_constant, std430) uniform PushConstantBlock\n"
3463 << "{\n"
3464 << " uint start;\n"
3465 << " float width;\n"
3466 << " float posY;\n"
3467 << "} pc;\n"
3468 << "\n"
3469 << "layout(xfb_buffer = 0, xfb_offset = 0, xfb_stride = 4, location = 0) out uint idx_out;\n"
3470 << "\n"
3471 << "void main(void)\n"
3472 << "{\n"
3473 << " idx_out = pc.start + gl_VertexIndex;\n"
3474 << " const float posX = ((float(gl_VertexIndex) + 0.5) / pc.width) * 2.0 - 1.0;\n"
3475 << " gl_Position = vec4(posX, pc.posY, 0.0, 1.0);\n"
3476 << " gl_PointSize = 1.0;\n"
3477 << "}\n";
3478
3479 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
3480 }
3481
3482 // Fragment shader.
3483 {
3484 std::ostringstream frag;
3485 frag
3486 << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
3487 << "layout (location=0) out vec4 outColor;\n"
3488 << "void main (void) { outColor = vec4(0.0, 0.0, 1.0, 1.0); }\n"
3489 ;
3490 programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
3491 }
3492
3493 return;
3494 }
3495
3496 if (m_parameters.primTopology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST)
3497 {
3498 // Vertex shader
3499 {
3500 std::ostringstream src;
3501 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
3502 << "layout(push_constant) uniform pushConstants\n"
3503 << "{\n"
3504 << " uint start;\n"
3505 << "} uInput;\n"
3506 << "void main(void)\n"
3507 << "{\n"
3508 << "}\n";
3509 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
3510 }
3511
3512 // Tesselation control shader
3513 {
3514 std::ostringstream src;
3515 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
3516 << "layout(vertices = 3) out;\n"
3517 << "void main (void)\n"
3518 << "{\n"
3519 << " gl_TessLevelInner[0] = 2.0;\n" // generate three triangles out of each patch
3520 << " gl_TessLevelOuter[0] = 1.0;\n"
3521 << " gl_TessLevelOuter[1] = 1.0;\n"
3522 << " gl_TessLevelOuter[2] = 1.0;\n"
3523 << "}\n";
3524 programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str());
3525 }
3526
3527 // Tessellation evaluation shader
3528 {
3529 std::ostringstream src;
3530 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
3531 << "layout(triangles, ccw) in;\n"
3532 << "layout(xfb_buffer = 0, xfb_offset = 0, xfb_stride = 4, location = 0) out uint idx_out;\n"
3533 << "\n"
3534 << "void main (void)\n"
3535 << "{\n"
3536 << " idx_out = gl_PrimitiveID;\n" // all vertex generated from patch will have its id
3537 << "}\n";
3538 programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
3539 }
3540
3541 return;
3542 }
3543
3544 if (xfbBuiltinPipeline)
3545 {
3546 const std::string outputBuiltIn = (m_parameters.testType == TEST_TYPE_XFB_POINTSIZE) ? "float gl_PointSize;\n"
3547 : (m_parameters.testType == TEST_TYPE_XFB_CLIPDISTANCE) ? "float gl_ClipDistance[8];\n"
3548 : (m_parameters.testType == TEST_TYPE_XFB_CULLDISTANCE) ? "float gl_CullDistance[8];\n"
3549 : (m_parameters.testType == TEST_TYPE_XFB_CLIP_AND_CULL) ? "float gl_CullDistance[5];\nfloat gl_ClipDistance[1];\n"
3550 : "";
3551 const std::string operationBuiltIn = (m_parameters.testType == TEST_TYPE_XFB_POINTSIZE) ? "gl_PointSize = float(gl_VertexIndex) / 32768.0f;"
3552 : (m_parameters.testType == TEST_TYPE_XFB_CLIPDISTANCE) ? "for (int i=0; i<8; i++) gl_ClipDistance[i] = float(8 * gl_VertexIndex + i) / 32768.0f;"
3553 : (m_parameters.testType == TEST_TYPE_XFB_CULLDISTANCE) ? "for (int i=0; i<8; i++) gl_CullDistance[i] = float(8 * gl_VertexIndex + i) / 32768.0f;"
3554 : (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"
3555 "gl_ClipDistance[0] = float(6 * gl_VertexIndex + 5) / 32768.0f;\n"
3556 : "";
3557
3558 // Vertex shader
3559 {
3560 std::ostringstream src;
3561 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
3562 << "\n"
3563 << "layout(xfb_buffer = " << m_parameters.partCount - 1 << ", xfb_offset = 0) out gl_PerVertex\n"
3564 << "{\n"
3565 << outputBuiltIn
3566 << "};\n"
3567 << "\n"
3568 << "void main(void)\n"
3569 << "{\n"
3570 << operationBuiltIn
3571 << "}\n";
3572
3573 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
3574 }
3575
3576 return;
3577 }
3578
3579 if (m_parameters.testType == TEST_TYPE_MULTISTREAMS)
3580 {
3581 // vertex shader
3582 {
3583 std::ostringstream src;
3584 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
3585 << "\n"
3586 << "void main(void)\n"
3587 << "{\n"
3588 << "}\n";
3589
3590 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
3591 }
3592
3593 // geometry shader
3594 {
3595 const deUint32 s = m_parameters.streamId;
3596 std::ostringstream src;
3597
3598 DE_ASSERT(s != 0);
3599
3600 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
3601 << "\n"
3602 << "layout(points) in;\n"
3603 << "\n"
3604 << "layout(points, max_vertices = 32) out;\n"
3605 << "layout(stream = " << 0 << ", xfb_buffer = 0, xfb_offset = 0, xfb_stride = 16, location = 0) out vec4 out0;\n"
3606 << "layout(stream = " << s << ", xfb_buffer = 1, xfb_offset = 0, xfb_stride = 16, location = 1) out vec4 out1;\n"
3607 << "\n"
3608 << "const int counts[] = int[](1, 1, 2, 4, 8);\n"
3609 << "\n"
3610 << "void main(void)\n"
3611 << "{\n"
3612 << " int c0 = 0;\n"
3613 << " int c1 = 0;\n"
3614 << "\n"
3615 << " // Start 1st buffer from point where 0th buffer ended\n"
3616 << " for (int i = 0; i < counts.length(); i++)\n"
3617 << " c1 = c1 + 4 * counts[i];\n"
3618 << "\n"
3619 << " for (int i = 0; i < counts.length(); i++)\n"
3620 << " {\n"
3621 << " const int n0 = counts[i];\n"
3622 << " const int n1 = counts[counts.length() - 1 - i];\n"
3623 << "\n"
3624 << " for (int j = 0; j < n0; j++)\n"
3625 << " {\n"
3626 << " out0 = vec4(ivec4(c0, c0 + 1, c0 + 2, c0 + 3));\n"
3627 << " c0 = c0 + 4;\n"
3628 << " EmitStreamVertex(0);\n"
3629 << " EndStreamPrimitive(0);\n"
3630 << " }\n"
3631 << "\n"
3632 << " for (int j = 0; j < n1; j++)\n"
3633 << " {\n"
3634 << " out1 = vec4(ivec4(c1, c1 + 1, c1 + 2, c1 + 3));\n"
3635 << " c1 = c1 + 4;\n"
3636 << " EmitStreamVertex(" << s << ");\n"
3637 << " EndStreamPrimitive(" << s << ");\n"
3638 << " }\n"
3639 << " }\n"
3640 << "}\n";
3641
3642 programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
3643 }
3644
3645 return;
3646 }
3647
3648 if (m_parameters.testType == TEST_TYPE_MULTISTREAMS_SAME_LOCATION)
3649 {
3650 // vertex shader
3651 {
3652 std::ostringstream src;
3653 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
3654 << "\n"
3655 << "layout(location=0) out uint id;"
3656 << "void main(void)\n"
3657 << "{\n"
3658 << " id = gl_VertexIndex;"
3659 << "}\n";
3660
3661 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
3662 }
3663
3664 // geometry shader
3665 {
3666 const deUint32 s = m_parameters.streamId;
3667 std::ostringstream src;
3668
3669 DE_ASSERT(s != 0);
3670
3671 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
3672 << "\n"
3673 << "layout(points) in;\n"
3674 << "\n"
3675 << "layout(points, max_vertices = 2) out;\n"
3676 << "\n"
3677 << "layout(location=0) in uint id[1];"
3678 << "layout(stream = " << 0 << ", xfb_buffer = 0, xfb_offset = 0, xfb_stride = 4, location = 0, component = 0) out uint out0;\n"
3679 << "layout(stream = " << s << ", xfb_buffer = 1, xfb_offset = 0, xfb_stride = 4, location = 0, component = 1) out uint out1;\n"
3680 << "\n"
3681 << "void main(void)\n"
3682 << "{\n"
3683 << " out0 = id[0] * 2 + 0;\n"
3684 << " EmitStreamVertex(0);\n"
3685 << " EndStreamPrimitive(0);\n"
3686 << "\n"
3687 << " out1 = id[0] * 2 + 1;\n"
3688 << " EmitStreamVertex(" << s << ");\n"
3689 << " EndStreamPrimitive(" << s << ");\n"
3690 << "}\n";
3691
3692 programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
3693 }
3694
3695 return;
3696 }
3697
3698 if (requiresFullPipeline)
3699 {
3700 // vertex shader
3701 {
3702 std::ostringstream src;
3703 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
3704 << "\n"
3705 << "void main(void)\n"
3706 << "{\n"
3707 << "}\n";
3708
3709 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
3710 }
3711
3712 // geometry shader
3713 {
3714 const deUint32 s = m_parameters.streamId;
3715 const bool requirePoints = m_parameters.testType == TEST_TYPE_STREAMS_POINTSIZE;
3716 const std::string outputPrimitiveType = requirePoints ? "points" : "triangle_strip";
3717 const std::string outputBuiltIn = (m_parameters.testType == TEST_TYPE_STREAMS_POINTSIZE) ? " float gl_PointSize;\n"
3718 : (m_parameters.testType == TEST_TYPE_STREAMS_CLIPDISTANCE) ? " float gl_ClipDistance[];\n"
3719 : (m_parameters.testType == TEST_TYPE_STREAMS_CULLDISTANCE) ? " float gl_CullDistance[];\n"
3720 : "";
3721 std::ostringstream src;
3722
3723 DE_ASSERT(s != 0);
3724
3725 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
3726 << "\n"
3727 << "layout(points) in;\n"
3728 << "layout(" << outputPrimitiveType << ", max_vertices = 16) out;\n"
3729 << "layout(stream = " << s << ") out;\n"
3730 << "layout(location = 0) out vec4 color;\n"
3731 << "\n"
3732 << "layout(stream = " << s << ") out gl_PerVertex\n"
3733 << "{\n"
3734 << " vec4 gl_Position;\n"
3735 << outputBuiltIn
3736 << "};\n"
3737 << "\n"
3738 << "void main(void)\n"
3739 << "{\n"
3740 << " // Color constants\n"
3741 << " vec4 g = vec4(0.0, 1.0, 0.0, 1.0);\n"
3742 << " vec4 m = vec4(1.0, 0.0, 1.0, 1.0);\n"
3743 << " // Coordinate constants: leftmost column\n"
3744 << " vec4 a = vec4(-1.0,-1.0, 0.0, 1.0);\n"
3745 << " vec4 b = vec4(-1.0, 0.0, 0.0, 1.0);\n"
3746 << " vec4 c = vec4(-1.0, 1.0, 0.0, 1.0);\n"
3747 << " // Coordinate constants: middle column\n"
3748 << " vec4 i = vec4( 0.0,-1.0, 0.0, 1.0);\n"
3749 << " vec4 j = vec4( 0.0, 0.0, 0.0, 1.0);\n"
3750 << " vec4 k = vec4( 0.0, 1.0, 0.0, 1.0);\n"
3751 << " // Coordinate constants: rightmost column\n"
3752 << " vec4 x = vec4( 1.0,-1.0, 0.0, 1.0);\n"
3753 << " vec4 y = vec4( 1.0, 0.0, 0.0, 1.0);\n"
3754 << " vec4 z = vec4( 1.0, 1.0, 0.0, 1.0);\n"
3755 << "\n";
3756
3757 if (m_parameters.testType == TEST_TYPE_STREAMS)
3758 {
3759 src << " if (gl_PrimitiveIDIn == 0)\n"
3760 << " {\n"
3761 << " color = m; gl_Position = b; EmitStreamVertex(" << s << ");\n"
3762 << " color = m; gl_Position = y; EmitStreamVertex(" << s << ");\n"
3763 << " color = m; gl_Position = c; EmitStreamVertex(" << s << ");\n"
3764 << " EndStreamPrimitive(" << s << ");\n"
3765 << " }\n"
3766 << " else\n"
3767 << " {\n"
3768 << " color = m; gl_Position = y; EmitStreamVertex(" << s << ");\n"
3769 << " color = m; gl_Position = c; EmitStreamVertex(" << s << ");\n"
3770 << " color = m; gl_Position = z; EmitStreamVertex(" << s << ");\n"
3771 << " EndStreamPrimitive(" << s << ");\n"
3772 << " }\n";
3773 }
3774
3775 if (m_parameters.testType == TEST_TYPE_STREAMS_POINTSIZE)
3776 {
3777 const std::string pointSize = "gl_PointSize = " + de::toString(m_parameters.pointSize) + ".0f";
3778
3779 src << " if (gl_PrimitiveIDIn == 0)\n"
3780 << " {\n"
3781 << " color = g; gl_Position = (a + j) / 2.0f; gl_PointSize = 1.0f; EmitStreamVertex(0);\n"
3782 << " EndStreamPrimitive(0);\n"
3783 << " color = m; gl_Position = (b + k) / 2.0f; gl_PointSize = 1.0f; EmitStreamVertex(" << s << ");\n"
3784 << " EndStreamPrimitive(" << s << ");\n"
3785 << " }\n"
3786 << " else\n"
3787 << " {\n"
3788 << " color = g; gl_Position = (j + x) / 2.0f; " << pointSize << "; EmitStreamVertex(0);\n"
3789 << " EndStreamPrimitive(0);\n"
3790 << " color = m; gl_Position = (k + y) / 2.0f; " << pointSize << "; EmitStreamVertex(" << s << ");\n"
3791 << " EndStreamPrimitive(" << s << ");\n"
3792 << " }\n";
3793 }
3794
3795 if (m_parameters.testType == TEST_TYPE_STREAMS_CLIPDISTANCE)
3796 {
3797 src << " if (gl_PrimitiveIDIn == 0)\n"
3798 << " {\n"
3799 << " color = m; gl_Position = b; gl_ClipDistance[0] = -1.0; EmitStreamVertex(" << s << ");\n"
3800 << " color = m; gl_Position = c; gl_ClipDistance[0] = -1.0; EmitStreamVertex(" << s << ");\n"
3801 << " color = m; gl_Position = y; gl_ClipDistance[0] = 1.0; EmitStreamVertex(" << s << ");\n"
3802 << " EndStreamPrimitive(" << s << ");\n"
3803 << " }\n"
3804 << " else\n"
3805 << " {\n"
3806 << " color = m; gl_Position = y; gl_ClipDistance[0] = 1.0; EmitStreamVertex(" << s << ");\n"
3807 << " color = m; gl_Position = c; gl_ClipDistance[0] = -1.0; EmitStreamVertex(" << s << ");\n"
3808 << " color = m; gl_Position = z; gl_ClipDistance[0] = 1.0; EmitStreamVertex(" << s << ");\n"
3809 << " EndStreamPrimitive(" << s << ");\n"
3810 << " }\n";
3811 }
3812
3813 if (m_parameters.testType == TEST_TYPE_STREAMS_CULLDISTANCE)
3814 {
3815 src << " if (gl_PrimitiveIDIn == 0)\n"
3816 << " {\n"
3817 << " color = m; gl_Position = b; gl_CullDistance[0] = -1.0; EmitStreamVertex(" << s << ");\n"
3818 << " color = m; gl_Position = c; gl_CullDistance[0] = -1.0; EmitStreamVertex(" << s << ");\n"
3819 << " color = m; gl_Position = j; gl_CullDistance[0] = -1.0; EmitStreamVertex(" << s << ");\n"
3820 << " EndStreamPrimitive(" << s << ");\n"
3821 << " color = m; gl_Position = j; gl_CullDistance[0] = -1.0; EmitStreamVertex(" << s << ");\n"
3822 << " color = m; gl_Position = c; gl_CullDistance[0] = -1.0; EmitStreamVertex(" << s << ");\n"
3823 << " color = m; gl_Position = k; gl_CullDistance[0] = -1.0; EmitStreamVertex(" << s << ");\n"
3824 << " EndStreamPrimitive(" << s << ");\n"
3825 << " }\n"
3826 << " else\n"
3827 << " {\n"
3828 << " color = m; gl_Position = j; gl_CullDistance[0] = 1.0; EmitStreamVertex(" << s << ");\n"
3829 << " color = m; gl_Position = k; gl_CullDistance[0] = 1.0; EmitStreamVertex(" << s << ");\n"
3830 << " color = m; gl_Position = y; gl_CullDistance[0] = 1.0; EmitStreamVertex(" << s << ");\n"
3831 << " EndStreamPrimitive(" << s << ");\n"
3832 << " color = m; gl_Position = y; gl_CullDistance[0] = 1.0; EmitStreamVertex(" << s << ");\n"
3833 << " color = m; gl_Position = k; gl_CullDistance[0] = 1.0; EmitStreamVertex(" << s << ");\n"
3834 << " color = m; gl_Position = z; gl_CullDistance[0] = 1.0; EmitStreamVertex(" << s << ");\n"
3835 << " EndStreamPrimitive(" << s << ");\n"
3836 << " }\n";
3837 }
3838
3839 src << "}\n";
3840
3841 programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
3842 }
3843
3844 // Fragment shader
3845 {
3846 std::ostringstream src;
3847 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
3848 << "\n"
3849 << "layout(location = 0) in vec4 i_color;\n"
3850 << "layout(location = 0) out vec4 o_color;\n"
3851 << "\n"
3852 << "void main(void)\n"
3853 << "{\n"
3854 << " o_color = i_color;\n"
3855 << "}\n";
3856
3857 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
3858 }
3859
3860 return;
3861 }
3862
3863 if (m_parameters.testType == TEST_TYPE_DRAW_INDIRECT || m_parameters.testType == TEST_TYPE_DRAW_INDIRECT_MULTIVIEW)
3864 {
3865 // vertex shader
3866 {
3867 std::ostringstream src;
3868 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
3869 << "\n"
3870 << "layout(location = 0) in vec4 in_position;\n"
3871 << "\n"
3872 << "void main(void)\n"
3873 << "{\n"
3874 << " gl_Position = in_position;\n"
3875 << "}\n";
3876
3877 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
3878 }
3879
3880 // Fragment shader
3881 {
3882 std::ostringstream src;
3883 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
3884 << "\n"
3885 << "layout(location = 0) out vec4 o_color;\n"
3886 << "\n"
3887 << "void main(void)\n"
3888 << "{\n"
3889 << " o_color = vec4(1.0, 1.0, 1.0, 1.0);\n"
3890 << "}\n";
3891
3892 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
3893 }
3894
3895 return;
3896 }
3897
3898 if (m_parameters.testType == TEST_TYPE_QUERY_GET ||
3899 m_parameters.testType == TEST_TYPE_QUERY_COPY ||
3900 m_parameters.testType == TEST_TYPE_QUERY_COPY_STRIDE_ZERO ||
3901 m_parameters.testType == TEST_TYPE_QUERY_RESET)
3902 {
3903 struct TopologyShaderInfo
3904 {
3905 std::string glslIn;
3906 std::string glslOut;
3907 std::string spirvIn;
3908 std::string spirvOut;
3909 };
3910
3911 const std::map<VkPrimitiveTopology, TopologyShaderInfo> primitiveNames =
3912 {
3913 { VK_PRIMITIVE_TOPOLOGY_POINT_LIST , { "points" , "points" , "InputPoints" , "OutputPoints" } },
3914 { VK_PRIMITIVE_TOPOLOGY_LINE_LIST , { "lines" , "line_strip" , "InputLines" , "OutputLineStrip" } },
3915 { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP , { "lines" , "line_strip" , "InputLines" , "OutputLineStrip" } },
3916 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST , { "triangles" , "triangle_strip" , "Triangles" , "OutputTriangleStrip" } },
3917 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP , { "triangles" , "triangle_strip" , "Triangles" , "OutputTriangleStrip" } },
3918 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN , { "triangles" , "triangle_strip" , "Triangles" , "OutputTriangleStrip" } },
3919 { VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY , { "lines_adjacency" , "line_strip" , "InputLinesAdjacency" , "OutputLineStrip" } },
3920 { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY , { "lines_adjacency" , "line_strip" , "InputLinesAdjacency" , "OutputLineStrip" } },
3921 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY , { "triangles_adjacency" , "triangle_strip" , "InputTrianglesAdjacency" , "OutputTriangleStrip" } },
3922 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY , { "triangles_adjacency" , "triangle_strip" , "InputTrianglesAdjacency" , "OutputTriangleStrip" } }
3923 };
3924
3925 // Vertex shader
3926 {
3927 std::ostringstream src;
3928 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
3929 << "\n"
3930 << "layout(location = 0) out vec4 out0;\n"
3931 << "\n"
3932 << "void main(void)\n"
3933 << "{\n"
3934 << " float n = 4.0 * float(gl_VertexIndex);\n"
3935 << " out0 = vec4(n + 0.0, n + 1.0, n + 2.0, n + 3.0);\n"
3936 << "}\n";
3937
3938 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
3939 }
3940
3941 // geometry shader
3942 if (m_parameters.streamId == 0)
3943 {
3944 std::ostringstream src;
3945
3946 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
3947 << "\n"
3948 << "layout(" << primitiveNames.at(m_parameters.primTopology).glslIn << ") in;\n"
3949 << "layout(location = 0) in vec4 in0[];\n"
3950 << "\n"
3951 << "layout(" << primitiveNames.at(m_parameters.primTopology).glslOut << ", max_vertices = " << topologyData.at(m_parameters.primTopology).primSize<< ") out;\n"
3952 << "layout(xfb_buffer = 0, xfb_offset = 0, xfb_stride = 16, location = 0) out vec4 out0;\n"
3953 << "\n"
3954 << "void main(void)\n"
3955 << "{\n";
3956
3957 for (deUint32 i = 0; i < topologyData.at(m_parameters.primTopology).primSize; i++)
3958 {
3959 if (!m_parameters.omitShaderWrite)
3960 src << " out0 = in0[" << i << "];\n";
3961 src << " EmitVertex();\n";
3962 }
3963
3964 src << " EndPrimitive();\n"
3965 << "}\n";
3966
3967 programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
3968 }
3969 else
3970 {
3971 const deUint32 s = m_parameters.streamId;
3972 std::ostringstream src;
3973
3974 if (m_parameters.testType == TEST_TYPE_QUERY_GET)
3975 {
3976 // The SPIR-V program below is roughly equivalent to the following GLSL code:
3977 //
3978 // #version 450
3979 // #extension GL_ARB_enhanced_layouts : require
3980 //
3981 // layout(points) in;
3982 // layout(location = 0) in vec4 in0[];
3983 //
3984 // layout(points, max_vertices = 1) out;
3985 // layout(location=0, stream=1, xfb_buffer=0, xfb_stride=16) out OutBlock {
3986 // layout(xfb_offset=0, location=0) vec4 out0;
3987 // } outBlock;
3988 //
3989 // void main(void)
3990 // {
3991 // outBlock.out0 = in0[0];
3992 // EmitStreamVertex(1);
3993 // EndStreamPrimitive(1);
3994 // }
3995 //
3996 // However, the stream number has been parametrized and the code generated by glslang has been tuned to move the
3997 // Stream, XfbBuffer and XfbStride decorations to the structure member instead of the block. This allows us to test
3998 // transform feedback decorations on structure members as part of these basic tests.
3999 src << "; SPIR-V\n"
4000 << "; Version: 1.0\n"
4001 << "; Generator: Khronos Glslang Reference Front End; 10\n"
4002 << "; Bound: 64\n"
4003 << "; Schema: 0\n"
4004 << " OpCapability Geometry\n"
4005 << " OpCapability TransformFeedback\n"
4006 << " OpCapability GeometryStreams\n"
4007 << " %1 = OpExtInstImport \"GLSL.std.450\"\n"
4008 << " OpMemoryModel Logical GLSL450\n"
4009 << " OpEntryPoint Geometry %main \"main\" %outBlock %in0\n"
4010 << " OpExecutionMode %main Xfb\n"
4011 << " OpExecutionMode %main " << primitiveNames.at(m_parameters.primTopology).spirvIn << "\n"
4012 << " OpExecutionMode %main Invocations 1\n"
4013 << " OpExecutionMode %main " << primitiveNames.at(m_parameters.primTopology).spirvOut << "\n"
4014 << " OpExecutionMode %main OutputVertices " << topologyData.at(m_parameters.primTopology).primSize << "\n"
4015 << " OpSource GLSL 450\n"
4016 << " OpSourceExtension \"GL_ARB_enhanced_layouts\"\n"
4017 << " OpName %main \"main\"\n"
4018 << " OpName %OutBlock \"OutBlock\"\n"
4019 << " OpMemberName %OutBlock 0 \"out0\"\n"
4020 << " OpName %outBlock \"outBlock\"\n"
4021 << " OpName %in0 \"in0\"\n"
4022 << " OpMemberDecorate %OutBlock 0 Location 0\n"
4023 << " OpMemberDecorate %OutBlock 0 Offset 0\n"
4024 // These Stream, XfbBuffer and XfbStride decorations have been moved to the struct member.
4025 << " OpMemberDecorate %OutBlock 0 Stream " << s << "\n"
4026 << " OpMemberDecorate %OutBlock 0 XfbBuffer 0\n"
4027 << " OpMemberDecorate %OutBlock 0 XfbStride 16\n"
4028 << " OpDecorate %OutBlock Block\n"
4029 // The decorations mentioned above were using OpDecorate and assigned to %outBlock itself here.
4030 << " OpDecorate %in0 Location 0\n"
4031 << " %void = OpTypeVoid\n"
4032 << " %3 = OpTypeFunction %void\n"
4033 << " %float = OpTypeFloat 32\n"
4034 << " %v4float = OpTypeVector %float 4\n"
4035 << " %OutBlock = OpTypeStruct %v4float\n"
4036 << "%_ptr_Output_OutBlock = OpTypePointer Output %OutBlock\n"
4037 << " %outBlock = OpVariable %_ptr_Output_OutBlock Output\n"
4038 << " %int = OpTypeInt 32 1\n"
4039 << " %int_0 = OpConstant %int 0\n";
4040
4041 for (deUint32 i = 1; i < topologyData.at(m_parameters.primTopology).primSize + 1; i++)
4042 {
4043 src << "%int_" << i << " = OpConstant %int " << i << "\n";
4044 }
4045
4046 src << " %uint = OpTypeInt 32 0\n"
4047 << " %uint_0 = OpConstant %uint " << topologyData.at(m_parameters.primTopology).primSize << "\n"
4048 << "%_arr_v4float_uint_0 = OpTypeArray %v4float %uint_0\n"
4049 << "%_ptr_Input__arr_v4float_uint_0 = OpTypePointer Input %_arr_v4float_uint_0\n"
4050 << " %in0 = OpVariable %_ptr_Input__arr_v4float_uint_0 Input\n"
4051 << "%_ptr_Input_v4float = OpTypePointer Input %v4float\n"
4052 << "%_ptr_Output_v4float = OpTypePointer Output %v4float\n"
4053 << " %streamNum = OpConstant %int " << s << "\n"
4054 << " %main = OpFunction %void None %3\n"
4055 << " %5 = OpLabel\n";
4056
4057 for (deUint32 i = 1; i < topologyData.at(m_parameters.primTopology).primSize + 1; i++)
4058 {
4059 src << "%" << i << "1 = OpAccessChain %_ptr_Input_v4float %in0 %int_" << i << "\n"
4060 << " %" << i << "2 = OpLoad %v4float %" << i << "1\n"
4061 << " %" << i << "3 = OpAccessChain %_ptr_Output_v4float %outBlock %int_0\n"
4062 << " OpStore %" << i << "3 %" << i << "2\n"
4063 << " OpEmitStreamVertex %streamNum\n";
4064 }
4065
4066 src << " OpEndStreamPrimitive %streamNum\n"
4067 << " OpReturn\n"
4068 << " OpFunctionEnd\n"
4069 ;
4070
4071 programCollection.spirvAsmSources.add("geom") << src.str();
4072 }
4073 else
4074 {
4075 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
4076 << "\n"
4077 << "layout(" << primitiveNames.at(m_parameters.primTopology).glslIn << ") in;\n"
4078 << "layout(location = 0) in vec4 in0[];\n"
4079 << "\n"
4080 << "layout(" << primitiveNames.at(m_parameters.primTopology).glslOut << ", max_vertices = " << topologyData.at(m_parameters.primTopology).primSize << ") out;\n"
4081 << "layout(stream = " << s << ", xfb_buffer = 0, xfb_offset = 0, xfb_stride = 16, location = 0) out vec4 out0;\n"
4082 << "\n"
4083 << "void main(void)\n"
4084 << "{\n";
4085
4086 for (deUint32 i = 0; i < topologyData.at(m_parameters.primTopology).primSize; i++)
4087 {
4088 src << " out0 = in0[" << i << "];\n"
4089 << " EmitStreamVertex(" << s << ");\n";
4090 }
4091
4092 src << " EndStreamPrimitive(" << s << ");\n"
4093 << "}\n";
4094
4095 programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
4096 }
4097 }
4098
4099 return;
4100 }
4101
4102 if (m_parameters.testType == TEST_TYPE_MULTIQUERY)
4103 {
4104 // vertex shader
4105 {
4106 std::ostringstream src;
4107 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
4108 << "\n"
4109 << "layout(location = 0) out ivec4 out0;\n"
4110 << "\n"
4111 << "void main(void)\n"
4112 << "{\n"
4113 << " out0 = ivec4(gl_VertexIndex);\n"
4114 << "}\n";
4115
4116 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
4117 }
4118
4119 // geometry shader
4120 {
4121 const deUint32 s = m_parameters.streamId;
4122 std::ostringstream src;
4123
4124 DE_ASSERT(s != 0);
4125
4126 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
4127 << "\n"
4128 << "layout(points) in;\n"
4129 << "\n"
4130 << "layout(points, max_vertices = 4) out;\n"
4131 << "\n"
4132 << "layout(stream = " << 0 << ", xfb_buffer = 0, xfb_offset = 0, xfb_stride = 16, location = 0) out vec4 out0;\n"
4133 << "layout(stream = " << s << ", xfb_buffer = 1, xfb_offset = 0, xfb_stride = 16, location = 1) out vec4 out1;\n"
4134 << "\n"
4135 << "void main(void)\n"
4136 << "{\n"
4137 << " const int n0 = 3;\n"
4138 << " const int n1 = 1;\n"
4139 << " const float c0 = 0.5f;\n"
4140 << " const float c1 = 0.5f + float(" << s << ");\n"
4141 << "\n"
4142 << " for (int j = 0; j < n0; j++)\n"
4143 << " {\n";
4144
4145 if (!m_parameters.omitShaderWrite)
4146 src << " out0 = vec4(c0);\n";
4147
4148 src << " EmitStreamVertex(0);\n"
4149 << " EndStreamPrimitive(0);\n"
4150 << " }\n"
4151 << "\n"
4152 << " for (int j = 0; j < n1; j++)\n"
4153 << " {\n"
4154 << " out1 = vec4(c1);\n"
4155 << " EmitStreamVertex(" << s << ");\n"
4156 << " EndStreamPrimitive(" << s << ");\n"
4157 << " }\n"
4158 << "}\n";
4159
4160 programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
4161 }
4162
4163 return;
4164 }
4165
4166 if (m_parameters.testType == TEST_TYPE_LINES_TRIANGLES)
4167 {
4168 // vertex shader
4169 {
4170 std::ostringstream src;
4171 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
4172 << "\n"
4173 << "void main(void)\n"
4174 << "{\n"
4175 << "}\n";
4176
4177 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
4178 }
4179
4180 // geometry shader
4181 {
4182 const deUint32 s = m_parameters.streamId;
4183 const bool line = isPrimitiveTopologyLine(m_parameters.primTopology);
4184 const bool tri = isPrimitiveTopologyTriangle(m_parameters.primTopology);
4185 const std::string p = line ? std::string("line_strip")
4186 : tri ? std::string("triangle_strip")
4187 : std::string("");
4188 const std::string vertexCount = line ? vectorToString(LINES_LIST)
4189 : tri ? vectorToString(TRIANGLES_LIST)
4190 : std::string("");
4191 std::ostringstream src;
4192
4193 DE_ASSERT(s != 0);
4194
4195 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
4196 << "\n"
4197 << "layout(points) in;\n"
4198 << "\n"
4199 << "layout(" << p << ", max_vertices = 256) out;\n"
4200 << "layout(stream = " << 0 << ", xfb_buffer = 0, xfb_offset = 0, xfb_stride = 16, location = 0) out vec4 out0;\n"
4201 << "layout(stream = " << s << ", xfb_buffer = 1, xfb_offset = 0, xfb_stride = 16, location = 1) out vec4 out1;\n"
4202 << "\n"
4203 << "const int vertices_in_primitive[] = int[](" << vertexCount << ");\n"
4204 << "\n"
4205 << "int num_vertices_in_primitives()\n"
4206 << "{\n"
4207 << " int c = 0;\n"
4208 << "\n"
4209 << " for (int i = 0; i < vertices_in_primitive.length(); i++)\n"
4210 << " c = c + vertices_in_primitive[i];\n"
4211 << "\n"
4212 << " return c;\n"
4213 << "}\n"
4214 << "\n"
4215 << "void main(void)\n"
4216 << "{\n"
4217 << " int vc = num_vertices_in_primitives();\n"
4218 << " int c0 = vc * gl_PrimitiveIDIn;\n"
4219 << " int c1 = vc * (" << INVOCATION_COUNT << " + gl_PrimitiveIDIn);\n"
4220 << "\n"
4221 << " for (int i = 0; i < vertices_in_primitive.length(); i++)\n"
4222 << " {\n"
4223 << " const int n = vertices_in_primitive[i];\n"
4224 << "\n"
4225 << " for (int j = 0; j < n; j++)\n"
4226 << " {\n"
4227 << " out0 = vec4(ivec4(c0, gl_PrimitiveIDIn, i, j));\n"
4228 << " c0 = c0 + 1;\n"
4229 << " EmitStreamVertex(0);\n"
4230 << "\n"
4231 << " out1 = vec4(ivec4(c1, gl_PrimitiveIDIn, i, j));\n"
4232 << " c1 = c1 + 1;\n"
4233 << " EmitStreamVertex(" << s << ");\n"
4234 << " }\n"
4235 << "\n"
4236 << " EndStreamPrimitive(0);\n"
4237 << " EndStreamPrimitive(" << s << ");\n"
4238 << " }\n"
4239 << "}\n";
4240
4241 programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
4242 }
4243
4244 return;
4245 }
4246
4247 if (m_parameters.testType == TEST_TYPE_DRAW_OUTSIDE)
4248 {
4249 // Vertex shader
4250 {
4251 std::ostringstream src;
4252 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
4253 << "\n"
4254 << "layout(push_constant) uniform pushConstants\n"
4255 << "{\n"
4256 << " uint start;\n"
4257 << "} uInput;\n"
4258 << "\n"
4259 << "layout(xfb_buffer = 0, xfb_offset = 0, xfb_stride = 4, location = 0) out uint idx_out;\n"
4260 << "\n"
4261 << "void main(void)\n"
4262 << "{\n"
4263 << " idx_out = uInput.start + gl_VertexIndex;\n"
4264 << " gl_PointSize = 1.0f;\n"
4265 << "}\n";
4266
4267 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
4268 }
4269
4270 {
4271 std::ostringstream src;
4272 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
4273 << "\n"
4274 << "layout(push_constant) uniform pushConstants\n"
4275 << "{\n"
4276 << " uint start;\n"
4277 << "} uInput;\n"
4278 << "\n"
4279 << "layout(xfb_buffer = 0, xfb_offset = 0, xfb_stride = 4, location = 0) out uint idx_out;\n"
4280 << "\n"
4281 << "void main(void)\n"
4282 << "{\n"
4283 << " idx_out = uInput.start + gl_VertexIndex * 2u;\n"
4284 << " gl_PointSize = 1.0f;\n"
4285 << "}\n";
4286
4287 programCollection.glslSources.add("vert2") << glu::VertexSource(src.str());
4288 }
4289
4290 return;
4291 }
4292
4293 if (m_parameters.testType == TEST_TYPE_HOLES_VERTEX || m_parameters.testType == TEST_TYPE_HOLES_GEOMETRY)
4294 {
4295 // The fragment shader is the same in both variants.
4296 {
4297 std::ostringstream frag;
4298 frag
4299 << "#version 460\n"
4300 << "layout (location=0) out vec4 outColor;\n"
4301 << "\n"
4302 << "layout (location = 0) in float goku;\n"
4303 << "layout (location = 0, component = 1) in float trunks;\n"
4304 << "layout (location = 0, component = 2) in float vegeta;\n"
4305 << "\n"
4306 << "void main ()\n"
4307 << "{\n"
4308 << " outColor = ((goku == 10.0 && trunks == 20.0 && vegeta == 30.0)\n"
4309 << " ? vec4(0.0, 0.0, 1.0, 1.0)\n"
4310 << " : vec4(0.0, 0.0, 0.0, 1.0));\n"
4311 << "}\n"
4312 ;
4313 programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
4314 }
4315
4316 const std::string pcDecl =
4317 "layout (push_constant, std430) uniform PushConstantBlock {\n"
4318 " vec3 values;\n"
4319 "} pc;\n"
4320 ;
4321
4322 const std::string dbChars =
4323 "layout (location = 0, xfb_buffer = 0, xfb_stride = 12, xfb_offset = 0) flat out float goku;\n"
4324 "layout (location = 0, component = 1) flat out float trunks;\n"
4325 "layout (location = 0, xfb_buffer = 0, xfb_stride = 12, xfb_offset = 8, component = 2) flat out float vegeta;\n"
4326 ;
4327
4328 const std::string assignments =
4329 " goku = pc.values.x;\n"
4330 " trunks = pc.values.y;\n"
4331 " vegeta = pc.values.z;\n"
4332 ;
4333
4334 if (m_parameters.testType == TEST_TYPE_HOLES_GEOMETRY)
4335 {
4336 std::ostringstream geom;
4337 geom
4338 << "#version 460\n"
4339 << "layout (points) in;\n"
4340 << "layout (max_vertices=1, points) out;\n"
4341 << "\n"
4342 << dbChars
4343 << "\n"
4344 << pcDecl
4345 << "\n"
4346 << "void main ()\n"
4347 << "{\n"
4348 << " gl_Position = gl_in[0].gl_Position;\n"
4349 << " gl_PointSize = gl_in[0].gl_PointSize;\n"
4350 << "\n"
4351 << assignments
4352 << "\n"
4353 << " EmitVertex();\n"
4354 << "}\n"
4355 ;
4356 programCollection.glslSources.add("geom") << glu::GeometrySource(geom.str());
4357 }
4358
4359 const bool vertOnly = (m_parameters.testType == TEST_TYPE_HOLES_VERTEX);
4360 std::ostringstream vert;
4361 vert
4362 << "#version 460\n"
4363 << "layout (location = 0) in vec4 inPos;\n"
4364 << "\n"
4365 << (vertOnly ? dbChars : "")
4366 << "\n"
4367 << (vertOnly ? pcDecl : "")
4368 << "\n"
4369 << "void main ()\n"
4370 << "{\n"
4371 << " gl_Position = inPos;\n"
4372 << " gl_PointSize = 1.0;\n"
4373 << "\n"
4374 << (vertOnly ? assignments : "")
4375 << "}\n"
4376 ;
4377 programCollection.glslSources.add("vert") << glu::VertexSource(vert.str());
4378
4379 return;
4380 }
4381
4382 DE_ASSERT(0 && "Unknown test");
4383 }
4384
createTransformFeedbackSimpleTests(tcu::TestCaseGroup* group)4385 void createTransformFeedbackSimpleTests(tcu::TestCaseGroup* group)
4386 {
4387 {
4388 const deUint32 bufferCounts[] = { 1u, 2u, 4u, 8u };
4389 const deUint32 bufferSizes[] = { 256u, 512u, 128u * 1024u };
4390 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, TEST_TYPE_DRAW_OUTSIDE };
4391 const std::string testTypeNames[] = { "basic", "resume", "xfb_pointsize", "xfb_clipdistance", "xfb_culldistance", "xfb_clip_and_cull", "draw_outside" };
4392
4393 for (deUint32 testTypesNdx = 0; testTypesNdx < DE_LENGTH_OF_ARRAY(testTypes); ++testTypesNdx)
4394 {
4395 const TestType testType = testTypes[testTypesNdx];
4396 const std::string testName = testTypeNames[testTypesNdx];
4397
4398 for (deUint32 bufferCountsNdx = 0; bufferCountsNdx < DE_LENGTH_OF_ARRAY(bufferCounts); ++bufferCountsNdx)
4399 {
4400 const deUint32 partCount = bufferCounts[bufferCountsNdx];
4401
4402 for (deUint32 bufferSizesNdx = 0; bufferSizesNdx < DE_LENGTH_OF_ARRAY(bufferSizes); ++bufferSizesNdx)
4403 {
4404 const deUint32 bufferSize = bufferSizes[bufferSizesNdx];
4405 TestParameters parameters = { testType, bufferSize, partCount, 0u, 0u, 0u, STREAM_ID_0_NORMAL, false, false, true, false, false, VK_PRIMITIVE_TOPOLOGY_POINT_LIST, false };
4406
4407 // Simple Transform Feedback test
4408 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_" + de::toString(partCount) + "_" + de::toString(bufferSize)).c_str(), parameters));
4409 parameters.streamId0Mode = STREAM_ID_0_BEGIN_QUERY_INDEXED;
4410 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_beginqueryindexed_streamid_0_" + de::toString(partCount) + "_" + de::toString(bufferSize)).c_str(), parameters));
4411 parameters.streamId0Mode = STREAM_ID_0_END_QUERY_INDEXED;
4412 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_endqueryindexed_streamid_0_" + de::toString(partCount) + "_" + de::toString(bufferSize)).c_str(), parameters));
4413 }
4414 }
4415 }
4416 }
4417
4418 {
4419 const deUint32 bufferCounts[] = { 6u, 8u, 10u, 12u };
4420 const TestType testType = TEST_TYPE_WINDING;
4421 const std::string testName = "winding";
4422
4423 for (const auto& topology : topologyData)
4424 {
4425 // Note: no need to test POINT_LIST as is tested in many tests.
4426 if (topology.first == VK_PRIMITIVE_TOPOLOGY_POINT_LIST)
4427 continue;
4428
4429 for (deUint32 bufferCountsNdx = 0; bufferCountsNdx < DE_LENGTH_OF_ARRAY(bufferCounts); ++bufferCountsNdx)
4430 {
4431 const deUint32 vertexCount = bufferCounts[bufferCountsNdx];
4432
4433 TestParameters parameters = { testType, 0u, vertexCount, 0u, 0u, 0u, STREAM_ID_0_NORMAL, false, false, false, false, false, topology.first, false };
4434
4435 // Topology winding test
4436 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_" + topology.second.topologyName + de::toString(vertexCount)).c_str(), parameters));
4437 }
4438 }
4439 }
4440
4441 {
4442 for (int i = 0; i < 2; ++i)
4443 {
4444 const bool multiview = (i > 0);
4445 const deUint32 vertexStrides[] = { 4u, 61u, 127u, 251u, 509u };
4446 const TestType testType = (multiview ? TEST_TYPE_DRAW_INDIRECT_MULTIVIEW : TEST_TYPE_DRAW_INDIRECT);
4447 const std::string testName = std::string("draw_indirect") + (multiview ? "_multiview" : "");
4448
4449 for (deUint32 vertexStridesNdx = 0; vertexStridesNdx < DE_LENGTH_OF_ARRAY(vertexStrides); ++vertexStridesNdx)
4450 {
4451 const deUint32 vertexStrideBytes = static_cast<deUint32>(sizeof(deUint32) * vertexStrides[vertexStridesNdx]);
4452 TestParameters parameters = { testType, 0u, 0u, 0u, 0u, vertexStrideBytes, STREAM_ID_0_NORMAL, false, false, false, false, false, VK_PRIMITIVE_TOPOLOGY_POINT_LIST, false };
4453
4454 // Rendering tests with various strides
4455 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_" + de::toString(vertexStrideBytes)).c_str(), parameters));
4456 parameters.streamId0Mode = STREAM_ID_0_BEGIN_QUERY_INDEXED;
4457 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_beginqueryindexed_streamid_0_" + de::toString(vertexStrideBytes)).c_str(), parameters));
4458 parameters.streamId0Mode = STREAM_ID_0_END_QUERY_INDEXED;
4459 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_endqueryindexed_streamid_0_" + de::toString(vertexStrideBytes)).c_str(), parameters));
4460 }
4461 }
4462 }
4463
4464 {
4465 const struct
4466 {
4467 TestType testType;
4468 const char* testName;
4469 } testCases[] =
4470 {
4471 { TEST_TYPE_BACKWARD_DEPENDENCY, "backward_dependency" },
4472 { TEST_TYPE_BACKWARD_DEPENDENCY_INDIRECT, "backward_dependency_indirect" },
4473 };
4474
4475 for (const auto& testCase : testCases)
4476 {
4477 const auto& testType = testCase.testType;
4478 const std::string testName = testCase.testName;
4479 TestParameters parameters = { testType, 512u, 2u, 0u, 0u, 0u, STREAM_ID_0_NORMAL, false, false, false, false, false, VK_PRIMITIVE_TOPOLOGY_POINT_LIST, false };
4480
4481 // Rendering test checks backward pipeline dependency
4482 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), testName.c_str(), parameters));
4483 parameters.streamId0Mode = STREAM_ID_0_BEGIN_QUERY_INDEXED;
4484 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_beginqueryindexed_streamid_0").c_str(), parameters));
4485 parameters.streamId0Mode = STREAM_ID_0_END_QUERY_INDEXED;
4486 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_endqueryindexed_streamid_0").c_str(), parameters));
4487
4488 // Rendering test checks backward pipeline dependency (using NULL for offset array)
4489 parameters.noOffsetArray = true;
4490 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_no_offset_array").c_str(), parameters));
4491 }
4492 }
4493
4494 {
4495 const deUint32 usedStreamId[] = { 0u, 1u, 3u, 6u, 14u };
4496 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.
4497 const TestType testType = TEST_TYPE_QUERY_GET;
4498 const std::string testName = "query";
4499 const TestType testTypeCopy[] = { TEST_TYPE_QUERY_COPY, TEST_TYPE_QUERY_COPY_STRIDE_ZERO };
4500 const std::string testNameCopy[] = { "query_copy", "query_copy_stride_zero" };
4501 const TestType testTypeHostQueryReset = TEST_TYPE_QUERY_RESET;
4502 const std::string testNameHostQueryReset = "host_query_reset";
4503
4504 for (const auto& topology : topologyData)
4505 {
4506 // Currently, we don't test tessellation here.
4507 if (topology.first == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST)
4508 continue;
4509
4510 for (const auto& streamCounts : usedStreamId)
4511 {
4512 const deUint32 streamId = streamCounts;
4513
4514 for (const auto& numVertices : vertexCounts)
4515 {
4516 for (deUint32 i = 0; i < 2; ++i)
4517 {
4518 const bool query64Bits = (i == 1);
4519 const std::string widthStr = (query64Bits ? "_64bits" : "_32bits");
4520
4521 deUint32 vertCount = numVertices;
4522
4523 // The number of vertices in original test was 4.
4524 if (topology.first == VK_PRIMITIVE_TOPOLOGY_POINT_LIST && vertCount == 6) vertCount -= 2;
4525
4526 // Round the number of vertices to match the used primitive topology - if necessary.
4527 const deUint32 primitiveCount = (deUint32)topology.second.getNumPrimitives(vertCount);
4528 const deUint32 vertexCount = (deUint32)topology.second.getNumVertices(primitiveCount);
4529
4530 DE_ASSERT(vertexCount > 0);
4531
4532 const deUint32 bytesPerVertex = static_cast<deUint32>(4 * sizeof(float));
4533 const deUint32 bufferSize = bytesPerVertex * vertexCount;
4534 TestParameters parameters = { testType, bufferSize, 0u, streamId, 0u, 0u, STREAM_ID_0_NORMAL, query64Bits, false, true, false, false, topology.first, false };
4535 const std::string fullTestName = testName + "_" + topology.second.topologyName + de::toString(streamId) + "_" + de::toString(vertexCount) + widthStr;
4536
4537 // Written primitives query test
4538 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), fullTestName.c_str(), parameters));
4539
4540 TestParameters omitParameters = { testType, bufferSize, 0u, streamId, 0u, 0u, STREAM_ID_0_NORMAL, query64Bits, false, true, true, false, topology.first, false };
4541 const std::string omitTestName = testName + "_omit_write_" + topology.second.topologyName + de::toString(streamId) + "_" + de::toString(vertexCount) + widthStr;
4542 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), omitTestName.c_str(), omitParameters));
4543
4544 for (deUint32 testTypeCopyNdx = 0; testTypeCopyNdx < DE_LENGTH_OF_ARRAY(testTypeCopy); testTypeCopyNdx++)
4545 {
4546 TestParameters parametersCopy = { testTypeCopy[testTypeCopyNdx], bufferSize, 0u, streamId, 0u, 0u, STREAM_ID_0_NORMAL, query64Bits, false, true, false, false, topology.first, false };
4547 const std::string fullTestNameCopy = testNameCopy[testTypeCopyNdx] + "_" + topology.second.topologyName + de::toString(streamId) + "_" + de::toString(vertexCount) + widthStr;
4548 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), fullTestNameCopy.c_str(), parametersCopy));
4549
4550 parametersCopy.queryResultWithAvailability = true;
4551 const std::string fullTestNameQueryWithAvailability = testNameCopy[testTypeCopyNdx] + "_" + topology.second.topologyName + de::toString(streamId) + "_" + de::toString(vertexCount) + widthStr + "_query_with_availability";
4552 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), fullTestNameQueryWithAvailability.c_str(), parametersCopy));
4553 }
4554
4555 const TestParameters parametersHostQueryReset = { testTypeHostQueryReset, bufferSize, 0u, streamId, 0u, 0u, STREAM_ID_0_NORMAL, query64Bits, false, true, false, false, topology.first, false };
4556 const std::string fullTestNameHostQueryReset = testNameHostQueryReset + "_" + topology.second.topologyName + de::toString(streamId) + "_" + de::toString(vertexCount) + widthStr;
4557 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), fullTestNameHostQueryReset.c_str(), parametersHostQueryReset));
4558
4559 if (streamId == 0)
4560 {
4561 std::string testNameStream0 = fullTestName;
4562 testNameStream0 += "_beginqueryindexed_streamid_0";
4563 parameters.streamId0Mode = STREAM_ID_0_BEGIN_QUERY_INDEXED;
4564 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), testNameStream0.c_str(), parameters));
4565 testNameStream0 = fullTestName;
4566 testNameStream0 += "_endqueryindexed_streamid_0";
4567 parameters.streamId0Mode = STREAM_ID_0_END_QUERY_INDEXED;
4568 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), testNameStream0.c_str(), parameters));
4569 }
4570 }
4571 }
4572 }
4573 }
4574 }
4575
4576 // Depth clip control tests.
4577 {
4578 TestParameters parameters = { TEST_TYPE_DEPTH_CLIP_CONTROL_VERTEX, 96, 1u, 0u, 0u, 0u, STREAM_ID_0_NORMAL, false, false, true, false, false, VK_PRIMITIVE_TOPOLOGY_POINT_LIST, false };
4579
4580 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), "depth_clip_control_vertex", parameters));
4581 }
4582 {
4583 TestParameters parameters = { TEST_TYPE_DEPTH_CLIP_CONTROL_GEOMETRY, 96, 1u, 0u, 0u, 0u, STREAM_ID_0_NORMAL, false, false, true, false, false, VK_PRIMITIVE_TOPOLOGY_POINT_LIST, false };
4584
4585 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), "depth_clip_control_geometry", parameters));
4586 }
4587 {
4588 TestParameters parameters = { TEST_TYPE_DEPTH_CLIP_CONTROL_TESE, 96, 1u, 0u, 0u, 0u, STREAM_ID_0_NORMAL, false, false, true, false, false, VK_PRIMITIVE_TOPOLOGY_PATCH_LIST, false };
4589
4590 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), "depth_clip_control_tese", parameters));
4591 }
4592
4593 {
4594 const deUint32 usedStreamId[] = { 1u, 3u, 6u, 14u };
4595 const TestType testType = TEST_TYPE_LINES_TRIANGLES;
4596 const std::string testName = "lines_or_triangles";
4597
4598 for (const auto& topology : topologyData)
4599 {
4600 const deUint32 outputVertexCount = (topology.first == VK_PRIMITIVE_TOPOLOGY_LINE_STRIP) ? 2 * destripedLineCount(LINES_LIST)
4601 : (topology.first == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP) ? 3 * destripedTriangleCount(TRIANGLES_LIST)
4602 : 0;
4603
4604 if (outputVertexCount == 0)
4605 continue;
4606
4607 for (const auto& streamId : usedStreamId)
4608 {
4609 const deUint32 partCount = 2u;
4610 const deUint32 bytesPerVertex = static_cast<deUint32>(sizeof(tcu::Vec4));
4611 const deUint32 bufferSize = partCount * INVOCATION_COUNT * outputVertexCount * bytesPerVertex;
4612 const std::string fullTestName = testName + "_" + topology.second.topologyName + de::toString(streamId);
4613 const TestParameters parameters =
4614 {
4615 testType, // TestType testType;
4616 bufferSize, // deUint32 bufferSize;
4617 partCount, // deUint32 partCount;
4618 streamId, // deUint32 streamId;
4619 0u, // deUint32 pointSize;
4620 0u, // deUint32 vertexStride;
4621 STREAM_ID_0_NORMAL, // StreamId0Mode streamId0Mode;
4622 false, // bool query64bits;
4623 false, // bool noOffsetArray;
4624 true, // bool requireRastStreamSelect;
4625 false, // bool omitShaderWrite;
4626 false, // bool useMaintenance5;
4627 topology.first, // VkPrimitiveTopology primTopology;
4628 false // bool queryResultWithAvailability;
4629 };
4630
4631 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), fullTestName.c_str(), parameters));
4632 }
4633 }
4634 }
4635
4636 #ifndef CTS_USES_VULKANSC
4637 {
4638 const TestParameters parameters
4639 {
4640 TEST_TYPE_RESUME, // TestType testType;
4641 96u, // deUint32 bufferSize;
4642 2u, // deUint32 partCount;
4643 1u, // deUint32 streamId;
4644 0u, // deUint32 pointSize;
4645 0u, // deUint32 vertexStride;
4646 STREAM_ID_0_NORMAL, // StreamId0Mode streamId0Mode;
4647 false, // bool query64bits;
4648 false, // bool noOffsetArray;
4649 true, // bool requireRastStreamSelect;
4650 false, // bool omitShaderWrite;
4651 true, // bool useMaintenance5;
4652 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, // VkPrimitiveTopology primTopology;
4653 false // bool queryResultWithAvailability
4654 };
4655 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), "maintenance5", parameters));
4656 }
4657 #endif // CTS_USES_VULKANSC
4658 }
4659
createTransformFeedbackStreamsSimpleTests(tcu::TestCaseGroup* group)4660 void createTransformFeedbackStreamsSimpleTests (tcu::TestCaseGroup* group)
4661 {
4662 const deUint32 usedStreamId[] = { 1u, 3u, 6u, 14u };
4663 const TestType testTypes[] = { TEST_TYPE_STREAMS, TEST_TYPE_STREAMS_POINTSIZE, TEST_TYPE_STREAMS_CLIPDISTANCE, TEST_TYPE_STREAMS_CULLDISTANCE };
4664 const std::string testTypeNames[] = { "streams", "streams_pointsize", "streams_clipdistance", "streams_culldistance" };
4665
4666 for (deUint32 testTypesNdx = 0; testTypesNdx < DE_LENGTH_OF_ARRAY(testTypes); ++testTypesNdx)
4667 {
4668 const TestType testType = testTypes[testTypesNdx];
4669 const std::string testName = testTypeNames[testTypesNdx];
4670 const deUint32 pointSize = (testType == TEST_TYPE_STREAMS_POINTSIZE) ? 2u : 0u;
4671
4672 for (deUint32 streamCountsNdx = 0; streamCountsNdx < DE_LENGTH_OF_ARRAY(usedStreamId); ++streamCountsNdx)
4673 {
4674 const deUint32 streamId = usedStreamId[streamCountsNdx];
4675 TestParameters parameters = { testType, 0u, 0u, streamId, pointSize, 0u, STREAM_ID_0_NORMAL, false, false, true, false, false, VK_PRIMITIVE_TOPOLOGY_POINT_LIST, false };
4676
4677 // Streams usage test
4678 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_" + de::toString(streamId)).c_str(), parameters));
4679 }
4680 }
4681
4682 {
4683 const TestType testType = TEST_TYPE_MULTISTREAMS;
4684 const std::string testName = "multistreams";
4685
4686 for (deUint32 bufferCountsNdx = 0; bufferCountsNdx < DE_LENGTH_OF_ARRAY(usedStreamId); ++bufferCountsNdx)
4687 {
4688 const deUint32 streamId = usedStreamId[bufferCountsNdx];
4689 const deUint32 streamsUsed = 2u;
4690 const deUint32 maxBytesPerVertex = 256u;
4691 const TestParameters parameters = { testType, maxBytesPerVertex * streamsUsed, streamsUsed, streamId, 0u, 0u, STREAM_ID_0_NORMAL, false, false, false, false, false, VK_PRIMITIVE_TOPOLOGY_POINT_LIST, false };
4692
4693 // Simultaneous multiple streams usage test
4694 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_" + de::toString(streamId)).c_str(), parameters));
4695 }
4696 }
4697
4698 {
4699 const TestType testType = TEST_TYPE_MULTISTREAMS_SAME_LOCATION;
4700 const std::string testName = "multistreams_same_location";
4701 for (const auto streamId : usedStreamId)
4702 {
4703 const deUint32 streamsUsed = 2u;
4704 const TestParameters parameters = { testType, 32 * 4, streamsUsed, streamId, 0u, 0u, STREAM_ID_0_NORMAL, false, false, false, false, false, VK_PRIMITIVE_TOPOLOGY_POINT_LIST, false };
4705
4706 // Simultaneous multiple streams to the same location usage test
4707 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_" + de::toString(streamId)).c_str(), parameters));
4708 }
4709 }
4710
4711 {
4712 const TestType testType = TEST_TYPE_MULTIQUERY;
4713 const std::string testName = "multiquery";
4714
4715 for (deUint32 bufferCountsNdx = 0; bufferCountsNdx < DE_LENGTH_OF_ARRAY(usedStreamId); ++bufferCountsNdx)
4716 {
4717 const deUint32 streamId = usedStreamId[bufferCountsNdx];
4718 const deUint32 streamsUsed = 2u;
4719 const deUint32 maxBytesPerVertex = 256u;
4720 const TestParameters parameters = { testType, maxBytesPerVertex * streamsUsed, streamsUsed, streamId, 0u, 0u, STREAM_ID_0_NORMAL, false, false, false, false, false, VK_PRIMITIVE_TOPOLOGY_POINT_LIST, false };
4721 const TestParameters writeOmitParameters = { testType, maxBytesPerVertex * streamsUsed, streamsUsed, streamId, 0u, 0u, STREAM_ID_0_NORMAL, false, false, false, true, false, VK_PRIMITIVE_TOPOLOGY_POINT_LIST, false };
4722
4723 // Simultaneous multiple queries usage test
4724 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_" + de::toString(streamId)).c_str(), parameters));
4725 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_omit_write_" + de::toString(streamId)).c_str(), writeOmitParameters));
4726 }
4727 }
4728
4729 {
4730 struct
4731 {
4732 TestType testType;
4733 const char* suffix;
4734 } holeCases[] =
4735 {
4736 { TEST_TYPE_HOLES_VERTEX, "_vert" },
4737 { TEST_TYPE_HOLES_GEOMETRY, "_geom" },
4738 };
4739 const std::string testNameBase = "holes";
4740
4741 for (const auto& holeCase : holeCases)
4742 for (const auto& extraDraw : { false, true})
4743 {
4744 const auto partCount = (extraDraw ? 2u : 1u);
4745 const auto testName = testNameBase + (extraDraw ? "_extra_draw" : "");
4746 const TestParameters parameters { holeCase.testType, 0u, partCount, 0u, 1u, 0u, STREAM_ID_0_NORMAL, false, false, false, false, false, VK_PRIMITIVE_TOPOLOGY_POINT_LIST, false };;
4747
4748 // Test skipping components in the XFB buffer
4749 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + holeCase.suffix).c_str(), parameters));
4750 }
4751 }
4752 }
4753
createTransformFeedbackAndStreamsSimpleTests(tcu::TestCaseGroup* group)4754 void createTransformFeedbackAndStreamsSimpleTests (tcu::TestCaseGroup* group)
4755 {
4756 createTransformFeedbackSimpleTests(group);
4757 createTransformFeedbackStreamsSimpleTests(group);
4758 }
4759 } // anonymous
4760
createTransformFeedbackSimpleTests(tcu::TestContext& testCtx)4761 tcu::TestCaseGroup* createTransformFeedbackSimpleTests (tcu::TestContext& testCtx)
4762 {
4763 return createTestGroup(testCtx, "simple", createTransformFeedbackAndStreamsSimpleTests);
4764 }
4765
4766 } // TransformFeedback
4767 } // vkt
4768