can add bodies at runtime

feature/softbody-runtime-control
Benjamin Kraft 3 months ago
parent 9b9fcef3fe
commit 0afe899295
  1. 15
      include/application.hpp
  2. 14
      include/vulkan/buffer.hpp
  3. 110
      src/application.cpp
  4. 74
      src/vulkan/buffer.cpp
  5. 4
      src/vulkan/image.cpp

@ -30,7 +30,7 @@ class Instance;
class Swapchain; class Swapchain;
class GraphicsPipeline; class GraphicsPipeline;
class Buffer; class Buffer;
class SimulationBuffer; class Buffer;
class CommandPool; class CommandPool;
class Image; class Image;
class ComputePipeline; class ComputePipeline;
@ -64,8 +64,9 @@ private:
unique_ptr<Semaphore> transferSemaphore; unique_ptr<Semaphore> transferSemaphore;
unique_ptr<Fence> renderFence; unique_ptr<Fence> renderFence;
unique_ptr<Fence> computeFence; unique_ptr<Fence> computeFence;
unique_ptr<Fence> transferFence; unique_ptr<Fence> computeTransferredFence;
std::mutex submitMutex; std::mutex submitMutex;
std::mutex bufferWriteMutex;
unique_ptr<Swapchain> swapchain; unique_ptr<Swapchain> swapchain;
unique_ptr<DescriptorPool> descriptorPool; unique_ptr<DescriptorPool> descriptorPool;
@ -83,11 +84,11 @@ private:
void updateConstraintBuffers(VkCommandBuffer commandBuffer); void updateConstraintBuffers(VkCommandBuffer commandBuffer);
size_t currentDrawVertexBuffer = 0; size_t currentDrawVertexBuffer = 0;
unique_ptr<SimulationBuffer> vertexBuffers[2]; unique_ptr<Buffer> vertexBuffers[2];
unique_ptr<SimulationBuffer> faceBuffer; unique_ptr<Buffer> faceBuffer;
unique_ptr<SimulationBuffer> edgeBuffer; unique_ptr<Buffer> edgeBuffer;
unique_ptr<SimulationBuffer> triangleBuffer; unique_ptr<Buffer> triangleBuffer;
unique_ptr<SimulationBuffer> tetrahedronBuffer; unique_ptr<Buffer> tetrahedronBuffer;
ConstraintData constraintData {}; ConstraintData constraintData {};
vector<unique_ptr<SoftBody>> softBodies; vector<unique_ptr<SoftBody>> softBodies;

@ -19,10 +19,8 @@ class Buffer {
public: public:
Buffer(VkDeviceSize bufferSize, VkBufferUsageFlags bufferUsage, Buffer(VkDeviceSize bufferSize, VkBufferUsageFlags bufferUsage,
VmaMemoryUsage memoryUsage, VmaAllocationCreateFlags vmaAllocationFlags); VmaMemoryUsage memoryUsage, VmaAllocationCreateFlags vmaAllocationFlags);
Buffer(VkDeviceSize bufferSize, void* initialData, VkBufferUsageFlags bufferUsage, unique_ptr<Buffer> appended(void* data, VkDeviceSize appendSize, VkCommandBuffer commandBuffer) const;
VmaMemoryUsage memoryUsage, VmaAllocationCreateFlags vmaAllocationFlags); unique_ptr<Buffer> replaced(void* data, VkDeviceSize replaceSize, VkCommandBuffer commandBuffer) const;
static unique_ptr<Buffer> Append(const Buffer& old, void* data, VkDeviceSize size, VkCommandBuffer commandBuffer=VK_NULL_HANDLE);
static unique_ptr<Buffer> Replace(const Buffer& old, void* data, VkDeviceSize size, VkCommandBuffer commandBuffer=VK_NULL_HANDLE);
virtual ~Buffer(); virtual ~Buffer();
VkBuffer handle = VK_NULL_HANDLE; VkBuffer handle = VK_NULL_HANDLE;
VmaAllocation allocation = VK_NULL_HANDLE; VmaAllocation allocation = VK_NULL_HANDLE;
@ -35,7 +33,7 @@ public:
} }
void copyTo(Buffer* buffer) const; void copyTo(Buffer* buffer) const;
void copyTo(Image* image) const; void copyTo(Image* image) const;
void setData(void* data, VkDeviceSize offset, VkDeviceSize size, VkCommandBuffer commandBuffer=VK_NULL_HANDLE); 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;
@ -46,9 +44,3 @@ private:
VmaMemoryUsage memoryUsage; VmaMemoryUsage memoryUsage;
VmaAllocationCreateFlags allocationCreateFlags; VmaAllocationCreateFlags allocationCreateFlags;
}; };
class SimulationBuffer : public Buffer {
public:
SimulationBuffer(VkDeviceSize bufferSize, VkBufferUsageFlags bufferUsage=0):
Buffer(bufferSize, initialData, bufferUsage | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE, 0) {}
};

