start abstraction

feature/softbody-runtime-control
Benjamin Kraft 2 months ago
parent 3acf80b3ee
commit 385c608d96
  1. 15
      include/simulation.hpp
  2. 23
      include/soft_body.hpp
  3. 13
      include/timer.hpp
  4. 31
      include/vulkan/application.hpp
  5. 17
      include/vulkan/synchronization.hpp
  6. 3
      include/vulkan/utils.h
  7. 2
      shaders/shader.comp
  8. 6
      src/main.cpp
  9. 33
      src/simulation.cpp
  10. 5
      src/soft_body.cpp
  11. 11
      src/timer.cpp
  12. 88
      src/vulkan/application.cpp
  13. 1
      src/vulkan/buffer.cpp
  14. 1
      src/vulkan/image.cpp
  15. 25
      src/vulkan/synchronization.cpp
  16. 17
      src/vulkan/utils.cpp

@ -0,0 +1,15 @@
#pragma once
#include "vulkan/application.hpp"
class SoftBody;
class Simulation : public Application {
public:
Simulation();
~Simulation();
private:
std::vector<std::unique_ptr<SoftBody>> softBodies;
void recordDrawCommands() override;
void recordComputeCommands() override;
};

@ -0,0 +1,23 @@
#pragma once
#include <cstdint>
#include <string>
#include <vector>
#include "vulkan/vertex.hpp"
#include <glm/vec3.hpp>
using std::vector;
struct Face {
uint32_t a;
uint32_t b;
uint32_t c;
};
class SoftBody {
public:
explicit SoftBody(const std::string& fileName);
private:
uint32_t indexCount = 0;
};

@ -0,0 +1,13 @@
#pragma once
#include <chrono>
using namespace std::chrono;
class Timer {
public:
explicit Timer();
~Timer();
private:
time_point<system_clock> start;
};

@ -21,26 +21,16 @@ class Buffer;
class CommandPool; class CommandPool;
class Image; class Image;
class ComputePipeline; class ComputePipeline;
class Fence;
class Timer { class Semaphore;
public:
explicit Timer(){
start = std::chrono::system_clock::now();
}
~Timer(){
size_t nanoseconds = (std::chrono::system_clock::now() - start).count();
printf("Timer: %zu mus\n", nanoseconds / 1000);
}
private:
std::chrono::time_point<std::chrono::system_clock> start;
};
class Application { class Application {
public: public:
explicit Application(); explicit Application();
void mainLoop(); void mainLoop();
~Application(); ~Application();
private:
protected:
Swapchain* swapchain = nullptr; Swapchain* swapchain = nullptr;
Pipeline* graphicsPipeline = nullptr; Pipeline* graphicsPipeline = nullptr;
Buffer* vertexBuffer = nullptr; Buffer* vertexBuffer = nullptr;
@ -52,15 +42,16 @@ private:
void updateUniformBuffer(); void updateUniformBuffer();
void recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex); void recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex);
void recordComputeCommandBuffer();
VkSemaphore imageAvailableSemaphore = VK_NULL_HANDLE; Semaphore* imageAvailable = nullptr;
VkSemaphore renderFinishedSemaphore = VK_NULL_HANDLE; Semaphore* renderFinished = nullptr;
VkSemaphore computeFinishedSemaphore = VK_NULL_HANDLE; Semaphore* computeFinished = nullptr;
VkFence renderInFlightFence = VK_NULL_HANDLE; Fence* renderInFlight = nullptr;
VkFence computeInFlightFence = VK_NULL_HANDLE; Fence* computeInFlight = nullptr;
void drawFrame(); void drawFrame();
virtual void recordDrawCommands() {};
virtual void recordComputeCommands() {}
void update(); void update();
void createSyncObjects(); void createSyncObjects();
}; };

@ -0,0 +1,17 @@
#pragma once
#include <vulkan/vulkan.h>
class Semaphore {
public:
explicit Semaphore();
~Semaphore();
VkSemaphore handle = VK_NULL_HANDLE;
};
class Fence {
public:
explicit Fence(bool signaled);
~Fence();
VkFence handle = VK_NULL_HANDLE;
};

@ -1,3 +0,0 @@
#include <vulkan/vulkan_core.h>
uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags propertyFlags);

@ -12,5 +12,5 @@ layout (std140, binding = 0) buffer VertexBuffer {
}; };
void main() { void main() {
vertices[4].position.z += 0.001; vertices[0].position.z += 0.001;
} }

@ -1,8 +1,8 @@
#include "vulkan/application.hpp" #include "simulation.hpp"
#include <thread> #include <thread>
int main() { int main() {
Application application; Simulation simulation;
application.mainLoop(); simulation.mainLoop();
} }

