1 /*-------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2015 Google Inc.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * \brief Test Case Skeleton Based on Compute Shaders
22 *//*--------------------------------------------------------------------*/
24 #include "vktSpvAsmComputeShaderCase.hpp"
26 #include "deSharedPtr.hpp"
27 #include "deSTLUtil.hpp"
29 #include "vktSpvAsmUtils.hpp"
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"
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;
57 /*--------------------------------------------------------------------*//*!
58 * \brief Create a buffer, allocate and bind memory for the buffer
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,
68 AllocationMp* outMemory,
69 bool coherent = false)
71 VkBufferUsageFlags usageBit = (VkBufferUsageFlags)0;
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");
83 const VkBufferCreateInfo bufferCreateInfo =
85 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // sType
90 VK_SHARING_MODE_EXCLUSIVE, // sharingMode
91 0u, // queueFamilyCount
92 DE_NULL, // pQueueFamilyIndices
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);
99 VK_CHECK(vkdi.bindBufferMemory(device, *buffer, bufferMemory->getMemory(), bufferMemory->getOffset()));
100 *outMemory = bufferMemory;
105 /*--------------------------------------------------------------------*//*!
106 * \brief Create image, allocate and bind memory for the image
108 *//*--------------------------------------------------------------------*/
109 Move<VkImage> createImageAndBindMemory (const DeviceInterface& vkdi, const VkDevice& device, VkDescriptorType dtype, Allocator& allocator, deUint32 queueFamilyIndex, AllocationMp* outMemory)
111 VkImageUsageFlags usageBits = (VkImageUsageFlags)0;
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");
121 const VkImageCreateInfo resourceImageParams =
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;
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);
145 VK_CHECK(vkdi.bindImageMemory(device, *image, imageMemory->getMemory(), imageMemory->getOffset()));
146 *outMemory = imageMemory;
151 void setMemory (const DeviceInterface& vkdi, const VkDevice& device, Allocation* destAlloc, size_t numBytes, const void* data, bool coherent = false)
153 void* const hostPtr = destAlloc->getHostPtr();
155 deMemcpy((deUint8*)hostPtr, data, numBytes);
158 flushMappedMemoryRange(vkdi, device, destAlloc->getMemory(), destAlloc->getOffset(), numBytes);
161 void fillMemoryWithValue (const DeviceInterface& vkdi, const VkDevice& device, Allocation* destAlloc, size_t numBytes, deUint8 value, bool coherent = false)
163 void* const hostPtr = destAlloc->getHostPtr();
165 deMemset((deUint8*)hostPtr, value, numBytes);
168 flushMappedMemoryRange(vkdi, device, destAlloc->getMemory(), destAlloc->getOffset(), numBytes);
171 void invalidateMemory (const DeviceInterface& vkdi, const VkDevice& device, Allocation* srcAlloc, size_t numBytes, bool coherent = false)
174 invalidateMappedMemoryRange(vkdi, device, srcAlloc->getMemory(), srcAlloc->getOffset(), numBytes);
177 /*--------------------------------------------------------------------*//*!
178 * \brief Create a descriptor set layout with the given descriptor types
180 * All descriptors are created for compute pipeline.
181 *//*--------------------------------------------------------------------*/
182 Move<VkDescriptorSetLayout> createDescriptorSetLayout (const DeviceInterface& vkdi, const VkDevice& device, const vector<VkDescriptorType>& dtypes)
184 DescriptorSetLayoutBuilder builder;
186 for (size_t bindingNdx = 0; bindingNdx < dtypes.size(); ++bindingNdx)
187 builder.addSingleBinding(dtypes[bindingNdx], VK_SHADER_STAGE_COMPUTE_BIT);
189 return builder.build(vkdi, device);
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)
197 VkPipelineLayoutCreateInfo createInfo =
199 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // sType
201 (VkPipelineLayoutCreateFlags)0,
202 1u, // descriptorSetCount
203 &descriptorSetLayout, // pSetLayouts
204 0u, // pushConstantRangeCount
205 DE_NULL, // pPushConstantRanges
208 VkPushConstantRange range =
210 VK_SHADER_STAGE_COMPUTE_BIT, // stageFlags
215 if (pushConstants != DE_NULL)
217 vector<deUint8> pushConstantsBytes;
218 pushConstants->getBytes(pushConstantsBytes);
220 range.size = static_cast<deUint32>(pushConstantsBytes.size());
221 createInfo.pushConstantRangeCount = 1;
222 createInfo.pPushConstantRanges = ⦥
225 return createPipelineLayout(vkdi, device, &createInfo);
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)
234 DescriptorPoolBuilder builder;
236 for (size_t typeNdx = 0; typeNdx < dtypes.size(); ++typeNdx)
237 builder.addType(dtypes[typeNdx], 1);
239 return builder.build(vkdi, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, /* maxSets = */ 1);
242 /*--------------------------------------------------------------------*//*!
243 * \brief Create a descriptor set
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)
250 DE_ASSERT(dtypes.size() == descriptorInfos.size() + descriptorImageInfos.size());
252 const VkDescriptorSetAllocateInfo allocInfo =
254 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
261 Move<VkDescriptorSet> descriptorSet = allocateDescriptorSet(vkdi, device, &allocInfo);
262 DescriptorSetUpdateBuilder builder;
264 deUint32 bufferNdx = 0u;
265 deUint32 imageNdx = 0u;
267 for (deUint32 descriptorNdx = 0; descriptorNdx < dtypes.size(); ++descriptorNdx)
269 switch (dtypes[descriptorNdx])
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++]);
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++]);
286 DE_FATAL("Not implemented");
289 builder.update(vkdi, device);
291 return descriptorSet;
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)
299 const deUint32 numSpecConstants = (deUint32)specConstants.getValuesCount();
300 vector<VkSpecializationMapEntry> entries;
301 VkSpecializationInfo specInfo;
304 if (numSpecConstants != 0)
306 entries.resize(numSpecConstants);
308 for (deUint32 ndx = 0; ndx < numSpecConstants; ++ndx)
310 const size_t valueSize = specConstants.getValueSize(ndx);
312 entries[ndx].constantID = ndx;
313 entries[ndx].offset = static_cast<deUint32>(offset);
314 entries[ndx].size = valueSize;
319 specInfo.mapEntryCount = numSpecConstants;
320 specInfo.pMapEntries = &entries[0];
321 specInfo.dataSize = numSpecConstants * sizeof(deUint32);
322 specInfo.pData = specConstants.getValuesBuffer();
325 const VkPipelineShaderStageCreateInfo pipelineShaderStageCreateInfo =
327 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // sType
329 (VkPipelineShaderStageCreateFlags)0, // flags
330 VK_SHADER_STAGE_COMPUTE_BIT, // stage
333 (numSpecConstants == 0) ? DE_NULL : &specInfo, // pSpecializationInfo
335 const VkComputePipelineCreateInfo pipelineCreateInfo =
337 VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // sType
339 (VkPipelineCreateFlags)0,
340 pipelineShaderStageCreateInfo, // cs
341 pipelineLayout, // layout
342 (VkPipeline)0, // basePipelineHandle
343 0u, // basePipelineIndex
346 return createComputePipeline(vkdi, device, (VkPipelineCache)0u, &pipelineCreateInfo);
353 namespace SpirVAssembly
356 // ComputeShaderTestCase implementations
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)
365 void SpvAsmComputeShaderCase::initPrograms (SourceCollections& programCollection) const
367 programCollection.spirvAsmSources.add("compute") << m_shaderSpec.assembly.c_str() << SpirVAsmBuildOptions(programCollection.usedVulkanVersion, m_shaderSpec.spirvVersion);
370 TestInstance* SpvAsmComputeShaderCase::createInstance (Context& ctx) const
372 if (getMinRequiredVulkanVersion(m_shaderSpec.spirvVersion) > ctx.getUsedApiVersion())
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());
376 return new SpvAsmComputeShaderInstance(ctx, m_shaderSpec, m_features);
379 // ComputeShaderTestInstance implementations
381 SpvAsmComputeShaderInstance::SpvAsmComputeShaderInstance (Context& ctx, const ComputeShaderSpec& spec, const ComputeTestFeatures features)
383 , m_shaderSpec (spec)
384 , m_features (features)
388 VkImageUsageFlags getMatchingComputeImageUsageFlags (VkDescriptorType dType)
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");
397 return (VkImageUsageFlags)0;
400 tcu::TestStatus SpvAsmComputeShaderInstance::iterate (void)
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();
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;
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)
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());
427 if ((m_features == COMPUTE_TEST_USES_INT16 || m_features == COMPUTE_TEST_USES_INT16_INT64) && !features.shaderInt16)
429 TCU_THROW(NotSupportedError, "shaderInt16 feature is not supported");
432 if ((m_features == COMPUTE_TEST_USES_INT64 || m_features == COMPUTE_TEST_USES_INT16_INT64) && !features.shaderInt64)
434 TCU_THROW(NotSupportedError, "shaderInt64 feature is not supported");
437 if ((m_features == COMPUTE_TEST_USES_FLOAT64) && !features.shaderFloat64)
439 TCU_THROW(NotSupportedError, "shaderFloat64 feature is not supported");
444 const char* unsupportedFeature = DE_NULL;
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);
450 // Extension features
452 // 8bit storage features
454 if (!is8BitStorageFeaturesSupported(m_context, m_shaderSpec.requestedVulkanFeatures.ext8BitStorage))
455 TCU_THROW(NotSupportedError, "Requested 8bit storage features not supported");
458 // 16bit storage features
460 if (!is16BitStorageFeaturesSupported(m_context, m_shaderSpec.requestedVulkanFeatures.ext16BitStorage))
461 TCU_THROW(NotSupportedError, "Requested 16bit storage features not supported");
464 // VariablePointers features
466 if (!isVariablePointersFeaturesSupported(m_context, m_shaderSpec.requestedVulkanFeatures.extVariablePointers))
467 TCU_THROW(NotSupportedError, "Request Variable Pointer feature not supported");
471 DE_ASSERT(!m_shaderSpec.outputs.empty());
473 // Create command pool and command buffer
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));
478 // Create buffer and image objects, allocate storage, and create view for all input/output buffers and images.
480 for (deUint32 inputNdx = 0; inputNdx < m_shaderSpec.inputs.size(); ++inputNdx)
482 const VkDescriptorType descType = m_shaderSpec.inputs[inputNdx].getDescriptorType();
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);
488 const bool hasSampler = (descType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE) ||
489 (descType == VK_DESCRIPTOR_TYPE_SAMPLER) ||
490 (descType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
492 descriptorTypes.push_back(descType);
495 if (!hasImage && !hasSampler)
497 const BufferSp& input = m_shaderSpec.inputs[inputNdx].getBuffer();
498 vector<deUint8> inputBytes;
500 input->getBytes(inputBytes);
502 const size_t numBytes = inputBytes.size();
504 AllocationMp bufferAlloc;
505 BufferHandleUp* buffer = new BufferHandleUp(createBufferAndBindMemory(vkdi, device, descType, allocator, numBytes, &bufferAlloc, m_shaderSpec.coherentMemory));
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()));
514 const BufferSp& input = m_shaderSpec.inputs[inputNdx].getBuffer();
515 vector<deUint8> inputBytes;
517 input->getBytes(inputBytes);
519 const size_t numBytes = inputBytes.size();
521 AllocationMp bufferAlloc;
522 BufferHandleUp* buffer = new BufferHandleUp(createBufferAndBindMemory(vkdi, device, descType, allocator, numBytes, &bufferAlloc));
524 AllocationMp imageAlloc;
525 ImageHandleUp* image = new ImageHandleUp(createImageAndBindMemory(vkdi, device, descType, allocator, queueFamilyIndex, &imageAlloc));
527 setMemory(vkdi, device, &*bufferAlloc, numBytes, &inputBytes.front());
529 inputBuffers.push_back(BufferHandleSp(buffer));
530 inputAllocs.push_back(de::SharedPtr<Allocation>(bufferAlloc.release()));
532 inputImages.push_back(ImageHandleSp(image));
533 inputAllocs.push_back(de::SharedPtr<Allocation>(imageAlloc.release()));
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 =
538 0u, // VkDeviceSize bufferOffset;
539 0u, // deUint32 bufferRowLength;
540 0u, // deUint32 bufferImageHeight;
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;
550 vector<VkBufferImageCopy> copyRegions;
551 copyRegions.push_back(copyRegion);
553 copyBufferToImage(vkdi, device, queue, queueFamilyIndex, buffer->get(), (deUint32)numBytes, copyRegions, DE_NULL, VK_IMAGE_ASPECT_COLOR_BIT, 1u, 1u, image->get(), imageLayout);
557 deUint32 imageNdx = 0u;
558 deUint32 bufferNdx = 0u;
560 for (deUint32 inputNdx = 0; inputNdx < descriptorTypes.size(); ++inputNdx)
562 const VkDescriptorType descType = descriptorTypes[inputNdx];
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);
568 const bool hasSampler = (descType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE) ||
569 (descType == VK_DESCRIPTOR_TYPE_SAMPLER) ||
570 (descType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
572 // Create image view and sampler
573 if (hasImage || hasSampler)
575 if (descType != VK_DESCRIPTOR_TYPE_SAMPLER)
577 const VkImageViewCreateInfo imgViewParams =
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;
586 VK_COMPONENT_SWIZZLE_R,
587 VK_COMPONENT_SWIZZLE_G,
588 VK_COMPONENT_SWIZZLE_B,
589 VK_COMPONENT_SWIZZLE_A
590 }, // VkChannelMapping channels;
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;
600 Move<VkImageView> imgView (createImageView(vkdi, device, &imgViewParams));
601 inputImageViews.push_back(ImageViewHandleSp(new ImageViewHandleUp(imgView)));
606 const VkSamplerCreateInfo samplerParams =
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;
628 Move<VkSampler> sampler (createSampler(vkdi, device, &samplerParams));
629 inputSamplers.push_back(SamplerHandleSp(new SamplerHandleUp(sampler)));
633 // Create descriptor buffer and image infos
636 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
637 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
639 const VkDescriptorBufferInfo bufInfo =
641 **inputBuffers[bufferNdx++], // VkBuffer buffer;
642 0, // VkDeviceSize offset;
643 VK_WHOLE_SIZE, // VkDeviceSize size;
645 descriptorInfos.push_back(bufInfo);
649 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
650 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
652 const VkDescriptorImageInfo imgInfo =
654 DE_NULL, // VkSampler sampler;
655 **inputImageViews.back(), // VkImageView imageView;
656 VK_IMAGE_LAYOUT_GENERAL // VkImageLayout imageLayout;
658 descriptorImageInfos.push_back(imgInfo);
662 case VK_DESCRIPTOR_TYPE_SAMPLER:
664 const VkDescriptorImageInfo imgInfo =
666 **inputSamplers.back(), // VkSampler sampler;
667 DE_NULL, // VkImageView imageView;
668 VK_IMAGE_LAYOUT_GENERAL // VkImageLayout imageLayout;
670 descriptorImageInfos.push_back(imgInfo);
674 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
677 const VkDescriptorImageInfo imgInfo =
679 **inputSamplers.back(), // VkSampler sampler;
680 **inputImageViews.back(), // VkImageView imageView;
681 VK_IMAGE_LAYOUT_GENERAL // VkImageLayout imageLayout;
683 descriptorImageInfos.push_back(imgInfo);
688 DE_FATAL("Not implemented");
692 for (deUint32 outputNdx = 0; outputNdx < m_shaderSpec.outputs.size(); ++outputNdx)
694 DE_ASSERT(m_shaderSpec.outputs[outputNdx].getDescriptorType() == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
696 descriptorTypes.push_back(m_shaderSpec.outputs[outputNdx].getDescriptorType());
699 const BufferSp& output = m_shaderSpec.outputs[outputNdx].getBuffer();
700 vector<deUint8> outputBytes;
702 output->getBytes(outputBytes);
704 const size_t numBytes = outputBytes.size();
705 BufferHandleUp* buffer = new BufferHandleUp(createBufferAndBindMemory(vkdi, device, descriptorTypes.back(), allocator, numBytes, &alloc, m_shaderSpec.coherentMemory));
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()));
713 // Create layouts and descriptor set.
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));
720 // Create compute shader and pipeline.
722 const ProgramBinary& binary = m_context.getBinaryCollection().get("compute");
723 if (m_shaderSpec.verifyBinary && !m_shaderSpec.verifyBinary(binary))
725 return tcu::TestStatus::fail("Binary verification of SPIR-V in the test failed");
727 Unique<VkShaderModule> module (createShaderModule(vkdi, device, binary, (VkShaderModuleCreateFlags)0u));
729 Unique<VkPipeline> computePipeline (createComputePipeline(vkdi, device, *pipelineLayout, *module, m_shaderSpec.entryPoint.c_str(), m_shaderSpec.specConstants));
731 // Create command buffer and record commands
733 const tcu::IVec3& numWorkGroups = m_shaderSpec.numWorkGroups;
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)
740 vector<deUint8> pushConstantsBytes;
741 m_shaderSpec.pushConstants->getBytes(pushConstantsBytes);
743 const deUint32 size = static_cast<deUint32>(pushConstantsBytes.size());
744 const void* data = &pushConstantsBytes.front();
746 vkdi.cmdPushConstants(*cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, /* offset = */ 0, /* size = */ size, data);
748 vkdi.cmdDispatch(*cmdBuffer, numWorkGroups.x(), numWorkGroups.y(), numWorkGroups.z());
749 endCommandBuffer(vkdi, *cmdBuffer);
751 submitCommandsAndWait(vkdi, device, queue, *cmdBuffer);
753 // Invalidate output memory ranges before checking on host.
754 for (size_t outputNdx = 0; outputNdx < m_shaderSpec.outputs.size(); ++outputNdx)
756 invalidateMemory(vkdi, device, outputAllocs[outputNdx].get(), m_shaderSpec.outputs[outputNdx].getByteSize(), m_shaderSpec.coherentMemory);
760 if (m_shaderSpec.verifyIO)
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);
767 for (size_t outputNdx = 0; outputNdx < m_shaderSpec.outputs.size(); ++outputNdx)
769 const BufferSp& expectedOutput = m_shaderSpec.outputs[outputNdx].getBuffer();;
770 vector<deUint8> expectedBytes;
772 expectedOutput->getBytes(expectedBytes);
774 if (deMemCmp(&expectedBytes.front(), outputAllocs[outputNdx]->getHostPtr(), expectedBytes.size()))
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)
781 if (ptrHost[ndx] != ptrExpected[ndx])
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);
791 return tcu::TestStatus::pass("Output match with expected");