Mesh loader now does staging to device local memory by default (Refs #84)
This commit is contained in:
parent
79b7fd440c
commit
66f006b783
2 changed files with 195 additions and 52 deletions
|
|
@ -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,
|
||||
©Region);
|
||||
|
||||
copyRegion.size = meshBuffer->indices.size;
|
||||
vkCmdCopyBuffer(
|
||||
copyCmd,
|
||||
indexStaging.buffer,
|
||||
meshBuffer->indices.buf,
|
||||
1,
|
||||
©Region);
|
||||
|
||||
VK_CHECK_RESULT(vkEndCommandBuffer(copyCmd));
|
||||
|
||||
VkSubmitInfo submitInfo = {};
|
||||
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||
submitInfo.commandBufferCount = 1;
|
||||
submitInfo.pCommandBuffers = ©Cmd;
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
|
@ -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, ©Cmd);
|
||||
|
||||
meshBuffer->dim = mesh->dim.size;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue