|
|
|
@ -56,12 +56,12 @@ Application::Application() { |
|
|
|
|
VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE, 0); |
|
|
|
|
sizeInformationBuffer->setName("Sizes"); |
|
|
|
|
|
|
|
|
|
properties.gravity = {0, -9.81, 0}; |
|
|
|
|
properties.k = 10; |
|
|
|
|
properties.dt = 1.f / 60.f; |
|
|
|
|
simulationProperties.gravity = {0, -9.81, 0}; |
|
|
|
|
simulationProperties.k = 10; |
|
|
|
|
simulationProperties.dt = 1.f / 60.f; |
|
|
|
|
|
|
|
|
|
propertiesBuffer = make_unique<Buffer>( |
|
|
|
|
sizeof(Properties), &properties, sizeof(properties), |
|
|
|
|
sizeof(SimulationProperties), &simulationProperties, sizeof(simulationProperties), |
|
|
|
|
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, |
|
|
|
|
VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE, 0); |
|
|
|
|
propertiesBuffer->setName("Simulation properties"); |
|
|
|
@ -90,22 +90,27 @@ Application::Application() { |
|
|
|
|
using namespace std::chrono; |
|
|
|
|
|
|
|
|
|
void Application::mainLoop() { |
|
|
|
|
vkDeviceWaitIdle(Instance::GetDevice()); |
|
|
|
|
std::future compute = std::async(std::launch::async, [this](){ |
|
|
|
|
while (!glfwWindowShouldClose(Instance::instance->window)){ |
|
|
|
|
auto t1 = system_clock::now(); |
|
|
|
|
update(); |
|
|
|
|
auto t2 = system_clock::now(); |
|
|
|
|
|
|
|
|
|
microseconds updateDuration = duration_cast<microseconds>(t2 - t1); |
|
|
|
|
|
|
|
|
|
microseconds sleepDuration(static_cast<int64_t>(properties.dt * 1000 * 1000)); |
|
|
|
|
auto updateDuration = duration<float>(t2 - t1); |
|
|
|
|
auto sleepDuration = duration<float>(simulationProperties.dt); |
|
|
|
|
std::this_thread::sleep_for(sleepDuration - updateDuration); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
auto t2 = system_clock::now(); |
|
|
|
|
auto t1 = system_clock::now(); |
|
|
|
|
while (!glfwWindowShouldClose(Instance::instance->window)){ |
|
|
|
|
glfwPollEvents(); |
|
|
|
|
drawFrame(); |
|
|
|
|
t2 = system_clock::now(); |
|
|
|
|
float seconds = duration<float>(t2 - t1).count(); |
|
|
|
|
t1 = system_clock::now(); |
|
|
|
|
drawFrame(seconds); |
|
|
|
|
} |
|
|
|
|
compute.wait(); |
|
|
|
|
vkDeviceWaitIdle(Instance::GetDevice()); |
|
|
|
@ -117,9 +122,9 @@ Application::~Application() { |
|
|
|
|
|
|
|
|
|
void Application::createSyncObjects() { |
|
|
|
|
imageAvailable = make_unique<Semaphore>(); |
|
|
|
|
renderFinished = make_unique<Semaphore>(); |
|
|
|
|
renderSemaphore = make_unique<Semaphore>(); |
|
|
|
|
computeSemaphore = make_unique<Semaphore>(); |
|
|
|
|
transferFinished = make_unique<Semaphore>(); |
|
|
|
|
transferSemaphore = make_unique<Semaphore>(); |
|
|
|
|
renderFence = make_unique<Fence>(true); |
|
|
|
|
computeFence = make_unique<Fence>(true); |
|
|
|
|
transferFence = make_unique<Fence>(true); |
|
|
|
@ -295,11 +300,7 @@ void Application::createComputePipelines() { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Application::updateUniformBuffer() { |
|
|
|
|
static float elapsed = 0; |
|
|
|
|
|
|
|
|
|
elapsed += 0.007; |
|
|
|
|
|
|
|
|
|
void Application::updateCameraBuffer() { |
|
|
|
|
CameraUniformData ubo {}; |
|
|
|
|
ubo.view = camera->view(); |
|
|
|
|
ubo.projection = camera->projection(); |
|
|
|
@ -314,7 +315,7 @@ void Application::updateUniformBuffer() { |
|
|
|
|
cameraUniformBuffer->allocationInfo.size); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Application::drawFrame() { |
|
|
|
|
void Application::drawFrame(float dt) { |
|
|
|
|
vkWaitForFences(Instance::GetDevice(), 1, &renderFence->handle, VK_TRUE, UINT64_MAX); |
|
|
|
|
|
|
|
|
|
uint32_t imageIndex; |
|
|
|
@ -326,8 +327,8 @@ void Application::drawFrame() { |
|
|
|
|
|
|
|
|
|
vkResetFences(Instance::GetDevice(), 1, &renderFence->handle); |
|
|
|
|
|
|
|
|
|
camera->update(0.017); |
|
|
|
|
updateUniformBuffer(); |
|
|
|
|
camera->update(dt); |
|
|
|
|
updateCameraBuffer(); |
|
|
|
|
|
|
|
|
|
VkCommandBuffer cmdBuffer = Instance::instance->renderingCommandPool->buffers[0]; |
|
|
|
|
{ |
|
|
|
@ -343,10 +344,10 @@ void Application::drawFrame() { |
|
|
|
|
vertexBufferBarrier.size = vertexBuffers[currentDrawVertexBuffer]->size; |
|
|
|
|
vertexBufferBarrier.offset = 0; |
|
|
|
|
vertexBufferBarrier.buffer = vertexBuffers[currentDrawVertexBuffer]->handle; |
|
|
|
|
vertexBufferBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT; |
|
|
|
|
vertexBufferBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; |
|
|
|
|
vertexBufferBarrier.dstAccessMask = VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT; |
|
|
|
|
|
|
|
|
|
vkCmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0, 0, |
|
|
|
|
vkCmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0, 0, |
|
|
|
|
nullptr, 1, &vertexBufferBarrier, 0, nullptr); |
|
|
|
|
|
|
|
|
|
VkBufferMemoryBarrier uniformBufferBarrier {}; |
|
|
|
@ -360,6 +361,16 @@ void Application::drawFrame() { |
|
|
|
|
vkCmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, |
|
|
|
|
0, nullptr, 1, &uniformBufferBarrier, 0, nullptr); |
|
|
|
|
|
|
|
|
|
VkMemoryBarrier barrier {}; |
|
|
|
|
barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER; |
|
|
|
|
barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_MEMORY_WRITE_BIT; |
|
|
|
|
barrier.dstAccessMask = VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT; |
|
|
|
|
|
|
|
|
|
vkCmdPipelineBarrier(cmdBuffer, |
|
|
|
|
VK_PIPELINE_STAGE_TRANSFER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, |
|
|
|
|
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 0, 1, &barrier, |
|
|
|
|
0, nullptr, 0, nullptr); |
|
|
|
|
|
|
|
|
|
VkRenderPassBeginInfo renderPassInfo{}; |
|
|
|
|
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; |
|
|
|
|
renderPassInfo.renderPass = swapchain->renderPass; |
|
|
|
@ -407,7 +418,7 @@ void Application::drawFrame() { |
|
|
|
|
submitInfo.commandBufferCount = 1; |
|
|
|
|
submitInfo.pCommandBuffers = &cmdBuffer; |
|
|
|
|
|
|
|
|
|
VkSemaphore signalSemaphores[] = {renderFinished->handle}; |
|
|
|
|
VkSemaphore signalSemaphores[] = {renderSemaphore->handle}; |
|
|
|
|
submitInfo.signalSemaphoreCount = 1; |
|
|
|
|
submitInfo.pSignalSemaphores = signalSemaphores; |
|
|
|
|
|
|
|
|
@ -450,12 +461,15 @@ void Application::recordDrawCommands(VkCommandBuffer cmdBuffer) { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Application::update() { |
|
|
|
|
vkWaitForFences(Instance::GetDevice(), 1, &transferFence->handle, VK_TRUE, UINT64_MAX); |
|
|
|
|
vkResetFences(Instance::GetDevice(), 1, &transferFence->handle); |
|
|
|
|
vkWaitForFences(Instance::GetDevice(), 1, &computeFence->handle, VK_TRUE, UINT64_MAX); |
|
|
|
|
vkResetFences(Instance::GetDevice(), 1, &computeFence->handle); |
|
|
|
|
|
|
|
|
|
currentDrawVertexBuffer = 1 - currentDrawVertexBuffer; |
|
|
|
|
descriptorPool->bindBuffer(*vertexBuffers[1 - currentDrawVertexBuffer], VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, DescriptorSet::MESH, 0); |
|
|
|
|
|
|
|
|
|
vkWaitForFences(Instance::GetDevice(), 1, &transferFence->handle, VK_TRUE, UINT64_MAX); |
|
|
|
|
vkResetFences(Instance::GetDevice(), 1, &transferFence->handle); |
|
|
|
|
|
|
|
|
|
VkCommandBufferBeginInfo beginInfo {}; |
|
|
|
|
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; |
|
|
|
|
beginInfo.flags = 0; |
|
|
|
@ -479,7 +493,7 @@ void Application::update() { |
|
|
|
|
submit.pSignalSemaphores = &computeSemaphore->handle; |
|
|
|
|
|
|
|
|
|
submitMutex.lock(); |
|
|
|
|
vkQueueSubmit(Instance::instance->computeAndTransferQueue, 1, &submit, nullptr); |
|
|
|
|
vkQueueSubmit(Instance::instance->computeAndTransferQueue, 1, &submit, computeFence->handle); |
|
|
|
|
submitMutex.unlock(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -587,7 +601,7 @@ void Application::recordPBDCommands(VkCommandBuffer cmdBuffer) { |
|
|
|
|
|
|
|
|
|
uint32_t state; |
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < properties.k; i++){ |
|
|
|
|
for (size_t i = 0; i < simulationProperties.k; i++){ |
|
|
|
|
state = 0; |
|
|
|
|
vkCmdPushConstants(cmdBuffer, pbdPipeline->layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(uint32_t), &state); |
|
|
|
|
vkCmdDispatch(cmdBuffer, vertexGroupCount, 1, 1); |
|
|
|
|