32 ghost_context_ = ghost_context;
44 if (surface_texture_) {
48 surface_texture_ =
nullptr;
56 this->process_frame_timings();
62 GHOST_VulkanSwapChainData swap_chain_data = {};
63 GHOST_GetVulkanSwapChainFormat((GHOST_WindowHandle)
ghost_window_, &swap_chain_data);
65 const bool reset_framebuffer = swap_chain_format_.format !=
66 swap_chain_data.surface_format.format ||
67 swap_chain_format_.colorSpace !=
68 swap_chain_data.surface_format.colorSpace ||
69 vk_extent_.width != swap_chain_data.extent.width ||
70 vk_extent_.height != swap_chain_data.extent.height;
71 if (reset_framebuffer) {
75 if (surface_texture_) {
77 surface_texture_ =
nullptr;
79 vk_extent_ = swap_chain_data.extent;
80 vk_extent_.width =
max_uu(vk_extent_.width, 1u);
81 vk_extent_.height =
max_uu(vk_extent_.height, 1u);
98 swap_chain_format_ = swap_chain_data.surface_format;
99 GCaps.hdr_viewport_support = (swap_chain_format_.format == VK_FORMAT_R16G16B16A16_SFLOAT) &&
100 ELEM(swap_chain_format_.colorSpace,
101 VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT,
102 VK_COLOR_SPACE_SRGB_NONLINEAR_KHR);
114 thread_data_ = std::reference_wrapper<VKThreadData>(thread_data);
116 if (!render_graph_.has_value()) {
117 render_graph_ = std::reference_wrapper<render_graph::VKRenderGraph>(
123 std::string str_group = group;
124 render_graph_.value().get().debug_group_begin(str_group.c_str(),
140 thread_data_.reset();
149 this->process_frame_timings();
158 VkPipelineStageFlags wait_dst_stage_mask,
159 VkSemaphore wait_semaphore,
160 VkSemaphore signal_semaphore,
161 VkFence signal_fence)
172 &render_graph_.value().get(),
180 render_graph_.reset();
181 streaming_buffers_.clear();
183 render_graph_ = std::reference_wrapper<render_graph::VKRenderGraph>(
189 std::string str_group = group;
190 render_graph_.value().get().debug_group_begin(str_group.c_str(),
211 return thread_data_.value().get().descriptor_pools;
216 return thread_data_.value().get().descriptor_set;
301 const bool is_line_primitive =
ELEM(primitive,
308 if (is_line_primitive) {
310 r_pipeline_data.
line_width = supports_wide_lines ?
332 VkPipeline vk_pipeline,
354 descriptor_set.update_descriptor_set(*
this, access_info_, r_pipeline_data);
360 access_info_.
reset();
374 context->swap_buffer_acquired_handler();
381 context->swap_buffer_draw_handler(*swap_chain_data);
384void VKContext::swap_buffer_acquired_handler()
389void VKContext::swap_buffer_draw_handler(
const GHOST_VulkanSwapChainData &swap_chain_data)
391 const bool do_blit_to_swapchain = swap_chain_data.image != VK_NULL_HANDLE;
392 const bool use_shader = swap_chain_data.surface_format.colorSpace ==
393 VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT;
396 if (!do_blit_to_swapchain) {
404 framebuffer.rendering_end(*
this);
405 VKTexture *color_attachment =
unwrap(
unwrap(framebuffer.color_tex(0)));
406 device.resources.add_swapchain_image(swap_chain_data.image,
"SwapchainImage");
410 VKTexture swap_chain_texture(
"swap_chain_texture");
411 swap_chain_texture.init_swapchain(swap_chain_data.image,
420 int2(swap_chain_data.extent.width, swap_chain_data.extent.height),
int2(16));
425 blit_image.
src_image = color_attachment->vk_image_handle();
426 blit_image.dst_image = swap_chain_data.image;
427 blit_image.filter = VK_FILTER_LINEAR;
429 VkImageBlit ®ion = blit_image.region;
430 region.srcOffsets[0] = {0, 0, 0};
431 region.srcOffsets[1] = {color_attachment->width_get(), color_attachment->height_get(), 1};
432 region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
433 region.srcSubresource.mipLevel = 0;
434 region.srcSubresource.baseArrayLayer = 0;
435 region.srcSubresource.layerCount = 1;
437 region.dstOffsets[0] = {0,
int32_t(swap_chain_data.extent.height), 0};
438 region.dstOffsets[1] = {
int32_t(swap_chain_data.extent.width), 0, 1};
439 region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
440 region.dstSubresource.mipLevel = 0;
441 region.dstSubresource.baseArrayLayer = 0;
442 region.dstSubresource.layerCount = 1;
448 synchronization.
vk_image = swap_chain_data.image;
449 synchronization.vk_image_layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
450 synchronization.vk_image_aspect = VK_IMAGE_ASPECT_COLOR_BIT;
455 VK_PIPELINE_STAGE_TRANSFER_BIT,
456 swap_chain_data.acquire_semaphore,
457 swap_chain_data.present_semaphore,
458 swap_chain_data.submission_fence);
460 device.resources.remove_image(swap_chain_data.image);
462 device.debug_print();
469 constants_state_ = (constants_state !=
nullptr) ? *constants_state :
474 VKBuffer &buffer, VkDeviceSize min_offset_alignment)
476 for (std::unique_ptr<VKStreamingBuffer> &streaming_buffer : streaming_buffers_) {
477 if (streaming_buffer->vk_buffer_dst() == buffer.
vk_handle()) {
478 return streaming_buffer;
482 streaming_buffers_.append(std::make_unique<VKStreamingBuffer>(buffer, min_offset_alignment));
483 return streaming_buffers_.last();
496 context->openxr_acquire_framebuffer_image_handler(*openxr_data);
503 context->openxr_release_framebuffer_image_handler(*openxr_data);
506void VKContext::openxr_acquire_framebuffer_image_handler(GHOST_VulkanOpenXRData &openxr_data)
510 openxr_data.extent.width = color_attachment->
width_get();
511 openxr_data.extent.height = color_attachment->
height_get();
516 if (
ELEM(device_format, TextureFormat::UNORM_8_8_8_8)) {
520 switch (openxr_data.data_transfer_mode) {
521 case GHOST_kVulkanXRModeCPU:
522 openxr_data.cpu.image_data = color_attachment->
read(0, data_format);
525 case GHOST_kVulkanXRModeFD: {
529 if (openxr_data.gpu.vk_image_blender != color_attachment->
vk_image_handle()) {
530 VKMemoryExport exported_memory = color_attachment->
export_memory(
531 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT);
532 openxr_data.gpu.image_handle = exported_memory.
handle;
533 openxr_data.gpu.new_handle =
true;
535 openxr_data.gpu.memory_size = exported_memory.memory_size;
536 openxr_data.gpu.memory_offset = exported_memory.memory_offset;
537 openxr_data.gpu.vk_image_blender = color_attachment->
vk_image_handle();
542 case GHOST_kVulkanXRModeWin32: {
546 if (openxr_data.gpu.vk_image_blender != color_attachment->
vk_image_handle()) {
547 VKMemoryExport exported_memory = color_attachment->
export_memory(
548 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT);
549 openxr_data.gpu.image_handle = exported_memory.
handle;
550 openxr_data.gpu.new_handle =
true;
552 openxr_data.gpu.memory_size = exported_memory.memory_size;
553 openxr_data.gpu.memory_offset = exported_memory.memory_offset;
554 openxr_data.gpu.vk_image_blender = color_attachment->
vk_image_handle();
561void VKContext::openxr_release_framebuffer_image_handler(GHOST_VulkanOpenXRData &openxr_data)
563 switch (openxr_data.data_transfer_mode) {
564 case GHOST_kVulkanXRModeCPU:
566 openxr_data.cpu.image_data =
nullptr;
569 case GHOST_kVulkanXRModeFD:
576 case GHOST_kVulkanXRModeWin32:
578 if (openxr_data.gpu.new_handle) {
580 CloseHandle(HANDLE(openxr_data.gpu.image_handle));
581 openxr_data.gpu.image_handle = 0;
MINLINE uint max_uu(uint a, uint b)
GHOST C-API function and type declarations.
void GPU_debug_group_end()
void GPU_debug_group_begin(const char *name)
#define GPU_ATTACHMENT_TEXTURE(_texture)
@ GPU_PRIM_LINE_STRIP_ADJ
void GPU_shader_uniform_1f(blender::gpu::Shader *sh, const char *name, float value)
void GPU_shader_bind(blender::gpu::Shader *shader, const blender::gpu::shader::SpecializationConstants *constants_state=nullptr)
@ GPU_TEXTURE_USAGE_SHADER_READ
@ GPU_TEXTURE_USAGE_ATTACHMENT
blender::gpu::Texture * GPU_texture_create_2d(const char *name, int width, int height, int mip_len, blender::gpu::TextureFormat format, eGPUTextureUsage usage, const float *data)
void GPU_texture_free(blender::gpu::Texture *texture)
StateManager * state_manager
blender::gpu::Texture * color_tex(int slot) const
GPUStateMutable mutable_state
virtual void image_bind(Texture *tex, int unit)=0
void compute_dispatch(int groups_x_len, int groups_y_len, int groups_z_len) override
VkBuffer vk_handle() const
void debug_unbind_all_ssbo() override
render_graph::VKResourceAccessInfo & reset_and_get_access_info()
static void openxr_acquire_framebuffer_image_callback(GHOST_VulkanOpenXRData *data)
void deactivate_framebuffer()
void specialization_constants_set(const shader::SpecializationConstants *constants_state)
void deactivate() override
void memory_statistics_get(int *r_total_mem_kb, int *r_free_mem_kb) override
VKContext(void *ghost_window, void *ghost_context)
VKDiscardPool discard_pool
static void swap_buffer_acquired_callback()
static void openxr_release_framebuffer_image_callback(GHOST_VulkanOpenXRData *data)
static void swap_buffer_draw_callback(const GHOST_VulkanSwapChainData *data)
VKFrameBuffer * active_framebuffer_get() const
const render_graph::VKRenderGraph & render_graph() const
bool has_active_framebuffer() const
void debug_unbind_all_ubo() override
void activate_framebuffer(VKFrameBuffer &framebuffer)
VKStateManager & state_manager_get() const
VKDescriptorSetTracker & descriptor_set_get()
std::unique_ptr< VKStreamingBuffer > & get_or_create_streaming_buffer(VKBuffer &buffer, VkDeviceSize min_offset_alignment)
void update_pipeline_data(render_graph::VKPipelineData &r_pipeline_data)
void begin_frame() override
VKDescriptorPools & descriptor_pools_get()
void end_frame() override
TimelineValue flush_render_graph(RenderGraphFlushFlags flags, VkPipelineStageFlags wait_dst_stage_mask=VK_PIPELINE_STAGE_NONE, VkSemaphore wait_semaphore=VK_NULL_HANDLE, VkSemaphore signal_semaphore=VK_NULL_HANDLE, VkFence signal_fence=VK_NULL_HANDLE)
void upload_descriptor_sets()
const VKExtensions & extensions_get() const
render_graph::VKRenderGraph * render_graph_new()
VKThreadData & current_thread_data()
TimelineValue render_graph_submit(render_graph::VKRenderGraph *render_graph, VKDiscardPool &context_discard_pool, bool submit_to_device, bool wait_for_completion, VkPipelineStageFlags wait_dst_stage_mask, VkSemaphore wait_semaphore, VkSemaphore signal_semaphore, VkFence signal_fence)
void context_unregister(VKContext &context)
void memory_statistics_get(int *r_total_mem_kb, int *r_free_mem_kb) const
bool is_rendering() const
void rendering_end(VKContext &context)
const void * data() const
const VKPushConstants::Layout & push_constants_layout_get() const
VkPipeline ensure_and_get_graphics_pipeline(GPUPrimType primitive, VKVertexAttributeObject &vao, VKStateManager &state_manager, VKFrameBuffer &framebuffer, shader::SpecializationConstants &constants_state)
VkPipeline ensure_and_get_compute_pipeline(const shader::SpecializationConstants &constants_state)
VKPushConstants push_constants
bool has_descriptor_set() const
VkPipelineLayout vk_pipeline_layout
const VKShaderInterface & interface_get() const
void storage_buffer_unbind_all()
void uniform_buffer_unbind_all()
VKMemoryExport export_memory(VkExternalMemoryHandleTypeFlagBits handle_type)
TextureFormat device_format_get() const
VkImage vk_image_handle() const
void * read(int mip, eGPUDataFormat format) override
VKBlitImageData CreateInfo
@ GPU_FB_COLOR_ATTACHMENT0
void MEM_freeN(void *vmemh)
static ColorTheme4f get_debug_group_color(StringRefNull name)
static Context * unwrap(GPUContext *ctx)
VkFormat to_vk_format(const TextureFormat format)
TextureFormat to_gpu_format(const VkFormat format)
VecBase< T, Size > divide_ceil(const VecBase< T, Size > &a, const VecBase< T, Size > &b)
VecBase< int32_t, 2 > int2
uint32_t size_in_bytes() const
StorageType storage_type_get() const
VKPipelineData pipeline_data
std::optional< float > line_width
VkDeviceAddress descriptor_buffer_device_address
const void * push_constants_data
VkDeviceSize descriptor_buffer_offset
VkPipelineLayout vk_pipeline_layout
VkDescriptorSet vk_descriptor_set
uint32_t push_constants_size