/*------------------------------------------------------------------------- * Vulkan Conformance Tests * ------------------------ * * Copyright (c) 2016 The Khronos Group Inc. * Copyright (c) 2016 Samsung Electronics Co., Ltd. * * 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 Memory Commitment tests *//*--------------------------------------------------------------------*/ #include "vktApiGetMemoryCommitment.hpp" #include "vkDeviceUtil.hpp" #include "vkQueryUtil.hpp" #include "vkRefUtil.hpp" #include "vkImageUtil.hpp" #include "vkMemUtil.hpp" #include "vkPrograms.hpp" #include "vktTestCase.hpp" #include "vkTypeUtil.hpp" #include "vkCmdUtil.hpp" #include "vkObjUtil.hpp" #include "tcuTestLog.hpp" using namespace vk; using tcu::TestLog; namespace vkt { namespace api { struct MemoryCommitmentCaseParams { deUint32 bufferSize; deUint32 bufferViewSize; deUint32 elementOffset; }; class MemoryCommitmentTestInstance : public vkt::TestInstance { public: MemoryCommitmentTestInstance (Context& context, MemoryCommitmentCaseParams testCase); tcu::TestStatus iterate (void); deUint32 getMemoryTypeIndex (VkMemoryPropertyFlags propertyFlag, VkPhysicalDeviceMemoryProperties pMemoryProperties); Move createCommandPool () const; Move allocatePrimaryCommandBuffer (VkCommandPool commandPool) const; bool isDeviceMemoryCommitmentOk (const VkMemoryRequirements memoryRequirements); private: const tcu::IVec2 m_renderSize; }; MemoryCommitmentTestInstance::MemoryCommitmentTestInstance(Context& context, MemoryCommitmentCaseParams testCase) : vkt::TestInstance (context) , m_renderSize (testCase.bufferViewSize, testCase.bufferViewSize) { } class MemoryCommitmentTestCase : public vkt::TestCase { public: MemoryCommitmentTestCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, MemoryCommitmentCaseParams memoryCommitmentTestInfo) : vkt::TestCase (testCtx, name, description) , m_memoryCommitmentTestInfo (memoryCommitmentTestInfo) {} virtual ~MemoryCommitmentTestCase(void){} virtual void initPrograms (SourceCollections& programCollection) const; virtual TestInstance* createInstance (Context& context) const { return new MemoryCommitmentTestInstance(context, m_memoryCommitmentTestInfo); } private: MemoryCommitmentCaseParams m_memoryCommitmentTestInfo; }; tcu::TestStatus MemoryCommitmentTestInstance::iterate(void) { const VkMemoryPropertyFlags propertyFlag = VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT; const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice(); const InstanceInterface& vki = m_context.getInstanceInterface(); const VkPhysicalDeviceMemoryProperties pMemoryProperties = getPhysicalDeviceMemoryProperties(vki,physicalDevice); const deUint32 memoryTypeIndex = getMemoryTypeIndex(propertyFlag, pMemoryProperties); Allocator& memAlloc = m_context.getDefaultAllocator(); bool isMemoryAllocationOK = false; const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); const VkComponentMapping componentMappingRGBA = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A }; const DeviceInterface& vkd = m_context.getDeviceInterface(); const Move cmdPool = createCommandPool(); const Move cmdBuffer = allocatePrimaryCommandBuffer(*cmdPool); const VkDevice device = m_context.getDevice(); Move colorAttachmentView; Move renderPass; Move framebuffer; Move descriptorSetLayout; Move pipelineLayout; Move vertexShaderModule; Move fragmentShaderModule; Move graphicsPipelines; if (memoryTypeIndex == static_cast(-1)) TCU_THROW(NotSupportedError, "Lazily allocated bit is not supported"); const VkImageCreateInfo imageParams = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; DE_NULL, // const void* pNext; 0u, // VkImageCreateFlags flags; VK_IMAGE_TYPE_2D, // VkImageType imageType; VK_FORMAT_R32_UINT, // VkFormat format; {256u, 256u, 1}, // VkExtent3D extent; 1u, // deUint32 mipLevels; 1u, // deUint32 arraySize; VK_SAMPLE_COUNT_1_BIT, // deUint32 samples; VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT, // VkImageUsageFlags usage; VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 1u, // deUint32 queueFamilyCount; &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; }; Move image = createImage(vkd, device, &imageParams); const VkMemoryRequirements memoryRequirements = getImageMemoryRequirements(vkd, device, *image); de::MovePtr imageAlloc = memAlloc.allocate(memoryRequirements, MemoryRequirement::LazilyAllocated); VK_CHECK(vkd.bindImageMemory(device, *image, imageAlloc->getMemory(), imageAlloc->getOffset())); const VkImageViewCreateInfo colorAttachmentViewParams = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType; DE_NULL, // const void* pNext; 0u, // VkImageViewCreateFlags flags; *image, // VkImage image; VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType; VK_FORMAT_R32_UINT, // VkFormat format; componentMappingRGBA, // VkComponentMapping components; { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u } // VkImageSubresourceRange subresourceRange; }; colorAttachmentView = createImageView(vkd, device, &colorAttachmentViewParams); // Create render pass renderPass = makeRenderPass(vkd, device, VK_FORMAT_R32_UINT); // Create framebuffer { const VkImageView attachmentBindInfos[1] = { *colorAttachmentView, }; const VkFramebufferCreateInfo framebufferParams = { VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType; DE_NULL, // const void* pNext; (VkFramebufferCreateFlags)0, *renderPass, // VkRenderPass renderPass; 1u, // deUint32 attachmentCount; attachmentBindInfos, // const VkImageView* pAttachments; (deUint32)m_renderSize.x(), // deUint32 width; (deUint32)m_renderSize.y(), // deUint32 height; 1u // deUint32 layers; }; framebuffer = createFramebuffer(vkd, device, &framebufferParams); } // Create descriptors { const VkDescriptorSetLayoutBinding layoutBindings[1] = { { 0u, // deUint32 binding; VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, // VkDescriptorType descriptorType; 1u, // deUint32 arraySize; VK_SHADER_STAGE_ALL, // VkShaderStageFlags stageFlags; DE_NULL // const VkSampler* pImmutableSamplers; }, }; const VkDescriptorSetLayoutCreateInfo descriptorLayoutParams = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // VkStructureType sType; DE_NULL, // cost void* pNexŧ; (VkDescriptorSetLayoutCreateFlags)0, DE_LENGTH_OF_ARRAY(layoutBindings), // deUint32 count; layoutBindings // const VkDescriptorSetLayoutBinding pBinding; }; descriptorSetLayout = createDescriptorSetLayout(vkd, device, &descriptorLayoutParams); } // Create pipeline layout { const VkPipelineLayoutCreateInfo pipelineLayoutParams = { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType; DE_NULL, // const void* pNext; (VkPipelineLayoutCreateFlags)0, 1u, // deUint32 descriptorSetCount; &*descriptorSetLayout, // const VkDescriptorSetLayout* pSetLayouts; 0u, // deUint32 pushConstantRangeCount; DE_NULL // const VkPushConstantRange* pPushConstantRanges; }; pipelineLayout = createPipelineLayout(vkd, device, &pipelineLayoutParams); } // Create shaders { vertexShaderModule = createShaderModule(vkd, device, m_context.getBinaryCollection().get("vert"), 0); fragmentShaderModule = createShaderModule(vkd, device, m_context.getBinaryCollection().get("frag"), 0); } // Create pipeline { const std::vector viewports (1, makeViewport(m_renderSize)); const std::vector scissors (1, makeRect2D(m_renderSize)); graphicsPipelines = makeGraphicsPipeline(vkd, // const DeviceInterface& vk device, // const VkDevice device *pipelineLayout, // const VkPipelineLayout pipelineLayout *vertexShaderModule, // const VkShaderModule vertexShaderModule DE_NULL, // const VkShaderModule tessellationControlModule DE_NULL, // const VkShaderModule tessellationEvalModule DE_NULL, // const VkShaderModule geometryShaderModule *fragmentShaderModule, // const VkShaderModule fragmentShaderModule *renderPass, // const VkRenderPass renderPass viewports, // const std::vector& viewports scissors); // const std::vector& scissors } // getMemoryCommitment isMemoryAllocationOK = isDeviceMemoryCommitmentOk(memoryRequirements); const deUint32 clearColor[4] = { 1u, 1u, 1u, 1u }; const VkClearAttachment clearAttachment = { VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; 0u, // deUint32 colorAttachment; makeClearValueColorU32(clearColor[0], clearColor[1], clearColor[2], clearColor[3]) // VkClearValue clearValue; }; const VkOffset2D offset = { 0, 0 }; const VkExtent2D extent = { 256u, 256u }; const VkRect2D rect = { offset, extent }; const VkClearRect clearRect = { rect, 0u, // baseArrayLayer 1u // layerCount }; // beginCommandBuffer beginCommandBuffer(vkd, *cmdBuffer); const VkImageMemoryBarrier initialImageBarrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; DE_NULL, // const void* pNext; 0, // VkMemoryOutputFlags outputMask; VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkMemoryInputFlags inputMask; VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout; VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout; VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex; image.get(), // VkImage image; { // VkImageSubresourceRange subresourceRange; VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; 0u, // deUint32 baseMipLevel; 1u, // deUint32 mipLevels; 0u, // deUint32 baseArraySlice; 1u // deUint32 arraySize; } }; vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &initialImageBarrier); beginRenderPass(vkd, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, 256u, 256u), tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f)); vkd.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipelines); // clearAttachments vkd.cmdClearAttachments(*cmdBuffer, 1, &clearAttachment, 1u, &clearRect); endRenderPass(vkd, *cmdBuffer); endCommandBuffer(vkd, *cmdBuffer); // queueSubmit const VkQueue queue = m_context.getUniversalQueue(); submitCommandsAndWait(vkd, device, queue, *cmdBuffer); // getMemoryCommitment isMemoryAllocationOK = (isMemoryAllocationOK && isDeviceMemoryCommitmentOk(memoryRequirements)) ? true : false; if (isMemoryAllocationOK) return tcu::TestStatus::pass("Pass"); return tcu::TestStatus::fail("Fail"); } class MemoryCommitmentAllocateOnlyTestInstance : public vkt::TestInstance { public: MemoryCommitmentAllocateOnlyTestInstance (Context& context); tcu::TestStatus iterate (void); }; class MemoryCommitmentAllocateOnlyTestCase : public vkt::TestCase { public: MemoryCommitmentAllocateOnlyTestCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description) : vkt::TestCase (testCtx, name, description) {} virtual ~MemoryCommitmentAllocateOnlyTestCase(void){} virtual TestInstance* createInstance (Context& context) const { return new MemoryCommitmentAllocateOnlyTestInstance(context); } }; MemoryCommitmentAllocateOnlyTestInstance::MemoryCommitmentAllocateOnlyTestInstance(Context& context) : vkt::TestInstance (context) { } tcu::TestStatus MemoryCommitmentAllocateOnlyTestInstance::iterate(void) { const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice(); const VkDevice device = m_context.getDevice(); const InstanceInterface& vki = m_context.getInstanceInterface(); const DeviceInterface& vkd = m_context.getDeviceInterface(); const VkPhysicalDeviceMemoryProperties pMemoryProperties = getPhysicalDeviceMemoryProperties(vki,physicalDevice); const VkMemoryPropertyFlags propertyFlag = VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT; const int arrayLength = 10; VkDeviceSize pCommittedMemoryInBytes = 0u; VkDeviceSize allocSize[arrayLength]; // generating random allocation sizes for (int i = 0; i < arrayLength; ++i) { allocSize[i] = rand() % 1000 + 1; } for (deUint32 memoryTypeIndex = 0u; memoryTypeIndex < VK_MAX_MEMORY_TYPES; ++memoryTypeIndex) //for memoryTypes { if((pMemoryProperties.memoryTypes[memoryTypeIndex].propertyFlags & propertyFlag) == propertyFlag) //if supports Lazy allocation { for (int i = 0; i < arrayLength; ++i) { const VkMemoryAllocateInfo memAllocInfo = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // VkStructureType sType NULL, // const void* pNext allocSize[i], // VkDeviceSize allocationSize memoryTypeIndex // deUint32 memoryTypeIndex }; Move memory = allocateMemory(vkd, device, &memAllocInfo, (const VkAllocationCallbacks*)DE_NULL); vkd.getDeviceMemoryCommitment(device, memory.get(), &pCommittedMemoryInBytes); if(pCommittedMemoryInBytes != 0) { tcu::TestLog& log = m_context.getTestContext().getLog(); log << TestLog::Message << "Warning: Memory commitment not null before binding." << TestLog::EndMessage; } if(pCommittedMemoryInBytes > allocSize[i]) return tcu::TestStatus::fail("Fail"); } } } return tcu::TestStatus::pass("Pass"); } deUint32 MemoryCommitmentTestInstance::getMemoryTypeIndex(VkMemoryPropertyFlags propertyFlag, VkPhysicalDeviceMemoryProperties pMemoryProperties) { for (deUint32 memoryTypeIndex = 0u; memoryTypeIndex < VK_MAX_MEMORY_TYPES; ++memoryTypeIndex) { if((pMemoryProperties.memoryTypes[memoryTypeIndex].propertyFlags & propertyFlag) == propertyFlag) return memoryTypeIndex; } return static_cast(-1); } void MemoryCommitmentTestCase::initPrograms (SourceCollections& programCollection) const { programCollection.glslSources.add("vert") << glu::VertexSource( "#version 310 es\n" "layout (location = 0) in highp vec4 a_position;\n" "void main()\n" "{\n" " gl_Position = a_position;\n" "}\n"); programCollection.glslSources.add("frag") << glu::FragmentSource( "#version 310 es\n" "#extension GL_EXT_texture_buffer : enable\n" "layout (set=0, binding=0) uniform highp usamplerBuffer u_buffer;\n" "layout (location = 0) out highp uint o_color;\n" "void main()\n" "{\n" " o_color = texelFetch(u_buffer, int(gl_FragCoord.x)).x;\n" "}\n"); } Move MemoryCommitmentTestInstance::createCommandPool() const { const VkDevice device = m_context.getDevice(); const DeviceInterface& vkd = m_context.getDeviceInterface(); const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); return vk::createCommandPool(vkd, device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex); } Move MemoryCommitmentTestInstance::allocatePrimaryCommandBuffer (VkCommandPool commandPool) const { const VkDevice device = m_context.getDevice(); const DeviceInterface& vkd = m_context.getDeviceInterface(); return vk::allocateCommandBuffer(vkd, device, commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY); } bool MemoryCommitmentTestInstance::isDeviceMemoryCommitmentOk(const VkMemoryRequirements memoryRequirements) { const VkFormat colorFormat = VK_FORMAT_R32_UINT; const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice(); const InstanceInterface& vki = m_context.getInstanceInterface(); const VkMemoryPropertyFlags propertyFlag = VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT; const VkPhysicalDeviceMemoryProperties pMemoryProperties = getPhysicalDeviceMemoryProperties(vki,physicalDevice); const VkDeviceSize pixelDataSize = m_renderSize.x() * m_renderSize.y() * mapVkFormat(colorFormat).getPixelSize(); for (deUint32 memTypeNdx = 0u; memTypeNdx < VK_MAX_MEMORY_TYPES; ++memTypeNdx) { if((pMemoryProperties.memoryTypes[memTypeNdx].propertyFlags & propertyFlag) == propertyFlag) //if supports Lazy allocation { const VkMemoryAllocateInfo memAllocInfo = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // VkStructureType sType NULL, // const void* pNext pixelDataSize, // VkDeviceSize allocationSize memTypeNdx // deUint32 memoryTypeIndex }; const VkDevice device = m_context.getDevice(); const DeviceInterface& vkd = m_context.getDeviceInterface(); Move memory = allocateMemory(vkd, device, &memAllocInfo, (const VkAllocationCallbacks*)DE_NULL); VkDeviceSize pCommittedMemoryInBytes = 0u; vkd.getDeviceMemoryCommitment(device, memory.get(), &pCommittedMemoryInBytes); if(pCommittedMemoryInBytes <= memoryRequirements.size) return true; } } return false; } tcu::TestCaseGroup* createMemoryCommitmentTests (tcu::TestContext& testCtx) { static const MemoryCommitmentCaseParams info = { 2048u, // deUint32 bufferSize 256u, // deUint32 bufferViewSize 0u, // deUint32 elementOffset }; de::MovePtr getMemoryCommitmentTests (new tcu::TestCaseGroup(testCtx, "get_memory_commitment", "Memory Commitment Tests")); { getMemoryCommitmentTests->addChild(new MemoryCommitmentTestCase(testCtx, "memory_commitment", "memory_commitment_test", info)); getMemoryCommitmentTests->addChild(new MemoryCommitmentAllocateOnlyTestCase(testCtx, "memory_commitment_allocate_only", "memory_commitment_allocate_only_test")); } return getMemoryCommitmentTests.release(); } } //api } //vkt