Toast Engine
Loading...
Searching...
No Matches
shared_texture_output_target.hpp
1
4
5#pragma once
6
7#include "output_target_base.hpp"
8
9#include <array>
10#include <atomic>
11#include <condition_variable>
12#include <memory>
13#include <mutex>
14#include <optional>
15#include <vector>
16
17namespace renderer {
18
19class VulkanCore;
20
22 uint32_t width = 0;
23 uint32_t height = 0;
24 uint32_t row_pitch = 0;
25 uint64_t frame_id = 0;
26};
27
29 uint32_t width = 0;
30 uint32_t height = 0;
31 uint64_t frame_id = 0;
32 uint64_t generation = 0;
33 uint64_t memory_size = 0;
34 uint32_t slot = 0;
35 uint32_t slot_count = 0;
36};
37
39 intptr_t image = 0;
40 intptr_t ready = 0;
41 intptr_t done = 0;
42};
43
44class SharedTextureOutputTarget final : public IOutputTarget {
45public:
46 SharedTextureOutputTarget(const VulkanCore& core, vk::Extent2D preferred_extent, uint32_t image_count = 3);
47 ~SharedTextureOutputTarget() override;
48
49 SharedTextureOutputTarget(const SharedTextureOutputTarget&) = delete;
50 auto operator=(const SharedTextureOutputTarget&) -> SharedTextureOutputTarget& = delete;
51 SharedTextureOutputTarget(SharedTextureOutputTarget&&) = delete;
52 auto operator=(SharedTextureOutputTarget&&) -> SharedTextureOutputTarget& = delete;
53
54 [[nodiscard]]
55 auto getExtent() const -> vk::Extent2D override {
56 return m_extent;
57 }
58
59 [[nodiscard]]
60 auto getColorFormat() const -> vk::Format override {
61 return m_color_format;
62 }
63
64 [[nodiscard]]
65 auto getImageCount() const -> uint32_t override {
66 return static_cast<uint32_t>(m_images.size());
67 }
68
69 [[nodiscard]]
70 auto getColorImage(uint32_t index) const -> const vk::Image& override;
71 [[nodiscard]]
72 auto getColorAttachment(uint32_t index) const -> const vk::raii::ImageView& override;
73 [[nodiscard]]
74 auto acquireNextImage(uint64_t timeout, vk::Semaphore image_available, vk::Fence in_flight_fence)
75 -> vk::ResultValue<uint32_t> override;
76 [[nodiscard]]
77 auto present(uint32_t image_index, vk::Semaphore render_finished) -> vk::Result override;
78
79 [[nodiscard]]
80 auto usesAcquirePresentSemaphores() const -> bool override {
81 return false;
82 }
83
84 void recordFinalize(vk::CommandBuffer command_buffer, uint32_t image_index) override;
85 void onImageRenderComplete(uint32_t image_index) override;
86 [[nodiscard]]
87 auto submitSync(uint32_t image_index) -> OutputSubmitSync override;
88
89 void recreate(vk::Extent2D extent) override;
90
92 [[nodiscard]]
93 auto copyLatestFrame(void* dst, uint32_t dst_capacity, ViewportFrameDesc* out) -> int;
94
96 void requestReadback();
97
104 auto enableSharedTextures(uint64_t adapter_luid, const uint8_t* adapter_uuid) -> bool;
105
106 void disableSharedTextures();
107
108 [[nodiscard]]
109 auto sharedFrame(ViewportSharedFrameDesc* out) -> int;
110
111 [[nodiscard]]
112 auto exportSharedSlot(uint64_t generation, uint32_t slot, ViewportSharedHandles* out) -> bool;
113
114 [[nodiscard]]
115 auto holdSharedSlot(uint64_t generation, uint32_t slot) -> bool;
116
117 void releaseSharedSlot(uint64_t generation, uint32_t slot, bool consumed);
118
119private:
120 struct SharedImage {
121 std::optional<vma::raii::Image> image;
122 std::optional<vk::raii::ImageView> view;
123 std::optional<vma::raii::Buffer> staging;
124 void* mapped = nullptr;
125 bool read_back = false;
126 bool shared = false;
127 };
128
129 struct Interop;
130
131 enum class SharingState : uint8_t {
132 off,
133 requested,
134 active,
135 failed,
136 };
137
138 void allocateResources(vk::Extent2D extent);
139 void createInterop();
140
141 [[nodiscard]]
142 auto imageByteSize() const -> vk::DeviceSize {
143 return static_cast<vk::DeviceSize>(m_extent.width) * m_extent.height * 4;
144 }
145
146 const VulkanCore* m_core = nullptr;
147 vk::Extent2D m_extent;
148 vk::Format m_color_format = vk::Format::eB8G8R8A8Unorm;
149
150 std::mutex m_frame_mutex;
151 std::vector<SharedImage> m_images;
152 uint32_t m_next_acquire_index = 0;
153
154 std::atomic<int32_t> m_latest_ready {-1};
155 std::atomic<int32_t> m_latest_readback {-1};
156 int32_t m_reading = -1;
157 std::condition_variable m_reading_done;
158 std::atomic<uint64_t> m_frame_counter {0};
159 std::unique_ptr<Interop> m_interop;
160 std::atomic<SharingState> m_sharing {SharingState::off};
161 std::atomic<bool> m_readback_requested {false};
162};
163
164}
Definition output_target_base.hpp:20
auto enableSharedTextures(uint64_t adapter_luid, const uint8_t *adapter_uuid) -> bool
Hands frames over as shared textures from the next acquired image on, and stops reading every frame b...
Definition shared_texture_output_target.cpp:548
void requestReadback()
Reads the next frame back to the CPU even while textures are shared.
Definition shared_texture_output_target.cpp:536
auto copyLatestFrame(void *dst, uint32_t dst_capacity, ViewportFrameDesc *out) -> int
Definition shared_texture_output_target.cpp:500
Definition vulkan_core.hpp:48
Definition output_target_base.hpp:13
Definition shared_texture_output_target.cpp:76
Definition shared_texture_output_target.hpp:21
Definition shared_texture_output_target.hpp:28
Definition shared_texture_output_target.hpp:38