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