@ -81,9 +81,11 @@ Application::Application() {
bool grabbing; bool grabbing;
} initialGrabInformation {}; } initialGrabInformation {};
initialGrabInformation.distanceToFace = 1e20; initialGrabInformation.distanceToFace = 1e20;
grabBuffer = make_unique<Buffer>(sizeof(GrabInformation), &initialGrabInformation, sizeof(GrabInformation), grabBuffer = make_unique<Buffer>(sizeof(GrabInformation),
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE, 0); VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE, 0);
grabBuffer->setName("Grab"); grabBuffer->setName("Grab");
grabBuffer->setData(&initialGrabInformation, 0, sizeof(initialGrabInformation));
grabber = make_unique<Grabber>(); grabber = make_unique<Grabber>();
sizeInformationBuffer = make_unique<Buffer>( sizeInformationBuffer = make_unique<Buffer>(
@ -93,8 +95,9 @@ Application::Application() {
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"); sizeInformationBuffer->setName("Sizes");
sizeInformation = &sizeInformationBuffer->access<SizesUniformData>(); sizeInformation = &sizeInformationBuffer->access<SizesUniformData>();
*sizeInformation = {};
addSoftBody("models/bunny_medium.ply"); addSoftBody("models/bunny_medium.ply", 10);
SimulationUniformData simulationUniformData { SimulationUniformData simulationUniformData {
.gravity = {0, -9.81, 0}, .gravity = {0, -9.81, 0},
@ -122,13 +125,6 @@ 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(*vertexBuffers[1 - currentDrawVertexBuffer], VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, DescriptorSet::MESH, 0);
descriptorPool->bindBuffer(*faceBuffer, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, DescriptorSet::MESH, 1);
descriptorPool->bindBuffer(*edgeBuffer, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, DescriptorSet::MESH, 2);
// descriptorPool->bindBuffer(*triangleBuffer, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, DescriptorSet::MESH, 3);
descriptorPool->bindBuffer(*tetrahedronBuffer, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, DescriptorSet::MESH, 4);
descriptorPool->bindBuffer(*sizeInformationBuffer, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, DescriptorSet::MESH, 5);
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);
@ -179,10 +175,12 @@ void Application::createSyncObjects() {
transferSemaphore = make_unique<Semaphore>(); transferSemaphore = make_unique<Semaphore>();
renderFence = make_unique<Fence>(true); renderFence = make_unique<Fence>(true);
computeFence = make_unique<Fence>(false); computeFence = make_unique<Fence>(false);
transferFence = make_unique<Fence>(false); computeTransferredFence = make_unique<Fence>(false);
} }
void Application::addSoftBody(const std::string &modelFile, size_t count) { void Application::addSoftBody(const std::string &modelFile, size_t count) {
bufferWriteMutex.lock();
Mesh mesh(modelFile); Mesh mesh(modelFile);
// Do SoftBody calculations once in constructor, will be copied from now on // Do SoftBody calculations once in constructor, will be copied from now on
@ -242,25 +240,64 @@ void Application::addSoftBody(const std::string &modelFile, size_t count) {
sizeInformation->vertexCount += newVertices.size(); sizeInformation->vertexCount += newVertices.size();
sizeInformation->faceCount += newFaces.size(); sizeInformation->faceCount += newFaces.size();
auto commandBuffer = Instance::instance->renderingCommandPool->beginSingleTimeCommandBuffer(); unique_ptr<Buffer> newVertexBuffers[2];
vertexBuffers[0] = Buffer::Append(*vertexBuffers[0], newVertices.data(), newVertices.size() * sizeof(Vertex), commandBuffer); unique_ptr<Buffer> newFaceBuffer;
vertexBuffers[1] = Buffer::Append(*vertexBuffers[1], newVertices.data(), newVertices.size() * sizeof(Vertex), commandBuffer); unique_ptr<Buffer> newEdgeBuffer;
faceBuffer = Buffer::Append(*faceBuffer, newFaces.data(), newFaces.size() * sizeof(Face), commandBuffer); unique_ptr<Buffer> newTetrahedronBuffer;
edgeBuffer = Buffer::Replace(*edgeBuffer, constraintData.edges.data(), constraintData.edges.size() * sizeof(Edge), commandBuffer);
// triangleBuffer = Buffer::Replace(*triangleBuffer, constraintData.triangles.data(), constraintData.triangles.size() * sizeof(Triangle), commandBuffer);
tetrahedronBuffer = Buffer::Replace(*tetrahedronBuffer, constraintData.tetrahedra.data(), constraintData.tetrahedra.size() * sizeof(Tetrahedron), commandBuffer);
vertexBuffers[0] = make_unique<SimulationBuffer>(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
vertexBuffers[1] = make_unique<SimulationBuffer>(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
faceBuffer = make_unique<SimulationBuffer>(VK_BUFFER_USAGE_INDEX_BUFFER_BIT);
auto commandBuffer = Instance::instance->renderingCommandPool->beginSingleTimeCommandBuffer();
vertexBuffers[0]->setName("Vertices 0"); VkBufferUsageFlags bufferUsageFlags = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
vertexBuffers[1]->setName("Vertices 1"); VmaMemoryUsage memoryUsage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE;
faceBuffer->setName("Faces");
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);
newFaceBuffer->setData(newFaces.data(), 0, newFaceBuffer->size, commandBuffer);
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);
}
VkQueue queue = Instance::instance->graphicsAndPresentQueue; VkQueue queue = Instance::instance->graphicsAndPresentQueue;
Instance::instance->renderingCommandPool->endSingleTimeCommandBuffer(commandBuffer, queue); Instance::instance->renderingCommandPool->endSingleTimeCommandBuffer(commandBuffer, queue);
vertexBuffers[0] = std::move(newVertexBuffers[0]);
vertexBuffers[1] = std::move(newVertexBuffers[1]);
faceBuffer = std::move(newFaceBuffer);
edgeBuffer = std::move(newEdgeBuffer);
tetrahedronBuffer = std::move(newTetrahedronBuffer);
descriptorPool->bindBuffer(*vertexBuffers[1 - currentDrawVertexBuffer], VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, DescriptorSet::MESH, 0);
descriptorPool->bindBuffer(*faceBuffer, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, DescriptorSet::MESH, 1);
descriptorPool->bindBuffer(*edgeBuffer, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, DescriptorSet::MESH, 2);
descriptorPool->bindBuffer(*tetrahedronBuffer, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, DescriptorSet::MESH, 4);
descriptorPool->bindBuffer(*sizeInformationBuffer, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, DescriptorSet::MESH, 5);
bufferWriteMutex.unlock();
} }
void Application::removeSoftBody(const unique_ptr<SoftBody> &softBody) { void Application::removeSoftBody(const unique_ptr<SoftBody> &softBody) {
@ -275,13 +312,14 @@ void Application::removeSoftBody(const unique_ptr<SoftBody> &softBody) {
} }
void Application::updateConstraintBuffers(VkCommandBuffer commandBuffer) { void Application::updateConstraintBuffers(VkCommandBuffer commandBuffer) {
edgeBuffer = make_unique<SimulationBuffer>(constraintData.edges.size() * sizeof(Edge), constraintData.edges.data()); /*
// triangleBuffer = make_unique<SimulationBuffer>(); edgeBuffer = make_unique<Buffer>(constraintData.edges.size() * sizeof(Edge), constraintData.edges.data());
tetrahedronBuffer = make_unique<SimulationBuffer>(constraintData.tetrahedra.size() * sizeof(Tetrahedron), constraintData.tetrahedra.data()); tetrahedronBuffer = make_unique<Buffer>(constraintData.tetrahedra.size() * sizeof(Tetrahedron), constraintData.tetrahedra.data());
edgeBuffer.value()->setName("Edges"); edgeBuffer.value()->setName("Edges");
// triangleBuffer->setName("Triangles"); // triangleBuffer->setName("Triangles");
tetrahedronBuffer.value()->setName("Tetrahedra"); tetrahedronBuffer.value()->setName("Tetrahedra");
*/
} }
void Application::createComputePipelines() { void Application::createComputePipelines() {
@ -365,7 +403,7 @@ void Application::drawFrame(float dt) {
VkBufferMemoryBarrier vertexBufferBarrier{}; VkBufferMemoryBarrier vertexBufferBarrier{};
vertexBufferBarrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; vertexBufferBarrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
vertexBufferBarrier.size = vertexBuffers[currentDrawVertexBuffer]->allocationInfo.size; vertexBufferBarrier.size = vertexBuffers[currentDrawVertexBuffer]->size;
vertexBufferBarrier.offset = 0; vertexBufferBarrier.offset = 0;
vertexBufferBarrier.buffer = vertexBuffers[currentDrawVertexBuffer]->handle; vertexBufferBarrier.buffer = vertexBuffers[currentDrawVertexBuffer]->handle;
vertexBufferBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; vertexBufferBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
@ -474,6 +512,8 @@ void Application::recordDrawCommands(VkCommandBuffer commandBuffer) {
} }
void Application::update() { void Application::update() {
bufferWriteMutex.lock();
VkCommandBufferBeginInfo beginInfo {}; VkCommandBufferBeginInfo beginInfo {};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
beginInfo.flags = 0; beginInfo.flags = 0;
@ -507,7 +547,7 @@ void Application::update() {
vkBeginCommandBuffer(cmdBuffer, &beginInfo); vkBeginCommandBuffer(cmdBuffer, &beginInfo);
VkBufferCopy copyRegion {}; VkBufferCopy copyRegion {};
copyRegion.size = vertexBuffers[1 - currentDrawVertexBuffer]->allocationInfo.size; copyRegion.size = vertexBuffers[1 - currentDrawVertexBuffer]->size;
copyRegion.srcOffset = 0; copyRegion.srcOffset = 0;
copyRegion.dstOffset = 0; copyRegion.dstOffset = 0;
@ -526,7 +566,7 @@ void Application::update() {
submit.pWaitDstStageMask = &waitStage; submit.pWaitDstStageMask = &waitStage;
submitMutex.lock(); submitMutex.lock();
vkQueueSubmit(Instance::instance->computeAndTransferQueue, 1, &submit, transferFence->handle); vkQueueSubmit(Instance::instance->computeAndTransferQueue, 1, &submit, computeTransferredFence->handle);
submitMutex.unlock(); submitMutex.unlock();
} }
@ -535,11 +575,13 @@ void Application::update() {
currentDrawVertexBuffer = 1 - currentDrawVertexBuffer; currentDrawVertexBuffer = 1 - currentDrawVertexBuffer;
vkWaitForFences(Instance::GetDevice(), 1, &transferFence->handle, VK_TRUE, UINT64_MAX); vkWaitForFences(Instance::GetDevice(), 1, &computeTransferredFence->handle, VK_TRUE, UINT64_MAX);
vkResetFences(Instance::GetDevice(), 1, &transferFence->handle); vkResetFences(Instance::GetDevice(), 1, &computeTransferredFence->handle);
currentDrawVertexBuffer = 1 - currentDrawVertexBuffer; currentDrawVertexBuffer = 1 - currentDrawVertexBuffer;
// descriptorPool->bindBuffer(*vertexBuffers[1 - currentDrawVertexBuffer], VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, DescriptorSet::MESH, 0); // descriptorPool->bindBuffer(*vertexBuffers[1 - currentDrawVertexBuffer], VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, DescriptorSet::MESH, 0);
bufferWriteMutex.unlock();
} }
uint32_t Application::GetGroupCount(uint32_t threads, uint32_t blockSize) { uint32_t Application::GetGroupCount(uint32_t threads, uint32_t blockSize) {
@ -670,7 +712,7 @@ void Application::computePipelineBarrier(VkCommandBuffer commandBuffer) {
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;
bufferMemoryBarrier.size = buffer.allocationInfo.size; bufferMemoryBarrier.size = buffer.size;
bufferMemoryBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; bufferMemoryBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
bufferMemoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT; bufferMemoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
bufferMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; bufferMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;

@ -22,21 +22,6 @@ Buffer::Buffer(VkDeviceSize bufferSize, VkBufferUsageFlags bufferUsageFlags, Vma
vmaCreateBuffer(Instance::GetAllocator(), &bufferCreateInfo, &allocationCreateInfo, &handle, &allocation, &allocationInfo); vmaCreateBuffer(Instance::GetAllocator(), &bufferCreateInfo, &allocationCreateInfo, &handle, &allocation, &allocationInfo);
} }
Buffer::Buffer(VkDeviceSize bufferSize, void *initialData, VkBufferUsageFlags bufferUsageFlags,
VmaMemoryUsage memoryUsage, VmaAllocationCreateFlags allocationFlags)
: Buffer(bufferSize, bufferUsageFlags | VK_BUFFER_USAGE_TRANSFER_DST_BIT, memoryUsage, allocationFlags){
Buffer stagingBuffer(
bufferSize,
VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
VMA_MEMORY_USAGE_AUTO,
VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT
);
memcpy(stagingBuffer.allocationInfo.pMappedData, initialData, bufferSize);
stagingBuffer.copyTo(this);
}
Buffer::~Buffer() { Buffer::~Buffer() {
vmaDestroyBuffer(Instance::GetAllocator(), handle, allocation); vmaDestroyBuffer(Instance::GetAllocator(), handle, allocation);
} }
@ -48,7 +33,7 @@ void Buffer::copyTo(Buffer *buffer) const {
VkCommandBuffer commandBuffer = commandPool->beginSingleTimeCommandBuffer(); VkCommandBuffer commandBuffer = commandPool->beginSingleTimeCommandBuffer();
VkBufferCopy copyRegion {}; VkBufferCopy copyRegion {};
copyRegion.size = allocationInfo.size; copyRegion.size = size;
vkCmdCopyBuffer(commandBuffer, handle, buffer->handle, 1, &copyRegion); vkCmdCopyBuffer(commandBuffer, handle, buffer->handle, 1, &copyRegion);
commandPool->endSingleTimeCommandBuffer(commandBuffer, queue); commandPool->endSingleTimeCommandBuffer(commandBuffer, queue);
@ -76,15 +61,23 @@ void Buffer::copyTo(Image *image) const {
commandPool->endSingleTimeCommandBuffer(commandBuffer, queue); commandPool->endSingleTimeCommandBuffer(commandBuffer, queue);
} }
void Buffer::setData(void *data, VkDeviceSize offset, VkDeviceSize size, VkCommandBuffer commandBuffer) { void Buffer::setData(void *data, VkDeviceSize offset, VkDeviceSize dataSize, VkCommandBuffer commandBuffer) {
if (allocationInfo.pMappedData){ if (allocationInfo.pMappedData){
memcpy(allocationInfo.pMappedData, reinterpret_cast<u_char*>(data) + offset, size); 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;
if (!commandBuffer){
commandBuffer = Instance::instance->renderingCommandPool->beginSingleTimeCommandBuffer();
singleShot = true;
}
auto stagingBuffer = getStagingBuffer(); auto stagingBuffer = getStagingBuffer();
stagingBuffer->setData(data, offset, size); stagingBuffer->setData(data, offset, dataSize);
VkBufferMemoryBarrier bufferMemoryBarrier {}; VkBufferMemoryBarrier bufferMemoryBarrier {};
bufferMemoryBarrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; bufferMemoryBarrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
@ -93,7 +86,7 @@ void Buffer::setData(void *data, VkDeviceSize offset, VkDeviceSize size, VkComma
bufferMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; bufferMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
bufferMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; bufferMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
bufferMemoryBarrier.buffer = stagingBuffer->handle; bufferMemoryBarrier.buffer = stagingBuffer->handle;
bufferMemoryBarrier.size = size; bufferMemoryBarrier.size = dataSize;
bufferMemoryBarrier.offset = offset; bufferMemoryBarrier.offset = offset;
vkCmdPipelineBarrier( vkCmdPipelineBarrier(
@ -108,9 +101,12 @@ void Buffer::setData(void *data, VkDeviceSize offset, VkDeviceSize size, VkComma
VkBufferCopy region {}; VkBufferCopy region {};
region.srcOffset = offset; region.srcOffset = offset;
region.dstOffset = offset; region.dstOffset = offset;
region.size = size; region.size = dataSize;
vkCmdCopyBuffer(commandBuffer, stagingBuffer->handle, handle, 1, &region); vkCmdCopyBuffer(commandBuffer, stagingBuffer->handle, handle, 1, &region);
if (singleShot)
Instance::instance->renderingCommandPool->endSingleTimeCommandBuffer(commandBuffer, Instance::instance->graphicsAndPresentQueue);
} }
} }
@ -119,28 +115,32 @@ void Buffer::setName(const std::string &newName) {
vmaSetAllocationName(Instance::GetAllocator(), allocation, newName.data()); vmaSetAllocationName(Instance::GetAllocator(), allocation, newName.data());
} }
unique_ptr<Buffer> Buffer::Append(const Buffer &old, void *data, VkDeviceSize size, VkCommandBuffer commandBuffer) { unique_ptr<Buffer> Buffer::appended(void *data, VkDeviceSize appendSize, VkCommandBuffer commandBuffer) const {
auto buffer = make_unique<Buffer>(old.size + size, auto buffer = make_unique<Buffer>(size + appendSize,
old.bufferUsageFlags | VK_BUFFER_USAGE_TRANSFER_DST_BIT, bufferUsageFlags,
old.memoryUsage, memoryUsage,
old.allocationCreateFlags); allocationCreateFlags);
buffer->setName(name);
VkBufferCopy copyRegion {}; VkBufferCopy copyRegion {};
copyRegion.size = old.size; copyRegion.size = size;
vkCmdCopyBuffer(commandBuffer, old.handle, buffer->handle, 1, &copyRegion); copyRegion.srcOffset = 0;
copyRegion.dstOffset = 0;
vkCmdCopyBuffer(commandBuffer, handle, buffer->handle, 1, &copyRegion);
buffer->setData(data, old.size, size, commandBuffer); buffer->setData(data, size, appendSize, commandBuffer);
return buffer; return buffer;
} }
unique_ptr<Buffer> Buffer::Replace(const Buffer &old, void *data, VkDeviceSize size, VkCommandBuffer commandBuffer) { unique_ptr<Buffer> Buffer::replaced(void *data, VkDeviceSize replaceSize, VkCommandBuffer commandBuffer) const {
auto buffer = make_unique<Buffer>(size, auto buffer = make_unique<Buffer>(replaceSize,
old.bufferUsageFlags | VK_BUFFER_USAGE_TRANSFER_DST_BIT, bufferUsageFlags,
old.memoryUsage, memoryUsage,
old.allocationCreateFlags); allocationCreateFlags);
buffer->setName(name);
buffer->setData(data, 0, size, commandBuffer); buffer->setData(data, 0, replaceSize, commandBuffer);
return buffer; return buffer;
} }
@ -150,10 +150,12 @@ shared_ptr<Buffer> Buffer::getStagingBuffer() {
return stagingBufferOptional.value(); return stagingBufferOptional.value();
stagingBufferOptional = make_shared<Buffer>( stagingBufferOptional = make_shared<Buffer>(
allocationInfo.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");
return stagingBufferOptional.value(); return stagingBufferOptional.value();
} }

@ -31,7 +31,9 @@ Image::Image(uint32_t width, uint32_t height, VkFormat format, VkImageTiling til
Image::Image(void *initialData, VkDeviceSize size, uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, Image::Image(void *initialData, VkDeviceSize size, uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling,
VkImageUsageFlags usage) : Image(width, height, format, tiling, usage){ VkImageUsageFlags usage) : Image(width, height, format, tiling, usage){
Buffer stagingBuffer(size, initialData, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE, 0); 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); transitionLayout(VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
stagingBuffer.copyTo(this); stagingBuffer.copyTo(this);

Loading…
Cancel
Save