From 574287f210e21c8ba854cdb4334a612b16994b31 Mon Sep 17 00:00:00 2001 From: saschawillems Date: Mon, 18 Jul 2016 20:32:25 +0200 Subject: [PATCH] Request host coherent memory types for index and vertex staging buffers (Fixes #203), example uses own getMemoryTypeIndex function for clarification, enabled exceptions for Android build --- android/triangle/jni/Application.mk | 1 + triangle/triangle.cpp | 42 +++++++++++++++++++++++------ 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/android/triangle/jni/Application.mk b/android/triangle/jni/Application.mk index 62020feb..e5347482 100644 --- a/android/triangle/jni/Application.mk +++ b/android/triangle/jni/Application.mk @@ -2,4 +2,5 @@ APP_PLATFORM := android-19 APP_ABI := armeabi-v7a APP_STL := c++_static APP_CPPFLAGS := -std=c++11 +APP_CPPFLAGS += -fexceptions NDK_TOOLCHAIN_VERSION := clang diff --git a/triangle/triangle.cpp b/triangle/triangle.cpp index 3567245f..ec359f4c 100644 --- a/triangle/triangle.cpp +++ b/triangle/triangle.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #define GLM_FORCE_RADIANS #define GLM_FORCE_DEPTH_ZERO_TO_ONE @@ -142,6 +143,29 @@ public: vkFreeMemory(device, uniformDataVS.memory, nullptr); } + // This function is used to request a device memory type that supports all the property flags we request (e.g. device local, host visibile) + // Upon success it will return the index of the memory type that fits our requestes memory properties + // This is necessary as implementations can offer an arbitrary number of memory types with different + // memory properties. + // You can check http://vulkan.gpuinfo.org/ for details on different memory configurations + uint32_t getMemoryTypeIndex(uint32_t typeBits, VkMemoryPropertyFlags properties) + { + // Iterate over all memory types available for the device used in this example + for (uint32_t i = 0; i < deviceMemoryProperties.memoryTypeCount; i++) + { + if ((typeBits & 1) == 1) + { + if ((deviceMemoryProperties.memoryTypes[i].propertyFlags & properties) == properties) + { + return i; + } + } + typeBits >>= 1; + } + + throw "Could not find a suitable memory type!"; + } + // We are going to use several temporary command buffers for setup stuff // like submitting barriers for layout translations of buffer copies // This function will allocate a single (primary) command buffer from the @@ -457,7 +481,9 @@ public: VK_CHECK_RESULT(vkCreateBuffer(device, &vertexBufferInfo, nullptr, &stagingBuffers.vertices.buffer)); vkGetBufferMemoryRequirements(device, stagingBuffers.vertices.buffer, &memReqs); memAlloc.allocationSize = memReqs.size; - memAlloc.memoryTypeIndex = getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); + // Request a host visible memory type that can be used to copy our data do + // Also request it to be coherent, so that writes are visible to the GPU right after unmapping the buffer + memAlloc.memoryTypeIndex = getMemoryTypeIndex(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &stagingBuffers.vertices.memory)); // Map and copy VK_CHECK_RESULT(vkMapMemory(device, stagingBuffers.vertices.memory, 0, memAlloc.allocationSize, 0, &data)); @@ -471,7 +497,7 @@ public: VK_CHECK_RESULT(vkCreateBuffer(device, &vertexBufferInfo, nullptr, &vertices.buf)); vkGetBufferMemoryRequirements(device, vertices.buf, &memReqs); memAlloc.allocationSize = memReqs.size; - memAlloc.memoryTypeIndex = getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + memAlloc.memoryTypeIndex = getMemoryTypeIndex(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &vertices.mem)); VK_CHECK_RESULT(vkBindBufferMemory(device, vertices.buf, vertices.mem, 0)); @@ -484,7 +510,7 @@ public: VK_CHECK_RESULT(vkCreateBuffer(device, &indexbufferInfo, nullptr, &stagingBuffers.indices.buffer)); vkGetBufferMemoryRequirements(device, stagingBuffers.indices.buffer, &memReqs); memAlloc.allocationSize = memReqs.size; - memAlloc.memoryTypeIndex = getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); + memAlloc.memoryTypeIndex = getMemoryTypeIndex(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &stagingBuffers.indices.memory)); VK_CHECK_RESULT(vkMapMemory(device, stagingBuffers.indices.memory, 0, indexBufferSize, 0, &data)); memcpy(data, indexBuffer.data(), indexBufferSize); @@ -496,7 +522,7 @@ public: VK_CHECK_RESULT(vkCreateBuffer(device, &indexbufferInfo, nullptr, &indices.buf)); vkGetBufferMemoryRequirements(device, indices.buf, &memReqs); memAlloc.allocationSize = memReqs.size; - memAlloc.memoryTypeIndex = getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + memAlloc.memoryTypeIndex = getMemoryTypeIndex(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &indices.mem)); VK_CHECK_RESULT(vkBindBufferMemory(device, indices.buf, indices.mem, 0)); @@ -558,7 +584,7 @@ public: VK_CHECK_RESULT(vkCreateBuffer(device, &vertexBufferInfo, nullptr, &vertices.buf)); vkGetBufferMemoryRequirements(device, vertices.buf, &memReqs); memAlloc.allocationSize = memReqs.size; - memAlloc.memoryTypeIndex = getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); + memAlloc.memoryTypeIndex = getMemoryTypeIndex(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &vertices.mem)); VK_CHECK_RESULT(vkMapMemory(device, vertices.mem, 0, memAlloc.allocationSize, 0, &data)); memcpy(data, vertexBuffer.data(), vertexBufferSize); @@ -575,7 +601,7 @@ public: VK_CHECK_RESULT(vkCreateBuffer(device, &indexbufferInfo, nullptr, &indices.buf)); vkGetBufferMemoryRequirements(device, indices.buf, &memReqs); memAlloc.allocationSize = memReqs.size; - memAlloc.memoryTypeIndex = getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); + memAlloc.memoryTypeIndex = getMemoryTypeIndex(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &indices.mem)); VK_CHECK_RESULT(vkMapMemory(device, indices.mem, 0, indexBufferSize, 0, &data)); memcpy(data, indexBuffer.data(), indexBufferSize); @@ -730,7 +756,7 @@ public: VkMemoryRequirements memReqs; vkGetImageMemoryRequirements(device, depthStencil.image, &memReqs); memAlloc.allocationSize = memReqs.size; - memAlloc.memoryTypeIndex = getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + memAlloc.memoryTypeIndex = getMemoryTypeIndex(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &depthStencil.mem)); VK_CHECK_RESULT(vkBindImageMemory(device, depthStencil.image, depthStencil.mem, 0)); @@ -1078,7 +1104,7 @@ public: // after every update. // Note that this may affect performance so you might not want to do this // in a real world application that updates buffers on a regular base - allocInfo.memoryTypeIndex = getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); + allocInfo.memoryTypeIndex = getMemoryTypeIndex(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); // Allocate memory for the uniform buffer VK_CHECK_RESULT(vkAllocateMemory(device, &allocInfo, nullptr, &(uniformDataVS.memory))); // Bind memory to buffer