--- /dev/null
+/*------------------------------------------------------------------------
+* Vulkan Conformance Tests
+* ------------------------
+*
+* Copyright (c) 2018 The Khronos Group Inc.
+* Copyright (c) 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*
+*//*!
+* \file
+* \brief VK_EXT_external_memory_host extension tests.
+*//*--------------------------------------------------------------------*/
+
+#include "vktMemoryExternalMemoryHostTests.hpp"
+
+#include "vktTestCaseUtil.hpp"
+
+#include "deMath.h"
+
+#include "vkQueryUtil.hpp"
+#include "vkImageUtil.hpp"
+#include "vkBuilderUtil.hpp"
+#include "vkRefUtil.hpp"
+#include "vkObjUtil.hpp"
+#include "vkTypeUtil.hpp"
+#include "vkCmdUtil.hpp"
+
+
+#include "tcuTestLog.hpp"
+#include "tcuImageCompare.hpp"
+
+namespace vkt
+{
+namespace memory
+{
+namespace
+{
+
+using namespace vk;
+
+inline deUint32 getBit (deUint32 src, int ndx)
+{
+ return (src >> ndx) & 1;
+}
+
+inline bool isBitSet (deUint32 src, int ndx)
+{
+ return getBit(src, ndx) != 0;
+}
+
+struct TestParams
+{
+ VkFormat m_format;
+ bool m_useOffset;
+
+ TestParams (VkFormat f, bool offset = false) : m_format(f) , m_useOffset(offset) {}
+};
+
+class ExternalMemoryHostBaseTestInstance : public TestInstance
+{
+public:
+ ExternalMemoryHostBaseTestInstance (Context& context, VkDeviceSize allocationSize);
+ ~ExternalMemoryHostBaseTestInstance (void);
+protected:
+ virtual tcu::TestStatus iterate (void);
+ VkDeviceSize getMinImportedHostPointerAlignment (void);
+ deUint32 getHostPointerMemoryTypeBits (void* hostPointer);
+ Move<VkDeviceMemory> allocateMemoryFromHostPointer (deUint32 memoryTypeIndex);
+ void logMemoryTypeIndexPropertyFlags (deUint32 index);
+ bool findMemoryTypeIndexToTest (deUint32 hostPointerMemoryTypeBits, deUint32* outMemoryTypeIndexToTest);
+
+ const InstanceInterface& m_vki;
+ const DeviceInterface& m_vkd;
+ tcu::TestLog& m_log;
+ const VkDevice m_device;
+ const VkPhysicalDevice m_physicalDevice;
+ const VkQueue m_queue;
+ const vk::VkPhysicalDeviceMemoryProperties m_memoryProps;
+ VkDeviceSize m_minImportedHostPointerAlignment;
+ VkDeviceSize m_allocationSize;
+ void* m_hostMemoryAlloc;
+ Allocator& m_allocator;
+ Move<VkDeviceMemory> m_deviceMemoryAllocatedFromHostPointer;
+};
+
+class ExternalMemoryHostRenderImageTestInstance : public ExternalMemoryHostBaseTestInstance
+{
+public:
+ ExternalMemoryHostRenderImageTestInstance (Context& context, TestParams testParams);
+protected:
+ virtual tcu::TestStatus iterate (void);
+ Move<VkImage> createImage (VkImageTiling tiling);
+ Move<VkImageView> createImageView (void);
+ Move<VkBuffer> createBindMemoryInitializeVertexBuffer (void);
+ Move<VkBuffer> createBindMemoryResultBuffer (void);
+ Move<VkFramebuffer> createFramebuffer (void);
+ Move<VkDescriptorSet> createAndUpdateDescriptorSet (void);
+ Move<VkPipelineLayout> createPipelineLayout (void);
+ Move<VkPipeline> createPipeline (void);
+ Move<VkRenderPass> createRenderPass (void);
+ void clear (VkClearColorValue color);
+ void draw (void);
+ void copyResultImagetoBuffer (void);
+ void prepareReferenceImage (tcu::PixelBufferAccess& reference);
+
+ TestParams m_testParams;
+ Move<VkImage> m_image;
+ Move<VkImageView> m_imageView;
+ Move<VkRenderPass> m_renderPass;
+ Move<VkFramebuffer> m_framebuffer;
+ Move<VkBuffer> m_vertexBuffer;
+ Move<VkBuffer> m_resultBuffer;
+ de::MovePtr<Allocation> m_vertexBufferAllocation;
+ de::MovePtr<Allocation> m_resultBufferAllocation;
+ Move<VkDescriptorPool> m_descriptorPool;
+ Move<VkDescriptorSetLayout> m_descriptorSetLayout;
+ Move<VkDescriptorSet> m_descriptorSet;
+ Move<VkShaderModule> m_vertexShaderModule;
+ Move<VkShaderModule> m_fragmentShaderModule;
+ Move<VkPipelineLayout> m_pipelineLayout;
+ Move<VkPipeline> m_pipeline;
+ Move<VkCommandPool> m_cmdPool;
+ Move<VkCommandBuffer> m_cmdBuffer;
+};
+
+class ExternalMemoryHostSynchronizationTestInstance : public ExternalMemoryHostRenderImageTestInstance
+{
+public:
+ ExternalMemoryHostSynchronizationTestInstance (Context& context, TestParams testParams);
+protected:
+ virtual tcu::TestStatus iterate (void);
+ void prepareBufferForHostAccess (void);
+ void copyResultBuffertoBuffer (void);
+ void submitCommands (VkCommandBuffer commandBuffer, VkFence fence);
+ Move<VkBuffer> createDataBuffer (void);
+ void fillBuffer (void);
+
+ Move<VkBuffer> m_dataBuffer;
+ Move<VkCommandPool> m_cmdPoolCopy;
+ Move<VkCommandBuffer> m_cmdBufferCopy;
+ Move<VkFence> m_fence_1;
+ Move<VkFence> m_fence_2;
+ Move<VkEvent> m_event;
+};
+
+ExternalMemoryHostBaseTestInstance::ExternalMemoryHostBaseTestInstance (Context& context, VkDeviceSize allocationSize)
+ : TestInstance (context)
+ , m_vki (m_context.getInstanceInterface())
+ , m_vkd (m_context.getDeviceInterface())
+ , m_log (m_context.getTestContext().getLog())
+ , m_device (m_context.getDevice())
+ , m_physicalDevice (m_context.getPhysicalDevice())
+ , m_queue (m_context.getUniversalQueue())
+ , m_memoryProps (getPhysicalDeviceMemoryProperties(m_vki, m_physicalDevice))
+ , m_minImportedHostPointerAlignment (getMinImportedHostPointerAlignment())
+ , m_allocationSize (m_minImportedHostPointerAlignment * allocationSize)
+ , m_allocator (m_context.getDefaultAllocator())
+{
+ if (!isDeviceExtensionSupported(context.getUsedApiVersion(), context.getDeviceExtensions(), "VK_EXT_external_memory_host"))
+ throw tcu::NotSupportedError("VK_EXT_external_memory_host is not supported");
+
+ m_hostMemoryAlloc = deAlignedMalloc((size_t)m_allocationSize, (size_t)m_minImportedHostPointerAlignment);
+
+ if (!m_hostMemoryAlloc)
+ TCU_FAIL("Failed to allocate memory block.");
+
+ DE_ASSERT(deIsAlignedPtr(m_hostMemoryAlloc, (deUintptr)m_minImportedHostPointerAlignment));
+}
+
+ExternalMemoryHostBaseTestInstance::~ExternalMemoryHostBaseTestInstance (void)
+{
+ deAlignedFree(m_hostMemoryAlloc);
+}
+
+VkDeviceSize ExternalMemoryHostBaseTestInstance::getMinImportedHostPointerAlignment (void)
+{
+ VkPhysicalDeviceExternalMemoryHostPropertiesEXT externalMemoryHostProperties =
+ {
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT, //VkStructureType sType
+ DE_NULL, //void* pNext
+ 0 //VkDeviceSize minImportedHostPointerAlignment
+ };
+
+ VkPhysicalDeviceProperties2 propertiesDeviceProperties2;
+ propertiesDeviceProperties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
+ propertiesDeviceProperties2.pNext = &externalMemoryHostProperties;
+
+ m_vki.getPhysicalDeviceProperties2(m_physicalDevice, &propertiesDeviceProperties2);
+
+ m_log << tcu::TestLog::Message << "VkPhysicalDeviceExternalMemoryHostPropertiesEXT::minImportedHostPointerAlignment is "
+ << externalMemoryHostProperties.minImportedHostPointerAlignment << tcu::TestLog::EndMessage;
+
+ if (externalMemoryHostProperties.minImportedHostPointerAlignment > 65536)
+ TCU_FAIL("minImportedHostPointerAlignment is exceeding the supported limit");
+
+ return externalMemoryHostProperties.minImportedHostPointerAlignment;
+}
+
+deUint32 ExternalMemoryHostBaseTestInstance::getHostPointerMemoryTypeBits (void* hostPointer)
+{
+ VkExternalMemoryHandleTypeFlagBits externalMemoryHandleTypeFlagBits = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT;
+
+ VkMemoryHostPointerPropertiesEXT memoryHostPointerProperties;
+ memoryHostPointerProperties.sType = VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT;
+ memoryHostPointerProperties.pNext = DE_NULL;
+
+ VK_CHECK(m_vkd.getMemoryHostPointerPropertiesEXT(m_device, externalMemoryHandleTypeFlagBits, hostPointer, &memoryHostPointerProperties));
+
+ m_log << tcu::TestLog::Message << "memoryTypeBits value: " << memoryHostPointerProperties.memoryTypeBits << tcu::TestLog::EndMessage;
+
+ return memoryHostPointerProperties.memoryTypeBits;
+}
+
+Move<VkDeviceMemory> ExternalMemoryHostBaseTestInstance::allocateMemoryFromHostPointer (deUint32 memoryTypeIndex)
+{
+ VkImportMemoryHostPointerInfoEXT importMemoryHostPointerInfo;
+ importMemoryHostPointerInfo.sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT;
+ importMemoryHostPointerInfo.pNext = DE_NULL;
+ importMemoryHostPointerInfo.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT;
+ importMemoryHostPointerInfo.pHostPointer = m_hostMemoryAlloc;
+
+ VkMemoryAllocateInfo memoryAllocateInfo;
+ memoryAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
+ memoryAllocateInfo.pNext = &importMemoryHostPointerInfo;
+ memoryAllocateInfo.allocationSize = m_allocationSize;
+ memoryAllocateInfo.memoryTypeIndex = memoryTypeIndex;
+
+ return allocateMemory(m_vkd, m_device, &memoryAllocateInfo, DE_NULL);
+}
+
+void ExternalMemoryHostBaseTestInstance::logMemoryTypeIndexPropertyFlags (deUint32 index)
+{
+ m_log << tcu::TestLog::Message << "Memory Type index " << index << " property flags:" << tcu::TestLog::EndMessage;
+ m_log << tcu::TestLog::Message << getMemoryPropertyFlagsStr(m_memoryProps.memoryTypes[index].propertyFlags) << tcu::TestLog::EndMessage;
+}
+
+bool ExternalMemoryHostBaseTestInstance::findMemoryTypeIndexToTest (deUint32 hostPointerMemoryTypeBits, deUint32* outMemoryTypeIndexToTest)
+{
+ for (deUint32 bitMaskPosition = 0; bitMaskPosition < VK_MAX_MEMORY_TYPES; bitMaskPosition++)
+ {
+ if (isBitSet(hostPointerMemoryTypeBits, bitMaskPosition))
+ {
+ logMemoryTypeIndexPropertyFlags(bitMaskPosition);
+ *outMemoryTypeIndexToTest = bitMaskPosition;
+ return true;
+ }
+ }
+ return false;
+}
+
+tcu::TestStatus ExternalMemoryHostBaseTestInstance::iterate (void)
+{
+ deUint32 hostPointerMemoryTypeBits;
+ deUint32 memoryTypeIndexToTest;
+
+ //realocate to meet requirements for host memory alignment
+ m_hostMemoryAlloc = deAlignedRealloc(m_hostMemoryAlloc, (size_t)m_minImportedHostPointerAlignment, (size_t)m_minImportedHostPointerAlignment);
+ m_allocationSize = m_minImportedHostPointerAlignment;
+
+ //check if reallocation is successfull
+ if (!m_hostMemoryAlloc)
+ TCU_FAIL("Failed to reallocate memory block.");
+
+ DE_ASSERT(deIsAlignedPtr(m_hostMemoryAlloc, (deUintptr)m_minImportedHostPointerAlignment));
+
+ //find the usable memory type index
+ hostPointerMemoryTypeBits = getHostPointerMemoryTypeBits(m_hostMemoryAlloc);
+ if (findMemoryTypeIndexToTest(hostPointerMemoryTypeBits, &memoryTypeIndexToTest))
+ m_deviceMemoryAllocatedFromHostPointer = allocateMemoryFromHostPointer(memoryTypeIndexToTest);
+ else
+ return tcu::TestStatus::fail("Fail");
+
+ return tcu::TestStatus::pass("Pass");
+}
+
+ExternalMemoryHostRenderImageTestInstance::ExternalMemoryHostRenderImageTestInstance (Context& context, TestParams testParams)
+ : ExternalMemoryHostBaseTestInstance (context, 1)
+ , m_testParams (testParams)
+{
+}
+
+tcu::TestStatus ExternalMemoryHostRenderImageTestInstance::iterate ()
+{
+ VkClearColorValue clearColorBlue = { { 0.0f, 0.0f, 1.0f, 1.0f } };
+ const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
+ deUint32 hostPointerMemoryTypeBits;
+ deUint32 memoryTypeIndexToTest;
+ VkMemoryRequirements imageMemoryRequirements;
+
+ m_image = createImage(VK_IMAGE_TILING_OPTIMAL);
+
+ //check memory requirements and reallocate memory if needed
+ imageMemoryRequirements = getImageMemoryRequirements(m_vkd, m_device, *m_image);
+
+ if (m_testParams.m_useOffset == false)
+ {
+ VkDeviceSize requiredSize = imageMemoryRequirements.size;
+ if (requiredSize > m_allocationSize)
+ {
+ //calculate new size, this must me a multiple of minImportedHostPointerAlignment
+ VkDeviceSize newHostAllocationSize = VkDeviceSize(deCeilFloatToInt32((float(requiredSize) / float(m_minImportedHostPointerAlignment))) * m_minImportedHostPointerAlignment);
+
+ m_log << tcu::TestLog::Message << "Realloc needed (required size: " << requiredSize << "). " << "New host allocation size: " << newHostAllocationSize << ")."
+ << tcu::TestLog::EndMessage;
+ //realocate
+ m_hostMemoryAlloc = deAlignedRealloc(m_hostMemoryAlloc, (size_t)newHostAllocationSize, (size_t)m_minImportedHostPointerAlignment);
+ m_allocationSize = newHostAllocationSize;
+ }
+ }
+
+ if (m_testParams.m_useOffset == true)
+ {
+ VkDeviceSize requiredSize = imageMemoryRequirements.size + imageMemoryRequirements.alignment;
+ if (requiredSize > m_allocationSize)
+ {
+ VkDeviceSize newHostAllocationSize = VkDeviceSize(deCeilFloatToInt32((float(requiredSize) / float(m_minImportedHostPointerAlignment))) * m_minImportedHostPointerAlignment);
+
+ m_log << tcu::TestLog::Message << "Realloc needed (required size: " << requiredSize << "). " << "New host allocation size: " << newHostAllocationSize << ")."
+ << tcu::TestLog::EndMessage;
+ m_hostMemoryAlloc = deAlignedRealloc(m_hostMemoryAlloc, (size_t)newHostAllocationSize, (size_t)m_minImportedHostPointerAlignment);
+ m_allocationSize = newHostAllocationSize;
+ }
+ }
+ //check if reallocation is successfull
+ if (!m_hostMemoryAlloc)
+ TCU_FAIL("Failed to reallocate memory block.");
+
+ DE_ASSERT(deIsAlignedPtr(m_hostMemoryAlloc, (deUintptr)m_minImportedHostPointerAlignment));
+
+ //find the usable memory type index
+ hostPointerMemoryTypeBits = getHostPointerMemoryTypeBits(m_hostMemoryAlloc);
+ if (findMemoryTypeIndexToTest(hostPointerMemoryTypeBits, &memoryTypeIndexToTest))
+ m_deviceMemoryAllocatedFromHostPointer = allocateMemoryFromHostPointer(memoryTypeIndexToTest);
+ else
+ return tcu::TestStatus::fail("Fail");
+
+ VK_CHECK(m_vkd.bindImageMemory(m_device, *m_image, *m_deviceMemoryAllocatedFromHostPointer, (m_testParams.m_useOffset ? imageMemoryRequirements.alignment : 0)));
+
+ m_imageView = createImageView();
+ m_renderPass = createRenderPass();
+ m_framebuffer = createFramebuffer();
+ m_vertexBuffer = createBindMemoryInitializeVertexBuffer();
+ m_resultBuffer = createBindMemoryResultBuffer();
+
+ vk::DescriptorSetLayoutBuilder builder;
+
+ builder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_ALL);
+
+ m_descriptorSetLayout = builder.build(m_vkd, m_device, (vk::VkDescriptorSetLayoutCreateFlags)0);
+
+ m_descriptorPool = DescriptorPoolBuilder().addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
+ .build(m_vkd, m_device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
+
+ m_pipelineLayout = createPipelineLayout();
+ m_descriptorSet = createAndUpdateDescriptorSet();
+
+ m_vertexShaderModule = createShaderModule(m_vkd, m_device, m_context.getBinaryCollection().get("position_only.vert"), 0);
+ m_fragmentShaderModule = createShaderModule(m_vkd, m_device, m_context.getBinaryCollection().get("only_color_out.frag"), 0);
+
+
+ m_pipeline = createPipeline();
+
+ m_cmdPool = createCommandPool(m_vkd, m_device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
+ m_cmdBuffer = allocateCommandBuffer(m_vkd, m_device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
+
+
+ beginCommandBuffer(m_vkd, *m_cmdBuffer);
+
+ clear(clearColorBlue);
+ draw();
+ copyResultImagetoBuffer();
+
+ endCommandBuffer(m_vkd, *m_cmdBuffer);
+
+ submitCommandsAndWait(m_vkd, m_device, m_queue, *m_cmdBuffer);
+
+ tcu::ConstPixelBufferAccess result(mapVkFormat(m_testParams.m_format), tcu::IVec3(100,100,1), m_resultBufferAllocation->getHostPtr());
+
+ std::vector<float> referenceData(40000, 0);
+ tcu::PixelBufferAccess reference(mapVkFormat(m_testParams.m_format), tcu::IVec3(100, 100, 1), referenceData.data());
+
+ prepareReferenceImage(reference);
+
+ if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Comparison", "Comparison", reference, result, tcu::Vec4(0.01f), tcu::COMPARE_LOG_ON_ERROR))
+ return tcu::TestStatus::fail("Fail");
+
+ return tcu::TestStatus::pass("Pass");
+}
+
+Move<VkImage> ExternalMemoryHostRenderImageTestInstance::createImage (VkImageTiling tiling)
+{
+ const VkImageCreateInfo imageCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType
+ DE_NULL, // const void* pNext
+ DE_NULL, // VkImageCreateFlags flags
+ VK_IMAGE_TYPE_2D, // VkImageType imageType
+ m_testParams.m_format, // VkFormat format
+ { 100, 100, 1 }, // VkExtent3D extent
+ 1, // deUint32 mipLevels
+ 1, // deUint32 arrayLayers
+ VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
+ tiling, // VkImageTiling tiling
+ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
+ VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
+ VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage
+ VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode
+ 0, // deUint32 queueFamilyIndexCount
+ DE_NULL, // const deUint32* pQueueFamilyIndices
+ VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout
+ };
+
+ return vk::createImage(m_vkd, m_device, &imageCreateInfo, DE_NULL);
+}
+
+Move<VkFramebuffer> ExternalMemoryHostRenderImageTestInstance::createFramebuffer ()
+{
+ const VkFramebufferCreateInfo framebufferCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType
+ DE_NULL, // const void* pNext
+ (VkFramebufferCreateFlags)0,
+ *m_renderPass, // VkRenderPass renderPass
+ 1, // deUint32 attachmentCount
+ &m_imageView.get(), // const VkImageView* pAttachments
+ 100, // deUint32 width
+ 100, // deUint32 height
+ 1 // deUint32 layers
+ };
+ return vk::createFramebuffer(m_vkd, m_device, &framebufferCreateInfo);
+}
+
+Move<VkImageView> ExternalMemoryHostRenderImageTestInstance::createImageView ()
+{
+ const VkImageViewCreateInfo imageViewCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType
+ DE_NULL, // const void* pNext
+ 0, // VkImageViewCreateFlags flags
+ *m_image, // VkImage image
+ VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType
+ m_testParams.m_format, // VkFormat format
+ { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A}, // VkComponentMapping components
+ { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } // VkImageSubresourceRange subresourceRange
+ };
+ return vk::createImageView(m_vkd, m_device, &imageViewCreateInfo);
+}
+
+Move<VkBuffer> ExternalMemoryHostRenderImageTestInstance::createBindMemoryInitializeVertexBuffer ()
+{
+ Move<VkBuffer> buffer;
+ float triangleData[] = { -1.0f, -1.0f, 0.0f, 1.0f,
+ -1.0f, 1.0f, 0.0f, 1.0f,
+ 0.0f, 1.0f, 0.0f, 1.0f,
+ 0.0f, -1.0f, 0.0f, 1.0f };
+ const VkBufferCreateInfo vertexBufferCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType
+ DE_NULL, // const void* pNext
+ 0, // VkBufferCreateFlags flag
+ sizeof(triangleData), // VkDeviceSize size
+ VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, // VkBufferUsageFlags usage
+ VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode
+ 0, // deUint32 queueFamilyCount
+ DE_NULL // const deUint32* pQueueFamilyIndices
+ };
+ buffer = vk::createBuffer(m_vkd, m_device, &vertexBufferCreateInfo, DE_NULL);
+ const VkMemoryRequirements bufferMemoryRequirements = getBufferMemoryRequirements(m_vkd, m_device, *buffer);
+ m_vertexBufferAllocation = m_allocator.allocate(bufferMemoryRequirements, MemoryRequirement::HostVisible);
+
+ VK_CHECK(m_vkd.bindBufferMemory(m_device, *buffer, m_vertexBufferAllocation->getMemory(), m_vertexBufferAllocation->getOffset()));
+
+ void* const mapPtr = m_vertexBufferAllocation->getHostPtr();
+
+ deMemcpy(mapPtr, triangleData, sizeof(triangleData));
+ flushMappedMemoryRange(m_vkd, m_device, m_vertexBufferAllocation->getMemory(), m_vertexBufferAllocation->getOffset(), sizeof(triangleData));
+
+ return buffer;
+}
+
+Move<VkBuffer> ExternalMemoryHostRenderImageTestInstance::createBindMemoryResultBuffer ()
+{
+ Move<VkBuffer> buffer;
+ VkDeviceSize size = 10000 * vk::mapVkFormat(m_testParams.m_format).getPixelSize();
+
+ const VkBufferCreateInfo resultBufferCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType
+ DE_NULL, // const void* pNext
+ 0, // VkBufferCreateFlags flags
+ size, // VkDeviceSize size
+ VK_BUFFER_USAGE_TRANSFER_SRC_BIT |
+ VK_BUFFER_USAGE_TRANSFER_DST_BIT, // VkBufferUsageFlags usage
+ VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode
+ 0, // deUint32 queueFamilyCount
+ DE_NULL // const deUint32* pQueueFamilyIndices
+ };
+ buffer = vk::createBuffer(m_vkd, m_device, &resultBufferCreateInfo, DE_NULL);
+
+ const VkMemoryRequirements bufferMemoryRequirements = getBufferMemoryRequirements(m_vkd, m_device, *buffer);
+ m_resultBufferAllocation = m_allocator.allocate(bufferMemoryRequirements, MemoryRequirement::HostVisible);
+
+ VK_CHECK(m_vkd.bindBufferMemory(m_device, *buffer, m_resultBufferAllocation->getMemory(), m_resultBufferAllocation->getOffset()));
+
+ return buffer;
+}
+
+Move<VkDescriptorSet> ExternalMemoryHostRenderImageTestInstance::createAndUpdateDescriptorSet ()
+{
+ Move<VkDescriptorSet> descriptorSet;
+ VkDescriptorBufferInfo descriptorInfo;
+
+ const VkDescriptorSetAllocateInfo allocInfo =
+ {
+ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType sType
+ DE_NULL, // const void* pNext
+ *m_descriptorPool, // VkDescriptorPool descriptorPool
+ 1u, // deUint32 setLayoutCount
+ &(m_descriptorSetLayout.get()) // const VkDescriptorSetLayout* pSetLayouts
+ };
+
+ descriptorSet = allocateDescriptorSet(m_vkd, m_device, &allocInfo);
+ descriptorInfo = makeDescriptorBufferInfo(*m_vertexBuffer, (VkDeviceSize)0u, sizeof(float) * 16);
+
+ DescriptorSetUpdateBuilder()
+ .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorInfo)
+ .update(m_vkd, m_device);
+
+ return descriptorSet;
+}
+
+Move<VkPipelineLayout> ExternalMemoryHostRenderImageTestInstance::createPipelineLayout ()
+{
+ const VkPipelineLayoutCreateInfo pipelineLayoutParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType
+ DE_NULL, // const void* pNext
+ (VkPipelineLayoutCreateFlags)0, // VkPipelineLayoutCreateFlags flags
+ 1u, // deUint32 descriptorSetCount
+ &(m_descriptorSetLayout.get()), // const VkDescriptorSetLayout* pSetLayouts
+ 0u, // deUint32 pushConstantRangeCount
+ DE_NULL // const VkPushConstantRange* pPushConstantRanges
+ };
+
+ return vk::createPipelineLayout(m_vkd, m_device, &pipelineLayoutParams);
+}
+
+Move<VkPipeline> ExternalMemoryHostRenderImageTestInstance::createPipeline ()
+{
+ Move<VkPipeline> pipeline;
+ const std::vector<VkViewport> viewports(1, makeViewport(tcu::UVec2(100,100)));
+ const std::vector<VkRect2D> scissors(1, makeRect2D(tcu::UVec2(100, 100)));
+ const VkPrimitiveTopology topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN;
+ const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType
+ DE_NULL, // const void* pNext
+ 0u, // vkPipelineVertexInputStateCreateFlags flags
+ 0u, // deUint32 bindingCount
+ DE_NULL, // const VkVertexInputBindingDescription* pVertexBindingDescriptions
+ 0u, // deUint32 attributeCount
+ DE_NULL, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions
+ };
+
+ return makeGraphicsPipeline( m_vkd, // const DeviceInterface& vk
+ m_device, // const VkDevice device
+ *m_pipelineLayout, // const VkPipelineLayout pipelineLayout
+ *m_vertexShaderModule, // const VkShaderModule vertexShaderModule
+ DE_NULL, // const VkShaderModule tessellationControlShaderModule
+ DE_NULL, // const VkShaderModule tessellationEvalShaderModule
+ DE_NULL, // const VkShaderModule geometryShaderModule
+ *m_fragmentShaderModule, // const VkShaderModule fragmentShaderModule
+ *m_renderPass, // const VkRenderPass renderPass
+ viewports, // const std::vector<VkViewport>& viewports
+ scissors, // const std::vector<VkRect2D>& scissors
+ topology, // const VkPrimitiveTopology topology
+ 0u, // const deUint32 subpass
+ 0u, // const deUint32 patchControlPoints
+ &vertexInputStateParams); // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo
+}
+
+void ExternalMemoryHostRenderImageTestInstance::clear (VkClearColorValue color)
+{
+ const struct VkImageSubresourceRange subRangeColor =
+ {
+ VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask
+ 0u, // deUint32 baseMipLevel
+ 1u, // deUint32 mipLevels
+ 0u, // deUint32 baseArrayLayer
+ 1u, // deUint32 arraySize
+ };
+ const VkImageMemoryBarrier imageBarrier =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType
+ DE_NULL, // const void* pNext
+ 0u, // VkAccessFlags srcAccessMask
+ VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask
+ VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout
+ VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex
+ VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex
+ *m_image, // VkImage image
+ subRangeColor // VkImageSubresourceRange subresourceRange
+ };
+
+ m_vkd.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, DE_FALSE, 0u, DE_NULL, 0u, DE_NULL, 1u, &imageBarrier);
+ m_vkd.cmdClearColorImage(*m_cmdBuffer, *m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &color, 1, &subRangeColor);
+}
+
+void ExternalMemoryHostRenderImageTestInstance::draw ()
+{
+ const struct VkImageSubresourceRange subRangeColor =
+ {
+ VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask
+ 0u, // deUint32 baseMipLevel
+ 1u, // deUint32 mipLevels
+ 0u, // deUint32 baseArrayLayer
+ 1u, // deUint32 arraySize
+ };
+ const VkImageMemoryBarrier imageBarrier =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType
+ DE_NULL, // const void* pNext
+ VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask
+ VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout
+ VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex
+ VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex
+ *m_image, // VkImage image
+ subRangeColor // VkImageSubresourceRange subresourceRange
+ };
+ m_vkd.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, DE_FALSE, 0u, DE_NULL, 0u, DE_NULL, 1u, &imageBarrier);
+
+ beginRenderPass(m_vkd, *m_cmdBuffer, *m_renderPass, *m_framebuffer, makeRect2D(0, 0, 75, 100), tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
+ m_vkd.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
+ m_vkd.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0, 1, &(*m_descriptorSet), 0, DE_NULL);
+ m_vkd.cmdDraw(*m_cmdBuffer, 4, 1, 0, 0);
+ endRenderPass(m_vkd, *m_cmdBuffer);
+}
+
+void ExternalMemoryHostRenderImageTestInstance::copyResultImagetoBuffer ()
+{
+ const struct VkImageSubresourceRange subRangeColor =
+ {
+ VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask
+ 0u, // deUint32 baseMipLevel
+ 1u, // deUint32 mipLevels
+ 0u, // deUint32 baseArrayLayer
+ 1u, // deUint32 arraySize
+ };
+ const VkImageMemoryBarrier imageBarrier =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType
+ DE_NULL, // const void* pNext
+ VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask
+ VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout
+ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout
+ VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex
+ VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex
+ *m_image, // VkImage image
+ subRangeColor // VkImageSubresourceRange subresourceRange
+ };
+ m_vkd.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, DE_FALSE, 0u, DE_NULL, 0u, DE_NULL, 1u, &imageBarrier);
+
+ const VkBufferImageCopy region_all =
+ {
+ 0, // VkDeviceSize bufferOffset
+ 0, // deUint32 bufferRowLength
+ 0, // deUint32 bufferImageHeight
+ { vk::VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }, // VkImageSubresourceLayers imageSubresource
+ { 0, 0, 0 }, // VkOffset3D imageOffset
+ { 100, 100, 1 } }; // VkExtent3D imageExtent
+
+ m_vkd.cmdCopyImageToBuffer(*m_cmdBuffer, *m_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *m_resultBuffer, 1, ®ion_all);
+}
+
+void ExternalMemoryHostRenderImageTestInstance::prepareReferenceImage (tcu::PixelBufferAccess& reference)
+{
+ for (int w=0; w < 100; w++)
+ for (int h = 0; h < 100; h++)
+ {
+ if (w < 50) reference.setPixel(tcu::Vec4(0, 1, 0, 1), w, h);
+ if ((w >= 50) && (w < 75)) reference.setPixel(tcu::Vec4(1, 0, 0, 1), w, h);
+ if (w >=75) reference.setPixel(tcu::Vec4(0, 0, 1, 1), w, h);
+ }
+}
+
+Move<VkRenderPass> ExternalMemoryHostRenderImageTestInstance::createRenderPass ()
+{
+ const VkAttachmentDescription colorAttachmentDescription =
+ {
+ (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags
+ m_testParams.m_format, // VkFormat format
+ VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
+ VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp
+ VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp
+ VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp
+ VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout
+ };
+
+ std::vector<VkAttachmentDescription> attachmentDescriptions;
+ attachmentDescriptions.push_back(colorAttachmentDescription);
+
+ const VkAttachmentReference colorAttachmentRef =
+ {
+ 0u, // deUint32 attachment
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout
+ };
+
+ const VkSubpassDescription subpassDescription =
+ {
+ (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags
+ VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint
+ 0u, // deUint32 inputAttachmentCount
+ DE_NULL, // const VkAttachmentReference* pInputAttachments
+ 1u, // deUint32 colorAttachmentCount
+ &colorAttachmentRef, // const VkAttachmentReference* pColorAttachments
+ DE_NULL, // const VkAttachmentReference* pResolveAttachments
+ DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment
+ 0u, // deUint32 preserveAttachmentCount
+ DE_NULL // const deUint32* pPreserveAttachments
+ };
+
+ const VkRenderPassCreateInfo renderPassInfo =
+ {
+ VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType
+ DE_NULL, // const void* pNext
+ (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags
+ (deUint32)attachmentDescriptions.size(), // deUint32 attachmentCount
+ &attachmentDescriptions[0], // const VkAttachmentDescription* pAttachments
+ 1u, // deUint32 subpassCount
+ &subpassDescription, // const VkSubpassDescription* pSubpasses
+ 0u, // deUint32 dependencyCount
+ DE_NULL // const VkSubpassDependency* pDependencies
+ };
+
+ return vk::createRenderPass(m_vkd, m_device, &renderPassInfo);
+}
+
+ExternalMemoryHostSynchronizationTestInstance::ExternalMemoryHostSynchronizationTestInstance (Context& context, TestParams testParams)
+ : ExternalMemoryHostRenderImageTestInstance (context, testParams)
+{
+}
+
+tcu::TestStatus ExternalMemoryHostSynchronizationTestInstance::iterate ()
+{
+ DE_ASSERT(m_testParams.m_format == VK_FORMAT_R8G8B8A8_UNORM);
+
+ const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
+ const VkDeviceSize dataBufferSize = 10000 * vk::mapVkFormat(m_testParams.m_format).getPixelSize();
+ void* pointerReturnedByMapMemory;
+ deUint32 hostPointerMemoryTypeBits;
+ deUint32 memoryTypeIndexToTest;
+ VkMemoryRequirements bufferMemoryRequirements;
+
+ m_dataBuffer = createDataBuffer();
+
+ //check memory requirements
+ bufferMemoryRequirements = getBufferMemoryRequirements(m_vkd, m_device, *m_dataBuffer);
+ VkDeviceSize requiredSize = bufferMemoryRequirements.size;
+ //reallocate memory if needed
+ if (requiredSize > m_allocationSize)
+ {
+ VkDeviceSize newHostAllocationSize = VkDeviceSize(deCeilFloatToInt32((float(requiredSize) / float(m_minImportedHostPointerAlignment))) * m_minImportedHostPointerAlignment);
+
+ m_log << tcu::TestLog::Message << "Realloc needed (required size: " << requiredSize << "). "
+ << "New host allocation size: " << newHostAllocationSize << ")." << tcu::TestLog::EndMessage;
+
+ m_hostMemoryAlloc = deAlignedRealloc(m_hostMemoryAlloc, (size_t)newHostAllocationSize, (size_t)m_minImportedHostPointerAlignment);
+ m_allocationSize = newHostAllocationSize;
+ }
+
+ //check if reallocation is successfull
+ if (!m_hostMemoryAlloc)
+ TCU_FAIL("Failed to reallocate memory block.");
+
+ DE_ASSERT(deIsAlignedPtr(m_hostMemoryAlloc, (deUintptr)m_minImportedHostPointerAlignment));
+
+ //find the usable memory type index
+ hostPointerMemoryTypeBits = getHostPointerMemoryTypeBits(m_hostMemoryAlloc);
+ if (findMemoryTypeIndexToTest(hostPointerMemoryTypeBits, &memoryTypeIndexToTest))
+ m_deviceMemoryAllocatedFromHostPointer = allocateMemoryFromHostPointer(memoryTypeIndexToTest);
+ else
+ return tcu::TestStatus::fail("Fail");
+
+ VK_CHECK(m_vkd.bindBufferMemory(m_device, *m_dataBuffer, *m_deviceMemoryAllocatedFromHostPointer, 0));
+
+ m_resultBuffer = createBindMemoryResultBuffer();
+ m_cmdPool = createCommandPool(m_vkd, m_device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
+ m_cmdBuffer = allocateCommandBuffer(m_vkd, m_device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
+ m_cmdBufferCopy = allocateCommandBuffer(m_vkd, m_device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
+
+ m_event = createEvent(m_vkd, m_device);
+ m_fence_1 = createFence(m_vkd, m_device);
+ m_fence_2 = createFence(m_vkd, m_device);
+
+ //record first command buffer
+ beginCommandBuffer(m_vkd, *m_cmdBuffer);
+ fillBuffer();
+ prepareBufferForHostAccess();
+ endCommandBuffer(m_vkd, *m_cmdBuffer);
+
+ //record second command buffer
+ beginCommandBuffer(m_vkd, *m_cmdBufferCopy);
+ copyResultBuffertoBuffer();
+ endCommandBuffer(m_vkd, *m_cmdBufferCopy);
+
+ submitCommands(*m_cmdBuffer, *m_fence_1);
+ submitCommands(*m_cmdBufferCopy, *m_fence_2);
+
+ //wait for fence_1 and modify image on host
+ VK_CHECK(m_vkd.waitForFences(m_device, 1u, &m_fence_1.get(), DE_TRUE, ~0ull));
+ pointerReturnedByMapMemory = mapMemory(m_vkd, m_device, *m_deviceMemoryAllocatedFromHostPointer, 0, dataBufferSize, 0);
+ invalidateMappedMemoryRange(m_vkd, m_device, *m_deviceMemoryAllocatedFromHostPointer, 0, dataBufferSize);
+ tcu::PixelBufferAccess bufferSurface(mapVkFormat(m_testParams.m_format), 100, 100, 1, (100 * vk::mapVkFormat(m_testParams.m_format).getPixelSize()), 0, m_hostMemoryAlloc);
+ prepareReferenceImage(bufferSurface);
+ flushMappedMemoryRange(m_vkd, m_device, *m_deviceMemoryAllocatedFromHostPointer, 0, dataBufferSize);
+ //compare memory pointed by both pointers
+ if (deMemCmp(m_hostMemoryAlloc, pointerReturnedByMapMemory, (size_t)dataBufferSize) != 0)
+ TCU_FAIL("Failed memcmp check.");
+ m_vkd.unmapMemory(m_device, *m_deviceMemoryAllocatedFromHostPointer);
+ VK_CHECK(m_vkd.setEvent(m_device, *m_event));
+
+ //wait for fence_2 before checking result
+ VK_CHECK(m_vkd.waitForFences(m_device, 1u, &m_fence_2.get(), DE_TRUE, ~0ull));
+
+ void * bufferDataPointer = static_cast<char*>(m_resultBufferAllocation->getHostPtr()) + m_resultBufferAllocation->getOffset();
+ tcu::ConstPixelBufferAccess result(mapVkFormat(m_testParams.m_format), tcu::IVec3(100, 100, 1), bufferDataPointer);
+
+ std::vector<float> referenceData((unsigned int)dataBufferSize, 0);
+ tcu::PixelBufferAccess reference(mapVkFormat(m_testParams.m_format), tcu::IVec3(100, 100, 1), referenceData.data());
+
+ prepareReferenceImage(reference);
+
+ if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Comparison", "Comparison", reference, result, tcu::Vec4(0.01f), tcu::COMPARE_LOG_ON_ERROR))
+ return tcu::TestStatus::fail("Fail");
+
+ return tcu::TestStatus::pass("Pass");
+}
+
+void ExternalMemoryHostSynchronizationTestInstance::prepareBufferForHostAccess ()
+{
+ VkDeviceSize size = 10000 * vk::mapVkFormat(m_testParams.m_format).getPixelSize();
+ const VkBufferMemoryBarrier bufferBarrier =
+ {
+ VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
+ VK_ACCESS_HOST_WRITE_BIT, // VkAccessFlags dstAccessMask;
+ VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
+ VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
+ *m_dataBuffer, // VkBuffer buffer;
+ 0u, // VkDeviceSize offset;
+ size // VkDeviceSize size;
+ };
+
+ m_vkd.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, DE_FALSE, 0u, DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL);
+}
+
+void ExternalMemoryHostSynchronizationTestInstance::copyResultBuffertoBuffer ()
+{
+ VkDeviceSize size = 10000 * vk::mapVkFormat(m_testParams.m_format).getPixelSize();
+ const VkBufferMemoryBarrier bufferBarrier =
+ {
+ VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ VK_ACCESS_HOST_WRITE_BIT, // VkAccessFlags srcAccessMask;
+ VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask;
+ VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
+ VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
+ *m_dataBuffer, // VkBuffer buffer;
+ 0u, // VkDeviceSize offset;
+ size // VkDeviceSize size;
+ };
+
+ const VkBufferCopy region_all =
+ {
+ 0, //VkDeviceSize srcOffset;
+ 0, //VkDeviceSize dstOffset;
+ size //VkDeviceSize size;
+ };
+
+ m_vkd.cmdWaitEvents(*m_cmdBufferCopy, 1, &m_event.get(), VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, DE_NULL, 1, &bufferBarrier, 0, DE_NULL);
+ m_vkd.cmdCopyBuffer(*m_cmdBufferCopy, *m_dataBuffer, *m_resultBuffer, 1, ®ion_all);
+}
+
+void ExternalMemoryHostSynchronizationTestInstance::submitCommands (VkCommandBuffer commandBuffer, VkFence fence)
+{
+ const VkSubmitInfo submitInfo =
+ {
+ VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType
+ DE_NULL, // const void* pNext
+ 0u, // deUint32 waitSemaphoreCount
+ DE_NULL, // const VkSemaphore* pWaitSemaphores
+ (const VkPipelineStageFlags*)DE_NULL, // const VkPipelineStageFlags* pWaitDstStageMask
+ 1u, // deUint32 commandBufferCount
+ &commandBuffer, // const VkCommandBuffer* pCommandBuffers
+ 0u, // deUint32 signalSemaphoreCount
+ DE_NULL, // const VkSemaphore* pSignalSemaphores
+ };
+
+ VK_CHECK(m_vkd.queueSubmit(m_queue, 1u, &submitInfo, fence));
+}
+
+Move<VkBuffer> ExternalMemoryHostSynchronizationTestInstance::createDataBuffer ()
+{
+ VkDeviceSize size = 10000 * vk::mapVkFormat(m_testParams.m_format).getPixelSize();
+ const VkBufferCreateInfo dataBufferCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType
+ DE_NULL, // const void* pNext
+ 0, // VkBufferCreateFlags flag
+ size, // VkDeviceSize size
+ VK_BUFFER_USAGE_TRANSFER_DST_BIT |
+ VK_BUFFER_USAGE_TRANSFER_SRC_BIT, // VkBufferUsageFlags usage
+ VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode
+ 0, // deUint32 queueFamilyCount
+ DE_NULL // const deUint32* pQueueFamilyIndices
+ };
+ return vk::createBuffer(m_vkd, m_device, &dataBufferCreateInfo, DE_NULL);
+}
+
+void ExternalMemoryHostSynchronizationTestInstance::fillBuffer ()
+{
+ VkDeviceSize size = 10000 * vk::mapVkFormat(m_testParams.m_format).getPixelSize();
+ const VkBufferMemoryBarrier bufferBarrier =
+ {
+ VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkAccessFlags srcAccessMask;
+ VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask;
+ VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
+ VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
+ *m_dataBuffer, // VkBuffer buffer;
+ 0u, // VkDeviceSize offset;
+ size // VkDeviceSize size;
+ };
+
+ m_vkd.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, DE_FALSE, 0u, DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL);
+ m_vkd.cmdFillBuffer(*m_cmdBuffer, *m_dataBuffer, 0, size, 0xFFFFFFFF);
+}
+
+struct AddPrograms
+{
+ void init (vk::SourceCollections& sources, TestParams testParams) const
+ {
+ //unused parameter
+ DE_UNREF(testParams);
+
+ const char* const vertexShader =
+ "#version 430\n"
+
+ "layout(std430, binding = 0) buffer BufferPos {\n"
+ "vec4 p[100];\n"
+ "} pos;\n"
+
+ "out gl_PerVertex{\n"
+ "vec4 gl_Position;\n"
+ "};\n"
+
+ "void main() {\n"
+ "gl_Position = pos.p[gl_VertexIndex];\n"
+ "}\n";
+
+ sources.glslSources.add("position_only.vert")
+ << glu::VertexSource(vertexShader);
+
+ const char* const fragmentShader =
+ "#version 430\n"
+
+ "layout(location = 0) out vec4 my_FragColor;\n"
+
+ "void main() {\n"
+ "my_FragColor = vec4(0,1,0,1);\n"
+ "}\n";
+
+ sources.glslSources.add("only_color_out.frag")
+ << glu::FragmentSource(fragmentShader);
+ }
+};
+
+} // unnamed namespace
+
+tcu::TestCaseGroup* createMemoryExternalMemoryHostTests (tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "external_memory_host", "VK_EXT_external_memory_host extension tests."));
+ de::MovePtr<tcu::TestCaseGroup> simpleAllocation(new tcu::TestCaseGroup(testCtx, "simple_allocation", "simple allocation tests."));
+ de::MovePtr<tcu::TestCaseGroup> bind_image_memory_and_render(new tcu::TestCaseGroup(testCtx, "bind_image_memory_and_render", "render tests."));
+ de::MovePtr<tcu::TestCaseGroup> with_zero_offset(new tcu::TestCaseGroup(testCtx, "with_zero_offset", "bind object with zero offset specified"));
+ de::MovePtr<tcu::TestCaseGroup> with_non_zero_offset(new tcu::TestCaseGroup(testCtx, "with_non_zero_offset", "bind object with zero offset specified"));
+ de::MovePtr<tcu::TestCaseGroup> synchronization(new tcu::TestCaseGroup(testCtx, "synchronization", "synchronization tests."));
+
+ //test cases:
+ simpleAllocation->addChild(new InstanceFactory1<ExternalMemoryHostBaseTestInstance, VkDeviceSize> (testCtx, tcu::NODETYPE_SELF_VALIDATE, "minImportedHostPointerAlignment_x1",
+ "allocate minImportedHostPointerAlignment multiplied by 1", 1));
+ simpleAllocation->addChild(new InstanceFactory1<ExternalMemoryHostBaseTestInstance, VkDeviceSize> (testCtx, tcu::NODETYPE_SELF_VALIDATE, "minImportedHostPointerAlignment_x3",
+ "allocate minImportedHostPointerAlignment multiplied by 3", 3));
+ group ->addChild(simpleAllocation.release());
+
+ const VkFormat testFormats[] = {
+ VK_FORMAT_R8G8B8A8_UNORM,
+ VK_FORMAT_R16G16B16A16_UNORM,
+ VK_FORMAT_R16G16B16A16_SFLOAT,
+ VK_FORMAT_R32G32B32A32_SFLOAT
+ };
+
+ const std::string testNames[] = {
+ "r8g8b8a8_unorm",
+ "r16g16b16a16_unorm",
+ "r16g16b16a16_sfloat",
+ "r32g32b32a32_sfloat"
+ };
+
+ for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(testFormats); formatNdx++)
+ {
+ std::string testName = testNames[formatNdx];
+ with_zero_offset->addChild(new InstanceFactory1<ExternalMemoryHostRenderImageTestInstance, TestParams, AddPrograms> (testCtx, tcu::NODETYPE_SELF_VALIDATE,
+ testName, testName, AddPrograms(),
+ TestParams(testFormats[formatNdx])));
+ }
+ bind_image_memory_and_render->addChild(with_zero_offset.release());
+
+ for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(testFormats); formatNdx++)
+ {
+ std::string testName = testNames[formatNdx];
+ with_non_zero_offset->addChild(new InstanceFactory1<ExternalMemoryHostRenderImageTestInstance, TestParams, AddPrograms> (testCtx, tcu::NODETYPE_SELF_VALIDATE,
+ testName, testName, AddPrograms(),
+ TestParams(testFormats[formatNdx], true)));
+ }
+ bind_image_memory_and_render->addChild(with_non_zero_offset.release());
+
+ group->addChild(bind_image_memory_and_render.release());
+
+ synchronization->addChild(new InstanceFactory1<ExternalMemoryHostSynchronizationTestInstance, TestParams, AddPrograms> (testCtx, tcu::NODETYPE_SELF_VALIDATE,
+ "synchronization", "synchronization", AddPrograms(),
+ TestParams(testFormats[0], true)));
+ group->addChild(synchronization.release());
+ return group.release();
+}
+
+} // memory
+} // vkt