1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2017 The Khronos Group Inc.
6 * Copyright (c) 2017 Codeplay Software Ltd.
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *
20 */ /*!
21 * \file
22 * \brief Subgroups Tests Utils
23 */ /*--------------------------------------------------------------------*/
24
25 #include "vktSubgroupsTestsUtils.hpp"
26 #include "deRandom.hpp"
27 #include "tcuCommandLine.hpp"
28 #include "vkImageUtil.hpp"
29
30 using namespace tcu;
31 using namespace std;
32 using namespace vk;
33 using namespace vkt;
34
35 namespace
36 {
getFormatSizeInBytes(const VkFormat format)37 deUint32 getFormatSizeInBytes(const VkFormat format)
38 {
39 switch (format)
40 {
41 default:
42 DE_FATAL("Unhandled format!");
43 case VK_FORMAT_R32_SINT:
44 case VK_FORMAT_R32_UINT:
45 return sizeof(deInt32);
46 case VK_FORMAT_R32G32_SINT:
47 case VK_FORMAT_R32G32_UINT:
48 return static_cast<deUint32>(sizeof(deInt32) * 2);
49 case VK_FORMAT_R32G32B32_SINT:
50 case VK_FORMAT_R32G32B32_UINT:
51 case VK_FORMAT_R32G32B32A32_SINT:
52 case VK_FORMAT_R32G32B32A32_UINT:
53 return static_cast<deUint32>(sizeof(deInt32) * 4);
54 case VK_FORMAT_R32_SFLOAT:
55 return 4;
56 case VK_FORMAT_R32G32_SFLOAT:
57 return 8;
58 case VK_FORMAT_R32G32B32_SFLOAT:
59 return 16;
60 case VK_FORMAT_R32G32B32A32_SFLOAT:
61 return 16;
62 case VK_FORMAT_R64_SFLOAT:
63 return 8;
64 case VK_FORMAT_R64G64_SFLOAT:
65 return 16;
66 case VK_FORMAT_R64G64B64_SFLOAT:
67 return 32;
68 case VK_FORMAT_R64G64B64A64_SFLOAT:
69 return 32;
70 // The below formats are used to represent bool and bvec* types. These
71 // types are passed to the shader as int and ivec* types, before the
72 // calculations are done as booleans. We need a distinct type here so
73 // that the shader generators can switch on it and generate the correct
74 // shader source for testing.
75 case VK_FORMAT_R8_USCALED:
76 return sizeof(deInt32);
77 case VK_FORMAT_R8G8_USCALED:
78 return static_cast<deUint32>(sizeof(deInt32) * 2);
79 case VK_FORMAT_R8G8B8_USCALED:
80 case VK_FORMAT_R8G8B8A8_USCALED:
81 return static_cast<deUint32>(sizeof(deInt32) * 4);
82 }
83 }
84
makePipelineLayout(Context & context,const VkDescriptorSetLayout descriptorSetLayout)85 Move<VkPipelineLayout> makePipelineLayout(
86 Context& context, const VkDescriptorSetLayout descriptorSetLayout)
87 {
88 const vk::VkPipelineLayoutCreateInfo pipelineLayoutParams = {
89 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
90 DE_NULL, // const void* pNext;
91 0u, // VkPipelineLayoutCreateFlags flags;
92 1u, // deUint32 setLayoutCount;
93 &descriptorSetLayout, // const VkDescriptorSetLayout* pSetLayouts;
94 0u, // deUint32 pushConstantRangeCount;
95 DE_NULL, // const VkPushConstantRange* pPushConstantRanges;
96 };
97 return createPipelineLayout(context.getDeviceInterface(),
98 context.getDevice(), &pipelineLayoutParams);
99 }
100
makeRenderPass(Context & context,VkFormat format)101 Move<VkRenderPass> makeRenderPass(Context& context, VkFormat format)
102 {
103 VkAttachmentReference colorReference = {
104 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
105 };
106
107 const VkSubpassDescription subpassDescription = {0u,
108 VK_PIPELINE_BIND_POINT_GRAPHICS, 0, DE_NULL, 1, &colorReference,
109 DE_NULL, DE_NULL, 0, DE_NULL
110 };
111
112 const VkSubpassDependency subpassDependencies[2] = {
113 { VK_SUBPASS_EXTERNAL, 0u, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
114 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
115 VK_ACCESS_MEMORY_READ_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
116 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
117 VK_DEPENDENCY_BY_REGION_BIT
118 },
119 { 0u, VK_SUBPASS_EXTERNAL, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
120 VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
121 VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
122 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
123 VK_ACCESS_MEMORY_READ_BIT, VK_DEPENDENCY_BY_REGION_BIT
124 },
125 };
126
127 VkAttachmentDescription attachmentDescription = {0u, format,
128 VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_CLEAR,
129 VK_ATTACHMENT_STORE_OP_STORE, VK_ATTACHMENT_LOAD_OP_DONT_CARE,
130 VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_UNDEFINED,
131 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
132 };
133
134 const VkRenderPassCreateInfo renderPassCreateInfo = {
135 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, DE_NULL, 0u, 1,
136 &attachmentDescription, 1, &subpassDescription, 2, subpassDependencies
137 };
138
139 return createRenderPass(context.getDeviceInterface(), context.getDevice(),
140 &renderPassCreateInfo);
141 }
142
makeFramebuffer(Context & context,const VkRenderPass renderPass,const VkImageView imageView,deUint32 width,deUint32 height)143 Move<VkFramebuffer> makeFramebuffer(Context& context,
144 const VkRenderPass renderPass, const VkImageView imageView, deUint32 width,
145 deUint32 height)
146 {
147 const VkFramebufferCreateInfo framebufferCreateInfo = {
148 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, DE_NULL, 0u, renderPass, 1,
149 &imageView, width, height, 1
150 };
151
152 return createFramebuffer(context.getDeviceInterface(), context.getDevice(),
153 &framebufferCreateInfo);
154 }
155
makeGraphicsPipeline(Context & context,const VkPipelineLayout pipelineLayout,const VkShaderStageFlags stages,const VkShaderModule vertexShaderModule,const VkShaderModule fragmentShaderModule,const VkShaderModule geometryShaderModule,const VkShaderModule tessellationControlModule,const VkShaderModule tessellationEvaluationModule,const VkRenderPass renderPass,const VkPrimitiveTopology topology=VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,const VkVertexInputBindingDescription * vertexInputBindingDescription=DE_NULL,const VkVertexInputAttributeDescription * vertexInputAttributeDescriptions=DE_NULL,const vk::VkFormat attachmentFormat=VK_FORMAT_R32G32B32A32_SFLOAT)156 Move<VkPipeline> makeGraphicsPipeline(Context& context,
157 const VkPipelineLayout pipelineLayout,
158 const VkShaderStageFlags stages,
159 const VkShaderModule vertexShaderModule,
160 const VkShaderModule fragmentShaderModule,
161 const VkShaderModule geometryShaderModule,
162 const VkShaderModule tessellationControlModule,
163 const VkShaderModule tessellationEvaluationModule,
164 const VkRenderPass renderPass,
165 const VkPrimitiveTopology topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
166 const VkVertexInputBindingDescription* vertexInputBindingDescription = DE_NULL,
167 const VkVertexInputAttributeDescription* vertexInputAttributeDescriptions = DE_NULL,
168 const vk::VkFormat attachmentFormat = VK_FORMAT_R32G32B32A32_SFLOAT
169 )
170 {
171 const VkBool32 disableRasterization = !(VK_SHADER_STAGE_FRAGMENT_BIT & stages);
172 std::vector<vk::VkPipelineShaderStageCreateInfo> pipelineShaderStageParams;
173 {
174 const vk::VkPipelineShaderStageCreateInfo stageCreateInfo =
175 {
176 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType
177 DE_NULL, // const void* pNext
178 0u, // VkPipelineShaderStageCreateFlags flags
179 VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage
180 vertexShaderModule, // VkShaderModule module
181 "main", // const char* pName
182 DE_NULL // const VkSpecializationInfo* pSpecializationInfo
183 };
184 pipelineShaderStageParams.push_back(stageCreateInfo);
185 }
186
187 if (VK_SHADER_STAGE_FRAGMENT_BIT & stages)
188 {
189 const vk::VkPipelineShaderStageCreateInfo stageCreateInfo =
190 {
191 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType
192 DE_NULL, // const void* pNext
193 0u, // VkPipelineShaderStageCreateFlags flags
194 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage
195 fragmentShaderModule, // VkShaderModule module
196 "main", // const char* pName
197 DE_NULL // const VkSpecializationInfo* pSpecializationInfo
198 };
199 pipelineShaderStageParams.push_back(stageCreateInfo);
200 }
201
202 if (VK_SHADER_STAGE_GEOMETRY_BIT & stages)
203 {
204 const vk::VkPipelineShaderStageCreateInfo stageCreateInfo =
205 {
206 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType
207 DE_NULL, // const void* pNext
208 0u, // VkPipelineShaderStageCreateFlags flags
209 VK_SHADER_STAGE_GEOMETRY_BIT, // VkShaderStageFlagBits stage
210 geometryShaderModule, // VkShaderModule module
211 "main", // const char* pName
212 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo
213 };
214 pipelineShaderStageParams.push_back(stageCreateInfo);
215 }
216
217 if (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT & stages)
218 {
219 const vk::VkPipelineShaderStageCreateInfo stageCreateInfo =
220 {
221 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType
222 DE_NULL, // const void* pNext
223 0u, // VkPipelineShaderStageCreateFlags flags
224 VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, // VkShaderStageFlagBits stage
225 tessellationControlModule, // VkShaderModule module
226 "main", // const char* pName
227 DE_NULL // const VkSpecializationInfo* pSpecializationInfo
228 };
229 pipelineShaderStageParams.push_back(stageCreateInfo);
230 }
231
232 if (VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT & stages)
233 {
234 const vk::VkPipelineShaderStageCreateInfo stageCreateInfo =
235 {
236 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType
237 DE_NULL, // const void* pNext
238 0u, // VkPipelineShaderStageCreateFlags flags
239 VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, // VkShaderStageFlagBits stage
240 tessellationEvaluationModule, // VkShaderModule module
241 "main", // const char* pName
242 DE_NULL // const VkSpecializationInfo* pSpecializationInfo
243 };
244 pipelineShaderStageParams.push_back(stageCreateInfo);
245 }
246
247 const VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo =
248 {
249 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
250 DE_NULL, // const void* pNext;
251 0u, // VkPipelineVertexInputStateCreateFlags flags;
252 vertexInputBindingDescription == DE_NULL ? 0u : 1u, // deUint32 vertexBindingDescriptionCount;
253 vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
254 vertexInputAttributeDescriptions == DE_NULL ? 0u : 1u, // deUint32 vertexAttributeDescriptionCount;
255 vertexInputAttributeDescriptions, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
256 };
257
258 const VkPipelineTessellationStateCreateInfo tessellationStateCreateInfo =
259 {
260 VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,
261 DE_NULL,
262 0,
263 1
264 };
265
266 const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo =
267 {
268 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, DE_NULL,
269 0u, topology, VK_FALSE
270 };
271
272 const VkPipelineViewportStateCreateInfo viewportStateCreateInfo =
273 {
274 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, DE_NULL, 0u, 1u,
275 DE_NULL, 1u, DE_NULL,
276 };
277
278 const VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo =
279 {
280 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, DE_NULL,
281 0u, VK_FALSE, disableRasterization, VK_POLYGON_MODE_FILL, VK_CULL_MODE_NONE,
282 VK_FRONT_FACE_COUNTER_CLOCKWISE, VK_FALSE, 0.0f, 0.0f, 0.0f, 1.0f
283 };
284
285 const VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfo =
286 {
287 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, DE_NULL, 0u,
288 VK_SAMPLE_COUNT_1_BIT, VK_FALSE, 0.0f, DE_NULL, VK_FALSE, VK_FALSE
289 };
290
291 const VkStencilOpState stencilOpState =
292 {
293 VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_COMPARE_OP_NEVER,
294 0, 0, 0
295 };
296
297 const VkPipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo =
298 {
299 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, DE_NULL, 0u,
300 VK_FALSE, VK_FALSE, VK_COMPARE_OP_NEVER, VK_FALSE, VK_FALSE, stencilOpState,
301 stencilOpState, 0.0f, 0.0f
302 };
303
304 const deUint32 numChannels = getNumUsedChannels(mapVkFormat(attachmentFormat).order);
305 const VkColorComponentFlags colorComponent =
306 numChannels == 1 ? VK_COLOR_COMPONENT_R_BIT :
307 numChannels == 2 ? VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT :
308 numChannels == 3 ? VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT :
309 VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
310
311 const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
312 {
313 VK_FALSE, VK_BLEND_FACTOR_ZERO, VK_BLEND_FACTOR_ZERO, VK_BLEND_OP_ADD,
314 VK_BLEND_FACTOR_ZERO, VK_BLEND_FACTOR_ZERO, VK_BLEND_OP_ADD,
315 colorComponent
316 };
317
318 const VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfo =
319 {
320 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, DE_NULL, 0u,
321 VK_FALSE, VK_LOGIC_OP_CLEAR, 1, &colorBlendAttachmentState,
322 { 0.0f, 0.0f, 0.0f, 0.0f }
323 };
324
325 const VkDynamicState dynamicState[2] =
326 {
327 VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR
328 };
329
330 const VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo =
331 {
332 VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, DE_NULL, 0u, 2,
333 dynamicState,
334 };
335
336 const bool usingTessellation = (VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT & stages)
337 || (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT & stages);
338
339 const VkGraphicsPipelineCreateInfo pipelineCreateInfo =
340 {
341 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, DE_NULL, 0u,
342 static_cast<deUint32>(pipelineShaderStageParams.size()),
343 &pipelineShaderStageParams[0], &vertexInputStateCreateInfo,
344 &inputAssemblyStateCreateInfo, usingTessellation ? &tessellationStateCreateInfo : DE_NULL, &viewportStateCreateInfo,
345 &rasterizationStateCreateInfo, &multisampleStateCreateInfo,
346 &depthStencilStateCreateInfo, &colorBlendStateCreateInfo,
347 &dynamicStateCreateInfo, pipelineLayout, renderPass, 0, DE_NULL, 0
348 };
349
350 return createGraphicsPipeline(context.getDeviceInterface(),
351 context.getDevice(), DE_NULL, &pipelineCreateInfo);
352 }
353
makeComputePipeline(Context & context,const VkPipelineLayout pipelineLayout,const VkShaderModule shaderModule,deUint32 localSizeX,deUint32 localSizeY,deUint32 localSizeZ)354 Move<VkPipeline> makeComputePipeline(Context& context,
355 const VkPipelineLayout pipelineLayout, const VkShaderModule shaderModule,
356 deUint32 localSizeX, deUint32 localSizeY, deUint32 localSizeZ)
357 {
358 const deUint32 localSize[3] = {localSizeX, localSizeY, localSizeZ};
359
360 const vk::VkSpecializationMapEntry entries[3] =
361 {
362 {0, sizeof(deUint32) * 0, sizeof(deUint32)},
363 {1, sizeof(deUint32) * 1, sizeof(deUint32)},
364 {2, static_cast<deUint32>(sizeof(deUint32) * 2), sizeof(deUint32)},
365 };
366
367 const vk::VkSpecializationInfo info =
368 {
369 /* mapEntryCount = */ 3,
370 /* pMapEntries = */ entries,
371 /* dataSize = */ sizeof(localSize),
372 /* pData = */ localSize
373 };
374
375 const vk::VkPipelineShaderStageCreateInfo pipelineShaderStageParams =
376 {
377 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
378 DE_NULL, // const void* pNext;
379 0u, // VkPipelineShaderStageCreateFlags flags;
380 VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlagBits stage;
381 shaderModule, // VkShaderModule module;
382 "main", // const char* pName;
383 &info, // const VkSpecializationInfo* pSpecializationInfo;
384 };
385
386 const vk::VkComputePipelineCreateInfo pipelineCreateInfo =
387 {
388 VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // VkStructureType sType;
389 DE_NULL, // const void* pNext;
390 0u, // VkPipelineCreateFlags flags;
391 pipelineShaderStageParams, // VkPipelineShaderStageCreateInfo stage;
392 pipelineLayout, // VkPipelineLayout layout;
393 DE_NULL, // VkPipeline basePipelineHandle;
394 0, // deInt32 basePipelineIndex;
395 };
396
397 return createComputePipeline(context.getDeviceInterface(),
398 context.getDevice(), DE_NULL, &pipelineCreateInfo);
399 }
400
makeDescriptorSet(Context & context,const VkDescriptorPool descriptorPool,const VkDescriptorSetLayout setLayout)401 Move<VkDescriptorSet> makeDescriptorSet(Context& context,
402 const VkDescriptorPool descriptorPool,
403 const VkDescriptorSetLayout setLayout)
404 {
405 const VkDescriptorSetAllocateInfo allocateParams =
406 {
407 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType
408 // sType;
409 DE_NULL, // const void* pNext;
410 descriptorPool, // VkDescriptorPool descriptorPool;
411 1u, // deUint32 setLayoutCount;
412 &setLayout, // const VkDescriptorSetLayout* pSetLayouts;
413 };
414 return allocateDescriptorSet(
415 context.getDeviceInterface(), context.getDevice(), &allocateParams);
416 }
417
makeCommandPool(Context & context)418 Move<VkCommandPool> makeCommandPool(Context& context)
419 {
420 const VkCommandPoolCreateInfo commandPoolParams =
421 {
422 VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // VkStructureType sType;
423 DE_NULL, // const void* pNext;
424 VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // VkCommandPoolCreateFlags
425 // flags;
426 context.getUniversalQueueFamilyIndex(), // deUint32 queueFamilyIndex;
427 };
428
429 return createCommandPool(
430 context.getDeviceInterface(), context.getDevice(), &commandPoolParams);
431 }
432
makeCommandBuffer(Context & context,const VkCommandPool commandPool)433 Move<VkCommandBuffer> makeCommandBuffer(
434 Context& context, const VkCommandPool commandPool)
435 {
436 const VkCommandBufferAllocateInfo bufferAllocateParams =
437 {
438 VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
439 DE_NULL, // const void* pNext;
440 commandPool, // VkCommandPool commandPool;
441 VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level;
442 1u, // deUint32 bufferCount;
443 };
444 return allocateCommandBuffer(context.getDeviceInterface(),
445 context.getDevice(), &bufferAllocateParams);
446 }
447
beginCommandBuffer(Context & context,const VkCommandBuffer commandBuffer)448 void beginCommandBuffer(Context& context, const VkCommandBuffer commandBuffer)
449 {
450 const VkCommandBufferBeginInfo commandBufBeginParams =
451 {
452 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
453 DE_NULL, // const void* pNext;
454 0u, // VkCommandBufferUsageFlags flags;
455 (const VkCommandBufferInheritanceInfo*)DE_NULL,
456 };
457 VK_CHECK(context.getDeviceInterface().beginCommandBuffer(
458 commandBuffer, &commandBufBeginParams));
459 }
460
endCommandBuffer(Context & context,const VkCommandBuffer commandBuffer)461 void endCommandBuffer(Context& context, const VkCommandBuffer commandBuffer)
462 {
463 VK_CHECK(context.getDeviceInterface().endCommandBuffer(commandBuffer));
464 }
465
submitCommandBuffer(Context & context,const VkCommandBuffer commandBuffer)466 Move<VkFence> submitCommandBuffer(
467 Context& context, const VkCommandBuffer commandBuffer)
468 {
469 const VkFenceCreateInfo fenceParams =
470 {
471 VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType;
472 DE_NULL, // const void* pNext;
473 0u, // VkFenceCreateFlags flags;
474 };
475
476 Move<VkFence> fence(createFence(
477 context.getDeviceInterface(), context.getDevice(), &fenceParams));
478
479 const VkSubmitInfo submitInfo =
480 {
481 VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
482 DE_NULL, // const void* pNext;
483 0u, // deUint32 waitSemaphoreCount;
484 DE_NULL, // const VkSemaphore* pWaitSemaphores;
485 (const VkPipelineStageFlags*)DE_NULL,
486 1u, // deUint32 commandBufferCount;
487 &commandBuffer, // const VkCommandBuffer* pCommandBuffers;
488 0u, // deUint32 signalSemaphoreCount;
489 DE_NULL, // const VkSemaphore* pSignalSemaphores;
490 };
491
492 vk::VkResult result = (context.getDeviceInterface().queueSubmit(
493 context.getUniversalQueue(), 1u, &submitInfo, *fence));
494 VK_CHECK(result);
495
496 return Move<VkFence>(fence);
497 }
498
waitFence(Context & context,Move<VkFence> fence)499 void waitFence(Context& context, Move<VkFence> fence)
500 {
501 VK_CHECK(context.getDeviceInterface().waitForFences(
502 context.getDevice(), 1u, &fence.get(), DE_TRUE, ~0ull));
503 }
504
505 struct Buffer;
506 struct Image;
507
508 struct BufferOrImage
509 {
isImage__anon47479df80111::BufferOrImage510 bool isImage() const
511 {
512 return m_isImage;
513 }
514
getAsBuffer__anon47479df80111::BufferOrImage515 Buffer* getAsBuffer()
516 {
517 if (m_isImage) DE_FATAL("Trying to get a buffer as an image!");
518 return reinterpret_cast<Buffer* >(this);
519 }
520
getAsImage__anon47479df80111::BufferOrImage521 Image* getAsImage()
522 {
523 if (!m_isImage) DE_FATAL("Trying to get an image as a buffer!");
524 return reinterpret_cast<Image*>(this);
525 }
526
getType__anon47479df80111::BufferOrImage527 virtual VkDescriptorType getType() const
528 {
529 if (m_isImage)
530 {
531 return VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
532 }
533 else
534 {
535 return VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
536 }
537 }
538
getAllocation__anon47479df80111::BufferOrImage539 Allocation& getAllocation() const
540 {
541 return *m_allocation;
542 }
543
~BufferOrImage__anon47479df80111::BufferOrImage544 virtual ~BufferOrImage() {}
545
546 protected:
BufferOrImage__anon47479df80111::BufferOrImage547 explicit BufferOrImage(bool image) : m_isImage(image) {}
548
549 bool m_isImage;
550 de::details::MovePtr<Allocation> m_allocation;
551 };
552
553 struct Buffer : public BufferOrImage
554 {
Buffer__anon47479df80111::Buffer555 explicit Buffer(
556 Context& context, VkDeviceSize sizeInBytes, VkBufferUsageFlags usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT)
557 : BufferOrImage (false)
558 , m_sizeInBytes (sizeInBytes)
559 , m_usage (usage)
560 {
561 const vk::VkBufferCreateInfo bufferCreateInfo =
562 {
563 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
564 DE_NULL,
565 0u,
566 sizeInBytes,
567 m_usage,
568 VK_SHARING_MODE_EXCLUSIVE,
569 0u,
570 DE_NULL,
571 };
572 m_buffer = createBuffer(context.getDeviceInterface(),
573 context.getDevice(), &bufferCreateInfo);
574 vk::VkMemoryRequirements req = getBufferMemoryRequirements(
575 context.getDeviceInterface(), context.getDevice(), *m_buffer);
576 req.size *= 2;
577 m_allocation = context.getDefaultAllocator().allocate(
578 req, MemoryRequirement::HostVisible);
579 VK_CHECK(context.getDeviceInterface().bindBufferMemory(
580 context.getDevice(), *m_buffer, m_allocation->getMemory(),
581 m_allocation->getOffset()));
582 }
583
getType__anon47479df80111::Buffer584 virtual VkDescriptorType getType() const
585 {
586 if (VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT == m_usage)
587 {
588 return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
589 }
590 return VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
591 }
592
getBuffer__anon47479df80111::Buffer593 VkBuffer getBuffer() const {
594 return *m_buffer;
595 }
596
getBufferPtr__anon47479df80111::Buffer597 const VkBuffer* getBufferPtr() const {
598 return &(*m_buffer);
599 }
600
getSize__anon47479df80111::Buffer601 VkDeviceSize getSize() const {
602 return m_sizeInBytes;
603 }
604
605 private:
606 Move<VkBuffer> m_buffer;
607 VkDeviceSize m_sizeInBytes;
608 const VkBufferUsageFlags m_usage;
609 };
610
611 struct Image : public BufferOrImage
612 {
Image__anon47479df80111::Image613 explicit Image(Context& context, deUint32 width, deUint32 height,
614 VkFormat format, VkImageUsageFlags usage = VK_IMAGE_USAGE_STORAGE_BIT)
615 : BufferOrImage(true)
616 {
617 const VkImageCreateInfo imageCreateInfo =
618 {
619 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, DE_NULL, 0, VK_IMAGE_TYPE_2D,
620 format, {width, height, 1}, 1, 1, VK_SAMPLE_COUNT_1_BIT,
621 VK_IMAGE_TILING_OPTIMAL, usage,
622 VK_SHARING_MODE_EXCLUSIVE, 0u, DE_NULL,
623 VK_IMAGE_LAYOUT_UNDEFINED
624 };
625 m_image = createImage(context.getDeviceInterface(), context.getDevice(),
626 &imageCreateInfo);
627 vk::VkMemoryRequirements req = getImageMemoryRequirements(
628 context.getDeviceInterface(), context.getDevice(), *m_image);
629 req.size *= 2;
630 m_allocation =
631 context.getDefaultAllocator().allocate(req, MemoryRequirement::Any);
632 VK_CHECK(context.getDeviceInterface().bindImageMemory(
633 context.getDevice(), *m_image, m_allocation->getMemory(),
634 m_allocation->getOffset()));
635
636 const VkComponentMapping componentMapping =
637 {
638 VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY,
639 VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY
640 };
641
642 const VkImageViewCreateInfo imageViewCreateInfo =
643 {
644 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, DE_NULL, 0, *m_image,
645 VK_IMAGE_VIEW_TYPE_2D, imageCreateInfo.format, componentMapping,
646 {
647 VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1,
648 }
649 };
650
651 m_imageView = createImageView(context.getDeviceInterface(),
652 context.getDevice(), &imageViewCreateInfo);
653
654 const struct VkSamplerCreateInfo samplerCreateInfo =
655 {
656 VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
657 DE_NULL,
658 0u,
659 VK_FILTER_NEAREST,
660 VK_FILTER_NEAREST,
661 VK_SAMPLER_MIPMAP_MODE_NEAREST,
662 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
663 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
664 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
665 0.0f,
666 VK_FALSE,
667 1.0f,
668 DE_FALSE,
669 VK_COMPARE_OP_ALWAYS,
670 0.0f,
671 0.0f,
672 VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,
673 VK_FALSE,
674 };
675
676 m_sampler = createSampler(context.getDeviceInterface(), context.getDevice(), &samplerCreateInfo);
677 }
678
getImage__anon47479df80111::Image679 VkImage getImage() const {
680 return *m_image;
681 }
682
getImageView__anon47479df80111::Image683 VkImageView getImageView() const {
684 return *m_imageView;
685 }
686
getSampler__anon47479df80111::Image687 VkSampler getSampler() const {
688 return *m_sampler;
689 }
690
691 private:
692 Move<VkImage> m_image;
693 Move<VkImageView> m_imageView;
694 Move<VkSampler> m_sampler;
695 };
696 }
697
getSharedMemoryBallotHelper()698 std::string vkt::subgroups::getSharedMemoryBallotHelper()
699 {
700 return "shared uvec4 superSecretComputeShaderHelper[gl_WorkGroupSize.x * gl_WorkGroupSize.y * gl_WorkGroupSize.z];\n"
701 "uvec4 sharedMemoryBallot(bool vote)\n"
702 "{\n"
703 " uint groupOffset = gl_SubgroupID;\n"
704 " // One invocation in the group 0's the whole group's data\n"
705 " if (subgroupElect())\n"
706 " {\n"
707 " superSecretComputeShaderHelper[groupOffset] = uvec4(0);\n"
708 " }\n"
709 " subgroupMemoryBarrierShared();\n"
710 " if (vote)\n"
711 " {\n"
712 " const highp uint invocationId = gl_SubgroupInvocationID % 32;\n"
713 " const highp uint bitToSet = 1u << invocationId;\n"
714 " switch (gl_SubgroupInvocationID / 32)\n"
715 " {\n"
716 " case 0: atomicOr(superSecretComputeShaderHelper[groupOffset].x, bitToSet); break;\n"
717 " case 1: atomicOr(superSecretComputeShaderHelper[groupOffset].y, bitToSet); break;\n"
718 " case 2: atomicOr(superSecretComputeShaderHelper[groupOffset].z, bitToSet); break;\n"
719 " case 3: atomicOr(superSecretComputeShaderHelper[groupOffset].w, bitToSet); break;\n"
720 " }\n"
721 " }\n"
722 " subgroupMemoryBarrierShared();\n"
723 " return superSecretComputeShaderHelper[groupOffset];\n"
724 "}\n";
725 }
726
getSubgroupSize(Context & context)727 deUint32 vkt::subgroups::getSubgroupSize(Context& context)
728 {
729 VkPhysicalDeviceSubgroupProperties subgroupProperties;
730 subgroupProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES;
731 subgroupProperties.pNext = DE_NULL;
732
733 VkPhysicalDeviceProperties2 properties;
734 properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
735 properties.pNext = &subgroupProperties;
736
737 context.getInstanceInterface().getPhysicalDeviceProperties2(context.getPhysicalDevice(), &properties);
738
739 return subgroupProperties.subgroupSize;
740 }
741
maxSupportedSubgroupSize()742 VkDeviceSize vkt::subgroups::maxSupportedSubgroupSize() {
743 return 128u;
744 }
745
getShaderStageName(VkShaderStageFlags stage)746 std::string vkt::subgroups::getShaderStageName(VkShaderStageFlags stage)
747 {
748 switch (stage)
749 {
750 default:
751 DE_FATAL("Unhandled stage!");
752 case VK_SHADER_STAGE_COMPUTE_BIT:
753 return "compute";
754 case VK_SHADER_STAGE_FRAGMENT_BIT:
755 return "fragment";
756 case VK_SHADER_STAGE_VERTEX_BIT:
757 return "vertex";
758 case VK_SHADER_STAGE_GEOMETRY_BIT:
759 return "geometry";
760 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
761 return "tess_control";
762 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
763 return "tess_eval";
764 }
765 }
766
getSubgroupFeatureName(vk::VkSubgroupFeatureFlagBits bit)767 std::string vkt::subgroups::getSubgroupFeatureName(vk::VkSubgroupFeatureFlagBits bit)
768 {
769 switch (bit)
770 {
771 default:
772 DE_FATAL("Unknown subgroup feature category!");
773 case VK_SUBGROUP_FEATURE_BASIC_BIT:
774 return "VK_SUBGROUP_FEATURE_BASIC_BIT";
775 case VK_SUBGROUP_FEATURE_VOTE_BIT:
776 return "VK_SUBGROUP_FEATURE_VOTE_BIT";
777 case VK_SUBGROUP_FEATURE_ARITHMETIC_BIT:
778 return "VK_SUBGROUP_FEATURE_ARITHMETIC_BIT";
779 case VK_SUBGROUP_FEATURE_BALLOT_BIT:
780 return "VK_SUBGROUP_FEATURE_BALLOT_BIT";
781 case VK_SUBGROUP_FEATURE_SHUFFLE_BIT:
782 return "VK_SUBGROUP_FEATURE_SHUFFLE_BIT";
783 case VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT:
784 return "VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT";
785 case VK_SUBGROUP_FEATURE_CLUSTERED_BIT:
786 return "VK_SUBGROUP_FEATURE_CLUSTERED_BIT";
787 case VK_SUBGROUP_FEATURE_QUAD_BIT:
788 return "VK_SUBGROUP_FEATURE_QUAD_BIT";
789 }
790 }
791
getVertShaderForStage(vk::VkShaderStageFlags stage)792 std::string vkt::subgroups::getVertShaderForStage(vk::VkShaderStageFlags stage)
793 {
794 switch (stage)
795 {
796 default:
797 DE_FATAL("Unhandled stage!");
798 case VK_SHADER_STAGE_FRAGMENT_BIT:
799 return
800 "#version 450\n"
801 "void main (void)\n"
802 "{\n"
803 " vec2 uv = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);\n"
804 " gl_Position = vec4(uv * 2.0f + -1.0f, 0.0f, 1.0f);\n"
805 "}\n";
806 case VK_SHADER_STAGE_GEOMETRY_BIT:
807 return
808 "#version 450\n"
809 "void main (void)\n"
810 "{\n"
811 "}\n";
812 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
813 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
814 return
815 "#version 450\n"
816 "void main (void)\n"
817 "{\n"
818 "}\n";
819 }
820 }
821
isSubgroupSupported(Context & context)822 bool vkt::subgroups::isSubgroupSupported(Context& context)
823 {
824 return context.contextSupports(vk::ApiVersion(1, 1, 0));
825 }
826
areSubgroupOperationsSupportedForStage(Context & context,const VkShaderStageFlags stage)827 bool vkt::subgroups::areSubgroupOperationsSupportedForStage(
828 Context& context, const VkShaderStageFlags stage)
829 {
830 VkPhysicalDeviceSubgroupProperties subgroupProperties;
831 subgroupProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES;
832 subgroupProperties.pNext = DE_NULL;
833
834 VkPhysicalDeviceProperties2 properties;
835 properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
836 properties.pNext = &subgroupProperties;
837
838 context.getInstanceInterface().getPhysicalDeviceProperties2(context.getPhysicalDevice(), &properties);
839
840 return (stage & subgroupProperties.supportedStages) ? true : false;
841 }
842
areSubgroupOperationsRequiredForStage(VkShaderStageFlags stage)843 bool vkt::subgroups::areSubgroupOperationsRequiredForStage(
844 VkShaderStageFlags stage)
845 {
846 switch (stage)
847 {
848 default:
849 return false;
850 case VK_SHADER_STAGE_COMPUTE_BIT:
851 return true;
852 }
853 }
854
isSubgroupFeatureSupportedForDevice(Context & context,VkSubgroupFeatureFlagBits bit)855 bool vkt::subgroups::isSubgroupFeatureSupportedForDevice(
856 Context& context,
857 VkSubgroupFeatureFlagBits bit) {
858 VkPhysicalDeviceSubgroupProperties subgroupProperties;
859 subgroupProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES;
860 subgroupProperties.pNext = DE_NULL;
861
862 VkPhysicalDeviceProperties2 properties;
863 properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
864 properties.pNext = &subgroupProperties;
865
866 context.getInstanceInterface().getPhysicalDeviceProperties2(context.getPhysicalDevice(), &properties);
867
868 return (bit & subgroupProperties.supportedOperations) ? true : false;
869 }
870
isFragmentSSBOSupportedForDevice(Context & context)871 bool vkt::subgroups::isFragmentSSBOSupportedForDevice(Context& context)
872 {
873 const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(
874 context.getInstanceInterface(), context.getPhysicalDevice());
875 return features.fragmentStoresAndAtomics ? true : false;
876 }
877
isVertexSSBOSupportedForDevice(Context & context)878 bool vkt::subgroups::isVertexSSBOSupportedForDevice(Context& context)
879 {
880 const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(
881 context.getInstanceInterface(), context.getPhysicalDevice());
882 return features.vertexPipelineStoresAndAtomics ? true : false;
883 }
884
isDoubleSupportedForDevice(Context & context)885 bool vkt::subgroups::isDoubleSupportedForDevice(Context& context)
886 {
887 const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(
888 context.getInstanceInterface(), context.getPhysicalDevice());
889 return features.shaderFloat64 ? true : false;
890 }
891
isDoubleFormat(VkFormat format)892 bool vkt::subgroups::isDoubleFormat(VkFormat format)
893 {
894 switch (format)
895 {
896 default:
897 return false;
898 case VK_FORMAT_R64_SFLOAT:
899 case VK_FORMAT_R64G64_SFLOAT:
900 case VK_FORMAT_R64G64B64_SFLOAT:
901 case VK_FORMAT_R64G64B64A64_SFLOAT:
902 return true;
903 }
904 }
905
getFormatNameForGLSL(VkFormat format)906 std::string vkt::subgroups::getFormatNameForGLSL(VkFormat format)
907 {
908 switch (format)
909 {
910 default:
911 DE_FATAL("Unhandled format!");
912 case VK_FORMAT_R32_SINT:
913 return "int";
914 case VK_FORMAT_R32G32_SINT:
915 return "ivec2";
916 case VK_FORMAT_R32G32B32_SINT:
917 return "ivec3";
918 case VK_FORMAT_R32G32B32A32_SINT:
919 return "ivec4";
920 case VK_FORMAT_R32_UINT:
921 return "uint";
922 case VK_FORMAT_R32G32_UINT:
923 return "uvec2";
924 case VK_FORMAT_R32G32B32_UINT:
925 return "uvec3";
926 case VK_FORMAT_R32G32B32A32_UINT:
927 return "uvec4";
928 case VK_FORMAT_R32_SFLOAT:
929 return "float";
930 case VK_FORMAT_R32G32_SFLOAT:
931 return "vec2";
932 case VK_FORMAT_R32G32B32_SFLOAT:
933 return "vec3";
934 case VK_FORMAT_R32G32B32A32_SFLOAT:
935 return "vec4";
936 case VK_FORMAT_R64_SFLOAT:
937 return "double";
938 case VK_FORMAT_R64G64_SFLOAT:
939 return "dvec2";
940 case VK_FORMAT_R64G64B64_SFLOAT:
941 return "dvec3";
942 case VK_FORMAT_R64G64B64A64_SFLOAT:
943 return "dvec4";
944 case VK_FORMAT_R8_USCALED:
945 return "bool";
946 case VK_FORMAT_R8G8_USCALED:
947 return "bvec2";
948 case VK_FORMAT_R8G8B8_USCALED:
949 return "bvec3";
950 case VK_FORMAT_R8G8B8A8_USCALED:
951 return "bvec4";
952 }
953 }
954
initializeMemory(Context & context,const Allocation & alloc,subgroups::SSBOData & data)955 void initializeMemory(Context& context, const Allocation& alloc, subgroups::SSBOData& data)
956 {
957 const vk::VkFormat format = data.format;
958 const vk::VkDeviceSize size = getFormatSizeInBytes(format) * data.numElements;
959 if (subgroups::SSBOData::InitializeNonZero == data.initializeType)
960 {
961 de::Random rnd(context.getTestContext().getCommandLine().getBaseSeed());
962
963 switch (format)
964 {
965 default:
966 DE_FATAL("Illegal buffer format");
967 case VK_FORMAT_R8_USCALED:
968 case VK_FORMAT_R8G8_USCALED:
969 case VK_FORMAT_R8G8B8_USCALED:
970 case VK_FORMAT_R8G8B8A8_USCALED:
971 case VK_FORMAT_R32_SINT:
972 case VK_FORMAT_R32G32_SINT:
973 case VK_FORMAT_R32G32B32_SINT:
974 case VK_FORMAT_R32G32B32A32_SINT:
975 case VK_FORMAT_R32_UINT:
976 case VK_FORMAT_R32G32_UINT:
977 case VK_FORMAT_R32G32B32_UINT:
978 case VK_FORMAT_R32G32B32A32_UINT:
979 {
980 deUint32* ptr = reinterpret_cast<deUint32*>(alloc.getHostPtr());
981
982 for (vk::VkDeviceSize k = 0; k < (size / 4); k++)
983 {
984 ptr[k] = rnd.getUint32();
985 }
986 }
987 break;
988 case VK_FORMAT_R32_SFLOAT:
989 case VK_FORMAT_R32G32_SFLOAT:
990 case VK_FORMAT_R32G32B32_SFLOAT:
991 case VK_FORMAT_R32G32B32A32_SFLOAT:
992 {
993 float* ptr = reinterpret_cast<float*>(alloc.getHostPtr());
994
995 for (vk::VkDeviceSize k = 0; k < (size / 4); k++)
996 {
997 ptr[k] = rnd.getFloat();
998 }
999 }
1000 break;
1001 case VK_FORMAT_R64_SFLOAT:
1002 case VK_FORMAT_R64G64_SFLOAT:
1003 case VK_FORMAT_R64G64B64_SFLOAT:
1004 case VK_FORMAT_R64G64B64A64_SFLOAT:
1005 {
1006 double* ptr = reinterpret_cast<double*>(alloc.getHostPtr());
1007
1008 for (vk::VkDeviceSize k = 0; k < (size / 4); k++)
1009 {
1010 ptr[k] = rnd.getDouble();
1011 }
1012 }
1013 break;
1014 }
1015 }
1016 else if (subgroups::SSBOData::InitializeZero == data.initializeType)
1017 {
1018 deUint32* ptr = reinterpret_cast<deUint32*>(alloc.getHostPtr());
1019
1020 for (vk::VkDeviceSize k = 0; k < size / 4; k++)
1021 {
1022 ptr[k] = 0;
1023 }
1024 }
1025
1026 if (subgroups::SSBOData::InitializeNone != data.initializeType)
1027 {
1028 flushMappedMemoryRange(context.getDeviceInterface(),
1029 context.getDevice(), alloc.getMemory(), alloc.getOffset(), size);
1030 }
1031 }
1032
makeTessellationEvaluationTest(Context & context,VkFormat format,SSBOData * extraDatas,deUint32 extraDatasCount,bool (* checkResult)(std::vector<const void * > datas,deUint32 width,deUint32 subgroupSize))1033 tcu::TestStatus vkt::subgroups::makeTessellationEvaluationTest(
1034 Context& context, VkFormat format, SSBOData* extraDatas,
1035 deUint32 extraDatasCount,
1036 bool (*checkResult)(std::vector<const void*> datas, deUint32 width, deUint32 subgroupSize))
1037 {
1038 const deUint32 maxWidth = 1024;
1039
1040 const Unique<VkShaderModule> vertexShaderModule(
1041 createShaderModule(context.getDeviceInterface(), context.getDevice(),
1042 context.getBinaryCollection().get("vert"), 0u));
1043 const Unique<VkShaderModule> tessellationControlShaderModule(
1044 createShaderModule(context.getDeviceInterface(), context.getDevice(),
1045 context.getBinaryCollection().get("tesc"), 0u));
1046 const Unique<VkShaderModule> tessellationEvaluationShaderModule(
1047 createShaderModule(context.getDeviceInterface(), context.getDevice(),
1048 context.getBinaryCollection().get("tese"), 0u));
1049
1050 std::vector< de::SharedPtr<BufferOrImage> > inputBuffers(extraDatasCount + 1);
1051
1052 // The implicit result SSBO we use to store our outputs from the shader
1053 {
1054 vk::VkDeviceSize size = getFormatSizeInBytes(format) * maxWidth * 2;
1055 inputBuffers[0] = de::SharedPtr<BufferOrImage>(new Buffer(context, size));
1056 }
1057
1058 for (deUint32 i = 0; i < (inputBuffers.size() - 1); i++)
1059 {
1060 if (extraDatas[i].isImage)
1061 {
1062 inputBuffers[i + 1] = de::SharedPtr<BufferOrImage>(new Image(context,
1063 static_cast<deUint32>(extraDatas[i].numElements), 1, extraDatas[i].format));
1064 }
1065 else
1066 {
1067 vk::VkDeviceSize size =
1068 getFormatSizeInBytes(extraDatas[i].format) * extraDatas[i].numElements;
1069 inputBuffers[i + 1] = de::SharedPtr<BufferOrImage>(new Buffer(context, size));
1070 }
1071
1072 const Allocation& alloc = inputBuffers[i + 1]->getAllocation();
1073 initializeMemory(context, alloc, extraDatas[i]);
1074 }
1075
1076 DescriptorSetLayoutBuilder layoutBuilder;
1077
1078 for (deUint32 i = 0; i < inputBuffers.size(); i++)
1079 {
1080 layoutBuilder.addBinding(inputBuffers[i]->getType(), 1,
1081 VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, DE_NULL);
1082 }
1083
1084 const Unique<VkDescriptorSetLayout> descriptorSetLayout(
1085 layoutBuilder.build(context.getDeviceInterface(), context.getDevice()));
1086
1087 const Unique<VkPipelineLayout> pipelineLayout(
1088 makePipelineLayout(context, *descriptorSetLayout));
1089
1090 const Unique<VkRenderPass> renderPass(makeRenderPass(context, VK_FORMAT_R32_SFLOAT));
1091 const Unique<VkPipeline> pipeline(makeGraphicsPipeline(context, *pipelineLayout,
1092 VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
1093 *vertexShaderModule, DE_NULL, DE_NULL, *tessellationControlShaderModule, *tessellationEvaluationShaderModule,
1094 *renderPass, VK_PRIMITIVE_TOPOLOGY_PATCH_LIST));
1095
1096 DescriptorPoolBuilder poolBuilder;
1097
1098 for (deUint32 i = 0; i < inputBuffers.size(); i++)
1099 {
1100 poolBuilder.addType(inputBuffers[i]->getType());
1101 }
1102
1103 const Unique<VkDescriptorPool> descriptorPool(
1104 poolBuilder.build(context.getDeviceInterface(), context.getDevice(),
1105 VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
1106
1107 // Create descriptor set
1108 const Unique<VkDescriptorSet> descriptorSet(
1109 makeDescriptorSet(context, *descriptorPool, *descriptorSetLayout));
1110
1111 DescriptorSetUpdateBuilder updateBuilder;
1112
1113 for (deUint32 i = 0; i < inputBuffers.size(); i++)
1114 {
1115 if (inputBuffers[i]->isImage())
1116 {
1117 VkDescriptorImageInfo info =
1118 makeDescriptorImageInfo(inputBuffers[i]->getAsImage()->getSampler(),
1119 inputBuffers[i]->getAsImage()->getImageView(), VK_IMAGE_LAYOUT_GENERAL);
1120
1121 updateBuilder.writeSingle(*descriptorSet,
1122 DescriptorSetUpdateBuilder::Location::binding(i),
1123 inputBuffers[i]->getType(), &info);
1124 }
1125 else
1126 {
1127 VkDescriptorBufferInfo info =
1128 makeDescriptorBufferInfo(inputBuffers[i]->getAsBuffer()->getBuffer(),
1129 0ull, inputBuffers[i]->getAsBuffer()->getSize());
1130
1131 updateBuilder.writeSingle(*descriptorSet,
1132 DescriptorSetUpdateBuilder::Location::binding(i),
1133 inputBuffers[i]->getType(), &info);
1134 }
1135 }
1136
1137 updateBuilder.update(context.getDeviceInterface(), context.getDevice());
1138
1139 const Unique<VkCommandPool> cmdPool(makeCommandPool(context));
1140
1141 const deUint32 subgroupSize = getSubgroupSize(context);
1142
1143 const Unique<VkCommandBuffer> cmdBuffer(
1144 makeCommandBuffer(context, *cmdPool));
1145
1146 unsigned totalIterations = 0;
1147 unsigned failedIterations = 0;
1148
1149 Image discardableImage(context, 1, 1, VK_FORMAT_R32_SFLOAT,
1150 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
1151 VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
1152
1153 for (deUint32 width = 1; width < maxWidth; width++)
1154 {
1155 for (deUint32 i = 1; i < inputBuffers.size(); i++)
1156 {
1157 // re-init the data
1158 const Allocation& alloc = inputBuffers[i]->getAllocation();
1159 initializeMemory(context, alloc, extraDatas[i - 1]);
1160 }
1161
1162 totalIterations++;
1163
1164 const Unique<VkFramebuffer> framebuffer(makeFramebuffer(context,
1165 *renderPass, discardableImage.getImageView(), 1, 1));
1166
1167 const VkClearValue clearValue = {{{0.0f, 0.0f, 0.0f, 0.0f}}};
1168
1169 const VkRenderPassBeginInfo renderPassBeginInfo = {
1170 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, DE_NULL, *renderPass,
1171 *framebuffer, {{0, 0}, {1, 1}}, 1, &clearValue,
1172 };
1173
1174 beginCommandBuffer(context, *cmdBuffer);
1175
1176 VkViewport viewport = {0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f};
1177
1178 context.getDeviceInterface().cmdSetViewport(
1179 *cmdBuffer, 0, 1, &viewport);
1180
1181 VkRect2D scissor = {{0, 0}, {1, 1}};
1182
1183 context.getDeviceInterface().cmdSetScissor(
1184 *cmdBuffer, 0, 1, &scissor);
1185
1186 context.getDeviceInterface().cmdBeginRenderPass(
1187 *cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1188
1189 context.getDeviceInterface().cmdBindPipeline(
1190 *cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1191
1192 context.getDeviceInterface().cmdBindDescriptorSets(*cmdBuffer,
1193 VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u,
1194 &descriptorSet.get(), 0u, DE_NULL);
1195
1196 context.getDeviceInterface().cmdDraw(*cmdBuffer, width, 1, 0, 0);
1197
1198 context.getDeviceInterface().cmdEndRenderPass(*cmdBuffer);
1199
1200 endCommandBuffer(context, *cmdBuffer);
1201
1202 Move<VkFence> fence(submitCommandBuffer(context, *cmdBuffer));
1203
1204 waitFence(context, fence);
1205
1206 std::vector<const void*> datas;
1207
1208 for (deUint32 i = 0; i < inputBuffers.size(); i++)
1209 {
1210 if (!inputBuffers[i]->isImage())
1211 {
1212 const Allocation& resultAlloc = inputBuffers[i]->getAllocation();
1213 invalidateMappedMemoryRange(context.getDeviceInterface(),
1214 context.getDevice(), resultAlloc.getMemory(),
1215 resultAlloc.getOffset(), inputBuffers[i]->getAsBuffer()->getSize());
1216
1217 // we always have our result data first
1218 datas.push_back(resultAlloc.getHostPtr());
1219 }
1220 }
1221
1222 if (!checkResult(datas, width * 2, subgroupSize))
1223 {
1224 failedIterations++;
1225 }
1226
1227 context.getDeviceInterface().resetCommandBuffer(*cmdBuffer, 0);
1228 }
1229
1230 if (0 < failedIterations)
1231 {
1232 context.getTestContext().getLog()
1233 << TestLog::Message << (totalIterations - failedIterations) << " / "
1234 << totalIterations << " values passed" << TestLog::EndMessage;
1235 return tcu::TestStatus::fail("Failed!");
1236 }
1237
1238 return tcu::TestStatus::pass("OK");
1239 }
1240
makeTessellationControlTest(Context & context,VkFormat format,SSBOData * extraDatas,deUint32 extraDatasCount,bool (* checkResult)(std::vector<const void * > datas,deUint32 width,deUint32 subgroupSize))1241 tcu::TestStatus vkt::subgroups::makeTessellationControlTest(
1242 Context& context, VkFormat format, SSBOData* extraDatas,
1243 deUint32 extraDatasCount,
1244 bool (*checkResult)(std::vector<const void*> datas, deUint32 width, deUint32 subgroupSize))
1245 {
1246 const deUint32 maxWidth = 1024;
1247
1248 const Unique<VkShaderModule> vertexShaderModule(
1249 createShaderModule(context.getDeviceInterface(), context.getDevice(),
1250 context.getBinaryCollection().get("vert"), 0u));
1251 const Unique<VkShaderModule> tessellationControlShaderModule(
1252 createShaderModule(context.getDeviceInterface(), context.getDevice(),
1253 context.getBinaryCollection().get("tesc"), 0u));
1254 const Unique<VkShaderModule> tessellationEvaluationShaderModule(
1255 createShaderModule(context.getDeviceInterface(), context.getDevice(),
1256 context.getBinaryCollection().get("tese"), 0u));
1257
1258 std::vector< de::SharedPtr<BufferOrImage> > inputBuffers(extraDatasCount + 1);
1259
1260 // The implicit result SSBO we use to store our outputs from the vertex shader
1261 {
1262 vk::VkDeviceSize size = getFormatSizeInBytes(format) * maxWidth;
1263 inputBuffers[0] = de::SharedPtr<BufferOrImage>(new Buffer(context, size));
1264 }
1265
1266 for (deUint32 i = 0; i < (inputBuffers.size() - 1); i++)
1267 {
1268 if (extraDatas[i].isImage)
1269 {
1270 inputBuffers[i + 1] = de::SharedPtr<BufferOrImage>(new Image(context,
1271 static_cast<deUint32>(extraDatas[i].numElements), 1, extraDatas[i].format));
1272 }
1273 else
1274 {
1275 vk::VkDeviceSize size =
1276 getFormatSizeInBytes(extraDatas[i].format) * extraDatas[i].numElements;
1277 inputBuffers[i + 1] = de::SharedPtr<BufferOrImage>(new Buffer(context, size));
1278 }
1279
1280 const Allocation& alloc = inputBuffers[i + 1]->getAllocation();
1281 initializeMemory(context, alloc, extraDatas[i]);
1282 }
1283
1284 DescriptorSetLayoutBuilder layoutBuilder;
1285
1286 for (deUint32 i = 0; i < inputBuffers.size(); i++)
1287 {
1288 layoutBuilder.addBinding(inputBuffers[i]->getType(), 1,
1289 VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, DE_NULL);
1290 }
1291
1292 const Unique<VkDescriptorSetLayout> descriptorSetLayout(
1293 layoutBuilder.build(context.getDeviceInterface(), context.getDevice()));
1294
1295 const Unique<VkPipelineLayout> pipelineLayout(
1296 makePipelineLayout(context, *descriptorSetLayout));
1297
1298 const Unique<VkRenderPass> renderPass(makeRenderPass(context, VK_FORMAT_R32_SFLOAT));
1299 const Unique<VkPipeline> pipeline(makeGraphicsPipeline(context, *pipelineLayout,
1300 VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
1301 *vertexShaderModule, DE_NULL, DE_NULL, *tessellationControlShaderModule, *tessellationEvaluationShaderModule,
1302 *renderPass, VK_PRIMITIVE_TOPOLOGY_PATCH_LIST));
1303
1304 DescriptorPoolBuilder poolBuilder;
1305
1306 for (deUint32 i = 0; i < inputBuffers.size(); i++)
1307 {
1308 poolBuilder.addType(inputBuffers[i]->getType());
1309 }
1310
1311 const Unique<VkDescriptorPool> descriptorPool(
1312 poolBuilder.build(context.getDeviceInterface(), context.getDevice(),
1313 VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
1314
1315 // Create descriptor set
1316 const Unique<VkDescriptorSet> descriptorSet(
1317 makeDescriptorSet(context, *descriptorPool, *descriptorSetLayout));
1318
1319 DescriptorSetUpdateBuilder updateBuilder;
1320
1321 for (deUint32 i = 0; i < inputBuffers.size(); i++)
1322 {
1323 if (inputBuffers[i]->isImage())
1324 {
1325 VkDescriptorImageInfo info =
1326 makeDescriptorImageInfo(inputBuffers[i]->getAsImage()->getSampler(),
1327 inputBuffers[i]->getAsImage()->getImageView(), VK_IMAGE_LAYOUT_GENERAL);
1328
1329 updateBuilder.writeSingle(*descriptorSet,
1330 DescriptorSetUpdateBuilder::Location::binding(i),
1331 inputBuffers[i]->getType(), &info);
1332 }
1333 else
1334 {
1335 VkDescriptorBufferInfo info =
1336 makeDescriptorBufferInfo(inputBuffers[i]->getAsBuffer()->getBuffer(),
1337 0ull, inputBuffers[i]->getAsBuffer()->getSize());
1338
1339 updateBuilder.writeSingle(*descriptorSet,
1340 DescriptorSetUpdateBuilder::Location::binding(i),
1341 inputBuffers[i]->getType(), &info);
1342 }
1343 }
1344
1345 updateBuilder.update(context.getDeviceInterface(), context.getDevice());
1346
1347 const Unique<VkCommandPool> cmdPool(makeCommandPool(context));
1348
1349 const deUint32 subgroupSize = getSubgroupSize(context);
1350
1351 const Unique<VkCommandBuffer> cmdBuffer(
1352 makeCommandBuffer(context, *cmdPool));
1353
1354 unsigned totalIterations = 0;
1355 unsigned failedIterations = 0;
1356
1357 Image discardableImage(context, 1, 1, VK_FORMAT_R32_SFLOAT,
1358 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
1359 VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
1360
1361 for (deUint32 width = 1; width < maxWidth; width++)
1362 {
1363 for (deUint32 i = 1; i < inputBuffers.size(); i++)
1364 {
1365 // re-init the data
1366 const Allocation& alloc = inputBuffers[i]->getAllocation();
1367 initializeMemory(context, alloc, extraDatas[i - 1]);
1368 }
1369
1370 totalIterations++;
1371
1372 const Unique<VkFramebuffer> framebuffer(makeFramebuffer(context,
1373 *renderPass, discardableImage.getImageView(), 1, 1));
1374
1375 const VkClearValue clearValue = {{{0.0f, 0.0f, 0.0f, 0.0f}}};
1376
1377 const VkRenderPassBeginInfo renderPassBeginInfo = {
1378 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, DE_NULL, *renderPass,
1379 *framebuffer, {{0, 0}, {1, 1}}, 1, &clearValue,
1380 };
1381
1382 beginCommandBuffer(context, *cmdBuffer);
1383
1384 VkViewport viewport = {0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f};
1385
1386 context.getDeviceInterface().cmdSetViewport(
1387 *cmdBuffer, 0, 1, &viewport);
1388
1389 VkRect2D scissor = {{0, 0}, {1, 1}};
1390
1391 context.getDeviceInterface().cmdSetScissor(
1392 *cmdBuffer, 0, 1, &scissor);
1393
1394 context.getDeviceInterface().cmdBeginRenderPass(
1395 *cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1396
1397 context.getDeviceInterface().cmdBindPipeline(
1398 *cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1399
1400 context.getDeviceInterface().cmdBindDescriptorSets(*cmdBuffer,
1401 VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u,
1402 &descriptorSet.get(), 0u, DE_NULL);
1403
1404 context.getDeviceInterface().cmdDraw(*cmdBuffer, width, 1, 0, 0);
1405
1406 context.getDeviceInterface().cmdEndRenderPass(*cmdBuffer);
1407
1408 endCommandBuffer(context, *cmdBuffer);
1409
1410 Move<VkFence> fence(submitCommandBuffer(context, *cmdBuffer));
1411
1412 waitFence(context, fence);
1413
1414 std::vector<const void*> datas;
1415
1416 for (deUint32 i = 0; i < inputBuffers.size(); i++)
1417 {
1418 if (!inputBuffers[i]->isImage())
1419 {
1420 const Allocation& resultAlloc = inputBuffers[i]->getAllocation();
1421 invalidateMappedMemoryRange(context.getDeviceInterface(),
1422 context.getDevice(), resultAlloc.getMemory(),
1423 resultAlloc.getOffset(), inputBuffers[i]->getAsBuffer()->getSize());
1424
1425 // we always have our result data first
1426 datas.push_back(resultAlloc.getHostPtr());
1427 }
1428 }
1429
1430 if (!checkResult(datas, width, subgroupSize))
1431 {
1432 failedIterations++;
1433 }
1434
1435 context.getDeviceInterface().resetCommandBuffer(*cmdBuffer, 0);
1436 }
1437
1438 if (0 < failedIterations)
1439 {
1440 context.getTestContext().getLog()
1441 << TestLog::Message << (totalIterations - failedIterations) << " / "
1442 << totalIterations << " values passed" << TestLog::EndMessage;
1443 return tcu::TestStatus::fail("Failed!");
1444 }
1445
1446 return tcu::TestStatus::pass("OK");
1447 }
1448
makeGeometryTest(Context & context,VkFormat format,SSBOData * extraDatas,deUint32 extraDatasCount,bool (* checkResult)(std::vector<const void * > datas,deUint32 width,deUint32 subgroupSize))1449 tcu::TestStatus vkt::subgroups::makeGeometryTest(
1450 Context& context, VkFormat format, SSBOData* extraDatas,
1451 deUint32 extraDatasCount,
1452 bool (*checkResult)(std::vector<const void*> datas, deUint32 width, deUint32 subgroupSize))
1453 {
1454 const deUint32 maxWidth = 1024;
1455
1456 const Unique<VkShaderModule> vertexShaderModule(
1457 createShaderModule(context.getDeviceInterface(), context.getDevice(),
1458 context.getBinaryCollection().get("vert"), 0u));
1459 const Unique<VkShaderModule> geometryShaderModule(
1460 createShaderModule(context.getDeviceInterface(), context.getDevice(),
1461 context.getBinaryCollection().get("geom"), 0u));
1462
1463 std::vector< de::SharedPtr<BufferOrImage> > inputBuffers(extraDatasCount + 1);
1464
1465 // The implicit result SSBO we use to store our outputs from the vertex shader
1466 {
1467 vk::VkDeviceSize size = getFormatSizeInBytes(format) * maxWidth;
1468 inputBuffers[0] = de::SharedPtr<BufferOrImage>(new Buffer(context, size));
1469 }
1470
1471 for (deUint32 i = 0; i < (inputBuffers.size() - 1); i++)
1472 {
1473 if (extraDatas[i].isImage)
1474 {
1475 inputBuffers[i + 1] = de::SharedPtr<BufferOrImage>(new Image(context,
1476 static_cast<deUint32>(extraDatas[i].numElements), 1, extraDatas[i].format));
1477 }
1478 else
1479 {
1480 vk::VkDeviceSize size =
1481 getFormatSizeInBytes(extraDatas[i].format) * extraDatas[i].numElements;
1482 inputBuffers[i + 1] = de::SharedPtr<BufferOrImage>(new Buffer(context, size));
1483 }
1484
1485 const Allocation& alloc = inputBuffers[i + 1]->getAllocation();
1486 initializeMemory(context, alloc, extraDatas[i]);
1487 }
1488
1489 DescriptorSetLayoutBuilder layoutBuilder;
1490
1491 for (deUint32 i = 0; i < inputBuffers.size(); i++)
1492 {
1493 layoutBuilder.addBinding(inputBuffers[i]->getType(), 1,
1494 VK_SHADER_STAGE_GEOMETRY_BIT, DE_NULL);
1495 }
1496
1497 const Unique<VkDescriptorSetLayout> descriptorSetLayout(
1498 layoutBuilder.build(context.getDeviceInterface(), context.getDevice()));
1499
1500 const Unique<VkPipelineLayout> pipelineLayout(
1501 makePipelineLayout(context, *descriptorSetLayout));
1502
1503 const Unique<VkRenderPass> renderPass(makeRenderPass(context, VK_FORMAT_R32_SFLOAT));
1504 const Unique<VkPipeline> pipeline(makeGraphicsPipeline(context, *pipelineLayout,
1505 VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_GEOMETRY_BIT,
1506 *vertexShaderModule, DE_NULL, *geometryShaderModule, DE_NULL, DE_NULL,
1507 *renderPass, VK_PRIMITIVE_TOPOLOGY_POINT_LIST));
1508
1509 DescriptorPoolBuilder poolBuilder;
1510
1511 for (deUint32 i = 0; i < inputBuffers.size(); i++)
1512 {
1513 poolBuilder.addType(inputBuffers[i]->getType());
1514 }
1515
1516 const Unique<VkDescriptorPool> descriptorPool(
1517 poolBuilder.build(context.getDeviceInterface(), context.getDevice(),
1518 VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
1519
1520 // Create descriptor set
1521 const Unique<VkDescriptorSet> descriptorSet(
1522 makeDescriptorSet(context, *descriptorPool, *descriptorSetLayout));
1523
1524 DescriptorSetUpdateBuilder updateBuilder;
1525
1526 for (deUint32 i = 0; i < inputBuffers.size(); i++)
1527 {
1528 if (inputBuffers[i]->isImage())
1529 {
1530 VkDescriptorImageInfo info =
1531 makeDescriptorImageInfo(inputBuffers[i]->getAsImage()->getSampler(),
1532 inputBuffers[i]->getAsImage()->getImageView(), VK_IMAGE_LAYOUT_GENERAL);
1533
1534 updateBuilder.writeSingle(*descriptorSet,
1535 DescriptorSetUpdateBuilder::Location::binding(i),
1536 inputBuffers[i]->getType(), &info);
1537 }
1538 else
1539 {
1540 VkDescriptorBufferInfo info =
1541 makeDescriptorBufferInfo(inputBuffers[i]->getAsBuffer()->getBuffer(),
1542 0ull, inputBuffers[i]->getAsBuffer()->getSize());
1543
1544 updateBuilder.writeSingle(*descriptorSet,
1545 DescriptorSetUpdateBuilder::Location::binding(i),
1546 inputBuffers[i]->getType(), &info);
1547 }
1548 }
1549
1550 updateBuilder.update(context.getDeviceInterface(), context.getDevice());
1551
1552 const Unique<VkCommandPool> cmdPool(makeCommandPool(context));
1553
1554 const deUint32 subgroupSize = getSubgroupSize(context);
1555
1556 const Unique<VkCommandBuffer> cmdBuffer(
1557 makeCommandBuffer(context, *cmdPool));
1558
1559 unsigned totalIterations = 0;
1560 unsigned failedIterations = 0;
1561
1562 Image discardableImage(context, 1, 1, VK_FORMAT_R32_SFLOAT,
1563 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
1564 VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
1565
1566 for (deUint32 width = 1; width < maxWidth; width++)
1567 {
1568 for (deUint32 i = 1; i < inputBuffers.size(); i++)
1569 {
1570 // re-init the data
1571 const Allocation& alloc = inputBuffers[i]->getAllocation();
1572 initializeMemory(context, alloc, extraDatas[i - 1]);
1573 }
1574
1575 totalIterations++;
1576
1577 const Unique<VkFramebuffer> framebuffer(makeFramebuffer(context,
1578 *renderPass, discardableImage.getImageView(), 1, 1));
1579
1580 const VkClearValue clearValue = {{{0.0f, 0.0f, 0.0f, 0.0f}}};
1581
1582 const VkRenderPassBeginInfo renderPassBeginInfo = {
1583 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, DE_NULL, *renderPass,
1584 *framebuffer, {{0, 0}, {1, 1}}, 1, &clearValue,
1585 };
1586
1587 beginCommandBuffer(context, *cmdBuffer);
1588
1589 VkViewport viewport = {0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f};
1590
1591 context.getDeviceInterface().cmdSetViewport(
1592 *cmdBuffer, 0, 1, &viewport);
1593
1594 VkRect2D scissor = {{0, 0}, {1, 1}};
1595
1596 context.getDeviceInterface().cmdSetScissor(
1597 *cmdBuffer, 0, 1, &scissor);
1598
1599 context.getDeviceInterface().cmdBeginRenderPass(
1600 *cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1601
1602 context.getDeviceInterface().cmdBindPipeline(
1603 *cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1604
1605 context.getDeviceInterface().cmdBindDescriptorSets(*cmdBuffer,
1606 VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u,
1607 &descriptorSet.get(), 0u, DE_NULL);
1608
1609 context.getDeviceInterface().cmdDraw(*cmdBuffer, width, 1, 0, 0);
1610
1611 context.getDeviceInterface().cmdEndRenderPass(*cmdBuffer);
1612
1613 endCommandBuffer(context, *cmdBuffer);
1614
1615 Move<VkFence> fence(submitCommandBuffer(context, *cmdBuffer));
1616
1617 waitFence(context, fence);
1618
1619 std::vector<const void*> datas;
1620
1621 for (deUint32 i = 0; i < inputBuffers.size(); i++)
1622 {
1623 if (!inputBuffers[i]->isImage())
1624 {
1625 const Allocation& resultAlloc = inputBuffers[i]->getAllocation();
1626 invalidateMappedMemoryRange(context.getDeviceInterface(),
1627 context.getDevice(), resultAlloc.getMemory(),
1628 resultAlloc.getOffset(), inputBuffers[i]->getAsBuffer()->getSize());
1629
1630 // we always have our result data first
1631 datas.push_back(resultAlloc.getHostPtr());
1632 }
1633 }
1634
1635 if (!checkResult(datas, width, subgroupSize))
1636 {
1637 failedIterations++;
1638 }
1639
1640 context.getDeviceInterface().resetCommandBuffer(*cmdBuffer, 0);
1641 }
1642
1643 if (0 < failedIterations)
1644 {
1645 context.getTestContext().getLog()
1646 << TestLog::Message << (totalIterations - failedIterations) << " / "
1647 << totalIterations << " values passed" << TestLog::EndMessage;
1648 return tcu::TestStatus::fail("Failed!");
1649 }
1650
1651 return tcu::TestStatus::pass("OK");
1652 }
1653
makeImageMemoryBarrier(const VkAccessFlags srcAccessMask,const VkAccessFlags dstAccessMask,const VkImageLayout oldLayout,const VkImageLayout newLayout,const VkImage image,const VkImageSubresourceRange subresourceRange)1654 VkImageMemoryBarrier makeImageMemoryBarrier (const VkAccessFlags srcAccessMask,
1655 const VkAccessFlags dstAccessMask,
1656 const VkImageLayout oldLayout,
1657 const VkImageLayout newLayout,
1658 const VkImage image,
1659 const VkImageSubresourceRange subresourceRange)
1660 {
1661 const VkImageMemoryBarrier barrier =
1662 {
1663 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1664 DE_NULL, // const void* pNext;
1665 srcAccessMask, // VkAccessFlags outputMask;
1666 dstAccessMask, // VkAccessFlags inputMask;
1667 oldLayout, // VkImageLayout oldLayout;
1668 newLayout, // VkImageLayout newLayout;
1669 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1670 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
1671 image, // VkImage image;
1672 subresourceRange, // VkImageSubresourceRange subresourceRange;
1673 };
1674 return barrier;
1675 }
1676
makeBufferMemoryBarrier(const VkAccessFlags srcAccessMask,const VkAccessFlags dstAccessMask,const VkBuffer buffer,const VkDeviceSize offset,const VkDeviceSize bufferSizeBytes)1677 VkBufferMemoryBarrier makeBufferMemoryBarrier (const VkAccessFlags srcAccessMask,
1678 const VkAccessFlags dstAccessMask,
1679 const VkBuffer buffer,
1680 const VkDeviceSize offset,
1681 const VkDeviceSize bufferSizeBytes)
1682 {
1683 const VkBufferMemoryBarrier barrier =
1684 {
1685 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
1686 DE_NULL, // const void* pNext;
1687 srcAccessMask, // VkAccessFlags srcAccessMask;
1688 dstAccessMask, // VkAccessFlags dstAccessMask;
1689 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1690 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
1691 buffer, // VkBuffer buffer;
1692 offset, // VkDeviceSize offset;
1693 bufferSizeBytes, // VkDeviceSize size;
1694 };
1695 return barrier;
1696 }
1697
makeVertexFrameBufferTest(Context & context,vk::VkFormat format,SSBOData * extraData,deUint32 extraDataCount,bool (* checkResult)(std::vector<const void * > datas,deUint32 width,deUint32 subgroupSize))1698 tcu::TestStatus vkt::subgroups::makeVertexFrameBufferTest(Context& context, vk::VkFormat format,
1699 SSBOData* extraData, deUint32 extraDataCount,
1700 bool (*checkResult)(std::vector<const void*> datas, deUint32 width, deUint32 subgroupSize))
1701 {
1702 const deUint32 maxWidth = 1024u;
1703 vector<de::SharedPtr<BufferOrImage> > inputBuffers (extraDataCount);
1704 DescriptorSetLayoutBuilder layoutBuilder;
1705 const Unique<VkShaderModule> vertexShaderModule (createShaderModule
1706 (context.getDeviceInterface(), context.getDevice(), context.getBinaryCollection().get("vert"), 0u));
1707 const Unique<VkShaderModule> fragmentShaderModule (createShaderModule
1708 (context.getDeviceInterface(), context.getDevice(), context.getBinaryCollection().get("fragment"), 0u));
1709 const Unique<VkRenderPass> renderPass (makeRenderPass(context, format));
1710
1711 const VkVertexInputBindingDescription vertexInputBinding =
1712 {
1713 0u, // binding;
1714 static_cast<deUint32>(sizeof(tcu::Vec4)), // stride;
1715 VK_VERTEX_INPUT_RATE_VERTEX // inputRate
1716 };
1717
1718 const VkVertexInputAttributeDescription vertexInputAttribute =
1719 {
1720 0u,
1721 0u,
1722 VK_FORMAT_R32G32B32A32_SFLOAT,
1723 0u
1724 };
1725
1726 for (deUint32 i = 0u; i < extraDataCount; i++)
1727 {
1728 if (extraData[i].isImage)
1729 {
1730 inputBuffers[i] = de::SharedPtr<BufferOrImage>(new Image(context, static_cast<deUint32>(extraData[i].numElements), 1u, extraData[i].format));
1731 }
1732 else
1733 {
1734 vk::VkDeviceSize size = getFormatSizeInBytes(extraData[i].format) * extraData[i].numElements;
1735 inputBuffers[i] = de::SharedPtr<BufferOrImage>(new Buffer(context, size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT));
1736 }
1737 const Allocation& alloc = inputBuffers[i]->getAllocation();
1738 initializeMemory(context, alloc, extraData[i]);
1739 }
1740
1741 for (deUint32 ndx = 0u; ndx < extraDataCount; ndx++)
1742 layoutBuilder.addBinding(inputBuffers[ndx]->getType(), 1u, VK_SHADER_STAGE_VERTEX_BIT, DE_NULL);
1743
1744 const Unique<VkDescriptorSetLayout> descriptorSetLayout (layoutBuilder.build(context.getDeviceInterface(), context.getDevice()));
1745
1746 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout(context, *descriptorSetLayout));
1747
1748 const Unique<VkPipeline> pipeline (makeGraphicsPipeline(context, *pipelineLayout,
1749 VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT,
1750 *vertexShaderModule, *fragmentShaderModule,
1751 DE_NULL, DE_NULL, DE_NULL,
1752 *renderPass, VK_PRIMITIVE_TOPOLOGY_POINT_LIST,
1753 &vertexInputBinding, &vertexInputAttribute, format));
1754 DescriptorPoolBuilder poolBuilder;
1755 DescriptorSetUpdateBuilder updateBuilder;
1756
1757
1758 for (deUint32 ndx = 0u; ndx < inputBuffers.size(); ndx++)
1759 poolBuilder.addType(inputBuffers[ndx]->getType());
1760
1761 Move <VkDescriptorPool> descriptorPool;
1762 Move <VkDescriptorSet> descriptorSet;
1763
1764 if (extraDataCount > 0)
1765 {
1766 descriptorPool = poolBuilder.build(context.getDeviceInterface(), context.getDevice(),
1767 VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1768 descriptorSet = makeDescriptorSet(context, *descriptorPool, *descriptorSetLayout);
1769 }
1770
1771 for (deUint32 ndx = 0u; ndx < extraDataCount; ndx++)
1772 {
1773 const Allocation& alloc = inputBuffers[ndx]->getAllocation();
1774 initializeMemory(context, alloc, extraData[ndx]);
1775 }
1776
1777 for (deUint32 buffersNdx = 0u; buffersNdx < inputBuffers.size(); buffersNdx++)
1778 {
1779 if (inputBuffers[buffersNdx]->isImage())
1780 {
1781 VkDescriptorImageInfo info =
1782 makeDescriptorImageInfo(inputBuffers[buffersNdx]->getAsImage()->getSampler(),
1783 inputBuffers[buffersNdx]->getAsImage()->getImageView(), VK_IMAGE_LAYOUT_GENERAL);
1784
1785 updateBuilder.writeSingle(*descriptorSet,
1786 DescriptorSetUpdateBuilder::Location::binding(buffersNdx),
1787 inputBuffers[buffersNdx]->getType(), &info);
1788 }
1789 else
1790 {
1791 VkDescriptorBufferInfo info =
1792 makeDescriptorBufferInfo(inputBuffers[buffersNdx]->getAsBuffer()->getBuffer(),
1793 0ull, inputBuffers[buffersNdx]->getAsBuffer()->getSize());
1794
1795 updateBuilder.writeSingle(*descriptorSet,
1796 DescriptorSetUpdateBuilder::Location::binding(buffersNdx),
1797 inputBuffers[buffersNdx]->getType(), &info);
1798 }
1799 }
1800 updateBuilder.update(context.getDeviceInterface(), context.getDevice());
1801
1802 const Unique<VkCommandPool> cmdPool (makeCommandPool(context));
1803
1804 const deUint32 subgroupSize = getSubgroupSize(context);
1805
1806 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(context, *cmdPool));
1807
1808 const vk::VkDeviceSize vertexBufferSize = maxWidth * sizeof(tcu::Vec4);
1809 Buffer vertexBuffer (context, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
1810
1811 unsigned totalIterations = 0u;
1812 unsigned failedIterations = 0u;
1813
1814 Image discardableImage (context, maxWidth, 1u, format, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
1815
1816 {
1817 const Allocation& alloc = vertexBuffer.getAllocation();
1818 std::vector<tcu::Vec4> data (maxWidth, Vec4(1.0f, 1.0f, 1.0f, 1.0f));
1819 const float pixelSize = 2.0f / static_cast<float>(maxWidth);
1820 float leftHandPosition = -1.0f;
1821
1822 for(deUint32 ndx = 0u; ndx < maxWidth; ++ndx)
1823 {
1824 data[ndx][0] = leftHandPosition + pixelSize / 2.0f;
1825 leftHandPosition += pixelSize;
1826 }
1827
1828 deMemcpy(alloc.getHostPtr(), &data[0], maxWidth * sizeof(tcu::Vec4));
1829 vk::flushMappedMemoryRange(context.getDeviceInterface(), context.getDevice(), alloc.getMemory(), alloc.getOffset(), vertexBufferSize);
1830 }
1831
1832 for (deUint32 width = 1u; width < maxWidth; width++)
1833 {
1834 totalIterations++;
1835 const Unique<VkFramebuffer> framebuffer (makeFramebuffer(context, *renderPass, discardableImage.getImageView(), maxWidth, 1));
1836 const VkClearValue clearValue = {{{0.0f, 0.0f, 0.0f, 0.0f}}};
1837 const VkViewport viewport = {0.0f, 0.0f, static_cast<float>(maxWidth), 1.0f, 0.0f, 1.0f};
1838 const VkRect2D scissor = {{0, 0}, {maxWidth, 1}};
1839 const vk::VkDeviceSize imageResultSize = tcu::getPixelSize(vk::mapVkFormat(format)) * maxWidth;
1840 Buffer imageBufferResult (context, imageResultSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1841 const VkDeviceSize vertexBufferOffset = 0u;
1842
1843 for (deUint32 ndx = 0u; ndx < inputBuffers.size(); ndx++)
1844 {
1845 const Allocation& alloc = inputBuffers[ndx]->getAllocation();
1846 initializeMemory(context, alloc, extraData[ndx]);
1847 }
1848
1849 const VkRenderPassBeginInfo renderPassBeginInfo =
1850 {
1851 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, DE_NULL, *renderPass,
1852 *framebuffer, {{0, 0}, {maxWidth, 1}}, 1, &clearValue,
1853 };
1854
1855 beginCommandBuffer(context, *cmdBuffer);
1856 {
1857 context.getDeviceInterface().cmdSetViewport(
1858 *cmdBuffer, 0, 1, &viewport);
1859
1860 context.getDeviceInterface().cmdSetScissor(
1861 *cmdBuffer, 0, 1, &scissor);
1862
1863 context.getDeviceInterface().cmdBeginRenderPass(
1864 *cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1865
1866 context.getDeviceInterface().cmdBindPipeline(
1867 *cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1868
1869 if (extraDataCount > 0)
1870 {
1871 context.getDeviceInterface().cmdBindDescriptorSets(*cmdBuffer,
1872 VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u,
1873 &descriptorSet.get(), 0u, DE_NULL);
1874 }
1875
1876 context.getDeviceInterface().cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, vertexBuffer.getBufferPtr(), &vertexBufferOffset);
1877
1878 context.getDeviceInterface().cmdDraw(*cmdBuffer, width, 1u, 0u, 0u);
1879
1880 context.getDeviceInterface().cmdEndRenderPass(*cmdBuffer);
1881
1882 const VkImageSubresourceRange subresourceRange =
1883 {
1884 VK_IMAGE_ASPECT_COLOR_BIT, //VkImageAspectFlags aspectMask
1885 0u, //deUint32 baseMipLevel
1886 1u, //deUint32 levelCount
1887 0u, //deUint32 baseArrayLayer
1888 1u //deUint32 layerCount
1889 };
1890
1891 const VkBufferImageCopy copyRegion =
1892 {
1893 0ull, // VkDeviceSize bufferOffset;
1894 0u, // deUint32 bufferRowLength;
1895 0u, // deUint32 bufferImageHeight;
1896 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u), // VkImageSubresourceLayers imageSubresource;
1897 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset;
1898 makeExtent3D(IVec3(maxWidth,1,1)), // VkExtent3D imageExtent;
1899 };
1900
1901 const VkImageMemoryBarrier prepareForTransferBarrier = makeImageMemoryBarrier(
1902 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
1903 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1904 discardableImage.getImage(), subresourceRange);
1905
1906 const VkBufferMemoryBarrier copyBarrier = makeBufferMemoryBarrier(
1907 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT,
1908 imageBufferResult.getBuffer(), 0ull, imageResultSize);
1909
1910 context.getDeviceInterface().cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0u, (const VkMemoryBarrier*)DE_NULL, 0u, (const VkBufferMemoryBarrier*)DE_NULL, 1u, &prepareForTransferBarrier);
1911 context.getDeviceInterface().cmdCopyImageToBuffer(*cmdBuffer, discardableImage.getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, imageBufferResult.getBuffer(), 1u, ©Region);
1912 context.getDeviceInterface().cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0u, (const VkMemoryBarrier*)DE_NULL, 1u, ©Barrier, 0u, (const VkImageMemoryBarrier*)DE_NULL);
1913
1914 endCommandBuffer(context, *cmdBuffer);
1915 Move<VkFence> fence(submitCommandBuffer(context, *cmdBuffer));
1916 waitFence(context, fence);
1917 }
1918
1919 {
1920 const Allocation& allocResult = imageBufferResult.getAllocation();
1921 invalidateMappedMemoryRange(context.getDeviceInterface(), context.getDevice(), allocResult.getMemory(), allocResult.getOffset(), imageResultSize);
1922
1923 std::vector<const void*> datas;
1924 datas.push_back(allocResult.getHostPtr());
1925 if (!checkResult(datas, width, subgroupSize))
1926 failedIterations++;
1927 }
1928 }
1929
1930 if (0 < failedIterations)
1931 {
1932 context.getTestContext().getLog()
1933 << TestLog::Message << (totalIterations - failedIterations) << " / "
1934 << totalIterations << " values passed" << TestLog::EndMessage;
1935 return tcu::TestStatus::fail("Failed!");
1936 }
1937
1938 return tcu::TestStatus::pass("OK");
1939 }
1940
makeVertexTest(Context & context,VkFormat format,SSBOData * extraDatas,deUint32 extraDatasCount,bool (* checkResult)(std::vector<const void * > datas,deUint32 width,deUint32 subgroupSize))1941 tcu::TestStatus vkt::subgroups::makeVertexTest(
1942 Context& context, VkFormat format, SSBOData* extraDatas,
1943 deUint32 extraDatasCount,
1944 bool (*checkResult)(std::vector<const void*> datas, deUint32 width, deUint32 subgroupSize))
1945 {
1946 const deUint32 maxWidth = 1024;
1947
1948 const Unique<VkShaderModule> vertexShaderModule(
1949 createShaderModule(context.getDeviceInterface(), context.getDevice(),
1950 context.getBinaryCollection().get("vert"), 0u));
1951
1952 std::vector< de::SharedPtr<BufferOrImage> > inputBuffers(extraDatasCount + 1);
1953
1954 // The implicit result SSBO we use to store our outputs from the vertex shader
1955 {
1956 vk::VkDeviceSize size = getFormatSizeInBytes(format) * maxWidth;
1957 inputBuffers[0] = de::SharedPtr<BufferOrImage>(new Buffer(context, size));
1958 }
1959
1960 for (deUint32 i = 0; i < (inputBuffers.size() - 1); i++)
1961 {
1962 if (extraDatas[i].isImage)
1963 {
1964 inputBuffers[i + 1] = de::SharedPtr<BufferOrImage>(new Image(context,
1965 static_cast<deUint32>(extraDatas[i].numElements), 1, extraDatas[i].format));
1966 }
1967 else
1968 {
1969 vk::VkDeviceSize size =
1970 getFormatSizeInBytes(extraDatas[i].format) * extraDatas[i].numElements;
1971 inputBuffers[i + 1] = de::SharedPtr<BufferOrImage>(new Buffer(context, size));
1972 }
1973
1974 const Allocation& alloc = inputBuffers[i + 1]->getAllocation();
1975 initializeMemory(context, alloc, extraDatas[i]);
1976 }
1977
1978 DescriptorSetLayoutBuilder layoutBuilder;
1979
1980 for (deUint32 i = 0; i < inputBuffers.size(); i++)
1981 {
1982 layoutBuilder.addBinding(inputBuffers[i]->getType(), 1,
1983 VK_SHADER_STAGE_VERTEX_BIT, DE_NULL);
1984 }
1985
1986 const Unique<VkDescriptorSetLayout> descriptorSetLayout(
1987 layoutBuilder.build(context.getDeviceInterface(), context.getDevice()));
1988
1989 const Unique<VkPipelineLayout> pipelineLayout(
1990 makePipelineLayout(context, *descriptorSetLayout));
1991
1992 const Unique<VkRenderPass> renderPass(makeRenderPass(context, VK_FORMAT_R32_SFLOAT));
1993 const Unique<VkPipeline> pipeline(makeGraphicsPipeline(context, *pipelineLayout,
1994 VK_SHADER_STAGE_VERTEX_BIT, *vertexShaderModule, DE_NULL, DE_NULL, DE_NULL, DE_NULL,
1995 *renderPass, VK_PRIMITIVE_TOPOLOGY_POINT_LIST));
1996
1997 DescriptorPoolBuilder poolBuilder;
1998
1999 for (deUint32 i = 0; i < inputBuffers.size(); i++)
2000 {
2001 poolBuilder.addType(inputBuffers[i]->getType());
2002 }
2003
2004 const Unique<VkDescriptorPool> descriptorPool(
2005 poolBuilder.build(context.getDeviceInterface(), context.getDevice(),
2006 VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
2007
2008 // Create descriptor set
2009 const Unique<VkDescriptorSet> descriptorSet(
2010 makeDescriptorSet(context, *descriptorPool, *descriptorSetLayout));
2011
2012 DescriptorSetUpdateBuilder updateBuilder;
2013
2014 for (deUint32 i = 0; i < inputBuffers.size(); i++)
2015 {
2016 if (inputBuffers[i]->isImage())
2017 {
2018 VkDescriptorImageInfo info =
2019 makeDescriptorImageInfo(inputBuffers[i]->getAsImage()->getSampler(),
2020 inputBuffers[i]->getAsImage()->getImageView(), VK_IMAGE_LAYOUT_GENERAL);
2021
2022 updateBuilder.writeSingle(*descriptorSet,
2023 DescriptorSetUpdateBuilder::Location::binding(i),
2024 inputBuffers[i]->getType(), &info);
2025 }
2026 else
2027 {
2028 VkDescriptorBufferInfo info =
2029 makeDescriptorBufferInfo(inputBuffers[i]->getAsBuffer()->getBuffer(),
2030 0ull, inputBuffers[i]->getAsBuffer()->getSize());
2031
2032 updateBuilder.writeSingle(*descriptorSet,
2033 DescriptorSetUpdateBuilder::Location::binding(i),
2034 inputBuffers[i]->getType(), &info);
2035 }
2036 }
2037
2038 updateBuilder.update(context.getDeviceInterface(), context.getDevice());
2039
2040 const Unique<VkCommandPool> cmdPool(makeCommandPool(context));
2041
2042 const deUint32 subgroupSize = getSubgroupSize(context);
2043
2044 const Unique<VkCommandBuffer> cmdBuffer(
2045 makeCommandBuffer(context, *cmdPool));
2046
2047 unsigned totalIterations = 0;
2048 unsigned failedIterations = 0;
2049
2050 Image discardableImage(context, 1, 1, VK_FORMAT_R32_SFLOAT,
2051 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
2052 VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
2053
2054 for (deUint32 width = 1; width < maxWidth; width++)
2055 {
2056 for (deUint32 i = 1; i < inputBuffers.size(); i++)
2057 {
2058 // re-init the data
2059 const Allocation& alloc = inputBuffers[i]->getAllocation();
2060 initializeMemory(context, alloc, extraDatas[i - 1]);
2061 }
2062
2063 totalIterations++;
2064
2065 const Unique<VkFramebuffer> framebuffer(makeFramebuffer(context,
2066 *renderPass, discardableImage.getImageView(), 1, 1));
2067
2068 const VkClearValue clearValue = {{{0.0f, 0.0f, 0.0f, 0.0f}}};
2069
2070 const VkRenderPassBeginInfo renderPassBeginInfo = {
2071 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, DE_NULL, *renderPass,
2072 *framebuffer, {{0, 0}, {1, 1}}, 1, &clearValue,
2073 };
2074
2075 beginCommandBuffer(context, *cmdBuffer);
2076
2077 VkViewport viewport = {0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f};
2078
2079 context.getDeviceInterface().cmdSetViewport(
2080 *cmdBuffer, 0, 1, &viewport);
2081
2082 VkRect2D scissor = {{0, 0}, {1, 1}};
2083
2084 context.getDeviceInterface().cmdSetScissor(
2085 *cmdBuffer, 0, 1, &scissor);
2086
2087 context.getDeviceInterface().cmdBeginRenderPass(
2088 *cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
2089
2090 context.getDeviceInterface().cmdBindPipeline(
2091 *cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
2092
2093 context.getDeviceInterface().cmdBindDescriptorSets(*cmdBuffer,
2094 VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u,
2095 &descriptorSet.get(), 0u, DE_NULL);
2096
2097 context.getDeviceInterface().cmdDraw(*cmdBuffer, width, 1, 0, 0);
2098
2099 context.getDeviceInterface().cmdEndRenderPass(*cmdBuffer);
2100
2101 endCommandBuffer(context, *cmdBuffer);
2102
2103 Move<VkFence> fence(submitCommandBuffer(context, *cmdBuffer));
2104
2105 waitFence(context, fence);
2106
2107 std::vector<const void*> datas;
2108
2109 for (deUint32 i = 0; i < inputBuffers.size(); i++)
2110 {
2111 if (!inputBuffers[i]->isImage())
2112 {
2113 const Allocation& resultAlloc = inputBuffers[i]->getAllocation();
2114 invalidateMappedMemoryRange(context.getDeviceInterface(),
2115 context.getDevice(), resultAlloc.getMemory(),
2116 resultAlloc.getOffset(), inputBuffers[i]->getAsBuffer()->getSize());
2117
2118 // we always have our result data first
2119 datas.push_back(resultAlloc.getHostPtr());
2120 }
2121 }
2122 if (!checkResult(datas, width, subgroupSize))
2123 {
2124 failedIterations++;
2125 }
2126
2127 context.getDeviceInterface().resetCommandBuffer(*cmdBuffer, 0);
2128 }
2129
2130 if (0 < failedIterations)
2131 {
2132 context.getTestContext().getLog()
2133 << TestLog::Message << (totalIterations - failedIterations) << " / "
2134 << totalIterations << " values passed" << TestLog::EndMessage;
2135 return tcu::TestStatus::fail("Failed!");
2136 }
2137
2138 return tcu::TestStatus::pass("OK");
2139 }
2140
makeFragmentFrameBufferTest(Context & context,VkFormat format,SSBOData * extraDatas,deUint32 extraDatasCount,bool (* checkResult)(std::vector<const void * > datas,deUint32 width,deUint32 height,deUint32 subgroupSize))2141 tcu::TestStatus vkt::subgroups::makeFragmentFrameBufferTest (Context& context, VkFormat format, SSBOData* extraDatas,
2142 deUint32 extraDatasCount,
2143 bool (*checkResult)(std::vector<const void*> datas, deUint32 width,
2144 deUint32 height, deUint32 subgroupSize))
2145 {
2146 const Unique<VkShaderModule> vertexShaderModule (createShaderModule
2147 (context.getDeviceInterface(), context.getDevice(), context.getBinaryCollection().get("vert"), 0u));
2148 const Unique<VkShaderModule> fragmentShaderModule (createShaderModule
2149 (context.getDeviceInterface(), context.getDevice(), context.getBinaryCollection().get("fragment"), 0u));
2150
2151 std::vector< de::SharedPtr<BufferOrImage> > inputBuffers(extraDatasCount);
2152
2153 for (deUint32 i = 0; i < extraDatasCount; i++)
2154 {
2155 if (extraDatas[i].isImage)
2156 {
2157 inputBuffers[i] = de::SharedPtr<BufferOrImage>(new Image(context,
2158 static_cast<deUint32>(extraDatas[i].numElements), 1, extraDatas[i].format));
2159 }
2160 else
2161 {
2162 vk::VkDeviceSize size =
2163 getFormatSizeInBytes(extraDatas[i].format) * extraDatas[i].numElements;
2164 inputBuffers[i] = de::SharedPtr<BufferOrImage>(new Buffer(context, size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT));
2165 }
2166
2167 const Allocation& alloc = inputBuffers[i]->getAllocation();
2168 initializeMemory(context, alloc, extraDatas[i]);
2169 }
2170
2171 DescriptorSetLayoutBuilder layoutBuilder;
2172
2173 for (deUint32 i = 0; i < extraDatasCount; i++)
2174 {
2175 layoutBuilder.addBinding(inputBuffers[i]->getType(), 1,
2176 VK_SHADER_STAGE_FRAGMENT_BIT, DE_NULL);
2177 }
2178
2179 const Unique<VkDescriptorSetLayout> descriptorSetLayout(
2180 layoutBuilder.build(context.getDeviceInterface(), context.getDevice()));
2181
2182 const Unique<VkPipelineLayout> pipelineLayout(
2183 makePipelineLayout(context, *descriptorSetLayout));
2184
2185 const Unique<VkRenderPass> renderPass(makeRenderPass(context, format));
2186 const Unique<VkPipeline> pipeline(makeGraphicsPipeline(context, *pipelineLayout,
2187 VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT,
2188 *vertexShaderModule, *fragmentShaderModule, DE_NULL, DE_NULL, DE_NULL, *renderPass));
2189
2190 DescriptorPoolBuilder poolBuilder;
2191
2192 // To stop validation complaining, always add at least one type to pool.
2193 poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
2194 for (deUint32 i = 0; i < extraDatasCount; i++)
2195 {
2196 poolBuilder.addType(inputBuffers[i]->getType());
2197 }
2198
2199 Move<VkDescriptorPool> descriptorPool;
2200 // Create descriptor set
2201 Move<VkDescriptorSet> descriptorSet;
2202
2203 if (extraDatasCount > 0)
2204 {
2205 descriptorPool = poolBuilder.build(context.getDeviceInterface(), context.getDevice(),
2206 VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
2207
2208 descriptorSet = makeDescriptorSet(context, *descriptorPool, *descriptorSetLayout);
2209 }
2210
2211 DescriptorSetUpdateBuilder updateBuilder;
2212
2213 for (deUint32 i = 0; i < extraDatasCount; i++)
2214 {
2215 if (inputBuffers[i]->isImage())
2216 {
2217 VkDescriptorImageInfo info =
2218 makeDescriptorImageInfo(inputBuffers[i]->getAsImage()->getSampler(),
2219 inputBuffers[i]->getAsImage()->getImageView(), VK_IMAGE_LAYOUT_GENERAL);
2220
2221 updateBuilder.writeSingle(*descriptorSet,
2222 DescriptorSetUpdateBuilder::Location::binding(i),
2223 inputBuffers[i]->getType(), &info);
2224 }
2225 else
2226 {
2227 VkDescriptorBufferInfo info =
2228 makeDescriptorBufferInfo(inputBuffers[i]->getAsBuffer()->getBuffer(),
2229 0ull, inputBuffers[i]->getAsBuffer()->getSize());
2230
2231 updateBuilder.writeSingle(*descriptorSet,
2232 DescriptorSetUpdateBuilder::Location::binding(i),
2233 inputBuffers[i]->getType(), &info);
2234 }
2235 }
2236
2237 if (extraDatasCount > 0)
2238 updateBuilder.update(context.getDeviceInterface(), context.getDevice());
2239
2240 const Unique<VkCommandPool> cmdPool(makeCommandPool(context));
2241
2242 const deUint32 subgroupSize = getSubgroupSize(context);
2243
2244 const Unique<VkCommandBuffer> cmdBuffer(
2245 makeCommandBuffer(context, *cmdPool));
2246
2247 unsigned totalIterations = 0;
2248 unsigned failedIterations = 0;
2249
2250 for (deUint32 width = 8; width <= subgroupSize; width *= 2)
2251 {
2252 for (deUint32 height = 8; height <= subgroupSize; height *= 2)
2253 {
2254 totalIterations++;
2255
2256 // re-init the data
2257 for (deUint32 i = 0; i < extraDatasCount; i++)
2258 {
2259 const Allocation& alloc = inputBuffers[i]->getAllocation();
2260 initializeMemory(context, alloc, extraDatas[i]);
2261 }
2262
2263 VkDeviceSize formatSize = getFormatSizeInBytes(format);
2264 const VkDeviceSize resultImageSizeInBytes =
2265 width * height * formatSize;
2266
2267 Image resultImage(context, width, height, format,
2268 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
2269 VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
2270
2271 Buffer resultBuffer(context, resultImageSizeInBytes,
2272 VK_IMAGE_USAGE_TRANSFER_DST_BIT);
2273
2274 const Unique<VkFramebuffer> framebuffer(makeFramebuffer(context,
2275 *renderPass, resultImage.getImageView(), width, height));
2276
2277 const VkClearValue clearValue = {{{0.0f, 0.0f, 0.0f, 0.0f}}};
2278
2279 const VkRenderPassBeginInfo renderPassBeginInfo = {
2280 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, DE_NULL, *renderPass,
2281 *framebuffer, {{0, 0}, {width, height}}, 1, &clearValue,
2282 };
2283
2284 beginCommandBuffer(context, *cmdBuffer);
2285
2286 VkViewport viewport = {0.0f, 0.0f, static_cast<float>(width),
2287 static_cast<float>(height), 0.0f, 1.0f
2288 };
2289
2290 context.getDeviceInterface().cmdSetViewport(
2291 *cmdBuffer, 0, 1, &viewport);
2292
2293 VkRect2D scissor = {{0, 0}, {width, height}};
2294
2295 context.getDeviceInterface().cmdSetScissor(
2296 *cmdBuffer, 0, 1, &scissor);
2297
2298 context.getDeviceInterface().cmdBeginRenderPass(
2299 *cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
2300
2301 context.getDeviceInterface().cmdBindPipeline(
2302 *cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
2303
2304 if (extraDatasCount > 0)
2305 {
2306 context.getDeviceInterface().cmdBindDescriptorSets(*cmdBuffer,
2307 VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u,
2308 &descriptorSet.get(), 0u, DE_NULL);
2309 }
2310
2311 context.getDeviceInterface().cmdDraw(*cmdBuffer, 3, 1, 0, 0);
2312
2313 context.getDeviceInterface().cmdEndRenderPass(*cmdBuffer);
2314
2315 vk::VkBufferImageCopy region = {0, 0, 0,
2316 {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}, {0, 0, 0},
2317 {width, height, 1}
2318 };
2319 context.getDeviceInterface().cmdCopyImageToBuffer(*cmdBuffer,
2320 resultImage.getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
2321 resultBuffer.getBuffer(), 1, ®ion);
2322
2323 endCommandBuffer(context, *cmdBuffer);
2324
2325 Move<VkFence> fence(submitCommandBuffer(context, *cmdBuffer));
2326
2327 waitFence(context, fence);
2328
2329 std::vector<const void*> datas;
2330 {
2331 const Allocation& resultAlloc = resultBuffer.getAllocation();
2332 invalidateMappedMemoryRange(context.getDeviceInterface(),
2333 context.getDevice(), resultAlloc.getMemory(),
2334 resultAlloc.getOffset(), resultImageSizeInBytes);
2335
2336 // we always have our result data first
2337 datas.push_back(resultAlloc.getHostPtr());
2338 }
2339
2340 if (!checkResult(datas, width, height, subgroupSize))
2341 {
2342 failedIterations++;
2343 }
2344
2345 context.getDeviceInterface().resetCommandBuffer(*cmdBuffer, 0);
2346 }
2347 }
2348
2349 if (0 < failedIterations)
2350 {
2351 context.getTestContext().getLog()
2352 << TestLog::Message << (totalIterations - failedIterations) << " / "
2353 << totalIterations << " values passed" << TestLog::EndMessage;
2354 return tcu::TestStatus::fail("Failed!");
2355 }
2356
2357 return tcu::TestStatus::pass("OK");
2358 }
2359
makeFragmentTest(Context & context,VkFormat format,SSBOData * extraDatas,deUint32 extraDatasCount,bool (* checkResult)(std::vector<const void * > datas,deUint32 width,deUint32 height,deUint32 subgroupSize))2360 tcu::TestStatus vkt::subgroups::makeFragmentTest(
2361 Context& context, VkFormat format, SSBOData* extraDatas,
2362 deUint32 extraDatasCount,
2363 bool (*checkResult)(std::vector<const void*> datas, deUint32 width,
2364 deUint32 height, deUint32 subgroupSize))
2365 {
2366 const Unique<VkShaderModule> vertexShaderModule(
2367 createShaderModule(context.getDeviceInterface(), context.getDevice(),
2368 context.getBinaryCollection().get("vert"), 0u));
2369 const Unique<VkShaderModule> fragmentShaderModule(
2370 createShaderModule(context.getDeviceInterface(), context.getDevice(),
2371 context.getBinaryCollection().get("frag"), 0u));
2372
2373 std::vector< de::SharedPtr<BufferOrImage> > inputBuffers(extraDatasCount);
2374
2375 for (deUint32 i = 0; i < extraDatasCount; i++)
2376 {
2377 if (extraDatas[i].isImage)
2378 {
2379 inputBuffers[i] = de::SharedPtr<BufferOrImage>(new Image(context,
2380 static_cast<deUint32>(extraDatas[i].numElements), 1, extraDatas[i].format));
2381 }
2382 else
2383 {
2384 vk::VkDeviceSize size =
2385 getFormatSizeInBytes(extraDatas[i].format) * extraDatas[i].numElements;
2386 inputBuffers[i] = de::SharedPtr<BufferOrImage>(new Buffer(context, size));
2387 }
2388
2389 const Allocation& alloc = inputBuffers[i]->getAllocation();
2390 initializeMemory(context, alloc, extraDatas[i]);
2391 }
2392
2393 DescriptorSetLayoutBuilder layoutBuilder;
2394
2395 for (deUint32 i = 0; i < extraDatasCount; i++)
2396 {
2397 layoutBuilder.addBinding(inputBuffers[i]->getType(), 1,
2398 VK_SHADER_STAGE_FRAGMENT_BIT, DE_NULL);
2399 }
2400
2401 const Unique<VkDescriptorSetLayout> descriptorSetLayout(
2402 layoutBuilder.build(context.getDeviceInterface(), context.getDevice()));
2403
2404 const Unique<VkPipelineLayout> pipelineLayout(
2405 makePipelineLayout(context, *descriptorSetLayout));
2406
2407 const Unique<VkRenderPass> renderPass(makeRenderPass(context, format));
2408 const Unique<VkPipeline> pipeline(makeGraphicsPipeline(context, *pipelineLayout,
2409 VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT,
2410 *vertexShaderModule, *fragmentShaderModule, DE_NULL, DE_NULL, DE_NULL, *renderPass));
2411
2412 DescriptorPoolBuilder poolBuilder;
2413
2414 // To stop validation complaining, always add at least one type to pool.
2415 poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
2416 for (deUint32 i = 0; i < extraDatasCount; i++)
2417 {
2418 poolBuilder.addType(inputBuffers[i]->getType());
2419 }
2420
2421 const Unique<VkDescriptorPool> descriptorPool(
2422 poolBuilder.build(context.getDeviceInterface(), context.getDevice(),
2423 VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
2424
2425 // Create descriptor set
2426 const Unique<VkDescriptorSet> descriptorSet(
2427 makeDescriptorSet(context, *descriptorPool, *descriptorSetLayout));
2428
2429 DescriptorSetUpdateBuilder updateBuilder;
2430
2431 for (deUint32 i = 0; i < extraDatasCount; i++)
2432 {
2433 if (inputBuffers[i]->isImage())
2434 {
2435 VkDescriptorImageInfo info =
2436 makeDescriptorImageInfo(inputBuffers[i]->getAsImage()->getSampler(),
2437 inputBuffers[i]->getAsImage()->getImageView(), VK_IMAGE_LAYOUT_GENERAL);
2438
2439 updateBuilder.writeSingle(*descriptorSet,
2440 DescriptorSetUpdateBuilder::Location::binding(i),
2441 inputBuffers[i]->getType(), &info);
2442 }
2443 else
2444 {
2445 VkDescriptorBufferInfo info =
2446 makeDescriptorBufferInfo(inputBuffers[i]->getAsBuffer()->getBuffer(),
2447 0ull, inputBuffers[i]->getAsBuffer()->getSize());
2448
2449 updateBuilder.writeSingle(*descriptorSet,
2450 DescriptorSetUpdateBuilder::Location::binding(i),
2451 inputBuffers[i]->getType(), &info);
2452 }
2453 }
2454
2455 updateBuilder.update(context.getDeviceInterface(), context.getDevice());
2456
2457 const Unique<VkCommandPool> cmdPool(makeCommandPool(context));
2458
2459 const deUint32 subgroupSize = getSubgroupSize(context);
2460
2461 const Unique<VkCommandBuffer> cmdBuffer(
2462 makeCommandBuffer(context, *cmdPool));
2463
2464 unsigned totalIterations = 0;
2465 unsigned failedIterations = 0;
2466
2467 for (deUint32 width = 8; width <= subgroupSize; width *= 2)
2468 {
2469 for (deUint32 height = 8; height <= subgroupSize; height *= 2)
2470 {
2471 totalIterations++;
2472
2473 // re-init the data
2474 for (deUint32 i = 0; i < extraDatasCount; i++)
2475 {
2476 const Allocation& alloc = inputBuffers[i]->getAllocation();
2477 initializeMemory(context, alloc, extraDatas[i]);
2478 }
2479
2480 VkDeviceSize formatSize = getFormatSizeInBytes(format);
2481 const VkDeviceSize resultImageSizeInBytes =
2482 width * height * formatSize;
2483
2484 Image resultImage(context, width, height, format,
2485 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
2486 VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
2487
2488 Buffer resultBuffer(context, resultImageSizeInBytes,
2489 VK_IMAGE_USAGE_TRANSFER_DST_BIT);
2490
2491 const Unique<VkFramebuffer> framebuffer(makeFramebuffer(context,
2492 *renderPass, resultImage.getImageView(), width, height));
2493
2494 const VkClearValue clearValue = {{{0.0f, 0.0f, 0.0f, 0.0f}}};
2495
2496 const VkRenderPassBeginInfo renderPassBeginInfo = {
2497 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, DE_NULL, *renderPass,
2498 *framebuffer, {{0, 0}, {width, height}}, 1, &clearValue,
2499 };
2500
2501 beginCommandBuffer(context, *cmdBuffer);
2502
2503 VkViewport viewport = {0.0f, 0.0f, static_cast<float>(width),
2504 static_cast<float>(height), 0.0f, 1.0f
2505 };
2506
2507 context.getDeviceInterface().cmdSetViewport(
2508 *cmdBuffer, 0, 1, &viewport);
2509
2510 VkRect2D scissor = {{0, 0}, {width, height}};
2511
2512 context.getDeviceInterface().cmdSetScissor(
2513 *cmdBuffer, 0, 1, &scissor);
2514
2515 context.getDeviceInterface().cmdBeginRenderPass(
2516 *cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
2517
2518 context.getDeviceInterface().cmdBindPipeline(
2519 *cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
2520
2521 context.getDeviceInterface().cmdBindDescriptorSets(*cmdBuffer,
2522 VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u,
2523 &descriptorSet.get(), 0u, DE_NULL);
2524
2525 context.getDeviceInterface().cmdDraw(*cmdBuffer, 3, 1, 0, 0);
2526
2527 context.getDeviceInterface().cmdEndRenderPass(*cmdBuffer);
2528
2529 vk::VkBufferImageCopy region = {0, 0, 0,
2530 {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}, {0, 0, 0},
2531 {width, height, 1}};
2532
2533 const vk::VkImageSubresourceRange subresourceRange = {
2534 VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u};
2535
2536 const VkImageMemoryBarrier prepareForTransferBarrier = makeImageMemoryBarrier(
2537 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
2538 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
2539 resultImage.getImage(), subresourceRange);
2540
2541 context.getDeviceInterface().cmdPipelineBarrier(*cmdBuffer,
2542 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
2543 (VkDependencyFlags)0, 0u, (const VkMemoryBarrier*)DE_NULL, 0u,
2544 (const VkBufferMemoryBarrier*)DE_NULL, 1u, &prepareForTransferBarrier);
2545
2546 context.getDeviceInterface().cmdCopyImageToBuffer(*cmdBuffer,
2547 resultImage.getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
2548 resultBuffer.getBuffer(), 1, ®ion);
2549
2550 endCommandBuffer(context, *cmdBuffer);
2551
2552 Move<VkFence> fence(submitCommandBuffer(context, *cmdBuffer));
2553
2554 waitFence(context, fence);
2555
2556 std::vector<const void*> datas;
2557 {
2558 const Allocation& resultAlloc = resultBuffer.getAllocation();
2559 invalidateMappedMemoryRange(context.getDeviceInterface(),
2560 context.getDevice(), resultAlloc.getMemory(),
2561 resultAlloc.getOffset(), resultImageSizeInBytes);
2562
2563 // we always have our result data first
2564 datas.push_back(resultAlloc.getHostPtr());
2565 }
2566
2567 for (deUint32 i = 0; i < extraDatasCount; i++)
2568 {
2569 if (!inputBuffers[i]->isImage())
2570 {
2571 const Allocation& resultAlloc = inputBuffers[i]->getAllocation();
2572 invalidateMappedMemoryRange(context.getDeviceInterface(),
2573 context.getDevice(), resultAlloc.getMemory(),
2574 resultAlloc.getOffset(), inputBuffers[i]->getAsBuffer()->getSize());
2575
2576 // we always have our result data first
2577 datas.push_back(resultAlloc.getHostPtr());
2578 }
2579 }
2580
2581 if (!checkResult(datas, width, height, subgroupSize))
2582 {
2583 failedIterations++;
2584 }
2585
2586 context.getDeviceInterface().resetCommandBuffer(*cmdBuffer, 0);
2587 }
2588 }
2589
2590 if (0 < failedIterations)
2591 {
2592 context.getTestContext().getLog()
2593 << TestLog::Message << (totalIterations - failedIterations) << " / "
2594 << totalIterations << " values passed" << TestLog::EndMessage;
2595 return tcu::TestStatus::fail("Failed!");
2596 }
2597
2598 return tcu::TestStatus::pass("OK");
2599 }
2600
makeComputeTest(Context & context,VkFormat format,SSBOData * inputs,deUint32 inputsCount,bool (* checkResult)(std::vector<const void * > datas,const deUint32 numWorkgroups[3],const deUint32 localSize[3],deUint32 subgroupSize))2601 tcu::TestStatus vkt::subgroups::makeComputeTest(
2602 Context& context, VkFormat format, SSBOData* inputs, deUint32 inputsCount,
2603 bool (*checkResult)(std::vector<const void*> datas,
2604 const deUint32 numWorkgroups[3], const deUint32 localSize[3],
2605 deUint32 subgroupSize))
2606 {
2607 VkDeviceSize elementSize = getFormatSizeInBytes(format);
2608
2609 const VkDeviceSize resultBufferSize = maxSupportedSubgroupSize() *
2610 maxSupportedSubgroupSize() *
2611 maxSupportedSubgroupSize();
2612 const VkDeviceSize resultBufferSizeInBytes = resultBufferSize * elementSize;
2613
2614 Buffer resultBuffer(
2615 context, resultBufferSizeInBytes);
2616
2617 std::vector< de::SharedPtr<BufferOrImage> > inputBuffers(inputsCount);
2618
2619 for (deUint32 i = 0; i < inputsCount; i++)
2620 {
2621 if (inputs[i].isImage)
2622 {
2623 inputBuffers[i] = de::SharedPtr<BufferOrImage>(new Image(context,
2624 static_cast<deUint32>(inputs[i].numElements), 1, inputs[i].format));
2625 }
2626 else
2627 {
2628 vk::VkDeviceSize size =
2629 getFormatSizeInBytes(inputs[i].format) * inputs[i].numElements;
2630 inputBuffers[i] = de::SharedPtr<BufferOrImage>(new Buffer(context, size));
2631 }
2632
2633 const Allocation& alloc = inputBuffers[i]->getAllocation();
2634 initializeMemory(context, alloc, inputs[i]);
2635 }
2636
2637 DescriptorSetLayoutBuilder layoutBuilder;
2638 layoutBuilder.addBinding(
2639 resultBuffer.getType(), 1, VK_SHADER_STAGE_COMPUTE_BIT, DE_NULL);
2640
2641 for (deUint32 i = 0; i < inputsCount; i++)
2642 {
2643 layoutBuilder.addBinding(
2644 inputBuffers[i]->getType(), 1, VK_SHADER_STAGE_COMPUTE_BIT, DE_NULL);
2645 }
2646
2647 const Unique<VkDescriptorSetLayout> descriptorSetLayout(
2648 layoutBuilder.build(context.getDeviceInterface(), context.getDevice()));
2649
2650 const Unique<VkShaderModule> shaderModule(
2651 createShaderModule(context.getDeviceInterface(), context.getDevice(),
2652 context.getBinaryCollection().get("comp"), 0u));
2653 const Unique<VkPipelineLayout> pipelineLayout(
2654 makePipelineLayout(context, *descriptorSetLayout));
2655
2656 DescriptorPoolBuilder poolBuilder;
2657
2658 poolBuilder.addType(resultBuffer.getType());
2659
2660 for (deUint32 i = 0; i < inputsCount; i++)
2661 {
2662 poolBuilder.addType(inputBuffers[i]->getType());
2663 }
2664
2665 const Unique<VkDescriptorPool> descriptorPool(
2666 poolBuilder.build(context.getDeviceInterface(), context.getDevice(),
2667 VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
2668
2669 // Create descriptor set
2670 const Unique<VkDescriptorSet> descriptorSet(
2671 makeDescriptorSet(context, *descriptorPool, *descriptorSetLayout));
2672
2673 DescriptorSetUpdateBuilder updateBuilder;
2674
2675 const VkDescriptorBufferInfo resultDescriptorInfo =
2676 makeDescriptorBufferInfo(
2677 resultBuffer.getBuffer(), 0ull, resultBufferSizeInBytes);
2678
2679 updateBuilder.writeSingle(*descriptorSet,
2680 DescriptorSetUpdateBuilder::Location::binding(0u),
2681 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultDescriptorInfo);
2682
2683 for (deUint32 i = 0; i < inputsCount; i++)
2684 {
2685 if (inputBuffers[i]->isImage())
2686 {
2687 VkDescriptorImageInfo info =
2688 makeDescriptorImageInfo(inputBuffers[i]->getAsImage()->getSampler(),
2689 inputBuffers[i]->getAsImage()->getImageView(), VK_IMAGE_LAYOUT_GENERAL);
2690
2691 updateBuilder.writeSingle(*descriptorSet,
2692 DescriptorSetUpdateBuilder::Location::binding(i + 1),
2693 inputBuffers[i]->getType(), &info);
2694 }
2695 else
2696 {
2697 vk::VkDeviceSize size =
2698 getFormatSizeInBytes(inputs[i].format) * inputs[i].numElements;
2699 VkDescriptorBufferInfo info =
2700 makeDescriptorBufferInfo(inputBuffers[i]->getAsBuffer()->getBuffer(), 0ull, size);
2701
2702 updateBuilder.writeSingle(*descriptorSet,
2703 DescriptorSetUpdateBuilder::Location::binding(i + 1),
2704 inputBuffers[i]->getType(), &info);
2705 }
2706 }
2707
2708 updateBuilder.update(context.getDeviceInterface(), context.getDevice());
2709
2710 const Unique<VkCommandPool> cmdPool(makeCommandPool(context));
2711
2712 unsigned totalIterations = 0;
2713 unsigned failedIterations = 0;
2714
2715 const deUint32 subgroupSize = getSubgroupSize(context);
2716
2717 const Unique<VkCommandBuffer> cmdBuffer(
2718 makeCommandBuffer(context, *cmdPool));
2719
2720 const deUint32 numWorkgroups[3] = {4, 2, 2};
2721
2722 const deUint32 localSizesToTestCount = 15;
2723 deUint32 localSizesToTest[localSizesToTestCount][3] =
2724 {
2725 {1, 1, 1},
2726 {32, 4, 1},
2727 {32, 1, 4},
2728 {1, 32, 4},
2729 {1, 4, 32},
2730 {4, 1, 32},
2731 {4, 32, 1},
2732 {subgroupSize, 1, 1},
2733 {1, subgroupSize, 1},
2734 {1, 1, subgroupSize},
2735 {3, 5, 7},
2736 {128, 1, 1},
2737 {1, 128, 1},
2738 {1, 1, 64},
2739 {1, 1, 1} // Isn't used, just here to make double buffering checks easier
2740 };
2741
2742 Move<VkPipeline> lastPipeline(
2743 makeComputePipeline(context, *pipelineLayout, *shaderModule,
2744 localSizesToTest[0][0], localSizesToTest[0][1], localSizesToTest[0][2]));
2745
2746 for (deUint32 index = 0; index < (localSizesToTestCount - 1); index++)
2747 {
2748 const deUint32 nextX = localSizesToTest[index + 1][0];
2749 const deUint32 nextY = localSizesToTest[index + 1][1];
2750 const deUint32 nextZ = localSizesToTest[index + 1][2];
2751
2752 // we are running one test
2753 totalIterations++;
2754
2755 beginCommandBuffer(context, *cmdBuffer);
2756
2757 context.getDeviceInterface().cmdBindPipeline(
2758 *cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *lastPipeline);
2759
2760 context.getDeviceInterface().cmdBindDescriptorSets(*cmdBuffer,
2761 VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u,
2762 &descriptorSet.get(), 0u, DE_NULL);
2763
2764 context.getDeviceInterface().cmdDispatch(*cmdBuffer,
2765 numWorkgroups[0], numWorkgroups[1], numWorkgroups[2]);
2766
2767 endCommandBuffer(context, *cmdBuffer);
2768
2769 Move<VkFence> fence(submitCommandBuffer(context, *cmdBuffer));
2770
2771 Move<VkPipeline> nextPipeline(
2772 makeComputePipeline(context, *pipelineLayout, *shaderModule,
2773 nextX, nextY, nextZ));
2774
2775 waitFence(context, fence);
2776
2777 std::vector<const void*> datas;
2778
2779 {
2780 const Allocation& resultAlloc = resultBuffer.getAllocation();
2781 invalidateMappedMemoryRange(context.getDeviceInterface(),
2782 context.getDevice(), resultAlloc.getMemory(),
2783 resultAlloc.getOffset(), resultBufferSizeInBytes);
2784
2785 // we always have our result data first
2786 datas.push_back(resultAlloc.getHostPtr());
2787 }
2788
2789 for (deUint32 i = 0; i < inputsCount; i++)
2790 {
2791 if (!inputBuffers[i]->isImage())
2792 {
2793 vk::VkDeviceSize size =
2794 getFormatSizeInBytes(inputs[i].format) *
2795 inputs[i].numElements;
2796 const Allocation& resultAlloc = inputBuffers[i]->getAllocation();
2797 invalidateMappedMemoryRange(context.getDeviceInterface(),
2798 context.getDevice(), resultAlloc.getMemory(),
2799 resultAlloc.getOffset(), size);
2800
2801 // we always have our result data first
2802 datas.push_back(resultAlloc.getHostPtr());
2803 }
2804 }
2805
2806 if (!checkResult(datas, numWorkgroups, localSizesToTest[index], subgroupSize))
2807 {
2808 failedIterations++;
2809 }
2810
2811 context.getDeviceInterface().resetCommandBuffer(*cmdBuffer, 0);
2812
2813 lastPipeline = nextPipeline;
2814 }
2815
2816 if (0 < failedIterations)
2817 {
2818 context.getTestContext().getLog()
2819 << TestLog::Message << (totalIterations - failedIterations) << " / "
2820 << totalIterations << " values passed" << TestLog::EndMessage;
2821 return tcu::TestStatus::fail("Failed!");
2822 }
2823
2824 return tcu::TestStatus::pass("OK");
2825 }
2826