diff --git a/src/headset/emulated_headset.cpp b/src/headset/emulated_headset.cpp index 9ef4bf68a9f7d2c796365b8a0f3aacee1618fb73..3bd74ecdad9d65e96c617d1c9c4a0d113dc0546c 100644 --- a/src/headset/emulated_headset.cpp +++ b/src/headset/emulated_headset.cpp @@ -230,12 +230,18 @@ void EmulatedHeadset::destroy_framebuffer() { for (lava::image::ptr& framebuffer : this->framebuffers) { - framebuffer->destroy(true); - framebuffer = nullptr; + if (framebuffer != nullptr) + { + framebuffer->destroy(true); + framebuffer = nullptr; + } } - this->framebuffer_array->destroy(); - this->framebuffer_array = nullptr; + if (this->framebuffer_array != nullptr) + { + this->framebuffer_array->destroy(); + this->framebuffer_array = nullptr; + } } void EmulatedHeadset::compute_matrices(Eye eye) diff --git a/src/headset/headset.cpp b/src/headset/headset.cpp index a90f140b34c2a676c78e7a86cc81a6b95aaa2cfe..52e0f0aa3b128479601980cecb2f47c1317751a9 100644 --- a/src/headset/headset.cpp +++ b/src/headset/headset.cpp @@ -24,6 +24,11 @@ bool Headset::on_setup_device(lava::device::create_param& parameters) return true; } +void Headset::on_shutdown() +{ + +} + void Headset::submit_metadata(const FrameMetadata& metadata) { diff --git a/src/headset/headset.hpp b/src/headset/headset.hpp index 77aca53b5905fdcfd35317cbb25b9d1161984ba8..2e8eceddb442c2d796356970ccc926420d891442 100644 --- a/src/headset/headset.hpp +++ b/src/headset/headset.hpp @@ -69,9 +69,13 @@ public: virtual bool on_create() = 0; // This function is called during the shutdown of the application and every time the active stereo strategy changes. - // A headset can use this function to destroy all reqources that it has created. + // A headset can use this function to destroy all resources that it has created. virtual void on_destroy() = 0; + // This function is only called during the shutdown of the application. + // A headset can use this function to destroy all remaining resources. + virtual void on_shutdown(); + // This function is called every frame when the interface needs to be rendered. // A headset can use this function to manage its own interface. virtual bool on_interface() = 0; diff --git a/src/headset/openvr_headset.cpp b/src/headset/openvr_headset.cpp index 5e4da384bcbda186fe9b619f14ddb892f7848154..5a2e89afc6b2aa78e5b71bbdaa5dd245b43c863b 100644 --- a/src/headset/openvr_headset.cpp +++ b/src/headset/openvr_headset.cpp @@ -68,7 +68,10 @@ bool OpenVRHeadset::on_create() void OpenVRHeadset::on_destroy() { this->destroy_framebuffer(); +} +void OpenVRHeadset::on_shutdown() +{ vr::VR_Shutdown(); } @@ -159,7 +162,7 @@ void OpenVRHeadset::submit_frame(VkCommandBuffer command_buffer, VkImageLayout f if (error != vr::VRCompositorError_None) { - lava::log()->error("Can't submit image to OpenVR. Error code '{}'", error); + lava::log()->error("Can't submit image to OpenVR. Maybe due to headset standby. Error code '{}'", error); } } @@ -246,12 +249,18 @@ void OpenVRHeadset::destroy_framebuffer() { for (lava::image::ptr& framebuffer : this->framebuffers) { - framebuffer->destroy(true); - framebuffer = nullptr; + if (framebuffer != nullptr) + { + framebuffer->destroy(true); + framebuffer = nullptr; + } } - this->framebuffer_array->destroy(); - this->framebuffer_array = nullptr; + if (this->framebuffer_array != nullptr) + { + this->framebuffer_array->destroy(); + this->framebuffer_array = nullptr; + } } void OpenVRHeadset::compute_matrices(Eye eye) diff --git a/src/headset/openvr_headset.hpp b/src/headset/openvr_headset.hpp index 42e1f4771c32f9f10f39872aa32d00cedceb93ca..cc2580113802048010aee851f3ab9a2a3affb56d 100644 --- a/src/headset/openvr_headset.hpp +++ b/src/headset/openvr_headset.hpp @@ -22,6 +22,7 @@ public: bool on_create() override; void on_destroy() override; + void on_shutdown() override; bool on_interface() override; bool on_update(lava::delta delta_time) override; diff --git a/src/headset/openxr_headset.cpp b/src/headset/openxr_headset.cpp index a5b263aec215ed2eafdf60dece88b3c5cdb6086c..4d298260afaf710e5896d0bf3fa0d164ce1fa216 100644 --- a/src/headset/openxr_headset.cpp +++ b/src/headset/openxr_headset.cpp @@ -129,6 +129,7 @@ bool OpenXRHeadset::on_setup_instance(lava::frame_config& config) } this->instance_extensions = OpenXRHeadset::split_string(extension_string); + this->instance_extensions.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME); //NOTE: For some reason this extension is not added for (const std::string& extension : this->instance_extensions) { @@ -273,6 +274,10 @@ void OpenXRHeadset::on_destroy() xrDestroySpace(this->space); xrDestroySession(this->session); +} + +void OpenXRHeadset::on_shutdown() +{ xrDestroyInstance(this->instance); } @@ -325,7 +330,7 @@ void OpenXRHeadset::submit_frame(VkCommandBuffer command_buffer, VkImageLayout f { VkImageMemoryBarrier frame_barrier = lava::image_memory_barrier(frame_image->get(), frame_layout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); frame_barrier.srcAccessMask = 0; - frame_barrier.dstAccessMask = 0; + frame_barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; frame_barrier.subresourceRange = frame_image->get_subresource_range(); image_barriers.push_back(frame_barrier); @@ -333,7 +338,7 @@ void OpenXRHeadset::submit_frame(VkCommandBuffer command_buffer, VkImageLayout f VkImageMemoryBarrier swapchain_begin_barrier = lava::image_memory_barrier(swapchain_image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); swapchain_begin_barrier.srcAccessMask = 0; - swapchain_begin_barrier.dstAccessMask = 0; + swapchain_begin_barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; swapchain_begin_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; swapchain_begin_barrier.subresourceRange.baseMipLevel = 0; swapchain_begin_barrier.subresourceRange.levelCount = 1; @@ -342,7 +347,7 @@ void OpenXRHeadset::submit_frame(VkCommandBuffer command_buffer, VkImageLayout f image_barriers.push_back(swapchain_begin_barrier); - vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, image_barriers.size(), image_barriers.data()); + vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, image_barriers.size(), image_barriers.data()); VkImageCopy copy_region; copy_region.srcSubresource = frame_image->get_subresource_layers(), @@ -362,8 +367,9 @@ void OpenXRHeadset::submit_frame(VkCommandBuffer command_buffer, VkImageLayout f vkCmdCopyImage(command_buffer, frame_image->get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, swapchain_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©_region); - VkImageMemoryBarrier swapchain_end_barrier = lava::image_memory_barrier(swapchain_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - swapchain_end_barrier.srcAccessMask = 0; + //NOTE: For some reason the image layout has to be VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL even though the OpenXR specification says that it has to be VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL + VkImageMemoryBarrier swapchain_end_barrier = lava::image_memory_barrier(swapchain_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + swapchain_end_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; swapchain_end_barrier.dstAccessMask = 0; swapchain_end_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; swapchain_end_barrier.subresourceRange.baseMipLevel = 0; @@ -371,7 +377,7 @@ void OpenXRHeadset::submit_frame(VkCommandBuffer command_buffer, VkImageLayout f swapchain_end_barrier.subresourceRange.baseArrayLayer = 0; swapchain_end_barrier.subresourceRange.layerCount = 1; - vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 1, &swapchain_end_barrier); + vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 1, &swapchain_end_barrier); this->release_image(frame_id); @@ -471,12 +477,18 @@ void OpenXRHeadset::destroy_framebuffers() { for (lava::image::ptr& framebuffer : this->framebuffers) { - framebuffer->destroy(true); - framebuffer = nullptr; + if (framebuffer != nullptr) + { + framebuffer->destroy(true); + framebuffer = nullptr; + } } - this->framebuffer_array->destroy(); - this->framebuffer_array = nullptr; + if (this->framebuffer_array != nullptr) + { + this->framebuffer_array->destroy(); + this->framebuffer_array = nullptr; + } } bool OpenXRHeadset::create_swapchains() diff --git a/src/headset/openxr_headset.hpp b/src/headset/openxr_headset.hpp index f0adbde8cbcd03eacfb17d487a15ac8b81816f3f..659a4cf40c852411cc68871fc6ebbfa2a570736b 100644 --- a/src/headset/openxr_headset.hpp +++ b/src/headset/openxr_headset.hpp @@ -22,6 +22,7 @@ public: bool on_create() override; void on_destroy() override; + void on_shutdown() override; bool on_interface() override; bool on_update(lava::delta delta_time) override; diff --git a/src/headset/remote_headset.cpp b/src/headset/remote_headset.cpp index 00c9c0059dcffcc70253fbfe1f9e594de696c385..addc043455fc44affb5ce8afa8207e6e467076f9 100644 --- a/src/headset/remote_headset.cpp +++ b/src/headset/remote_headset.cpp @@ -364,8 +364,11 @@ void RemoteHeadset::destroy_framebuffers() this->framebuffers.clear(); - this->framebuffer_array->destroy(); - this->framebuffer_array = nullptr; + if (this->framebuffer_array != nullptr) + { + this->framebuffer_array->destroy(); + this->framebuffer_array = nullptr; + } } bool RemoteHeadset::create_encoders() diff --git a/src/vr_application.cpp b/src/vr_application.cpp index f719dc9be530dc91a264bc5f0e74b8d970219666..f2b841fd45affc2a8b5be04cfd4dc577c2c84fc3 100644 --- a/src/vr_application.cpp +++ b/src/vr_application.cpp @@ -456,6 +456,11 @@ void VRApplication::on_destroy() { this->destroy_config(); + if (this->headset != nullptr) + { + this->headset->on_shutdown(); + } + if (this->pass_timer != nullptr) { this->pass_timer->write_to_file(this->app->device);