Compare commits

..

No commits in common. 'main' and 'feature/softbody-runtime-control' have entirely different histories.

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

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

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

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

@ -14,13 +14,13 @@ using std::vector;
struct Vertex;
typedef unordered_map<const Constraint *, vector<const Constraint *>> Graph;
typedef unordered_map<const Constraint*, vector<const Constraint *>> Graph;
class Mesh;
class SoftBody {
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;
int32_t vertexOffset = 0;
@ -28,9 +28,9 @@ public:
vector<Face> faces;
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:
void splitConstraints();
void reorderConstraintIndices(const vector<unordered_set<const Constraint *>> &partitions);

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

@ -5,7 +5,6 @@
#include <map>
class Buffer;
class Image;
enum class DescriptorSet {
@ -19,8 +18,8 @@ public:
DescriptorPool();
~DescriptorPool();
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 bindBuffer(const Buffer& buffer, 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, VkDescriptorSetLayout> layouts;
VkDescriptorPool handle = VK_NULL_HANDLE;

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

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

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

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

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

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

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

@ -11,35 +11,31 @@ void ConstraintData::writePartitionInformation() {
}
void ConstraintData::insert(const ConstraintData &other) {
if (other.partitionCount > partitionCount) {
if (other.partitionCount > partitionCount){
edgePartitions.resize(other.partitionCount);
tetrahedronPartitions.resize(other.partitionCount);
}
// 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;
tetrahedronPartitions[i].offset += other.tetrahedronPartitions[i].offset;
auto baseEdgeInsert = other.edges.begin() + other.edgePartitions[i].offset;
edges.insert(
edges.begin() + edgePartitions[i].offset + edgePartitions[i].size,
baseEdgeInsert, baseEdgeInsert + other.edgePartitions[i].size
);
edges.insert(edges.begin() + edgePartitions[i].offset + edgePartitions[i].size,
baseEdgeInsert, baseEdgeInsert + other.edgePartitions[i].size);
auto baseTetrahedronInsert = other.tetrahedra.begin() + other.tetrahedronPartitions[i].offset;
tetrahedra.insert(
tetrahedra.begin() + tetrahedronPartitions[i].offset + tetrahedronPartitions[i].size,
baseTetrahedronInsert, baseTetrahedronInsert + other.tetrahedronPartitions[i].size
);
tetrahedra.insert(tetrahedra.begin() + tetrahedronPartitions[i].offset + tetrahedronPartitions[i].size,
baseTetrahedronInsert, baseTetrahedronInsert + other.tetrahedronPartitions[i].size);
edgePartitions[i].size += other.edgePartitions[i].size;
tetrahedronPartitions[i].size += other.tetrahedronPartitions[i].size;
}
// 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;
tetrahedronPartitions[i].offset += other.tetrahedronPartitions[other.partitionCount - 1].offset;
}

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

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

@ -11,19 +11,19 @@ Mesh::Mesh(const std::string &fileName) {
auto mesh = scene->mMeshes[0];
for (size_t i = 0; i < mesh->mNumVertices; i++) {
glm::vec3 pos = *reinterpret_cast<glm::vec3 *>(&mesh->mVertices[i]);
for (size_t i = 0; i < mesh->mNumVertices; i++){
glm::vec3 pos = *reinterpret_cast<glm::vec3*>(&mesh->mVertices[i]);
glm::vec2 uv = {0, 0};
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};
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});
}
for (size_t i = 0; i < mesh->mNumFaces; i++) {
faces.push_back(*reinterpret_cast<Face *>(mesh->mFaces[i].mIndices));
for (size_t i = 0; i < mesh->mNumFaces; i++){
faces.push_back(*reinterpret_cast<Face*>(mesh->mFaces[i].mIndices));
}
}

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

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

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

@ -6,8 +6,8 @@
DescriptorPool::DescriptorPool() {
VkDescriptorPoolSize poolSizes[] = {
{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 20},
{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 20},
{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 20},
{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 20},
{VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 10}
};
@ -20,23 +20,18 @@ DescriptorPool::DescriptorPool() {
vkCreateDescriptorPool(Instance::GetDevice(), &poolInfo, nullptr, &handle);
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();
setBindings[set].push_back(
{
.binding = binding,
.descriptorType = type,
.descriptorCount = 1,
.stageFlags = stageFlags
}
);
setBindings[set].push_back({
.binding = binding,
.descriptorType = type,
.descriptorCount = 1,
.stageFlags = stageFlags
});
};
// 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
addBinding(DescriptorSet::WORLD, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT);
// texture
@ -60,10 +55,10 @@ DescriptorPool::DescriptorPool() {
// grab information
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);
for (const auto &[set, layout]: layouts) {
for (const auto &[set, layout] : layouts){
VkDescriptorSetAllocateInfo allocateInfo {};
allocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
allocateInfo.descriptorPool = handle;
@ -76,11 +71,11 @@ DescriptorPool::DescriptorPool() {
DescriptorPool::~DescriptorPool() {
vkDestroyDescriptorPool(Instance::GetDevice(), handle, nullptr);
for (const auto &[type, layout]: layouts)
for (const auto &[type, layout] : layouts)
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 {};
bufferInfo.buffer = buffer.handle;
bufferInfo.offset = 0;

@ -3,10 +3,8 @@
#include "vulkan/buffer.hpp"
#include "vulkan/command_pool.hpp"
Image::Image(
uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling,
VkImageUsageFlags usage
) : format(format), width(width), height(height) {
Image::Image(uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling,
VkImageUsageFlags usage) : format(format), width(width), height(height) {
VkImageCreateInfo imageCreateInfo {};
imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
@ -27,20 +25,14 @@ Image::Image(
allocationCreateInfo.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE;
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,
VkImageUsageFlags usage
) : Image(width, height, format, tiling, usage) {
Image::Image(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,
VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT
);
Buffer stagingBuffer(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);
transitionLayout(VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
@ -124,14 +116,13 @@ void Image::transitionLayout(VkImageLayout oldLayout, VkImageLayout newLayout) {
VkPipelineStageFlags sourceStage = 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.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_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.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
@ -139,14 +130,12 @@ void Image::transitionLayout(VkImageLayout oldLayout, VkImageLayout newLayout) {
destinationStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
}
vkCmdPipelineBarrier(
commandBuffer,
sourceStage, destinationStage,
0,
0, nullptr,
0, nullptr,
1, &barrier
);
vkCmdPipelineBarrier(commandBuffer,
sourceStage, destinationStage,
0,
0, nullptr,
0, nullptr,
1, &barrier);
commandPool->endSingleTimeCommandBuffer(commandBuffer, Instance::instance->graphicsAndPresentQueue);
}

@ -6,7 +6,7 @@
#include "vk_mem_alloc.h"
#include <cstring>
const std::vector<const char *> deviceExtensions = {
const std::vector<const char*> deviceExtensions = {
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
VK_EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME
};
@ -49,7 +49,7 @@ bool checkValidationLayerSupport(){
}
#endif
Instance *Instance::instance = nullptr;
Instance* Instance::instance = nullptr;
Instance::Instance() {
instance = this;
@ -71,26 +71,10 @@ void Instance::initWindow() {
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
glfwWindowHint(GLFW_RESIZABLE, 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);
glfwSetWindowPos(window, x, y);
glfwSetFramebufferSizeCallback(
window, [](GLFWwindow *window, int width, int height) {
instance->windowResized = true;
}
);
glfwSetFramebufferSizeCallback(window, [](GLFWwindow* window, int width, int height) {
instance->windowResized = true;
});
}
void Instance::createInstance() {
@ -109,7 +93,7 @@ void Instance::createInstance() {
applicationInfo.apiVersion = VK_API_VERSION_1_1;
uint32_t glfwExtensionCount = 0;
const char **glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
const char** glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
VkInstanceCreateInfo instanceCreateInfo {};
instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
@ -133,21 +117,21 @@ void Instance::createSurface() {
void Instance::pickPhysicalDevice() {
uint32_t deviceCount = 0;
vkEnumeratePhysicalDevices(handle, &deviceCount, nullptr);
if (deviceCount == 0) {
if (deviceCount == 0){
throw std::runtime_error("failed to find GPUs with Vulkan support!");
}
std::vector<VkPhysicalDevice> devices(deviceCount);
vkEnumeratePhysicalDevices(handle, &deviceCount, devices.data());
for (const VkPhysicalDevice &potentialPhysicalDevice: devices) {
if (isDeviceSuitable(potentialPhysicalDevice)) {
for (const VkPhysicalDevice &potentialPhysicalDevice : devices){
if (isDeviceSuitable(potentialPhysicalDevice)){
physicalDevice = potentialPhysicalDevice;
indices = findQueueFamilies(physicalDevice, surface);
break;
}
}
if (physicalDevice == VK_NULL_HANDLE) {
if (physicalDevice == VK_NULL_HANDLE){
throw std::runtime_error("failed to find a suitable GPU!");
}
@ -160,7 +144,7 @@ void Instance::createLogicalDevice() {
std::vector<VkDeviceQueueCreateInfo> queueCreateInfos;
float queuePriority = 1.0f;
for (uint32_t queueFamily: indices.uniqueQueueFamilies()) {
for (uint32_t queueFamily : indices.uniqueQueueFamilies()){
VkDeviceQueueCreateInfo queueCreateInfo {};
queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queueCreateInfo.queueFamilyIndex = queueFamily;
@ -195,9 +179,8 @@ void Instance::createLogicalDevice() {
}
#include <fstream>
void printVmaStats() {
char *stats;
void printVmaStats(){
char* stats;
vmaBuildStatsString(Instance::GetAllocator(), &stats, VK_TRUE);
std::ofstream stream("stats.json");
stream << stats;
@ -228,7 +211,7 @@ Instance::QueueFamilyIndices Instance::findQueueFamilies(VkPhysicalDevice device
QueueFamilyIndices indices {};
uint32_t i = 0;
for (const VkQueueFamilyProperties &queueFamilyProperties: queueFamilies) {
for (const VkQueueFamilyProperties& queueFamilyProperties : queueFamilies){
VkBool32 present = false;
vkGetPhysicalDeviceSurfaceSupportKHR(device, i, surface, &present);
@ -258,7 +241,7 @@ bool Instance::isDeviceSuitable(VkPhysicalDevice potentialPhysicalDevice) {
bool extensionsSupported = checkDeviceExtensionSupport(potentialPhysicalDevice);
bool swapChainAdequate = false;
if (extensionsSupported) {
if (extensionsSupported){
SwapchainSupportDetails details = querySwapchainSupport(potentialPhysicalDevice, surface);
swapChainAdequate = !details.formats.empty() && !details.presentModes.empty();
}
@ -275,7 +258,7 @@ bool Instance::checkDeviceExtensionSupport(VkPhysicalDevice device) {
std::vector<VkExtensionProperties> availableExtensions(extensionCount);
vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, availableExtensions.data());
for (const VkExtensionProperties &extension: availableExtensions) {
for (const VkExtensionProperties& extension : availableExtensions){
required.erase(extension.extensionName);
}
@ -316,24 +299,24 @@ Instance::~Instance() {
glfwTerminate();
}
void Instance::initImGui(const Swapchain &swapchain) {
void Instance::initImGui(const Swapchain& swapchain) {
ImGui::CreateContext();
ImGui::StyleColorsDark();
ImGuiIO &io = ImGui::GetIO();
ImGuiIO& io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
ImGui_ImplGlfw_InitForVulkan(window, true);
VkDescriptorPoolSize pool_sizes[] = {
{
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1
}
};
VkDescriptorPoolCreateInfo pool_info = {};
pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
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;
vkCreateDescriptorPool(Instance::GetDevice(), &pool_info, nullptr, &imGuiDescriptorPool);
@ -355,22 +338,3 @@ void Instance::initImGui(const Swapchain &swapchain) {
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/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);
if (!file.is_open()) {
if (!file.is_open()){
throw std::runtime_error("failed to open file!");
}
@ -33,10 +33,8 @@ VkShaderModule Pipeline::createShaderModule(const std::vector<char> &code) {
return shaderModule;
}
Pipeline::Pipeline(
const std::vector<VkDescriptorSetLayout> &descriptorSetLayouts,
const std::vector<VkPushConstantRange> &pushConstantRanges
) {
Pipeline::Pipeline(const std::vector<VkDescriptorSetLayout> &descriptorSetLayouts,
const std::vector<VkPushConstantRange> &pushConstantRanges) {
VkPipelineLayoutCreateInfo pipelineLayoutInfo {};
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipelineLayoutInfo.setLayoutCount = descriptorSetLayouts.size();
@ -53,12 +51,10 @@ Pipeline::~Pipeline() {
}
GraphicsPipeline::GraphicsPipeline(
const std::string &vertexShaderPath, const std::string &fragmentShaderPath,
VkRenderPass renderPass,
const std::vector<VkDescriptorSetLayout> &descriptorSetLayouts,
const std::vector<VkPushConstantRange> &pushConstantRanges
) : Pipeline(descriptorSetLayouts, pushConstantRanges) {
GraphicsPipeline::GraphicsPipeline(const std::string& vertexShaderPath, const std::string& fragmentShaderPath,
VkRenderPass renderPass,
const std::vector<VkDescriptorSetLayout> &descriptorSetLayouts,
const std::vector<VkPushConstantRange> &pushConstantRanges) : Pipeline(descriptorSetLayouts, pushConstantRanges) {
auto vertShaderCode = readFile(vertexShaderPath);
auto fragShaderCode = readFile(fragmentShaderPath);
@ -126,8 +122,7 @@ GraphicsPipeline::GraphicsPipeline(
multisample.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
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;
VkPipelineColorBlendStateCreateInfo colorBlending {};
@ -171,11 +166,9 @@ GraphicsPipeline::GraphicsPipeline(
vkDestroyShaderModule(Instance::GetDevice(), fragShaderModule, nullptr);
}
ComputePipeline::ComputePipeline(
const std::string &shaderFile,
const std::vector<VkDescriptorSetLayout> &descriptorSetLayouts,
const std::vector<VkPushConstantRange> &pushConstantRanges
) : Pipeline(descriptorSetLayouts, pushConstantRanges) {
ComputePipeline::ComputePipeline(const std::string& shaderFile,
const std::vector<VkDescriptorSetLayout> &descriptorSetLayouts,
const std::vector<VkPushConstantRange> &pushConstantRanges) : Pipeline(descriptorSetLayouts, pushConstantRanges) {
VkShaderModule module = createShaderModule(readFile(shaderFile));
VkPipelineShaderStageCreateInfo stageInfo {};

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

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