1/*------------------------------------------------------------------------- 2 * Vulkan Conformance Tests 3 * ------------------------ 4 * 5 * Copyright (c) 2016 The Khronos Group Inc. 6 * Copyright (c) 2016 Samsung Electronics Co., Ltd. 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); 9 * you may not use this file except in compliance with the License. 10 * You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 * 20 *//*! 21 * \file 22 * \brief Memory Commitment tests 23 *//*--------------------------------------------------------------------*/ 24 25#include "vktApiGetMemoryCommitment.hpp" 26 27#include "vkDeviceUtil.hpp" 28#include "vkQueryUtil.hpp" 29#include "vkRefUtil.hpp" 30#include "vkImageUtil.hpp" 31#include "vkMemUtil.hpp" 32#include "vkPrograms.hpp" 33#include "vktTestCase.hpp" 34#include "vkTypeUtil.hpp" 35#include "vkCmdUtil.hpp" 36#include "vkObjUtil.hpp" 37 38#include "tcuTestLog.hpp" 39 40using namespace vk; 41using tcu::TestLog; 42 43namespace vkt 44{ 45namespace api 46{ 47 48struct MemoryCommitmentCaseParams 49{ 50 deUint32 bufferSize; 51 deUint32 bufferViewSize; 52 deUint32 elementOffset; 53}; 54 55namespace 56{ 57 58std::vector<deUint32> getMemoryTypeIndices (VkMemoryPropertyFlags propertyFlag, const VkPhysicalDeviceMemoryProperties& pMemoryProperties) 59{ 60 std::vector<deUint32> indices; 61 for (deUint32 typeIndex = 0u; typeIndex < pMemoryProperties.memoryTypeCount; ++typeIndex) 62 { 63 if ((pMemoryProperties.memoryTypes[typeIndex].propertyFlags & propertyFlag) == propertyFlag) 64 indices.push_back(typeIndex); 65 } 66 return indices; 67} 68 69} 70 71class MemoryCommitmentTestInstance : public vkt::TestInstance 72{ 73public: 74 MemoryCommitmentTestInstance (Context& context, MemoryCommitmentCaseParams testCase); 75 tcu::TestStatus iterate (void); 76 Move<VkCommandPool> createCommandPool () const; 77 Move<VkCommandBuffer> allocatePrimaryCommandBuffer (VkCommandPool commandPool) const; 78 bool isDeviceMemoryCommitmentOk (const VkMemoryRequirements memoryRequirements); 79 80private: 81 const tcu::IVec2 m_renderSize; 82}; 83 84MemoryCommitmentTestInstance::MemoryCommitmentTestInstance(Context& context, MemoryCommitmentCaseParams testCase) 85 : vkt::TestInstance (context) 86 , m_renderSize (testCase.bufferViewSize, testCase.bufferViewSize) 87{ 88} 89 90class MemoryCommitmentTestCase : public vkt::TestCase 91{ 92public: 93 MemoryCommitmentTestCase (tcu::TestContext& testCtx, 94 const std::string& name, 95 MemoryCommitmentCaseParams memoryCommitmentTestInfo) 96 : vkt::TestCase (testCtx, name) 97 , m_memoryCommitmentTestInfo (memoryCommitmentTestInfo) 98 {} 99 virtual ~MemoryCommitmentTestCase(void){} 100 virtual void initPrograms (SourceCollections& programCollection) const; 101 virtual TestInstance* createInstance (Context& context) const 102 { 103 return new MemoryCommitmentTestInstance(context, m_memoryCommitmentTestInfo); 104 } 105private: 106 MemoryCommitmentCaseParams m_memoryCommitmentTestInfo; 107}; 108 109tcu::TestStatus MemoryCommitmentTestInstance::iterate(void) 110{ 111 const VkMemoryPropertyFlags propertyFlag = VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT; 112 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice(); 113 const InstanceInterface& vki = m_context.getInstanceInterface(); 114 const VkPhysicalDeviceMemoryProperties pMemoryProperties = getPhysicalDeviceMemoryProperties(vki,physicalDevice); 115 const std::vector<deUint32> memoryTypeIndices = getMemoryTypeIndices(propertyFlag, pMemoryProperties); 116 Allocator& memAlloc = m_context.getDefaultAllocator(); 117 bool isMemoryAllocationOK = false; 118 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); 119 const VkComponentMapping componentMappingRGBA = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A }; 120 const DeviceInterface& vkd = m_context.getDeviceInterface(); 121 const Move<VkCommandPool> cmdPool = createCommandPool(); 122 const Move<VkCommandBuffer> cmdBuffer = allocatePrimaryCommandBuffer(*cmdPool); 123 const VkDevice device = m_context.getDevice(); 124 Move<VkImageView> colorAttachmentView; 125 Move<VkRenderPass> renderPass; 126 Move<VkFramebuffer> framebuffer; 127 Move<VkDescriptorSetLayout> descriptorSetLayout; 128 Move<VkPipelineLayout> pipelineLayout; 129 Move<VkShaderModule> vertexShaderModule; 130 Move<VkShaderModule> fragmentShaderModule; 131 Move<VkPipeline> graphicsPipelines; 132 133 // Note we can still fail later if none of lazily allocated memory types can be used with the image below. 134 if (memoryTypeIndices.empty()) 135 TCU_THROW(NotSupportedError, "Lazily allocated bit is not supported by any memory type"); 136 137 const VkImageCreateInfo imageParams = 138 { 139 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; 140 DE_NULL, // const void* pNext; 141 0u, // VkImageCreateFlags flags; 142 VK_IMAGE_TYPE_2D, // VkImageType imageType; 143 VK_FORMAT_R32_UINT, // VkFormat format; 144 {256u, 256u, 1}, // VkExtent3D extent; 145 1u, // deUint32 mipLevels; 146 1u, // deUint32 arraySize; 147 VK_SAMPLE_COUNT_1_BIT, // deUint32 samples; 148 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; 149 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | 150 VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT, // VkImageUsageFlags usage; 151 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 152 1u, // deUint32 queueFamilyCount; 153 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; 154 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 155 }; 156 157 Move<VkImage> image = createImage(vkd, device, &imageParams); 158 const VkMemoryRequirements memoryRequirements = getImageMemoryRequirements(vkd, device, *image); 159 de::MovePtr<Allocation> imageAlloc = memAlloc.allocate(memoryRequirements, MemoryRequirement::LazilyAllocated); 160 161 VK_CHECK(vkd.bindImageMemory(device, *image, imageAlloc->getMemory(), imageAlloc->getOffset())); 162 163 const VkImageViewCreateInfo colorAttachmentViewParams = 164 { 165 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType; 166 DE_NULL, // const void* pNext; 167 0u, // VkImageViewCreateFlags flags; 168 *image, // VkImage image; 169 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType; 170 VK_FORMAT_R32_UINT, // VkFormat format; 171 componentMappingRGBA, // VkComponentMapping components; 172 { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u } // VkImageSubresourceRange subresourceRange; 173 }; 174 175 colorAttachmentView = createImageView(vkd, device, &colorAttachmentViewParams); 176 177 // Create render pass 178 renderPass = makeRenderPass(vkd, device, VK_FORMAT_R32_UINT); 179 180 // Create framebuffer 181 { 182 const VkImageView attachmentBindInfos[1] = 183 { 184 *colorAttachmentView, 185 }; 186 187 const VkFramebufferCreateInfo framebufferParams = 188 { 189 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType; 190 DE_NULL, // const void* pNext; 191 (VkFramebufferCreateFlags)0, 192 *renderPass, // VkRenderPass renderPass; 193 1u, // deUint32 attachmentCount; 194 attachmentBindInfos, // const VkImageView* pAttachments; 195 (deUint32)m_renderSize.x(), // deUint32 width; 196 (deUint32)m_renderSize.y(), // deUint32 height; 197 1u // deUint32 layers; 198 }; 199 200 framebuffer = createFramebuffer(vkd, device, &framebufferParams); 201 } 202 203 // Create descriptors 204 { 205 const VkDescriptorSetLayoutBinding layoutBindings[1] = 206 { 207 { 208 0u, // deUint32 binding; 209 VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, // VkDescriptorType descriptorType; 210 1u, // deUint32 arraySize; 211 VK_SHADER_STAGE_ALL, // VkShaderStageFlags stageFlags; 212 DE_NULL // const VkSampler* pImmutableSamplers; 213 }, 214 }; 215 216 const VkDescriptorSetLayoutCreateInfo descriptorLayoutParams = 217 { 218 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // VkStructureType sType; 219 DE_NULL, // const void* pNext; 220 (VkDescriptorSetLayoutCreateFlags)0, 221 DE_LENGTH_OF_ARRAY(layoutBindings), // deUint32 count; 222 layoutBindings // const VkDescriptorSetLayoutBinding pBinding; 223 }; 224 225 descriptorSetLayout = createDescriptorSetLayout(vkd, device, &descriptorLayoutParams); 226 } 227 228 // Create pipeline layout 229 { 230 const VkPipelineLayoutCreateInfo pipelineLayoutParams = 231 { 232 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType; 233 DE_NULL, // const void* pNext; 234 (VkPipelineLayoutCreateFlags)0, 235 1u, // deUint32 descriptorSetCount; 236 &*descriptorSetLayout, // const VkDescriptorSetLayout* pSetLayouts; 237 0u, // deUint32 pushConstantRangeCount; 238 DE_NULL // const VkPushConstantRange* pPushConstantRanges; 239 }; 240 241 pipelineLayout = createPipelineLayout(vkd, device, &pipelineLayoutParams); 242 } 243 244 // Create shaders 245 { 246 vertexShaderModule = createShaderModule(vkd, device, m_context.getBinaryCollection().get("vert"), 0); 247 fragmentShaderModule = createShaderModule(vkd, device, m_context.getBinaryCollection().get("frag"), 0); 248 } 249 250 // Create pipeline 251 { 252 const std::vector<VkViewport> viewports (1, makeViewport(m_renderSize)); 253 const std::vector<VkRect2D> scissors (1, makeRect2D(m_renderSize)); 254 255 graphicsPipelines = makeGraphicsPipeline(vkd, // const DeviceInterface& vk 256 device, // const VkDevice device 257 *pipelineLayout, // const VkPipelineLayout pipelineLayout 258 *vertexShaderModule, // const VkShaderModule vertexShaderModule 259 DE_NULL, // const VkShaderModule tessellationControlModule 260 DE_NULL, // const VkShaderModule tessellationEvalModule 261 DE_NULL, // const VkShaderModule geometryShaderModule 262 *fragmentShaderModule, // const VkShaderModule fragmentShaderModule 263 *renderPass, // const VkRenderPass renderPass 264 viewports, // const std::vector<VkViewport>& viewports 265 scissors); // const std::vector<VkRect2D>& scissors 266 } 267 268 // getMemoryCommitment 269 isMemoryAllocationOK = isDeviceMemoryCommitmentOk(memoryRequirements); 270 271 const deUint32 clearColor[4] = { 1u, 1u, 1u, 1u }; 272 const VkClearAttachment clearAttachment = 273 { 274 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; 275 0u, // deUint32 colorAttachment; 276 makeClearValueColorU32(clearColor[0], 277 clearColor[1], 278 clearColor[2], 279 clearColor[3]) // VkClearValue clearValue; 280 }; 281 282 const VkOffset2D offset = 283 { 284 0, 285 0 286 }; 287 288 const VkExtent2D extent = 289 { 290 256u, 291 256u 292 }; 293 294 const VkRect2D rect = 295 { 296 offset, 297 extent 298 }; 299 300 const VkClearRect clearRect = 301 { 302 rect, 303 0u, // baseArrayLayer 304 1u // layerCount 305 }; 306 307 // beginCommandBuffer 308 beginCommandBuffer(vkd, *cmdBuffer); 309 310 const VkImageMemoryBarrier initialImageBarrier = 311 { 312 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; 313 DE_NULL, // const void* pNext; 314 0, // VkMemoryOutputFlags outputMask; 315 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkMemoryInputFlags inputMask; 316 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout; 317 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout; 318 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; 319 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex; 320 image.get(), // VkImage image; 321 { // VkImageSubresourceRange subresourceRange; 322 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; 323 0u, // deUint32 baseMipLevel; 324 1u, // deUint32 mipLevels; 325 0u, // deUint32 baseArraySlice; 326 1u // deUint32 arraySize; 327 } 328 }; 329 330 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); 331 beginRenderPass(vkd, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, 256u, 256u), tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f)); 332 vkd.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipelines); 333 // clearAttachments 334 vkd.cmdClearAttachments(*cmdBuffer, 1, &clearAttachment, 1u, &clearRect); 335 endRenderPass(vkd, *cmdBuffer); 336 endCommandBuffer(vkd, *cmdBuffer); 337 338 // queueSubmit 339 const VkQueue queue = m_context.getUniversalQueue(); 340 submitCommandsAndWait(vkd, device, queue, *cmdBuffer); 341 342 // getMemoryCommitment 343 isMemoryAllocationOK = (isMemoryAllocationOK && isDeviceMemoryCommitmentOk(memoryRequirements)) ? true : false; 344 345 if (isMemoryAllocationOK) 346 return tcu::TestStatus::pass("Pass"); 347 348 return tcu::TestStatus::fail("Fail"); 349} 350 351class MemoryCommitmentAllocateOnlyTestInstance : public vkt::TestInstance 352{ 353public: 354 MemoryCommitmentAllocateOnlyTestInstance (Context& context); 355 tcu::TestStatus iterate (void); 356}; 357 358class MemoryCommitmentAllocateOnlyTestCase : public vkt::TestCase 359{ 360public: 361 MemoryCommitmentAllocateOnlyTestCase (tcu::TestContext& testCtx, 362 const std::string& name) 363 : vkt::TestCase (testCtx, name) 364 {} 365 virtual ~MemoryCommitmentAllocateOnlyTestCase(void){} 366 virtual TestInstance* createInstance (Context& context) const 367 { 368 return new MemoryCommitmentAllocateOnlyTestInstance(context); 369 } 370}; 371 372MemoryCommitmentAllocateOnlyTestInstance::MemoryCommitmentAllocateOnlyTestInstance(Context& context) 373 : vkt::TestInstance (context) 374{ 375} 376 377tcu::TestStatus MemoryCommitmentAllocateOnlyTestInstance::iterate(void) 378{ 379 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice(); 380 const VkDevice device = m_context.getDevice(); 381 const InstanceInterface& vki = m_context.getInstanceInterface(); 382 const DeviceInterface& vkd = m_context.getDeviceInterface(); 383 const VkPhysicalDeviceMemoryProperties pMemoryProperties = getPhysicalDeviceMemoryProperties(vki,physicalDevice); 384 const VkMemoryPropertyFlags propertyFlag = VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT; 385 const std::vector<deUint32> memoryTypeIndices = getMemoryTypeIndices(propertyFlag, pMemoryProperties); 386 const int arrayLength = 10; 387 VkDeviceSize pCommittedMemoryInBytes = 0u; 388 VkDeviceSize allocSize[arrayLength]; 389 390 if (memoryTypeIndices.empty()) 391 TCU_THROW(NotSupportedError, "Lazily allocated bit is not supported by any memory type"); 392 393 // generating random allocation sizes 394 for (int i = 0; i < arrayLength; ++i) 395 { 396 allocSize[i] = rand() % 1000 + 1; 397 } 398 399 for (const auto memoryTypeIndex : memoryTypeIndices) 400 { 401 for (int i = 0; i < arrayLength; ++i) 402 { 403 const VkMemoryAllocateInfo memAllocInfo = 404 { 405 VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // VkStructureType sType 406 NULL, // const void* pNext 407 allocSize[i], // VkDeviceSize allocationSize 408 memoryTypeIndex // deUint32 memoryTypeIndex 409 }; 410 411 Move<VkDeviceMemory> memory = allocateMemory(vkd, device, &memAllocInfo, (const VkAllocationCallbacks*)DE_NULL); 412 413 vkd.getDeviceMemoryCommitment(device, memory.get(), &pCommittedMemoryInBytes); 414 if(pCommittedMemoryInBytes != 0) 415 { 416 tcu::TestLog& log = m_context.getTestContext().getLog(); 417 log << TestLog::Message << "Warning: Memory commitment not null before binding." << TestLog::EndMessage; 418 } 419 if(pCommittedMemoryInBytes > allocSize[i]) 420 return tcu::TestStatus::fail("Fail"); 421 422 } 423 } 424 return tcu::TestStatus::pass("Pass"); 425} 426 427void MemoryCommitmentTestCase::initPrograms (SourceCollections& programCollection) const 428{ 429 programCollection.glslSources.add("vert") << glu::VertexSource( 430 "#version 310 es\n" 431 "layout (location = 0) in highp vec4 a_position;\n" 432 "void main()\n" 433 "{\n" 434 " gl_Position = a_position;\n" 435 "}\n"); 436 437 programCollection.glslSources.add("frag") << glu::FragmentSource( 438 "#version 310 es\n" 439 "#extension GL_EXT_texture_buffer : enable\n" 440 "layout (set=0, binding=0) uniform highp usamplerBuffer u_buffer;\n" 441 "layout (location = 0) out highp uint o_color;\n" 442 "void main()\n" 443 "{\n" 444 " o_color = texelFetch(u_buffer, int(gl_FragCoord.x)).x;\n" 445 "}\n"); 446} 447 448Move<VkCommandPool> MemoryCommitmentTestInstance::createCommandPool() const 449{ 450 const VkDevice device = m_context.getDevice(); 451 const DeviceInterface& vkd = m_context.getDeviceInterface(); 452 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); 453 454 return vk::createCommandPool(vkd, device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex); 455} 456 457Move<VkCommandBuffer> MemoryCommitmentTestInstance::allocatePrimaryCommandBuffer (VkCommandPool commandPool) const 458{ 459 const VkDevice device = m_context.getDevice(); 460 const DeviceInterface& vkd = m_context.getDeviceInterface(); 461 462 return vk::allocateCommandBuffer(vkd, device, commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY); 463} 464 465bool MemoryCommitmentTestInstance::isDeviceMemoryCommitmentOk(const VkMemoryRequirements memoryRequirements) 466{ 467 const VkFormat colorFormat = VK_FORMAT_R32_UINT; 468 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice(); 469 const InstanceInterface& vki = m_context.getInstanceInterface(); 470 const VkMemoryPropertyFlags propertyFlag = VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT; 471 const VkPhysicalDeviceMemoryProperties pMemoryProperties = getPhysicalDeviceMemoryProperties(vki,physicalDevice); 472 const VkDeviceSize pixelDataSize = m_renderSize.x() * m_renderSize.y() * mapVkFormat(colorFormat).getPixelSize(); 473 474 for (deUint32 memTypeNdx = 0u; memTypeNdx < VK_MAX_MEMORY_TYPES; ++memTypeNdx) 475 { 476 if((pMemoryProperties.memoryTypes[memTypeNdx].propertyFlags & propertyFlag) == propertyFlag) //if supports Lazy allocation 477 { 478 const VkMemoryAllocateInfo memAllocInfo = 479 { 480 VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // VkStructureType sType 481 NULL, // const void* pNext 482 pixelDataSize, // VkDeviceSize allocationSize 483 memTypeNdx // deUint32 memoryTypeIndex 484 }; 485 const VkDevice device = m_context.getDevice(); 486 const DeviceInterface& vkd = m_context.getDeviceInterface(); 487 Move<VkDeviceMemory> memory = allocateMemory(vkd, device, &memAllocInfo, (const VkAllocationCallbacks*)DE_NULL); 488 VkDeviceSize pCommittedMemoryInBytes = 0u; 489 vkd.getDeviceMemoryCommitment(device, memory.get(), &pCommittedMemoryInBytes); 490 if(pCommittedMemoryInBytes <= memoryRequirements.size) 491 return true; 492 } 493 } 494 return false; 495} 496 497tcu::TestCaseGroup* createMemoryCommitmentTests (tcu::TestContext& testCtx) 498{ 499 static const MemoryCommitmentCaseParams info = 500 { 501 2048u, // deUint32 bufferSize 502 256u, // deUint32 bufferViewSize 503 0u, // deUint32 elementOffset 504 }; 505 506 de::MovePtr<tcu::TestCaseGroup> getMemoryCommitmentTests (new tcu::TestCaseGroup(testCtx, "get_memory_commitment")); 507 508 { 509 getMemoryCommitmentTests->addChild(new MemoryCommitmentTestCase(testCtx, "memory_commitment", info)); 510 getMemoryCommitmentTests->addChild(new MemoryCommitmentAllocateOnlyTestCase(testCtx, "memory_commitment_allocate_only")); 511 } 512 513 return getMemoryCommitmentTests.release(); 514} 515 516} //api 517} //vkt 518