@ -0,0 +1,33 @@
#include "simulation.hpp"
#include "vulkan/instance.hpp"
#include "vulkan/command_pool.hpp"
#include "vulkan/buffer.hpp"
#include "vulkan/pipeline.hpp"
#include "soft_body.hpp"
Simulation::Simulation() {
softBodies.push_back(std::make_unique<SoftBody>(""));
}
void Simulation::recordDrawCommands() {
VkCommandBuffer commandBuffer = Instance::instance->commandPool->graphicsBuffer;
VkBuffer buffers[] = {vertexBuffer->handle};
VkDeviceSize offsets[] = {0};
vkCmdBindVertexBuffers(commandBuffer, 0, 1, buffers, offsets);
vkCmdBindIndexBuffer(commandBuffer, indexBuffer->handle, 0, VK_INDEX_TYPE_UINT32);
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline->layout, 0, 1, &graphicsPipeline->descriptorSet, 0, nullptr);
vkCmdDrawIndexed(commandBuffer, 12, 1, 0, 0, 0);
}
void Simulation::recordComputeCommands() {
VkCommandBuffer commandBuffer = Instance::instance->commandPool->computeBuffer;
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, computePipeline->layout, 0, 1, &computePipeline->descriptorSet, 0, nullptr);
vkCmdDispatch(commandBuffer, 1, 1, 1);
}
Simulation::~Simulation() {
}

@ -0,0 +1,5 @@
#include "soft_body.hpp"
SoftBody::SoftBody(const std::string &fileName) {
}

@ -0,0 +1,11 @@
#include <cstdio>
#include "timer.hpp"
Timer::Timer() {
start = system_clock::now();
}
Timer::~Timer() {
size_t nanoseconds = (system_clock::now() - start).count();
printf("Timer: %zu mus\n", nanoseconds / 1000);
}

