Refactor: Compatible compute and graphics VerifyIO
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / spirv_assembly / vktSpvAsmComputeShaderCase.cpp
1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 Google Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Test Case Skeleton Based on Compute Shaders
22  *//*--------------------------------------------------------------------*/
23
24 #include "vktSpvAsmComputeShaderCase.hpp"
25
26 #include "deSharedPtr.hpp"
27 #include "deSTLUtil.hpp"
28
29 #include "vktSpvAsmUtils.hpp"
30
31 #include "vkBuilderUtil.hpp"
32 #include "vkMemUtil.hpp"
33 #include "vkPlatform.hpp"
34 #include "vkRefUtil.hpp"
35 #include "vkQueryUtil.hpp"
36 #include "vkTypeUtil.hpp"
37 #include "vkCmdUtil.hpp"
38 #include "vkImageUtil.hpp"
39
40 namespace
41 {
42
43 using namespace vk;
44 using std::vector;
45
46 typedef vkt::SpirVAssembly::AllocationMp                        AllocationMp;
47 typedef vkt::SpirVAssembly::AllocationSp                        AllocationSp;
48 typedef vk::Unique<VkBuffer>                                            BufferHandleUp;
49 typedef vk::Unique<VkImage>                                                     ImageHandleUp;
50 typedef vk::Unique<VkImageView>                                         ImageViewHandleUp;
51 typedef vk::Unique<VkSampler>                                           SamplerHandleUp;
52 typedef de::SharedPtr<BufferHandleUp>                           BufferHandleSp;
53 typedef de::SharedPtr<ImageHandleUp>                            ImageHandleSp;
54 typedef de::SharedPtr<ImageViewHandleUp>                        ImageViewHandleSp;
55 typedef de::SharedPtr<SamplerHandleUp>                          SamplerHandleSp;
56
57 /*--------------------------------------------------------------------*//*!
58  * \brief Create a buffer, allocate and bind memory for the buffer
59  *
60  * The memory is created as host visible and passed back as a vk::Allocation
61  * instance via outMemory.
62  *//*--------------------------------------------------------------------*/
63 Move<VkBuffer> createBufferAndBindMemory (const DeviceInterface&        vkdi,
64                                                                                   const VkDevice&                       device,
65                                                                                   VkDescriptorType                      dtype,
66                                                                                   Allocator&                            allocator,
67                                                                                   size_t                                        numBytes,
68                                                                                   AllocationMp*                         outMemory,
69                                                                                   bool                                          coherent = false)
70 {
71         VkBufferUsageFlags                      usageBit                        = (VkBufferUsageFlags)0;
72
73         switch (dtype)
74         {
75                 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:                 usageBit = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;  break;
76                 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:                 usageBit = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;  break;
77                 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:                  usageBit = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;    break;
78                 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:                  usageBit = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;    break;
79                 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: usageBit = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;    break;
80                 default:                                                                                DE_FATAL("Not implemented");
81         }
82
83         const VkBufferCreateInfo        bufferCreateInfo        =
84         {
85                 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,   // sType
86                 DE_NULL,                                                                // pNext
87                 0u,                                                                             // flags
88                 numBytes,                                                               // size
89                 usageBit,                                                               // usage
90                 VK_SHARING_MODE_EXCLUSIVE,                              // sharingMode
91                 0u,                                                                             // queueFamilyCount
92                 DE_NULL,                                                                // pQueueFamilyIndices
93         };
94
95         Move<VkBuffer>                          buffer                  (createBuffer(vkdi, device, &bufferCreateInfo));
96         const VkMemoryRequirements      requirements    = getBufferMemoryRequirements(vkdi, device, *buffer);
97         AllocationMp                            bufferMemory    = allocator.allocate(requirements, coherent ? MemoryRequirement::Coherent | MemoryRequirement::HostVisible : MemoryRequirement::HostVisible);
98
99         VK_CHECK(vkdi.bindBufferMemory(device, *buffer, bufferMemory->getMemory(), bufferMemory->getOffset()));
100         *outMemory = bufferMemory;
101
102         return buffer;
103 }
104
105 /*--------------------------------------------------------------------*//*!
106  * \brief Create image, allocate and bind memory for the image
107  *
108  *//*--------------------------------------------------------------------*/
109 Move<VkImage> createImageAndBindMemory (const DeviceInterface& vkdi, const VkDevice& device, VkDescriptorType dtype, Allocator& allocator, deUint32 queueFamilyIndex, AllocationMp* outMemory)
110 {
111         VkImageUsageFlags                       usageBits                       = (VkImageUsageFlags)0;
112
113         switch (dtype)
114         {
115                 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:                  usageBits = VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;       break;
116                 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:                  usageBits = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;       break;
117                 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: usageBits = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;       break;
118                 default:                                                                                DE_FATAL("Not implemented");
119         }
120
121         const VkImageCreateInfo         resourceImageParams     =
122         {
123                 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                                                                    //      VkStructureType         sType;
124                 DE_NULL,                                                                                                                                //      const void*                     pNext;
125                 0u,                                                                                                                                             //      VkImageCreateFlags      flags;
126                 VK_IMAGE_TYPE_2D,                                                                                                               //      VkImageType                     imageType;
127                 VK_FORMAT_R32G32B32A32_SFLOAT,                                                                                  //      VkFormat                        format;
128                 { 8, 8, 1 },                                                                                                                    //  VkExtent3D                  extent;
129                 1u,                                                                                                                                             //      deUint32                        mipLevels;
130                 1u,                                                                                                                                             //      deUint32                        arraySize;
131                 VK_SAMPLE_COUNT_1_BIT,                                                                                                  //      deUint32                        samples;
132                 VK_IMAGE_TILING_OPTIMAL,                                                                                                //      VkImageTiling           tiling;
133                 usageBits,                                                                                                                              //  VkImageUsageFlags   usage;
134                 VK_SHARING_MODE_EXCLUSIVE,                                                                                              //      VkSharingMode           sharingMode;
135                 1u,                                                                                                                                             //      deUint32                        queueFamilyCount;
136                 &queueFamilyIndex,                                                                                                              //      const deUint32*         pQueueFamilyIndices;
137                 VK_IMAGE_LAYOUT_UNDEFINED,                                                                                              //      VkImageLayout           initialLayout;
138         };
139
140         // Create image
141         Move<VkImage>                           image                           = createImage(vkdi, device, &resourceImageParams);
142         const VkMemoryRequirements      requirements            = getImageMemoryRequirements(vkdi, device, *image);
143         de::MovePtr<Allocation>         imageMemory                     = allocator.allocate(requirements, MemoryRequirement::Any);
144
145         VK_CHECK(vkdi.bindImageMemory(device, *image, imageMemory->getMemory(), imageMemory->getOffset()));
146         *outMemory = imageMemory;
147
148         return image;
149 }
150
151 void setMemory (const DeviceInterface& vkdi, const VkDevice& device, Allocation* destAlloc, size_t numBytes, const void* data, bool coherent = false)
152 {
153         void* const hostPtr = destAlloc->getHostPtr();
154
155         deMemcpy((deUint8*)hostPtr, data, numBytes);
156
157         if (!coherent)
158                 flushMappedMemoryRange(vkdi, device, destAlloc->getMemory(), destAlloc->getOffset(), numBytes);
159 }
160
161 void fillMemoryWithValue (const DeviceInterface& vkdi, const VkDevice& device, Allocation* destAlloc, size_t numBytes, deUint8 value, bool coherent = false)
162 {
163         void* const hostPtr = destAlloc->getHostPtr();
164
165         deMemset((deUint8*)hostPtr, value, numBytes);
166
167         if (!coherent)
168                 flushMappedMemoryRange(vkdi, device, destAlloc->getMemory(), destAlloc->getOffset(), numBytes);
169 }
170
171 void invalidateMemory (const DeviceInterface& vkdi, const VkDevice& device, Allocation* srcAlloc, size_t numBytes, bool coherent = false)
172 {
173         if (!coherent)
174                 invalidateMappedMemoryRange(vkdi, device, srcAlloc->getMemory(), srcAlloc->getOffset(), numBytes);
175 }
176
177 /*--------------------------------------------------------------------*//*!
178  * \brief Create a descriptor set layout with the given descriptor types
179  *
180  * All descriptors are created for compute pipeline.
181  *//*--------------------------------------------------------------------*/
182 Move<VkDescriptorSetLayout> createDescriptorSetLayout (const DeviceInterface& vkdi, const VkDevice& device, const vector<VkDescriptorType>& dtypes)
183 {
184         DescriptorSetLayoutBuilder builder;
185
186         for (size_t bindingNdx = 0; bindingNdx < dtypes.size(); ++bindingNdx)
187                 builder.addSingleBinding(dtypes[bindingNdx], VK_SHADER_STAGE_COMPUTE_BIT);
188
189         return builder.build(vkdi, device);
190 }
191
192 /*--------------------------------------------------------------------*//*!
193  * \brief Create a pipeline layout with one descriptor set
194  *//*--------------------------------------------------------------------*/
195 Move<VkPipelineLayout> createPipelineLayout (const DeviceInterface& vkdi, const VkDevice& device, VkDescriptorSetLayout descriptorSetLayout, const vkt::SpirVAssembly::BufferSp& pushConstants)
196 {
197         VkPipelineLayoutCreateInfo              createInfo      =
198         {
199                 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,  // sType
200                 DE_NULL,                                                                                // pNext
201                 (VkPipelineLayoutCreateFlags)0,
202                 1u,                                                                                             // descriptorSetCount
203                 &descriptorSetLayout,                                                   // pSetLayouts
204                 0u,                                                                                             // pushConstantRangeCount
205                 DE_NULL,                                                                                // pPushConstantRanges
206         };
207
208         VkPushConstantRange                             range           =
209         {
210                 VK_SHADER_STAGE_COMPUTE_BIT,                                    // stageFlags
211                 0,                                                                                              // offset
212                 0,                                                                                              // size
213         };
214
215         if (pushConstants != DE_NULL)
216         {
217                 vector<deUint8> pushConstantsBytes;
218                 pushConstants->getBytes(pushConstantsBytes);
219
220                 range.size                                                      = static_cast<deUint32>(pushConstantsBytes.size());
221                 createInfo.pushConstantRangeCount       = 1;
222                 createInfo.pPushConstantRanges          = &range;
223         }
224
225         return createPipelineLayout(vkdi, device, &createInfo);
226 }
227
228 /*--------------------------------------------------------------------*//*!
229  * \brief Create a one-time descriptor pool for one descriptor set that
230  * support the given descriptor types.
231  *//*--------------------------------------------------------------------*/
232 inline Move<VkDescriptorPool> createDescriptorPool (const DeviceInterface& vkdi, const VkDevice& device, const vector<VkDescriptorType>& dtypes)
233 {
234         DescriptorPoolBuilder builder;
235
236         for (size_t typeNdx = 0; typeNdx < dtypes.size(); ++typeNdx)
237                 builder.addType(dtypes[typeNdx], 1);
238
239         return builder.build(vkdi, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, /* maxSets = */ 1);
240 }
241
242 /*--------------------------------------------------------------------*//*!
243  * \brief Create a descriptor set
244  *
245  * The descriptor set's layout contains the given descriptor types,
246  * sequentially binded to binding points starting from 0.
247  *//*--------------------------------------------------------------------*/
248 Move<VkDescriptorSet> createDescriptorSet (const DeviceInterface& vkdi, const VkDevice& device, VkDescriptorPool pool, VkDescriptorSetLayout layout, const vector<VkDescriptorType>& dtypes, const vector<VkDescriptorBufferInfo>& descriptorInfos, const vector<VkDescriptorImageInfo>& descriptorImageInfos)
249 {
250         DE_ASSERT(dtypes.size() == descriptorInfos.size() + descriptorImageInfos.size());
251
252         const VkDescriptorSetAllocateInfo       allocInfo       =
253         {
254                 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
255                 DE_NULL,
256                 pool,
257                 1u,
258                 &layout
259         };
260
261         Move<VkDescriptorSet>                           descriptorSet   = allocateDescriptorSet(vkdi, device, &allocInfo);
262         DescriptorSetUpdateBuilder                      builder;
263
264         deUint32                                                        bufferNdx               = 0u;
265         deUint32                                                        imageNdx                = 0u;
266
267         for (deUint32 descriptorNdx = 0; descriptorNdx < dtypes.size(); ++descriptorNdx)
268         {
269                 switch (dtypes[descriptorNdx])
270                 {
271                         // Write buffer descriptor
272                         case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
273                         case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
274                                 builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(descriptorNdx), dtypes[descriptorNdx], &descriptorInfos[bufferNdx++]);
275                                 break;
276
277                         // Write image/sampler descriptor
278                         case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
279                         case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
280                         case VK_DESCRIPTOR_TYPE_SAMPLER:
281                         case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
282                                 builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(descriptorNdx), dtypes[descriptorNdx], &descriptorImageInfos[imageNdx++]);
283                                 break;
284
285                         default:
286                                 DE_FATAL("Not implemented");
287                 }
288         }
289         builder.update(vkdi, device);
290
291         return descriptorSet;
292 }
293
294 /*--------------------------------------------------------------------*//*!
295  * \brief Create a compute pipeline based on the given shader
296  *//*--------------------------------------------------------------------*/
297 Move<VkPipeline> createComputePipeline (const DeviceInterface& vkdi, const VkDevice& device, VkPipelineLayout pipelineLayout, VkShaderModule shader, const char* entryPoint, const vkt::SpirVAssembly::SpecConstants& specConstants)
298 {
299         const deUint32                                                  numSpecConstants                                = (deUint32)specConstants.getValuesCount();
300         vector<VkSpecializationMapEntry>                entries;
301         VkSpecializationInfo                                    specInfo;
302         size_t                                                                  offset                                                  = 0;
303
304         if (numSpecConstants != 0)
305         {
306                 entries.resize(numSpecConstants);
307
308                 for (deUint32 ndx = 0; ndx < numSpecConstants; ++ndx)
309                 {
310                         const size_t valueSize  = specConstants.getValueSize(ndx);
311
312                         entries[ndx].constantID = ndx;
313                         entries[ndx].offset             = static_cast<deUint32>(offset);
314                         entries[ndx].size               = valueSize;
315
316                         offset                                  += valueSize;
317                 }
318
319                 specInfo.mapEntryCount          = numSpecConstants;
320                 specInfo.pMapEntries            = &entries[0];
321                 specInfo.dataSize                       = numSpecConstants * sizeof(deUint32);
322                 specInfo.pData                          = specConstants.getValuesBuffer();
323         }
324
325         const VkPipelineShaderStageCreateInfo   pipelineShaderStageCreateInfo   =
326         {
327                 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,    // sType
328                 DE_NULL,                                                                                                // pNext
329                 (VkPipelineShaderStageCreateFlags)0,                                    // flags
330                 VK_SHADER_STAGE_COMPUTE_BIT,                                                    // stage
331                 shader,                                                                                                 // module
332                 entryPoint,                                                                                             // pName
333                 (numSpecConstants == 0) ? DE_NULL : &specInfo,                  // pSpecializationInfo
334         };
335         const VkComputePipelineCreateInfo               pipelineCreateInfo                              =
336         {
337                 VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,                 // sType
338                 DE_NULL,                                                                                                // pNext
339                 (VkPipelineCreateFlags)0,
340                 pipelineShaderStageCreateInfo,                                                  // cs
341                 pipelineLayout,                                                                                 // layout
342                 (VkPipeline)0,                                                                                  // basePipelineHandle
343                 0u,                                                                                                             // basePipelineIndex
344         };
345
346         return createComputePipeline(vkdi, device, (VkPipelineCache)0u, &pipelineCreateInfo);
347 }
348
349 } // anonymous
350
351 namespace vkt
352 {
353 namespace SpirVAssembly
354 {
355
356 // ComputeShaderTestCase implementations
357
358 SpvAsmComputeShaderCase::SpvAsmComputeShaderCase (tcu::TestContext& testCtx, const char* name, const char* description, const ComputeShaderSpec& spec, const ComputeTestFeatures features)
359         : TestCase              (testCtx, name, description)
360         , m_shaderSpec  (spec)
361         , m_features    (features)
362 {
363 }
364
365 void SpvAsmComputeShaderCase::initPrograms (SourceCollections& programCollection) const
366 {
367         programCollection.spirvAsmSources.add("compute") << m_shaderSpec.assembly.c_str() << SpirVAsmBuildOptions(programCollection.usedVulkanVersion, m_shaderSpec.spirvVersion);
368 }
369
370 TestInstance* SpvAsmComputeShaderCase::createInstance (Context& ctx) const
371 {
372         if (getMinRequiredVulkanVersion(m_shaderSpec.spirvVersion) > ctx.getUsedApiVersion())
373         {
374                 TCU_THROW(NotSupportedError, std::string("Vulkan higher than or equal to " + getVulkanName(getMinRequiredVulkanVersion(m_shaderSpec.spirvVersion)) + " is required for this test to run").c_str());
375         }
376         return new SpvAsmComputeShaderInstance(ctx, m_shaderSpec, m_features);
377 }
378
379 // ComputeShaderTestInstance implementations
380
381 SpvAsmComputeShaderInstance::SpvAsmComputeShaderInstance (Context& ctx, const ComputeShaderSpec& spec, const ComputeTestFeatures features)
382         : TestInstance          (ctx)
383         , m_shaderSpec          (spec)
384         , m_features            (features)
385 {
386 }
387
388 VkImageUsageFlags getMatchingComputeImageUsageFlags (VkDescriptorType dType)
389 {
390         switch (dType)
391         {
392                 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:                  return VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
393                 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:                  return VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
394                 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: return VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
395                 default:                                                                                DE_FATAL("Not implemented");
396         }
397         return (VkImageUsageFlags)0;
398 }
399
400 tcu::TestStatus SpvAsmComputeShaderInstance::iterate (void)
401 {
402         const deUint32                                          queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
403         const VkDevice&                                         device                          = m_context.getDevice();
404         const DeviceInterface&                          vkdi                            = m_context.getDeviceInterface();
405         Allocator&                                                      allocator                       = m_context.getDefaultAllocator();
406         const VkQueue                                           queue                           = m_context.getUniversalQueue();
407         const VkPhysicalDeviceFeatures&         features                        = m_context.getDeviceFeatures();
408
409         vector<AllocationSp>                            inputAllocs;
410         vector<AllocationSp>                            outputAllocs;
411         vector<BufferHandleSp>                          inputBuffers;
412         vector<ImageHandleSp>                           inputImages;
413         vector<ImageViewHandleSp>                       inputImageViews;
414         vector<SamplerHandleSp>                         inputSamplers;
415         vector<BufferHandleSp>                          outputBuffers;
416         vector<VkDescriptorBufferInfo>          descriptorInfos;
417         vector<VkDescriptorImageInfo>           descriptorImageInfos;
418         vector<VkDescriptorType>                        descriptorTypes;
419
420         // Check all required extensions are supported
421         for (std::vector<std::string>::const_iterator i = m_shaderSpec.extensions.begin(); i != m_shaderSpec.extensions.end(); ++i)
422         {
423                 if (!de::contains(m_context.getDeviceExtensions().begin(), m_context.getDeviceExtensions().end(), *i))
424                         TCU_THROW(NotSupportedError, (std::string("Extension not supported: ") + *i).c_str());
425         }
426
427         if ((m_features == COMPUTE_TEST_USES_INT16 || m_features == COMPUTE_TEST_USES_INT16_INT64) && !features.shaderInt16)
428         {
429                 TCU_THROW(NotSupportedError, "shaderInt16 feature is not supported");
430         }
431
432         if ((m_features == COMPUTE_TEST_USES_INT64 || m_features == COMPUTE_TEST_USES_INT16_INT64) && !features.shaderInt64)
433         {
434                 TCU_THROW(NotSupportedError, "shaderInt64 feature is not supported");
435         }
436
437         if ((m_features == COMPUTE_TEST_USES_FLOAT64) && !features.shaderFloat64)
438         {
439                 TCU_THROW(NotSupportedError, "shaderFloat64 feature is not supported");
440         }
441
442         // Core features
443         {
444                 const char* unsupportedFeature = DE_NULL;
445
446                 if (!isCoreFeaturesSupported(m_context, m_shaderSpec.requestedVulkanFeatures.coreFeatures, &unsupportedFeature))
447                         TCU_THROW(NotSupportedError, std::string("At least following requested core feature is not supported: ") + unsupportedFeature);
448         }
449
450         // Extension features
451         {
452                 // 8bit storage features
453                 {
454                         if (!is8BitStorageFeaturesSupported(m_context, m_shaderSpec.requestedVulkanFeatures.ext8BitStorage))
455                                 TCU_THROW(NotSupportedError, "Requested 8bit storage features not supported");
456                 }
457
458                 // 16bit storage features
459                 {
460                         if (!is16BitStorageFeaturesSupported(m_context, m_shaderSpec.requestedVulkanFeatures.ext16BitStorage))
461                                 TCU_THROW(NotSupportedError, "Requested 16bit storage features not supported");
462                 }
463
464                 // VariablePointers features
465                 {
466                         if (!isVariablePointersFeaturesSupported(m_context, m_shaderSpec.requestedVulkanFeatures.extVariablePointers))
467                                 TCU_THROW(NotSupportedError, "Request Variable Pointer feature not supported");
468                 }
469         }
470
471         DE_ASSERT(!m_shaderSpec.outputs.empty());
472
473         // Create command pool and command buffer
474
475         const Unique<VkCommandPool>                     cmdPool                         (createCommandPool(vkdi, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
476         Unique<VkCommandBuffer>                         cmdBuffer                       (allocateCommandBuffer(vkdi, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
477
478         // Create buffer and image objects, allocate storage, and create view for all input/output buffers and images.
479
480         for (deUint32 inputNdx = 0; inputNdx < m_shaderSpec.inputs.size(); ++inputNdx)
481         {
482                 const VkDescriptorType  descType        = m_shaderSpec.inputs[inputNdx].getDescriptorType();
483
484                 const bool                              hasImage        = (descType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)        ||
485                                                                                           (descType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)        ||
486                                                                                           (descType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
487
488                 const bool                              hasSampler      = (descType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)        ||
489                                                                                           (descType == VK_DESCRIPTOR_TYPE_SAMPLER)                      ||
490                                                                                           (descType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
491
492                 descriptorTypes.push_back(descType);
493
494                 // Buffer
495                 if (!hasImage && !hasSampler)
496                 {
497                         const BufferSp&         input                   = m_shaderSpec.inputs[inputNdx].getBuffer();
498                         vector<deUint8>         inputBytes;
499
500                         input->getBytes(inputBytes);
501
502                         const size_t            numBytes                = inputBytes.size();
503
504                         AllocationMp            bufferAlloc;
505                         BufferHandleUp*         buffer                  = new BufferHandleUp(createBufferAndBindMemory(vkdi, device, descType, allocator, numBytes, &bufferAlloc, m_shaderSpec.coherentMemory));
506
507                         setMemory(vkdi, device, &*bufferAlloc, numBytes, &inputBytes.front(), m_shaderSpec.coherentMemory);
508                         inputBuffers.push_back(BufferHandleSp(buffer));
509                         inputAllocs.push_back(de::SharedPtr<Allocation>(bufferAlloc.release()));
510                 }
511                 // Image
512                 else if (hasImage)
513                 {
514                         const BufferSp&                         input                   = m_shaderSpec.inputs[inputNdx].getBuffer();
515                         vector<deUint8>                         inputBytes;
516
517                         input->getBytes(inputBytes);
518
519                         const size_t                            numBytes                = inputBytes.size();
520
521                         AllocationMp                            bufferAlloc;
522                         BufferHandleUp*                         buffer                  = new BufferHandleUp(createBufferAndBindMemory(vkdi, device, descType, allocator, numBytes, &bufferAlloc));
523
524                         AllocationMp                            imageAlloc;
525                         ImageHandleUp*                          image                   = new ImageHandleUp(createImageAndBindMemory(vkdi, device, descType, allocator, queueFamilyIndex, &imageAlloc));
526
527                         setMemory(vkdi, device, &*bufferAlloc, numBytes, &inputBytes.front());
528
529                         inputBuffers.push_back(BufferHandleSp(buffer));
530                         inputAllocs.push_back(de::SharedPtr<Allocation>(bufferAlloc.release()));
531
532                         inputImages.push_back(ImageHandleSp(image));
533                         inputAllocs.push_back(de::SharedPtr<Allocation>(imageAlloc.release()));
534
535                         const VkImageLayout                     imageLayout             = (descType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
536                         const VkBufferImageCopy         copyRegion              =
537                         {
538                                 0u,                                                                                             // VkDeviceSize                         bufferOffset;
539                                 0u,                                                                                             // deUint32                                     bufferRowLength;
540                                 0u,                                                                                             // deUint32                                     bufferImageHeight;
541                                 {
542                                         VK_IMAGE_ASPECT_COLOR_BIT,                                              // VkImageAspectFlags           aspect;
543                                         0u,                                                                                             // deUint32                                     mipLevel;
544                                         0u,                                                                                             // deUint32                                     baseArrayLayer;
545                                         1u,                                                                                             // deUint32                                     layerCount;
546                                 },                                                                                              // VkImageSubresourceLayers     imageSubresource;
547                                 { 0, 0, 0 },                                                                    // VkOffset3D                           imageOffset;
548                                 { 8, 8, 1 }                                                                             // VkExtent3D                           imageExtent;
549                         };
550                         vector<VkBufferImageCopy>       copyRegions;
551                         copyRegions.push_back(copyRegion);
552
553                         copyBufferToImage(vkdi, device, queue, queueFamilyIndex, buffer->get(), (deUint32)numBytes, copyRegions, DE_NULL, VK_IMAGE_ASPECT_COLOR_BIT, 1u, 1u, image->get(), imageLayout);
554                 }
555         }
556
557         deUint32                                                        imageNdx                        = 0u;
558         deUint32                                                        bufferNdx                       = 0u;
559
560         for (deUint32 inputNdx = 0; inputNdx < descriptorTypes.size(); ++inputNdx)
561         {
562                 const VkDescriptorType  descType        = descriptorTypes[inputNdx];
563
564                 const bool                              hasImage        = (descType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)        ||
565                                                                                           (descType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)        ||
566                                                                                           (descType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
567
568                 const bool                              hasSampler      = (descType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)        ||
569                                                                                           (descType == VK_DESCRIPTOR_TYPE_SAMPLER)                      ||
570                                                                                           (descType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
571
572                 // Create image view and sampler
573                 if (hasImage || hasSampler)
574                 {
575                         if (descType != VK_DESCRIPTOR_TYPE_SAMPLER)
576                         {
577                                 const VkImageViewCreateInfo     imgViewParams   =
578                                 {
579                                         VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,       //      VkStructureType                 sType;
580                                         DE_NULL,                                                                        //      const void*                             pNext;
581                                         0u,                                                                                     //      VkImageViewCreateFlags  flags;
582                                         **inputImages[imageNdx++],                                      //      VkImage                                 image;
583                                         VK_IMAGE_VIEW_TYPE_2D,                                          //      VkImageViewType                 viewType;
584                                         VK_FORMAT_R32G32B32A32_SFLOAT,                          //      VkFormat                                format;
585                                         {
586                                                 VK_COMPONENT_SWIZZLE_R,
587                                                 VK_COMPONENT_SWIZZLE_G,
588                                                 VK_COMPONENT_SWIZZLE_B,
589                                                 VK_COMPONENT_SWIZZLE_A
590                                         },                                                                                      //      VkChannelMapping                channels;
591                                         {
592                                                 VK_IMAGE_ASPECT_COLOR_BIT,                                      //      VkImageAspectFlags              aspectMask;
593                                                 0u,                                                                                     //      deUint32                                baseMipLevel;
594                                                 1u,                                                                                     //      deUint32                                mipLevels;
595                                                 0u,                                                                                     //      deUint32                                baseArrayLayer;
596                                                 1u,                                                                                     //      deUint32                                arraySize;
597                                         },                                                                                      //      VkImageSubresourceRange subresourceRange;
598                                 };
599
600                                 Move<VkImageView>                       imgView                 (createImageView(vkdi, device, &imgViewParams));
601                                 inputImageViews.push_back(ImageViewHandleSp(new ImageViewHandleUp(imgView)));
602                         }
603
604                         if (hasSampler)
605                         {
606                                 const VkSamplerCreateInfo       samplerParams   =
607                                 {
608                                         VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,          // VkStructureType                      sType;
609                                         DE_NULL,                                                                        // const void*                          pNext;
610                                         0,                                                                                      // VkSamplerCreateFlags         flags;
611                                         VK_FILTER_NEAREST,                                                      // VkFilter                                     magFilter:
612                                         VK_FILTER_NEAREST,                                                      // VkFilter                                     minFilter;
613                                         VK_SAMPLER_MIPMAP_MODE_NEAREST,                         // VkSamplerMipmapMode          mipmapMode;
614                                         VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,          // VkSamplerAddressMode         addressModeU;
615                                         VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,          // VkSamplerAddressMode         addressModeV;
616                                         VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,          // VkSamplerAddressMode         addressModeW;
617                                         0.0f,                                                                           // float                                        mipLodBias;
618                                         VK_FALSE,                                                                       // VkBool32                                     anistoropyÉnable;
619                                         1.0f,                                                                           // float                                        maxAnisotropy;
620                                         VK_FALSE,                                                                       // VkBool32                                     compareEnable;
621                                         VK_COMPARE_OP_ALWAYS,                                           // VkCompareOp                          compareOp;
622                                         0.0f,                                                                           // float                                        minLod;
623                                         0.0f,                                                                           // float                                        maxLod;
624                                         VK_BORDER_COLOR_INT_OPAQUE_BLACK,                       // VkBorderColor                        borderColor;
625                                         VK_FALSE                                                                        // VkBool32                                     unnormalizedCoordinates;
626                                 };
627
628                                 Move<VkSampler>                         sampler                 (createSampler(vkdi, device, &samplerParams));
629                                 inputSamplers.push_back(SamplerHandleSp(new SamplerHandleUp(sampler)));
630                         }
631                 }
632
633                 // Create descriptor buffer and image infos
634                 switch (descType)
635                 {
636                         case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
637                         case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
638                         {
639                                 const VkDescriptorBufferInfo bufInfo =
640                                 {
641                                         **inputBuffers[bufferNdx++],                            // VkBuffer                                     buffer;
642                                         0,                                                                                      // VkDeviceSize                         offset;
643                                         VK_WHOLE_SIZE,                                                          // VkDeviceSize                         size;
644                                 };
645                                 descriptorInfos.push_back(bufInfo);
646                                 break;
647                         }
648
649                         case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
650                         case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
651                         {
652                                 const VkDescriptorImageInfo     imgInfo =
653                                 {
654                                         DE_NULL,                                                                        // VkSampler                            sampler;
655                                         **inputImageViews.back(),                                       // VkImageView                          imageView;
656                                         VK_IMAGE_LAYOUT_GENERAL                                         // VkImageLayout                        imageLayout;
657                                 };
658                                 descriptorImageInfos.push_back(imgInfo);
659                                 break;
660                         }
661
662                         case VK_DESCRIPTOR_TYPE_SAMPLER:
663                         {
664                                 const VkDescriptorImageInfo     imgInfo =
665                                 {
666                                         **inputSamplers.back(),                                         // VkSampler                            sampler;
667                                         DE_NULL,                                                                        // VkImageView                          imageView;
668                                         VK_IMAGE_LAYOUT_GENERAL                                         // VkImageLayout                        imageLayout;
669                                 };
670                                 descriptorImageInfos.push_back(imgInfo);
671                                 break;
672                         }
673
674                         case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
675                         {
676
677                                 const VkDescriptorImageInfo     imgInfo =
678                                 {
679                                         **inputSamplers.back(),                                         // VkSampler                            sampler;
680                                         **inputImageViews.back(),                                       // VkImageView                          imageView;
681                                         VK_IMAGE_LAYOUT_GENERAL                                         // VkImageLayout                        imageLayout;
682                                 };
683                                 descriptorImageInfos.push_back(imgInfo);
684                                 break;
685                         }
686
687                         default:
688                                 DE_FATAL("Not implemented");
689                 }
690         }
691
692         for (deUint32 outputNdx = 0; outputNdx < m_shaderSpec.outputs.size(); ++outputNdx)
693         {
694                 DE_ASSERT(m_shaderSpec.outputs[outputNdx].getDescriptorType() == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
695
696                 descriptorTypes.push_back(m_shaderSpec.outputs[outputNdx].getDescriptorType());
697
698                 AllocationMp            alloc;
699                 const BufferSp&         output          = m_shaderSpec.outputs[outputNdx].getBuffer();
700                 vector<deUint8>         outputBytes;
701
702                 output->getBytes(outputBytes);
703
704                 const size_t            numBytes        = outputBytes.size();
705                 BufferHandleUp*         buffer          = new BufferHandleUp(createBufferAndBindMemory(vkdi, device, descriptorTypes.back(), allocator, numBytes, &alloc, m_shaderSpec.coherentMemory));
706
707                 fillMemoryWithValue(vkdi, device, &*alloc, numBytes, 0xff, m_shaderSpec.coherentMemory);
708                 descriptorInfos.push_back(vk::makeDescriptorBufferInfo(**buffer, 0u, numBytes));
709                 outputBuffers.push_back(BufferHandleSp(buffer));
710                 outputAllocs.push_back(de::SharedPtr<Allocation>(alloc.release()));
711         }
712
713         // Create layouts and descriptor set.
714
715         Unique<VkDescriptorSetLayout>           descriptorSetLayout     (createDescriptorSetLayout(vkdi, device, descriptorTypes));
716         Unique<VkPipelineLayout>                        pipelineLayout          (createPipelineLayout(vkdi, device, *descriptorSetLayout, m_shaderSpec.pushConstants));
717         Unique<VkDescriptorPool>                        descriptorPool          (createDescriptorPool(vkdi, device, descriptorTypes));
718         Unique<VkDescriptorSet>                         descriptorSet           (createDescriptorSet(vkdi, device, *descriptorPool, *descriptorSetLayout, descriptorTypes, descriptorInfos, descriptorImageInfos));
719
720         // Create compute shader and pipeline.
721
722         const ProgramBinary&                            binary                          = m_context.getBinaryCollection().get("compute");
723         if (m_shaderSpec.verifyBinary && !m_shaderSpec.verifyBinary(binary))
724         {
725                 return tcu::TestStatus::fail("Binary verification of SPIR-V in the test failed");
726         }
727         Unique<VkShaderModule>                          module                          (createShaderModule(vkdi, device, binary, (VkShaderModuleCreateFlags)0u));
728
729         Unique<VkPipeline>                                      computePipeline         (createComputePipeline(vkdi, device, *pipelineLayout, *module, m_shaderSpec.entryPoint.c_str(), m_shaderSpec.specConstants));
730
731         // Create command buffer and record commands
732
733         const tcu::IVec3&                               numWorkGroups           = m_shaderSpec.numWorkGroups;
734
735         beginCommandBuffer(vkdi, *cmdBuffer);
736         vkdi.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *computePipeline);
737         vkdi.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0, 1, &descriptorSet.get(), 0, DE_NULL);
738         if (m_shaderSpec.pushConstants != DE_NULL)
739         {
740                 vector<deUint8> pushConstantsBytes;
741                 m_shaderSpec.pushConstants->getBytes(pushConstantsBytes);
742
743                 const deUint32  size    = static_cast<deUint32>(pushConstantsBytes.size());
744                 const void*             data    = &pushConstantsBytes.front();
745
746                 vkdi.cmdPushConstants(*cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, /* offset = */ 0, /* size = */ size, data);
747         }
748         vkdi.cmdDispatch(*cmdBuffer, numWorkGroups.x(), numWorkGroups.y(), numWorkGroups.z());
749         endCommandBuffer(vkdi, *cmdBuffer);
750
751         submitCommandsAndWait(vkdi, device, queue, *cmdBuffer);
752
753         // Invalidate output memory ranges before checking on host.
754         for (size_t outputNdx = 0; outputNdx < m_shaderSpec.outputs.size(); ++outputNdx)
755         {
756                 invalidateMemory(vkdi, device, outputAllocs[outputNdx].get(), m_shaderSpec.outputs[outputNdx].getByteSize(), m_shaderSpec.coherentMemory);
757         }
758
759         // Check output.
760         if (m_shaderSpec.verifyIO)
761         {
762                 if (!(*m_shaderSpec.verifyIO)(m_shaderSpec.inputs, outputAllocs, m_shaderSpec.outputs, m_context.getTestContext().getLog()))
763                         return tcu::TestStatus(m_shaderSpec.failResult, m_shaderSpec.failMessage);
764         }
765         else
766         {
767                 for (size_t outputNdx = 0; outputNdx < m_shaderSpec.outputs.size(); ++outputNdx)
768                 {
769                         const BufferSp& expectedOutput = m_shaderSpec.outputs[outputNdx].getBuffer();;
770                         vector<deUint8> expectedBytes;
771
772                         expectedOutput->getBytes(expectedBytes);
773
774                         if (deMemCmp(&expectedBytes.front(), outputAllocs[outputNdx]->getHostPtr(), expectedBytes.size()))
775                         {
776                                 const deUint8*  ptrHost         = static_cast<deUint8*>(outputAllocs[outputNdx]->getHostPtr());
777                                 const deUint8*  ptrExpected     = static_cast<deUint8*>(&expectedBytes.front());
778                                 unsigned int    ndx                     = 0u;
779                                 for (; ndx < expectedBytes.size(); ++ndx)
780                                 {
781                                         if (ptrHost[ndx] != ptrExpected[ndx])
782                                                 break;
783                                 }
784                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "OutputBuffer: " << outputNdx
785                                                                                                         << " Got " << (deUint8)ptrHost[ndx] <<" expected " << (deUint8)ptrExpected[ndx] << " at byte" << ndx << tcu::TestLog::EndMessage;
786                                 return tcu::TestStatus(m_shaderSpec.failResult, m_shaderSpec.failMessage);
787                         }
788                 }
789         }
790
791         return tcu::TestStatus::pass("Output match with expected");
792 }
793
794 } // SpirVAssembly
795 } // vkt