Multiple objects per thread

This commit is contained in:
saschawillems 2016-04-01 14:24:46 +02:00
parent ad49cb7997
commit 3caeb6ee84

View file

@ -79,20 +79,27 @@ public:
glm::vec3 color; glm::vec3 color;
}; };
struct MeshData { struct MeshBuffer {
glm::vec3 pos;
glm::vec3 rotation;
float deltaT;
vkMeshLoader::MeshBufferInfo vertices; vkMeshLoader::MeshBufferInfo vertices;
vkMeshLoader::MeshBufferInfo indices; vkMeshLoader::MeshBufferInfo indices;
uint32_t indexCount; uint32_t indexCount;
}; };
struct ObjectData {
glm::vec3 pos;
glm::vec3 rotation;
float deltaT;
};
struct ThreadData { struct ThreadData {
MeshData meshData; MeshBuffer mesh;
VkCommandPool commandPool; VkCommandPool commandPool;
// One command buffer per render object
std::vector<VkCommandBuffer> commandBuffer; std::vector<VkCommandBuffer> commandBuffer;
ThreadPushConstantBlock pushConstBlock; // One push constant block per render object
std::vector<ThreadPushConstantBlock> pushConstBlock;
// Per object information (position, rotation, etc.)
std::vector<ObjectData> objectData;
}; };
std::vector<ThreadData> threadData; std::vector<ThreadData> threadData;
@ -163,7 +170,6 @@ public:
{ {
ThreadData *thread = &threadData[i]; ThreadData *thread = &threadData[i];
// Create one command pool for each thread // Create one command pool for each thread
VkCommandPoolCreateInfo cmdPoolInfo = vkTools::initializers::commandPoolCreateInfo(); VkCommandPoolCreateInfo cmdPoolInfo = vkTools::initializers::commandPoolCreateInfo();
cmdPoolInfo.queueFamilyIndex = swapChain.queueNodeIndex; cmdPoolInfo.queueFamilyIndex = swapChain.queueNodeIndex;
@ -186,14 +192,14 @@ public:
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
meshes.ufo.vertices.size, meshes.ufo.vertices.size,
nullptr, nullptr,
&thread->meshData.vertices.buf, &thread->mesh.vertices.buf,
&thread->meshData.vertices.mem); &thread->mesh.vertices.mem);
createBuffer( createBuffer(
VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
meshes.ufo.indices.size, meshes.ufo.indices.size,
nullptr, nullptr,
&thread->meshData.indices.buf, &thread->mesh.indices.buf,
&thread->meshData.indices.mem); &thread->mesh.indices.mem);
// Copy from mesh buffer // Copy from mesh buffer
VkBufferCopy copyRegion = {}; VkBufferCopy copyRegion = {};
@ -203,7 +209,7 @@ public:
vkCmdCopyBuffer( vkCmdCopyBuffer(
setupCmdBuffer, setupCmdBuffer,
meshes.ufo.vertices.buf, meshes.ufo.vertices.buf,
thread->meshData.vertices.buf, thread->mesh.vertices.buf,
1, 1,
&copyRegion); &copyRegion);
// Index buffer // Index buffer
@ -211,18 +217,24 @@ public:
vkCmdCopyBuffer( vkCmdCopyBuffer(
setupCmdBuffer, setupCmdBuffer,
meshes.ufo.indices.buf, meshes.ufo.indices.buf,
thread->meshData.indices.buf, thread->mesh.indices.buf,
1, 1,
&copyRegion); &copyRegion);
thread->meshData.indexCount = meshes.ufo.indexCount; thread->mesh.indexCount = meshes.ufo.indexCount;
float step = 360.0f / (float)numThreads; thread->pushConstBlock.resize(numObjectsPerThread);
thread->objectData.resize(numObjectsPerThread);
float step = 360.0f / (float)(numThreads * numObjectsPerThread);
float radius = 20.0f; float radius = 20.0f;
thread->meshData.pos.x = sin(glm::radians(step * i)) * radius; for (uint32_t j = 0; j < numObjectsPerThread; j++)
thread->meshData.pos.z = cos(glm::radians(step * i)) * radius; {
thread->meshData.rotation = glm::vec3(0.0f, (float)(rand() % 360), 0.0f); thread->objectData[j].pos.x = sin(glm::radians(step * (i * numObjectsPerThread + j))) * radius;
thread->meshData.deltaT = (float)(rand() % 255) / 255.0f; thread->objectData[j].pos.z = cos(glm::radians(step * (i * numObjectsPerThread + j))) * radius;
thread->objectData[j].rotation = glm::vec3(0.0f, (float)(rand() % 360), 0.0f);
thread->objectData[j].deltaT = (float)i / (float)numThreads;
}
} }
// Submit buffer copies to the queue // Submit buffer copies to the queue
@ -252,20 +264,21 @@ public:
// Update // Update
// todo : timebased // todo : timebased
thread->meshData.rotation.y += 0.15f; ObjectData *objectData = &thread->objectData[cmdBufferIndex];
if (thread->meshData.rotation.y > 360.0f) objectData->rotation.y += 0.15f;
thread->meshData.rotation.y -= 360.0f; if (objectData->rotation.y > 360.0f)
thread->meshData.deltaT += 0.0005f; objectData->rotation.y -= 360.0f;
if (thread->meshData.deltaT > 1.0f) objectData->deltaT += 0.0005f;
thread->meshData.deltaT -= 1.0f; if (objectData->deltaT > 1.0f)
thread->meshData.pos.y = sin(glm::radians(thread->meshData.deltaT * 360.0f)) * 1.5f; objectData->deltaT -= 1.0f;
objectData->pos.y = sin(glm::radians(objectData->deltaT * 360.0f)) * 1.5f;
glm::mat4 model = glm::translate(glm::mat4(), thread->meshData.pos); glm::mat4 model = glm::translate(glm::mat4(), objectData->pos);
model = glm::rotate(model, -sinf(glm::radians(thread->meshData.deltaT * 360.0f)) * 0.25f, glm::vec3(1.0f, 0.0f, 0.0f)); model = glm::rotate(model, -sinf(glm::radians(objectData->deltaT * 360.0f)) * 0.25f, glm::vec3(1.0f, 0.0f, 0.0f));
model = glm::rotate(model, glm::radians(thread->meshData.rotation.y), glm::vec3(0.0f, 1.0f, 0.0f)); model = glm::rotate(model, glm::radians(objectData->rotation.y), glm::vec3(0.0f, 1.0f, 0.0f));
model = glm::rotate(model, glm::radians(thread->meshData.deltaT * 360.0f), glm::vec3(0.0f, 1.0f, 0.0f)); model = glm::rotate(model, glm::radians(objectData->deltaT * 360.0f), glm::vec3(0.0f, 1.0f, 0.0f));
thread->pushConstBlock.mvp = matrices.projection * matrices.view * model; thread->pushConstBlock[cmdBufferIndex].mvp = matrices.projection * matrices.view * model;
// Update shader push constant block // Update shader push constant block
// Contains model view matrix // Contains model view matrix
@ -275,16 +288,19 @@ public:
VK_SHADER_STAGE_VERTEX_BIT, VK_SHADER_STAGE_VERTEX_BIT,
0, 0,
sizeof(ThreadPushConstantBlock), sizeof(ThreadPushConstantBlock),
&thread->pushConstBlock); &thread->pushConstBlock[cmdBufferIndex]);
VkDeviceSize offsets[1] = { 0 }; VkDeviceSize offsets[1] = { 0 };
vkCmdBindVertexBuffers(cmdBuffer, 0, 1, &thread->meshData.vertices.buf, offsets); vkCmdBindVertexBuffers(cmdBuffer, 0, 1, &thread->mesh.vertices.buf, offsets);
vkCmdBindIndexBuffer(cmdBuffer, thread->meshData.indices.buf, 0, VK_INDEX_TYPE_UINT32); vkCmdBindIndexBuffer(cmdBuffer, thread->mesh.indices.buf, 0, VK_INDEX_TYPE_UINT32);
vkCmdDrawIndexed(cmdBuffer, thread->meshData.indexCount, 1, 0, 0, 0); vkCmdDrawIndexed(cmdBuffer, thread->mesh.indexCount, 1, 0, 0, 0);
vkTools::checkResult(vkEndCommandBuffer(cmdBuffer)); vkTools::checkResult(vkEndCommandBuffer(cmdBuffer));
} }
// Updates the secondary command buffers using a thread pool
// and puts them into the primary command buffer that's
// lat submitted to the queue for rendering
void updateCommandBuffers(VkFramebuffer frameBuffer) void updateCommandBuffers(VkFramebuffer frameBuffer)
{ {
VkCommandBufferBeginInfo cmdBufInfo = vkTools::initializers::commandBufferBeginInfo(); VkCommandBufferBeginInfo cmdBufInfo = vkTools::initializers::commandBufferBeginInfo();
@ -322,8 +338,12 @@ public:
for (uint32_t t = 0; t < numThreads; t++) for (uint32_t t = 0; t < numThreads; t++)
{ {
threadPool.threads[t]->addJob([=] { threadRenderCode(t, 0, inheritanceInfo); }); // Add a job to the thread's queue for each object to be rendered
commandBuffers.push_back(threadData[t].commandBuffer[0]); for (uint32_t i = 0; i < numObjectsPerThread; i++)
{
threadPool.threads[t]->addJob([=] { threadRenderCode(t, i, inheritanceInfo); });
commandBuffers.push_back(threadData[t].commandBuffer[i]);
}
} }
threadPool.wait(); threadPool.wait();