@ -5,6 +5,7 @@
#include "vulkan/buffer.hpp" #include "vulkan/buffer.hpp"
#include "vulkan/command_pool.hpp" #include "vulkan/command_pool.hpp"
#include "vulkan/image.hpp" #include "vulkan/image.hpp"
#include "vulkan/synchronization.hpp"
#include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/matrix_transform.hpp>
@ -53,17 +54,16 @@ Application::Application() {
createSyncObjects(); createSyncObjects();
recordComputeCommandBuffer();
char* stats; char* stats;
vmaBuildStatsString(Instance::instance->allocator, &stats, VK_TRUE); vmaBuildStatsString(Instance::instance->allocator, &stats, VK_TRUE);
// printf("%s", stats); // printf("%s", stats);
vmaFreeStatsString(Instance::instance->allocator, stats);
} }
void Application::updateUniformBuffer() { void Application::updateUniformBuffer() {
static float elapsed = 0; static float elapsed = 0;
elapsed += 0.007; // elapsed += 0.007;
UniformBufferObject ubo {}; UniformBufferObject ubo {};
ubo.model = glm::rotate(glm::mat4(1), elapsed * glm::radians(90.f), glm::vec3(0, 0, 1)); ubo.model = glm::rotate(glm::mat4(1), elapsed * glm::radians(90.f), glm::vec3(0, 0, 1));
@ -113,31 +113,18 @@ void Application::recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t im
scissor.extent = swapchain->extent; scissor.extent = swapchain->extent;
vkCmdSetScissor(commandBuffer, 0, 1, &scissor); vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
VkBuffer buffers[] = {vertexBuffer->handle}; recordDrawCommands();
VkDeviceSize offsets[] = {0};
vkCmdBindVertexBuffers(commandBuffer, 0, 1, buffers, offsets);
vkCmdBindIndexBuffer(commandBuffer, indexBuffer->handle, 0, VK_INDEX_TYPE_UINT32);
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline->layout, 0, 1, &graphicsPipeline->descriptorSet, 0, nullptr);
vkCmdDrawIndexed(commandBuffer, 12, 1, 0, 0, 0);
vkCmdEndRenderPass(commandBuffer); vkCmdEndRenderPass(commandBuffer);
vkEndCommandBuffer(commandBuffer); vkEndCommandBuffer(commandBuffer);
} }
void Application::createSyncObjects() { void Application::createSyncObjects() {
VkSemaphoreCreateInfo semaphoreInfo {}; imageAvailable = new Semaphore;
semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; renderFinished = new Semaphore;
computeFinished = new Semaphore;
VkFenceCreateInfo fenceInfo {}; renderInFlight = new Fence(true);
fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; computeInFlight = new Fence(true);
fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
vkCreateSemaphore(Instance::instance->device, &semaphoreInfo, nullptr, &imageAvailableSemaphore);
vkCreateSemaphore(Instance::instance->device, &semaphoreInfo, nullptr, &renderFinishedSemaphore);
vkCreateSemaphore(Instance::instance->device, &semaphoreInfo, nullptr, &computeFinishedSemaphore);
vkCreateFence(Instance::instance->device, &fenceInfo, nullptr, &renderInFlightFence);
vkCreateFence(Instance::instance->device, &fenceInfo, nullptr, &computeInFlightFence);
} }
void Application::mainLoop() { void Application::mainLoop() {
@ -150,16 +137,16 @@ void Application::mainLoop() {
} }
void Application::drawFrame() { void Application::drawFrame() {
vkWaitForFences(Instance::instance->device, 1, &renderInFlightFence, VK_TRUE, UINT64_MAX); vkWaitForFences(Instance::instance->device, 1, &renderInFlight->handle, VK_TRUE, UINT64_MAX);
uint32_t imageIndex; uint32_t imageIndex;
VkResult result = vkAcquireNextImageKHR(Instance::instance->device, swapchain->handle, UINT64_MAX, imageAvailableSemaphore, VK_NULL_HANDLE, &imageIndex); VkResult result = vkAcquireNextImageKHR(Instance::instance->device, swapchain->handle, UINT64_MAX, imageAvailable->handle, VK_NULL_HANDLE, &imageIndex);
if (result == VK_ERROR_OUT_OF_DATE_KHR){ if (result == VK_ERROR_OUT_OF_DATE_KHR){
swapchain->recreateSwapchain(); swapchain->recreateSwapchain();
return; return;
} }
vkResetFences(Instance::instance->device, 1, &renderInFlightFence); vkResetFences(Instance::instance->device, 1, &renderInFlight->handle);
vkResetCommandBuffer(Instance::instance->commandPool->graphicsBuffer, 0); vkResetCommandBuffer(Instance::instance->commandPool->graphicsBuffer, 0);
recordCommandBuffer(Instance::instance->commandPool->graphicsBuffer, imageIndex); recordCommandBuffer(Instance::instance->commandPool->graphicsBuffer, imageIndex);
@ -169,7 +156,7 @@ void Application::drawFrame() {
VkSubmitInfo submitInfo {}; VkSubmitInfo submitInfo {};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
VkSemaphore waitSemaphores[] = {imageAvailableSemaphore, computeFinishedSemaphore}; VkSemaphore waitSemaphores[] = {imageAvailable->handle, computeFinished->handle};
VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT}; VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT};
submitInfo.waitSemaphoreCount = 2; submitInfo.waitSemaphoreCount = 2;
submitInfo.pWaitSemaphores = waitSemaphores; submitInfo.pWaitSemaphores = waitSemaphores;
@ -177,11 +164,11 @@ void Application::drawFrame() {
submitInfo.commandBufferCount = 1; submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &Instance::instance->commandPool->graphicsBuffer; submitInfo.pCommandBuffers = &Instance::instance->commandPool->graphicsBuffer;
VkSemaphore signalSemaphores[] = {renderFinishedSemaphore}; VkSemaphore signalSemaphores[] = {renderFinished->handle};
submitInfo.signalSemaphoreCount = 1; submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = signalSemaphores; submitInfo.pSignalSemaphores = signalSemaphores;
vkQueueSubmit(Instance::instance->graphicsQueue, 1, &submitInfo, renderInFlightFence); vkQueueSubmit(Instance::instance->graphicsQueue, 1, &submitInfo, renderInFlight->handle);
VkPresentInfoKHR presentInfo {}; VkPresentInfoKHR presentInfo {};
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
@ -201,41 +188,40 @@ void Application::drawFrame() {
} }
void Application::update() { void Application::update() {
vkWaitForFences(Instance::instance->device, 1, &computeInFlightFence, VK_TRUE, UINT64_MAX); vkWaitForFences(Instance::instance->device, 1, &computeInFlight->handle, VK_TRUE, UINT64_MAX);
vkResetFences(Instance::instance->device, 1, &computeInFlightFence); vkResetFences(Instance::instance->device, 1, &computeInFlight->handle);
VkSubmitInfo submit {};
submit.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submit.commandBufferCount = 1;
submit.pCommandBuffers = &Instance::instance->commandPool->computeBuffer;
submit.signalSemaphoreCount = 1;
submit.pSignalSemaphores = &computeFinishedSemaphore;
vkQueueSubmit(Instance::instance->computeQueue, 1, &submit, computeInFlightFence);
}
void Application::recordComputeCommandBuffer() { VkCommandBuffer commandBuffer = Instance::instance->commandPool->computeBuffer;
VkCommandBuffer buffer = Instance::instance->commandPool->computeBuffer; vkResetCommandBuffer(commandBuffer, 0);
VkCommandBufferBeginInfo beginInfo {}; VkCommandBufferBeginInfo beginInfo {};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
beginInfo.flags = 0;
vkBeginCommandBuffer(buffer, &beginInfo);
vkCmdBindPipeline(buffer, VK_PIPELINE_BIND_POINT_COMPUTE, computePipeline->handle); vkBeginCommandBuffer(commandBuffer, &beginInfo);
vkCmdBindDescriptorSets(buffer, VK_PIPELINE_BIND_POINT_COMPUTE, computePipeline->layout,0, 1, &computePipeline->descriptorSet, 0, nullptr); vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, computePipeline->handle);
vkCmdDispatch(buffer, 1, 1, 1); recordComputeCommands();
vkEndCommandBuffer(commandBuffer);
VkSubmitInfo submit {};
submit.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submit.commandBufferCount = 1;
submit.pCommandBuffers = &Instance::instance->commandPool->computeBuffer;
submit.signalSemaphoreCount = 1;
submit.pSignalSemaphores = &computeFinished->handle;
vkEndCommandBuffer(buffer); vkQueueSubmit(Instance::instance->computeQueue, 1, &submit, computeInFlight->handle);
} }
Application::~Application() { Application::~Application() {
delete swapchain; delete swapchain;
vkDestroySemaphore(Instance::instance->device, imageAvailableSemaphore, nullptr); delete imageAvailable;
vkDestroySemaphore(Instance::instance->device, renderFinishedSemaphore, nullptr); delete renderFinished;
vkDestroySemaphore(Instance::instance->device, computeFinishedSemaphore, nullptr); delete computeFinished;
vkDestroyFence(Instance::instance->device, renderInFlightFence, nullptr); delete renderInFlight;
vkDestroyFence(Instance::instance->device, computeInFlightFence, nullptr); delete computeInFlight;
delete vertexBuffer; delete vertexBuffer;
delete indexBuffer; delete indexBuffer;
delete uniformBuffer; delete uniformBuffer;

@ -3,7 +3,6 @@
#include "vulkan/buffer.hpp" #include "vulkan/buffer.hpp"
#include "vulkan/instance.hpp" #include "vulkan/instance.hpp"
#include "vulkan/command_pool.hpp" #include "vulkan/command_pool.hpp"
#include "vulkan/utils.h"
#include "vk_mem_alloc.h" #include "vk_mem_alloc.h"

@ -1,7 +1,6 @@
#include <cstdio> #include <cstdio>
#include "vulkan/image.hpp" #include "vulkan/image.hpp"
#include "vulkan/instance.hpp" #include "vulkan/instance.hpp"
#include "vulkan/utils.h"
Image::Image(uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, Image::Image(uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling,

@ -0,0 +1,25 @@
#include "vulkan/synchronization.hpp"
#include "vulkan/instance.hpp"
Semaphore::Semaphore() {
VkSemaphoreCreateInfo semaphoreInfo {};
semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
vkCreateSemaphore(Instance::instance->device, &semaphoreInfo, nullptr, &handle);
}
Semaphore::~Semaphore() {
vkDestroySemaphore(Instance::instance->device, handle, nullptr);
}
Fence::Fence(bool signaled) {
VkFenceCreateInfo fenceInfo {};
fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
fenceInfo.flags = signaled ? VK_FENCE_CREATE_SIGNALED_BIT : 0;
vkCreateFence(Instance::instance->device, &fenceInfo, nullptr, &handle);
}
Fence::~Fence() {
vkDestroyFence(Instance::instance->device, handle, nullptr);
}

@ -1,17 +0,0 @@
#include <stdexcept>
#include "vulkan/utils.h"
#include "vulkan/instance.hpp"
uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags propertyFlags) {
VkPhysicalDeviceMemoryProperties memoryProperties;
vkGetPhysicalDeviceMemoryProperties(Instance::instance->physicalDevice, &memoryProperties);
for (uint32_t type = 0; type < memoryProperties.memoryTypeCount; type++){
if ((typeFilter & (1 << type)) && (memoryProperties.memoryTypes[type].propertyFlags & propertyFlags)){
return type;
}
}
throw std::runtime_error("failed to find suitable memory type!");
}
Loading…
Cancel
Save