Mesh loader now does staging to device local memory by default (Refs #84)

This commit is contained in:
saschawillems 2016-05-20 23:15:31 +02:00
parent 79b7fd440c
commit 66f006b783
2 changed files with 195 additions and 52 deletions

View file

@ -197,22 +197,22 @@ private:
std::vector<unsigned int> Indices;
};
VkBool32 getMemoryType(VkPhysicalDeviceMemoryProperties deviceMemoryProperties, uint32_t typeBits, VkFlags properties, uint32_t * typeIndex)
VkBool32 getMemoryType(VkPhysicalDeviceMemoryProperties deviceMemoryProperties, uint32_t typeBits, VkMemoryPropertyFlags properties)
{
for (int i = 0; i < 32; i++)
for (uint32_t i = 0; i < 32; i++)
{
if ((typeBits & 1) == 1)
{
if ((deviceMemoryProperties.memoryTypes[i].propertyFlags & properties) == properties)
{
*typeIndex = i;
return true;
return i;
}
}
typeBits >>= 1;
}
return false;
// todo : throw error
return 0;
}
public:
@ -388,15 +388,41 @@ public:
vkFreeMemory(device, mesh->indexBuffer.mem, nullptr);
}
VkResult createBuffer(
VkDevice device,
VkPhysicalDeviceMemoryProperties deviceMemoryProperties,
VkBufferUsageFlags usageFlags,
VkMemoryPropertyFlags memoryPropertyFlags,
VkDeviceSize size,
VkBuffer *buffer,
VkDeviceMemory *memory)
{
VkMemoryAllocateInfo memAllocInfo = vkTools::initializers::memoryAllocateInfo();
VkMemoryRequirements memReqs;
VkBufferCreateInfo bufferInfo = vkTools::initializers::bufferCreateInfo(usageFlags, size);
VK_CHECK_RESULT(vkCreateBuffer(device, &bufferInfo, nullptr, buffer));
vkGetBufferMemoryRequirements(device, *buffer, &memReqs);
memAllocInfo.allocationSize = memReqs.size;
memAllocInfo.memoryTypeIndex = getMemoryType(deviceMemoryProperties, memReqs.memoryTypeBits, memoryPropertyFlags);
VK_CHECK_RESULT(vkAllocateMemory(device, &memAllocInfo, nullptr, memory));
VK_CHECK_RESULT(vkBindBufferMemory(device, *buffer, *memory, 0));
return VK_SUCCESS;
}
// Create vertex and index buffer with given layout
void createVulkanBuffers(
// Note : Only does staging if a valid command buffer and transfer queue are passed
void createBuffers(
VkDevice device,
VkPhysicalDeviceMemoryProperties deviceMemoryProperties,
vkMeshLoader::MeshBuffer *meshBuffer,
std::vector<vkMeshLoader::VertexLayout> layout,
float scale)
float scale,
bool useStaging,
VkCommandBuffer copyCmd,
VkQueue copyQueue)
{
std::vector<float> vertexBuffer;
for (int m = 0; m < m_Entries.size(); m++)
{
@ -478,43 +504,153 @@ public:
}
meshBuffer->indices.size = indexBuffer.size() * sizeof(uint32_t);
VkMemoryAllocateInfo memAlloc = vkTools::initializers::memoryAllocateInfo();
VkMemoryRequirements memReqs;
meshBuffer->indexCount = (uint32_t)indexBuffer.size();
VkResult err;
void* data;
// Use staging buffer to move vertex and index buffer to device local memory
if (useStaging && copyQueue != VK_NULL_HANDLE && copyCmd != VK_NULL_HANDLE)
{
// Create staging buffers
struct {
VkBuffer buffer;
VkDeviceMemory memory;
} vertexStaging, indexStaging;
// Vertex buffer
createBuffer(
device,
deviceMemoryProperties,
VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
meshBuffer->vertices.size,
&vertexStaging.buffer,
&vertexStaging.memory);
VK_CHECK_RESULT(vkMapMemory(device, vertexStaging.memory, 0, VK_WHOLE_SIZE, 0, &data));
memcpy(data, vertexBuffer.data(), meshBuffer->vertices.size);
vkUnmapMemory(device, vertexStaging.memory);
// Index buffer
createBuffer(
device,
deviceMemoryProperties,
VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
meshBuffer->indices.size,
&indexStaging.buffer,
&indexStaging.memory);
VK_CHECK_RESULT(vkMapMemory(device, indexStaging.memory, 0, VK_WHOLE_SIZE, 0, &data));
memcpy(data, indexBuffer.data(), meshBuffer->indices.size);
vkUnmapMemory(device, indexStaging.memory);
// Create device local target buffers
// Vertex buffer
createBuffer(
device,
deviceMemoryProperties,
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
meshBuffer->vertices.size,
&meshBuffer->vertices.buf,
&meshBuffer->vertices.mem);
// Index buffer
createBuffer(
device,
deviceMemoryProperties,
VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
meshBuffer->indices.size,
&meshBuffer->indices.buf,
&meshBuffer->indices.mem);
// Copy from staging buffers
VkCommandBufferBeginInfo cmdBufInfo = vkTools::initializers::commandBufferBeginInfo();
VK_CHECK_RESULT(vkBeginCommandBuffer(copyCmd, &cmdBufInfo));
VkBufferCopy copyRegion = {};
copyRegion.size = meshBuffer->vertices.size;
vkCmdCopyBuffer(
copyCmd,
vertexStaging.buffer,
meshBuffer->vertices.buf,
1,
&copyRegion);
copyRegion.size = meshBuffer->indices.size;
vkCmdCopyBuffer(
copyCmd,
indexStaging.buffer,
meshBuffer->indices.buf,
1,
&copyRegion);
VK_CHECK_RESULT(vkEndCommandBuffer(copyCmd));
VkSubmitInfo submitInfo = {};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &copyCmd;
VK_CHECK_RESULT(vkQueueSubmit(copyQueue, 1, &submitInfo, VK_NULL_HANDLE));
VK_CHECK_RESULT(vkQueueWaitIdle(copyQueue));
vkDestroyBuffer(device, vertexStaging.buffer, nullptr);
vkFreeMemory(device, vertexStaging.memory, nullptr);
vkDestroyBuffer(device, indexStaging.buffer, nullptr);
vkFreeMemory(device, indexStaging.memory, nullptr);
}
else
{
// Generate vertex buffer
VkBufferCreateInfo vBufferInfo = vkTools::initializers::bufferCreateInfo(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT, meshBuffer->vertices.size);
err = vkCreateBuffer(device, &vBufferInfo, nullptr, &meshBuffer->vertices.buf);
assert(!err);
vkGetBufferMemoryRequirements(device, meshBuffer->vertices.buf, &memReqs);
memAlloc.allocationSize = memReqs.size;
getMemoryType(deviceMemoryProperties, memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &memAlloc.memoryTypeIndex);
err = vkAllocateMemory(device, &memAlloc, nullptr, &meshBuffer->vertices.mem);
assert(!err);
err = vkMapMemory(device, meshBuffer->vertices.mem, 0, meshBuffer->vertices.size, 0, &data);
assert(!err);
createBuffer(
device,
deviceMemoryProperties,
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
meshBuffer->vertices.size,
&meshBuffer->vertices.buf,
&meshBuffer->vertices.mem);
VK_CHECK_RESULT(vkMapMemory(device, meshBuffer->vertices.mem, 0, meshBuffer->vertices.size, 0, &data));
memcpy(data, vertexBuffer.data(), meshBuffer->vertices.size);
vkUnmapMemory(device, meshBuffer->vertices.mem);
err = vkBindBufferMemory(device, meshBuffer->vertices.buf, meshBuffer->vertices.mem, 0);
assert(!err);
// Generate index buffer
VkBufferCreateInfo iBufferInfo = vkTools::initializers::bufferCreateInfo(VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT, meshBuffer->indices.size);
err = vkCreateBuffer(device, &iBufferInfo, nullptr, &meshBuffer->indices.buf);
assert(!err);
vkGetBufferMemoryRequirements(device, meshBuffer->indices.buf, &memReqs);
memAlloc.allocationSize = memReqs.size;
getMemoryType(deviceMemoryProperties, memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &memAlloc.memoryTypeIndex);
err = vkAllocateMemory(device, &memAlloc, nullptr, &meshBuffer->indices.mem);
assert(!err);
err = vkMapMemory(device, meshBuffer->indices.mem, 0, meshBuffer->indices.size, 0, &data);
assert(!err);
createBuffer(
device,
deviceMemoryProperties,
VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
meshBuffer->indices.size,
&meshBuffer->indices.buf,
&meshBuffer->indices.mem);
VK_CHECK_RESULT(vkMapMemory(device, meshBuffer->indices.mem, 0, meshBuffer->indices.size, 0, &data));
memcpy(data, indexBuffer.data(), meshBuffer->indices.size);
vkUnmapMemory(device, meshBuffer->indices.mem);
err = vkBindBufferMemory(device, meshBuffer->indices.buf, meshBuffer->indices.mem, 0);
assert(!err);
meshBuffer->indexCount = (uint32_t)indexBuffer.size();
}
}
// Create vertex and index buffer with given layout
void createVulkanBuffers(
VkDevice device,
VkPhysicalDeviceMemoryProperties deviceMemoryProperties,
vkMeshLoader::MeshBuffer *meshBuffer,
std::vector<vkMeshLoader::VertexLayout> layout,
float scale)
{
createBuffers(
device,
deviceMemoryProperties,
meshBuffer,
layout,
scale,
false,
VK_NULL_HANDLE,
VK_NULL_HANDLE);
}
};

View file

@ -378,12 +378,19 @@ void VulkanExampleBase::loadMesh(
mesh->LoadMesh(filename);
assert(mesh->m_Entries.size() > 0);
mesh->createVulkanBuffers(
VkCommandBuffer copyCmd = VulkanExampleBase::createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, false);
mesh->createBuffers(
device,
deviceMemoryProperties,
meshBuffer,
vertexLayout,
scale);
scale,
true,
copyCmd,
queue);
vkFreeCommandBuffers(device, cmdPool, 1, &copyCmd);
meshBuffer->dim = mesh->dim.size;