Blender V4.3
vk_context.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2022 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8#include "vk_context.hh"
9#include "vk_debug.hh"
10
11#include "vk_backend.hh"
12#include "vk_framebuffer.hh"
13#include "vk_immediate.hh"
14#include "vk_memory.hh"
15#include "vk_shader.hh"
17#include "vk_state_manager.hh"
18#include "vk_texture.hh"
19
20#include "GHOST_C-api.h"
21
22namespace blender::gpu {
23
24VKContext::VKContext(void *ghost_window,
25 void *ghost_context,
27 : render_graph(std::make_unique<render_graph::VKCommandBufferWrapper>(), resources)
28{
29 ghost_window_ = ghost_window;
30 ghost_context_ = ghost_context;
31
33
34 back_left = new VKFrameBuffer("back_left");
35 front_left = new VKFrameBuffer("front_left");
37
39}
40
42{
43 if (surface_texture_) {
46 GPU_texture_free(surface_texture_);
47 surface_texture_ = nullptr;
48 }
50
51 imm = nullptr;
52 compiler = nullptr;
53}
54
56{
57 VKDevice &device = VKBackend::get().device;
58 if (ghost_window_) {
59 GHOST_VulkanSwapChainData swap_chain_data = {};
60 GHOST_GetVulkanSwapChainFormat((GHOST_WindowHandle)ghost_window_, &swap_chain_data);
61 VKThreadData &thread_data = thread_data_.value().get();
62 if (assign_if_different(thread_data.resource_pool_index, swap_chain_data.swap_chain_index)) {
63 VKResourcePool &resource_pool = thread_data.resource_pool_get();
64 imm = &resource_pool.immediate;
65 resource_pool.discard_pool.destroy_discarded_resources(device);
66 resource_pool.reset();
67 resource_pool.discard_pool.move_data(device.orphaned_data);
68 }
69
70 const bool reset_framebuffer = swap_chain_format_ != swap_chain_data.format ||
71 vk_extent_.width != swap_chain_data.extent.width ||
72 vk_extent_.height != swap_chain_data.extent.height;
73 if (reset_framebuffer) {
76 }
77 if (surface_texture_) {
78 GPU_texture_free(surface_texture_);
79 surface_texture_ = nullptr;
80 }
81 surface_texture_ = GPU_texture_create_2d("back-left",
82 swap_chain_data.extent.width,
83 swap_chain_data.extent.height,
84 1,
85 to_gpu_format(swap_chain_data.format),
87 nullptr);
88
90 GPU_ATTACHMENT_TEXTURE(surface_texture_));
92 GPU_ATTACHMENT_TEXTURE(surface_texture_));
93
94 back_left->bind(false);
95
96 swap_chain_format_ = swap_chain_data.format;
97 vk_extent_ = swap_chain_data.extent;
98 }
99 }
100#if 0
101 else (is_background) {
102 discard all orphaned data
103 }
104#endif
105}
106
108{
109 /* Make sure no other context is already bound to this thread. */
110 BLI_assert(is_active_ == false);
111
112 VKDevice &device = VKBackend::get().device;
113 VKThreadData &thread_data = device.current_thread_data();
114 thread_data_ = std::reference_wrapper<VKThreadData>(thread_data);
115
116 imm = &thread_data.resource_pool_get().immediate;
117
118 is_active_ = true;
119
121
122 immActivate();
123}
124
126{
129 imm = nullptr;
130 thread_data_.reset();
131 is_active_ = false;
132}
133
135
137
139
141{
143 VKFrameBuffer &framebuffer = *active_framebuffer_get();
144 if (framebuffer.is_rendering()) {
145 framebuffer.rendering_end(*this);
146 }
147 }
150}
151
153
154void VKContext::memory_statistics_get(int *r_total_mem_kb, int *r_free_mem_kb)
155{
156 const VKDevice &device = VKBackend::get().device;
157 device.memory_statistics_get(r_total_mem_kb, r_free_mem_kb);
158}
159
160/* -------------------------------------------------------------------- */
165{
166 return thread_data_.value().get().resource_pool_get().descriptor_pools;
167}
168
170{
171 return thread_data_.value().get().resource_pool_get().descriptor_set;
172}
173
175{
176 return *static_cast<VKStateManager *>(state_manager);
177}
178
183
188
191/* -------------------------------------------------------------------- */
196{
199 }
200
201 BLI_assert(active_fb == nullptr);
202 active_fb = &framebuffer;
203 framebuffer.update_size();
204 framebuffer.update_srgb();
205 framebuffer.rendering_reset();
206}
207
212
214{
215 return active_framebuffer_get() != nullptr;
216}
217
219{
220 VKFrameBuffer *framebuffer = active_framebuffer_get();
221 BLI_assert(framebuffer != nullptr);
222 if (framebuffer->is_rendering()) {
223 framebuffer->rendering_end(*this);
224 }
225 active_fb = nullptr;
226}
227
229{
230 VKFrameBuffer *framebuffer = active_framebuffer_get();
231 if (framebuffer) {
232 framebuffer->rendering_end(*this);
233 }
234}
235
238/* -------------------------------------------------------------------- */
244 render_graph::VKPipelineData &r_pipeline_data)
245{
246 VKShader &vk_shader = unwrap(*shader);
247 VKFrameBuffer &framebuffer = *active_framebuffer_get();
249 vk_shader,
250 vk_shader.ensure_and_get_graphics_pipeline(primitive, vao, state_manager_get(), framebuffer),
251 r_pipeline_data);
252}
253
255{
256 VKShader &vk_shader = unwrap(*shader);
257 update_pipeline_data(vk_shader, vk_shader.ensure_and_get_compute_pipeline(), r_pipeline_data);
258}
259
261 VkPipeline vk_pipeline,
262 render_graph::VKPipelineData &r_pipeline_data)
263{
264 r_pipeline_data.vk_pipeline_layout = vk_shader.vk_pipeline_layout;
265 r_pipeline_data.vk_pipeline = vk_pipeline;
266
267 /* Update push constants. */
268 r_pipeline_data.push_constants_data = nullptr;
269 r_pipeline_data.push_constants_size = 0;
270 const VKPushConstants::Layout &push_constants_layout =
272 if (push_constants_layout.storage_type_get() == VKPushConstants::StorageType::PUSH_CONSTANTS) {
273 r_pipeline_data.push_constants_size = push_constants_layout.size_in_bytes();
274 r_pipeline_data.push_constants_data = vk_shader.push_constants.data();
275 }
276
277 /* Update descriptor set. */
278 r_pipeline_data.vk_descriptor_set = VK_NULL_HANDLE;
279 if (vk_shader.has_descriptor_set()) {
280 VKDescriptorSetTracker &descriptor_set = descriptor_set_get();
281 descriptor_set.update_descriptor_set(*this, access_info_);
282 r_pipeline_data.vk_descriptor_set = descriptor_set.vk_descriptor_set;
283 }
284}
285
287{
288 access_info_.reset();
289 return access_info_;
290}
291
294/* -------------------------------------------------------------------- */
298void VKContext::swap_buffers_pre_callback(const GHOST_VulkanSwapChainData *swap_chain_data)
299{
300 VKContext *context = VKContext::get();
301 BLI_assert(context);
302 context->swap_buffers_pre_handler(*swap_chain_data);
303}
304
306{
307 VKContext *context = VKContext::get();
308 BLI_assert(context);
309 context->swap_buffers_post_handler();
310}
311
312void VKContext::swap_buffers_pre_handler(const GHOST_VulkanSwapChainData &swap_chain_data)
313{
314 VKFrameBuffer &framebuffer = *unwrap(back_left);
315 VKTexture *color_attachment = unwrap(unwrap(framebuffer.color_tex(0)));
316
318 blit_image.src_image = color_attachment->vk_image_handle();
319 blit_image.dst_image = swap_chain_data.image;
320 blit_image.filter = VK_FILTER_NEAREST;
321
322 VkImageBlit &region = blit_image.region;
323 region.srcOffsets[0] = {0, color_attachment->height_get() - 1, 0};
324 region.srcOffsets[1] = {color_attachment->width_get(), 0, 1};
325 region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
326 region.srcSubresource.mipLevel = 0;
327 region.srcSubresource.baseArrayLayer = 0;
328 region.srcSubresource.layerCount = 1;
329
330 region.dstOffsets[0] = {0, 0, 0};
331 region.dstOffsets[1] = {
332 int32_t(swap_chain_data.extent.width), int32_t(swap_chain_data.extent.height), 1};
333 region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
334 region.dstSubresource.mipLevel = 0;
335 region.dstSubresource.baseArrayLayer = 0;
336 region.dstSubresource.layerCount = 1;
337
338 /* Swap chain commands are CPU synchronized at this moment, allowing to temporary add the swap
339 * chain image as device resources. When we move towards GPU swap chain synchronization we need
340 * to keep track of the swap chain image between frames. */
341 VKDevice &device = VKBackend::get().device;
342 device.resources.add_image(swap_chain_data.image,
343 1,
344 VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
346 "SwapchainImage");
347
348 framebuffer.rendering_end(*this);
349 render_graph.add_node(blit_image);
351 render_graph.submit_for_present(swap_chain_data.image);
352
353 device.resources.remove_image(swap_chain_data.image);
354#if 0
355 device.debug_print();
356#endif
357}
358
359void VKContext::swap_buffers_post_handler()
360{
362}
363
366} // namespace blender::gpu
#define BLI_assert(a)
Definition BLI_assert.h:50
GHOST C-API function and type declarations.
#define GPU_ATTACHMENT_TEXTURE(_texture)
GPUPrimType
GPUTexture * GPU_texture_create_2d(const char *name, int width, int height, int mip_len, eGPUTextureFormat format, eGPUTextureUsage usage, const float *data)
void GPU_texture_free(GPUTexture *texture)
@ GPU_TEXTURE_USAGE_ATTACHMENT
void attachment_remove(GPUAttachmentType type)
virtual void bind(bool enabled_srgb)=0
GPUTexture * color_tex(int slot) const
void attachment_set(GPUAttachmentType type, const GPUAttachment &new_attachment)
VKShaderCompiler shader_compiler
Definition vk_backend.hh:34
static VKBackend & get()
Definition vk_backend.hh:92
void debug_unbind_all_ssbo() override
render_graph::VKResourceAccessInfo & reset_and_get_access_info()
void finish() override
render_graph::VKRenderGraph render_graph
Definition vk_context.hh:42
void deactivate() override
void memory_statistics_get(int *r_total_mem_kb, int *r_free_mem_kb) override
void flush() override
static void swap_buffers_post_callback()
VKFrameBuffer * active_framebuffer_get() const
void activate() override
bool has_active_framebuffer() const
void debug_unbind_all_ubo() override
static void swap_buffers_pre_callback(const GHOST_VulkanSwapChainData *data)
void activate_framebuffer(VKFrameBuffer &framebuffer)
VKStateManager & state_manager_get() const
VKDescriptorSetTracker & descriptor_set_get()
void update_pipeline_data(render_graph::VKPipelineData &r_pipeline_data)
static VKContext * get()
Definition vk_context.hh:97
VKContext(void *ghost_window, void *ghost_context, render_graph::VKResourceStateTracker &resources)
Definition vk_context.cc:24
void begin_frame() override
VKDescriptorPools & descriptor_pools_get()
void end_frame() override
render_graph::VKResourceStateTracker resources
Definition vk_device.hh:172
VKDiscardPool orphaned_data
Definition vk_device.hh:173
VKThreadData & current_thread_data()
Definition vk_device.cc:383
void context_unregister(VKContext &context)
Definition vk_device.cc:419
void memory_statistics_get(int *r_total_mem_kb, int *r_free_mem_kb) const
Definition vk_device.cc:428
void move_data(VKDiscardPool &src_pool)
void destroy_discarded_resources(VKDevice &device)
void rendering_end(VKContext &context)
const VKPushConstants::Layout & push_constants_layout_get() const
VKPushConstants push_constants
Definition vk_shader.hh:55
bool has_descriptor_set() const
Definition vk_shader.hh:123
VkPipelineLayout vk_pipeline_layout
Definition vk_shader.hh:54
VkPipeline ensure_and_get_compute_pipeline()
VkPipeline ensure_and_get_graphics_pipeline(GPUPrimType primitive, VKVertexAttributeObject &vao, VKStateManager &state_manager, VKFrameBuffer &framebuffer)
const VKShaderInterface & interface_get() const
VkImage vk_image_handle() const
Definition vk_texture.hh:99
VKResourcePool & resource_pool_get()
Definition vk_device.hh:105
void submit_for_present(VkImage vk_swapchain_image)
void add_image(VkImage vk_image, uint32_t layer_count, VkImageLayout vk_image_layout, ResourceOwner owner, const char *name=nullptr)
@ GPU_FB_COLOR_ATTACHMENT0
void immDeactivate()
void immActivate()
static Context * unwrap(GPUContext *ctx)
eGPUTextureFormat to_gpu_format(const VkFormat format)
Definition vk_common.cc:118
bool assign_if_different(T &old_value, T new_value)
signed int int32_t
Definition stdint.h:77