Compare commits

...

3 Commits

  1. 18
      include/application.hpp
  2. 6
      include/camera.hpp
  3. 12
      include/constraints.hpp
  4. 15
      include/input.hpp
  5. 8
      include/soft_body.hpp
  6. 27
      include/vulkan/buffer.hpp
  7. 5
      include/vulkan/descriptor_pool.hpp
  8. 4
      include/vulkan/image.hpp
  9. 32
      include/vulkan/instance.hpp
  10. 12
      include/vulkan/pipeline.hpp
  11. 9
      include/vulkan/swapchain.hpp
  12. 2
      lib/imgui
  13. 381
      src/application.cpp
  14. 16
      src/camera.cpp
  15. 18
      src/constraints.cpp
  16. 4
      src/grabber.cpp
  17. 60
      src/input.cpp
  18. 12
      src/mesh.cpp
  19. 81
      src/soft_body.cpp
  20. 1
      src/stb_image.cpp
  21. 54
      src/vulkan/buffer.cpp
  22. 33
      src/vulkan/descriptor_pool.cpp
  23. 41
      src/vulkan/image.cpp
  24. 76
      src/vulkan/instance.cpp
  25. 31
      src/vulkan/pipeline.cpp
  26. 40
      src/vulkan/swapchain.cpp
  27. 1
      src/vulkan/vma.cpp

@ -26,19 +26,33 @@ using std::vector;
using std::optional; using std::optional;
class SoftBody; class SoftBody;
class Instance; class Instance;
class Swapchain; class Swapchain;
class GraphicsPipeline; class GraphicsPipeline;
class Buffer; class Buffer;
class Buffer; class Buffer;
class CommandPool; class CommandPool;
class Image; class Image;
class ComputePipeline; class ComputePipeline;
class Fence; class Fence;
class Semaphore; class Semaphore;
class Camera; class Camera;
class DescriptorPool; class DescriptorPool;
class Grabber; class Grabber;
struct SizesUniformData; struct SizesUniformData;
class Application { class Application {
@ -79,8 +93,8 @@ private:
unique_ptr<Grabber> grabber; unique_ptr<Grabber> grabber;
unique_ptr<Buffer> grabBuffer; unique_ptr<Buffer> grabBuffer;
void addSoftBody(const std::string& modelFile, size_t count=1); void addSoftBody(const std::string &modelFile, size_t count = 1);
void removeSoftBody(const unique_ptr<SoftBody>& softBody); void removeSoftBody(const unique_ptr<SoftBody> &softBody);
void updateConstraintBuffers(VkCommandBuffer commandBuffer); void updateConstraintBuffers(VkCommandBuffer commandBuffer);
size_t currentDrawVertexBuffer = 0; size_t currentDrawVertexBuffer = 0;

@ -18,14 +18,14 @@ private:
float near = 0.1; float near = 0.1;
float far = 100; float far = 100;
VkExtent2D& extent; VkExtent2D &extent;
public: public:
explicit Camera(VkExtent2D& extent); explicit Camera(VkExtent2D &extent);
void update(float dt); void update(float dt);
glm::mat4 view() const; glm::mat4 view() const;
glm::mat4 projection() const; glm::mat4 projection() const;
glm::vec2 viewport() const; glm::vec2 viewport() const;
glm::vec3 localToWorld(const glm::vec3& direction) const; glm::vec3 localToWorld(const glm::vec3 &direction) const;
protected: protected:
void mouseMoved(const glm::vec2 &delta) override; void mouseMoved(const glm::vec2 &delta) override;
}; };

@ -51,7 +51,7 @@ struct ConstraintData {
void recordNewPartition(); void recordNewPartition();
void writePartitionInformation(); void writePartitionInformation();
void insert(const ConstraintData& other); void insert(const ConstraintData &other);
private: private:
uint32_t prePartitionEdgeCount; uint32_t prePartitionEdgeCount;
uint32_t prePartitionTetrahedronCount; uint32_t prePartitionTetrahedronCount;
@ -62,20 +62,24 @@ private:
struct Constraint { struct Constraint {
virtual ~Constraint() {} virtual ~Constraint() {}
virtual void writeData(ConstraintData& dataLists) const {};
virtual void writeData(ConstraintData &dataLists) const {};
}; };
struct DistanceConstraint : Edge, Constraint { struct DistanceConstraint : Edge, Constraint {
explicit DistanceConstraint(const Edge &edge) : Edge(edge) {} explicit DistanceConstraint(const Edge &edge) : Edge(edge) {}
void writeData(ConstraintData &dataLists) const override; void writeData(ConstraintData &dataLists) const override;
}; };
struct AreaConstraint : Triangle, Constraint { struct AreaConstraint : Triangle, Constraint {
explicit AreaConstraint(const Triangle& triangle) : Triangle(triangle) {} explicit AreaConstraint(const Triangle &triangle) : Triangle(triangle) {}
void writeData(ConstraintData &dataLists) const override; void writeData(ConstraintData &dataLists) const override;
}; };
struct VolumeConstraint : Tetrahedron, Constraint { struct VolumeConstraint : Tetrahedron, Constraint {
explicit VolumeConstraint(const Tetrahedron& tetrahedron) : Tetrahedron(tetrahedron) {} explicit VolumeConstraint(const Tetrahedron &tetrahedron) : Tetrahedron(tetrahedron) {}
void writeData(ConstraintData &dataLists) const override; void writeData(ConstraintData &dataLists) const override;
}; };

@ -6,27 +6,28 @@
#include "glm/vec2.hpp" #include "glm/vec2.hpp"
class Listener; class Listener;
class MouseListener; class MouseListener;
class Input { class Input {
friend Listener; friend Listener;
friend MouseListener; friend MouseListener;
public: public:
explicit Input(GLFWwindow* window); explicit Input(GLFWwindow *window);
static Input* instance; static Input *instance;
static std::map<int, bool> KeyIsDown; static std::map<int, bool> KeyIsDown;
static std::map<int, bool> MouseButtonIsDown; static std::map<int, bool> MouseButtonIsDown;
glm::vec2 currentCursorPosition {}; glm::vec2 currentCursorPosition {};
private: private:
GLFWwindow* window; GLFWwindow *window;
std::set<Listener*> listeners; std::set<Listener *> listeners;
void keyPressed(int key); void keyPressed(int key);
void keyReleased(int key); void keyReleased(int key);
void mouseButtonPressed(int button); void mouseButtonPressed(int button);
void mouseButtonReleased(int button); void mouseButtonReleased(int button);
void mouseMoved(const glm::vec2& newCursorPosition); void mouseMoved(const glm::vec2 &newCursorPosition);
}; };
class Listener { class Listener {
@ -41,7 +42,9 @@ class KeyListener : Listener {
class MouseListener : public Listener { class MouseListener : public Listener {
public: public:
virtual void mouseMoved(const glm::vec2& delta) {}; virtual void mouseMoved(const glm::vec2 &delta) {};
virtual void mouseButtonPressed(int button) {}; virtual void mouseButtonPressed(int button) {};
virtual void mouseButtonReleased(int button) {}; virtual void mouseButtonReleased(int button) {};
}; };

@ -14,13 +14,13 @@ using std::vector;
struct Vertex; struct Vertex;
typedef unordered_map<const Constraint*, vector<const Constraint *>> Graph; typedef unordered_map<const Constraint *, vector<const Constraint *>> Graph;
class Mesh; class Mesh;
class SoftBody { class SoftBody {
public: public:
explicit SoftBody(Mesh* mesh, float edgeCompliance, float triangleCompliance=0, float tetrahedronCompliance=0); explicit SoftBody(Mesh *mesh, float edgeCompliance, float triangleCompliance = 0, float tetrahedronCompliance = 0);
uint32_t firstIndex = 0; uint32_t firstIndex = 0;
int32_t vertexOffset = 0; int32_t vertexOffset = 0;
@ -28,9 +28,9 @@ public:
vector<Face> faces; vector<Face> faces;
ConstraintData constraintData; ConstraintData constraintData;
void applyVertexWorldOffset(const glm::vec3& offset); void applyVertexWorldOffset(const glm::vec3 &offset);
SoftBody& operator =(const SoftBody& other) = delete; SoftBody &operator=(const SoftBody &other) = delete;
private: private:
void splitConstraints(); void splitConstraints();
void reorderConstraintIndices(const vector<unordered_set<const Constraint *>> &partitions); void reorderConstraintIndices(const vector<unordered_set<const Constraint *>> &partitions);

@ -18,25 +18,28 @@ class Image;
class Buffer { class Buffer {
public: public:
Buffer(VkDeviceSize bufferSize, VkBufferUsageFlags bufferUsage, Buffer(VkDeviceSize bufferSize, VkBufferUsageFlags bufferUsage,
VmaMemoryUsage memoryUsage, VmaAllocationCreateFlags vmaAllocationFlags); VmaMemoryUsage memoryUsage, VmaAllocationCreateFlags vmaAllocationFlags,
unique_ptr<Buffer> appended(void* data, VkDeviceSize appendSize, VkCommandBuffer commandBuffer) const; const std::string &name = "");
unique_ptr<Buffer> replaced(void* data, VkDeviceSize replaceSize, VkCommandBuffer commandBuffer) const; unique_ptr<Buffer> appended(void *data, VkDeviceSize appendSize, VkCommandBuffer commandBuffer) const;
unique_ptr<Buffer> replaced(void *data, VkDeviceSize replaceSize, VkCommandBuffer commandBuffer) const;
virtual ~Buffer(); virtual ~Buffer();
VkBuffer handle = VK_NULL_HANDLE; VkBuffer handle = VK_NULL_HANDLE;
VmaAllocation allocation = VK_NULL_HANDLE; VmaAllocation allocation = VK_NULL_HANDLE;
VmaAllocationInfo allocationInfo {}; VmaAllocationInfo allocationInfo {};
VkDeviceSize size; VkDeviceSize size;
void setName(const std::string& newName); void setName(const std::string &newName);
template <typename T>
T& access(){ template<typename T>
return *reinterpret_cast<T*>(allocationInfo.pMappedData); T &access() {
return *reinterpret_cast<T *>(allocationInfo.pMappedData);
} }
void copyTo(Buffer* buffer) const;
void copyTo(Image* image) const; void copyTo(Buffer *buffer) const;
void setData(void* data, VkDeviceSize offset, VkDeviceSize dataSize, VkCommandBuffer commandBuffer=VK_NULL_HANDLE); void copyTo(Image *image) const;
void setData(void *data, VkDeviceSize offset, VkDeviceSize dataSize, VkCommandBuffer commandBuffer = VK_NULL_HANDLE);
shared_ptr<Buffer> getStagingBuffer(); shared_ptr<Buffer> getStagingBuffer();
Buffer(const Buffer& other) = delete; Buffer(const Buffer &other) = delete;
Buffer& operator =(const Buffer& other) = delete; Buffer &operator=(const Buffer &other) = delete;
private: private:
optional<shared_ptr<Buffer>> stagingBufferOptional; optional<shared_ptr<Buffer>> stagingBufferOptional;
std::string name; std::string name;

@ -5,6 +5,7 @@
#include <map> #include <map>
class Buffer; class Buffer;
class Image; class Image;
enum class DescriptorSet { enum class DescriptorSet {
@ -18,8 +19,8 @@ public:
DescriptorPool(); DescriptorPool();
~DescriptorPool(); ~DescriptorPool();
void bindBuffer(const Buffer& buffer, VkDescriptorType type, DescriptorSet set, uint32_t binding); void bindBuffer(const Buffer &buffer, VkDescriptorType type, DescriptorSet set, uint32_t binding);
void bindImage(const Image& image, VkDescriptorType type, DescriptorSet set, uint32_t binding); void bindImage(const Image &image, VkDescriptorType type, DescriptorSet set, uint32_t binding);
std::map<DescriptorSet, VkDescriptorSet> sets; std::map<DescriptorSet, VkDescriptorSet> sets;
std::map<DescriptorSet, VkDescriptorSetLayout> layouts; std::map<DescriptorSet, VkDescriptorSetLayout> layouts;
VkDescriptorPool handle = VK_NULL_HANDLE; VkDescriptorPool handle = VK_NULL_HANDLE;

@ -8,8 +8,8 @@ class Instance;
class Image { class Image {
public: public:
Image(uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, Image(uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling,
VkImageUsageFlags usage); VkImageUsageFlags usage);
Image(void* initialData, VkDeviceSize size, uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, Image(void *initialData, VkDeviceSize size, uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling,
VkImageUsageFlags usage); VkImageUsageFlags usage);
~Image(); ~Image();

@ -14,6 +14,7 @@
using std::optional, std::vector; using std::optional, std::vector;
class CommandPool; class CommandPool;
class Swapchain; class Swapchain;
void printVmaStats(); void printVmaStats();
@ -29,39 +30,26 @@ public:
bool windowResized = false; bool windowResized = false;
CommandPool* renderingCommandPool = nullptr; CommandPool *renderingCommandPool = nullptr;
CommandPool* computeCommandPool = nullptr; CommandPool *computeCommandPool = nullptr;
struct QueueFamilyIndices { struct QueueFamilyIndices {
vector<uint32_t> graphicsAndPresent; vector<uint32_t> graphicsAndPresent;
vector<uint32_t> computeAndTransfer; vector<uint32_t> computeAndTransfer;
std::set<uint32_t> uniqueQueueFamilies(){ std::set<uint32_t> uniqueQueueFamilies();
std::set<uint32_t> unique; uint32_t tryComputeAndTransferDedicated();
unique.insert(graphicsAndPresent.begin(), graphicsAndPresent.end()); bool isEnough();
unique.insert(computeAndTransfer.begin(), computeAndTransfer.end());
return unique;
}
uint32_t tryComputeAndTransferDedicated(){
for (uint32_t family : computeAndTransfer){
if (std::find(graphicsAndPresent.begin(), graphicsAndPresent.end(), family) == graphicsAndPresent.end()){
return family;
}
}
return computeAndTransfer[0];
}
bool isEnough(){
return !graphicsAndPresent.empty() && !computeAndTransfer.empty();
}
}; };
QueueFamilyIndices indices {}; QueueFamilyIndices indices {};
static Instance* instance; static Instance *instance;
static VkDevice GetDevice(); static VkDevice GetDevice();
static VkPhysicalDevice GetPhysicalDevice(); static VkPhysicalDevice GetPhysicalDevice();
static VmaAllocator GetAllocator(); static VmaAllocator GetAllocator();
static VkSurfaceKHR GetSurface(); static VkSurfaceKHR GetSurface();
void initImGui(const Swapchain& swapchain); void initImGui(const Swapchain &swapchain);
private: private:
VkPhysicalDevice physicalDevice = VK_NULL_HANDLE; VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;
VkDevice device = VK_NULL_HANDLE; VkDevice device = VK_NULL_HANDLE;

@ -20,15 +20,15 @@ protected:
class GraphicsPipeline : public Pipeline { class GraphicsPipeline : public Pipeline {
public: public:
explicit GraphicsPipeline(const std::string& vertexShaderPath, const std::string& fragmentShaderPath, explicit GraphicsPipeline(const std::string &vertexShaderPath, const std::string &fragmentShaderPath,
VkRenderPass renderPass, VkRenderPass renderPass,
const std::vector<VkDescriptorSetLayout> &descriptorSetLayouts={}, const std::vector<VkDescriptorSetLayout> &descriptorSetLayouts = {},
const std::vector<VkPushConstantRange> &pushConstantRanges={}); const std::vector<VkPushConstantRange> &pushConstantRanges = {});
}; };
class ComputePipeline : public Pipeline { class ComputePipeline : public Pipeline {
public: public:
explicit ComputePipeline(const std::string& shaderFile, explicit ComputePipeline(const std::string &shaderFile,
const std::vector<VkDescriptorSetLayout> &descriptorSetLayouts={}, const std::vector<VkDescriptorSetLayout> &descriptorSetLayouts = {},
const std::vector<VkPushConstantRange> &pushConstantRanges={}); const std::vector<VkPushConstantRange> &pushConstantRanges = {});
}; };

@ -4,6 +4,7 @@
#include <vector> #include <vector>
class Image; class Image;
class Instance; class Instance;
struct SwapchainSupportDetails { struct SwapchainSupportDetails {
@ -34,15 +35,15 @@ private:
void createRenderpass(); void createRenderpass();
Image* depthImage = nullptr; Image *depthImage = nullptr;
void createDepthResources(); void createDepthResources();
void createFramebuffers(); void createFramebuffers();
static VkSurfaceFormatKHR chooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& availableFormats); static VkSurfaceFormatKHR chooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR> &availableFormats);
static VkPresentModeKHR chooseSwapPresentMode(const std::vector<VkPresentModeKHR>& availablePresentModes); static VkPresentModeKHR chooseSwapPresentMode(const std::vector<VkPresentModeKHR> &availablePresentModes);
VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities); VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR &capabilities);
void createSwapchain(); void createSwapchain();
}; };

@ -1 +1 @@
Subproject commit 4e2126ee44c066c642d89d25320fd32e449e5a9a Subproject commit 646df390032f64eb03f8b5e2e5cbaf0c8e3bb237

@ -62,15 +62,21 @@ Application::Application() {
swapchain = make_unique<Swapchain>(); swapchain = make_unique<Swapchain>();
Instance::instance->initImGui(*swapchain); Instance::instance->initImGui(*swapchain);
descriptorPool = make_unique<DescriptorPool>(); descriptorPool = make_unique<DescriptorPool>();
graphicsPipeline = unique_ptr<GraphicsPipeline>(new GraphicsPipeline("shaders/vert.spv", "shaders/frag.spv", graphicsPipeline = unique_ptr<GraphicsPipeline>(
swapchain->renderPass, new GraphicsPipeline(
{descriptorPool->layouts[DescriptorSet::WORLD]})); "shaders/vert.spv", "shaders/frag.spv",
swapchain->renderPass,
cameraUniformBuffer = make_unique<Buffer>(sizeof(CameraUniformData), {descriptorPool->layouts[DescriptorSet::WORLD]}
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, )
VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE, );
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT);
cameraUniformBuffer->setName("Camera"); cameraUniformBuffer = make_unique<Buffer>(
sizeof(CameraUniformData),
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE,
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT,
"Camera"
);
camera = make_unique<Camera>(swapchain->extent); camera = make_unique<Camera>(swapchain->extent);
updateCameraBuffer(); updateCameraBuffer();
@ -81,10 +87,11 @@ Application::Application() {
bool grabbing; bool grabbing;
} initialGrabInformation {}; } initialGrabInformation {};
initialGrabInformation.distanceToFace = 1e20; initialGrabInformation.distanceToFace = 1e20;
grabBuffer = make_unique<Buffer>(sizeof(GrabInformation), grabBuffer = make_unique<Buffer>(
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, sizeof(GrabInformation),
VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE, 0); VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
grabBuffer->setName("Grab"); VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE, 0, "Grab"
);
grabBuffer->setData(&initialGrabInformation, 0, sizeof(initialGrabInformation)); grabBuffer->setData(&initialGrabInformation, 0, sizeof(initialGrabInformation));
grabber = make_unique<Grabber>(); grabber = make_unique<Grabber>();
@ -92,32 +99,37 @@ Application::Application() {
sizeof(SizesUniformData), sizeof(SizesUniformData),
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE, VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE,
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT); VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT,
sizeInformationBuffer->setName("Sizes"); "Sizes"
);
sizeInformation = &sizeInformationBuffer->access<SizesUniformData>(); sizeInformation = &sizeInformationBuffer->access<SizesUniformData>();
*sizeInformation = {}; *sizeInformation = {};
addSoftBody("models/bunny_medium.ply", 10); addSoftBody("models/bunny_medium.ply", 10);
SimulationUniformData simulationUniformData { SimulationUniformData simulationUniformData {
.gravity = {0, -9.81, 0}, .gravity = {0, -9.81, 0},
.dt = 1.f / 60.f, .dt = 1.f / 60.f,
.k = 10, .k = 10,
}; };
simulationPropertiesBuffer = make_unique<Buffer>( simulationPropertiesBuffer = make_unique<Buffer>(
sizeof(SimulationUniformData), sizeof(SimulationUniformData),
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE, VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE,
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT); VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT,
simulationPropertiesBuffer->setName("Simulation properties"); "Simulation properties"
);
simulationPropertiesBuffer->access<SimulationUniformData>() = simulationUniformData; simulationPropertiesBuffer->access<SimulationUniformData>() = simulationUniformData;
{ {
int w, h; int w, h;
stbi_uc* data = stbi_load("textures/rocky_diff.jpg", &w, &h, nullptr, STBI_rgb_alpha); stbi_uc *data = stbi_load("textures/rocky_diff.jpg", &w, &h, nullptr, STBI_rgb_alpha);
VkDeviceSize imageSize = w * h * 4; VkDeviceSize imageSize = w * h * 4;
firstImage = make_unique<Image>(data, imageSize, w, h, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); firstImage = make_unique<Image>(
data, imageSize, w, h, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT
);
firstImage->createView(VK_IMAGE_ASPECT_COLOR_BIT); firstImage->createView(VK_IMAGE_ASPECT_COLOR_BIT);
firstImage->createSampler(); firstImage->createSampler();
} }
@ -125,7 +137,9 @@ Application::Application() {
descriptorPool->bindBuffer(*cameraUniformBuffer, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, DescriptorSet::WORLD, 0); descriptorPool->bindBuffer(*cameraUniformBuffer, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, DescriptorSet::WORLD, 0);
descriptorPool->bindImage(*firstImage, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, DescriptorSet::WORLD, 2); descriptorPool->bindImage(*firstImage, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, DescriptorSet::WORLD, 2);
descriptorPool->bindBuffer(*simulationPropertiesBuffer, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, DescriptorSet::SIMULATION, 0); descriptorPool->bindBuffer(
*simulationPropertiesBuffer, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, DescriptorSet::SIMULATION, 0
);
descriptorPool->bindBuffer(*grabBuffer, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, DescriptorSet::SIMULATION, 1); descriptorPool->bindBuffer(*grabBuffer, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, DescriptorSet::SIMULATION, 1);
createComputePipelines(); createComputePipelines();
@ -135,24 +149,28 @@ Application::Application() {
void Application::mainLoop() { void Application::mainLoop() {
vkDeviceWaitIdle(Instance::GetDevice()); vkDeviceWaitIdle(Instance::GetDevice());
std::future compute = std::async(std::launch::async, [this](){ std::future compute = std::async(
while (!glfwWindowShouldClose(Instance::instance->window)){ std::launch::async, [this]() {
auto t1 = system_clock::now(); while (!glfwWindowShouldClose(Instance::instance->window)) {
update(); auto t1 = system_clock::now();
auto t2 = system_clock::now(); update();
auto t2 = system_clock::now();
auto measuredUpdateDuration = duration<float>(t2 - t1);
auto requestedUpdateDuration = duration<float>( auto measuredUpdateDuration = duration<float>(t2 - t1);
simulationPropertiesBuffer->access<SimulationUniformData>().dt); auto requestedUpdateDuration = duration<float>(
std::this_thread::sleep_for(requestedUpdateDuration - measuredUpdateDuration); simulationPropertiesBuffer->access<SimulationUniformData>().dt
);
performanceInformation.updateDuration = measuredUpdateDuration.count(); std::this_thread::sleep_for(requestedUpdateDuration - measuredUpdateDuration);
performanceInformation.recentTotalUpdateDurations.push(std::max(requestedUpdateDuration, measuredUpdateDuration).count());
} performanceInformation.updateDuration = measuredUpdateDuration.count();
}); performanceInformation.recentTotalUpdateDurations.push(
std::max(requestedUpdateDuration, measuredUpdateDuration).count());
}
}
);
auto t1 = system_clock::now(); auto t1 = system_clock::now();
while (!glfwWindowShouldClose(Instance::instance->window)){ while (!glfwWindowShouldClose(Instance::instance->window)) {
glfwPollEvents(); glfwPollEvents();
imGuiWindows(); imGuiWindows();
@ -189,7 +207,7 @@ void Application::addSoftBody(const std::string &modelFile, size_t count) {
vector<Vertex> newVertices; vector<Vertex> newVertices;
vector<Face> newFaces; vector<Face> newFaces;
for (size_t i = 0; i < count; i++){ for (size_t i = 0; i < count; i++) {
// Local copy // Local copy
auto softBody = std::make_unique<SoftBody>(*original.get()); auto softBody = std::make_unique<SoftBody>(*original.get());
@ -205,21 +223,21 @@ void Application::addSoftBody(const std::string &modelFile, size_t count) {
// Vertex offset added manually for easy access in Compute Shaders // Vertex offset added manually for easy access in Compute Shaders
{ {
auto vertexOffset = softBody->vertexOffset; auto vertexOffset = softBody->vertexOffset;
for (auto &face : softBody->faces){ for (auto &face: softBody->faces) {
face.a += vertexOffset; face.a += vertexOffset;
face.b += vertexOffset; face.b += vertexOffset;
face.c += vertexOffset; face.c += vertexOffset;
} }
for (auto &edge : softBody->constraintData.edges){ for (auto &edge: softBody->constraintData.edges) {
edge.a += vertexOffset; edge.a += vertexOffset;
edge.b += vertexOffset; edge.b += vertexOffset;
} }
for (auto &triangle : softBody->constraintData.triangles){ for (auto &triangle: softBody->constraintData.triangles) {
triangle.a += vertexOffset; triangle.a += vertexOffset;
triangle.b += vertexOffset; triangle.b += vertexOffset;
triangle.c += vertexOffset; triangle.c += vertexOffset;
} }
for (auto &tetrahedron : softBody->constraintData.tetrahedra){ for (auto &tetrahedron: softBody->constraintData.tetrahedra) {
tetrahedron.a += vertexOffset; tetrahedron.a += vertexOffset;
tetrahedron.b += vertexOffset; tetrahedron.b += vertexOffset;
tetrahedron.c += vertexOffset; tetrahedron.c += vertexOffset;
@ -247,27 +265,46 @@ void Application::addSoftBody(const std::string &modelFile, size_t count) {
auto commandBuffer = Instance::instance->renderingCommandPool->beginSingleTimeCommandBuffer(); auto commandBuffer = Instance::instance->renderingCommandPool->beginSingleTimeCommandBuffer();
VkBufferUsageFlags bufferUsageFlags = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT; VkBufferUsageFlags bufferUsageFlags =
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
VmaMemoryUsage memoryUsage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE; VmaMemoryUsage memoryUsage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE;
if (vertexBuffers[0] == nullptr){ if (vertexBuffers[0] == nullptr) {
newVertexBuffers[0] = make_unique<Buffer>(newVertices.size() * sizeof(Vertex), newVertexBuffers[0] = make_unique<Buffer>(
bufferUsageFlags | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, newVertices.size() * sizeof(Vertex),
memoryUsage, 0); bufferUsageFlags | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
newVertexBuffers[1] = make_unique<Buffer>(newVertices.size() * sizeof(Vertex), memoryUsage,
bufferUsageFlags | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, 0,
memoryUsage, 0); "Vertices 0"
newFaceBuffer = make_unique<Buffer>(newFaces.size() * sizeof(Face), );
bufferUsageFlags | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, newVertexBuffers[1] = make_unique<Buffer>(
memoryUsage, 0); newVertices.size() * sizeof(Vertex),
newEdgeBuffer = make_unique<Buffer>(constraintData.edges.size() * sizeof(Edge), bufferUsageFlags, memoryUsage, 0); bufferUsageFlags | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
newTetrahedronBuffer = make_unique<Buffer>(constraintData.tetrahedra.size() * sizeof(Tetrahedron), bufferUsageFlags, memoryUsage, 0); memoryUsage,
0,
newVertexBuffers[0]->setName("Vertices 0"); "Vertices 1"
newVertexBuffers[1]->setName("Vertices 1"); );
newFaceBuffer->setName("Faces"); newFaceBuffer = make_unique<Buffer>(
newEdgeBuffer->setName("Edges"); newFaces.size() * sizeof(Face),
newTetrahedronBuffer->setName("Tetrahedra"); bufferUsageFlags | VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
memoryUsage,
0,
"Faces"
);
newEdgeBuffer = make_unique<Buffer>(
constraintData.edges.size() * sizeof(Edge),
bufferUsageFlags,
memoryUsage,
0,
"Edges"
);
newTetrahedronBuffer = make_unique<Buffer>(
constraintData.tetrahedra.size() * sizeof(Tetrahedron),
bufferUsageFlags,
memoryUsage,
0,
"Tetrahedra"
);
newVertexBuffers[0]->setData(newVertices.data(), 0, newVertexBuffers[0]->size, commandBuffer); newVertexBuffers[0]->setData(newVertices.data(), 0, newVertexBuffers[0]->size, commandBuffer);
newVertexBuffers[1]->setData(newVertices.data(), 0, newVertexBuffers[1]->size, commandBuffer); newVertexBuffers[1]->setData(newVertices.data(), 0, newVertexBuffers[1]->size, commandBuffer);
@ -275,11 +312,31 @@ void Application::addSoftBody(const std::string &modelFile, size_t count) {
newEdgeBuffer->setData(constraintData.edges.data(), 0, newEdgeBuffer->size, commandBuffer); newEdgeBuffer->setData(constraintData.edges.data(), 0, newEdgeBuffer->size, commandBuffer);
newTetrahedronBuffer->setData(constraintData.tetrahedra.data(), 0, newTetrahedronBuffer->size, commandBuffer); newTetrahedronBuffer->setData(constraintData.tetrahedra.data(), 0, newTetrahedronBuffer->size, commandBuffer);
} else { } else {
newVertexBuffers[0] = vertexBuffers[0]->appended(newVertices.data(), newVertices.size() * sizeof(Vertex), commandBuffer); newVertexBuffers[0] = vertexBuffers[0]->appended(
newVertexBuffers[1] = vertexBuffers[1]->appended(newVertices.data(), newVertices.size() * sizeof(Vertex), commandBuffer); newVertices.data(),
newFaceBuffer = faceBuffer->appended(newFaces.data(), newFaces.size() * sizeof(Face), commandBuffer); newVertices.size() * sizeof(Vertex),
newEdgeBuffer = edgeBuffer->replaced(constraintData.edges.data(), constraintData.edges.size() * sizeof(Edge), commandBuffer); commandBuffer
newTetrahedronBuffer = tetrahedronBuffer->replaced(constraintData.tetrahedra.data(), constraintData.tetrahedra.size() * sizeof(Tetrahedron), commandBuffer); );
newVertexBuffers[1] = vertexBuffers[1]->appended(
newVertices.data(),
newVertices.size() * sizeof(Vertex),
commandBuffer
);
newFaceBuffer = faceBuffer->appended(
newFaces.data(),
newFaces.size() * sizeof(Face),
commandBuffer
);
newEdgeBuffer = edgeBuffer->replaced(
constraintData.edges.data(),
constraintData.edges.size() * sizeof(Edge),
commandBuffer
);
newTetrahedronBuffer = tetrahedronBuffer->replaced(
constraintData.tetrahedra.data(),
constraintData.tetrahedra.size() * sizeof(Tetrahedron),
commandBuffer
);
} }
VkQueue queue = Instance::instance->graphicsAndPresentQueue; VkQueue queue = Instance::instance->graphicsAndPresentQueue;
@ -330,11 +387,13 @@ void Application::createComputePipelines() {
layouts.push_back(descriptorPool->layouts[DescriptorSet::MESH]); layouts.push_back(descriptorPool->layouts[DescriptorSet::MESH]);
layouts.push_back(descriptorPool->layouts[DescriptorSet::WORLD]); layouts.push_back(descriptorPool->layouts[DescriptorSet::WORLD]);
layouts.push_back(descriptorPool->layouts[DescriptorSet::SIMULATION]); layouts.push_back(descriptorPool->layouts[DescriptorSet::SIMULATION]);
pushRanges.push_back({ pushRanges.push_back(
.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, {
.offset = 0, .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
.size = sizeof(GrabPushData) .offset = 0,
}); .size = sizeof(GrabPushData)
}
);
grabPipeline = unique_ptr<ComputePipeline>(new ComputePipeline("shaders/grab.spv", layouts, pushRanges)); grabPipeline = unique_ptr<ComputePipeline>(new ComputePipeline("shaders/grab.spv", layouts, pushRanges));
} }
@ -344,11 +403,13 @@ void Application::createComputePipelines() {
{ {
layouts.push_back(descriptorPool->layouts[DescriptorSet::MESH]); layouts.push_back(descriptorPool->layouts[DescriptorSet::MESH]);
layouts.push_back(descriptorPool->layouts[DescriptorSet::SIMULATION]); layouts.push_back(descriptorPool->layouts[DescriptorSet::SIMULATION]);
pushRanges.push_back({ pushRanges.push_back(
.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, {
.offset = 0, .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
.size = sizeof(PBDPushData) .offset = 0,
}); .size = sizeof(PBDPushData)
}
);
pbdPipeline = unique_ptr<ComputePipeline>(new ComputePipeline("shaders/pbd.spv", layouts, pushRanges)); pbdPipeline = unique_ptr<ComputePipeline>(new ComputePipeline("shaders/pbd.spv", layouts, pushRanges));
} }
@ -357,18 +418,20 @@ void Application::createComputePipelines() {
{ {
layouts.push_back(descriptorPool->layouts[DescriptorSet::MESH]); layouts.push_back(descriptorPool->layouts[DescriptorSet::MESH]);
pushRanges.push_back({ pushRanges.push_back(
.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, {
.offset = 0, .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
.size = sizeof(uint32_t) .offset = 0,
}); .size = sizeof(uint32_t)
}
);
normalPipeline = unique_ptr<ComputePipeline>(new ComputePipeline("shaders/normal.spv", layouts, pushRanges)); normalPipeline = unique_ptr<ComputePipeline>(new ComputePipeline("shaders/normal.spv", layouts, pushRanges));
} }
} }
void Application::updateCameraBuffer() { void Application::updateCameraBuffer() {
CameraUniformData& data = cameraUniformBuffer->access<CameraUniformData>(); CameraUniformData &data = cameraUniformBuffer->access<CameraUniformData>();
data.view = camera->view(); data.view = camera->view();
data.projection = camera->projection(); data.projection = camera->projection();
data.projection[1][1] *= -1; data.projection[1][1] *= -1;
@ -379,8 +442,10 @@ void Application::drawFrame(float dt) {
vkWaitForFences(Instance::GetDevice(), 1, &renderFence->handle, VK_TRUE, UINT64_MAX); vkWaitForFences(Instance::GetDevice(), 1, &renderFence->handle, VK_TRUE, UINT64_MAX);
uint32_t imageIndex; uint32_t imageIndex;
VkResult result = vkAcquireNextImageKHR(Instance::GetDevice(), swapchain->handle, UINT64_MAX, imageAvailable->handle, VK_NULL_HANDLE, &imageIndex); VkResult result = vkAcquireNextImageKHR(
if (result == VK_ERROR_OUT_OF_DATE_KHR){ Instance::GetDevice(), swapchain->handle, UINT64_MAX, imageAvailable->handle, VK_NULL_HANDLE, &imageIndex
);
if (result == VK_ERROR_OUT_OF_DATE_KHR) {
submitMutex.lock(); submitMutex.lock();
swapchain->recreateSwapchain(); swapchain->recreateSwapchain();
submitMutex.unlock(); submitMutex.unlock();
@ -396,12 +461,12 @@ void Application::drawFrame(float dt) {
{ {
vkResetCommandBuffer(cmdBuffer, 0); vkResetCommandBuffer(cmdBuffer, 0);
VkCommandBufferBeginInfo beginInfo{}; VkCommandBufferBeginInfo beginInfo {};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
vkBeginCommandBuffer(cmdBuffer, &beginInfo); vkBeginCommandBuffer(cmdBuffer, &beginInfo);
VkBufferMemoryBarrier vertexBufferBarrier{}; VkBufferMemoryBarrier vertexBufferBarrier {};
vertexBufferBarrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; vertexBufferBarrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
vertexBufferBarrier.size = vertexBuffers[currentDrawVertexBuffer]->size; vertexBufferBarrier.size = vertexBuffers[currentDrawVertexBuffer]->size;
vertexBufferBarrier.offset = 0; vertexBufferBarrier.offset = 0;
@ -414,17 +479,19 @@ void Application::drawFrame(float dt) {
barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT; barrier.dstAccessMask = VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
vkCmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0, 1, vkCmdPipelineBarrier(
&barrier, 1, &vertexBufferBarrier, 0, nullptr); cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0, 1,
&barrier, 1, &vertexBufferBarrier, 0, nullptr
);
VkRenderPassBeginInfo renderPassInfo{}; VkRenderPassBeginInfo renderPassInfo {};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
renderPassInfo.renderPass = swapchain->renderPass; renderPassInfo.renderPass = swapchain->renderPass;
renderPassInfo.framebuffer = swapchain->frameBuffers[imageIndex]; renderPassInfo.framebuffer = swapchain->frameBuffers[imageIndex];
renderPassInfo.renderArea.offset = {0, 0}; renderPassInfo.renderArea.offset = {0, 0};
renderPassInfo.renderArea.extent = swapchain->extent; renderPassInfo.renderArea.extent = swapchain->extent;
VkClearValue clearValues[2]{}; VkClearValue clearValues[2] {};
clearValues[0].color = {{0, 0, 0, 1}}; clearValues[0].color = {{0, 0, 0, 1}};
clearValues[1].depthStencil = {1.0f, 0}; clearValues[1].depthStencil = {1.0f, 0};
@ -433,7 +500,7 @@ void Application::drawFrame(float dt) {
vkCmdBeginRenderPass(cmdBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE); vkCmdBeginRenderPass(cmdBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
VkViewport viewport{}; VkViewport viewport {};
viewport.x = 0; viewport.x = 0;
viewport.y = 0; viewport.y = 0;
viewport.width = static_cast<float>(swapchain->extent.width); viewport.width = static_cast<float>(swapchain->extent.width);
@ -442,7 +509,7 @@ void Application::drawFrame(float dt) {
viewport.maxDepth = 1; viewport.maxDepth = 1;
vkCmdSetViewport(cmdBuffer, 0, 1, &viewport); vkCmdSetViewport(cmdBuffer, 0, 1, &viewport);
VkRect2D scissor{}; VkRect2D scissor {};
scissor.offset = {0, 0}; scissor.offset = {0, 0};
scissor.extent = swapchain->extent; scissor.extent = swapchain->extent;
vkCmdSetScissor(cmdBuffer, 0, 1, &scissor); vkCmdSetScissor(cmdBuffer, 0, 1, &scissor);
@ -489,7 +556,7 @@ void Application::drawFrame(float dt) {
result = vkQueuePresentKHR(Instance::instance->graphicsAndPresentQueue, &presentInfo); result = vkQueuePresentKHR(Instance::instance->graphicsAndPresentQueue, &presentInfo);
submitMutex.unlock(); submitMutex.unlock();
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || Instance::instance->windowResized){ if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || Instance::instance->windowResized) {
Instance::instance->windowResized = false; Instance::instance->windowResized = false;
submitMutex.lock(); submitMutex.lock();
swapchain->recreateSwapchain(); swapchain->recreateSwapchain();
@ -504,9 +571,12 @@ void Application::recordDrawCommands(VkCommandBuffer commandBuffer) {
VkDeviceSize offsets[] = {0}; VkDeviceSize offsets[] = {0};
vkCmdBindVertexBuffers(commandBuffer, 0, 1, buffers, offsets); vkCmdBindVertexBuffers(commandBuffer, 0, 1, buffers, offsets);
vkCmdBindIndexBuffer(commandBuffer, faceBuffer->handle, 0, VK_INDEX_TYPE_UINT32); vkCmdBindIndexBuffer(commandBuffer, faceBuffer->handle, 0, VK_INDEX_TYPE_UINT32);
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline->layout, 0, 1, &descriptorPool->sets[DescriptorSet::WORLD], 0, nullptr); vkCmdBindDescriptorSets(
commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline->layout, 0, 1,
&descriptorPool->sets[DescriptorSet::WORLD], 0, nullptr
);
for (const auto &softBody : softBodies){ for (const auto &softBody: softBodies) {
vkCmdDrawIndexed(commandBuffer, softBody->faces.size() * 3, 1, softBody->firstIndex, 0, 0); vkCmdDrawIndexed(commandBuffer, softBody->faces.size() * 3, 1, softBody->firstIndex, 0, 0);
} }
} }
@ -551,7 +621,10 @@ void Application::update() {
copyRegion.srcOffset = 0; copyRegion.srcOffset = 0;
copyRegion.dstOffset = 0; copyRegion.dstOffset = 0;
vkCmdCopyBuffer(cmdBuffer, vertexBuffers[1 - currentDrawVertexBuffer]->handle, vertexBuffers[currentDrawVertexBuffer]->handle, 1, &copyRegion); vkCmdCopyBuffer(
cmdBuffer, vertexBuffers[1 - currentDrawVertexBuffer]->handle,
vertexBuffers[currentDrawVertexBuffer]->handle, 1, &copyRegion
);
vkEndCommandBuffer(cmdBuffer); vkEndCommandBuffer(cmdBuffer);
@ -592,16 +665,28 @@ void Application::recordGrabCommands(VkCommandBuffer commandBuffer) {
// TODO maybe add buffermemorybarrier for camera uniform, because it can be changed from main drawing thread // TODO maybe add buffermemorybarrier for camera uniform, because it can be changed from main drawing thread
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, grabPipeline->handle); vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, grabPipeline->handle);
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, grabPipeline->layout, 0, 1, &descriptorPool->sets[DescriptorSet::MESH], 0, nullptr); vkCmdBindDescriptorSets(
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, grabPipeline->layout, 1, 1, &descriptorPool->sets[DescriptorSet::WORLD], 0, nullptr); commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, grabPipeline->layout, 0, 1,
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, grabPipeline->layout, 2, 1, &descriptorPool->sets[DescriptorSet::SIMULATION], 0, nullptr); &descriptorPool->sets[DescriptorSet::MESH], 0, nullptr
);
vkCmdBindDescriptorSets(
commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, grabPipeline->layout, 1, 1,
&descriptorPool->sets[DescriptorSet::WORLD], 0, nullptr
);
vkCmdBindDescriptorSets(
commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, grabPipeline->layout, 2, 1,
&descriptorPool->sets[DescriptorSet::SIMULATION], 0, nullptr
);
GrabPushData pushConstants {}; GrabPushData pushConstants {};
if (grabber->started()){ if (grabber->started()) {
pushConstants.state = 0; pushConstants.state = 0;
pushConstants.screenPosition = grabber->previousCursorPosition; pushConstants.screenPosition = grabber->previousCursorPosition;
vkCmdPushConstants(commandBuffer, grabPipeline->layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(GrabPushData), &pushConstants); vkCmdPushConstants(
commandBuffer, grabPipeline->layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(GrabPushData),
&pushConstants
);
uint32_t faceInvocations = GetGroupCount(sizeInformation->faceCount, BLOCK_SIZE_GRAB); uint32_t faceInvocations = GetGroupCount(sizeInformation->faceCount, BLOCK_SIZE_GRAB);
@ -609,25 +694,34 @@ void Application::recordGrabCommands(VkCommandBuffer commandBuffer) {
computePipelineBarrier(commandBuffer); computePipelineBarrier(commandBuffer);
pushConstants.state = 1; pushConstants.state = 1;
vkCmdPushConstants(commandBuffer, grabPipeline->layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(GrabPushData), &pushConstants); vkCmdPushConstants(
commandBuffer, grabPipeline->layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(GrabPushData),
&pushConstants
);
vkCmdDispatch(commandBuffer, 1, 1, 1); vkCmdDispatch(commandBuffer, 1, 1, 1);
} }
computePipelineBarrier(commandBuffer); computePipelineBarrier(commandBuffer);
glm::vec2 screenDelta; glm::vec2 screenDelta;
if (grabber->moved(screenDelta)){ if (grabber->moved(screenDelta)) {
pushConstants.state = 2; pushConstants.state = 2;
pushConstants.screenDelta = screenDelta; pushConstants.screenDelta = screenDelta;
vkCmdPushConstants(commandBuffer, grabPipeline->layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(GrabPushData), &pushConstants); vkCmdPushConstants(
commandBuffer, grabPipeline->layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(GrabPushData),
&pushConstants
);
vkCmdDispatch(commandBuffer, 1, 1, 1); vkCmdDispatch(commandBuffer, 1, 1, 1);
} }
computePipelineBarrier(commandBuffer); computePipelineBarrier(commandBuffer);
if (grabber->stopped()){ if (grabber->stopped()) {
pushConstants.state = 3; pushConstants.state = 3;
vkCmdPushConstants(commandBuffer, grabPipeline->layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(GrabPushData), &pushConstants); vkCmdPushConstants(
commandBuffer, grabPipeline->layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(GrabPushData),
&pushConstants
);
vkCmdDispatch(commandBuffer, 1, 1, 1); vkCmdDispatch(commandBuffer, 1, 1, 1);
} }
@ -638,23 +732,33 @@ void Application::recordPBDCommands(VkCommandBuffer commandBuffer) {
uint32_t vertexGroupCount = GetGroupCount(sizeInformation->vertexCount, BLOCK_SIZE_PBD); uint32_t vertexGroupCount = GetGroupCount(sizeInformation->vertexCount, BLOCK_SIZE_PBD);
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pbdPipeline->handle); vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pbdPipeline->handle);
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pbdPipeline->layout, 0, 1, &descriptorPool->sets[DescriptorSet::MESH], 0, nullptr); vkCmdBindDescriptorSets(
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pbdPipeline->layout, 1, 1, &descriptorPool->sets[DescriptorSet::SIMULATION], 0, nullptr); commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pbdPipeline->layout, 0, 1,
&descriptorPool->sets[DescriptorSet::MESH], 0, nullptr
);
vkCmdBindDescriptorSets(
commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pbdPipeline->layout, 1, 1,
&descriptorPool->sets[DescriptorSet::SIMULATION], 0, nullptr
);
uint32_t state; uint32_t state;
uint32_t k = simulationPropertiesBuffer->access<SimulationUniformData>().k; uint32_t k = simulationPropertiesBuffer->access<SimulationUniformData>().k;
for (size_t i = 0; i < k; i++){ for (size_t i = 0; i < k; i++) {
state = 0; state = 0;
vkCmdPushConstants(commandBuffer, pbdPipeline->layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(uint32_t), &state); vkCmdPushConstants(
commandBuffer, pbdPipeline->layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(uint32_t), &state
);
vkCmdDispatch(commandBuffer, vertexGroupCount, 1, 1); vkCmdDispatch(commandBuffer, vertexGroupCount, 1, 1);
computePipelineBarrier(commandBuffer); computePipelineBarrier(commandBuffer);
state = 1; state = 1;
vkCmdPushConstants(commandBuffer, pbdPipeline->layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(uint32_t), &state); vkCmdPushConstants(
commandBuffer, pbdPipeline->layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(uint32_t), &state
);
for (uint32_t partition = 0; partition < constraintData.partitionCount; partition++){ for (uint32_t partition = 0; partition < constraintData.partitionCount; partition++) {
auto edgePartition = constraintData.edgePartitions[partition]; auto edgePartition = constraintData.edgePartitions[partition];
auto tetrahedronPartition = constraintData.tetrahedronPartitions[partition]; auto tetrahedronPartition = constraintData.tetrahedronPartitions[partition];
@ -663,9 +767,11 @@ void Application::recordPBDCommands(VkCommandBuffer commandBuffer) {
ConstraintData::Partition partitions[2] = {edgePartition, tetrahedronPartition}; ConstraintData::Partition partitions[2] = {edgePartition, tetrahedronPartition};
vkCmdPushConstants(commandBuffer, pbdPipeline->layout, VK_SHADER_STAGE_COMPUTE_BIT, vkCmdPushConstants(
offsetof(PBDPushData, edgePartition), commandBuffer, pbdPipeline->layout, VK_SHADER_STAGE_COMPUTE_BIT,
sizeof(partitions), partitions); offsetof(PBDPushData, edgePartition),
sizeof(partitions), partitions
);
uint32_t invocations = GetGroupCount(edgePartition.size + tetrahedronPartition.size, BLOCK_SIZE_PBD); uint32_t invocations = GetGroupCount(edgePartition.size + tetrahedronPartition.size, BLOCK_SIZE_PBD);
vkCmdDispatch(commandBuffer, invocations, 1, 1); vkCmdDispatch(commandBuffer, invocations, 1, 1);
@ -673,7 +779,9 @@ void Application::recordPBDCommands(VkCommandBuffer commandBuffer) {
} }
state = 2; state = 2;
vkCmdPushConstants(commandBuffer, pbdPipeline->layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(uint32_t), &state); vkCmdPushConstants(
commandBuffer, pbdPipeline->layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(uint32_t), &state
);
vkCmdDispatch(commandBuffer, vertexGroupCount, 1, 1); vkCmdDispatch(commandBuffer, vertexGroupCount, 1, 1);
computePipelineBarrier(commandBuffer); computePipelineBarrier(commandBuffer);
} }
@ -684,7 +792,10 @@ void Application::recordNormalCommands(VkCommandBuffer commandBuffer) {
uint32_t faceGroupCount = GetGroupCount(sizeInformation->faceCount, BLOCK_SIZE_NORMAL); uint32_t faceGroupCount = GetGroupCount(sizeInformation->faceCount, BLOCK_SIZE_NORMAL);
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, normalPipeline->handle); vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, normalPipeline->handle);
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, normalPipeline->layout, 0, 1, &descriptorPool->sets[DescriptorSet::MESH], 0, nullptr); vkCmdBindDescriptorSets(
commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, normalPipeline->layout, 0, 1,
&descriptorPool->sets[DescriptorSet::MESH], 0, nullptr
);
uint32_t state = 0; uint32_t state = 0;
vkCmdPushConstants(commandBuffer, normalPipeline->layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(uint32_t), &state); vkCmdPushConstants(commandBuffer, normalPipeline->layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(uint32_t), &state);
@ -708,7 +819,7 @@ void Application::computePipelineBarrier(VkCommandBuffer commandBuffer) {
memoryBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; memoryBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
memoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT; memoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
const Buffer& buffer = *vertexBuffers[1 - currentDrawVertexBuffer]; const Buffer &buffer = *vertexBuffers[1 - currentDrawVertexBuffer];
VkBufferMemoryBarrier bufferMemoryBarrier {}; VkBufferMemoryBarrier bufferMemoryBarrier {};
bufferMemoryBarrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; bufferMemoryBarrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
bufferMemoryBarrier.buffer = buffer.handle; bufferMemoryBarrier.buffer = buffer.handle;
@ -718,12 +829,14 @@ void Application::computePipelineBarrier(VkCommandBuffer commandBuffer) {
bufferMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; bufferMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
bufferMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; bufferMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
vkCmdPipelineBarrier(commandBuffer, vkCmdPipelineBarrier(
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, commandBuffer,
0, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
1, &memoryBarrier, 0,
1, &bufferMemoryBarrier, 1, &memoryBarrier,
0, nullptr); 1, &bufferMemoryBarrier,
0, nullptr
);
} }
void Application::imGuiWindows() { void Application::imGuiWindows() {
@ -731,7 +844,8 @@ void Application::imGuiWindows() {
ImGui_ImplGlfw_NewFrame(); ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame(); ImGui::NewFrame();
ImGui::Begin("Performance"); { ImGui::Begin("Performance");
{
float updateMS = performanceInformation.updateDuration * 1000.f; float updateMS = performanceInformation.updateDuration * 1000.f;
float updateHZ = 1 / performanceInformation.recentTotalUpdateDurations.average(); float updateHZ = 1 / performanceInformation.recentTotalUpdateDurations.average();
ImGui::Text("Updates: %2.0fms | %.1fHz", updateMS, updateHZ); ImGui::Text("Updates: %2.0fms | %.1fHz", updateMS, updateHZ);
@ -739,14 +853,17 @@ void Application::imGuiWindows() {
float frameMS = performanceInformation.recentFrameDurations.average() * 1000.f; float frameMS = performanceInformation.recentFrameDurations.average() * 1000.f;
float frameHZ = 1 / performanceInformation.recentFrameDurations.average(); float frameHZ = 1 / performanceInformation.recentFrameDurations.average();
ImGui::Text("Frames: %.2fms | %.1fHz", frameMS, frameHZ); ImGui::Text("Frames: %.2fms | %.1fHz", frameMS, frameHZ);
} ImGui::End(); }
ImGui::End();
ImGui::Begin("Scene"); { ImGui::Begin("Scene");
if (ImGui::Button("Add")){ {
if (ImGui::Button("Add")) {
addSoftBody("models/bunny_medium.ply"); addSoftBody("models/bunny_medium.ply");
} }
for (const auto &softBody: softBodies){ for (const auto &softBody: softBodies) {
ImGui::Text("Some softbody"); ImGui::Text("Some softbody");
} }
} ImGui::End(); }
ImGui::End();
} }

@ -5,18 +5,18 @@
#include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/matrix_transform.hpp>
const std::map<int, glm::vec3> moveDirections { const std::map<int, glm::vec3> moveDirections {
{GLFW_KEY_A, {-1, 0, 0}}, {GLFW_KEY_A, {-1, 0, 0}},
{GLFW_KEY_D, {1, 0, 0}}, {GLFW_KEY_D, {1, 0, 0}},
{GLFW_KEY_S, {0, 0, 1}}, {GLFW_KEY_S, {0, 0, 1}},
{GLFW_KEY_W, {0, 0, -1}}, {GLFW_KEY_W, {0, 0, -1}},
{GLFW_KEY_E, {0, 1, 0}}, {GLFW_KEY_E, {0, 1, 0}},
{GLFW_KEY_Q, {0, -1, 0}}, {GLFW_KEY_Q, {0, -1, 0}},
}; };
void Camera::update(float dt) { void Camera::update(float dt) {
glm::vec3 velocity {}; glm::vec3 velocity {};
for (const auto &[key, dir] : moveDirections) for (const auto &[key, dir]: moveDirections)
if (Input::KeyIsDown[key]) if (Input::KeyIsDown[key])
velocity += dir; velocity += dir;
@ -50,7 +50,7 @@ glm::vec2 Camera::viewport() const {
return glm::vec2(static_cast<float>(extent.width), static_cast<float>(extent.height)); return glm::vec2(static_cast<float>(extent.width), static_cast<float>(extent.height));
} }
glm::vec3 Camera::localToWorld(const glm::vec3& direction) const { glm::vec3 Camera::localToWorld(const glm::vec3 &direction) const {
float x = glm::sin(phi) * glm::cos(theta); float x = glm::sin(phi) * glm::cos(theta);
float y = glm::sin(theta); float y = glm::sin(theta);
float z = -glm::cos(phi) * glm::cos(theta); float z = -glm::cos(phi) * glm::cos(theta);

@ -11,31 +11,35 @@ void ConstraintData::writePartitionInformation() {
} }
void ConstraintData::insert(const ConstraintData &other) { void ConstraintData::insert(const ConstraintData &other) {
if (other.partitionCount > partitionCount){ if (other.partitionCount > partitionCount) {
edgePartitions.resize(other.partitionCount); edgePartitions.resize(other.partitionCount);
tetrahedronPartitions.resize(other.partitionCount); tetrahedronPartitions.resize(other.partitionCount);
} }
// insert constraints, increase partition offsets and sizes // insert constraints, increase partition offsets and sizes
for (size_t i = 0; i < other.partitionCount; i++){ for (size_t i = 0; i < other.partitionCount; i++) {
edgePartitions[i].offset += other.edgePartitions[i].offset; edgePartitions[i].offset += other.edgePartitions[i].offset;
tetrahedronPartitions[i].offset += other.tetrahedronPartitions[i].offset; tetrahedronPartitions[i].offset += other.tetrahedronPartitions[i].offset;
auto baseEdgeInsert = other.edges.begin() + other.edgePartitions[i].offset; auto baseEdgeInsert = other.edges.begin() + other.edgePartitions[i].offset;
edges.insert(edges.begin() + edgePartitions[i].offset + edgePartitions[i].size, edges.insert(
baseEdgeInsert, baseEdgeInsert + other.edgePartitions[i].size); edges.begin() + edgePartitions[i].offset + edgePartitions[i].size,
baseEdgeInsert, baseEdgeInsert + other.edgePartitions[i].size
);
auto baseTetrahedronInsert = other.tetrahedra.begin() + other.tetrahedronPartitions[i].offset; auto baseTetrahedronInsert = other.tetrahedra.begin() + other.tetrahedronPartitions[i].offset;
tetrahedra.insert(tetrahedra.begin() + tetrahedronPartitions[i].offset + tetrahedronPartitions[i].size, tetrahedra.insert(
baseTetrahedronInsert, baseTetrahedronInsert + other.tetrahedronPartitions[i].size); tetrahedra.begin() + tetrahedronPartitions[i].offset + tetrahedronPartitions[i].size,
baseTetrahedronInsert, baseTetrahedronInsert + other.tetrahedronPartitions[i].size
);
edgePartitions[i].size += other.edgePartitions[i].size; edgePartitions[i].size += other.edgePartitions[i].size;
tetrahedronPartitions[i].size += other.tetrahedronPartitions[i].size; tetrahedronPartitions[i].size += other.tetrahedronPartitions[i].size;
} }
// increase offsets for remaining partitions // increase offsets for remaining partitions
for (size_t i = other.partitionCount; i < partitionCount; i++){ for (size_t i = other.partitionCount; i < partitionCount; i++) {
edgePartitions[i].offset += other.edgePartitions[other.partitionCount - 1].offset; edgePartitions[i].offset += other.edgePartitions[other.partitionCount - 1].offset;
tetrahedronPartitions[i].offset += other.tetrahedronPartitions[other.partitionCount - 1].offset; tetrahedronPartitions[i].offset += other.tetrahedronPartitions[other.partitionCount - 1].offset;
} }

@ -16,7 +16,7 @@ void Grabber::mouseButtonReleased(int button) {
} }
bool Grabber::started() { bool Grabber::started() {
if (start){ if (start) {
start = false; start = false;
return true; return true;
} }
@ -24,7 +24,7 @@ bool Grabber::started() {
} }
bool Grabber::stopped() { bool Grabber::stopped() {
if (stop){ if (stop) {
stop = false; stop = false;
return true; return true;
} }

@ -3,36 +3,42 @@
std::map<int, bool> Input::KeyIsDown; std::map<int, bool> Input::KeyIsDown;
std::map<int, bool> Input::MouseButtonIsDown; std::map<int, bool> Input::MouseButtonIsDown;
Input* Input::instance; Input *Input::instance;
Input::Input(GLFWwindow *window) : window(window) { Input::Input(GLFWwindow *window) : window(window) {
instance = this; instance = this;
glfwSetWindowUserPointer(window, this); glfwSetWindowUserPointer(window, this);
glfwSetKeyCallback(window, [](GLFWwindow* window, int key, int scancode, int action, int mods){ glfwSetKeyCallback(
auto inputManager = static_cast<Input*>(glfwGetWindowUserPointer(window)); window, [](GLFWwindow *window, int key, int scancode, int action, int mods) {
if (action == GLFW_PRESS) auto inputManager = static_cast<Input *>(glfwGetWindowUserPointer(window));
inputManager->keyPressed(key); if (action == GLFW_PRESS)
if (action == GLFW_RELEASE) inputManager->keyPressed(key);
inputManager->keyReleased(key); if (action == GLFW_RELEASE)
}); inputManager->keyReleased(key);
}
);
glfwSetCursorPosCallback(window, [](GLFWwindow* window, double xpos, double ypos){ glfwSetCursorPosCallback(
auto inputManager = static_cast<Input*>(glfwGetWindowUserPointer(window)); window, [](GLFWwindow *window, double xpos, double ypos) {
glm::vec2 newPosition = {static_cast<float>(xpos), static_cast<float>(ypos)}; auto inputManager = static_cast<Input *>(glfwGetWindowUserPointer(window));
inputManager->mouseMoved(newPosition); glm::vec2 newPosition = {static_cast<float>(xpos), static_cast<float>(ypos)};
}); inputManager->mouseMoved(newPosition);
}
);
double x = 0, y = 0; double x = 0, y = 0;
glfwGetCursorPos(window, &x, &y); glfwGetCursorPos(window, &x, &y);
currentCursorPosition = glm::vec2(static_cast<float>(x), static_cast<float>(y)); currentCursorPosition = glm::vec2(static_cast<float>(x), static_cast<float>(y));
glfwSetMouseButtonCallback(window, [](GLFWwindow* window, int button, int action, int mods){ glfwSetMouseButtonCallback(
auto inputManager = static_cast<Input*>(glfwGetWindowUserPointer(window)); window, [](GLFWwindow *window, int button, int action, int mods) {
if (action == GLFW_PRESS) auto inputManager = static_cast<Input *>(glfwGetWindowUserPointer(window));
inputManager->mouseButtonPressed(button); if (action == GLFW_PRESS)
if (action == GLFW_RELEASE) inputManager->mouseButtonPressed(button);
inputManager->mouseButtonReleased(button); if (action == GLFW_RELEASE)
}); inputManager->mouseButtonReleased(button);
}
);
} }
void Input::keyPressed(int key) { void Input::keyPressed(int key) {
@ -47,8 +53,8 @@ void Input::mouseButtonPressed(int button) {
Input::MouseButtonIsDown[button] = true; Input::MouseButtonIsDown[button] = true;
if (button == GLFW_MOUSE_BUTTON_RIGHT) if (button == GLFW_MOUSE_BUTTON_RIGHT)
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
for (auto listener : listeners) for (auto listener: listeners)
if (auto mouseListener = dynamic_cast<MouseListener*>(listener)) if (auto mouseListener = dynamic_cast<MouseListener *>(listener))
mouseListener->mouseButtonPressed(button); mouseListener->mouseButtonPressed(button);
} }
@ -56,15 +62,15 @@ void Input::mouseButtonReleased(int button) {
Input::MouseButtonIsDown[button] = false; Input::MouseButtonIsDown[button] = false;
if (button == GLFW_MOUSE_BUTTON_RIGHT) if (button == GLFW_MOUSE_BUTTON_RIGHT)
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
for (auto listener : listeners) for (auto listener: listeners)
if (auto mouseListener = dynamic_cast<MouseListener*>(listener)) if (auto mouseListener = dynamic_cast<MouseListener *>(listener))
mouseListener->mouseButtonReleased(button); mouseListener->mouseButtonReleased(button);
} }
void Input::mouseMoved(const glm::vec2& newCursorPosition) { void Input::mouseMoved(const glm::vec2 &newCursorPosition) {
glm::vec2 delta = newCursorPosition - currentCursorPosition; glm::vec2 delta = newCursorPosition - currentCursorPosition;
for (auto listener : listeners) for (auto listener: listeners)
if (auto mouseListener = dynamic_cast<MouseListener*>(listener)) if (auto mouseListener = dynamic_cast<MouseListener *>(listener))
mouseListener->mouseMoved(delta); mouseListener->mouseMoved(delta);
currentCursorPosition = newCursorPosition; currentCursorPosition = newCursorPosition;
} }

@ -11,19 +11,19 @@ Mesh::Mesh(const std::string &fileName) {
auto mesh = scene->mMeshes[0]; auto mesh = scene->mMeshes[0];
for (size_t i = 0; i < mesh->mNumVertices; i++){ for (size_t i = 0; i < mesh->mNumVertices; i++) {
glm::vec3 pos = *reinterpret_cast<glm::vec3*>(&mesh->mVertices[i]); glm::vec3 pos = *reinterpret_cast<glm::vec3 *>(&mesh->mVertices[i]);
glm::vec2 uv = {0, 0}; glm::vec2 uv = {0, 0};
if (mesh->mNumUVComponents[0] == 2) if (mesh->mNumUVComponents[0] == 2)
uv = *reinterpret_cast<glm::vec2*>(&mesh->mTextureCoords[0][i]); uv = *reinterpret_cast<glm::vec2 *>(&mesh->mTextureCoords[0][i]);
glm::vec3 normal = {0, 0, 0}; glm::vec3 normal = {0, 0, 0};
if (mesh->mNormals != nullptr) if (mesh->mNormals != nullptr)
normal = *reinterpret_cast<glm::vec3*>(&mesh->mNormals[i]); normal = *reinterpret_cast<glm::vec3 *>(&mesh->mNormals[i]);
vertices.push_back({pos, uv, normal}); vertices.push_back({pos, uv, normal});
} }
for (size_t i = 0; i < mesh->mNumFaces; i++){ for (size_t i = 0; i < mesh->mNumFaces; i++) {
faces.push_back(*reinterpret_cast<Face*>(mesh->mFaces[i].mIndices)); faces.push_back(*reinterpret_cast<Face *>(mesh->mFaces[i].mIndices));
} }
} }

@ -7,7 +7,7 @@
#include <omp.h> #include <omp.h>
#include <iostream> #include <iostream>
SoftBody::SoftBody(Mesh* mesh, float edgeCompliance, float triangleCompliance, float tetrahedronCompliance) { SoftBody::SoftBody(Mesh *mesh, float edgeCompliance, float triangleCompliance, float tetrahedronCompliance) {
tetgenbehavior behavior; tetgenbehavior behavior;
behavior.parse_commandline(std::string("pYQfeza1").data()); behavior.parse_commandline(std::string("pYQfeza1").data());
@ -19,7 +19,7 @@ SoftBody::SoftBody(Mesh* mesh, float edgeCompliance, float triangleCompliance, f
in.numberofpointattributes = 2; // uv in.numberofpointattributes = 2; // uv
in.pointattributelist = new REAL[mesh->vertices.size() * 2]; in.pointattributelist = new REAL[mesh->vertices.size() * 2];
for (size_t i = 0; i < mesh->vertices.size(); i++){ for (size_t i = 0; i < mesh->vertices.size(); i++) {
in.pointlist[i * 3 + 0] = mesh->vertices[i].position.x; in.pointlist[i * 3 + 0] = mesh->vertices[i].position.x;
in.pointlist[i * 3 + 1] = mesh->vertices[i].position.y; in.pointlist[i * 3 + 1] = mesh->vertices[i].position.y;
in.pointlist[i * 3 + 2] = mesh->vertices[i].position.z; in.pointlist[i * 3 + 2] = mesh->vertices[i].position.z;
@ -27,7 +27,7 @@ SoftBody::SoftBody(Mesh* mesh, float edgeCompliance, float triangleCompliance, f
in.pointattributelist[i * 2 + 1] = mesh->vertices[i].uv.t; in.pointattributelist[i * 2 + 1] = mesh->vertices[i].uv.t;
} }
for (size_t i = 0; i < mesh->faces.size(); i++){ for (size_t i = 0; i < mesh->faces.size(); i++) {
tetgenio::facet &f = in.facetlist[i]; tetgenio::facet &f = in.facetlist[i];
tetgenio::polygon p; tetgenio::polygon p;
@ -48,7 +48,7 @@ SoftBody::SoftBody(Mesh* mesh, float edgeCompliance, float triangleCompliance, f
tetrahedralize(&behavior, &in, &out); tetrahedralize(&behavior, &in, &out);
vertices.reserve(out.numberofpoints); vertices.reserve(out.numberofpoints);
for (size_t i = 0; i < out.numberofpoints; i++){ for (size_t i = 0; i < out.numberofpoints; i++) {
float x = static_cast<float>(out.pointlist[i * 3 + 0]); float x = static_cast<float>(out.pointlist[i * 3 + 0]);
float y = static_cast<float>(out.pointlist[i * 3 + 1]); float y = static_cast<float>(out.pointlist[i * 3 + 1]);
float z = static_cast<float>(out.pointlist[i * 3 + 2]); float z = static_cast<float>(out.pointlist[i * 3 + 2]);
@ -59,7 +59,7 @@ SoftBody::SoftBody(Mesh* mesh, float edgeCompliance, float triangleCompliance, f
faces.reserve(out.numberoftrifaces); faces.reserve(out.numberoftrifaces);
constraintData.triangles.reserve(out.numberoftrifaces); constraintData.triangles.reserve(out.numberoftrifaces);
for (size_t i = 0; i < out.numberoftrifaces; i++){ for (size_t i = 0; i < out.numberoftrifaces; i++) {
uint32_t a = out.trifacelist[i * 3 + 0]; uint32_t a = out.trifacelist[i * 3 + 0];
uint32_t b = out.trifacelist[i * 3 + 1]; uint32_t b = out.trifacelist[i * 3 + 1];
uint32_t c = out.trifacelist[i * 3 + 2]; uint32_t c = out.trifacelist[i * 3 + 2];
@ -81,7 +81,7 @@ SoftBody::SoftBody(Mesh* mesh, float edgeCompliance, float triangleCompliance, f
vector<float> masses(vertices.size()); vector<float> masses(vertices.size());
constraintData.tetrahedra.reserve(out.numberoftetrahedra); constraintData.tetrahedra.reserve(out.numberoftetrahedra);
for (size_t i = 0; i < out.numberoftetrahedra; i++){ for (size_t i = 0; i < out.numberoftetrahedra; i++) {
uint32_t a = out.tetrahedronlist[i * 4 + 0]; uint32_t a = out.tetrahedronlist[i * 4 + 0];
uint32_t b = out.tetrahedronlist[i * 4 + 1]; uint32_t b = out.tetrahedronlist[i * 4 + 1];
uint32_t c = out.tetrahedronlist[i * 4 + 2]; uint32_t c = out.tetrahedronlist[i * 4 + 2];
@ -105,7 +105,7 @@ SoftBody::SoftBody(Mesh* mesh, float edgeCompliance, float triangleCompliance, f
constraintData.tetrahedra.emplace_back(Tetrahedron(a, b, c, d, volume, tetrahedronCompliance)); constraintData.tetrahedra.emplace_back(Tetrahedron(a, b, c, d, volume, tetrahedronCompliance));
} }
for (size_t i = 0; i < masses.size(); i++){ for (size_t i = 0; i < masses.size(); i++) {
vertices[i].inverseMass = 1.0f / masses[i]; vertices[i].inverseMass = 1.0f / masses[i];
} }
@ -113,19 +113,20 @@ SoftBody::SoftBody(Mesh* mesh, float edgeCompliance, float triangleCompliance, f
} }
void SoftBody::applyVertexWorldOffset(const glm::vec3 &offset) { void SoftBody::applyVertexWorldOffset(const glm::vec3 &offset) {
for (Vertex& vertex : vertices){ for (Vertex &vertex: vertices) {
vertex.position += offset; vertex.position += offset;
} }
} }
vector<unordered_set<const Constraint *>> createPartitions(const Graph &graph, const vector<const Constraint *> &ordering){ vector<unordered_set<const Constraint *>>
createPartitions(const Graph &graph, const vector<const Constraint *> &ordering) {
unordered_map<const Constraint *, uint32_t> constraintToColor; unordered_map<const Constraint *, uint32_t> constraintToColor;
vector<unordered_set<const Constraint *>> colorToConstraintList; vector<unordered_set<const Constraint *>> colorToConstraintList;
for (const Constraint * constraint : ordering){ for (const Constraint *constraint: ordering) {
unordered_set<uint32_t> forbiddenColors; unordered_set<uint32_t> forbiddenColors;
for (auto adjacent : graph.at(constraint)) for (auto adjacent: graph.at(constraint))
if (constraintToColor.contains(adjacent)) if (constraintToColor.contains(adjacent))
forbiddenColors.insert(constraintToColor.at(adjacent)); forbiddenColors.insert(constraintToColor.at(adjacent));
@ -136,8 +137,8 @@ vector<unordered_set<const Constraint *>> createPartitions(const Graph &graph, c
} else { } else {
uint32_t minColor; uint32_t minColor;
uint32_t minColorUseCount = UINT32_MAX; uint32_t minColorUseCount = UINT32_MAX;
for (uint32_t color = 0; color < colorToConstraintList.size(); color++){ for (uint32_t color = 0; color < colorToConstraintList.size(); color++) {
if (colorToConstraintList[color].size() < minColorUseCount && !forbiddenColors.contains(color)){ if (colorToConstraintList[color].size() < minColorUseCount && !forbiddenColors.contains(color)) {
minColorUseCount = colorToConstraintList[color].size(); minColorUseCount = colorToConstraintList[color].size();
minColor = color; minColor = color;
} }
@ -157,7 +158,7 @@ vector<const Constraint *> smallestLastOrdering(const Graph &graph) {
unordered_map<size_t, unordered_set<const Constraint *>> degreesToConstraints; unordered_map<size_t, unordered_set<const Constraint *>> degreesToConstraints;
unordered_map<const Constraint *, size_t> constraintsToDegrees; unordered_map<const Constraint *, size_t> constraintsToDegrees;
for (const auto &[constraint, adjacent] : graph) { for (const auto &[constraint, adjacent]: graph) {
degreesToConstraints[adjacent.size()].insert(constraint); degreesToConstraints[adjacent.size()].insert(constraint);
constraintsToDegrees[constraint] = adjacent.size(); constraintsToDegrees[constraint] = adjacent.size();
} }
@ -167,7 +168,7 @@ vector<const Constraint *> smallestLastOrdering(const Graph &graph) {
size_t minDegree = 0; size_t minDegree = 0;
while (degreesToConstraints[minDegree].empty()) while (degreesToConstraints[minDegree].empty())
minDegree++; minDegree++;
const Constraint * minConstraint = *degreesToConstraints[minDegree].begin(); const Constraint *minConstraint = *degreesToConstraints[minDegree].begin();
degreesToConstraints[minDegree].erase(minConstraint); degreesToConstraints[minDegree].erase(minConstraint);
constraintsToDegrees.erase(minConstraint); constraintsToDegrees.erase(minConstraint);
@ -197,17 +198,17 @@ void SoftBody::splitConstraints() {
distanceConstraints.reserve(constraintData.edges.size()); distanceConstraints.reserve(constraintData.edges.size());
volumeConstraints.reserve(constraintData.tetrahedra.size()); volumeConstraints.reserve(constraintData.tetrahedra.size());
for (const Edge &edge : constraintData.edges) for (const Edge &edge: constraintData.edges)
distanceConstraints.push_back(DistanceConstraint(edge)); distanceConstraints.push_back(DistanceConstraint(edge));
for (const Tetrahedron &tetrahedron : constraintData.tetrahedra) for (const Tetrahedron &tetrahedron: constraintData.tetrahedra)
volumeConstraints.push_back(VolumeConstraint(tetrahedron)); volumeConstraints.push_back(VolumeConstraint(tetrahedron));
for (const DistanceConstraint &distanceConstraint : distanceConstraints){ for (const DistanceConstraint &distanceConstraint: distanceConstraints) {
pointToConstraints[distanceConstraint.a].push_back(&distanceConstraint); pointToConstraints[distanceConstraint.a].push_back(&distanceConstraint);
pointToConstraints[distanceConstraint.b].push_back(&distanceConstraint); pointToConstraints[distanceConstraint.b].push_back(&distanceConstraint);
} }
for (const VolumeConstraint &volumeConstraint : volumeConstraints){ for (const VolumeConstraint &volumeConstraint: volumeConstraints) {
pointToConstraints[volumeConstraint.a].push_back(&volumeConstraint); pointToConstraints[volumeConstraint.a].push_back(&volumeConstraint);
pointToConstraints[volumeConstraint.b].push_back(&volumeConstraint); pointToConstraints[volumeConstraint.b].push_back(&volumeConstraint);
pointToConstraints[volumeConstraint.c].push_back(&volumeConstraint); pointToConstraints[volumeConstraint.c].push_back(&volumeConstraint);
@ -216,31 +217,35 @@ void SoftBody::splitConstraints() {
Graph graph; Graph graph;
auto findAdjacent = [&pointToConstraints, &graph](const Constraint * constraint, const vector<uint32_t> &vIDs){ auto findAdjacent = [&pointToConstraints, &graph](const Constraint *constraint, const vector<uint32_t> &vIDs) {
unordered_set<const Constraint *> neighbors; unordered_set<const Constraint *> neighbors;
for (uint32_t vID : vIDs) for (uint32_t vID: vIDs)
neighbors.insert(pointToConstraints[vID].begin(), pointToConstraints[vID].end()); neighbors.insert(pointToConstraints[vID].begin(), pointToConstraints[vID].end());
neighbors.erase(constraint); neighbors.erase(constraint);
#pragma omp critical #pragma omp critical
graph[constraint].assign(neighbors.begin(), neighbors.end()); graph[constraint].assign(neighbors.begin(), neighbors.end());
}; };
#pragma omp parallel for default(none) shared(findAdjacent, distanceConstraints) #pragma omp parallel for default(none) shared(findAdjacent, distanceConstraints)
for (const DistanceConstraint &distanceConstraint : distanceConstraints){ for (const DistanceConstraint &distanceConstraint: distanceConstraints) {
findAdjacent(&distanceConstraint, { findAdjacent(
distanceConstraint.a, &distanceConstraint, {
distanceConstraint.b distanceConstraint.a,
}); distanceConstraint.b
}
);
} }
#pragma omp parallel for default(none) shared(findAdjacent, volumeConstraints) #pragma omp parallel for default(none) shared(findAdjacent, volumeConstraints)
for (const VolumeConstraint &volumeConstraint : volumeConstraints){ for (const VolumeConstraint &volumeConstraint: volumeConstraints) {
findAdjacent(&volumeConstraint, { findAdjacent(
volumeConstraint.a, &volumeConstraint, {
volumeConstraint.b, volumeConstraint.a,
volumeConstraint.c, volumeConstraint.b,
volumeConstraint.d, volumeConstraint.c,
}); volumeConstraint.d,
}
);
} }
auto ordering = smallestLastOrdering(graph); auto ordering = smallestLastOrdering(graph);
@ -253,9 +258,9 @@ void SoftBody::splitConstraints() {
void SoftBody::reorderConstraintIndices(const vector<unordered_set<const Constraint *>> &partitions) { void SoftBody::reorderConstraintIndices(const vector<unordered_set<const Constraint *>> &partitions) {
ConstraintData reordered; ConstraintData reordered;
for (uint32_t partition = 0; partition < partitions.size(); partition++){ for (uint32_t partition = 0; partition < partitions.size(); partition++) {
reordered.recordNewPartition(); reordered.recordNewPartition();
for (const Constraint * constraint : partitions[partition]) for (const Constraint *constraint: partitions[partition])
constraint->writeData(reordered); constraint->writeData(reordered);
reordered.writePartitionInformation(); reordered.writePartitionInformation();
} }

@ -1,2 +1,3 @@
#define STB_IMAGE_IMPLEMENTATION #define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h" #include "stb_image.h"

@ -6,8 +6,12 @@
#include "vulkan/image.hpp" #include "vulkan/image.hpp"
#include "vk_mem_alloc.h" #include "vk_mem_alloc.h"
Buffer::Buffer(VkDeviceSize bufferSize, VkBufferUsageFlags bufferUsageFlags, VmaMemoryUsage memoryUsage, VmaAllocationCreateFlags allocationFlags) Buffer::Buffer(
: size(bufferSize), bufferUsageFlags(bufferUsageFlags), memoryUsage(memoryUsage), allocationCreateFlags(allocationFlags) { VkDeviceSize bufferSize, VkBufferUsageFlags bufferUsageFlags,
VmaMemoryUsage memoryUsage, VmaAllocationCreateFlags allocationFlags, const std::string &name
)
: size(bufferSize), bufferUsageFlags(bufferUsageFlags), memoryUsage(memoryUsage),
allocationCreateFlags(allocationFlags) {
VkBufferCreateInfo bufferCreateInfo {}; VkBufferCreateInfo bufferCreateInfo {};
bufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; bufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
@ -19,7 +23,11 @@ Buffer::Buffer(VkDeviceSize bufferSize, VkBufferUsageFlags bufferUsageFlags, Vma
allocationCreateInfo.usage = memoryUsage; allocationCreateInfo.usage = memoryUsage;
allocationCreateInfo.flags = allocationFlags; allocationCreateInfo.flags = allocationFlags;
vmaCreateBuffer(Instance::GetAllocator(), &bufferCreateInfo, &allocationCreateInfo, &handle, &allocation, &allocationInfo); vmaCreateBuffer(
Instance::GetAllocator(), &bufferCreateInfo, &allocationCreateInfo, &handle, &allocation, &allocationInfo
);
setName(name);
} }
Buffer::~Buffer() { Buffer::~Buffer() {
@ -28,7 +36,7 @@ Buffer::~Buffer() {
void Buffer::copyTo(Buffer *buffer) const { void Buffer::copyTo(Buffer *buffer) const {
VkQueue queue = Instance::instance->graphicsAndPresentQueue; VkQueue queue = Instance::instance->graphicsAndPresentQueue;
CommandPool* commandPool = Instance::instance->renderingCommandPool; CommandPool *commandPool = Instance::instance->renderingCommandPool;
VkCommandBuffer commandBuffer = commandPool->beginSingleTimeCommandBuffer(); VkCommandBuffer commandBuffer = commandPool->beginSingleTimeCommandBuffer();
@ -41,7 +49,7 @@ void Buffer::copyTo(Buffer *buffer) const {
void Buffer::copyTo(Image *image) const { void Buffer::copyTo(Image *image) const {
VkQueue queue = Instance::instance->graphicsAndPresentQueue; VkQueue queue = Instance::instance->graphicsAndPresentQueue;
CommandPool* commandPool = Instance::instance->renderingCommandPool; CommandPool *commandPool = Instance::instance->renderingCommandPool;
VkCommandBuffer commandBuffer = commandPool->beginSingleTimeCommandBuffer(); VkCommandBuffer commandBuffer = commandPool->beginSingleTimeCommandBuffer();
@ -62,15 +70,15 @@ void Buffer::copyTo(Image *image) const {
} }
void Buffer::setData(void *data, VkDeviceSize offset, VkDeviceSize dataSize, VkCommandBuffer commandBuffer) { void Buffer::setData(void *data, VkDeviceSize offset, VkDeviceSize dataSize, VkCommandBuffer commandBuffer) {
if (allocationInfo.pMappedData){ if (allocationInfo.pMappedData) {
memcpy(reinterpret_cast<u_char*>(allocationInfo.pMappedData) + offset, data, dataSize); memcpy(reinterpret_cast<u_char *>(allocationInfo.pMappedData) + offset, data, dataSize);
VkMemoryPropertyFlags flags; VkMemoryPropertyFlags flags;
vmaGetAllocationMemoryProperties(Instance::GetAllocator(), allocation, &flags); vmaGetAllocationMemoryProperties(Instance::GetAllocator(), allocation, &flags);
assert(flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); assert(flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
} else { } else {
bool singleShot = false; bool singleShot = false;
if (!commandBuffer){ if (!commandBuffer) {
commandBuffer = Instance::instance->renderingCommandPool->beginSingleTimeCommandBuffer(); commandBuffer = Instance::instance->renderingCommandPool->beginSingleTimeCommandBuffer();
singleShot = true; singleShot = true;
} }
@ -96,7 +104,8 @@ void Buffer::setData(void *data, VkDeviceSize offset, VkDeviceSize dataSize, VkC
0, 0,
0, nullptr, 0, nullptr,
1, &bufferMemoryBarrier, 1, &bufferMemoryBarrier,
0, nullptr); 0, nullptr
);
VkBufferCopy region {}; VkBufferCopy region {};
region.srcOffset = offset; region.srcOffset = offset;
@ -106,7 +115,9 @@ void Buffer::setData(void *data, VkDeviceSize offset, VkDeviceSize dataSize, VkC
vkCmdCopyBuffer(commandBuffer, stagingBuffer->handle, handle, 1, &region); vkCmdCopyBuffer(commandBuffer, stagingBuffer->handle, handle, 1, &region);
if (singleShot) if (singleShot)
Instance::instance->renderingCommandPool->endSingleTimeCommandBuffer(commandBuffer, Instance::instance->graphicsAndPresentQueue); Instance::instance->renderingCommandPool->endSingleTimeCommandBuffer(
commandBuffer, Instance::instance->graphicsAndPresentQueue
);
} }
} }
@ -116,10 +127,12 @@ void Buffer::setName(const std::string &newName) {
} }
unique_ptr<Buffer> Buffer::appended(void *data, VkDeviceSize appendSize, VkCommandBuffer commandBuffer) const { unique_ptr<Buffer> Buffer::appended(void *data, VkDeviceSize appendSize, VkCommandBuffer commandBuffer) const {
auto buffer = make_unique<Buffer>(size + appendSize, auto buffer = make_unique<Buffer>(
bufferUsageFlags, size + appendSize,
memoryUsage, bufferUsageFlags,
allocationCreateFlags); memoryUsage,
allocationCreateFlags
);
buffer->setName(name); buffer->setName(name);
VkBufferCopy copyRegion {}; VkBufferCopy copyRegion {};
@ -134,10 +147,12 @@ unique_ptr<Buffer> Buffer::appended(void *data, VkDeviceSize appendSize, VkComma
} }
unique_ptr<Buffer> Buffer::replaced(void *data, VkDeviceSize replaceSize, VkCommandBuffer commandBuffer) const { unique_ptr<Buffer> Buffer::replaced(void *data, VkDeviceSize replaceSize, VkCommandBuffer commandBuffer) const {
auto buffer = make_unique<Buffer>(replaceSize, auto buffer = make_unique<Buffer>(
bufferUsageFlags, replaceSize,
memoryUsage, bufferUsageFlags,
allocationCreateFlags); memoryUsage,
allocationCreateFlags
);
buffer->setName(name); buffer->setName(name);
buffer->setData(data, 0, replaceSize, commandBuffer); buffer->setData(data, 0, replaceSize, commandBuffer);
@ -153,7 +168,8 @@ shared_ptr<Buffer> Buffer::getStagingBuffer() {
size, size,
VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
VMA_MEMORY_USAGE_AUTO, VMA_MEMORY_USAGE_AUTO,
VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT); VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT
);
stagingBufferOptional.value()->setName(name + " staging"); stagingBufferOptional.value()->setName(name + " staging");

@ -6,8 +6,8 @@
DescriptorPool::DescriptorPool() { DescriptorPool::DescriptorPool() {
VkDescriptorPoolSize poolSizes[] = { VkDescriptorPoolSize poolSizes[] = {
{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 20}, {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 20},
{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 20}, {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 20},
{VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 10} {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 10}
}; };
@ -20,18 +20,23 @@ DescriptorPool::DescriptorPool() {
vkCreateDescriptorPool(Instance::GetDevice(), &poolInfo, nullptr, &handle); vkCreateDescriptorPool(Instance::GetDevice(), &poolInfo, nullptr, &handle);
std::map<DescriptorSet, std::vector<VkDescriptorSetLayoutBinding>> setBindings; std::map<DescriptorSet, std::vector<VkDescriptorSetLayoutBinding>> setBindings;
auto addBinding = [&setBindings](DescriptorSet set, VkDescriptorType type, VkShaderStageFlags stageFlags){ auto addBinding = [&setBindings](DescriptorSet set, VkDescriptorType type, VkShaderStageFlags stageFlags) {
uint32_t binding = setBindings[set].size(); uint32_t binding = setBindings[set].size();
setBindings[set].push_back({ setBindings[set].push_back(
.binding = binding, {
.descriptorType = type, .binding = binding,
.descriptorCount = 1, .descriptorType = type,
.stageFlags = stageFlags .descriptorCount = 1,
}); .stageFlags = stageFlags
}
);
}; };
// camera // camera
addBinding(DescriptorSet::WORLD, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_COMPUTE_BIT); addBinding(
DescriptorSet::WORLD, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_COMPUTE_BIT
);
// lights // lights
addBinding(DescriptorSet::WORLD, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT); addBinding(DescriptorSet::WORLD, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT);
// texture // texture
@ -55,10 +60,10 @@ DescriptorPool::DescriptorPool() {
// grab information // grab information
addBinding(DescriptorSet::SIMULATION, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT); addBinding(DescriptorSet::SIMULATION, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT);
for (const auto &[set, bindings] : setBindings) for (const auto &[set, bindings]: setBindings)
createLayout(set, bindings); createLayout(set, bindings);
for (const auto &[set, layout] : layouts){ for (const auto &[set, layout]: layouts) {
VkDescriptorSetAllocateInfo allocateInfo {}; VkDescriptorSetAllocateInfo allocateInfo {};
allocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; allocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
allocateInfo.descriptorPool = handle; allocateInfo.descriptorPool = handle;
@ -71,11 +76,11 @@ DescriptorPool::DescriptorPool() {
DescriptorPool::~DescriptorPool() { DescriptorPool::~DescriptorPool() {
vkDestroyDescriptorPool(Instance::GetDevice(), handle, nullptr); vkDestroyDescriptorPool(Instance::GetDevice(), handle, nullptr);
for (const auto &[type, layout] : layouts) for (const auto &[type, layout]: layouts)
vkDestroyDescriptorSetLayout(Instance::GetDevice(), layout, nullptr); vkDestroyDescriptorSetLayout(Instance::GetDevice(), layout, nullptr);
} }
void DescriptorPool::bindBuffer(const Buffer& buffer, VkDescriptorType type, DescriptorSet set, uint32_t binding) { void DescriptorPool::bindBuffer(const Buffer &buffer, VkDescriptorType type, DescriptorSet set, uint32_t binding) {
VkDescriptorBufferInfo bufferInfo {}; VkDescriptorBufferInfo bufferInfo {};
bufferInfo.buffer = buffer.handle; bufferInfo.buffer = buffer.handle;
bufferInfo.offset = 0; bufferInfo.offset = 0;

@ -3,8 +3,10 @@
#include "vulkan/buffer.hpp" #include "vulkan/buffer.hpp"
#include "vulkan/command_pool.hpp" #include "vulkan/command_pool.hpp"
Image::Image(uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, Image::Image(
VkImageUsageFlags usage) : format(format), width(width), height(height) { uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling,
VkImageUsageFlags usage
) : format(format), width(width), height(height) {
VkImageCreateInfo imageCreateInfo {}; VkImageCreateInfo imageCreateInfo {};
imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
@ -25,14 +27,20 @@ Image::Image(uint32_t width, uint32_t height, VkFormat format, VkImageTiling til
allocationCreateInfo.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE; allocationCreateInfo.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE;
allocationCreateInfo.flags = 0; allocationCreateInfo.flags = 0;
vmaCreateImage(Instance::GetAllocator(), &imageCreateInfo, &allocationCreateInfo, &handle, &allocation, &allocationInfo); vmaCreateImage(
Instance::GetAllocator(), &imageCreateInfo, &allocationCreateInfo, &handle, &allocation, &allocationInfo
);
} }
Image::Image(void *initialData, VkDeviceSize size, uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, Image::Image(
VkImageUsageFlags usage) : Image(width, height, format, tiling, usage){ void *initialData, VkDeviceSize size, uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling,
VkImageUsageFlags usage
) : Image(width, height, format, tiling, usage) {
Buffer stagingBuffer(size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE, Buffer stagingBuffer(
VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT); size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE,
VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT
);
stagingBuffer.setData(initialData, 0, size); stagingBuffer.setData(initialData, 0, size);
transitionLayout(VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); transitionLayout(VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
@ -116,13 +124,14 @@ void Image::transitionLayout(VkImageLayout oldLayout, VkImageLayout newLayout) {
VkPipelineStageFlags sourceStage = 0; VkPipelineStageFlags sourceStage = 0;
VkPipelineStageFlags destinationStage = 0; VkPipelineStageFlags destinationStage = 0;
if ((oldLayout == VK_IMAGE_LAYOUT_UNDEFINED) && newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL){ if ((oldLayout == VK_IMAGE_LAYOUT_UNDEFINED) && newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
barrier.srcAccessMask = 0; barrier.srcAccessMask = 0;
barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
destinationStage = VK_PIPELINE_STAGE_TRANSFER_BIT; destinationStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
} else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL){ } else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL &&
newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
@ -130,12 +139,14 @@ void Image::transitionLayout(VkImageLayout oldLayout, VkImageLayout newLayout) {
destinationStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; destinationStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
} }
vkCmdPipelineBarrier(commandBuffer, vkCmdPipelineBarrier(
sourceStage, destinationStage, commandBuffer,
0, sourceStage, destinationStage,
0, nullptr, 0,
0, nullptr, 0, nullptr,
1, &barrier); 0, nullptr,
1, &barrier
);
commandPool->endSingleTimeCommandBuffer(commandBuffer, Instance::instance->graphicsAndPresentQueue); commandPool->endSingleTimeCommandBuffer(commandBuffer, Instance::instance->graphicsAndPresentQueue);
} }

@ -6,7 +6,7 @@
#include "vk_mem_alloc.h" #include "vk_mem_alloc.h"
#include <cstring> #include <cstring>
const std::vector<const char*> deviceExtensions = { const std::vector<const char *> deviceExtensions = {
VK_KHR_SWAPCHAIN_EXTENSION_NAME, VK_KHR_SWAPCHAIN_EXTENSION_NAME,
VK_EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME VK_EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME
}; };
@ -49,7 +49,7 @@ bool checkValidationLayerSupport(){
} }
#endif #endif
Instance* Instance::instance = nullptr; Instance *Instance::instance = nullptr;
Instance::Instance() { Instance::Instance() {
instance = this; instance = this;
@ -71,10 +71,26 @@ void Instance::initWindow() {
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
glfwWindowHint(GLFW_MAXIMIZED, GLFW_TRUE); glfwWindowHint(GLFW_MAXIMIZED, GLFW_TRUE);
int monitorCount;
GLFWmonitor **monitors = glfwGetMonitors(&monitorCount);
GLFWmonitor *monitor = glfwGetPrimaryMonitor();
for (int i = 1; i < monitorCount; i++) {
int w, h;
glfwGetMonitorPhysicalSize(monitors[i], &w, &h);
if (w > h) {
monitor = monitors[i];
break;
}
}
int x, y;
glfwGetMonitorPos(monitor, &x, &y);
window = glfwCreateWindow(800, 600, "Vulkan Simulation", nullptr, nullptr); window = glfwCreateWindow(800, 600, "Vulkan Simulation", nullptr, nullptr);
glfwSetFramebufferSizeCallback(window, [](GLFWwindow* window, int width, int height) { glfwSetWindowPos(window, x, y);
instance->windowResized = true; glfwSetFramebufferSizeCallback(
}); window, [](GLFWwindow *window, int width, int height) {
instance->windowResized = true;
}
);
} }
void Instance::createInstance() { void Instance::createInstance() {
@ -93,7 +109,7 @@ void Instance::createInstance() {
applicationInfo.apiVersion = VK_API_VERSION_1_1; applicationInfo.apiVersion = VK_API_VERSION_1_1;
uint32_t glfwExtensionCount = 0; uint32_t glfwExtensionCount = 0;
const char** glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount); const char **glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
VkInstanceCreateInfo instanceCreateInfo {}; VkInstanceCreateInfo instanceCreateInfo {};
instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
@ -117,21 +133,21 @@ void Instance::createSurface() {
void Instance::pickPhysicalDevice() { void Instance::pickPhysicalDevice() {
uint32_t deviceCount = 0; uint32_t deviceCount = 0;
vkEnumeratePhysicalDevices(handle, &deviceCount, nullptr); vkEnumeratePhysicalDevices(handle, &deviceCount, nullptr);
if (deviceCount == 0){ if (deviceCount == 0) {
throw std::runtime_error("failed to find GPUs with Vulkan support!"); throw std::runtime_error("failed to find GPUs with Vulkan support!");
} }
std::vector<VkPhysicalDevice> devices(deviceCount); std::vector<VkPhysicalDevice> devices(deviceCount);
vkEnumeratePhysicalDevices(handle, &deviceCount, devices.data()); vkEnumeratePhysicalDevices(handle, &deviceCount, devices.data());
for (const VkPhysicalDevice &potentialPhysicalDevice : devices){ for (const VkPhysicalDevice &potentialPhysicalDevice: devices) {
if (isDeviceSuitable(potentialPhysicalDevice)){ if (isDeviceSuitable(potentialPhysicalDevice)) {
physicalDevice = potentialPhysicalDevice; physicalDevice = potentialPhysicalDevice;
indices = findQueueFamilies(physicalDevice, surface); indices = findQueueFamilies(physicalDevice, surface);
break; break;
} }
} }
if (physicalDevice == VK_NULL_HANDLE){ if (physicalDevice == VK_NULL_HANDLE) {
throw std::runtime_error("failed to find a suitable GPU!"); throw std::runtime_error("failed to find a suitable GPU!");
} }
@ -144,7 +160,7 @@ void Instance::createLogicalDevice() {
std::vector<VkDeviceQueueCreateInfo> queueCreateInfos; std::vector<VkDeviceQueueCreateInfo> queueCreateInfos;
float queuePriority = 1.0f; float queuePriority = 1.0f;
for (uint32_t queueFamily : indices.uniqueQueueFamilies()){ for (uint32_t queueFamily: indices.uniqueQueueFamilies()) {
VkDeviceQueueCreateInfo queueCreateInfo {}; VkDeviceQueueCreateInfo queueCreateInfo {};
queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queueCreateInfo.queueFamilyIndex = queueFamily; queueCreateInfo.queueFamilyIndex = queueFamily;
@ -179,8 +195,9 @@ void Instance::createLogicalDevice() {
} }
#include <fstream> #include <fstream>
void printVmaStats(){
char* stats; void printVmaStats() {
char *stats;
vmaBuildStatsString(Instance::GetAllocator(), &stats, VK_TRUE); vmaBuildStatsString(Instance::GetAllocator(), &stats, VK_TRUE);
std::ofstream stream("stats.json"); std::ofstream stream("stats.json");
stream << stats; stream << stats;
@ -211,7 +228,7 @@ Instance::QueueFamilyIndices Instance::findQueueFamilies(VkPhysicalDevice device
QueueFamilyIndices indices {}; QueueFamilyIndices indices {};
uint32_t i = 0; uint32_t i = 0;
for (const VkQueueFamilyProperties& queueFamilyProperties : queueFamilies){ for (const VkQueueFamilyProperties &queueFamilyProperties: queueFamilies) {
VkBool32 present = false; VkBool32 present = false;
vkGetPhysicalDeviceSurfaceSupportKHR(device, i, surface, &present); vkGetPhysicalDeviceSurfaceSupportKHR(device, i, surface, &present);
@ -241,7 +258,7 @@ bool Instance::isDeviceSuitable(VkPhysicalDevice potentialPhysicalDevice) {
bool extensionsSupported = checkDeviceExtensionSupport(potentialPhysicalDevice); bool extensionsSupported = checkDeviceExtensionSupport(potentialPhysicalDevice);
bool swapChainAdequate = false; bool swapChainAdequate = false;
if (extensionsSupported){ if (extensionsSupported) {
SwapchainSupportDetails details = querySwapchainSupport(potentialPhysicalDevice, surface); SwapchainSupportDetails details = querySwapchainSupport(potentialPhysicalDevice, surface);
swapChainAdequate = !details.formats.empty() && !details.presentModes.empty(); swapChainAdequate = !details.formats.empty() && !details.presentModes.empty();
} }
@ -258,7 +275,7 @@ bool Instance::checkDeviceExtensionSupport(VkPhysicalDevice device) {
std::vector<VkExtensionProperties> availableExtensions(extensionCount); std::vector<VkExtensionProperties> availableExtensions(extensionCount);
vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, availableExtensions.data()); vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, availableExtensions.data());
for (const VkExtensionProperties& extension : availableExtensions){ for (const VkExtensionProperties &extension: availableExtensions) {
required.erase(extension.extensionName); required.erase(extension.extensionName);
} }
@ -299,24 +316,24 @@ Instance::~Instance() {
glfwTerminate(); glfwTerminate();
} }
void Instance::initImGui(const Swapchain& swapchain) { void Instance::initImGui(const Swapchain &swapchain) {
ImGui::CreateContext(); ImGui::CreateContext();
ImGui::StyleColorsDark(); ImGui::StyleColorsDark();
ImGuiIO& io = ImGui::GetIO(); ImGuiIO &io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
ImGui_ImplGlfw_InitForVulkan(window, true); ImGui_ImplGlfw_InitForVulkan(window, true);
VkDescriptorPoolSize pool_sizes[] = { VkDescriptorPoolSize pool_sizes[] = {
{ {
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1 VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1
} }
}; };
VkDescriptorPoolCreateInfo pool_info = {}; VkDescriptorPoolCreateInfo pool_info = {};
pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
pool_info.maxSets = 1; pool_info.maxSets = 1;
pool_info.poolSizeCount = (uint32_t)IM_ARRAYSIZE(pool_sizes); pool_info.poolSizeCount = (uint32_t) IM_ARRAYSIZE(pool_sizes);
pool_info.pPoolSizes = pool_sizes; pool_info.pPoolSizes = pool_sizes;
vkCreateDescriptorPool(Instance::GetDevice(), &pool_info, nullptr, &imGuiDescriptorPool); vkCreateDescriptorPool(Instance::GetDevice(), &pool_info, nullptr, &imGuiDescriptorPool);
@ -338,3 +355,22 @@ void Instance::initImGui(const Swapchain& swapchain) {
ImGui_ImplVulkan_Init(&initInfo); ImGui_ImplVulkan_Init(&initInfo);
} }
std::set<uint32_t> Instance::QueueFamilyIndices::uniqueQueueFamilies() {
std::set<uint32_t> unique;
unique.insert(graphicsAndPresent.begin(), graphicsAndPresent.end());
unique.insert(computeAndTransfer.begin(), computeAndTransfer.end());
return unique;
}
uint32_t Instance::QueueFamilyIndices::tryComputeAndTransferDedicated() {
for (uint32_t family: computeAndTransfer)
if (std::find(graphicsAndPresent.begin(), graphicsAndPresent.end(), family) == graphicsAndPresent.end())
return family;
return computeAndTransfer[0];
}
bool Instance::QueueFamilyIndices::isEnough() {
return !graphicsAndPresent.empty() && !computeAndTransfer.empty();
}

@ -4,10 +4,10 @@
#include "vulkan/vertex.hpp" #include "vulkan/vertex.hpp"
#include "vulkan/instance.hpp" #include "vulkan/instance.hpp"
std::vector<char> readFile(const std::string& fileName){ std::vector<char> readFile(const std::string &fileName) {
std::ifstream file(fileName, std::ios::ate | std::ios::binary); std::ifstream file(fileName, std::ios::ate | std::ios::binary);
if (!file.is_open()){ if (!file.is_open()) {
throw std::runtime_error("failed to open file!"); throw std::runtime_error("failed to open file!");
} }
@ -33,8 +33,10 @@ VkShaderModule Pipeline::createShaderModule(const std::vector<char> &code) {
return shaderModule; return shaderModule;
} }
Pipeline::Pipeline(const std::vector<VkDescriptorSetLayout> &descriptorSetLayouts, Pipeline::Pipeline(
const std::vector<VkPushConstantRange> &pushConstantRanges) { const std::vector<VkDescriptorSetLayout> &descriptorSetLayouts,
const std::vector<VkPushConstantRange> &pushConstantRanges
) {
VkPipelineLayoutCreateInfo pipelineLayoutInfo {}; VkPipelineLayoutCreateInfo pipelineLayoutInfo {};
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipelineLayoutInfo.setLayoutCount = descriptorSetLayouts.size(); pipelineLayoutInfo.setLayoutCount = descriptorSetLayouts.size();
@ -51,10 +53,12 @@ Pipeline::~Pipeline() {
} }
GraphicsPipeline::GraphicsPipeline(const std::string& vertexShaderPath, const std::string& fragmentShaderPath, GraphicsPipeline::GraphicsPipeline(
VkRenderPass renderPass, const std::string &vertexShaderPath, const std::string &fragmentShaderPath,
const std::vector<VkDescriptorSetLayout> &descriptorSetLayouts, VkRenderPass renderPass,
const std::vector<VkPushConstantRange> &pushConstantRanges) : Pipeline(descriptorSetLayouts, pushConstantRanges) { const std::vector<VkDescriptorSetLayout> &descriptorSetLayouts,
const std::vector<VkPushConstantRange> &pushConstantRanges
) : Pipeline(descriptorSetLayouts, pushConstantRanges) {
auto vertShaderCode = readFile(vertexShaderPath); auto vertShaderCode = readFile(vertexShaderPath);
auto fragShaderCode = readFile(fragmentShaderPath); auto fragShaderCode = readFile(fragmentShaderPath);
@ -122,7 +126,8 @@ GraphicsPipeline::GraphicsPipeline(const std::string& vertexShaderPath, const st
multisample.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; multisample.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
VkPipelineColorBlendAttachmentState colorBlendAttachment {}; VkPipelineColorBlendAttachmentState colorBlendAttachment {};
colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; colorBlendAttachment.colorWriteMask =
VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
colorBlendAttachment.blendEnable = VK_FALSE; colorBlendAttachment.blendEnable = VK_FALSE;
VkPipelineColorBlendStateCreateInfo colorBlending {}; VkPipelineColorBlendStateCreateInfo colorBlending {};
@ -166,9 +171,11 @@ GraphicsPipeline::GraphicsPipeline(const std::string& vertexShaderPath, const st
vkDestroyShaderModule(Instance::GetDevice(), fragShaderModule, nullptr); vkDestroyShaderModule(Instance::GetDevice(), fragShaderModule, nullptr);
} }
ComputePipeline::ComputePipeline(const std::string& shaderFile, ComputePipeline::ComputePipeline(
const std::vector<VkDescriptorSetLayout> &descriptorSetLayouts, const std::string &shaderFile,
const std::vector<VkPushConstantRange> &pushConstantRanges) : Pipeline(descriptorSetLayouts, pushConstantRanges) { const std::vector<VkDescriptorSetLayout> &descriptorSetLayouts,
const std::vector<VkPushConstantRange> &pushConstantRanges
) : Pipeline(descriptorSetLayouts, pushConstantRanges) {
VkShaderModule module = createShaderModule(readFile(shaderFile)); VkShaderModule module = createShaderModule(readFile(shaderFile));
VkPipelineShaderStageCreateInfo stageInfo {}; VkPipelineShaderStageCreateInfo stageInfo {};

@ -4,21 +4,21 @@
#include "vulkan/instance.hpp" #include "vulkan/instance.hpp"
#include "vulkan/image.hpp" #include "vulkan/image.hpp"
SwapchainSupportDetails querySwapchainSupport(VkPhysicalDevice device, VkSurfaceKHR surface){ SwapchainSupportDetails querySwapchainSupport(VkPhysicalDevice device, VkSurfaceKHR surface) {
SwapchainSupportDetails details; SwapchainSupportDetails details;
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface, &details.capabilities); vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface, &details.capabilities);
uint32_t formatCount; uint32_t formatCount;
vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, nullptr); vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, nullptr);
if (formatCount != 0){ if (formatCount != 0) {
details.formats.resize(formatCount); details.formats.resize(formatCount);
vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, details.formats.data()); vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, details.formats.data());
} }
uint32_t presentModeCount; uint32_t presentModeCount;
vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, nullptr); vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, nullptr);
if (presentModeCount != 0){ if (presentModeCount != 0) {
details.presentModes.resize(presentModeCount); details.presentModes.resize(presentModeCount);
vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, details.presentModes.data()); vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, details.presentModes.data());
} }
@ -40,7 +40,7 @@ Swapchain::~Swapchain() {
} }
VkExtent2D Swapchain::chooseSwapExtent(const VkSurfaceCapabilitiesKHR &capabilities) { VkExtent2D Swapchain::chooseSwapExtent(const VkSurfaceCapabilitiesKHR &capabilities) {
if (capabilities.currentExtent.width != std::numeric_limits<uint32_t>::max()){ if (capabilities.currentExtent.width != std::numeric_limits<uint32_t>::max()) {
return capabilities.currentExtent; return capabilities.currentExtent;
} else { } else {
int width, height; int width, height;
@ -51,22 +51,27 @@ VkExtent2D Swapchain::chooseSwapExtent(const VkSurfaceCapabilitiesKHR &capabilit
static_cast<uint32_t>(height) static_cast<uint32_t>(height)
}; };
actualExtent.width = std::clamp(actualExtent.width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width); actualExtent.width = std::clamp(
actualExtent.height = std::clamp(actualExtent.height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height); actualExtent.width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width
);
actualExtent.height = std::clamp(
actualExtent.height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height
);
return actualExtent; return actualExtent;
} }
} }
void Swapchain::createSwapchain() { void Swapchain::createSwapchain() {
SwapchainSupportDetails swapchainSupport = querySwapchainSupport(Instance::GetPhysicalDevice(), Instance::GetSurface()); SwapchainSupportDetails swapchainSupport = querySwapchainSupport(
Instance::GetPhysicalDevice(), Instance::GetSurface());
VkSurfaceFormatKHR surfaceFormat = chooseSwapSurfaceFormat(swapchainSupport.formats); VkSurfaceFormatKHR surfaceFormat = chooseSwapSurfaceFormat(swapchainSupport.formats);
VkPresentModeKHR presentMode = chooseSwapPresentMode(swapchainSupport.presentModes); VkPresentModeKHR presentMode = chooseSwapPresentMode(swapchainSupport.presentModes);
extent = chooseSwapExtent(swapchainSupport.capabilities); extent = chooseSwapExtent(swapchainSupport.capabilities);
uint32_t imageCount = swapchainSupport.capabilities.minImageCount + 1; uint32_t imageCount = swapchainSupport.capabilities.minImageCount + 1;
if (swapchainSupport.capabilities.maxImageCount > 0 && imageCount > swapchainSupport.capabilities.maxImageCount){ if (swapchainSupport.capabilities.maxImageCount > 0 && imageCount > swapchainSupport.capabilities.maxImageCount) {
imageCount = swapchainSupport.capabilities.maxImageCount; imageCount = swapchainSupport.capabilities.maxImageCount;
} }
@ -98,10 +103,10 @@ void Swapchain::createSwapchain() {
} }
void Swapchain::cleanupSwapchain() { void Swapchain::cleanupSwapchain() {
for (auto framebuffer : frameBuffers){ for (auto framebuffer: frameBuffers) {
vkDestroyFramebuffer(Instance::GetDevice(), framebuffer, nullptr); vkDestroyFramebuffer(Instance::GetDevice(), framebuffer, nullptr);
} }
for (auto imageView : imageViews){ for (auto imageView: imageViews) {
vkDestroyImageView(Instance::GetDevice(), imageView, nullptr); vkDestroyImageView(Instance::GetDevice(), imageView, nullptr);
} }
delete depthImage; delete depthImage;
@ -121,7 +126,7 @@ void Swapchain::recreateSwapchain() {
void Swapchain::createImageViews() { void Swapchain::createImageViews() {
imageViews.resize(images.size()); imageViews.resize(images.size());
for (size_t i = 0; i < images.size(); i++){ for (size_t i = 0; i < images.size(); i++) {
VkImageViewCreateInfo createInfo {}; VkImageViewCreateInfo createInfo {};
createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
createInfo.format = imageFormat; createInfo.format = imageFormat;
@ -178,9 +183,11 @@ void Swapchain::createRenderpass() {
VkSubpassDependency dependency {}; VkSubpassDependency dependency {};
dependency.srcSubpass = VK_SUBPASS_EXTERNAL; dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
dependency.dstSubpass = 0; dependency.dstSubpass = 0;
dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; dependency.srcStageMask =
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
dependency.srcAccessMask = 0; dependency.srcAccessMask = 0;
dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; dependency.dstStageMask =
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
VkRenderPassCreateInfo renderPassInfo {}; VkRenderPassCreateInfo renderPassInfo {};
@ -208,7 +215,7 @@ void Swapchain::createDepthResources() {
void Swapchain::createFramebuffers() { void Swapchain::createFramebuffers() {
frameBuffers.resize(imageViews.size()); frameBuffers.resize(imageViews.size());
for (size_t i = 0; i < imageViews.size(); i++){ for (size_t i = 0; i < imageViews.size(); i++) {
VkImageView attachments[] = { VkImageView attachments[] = {
imageViews[i], imageViews[i],
depthImage->view depthImage->view
@ -228,8 +235,9 @@ void Swapchain::createFramebuffers() {
} }
VkSurfaceFormatKHR Swapchain::chooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR> &availableFormats) { VkSurfaceFormatKHR Swapchain::chooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR> &availableFormats) {
for (const auto& availableFormat : availableFormats){ for (const auto &availableFormat: availableFormats) {
if (availableFormat.format == VK_FORMAT_B8G8R8A8_SRGB && availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR){ if (availableFormat.format == VK_FORMAT_B8G8R8A8_SRGB &&
availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
return availableFormat; return availableFormat;
} }
} }

@ -1,2 +1,3 @@
#define VMA_IMPLEMENTATION #define VMA_IMPLEMENTATION
#include "vk_mem_alloc.h" #include "vk_mem_alloc.h"
Loading…
Cancel
Save