Files
test/source/blender/gpu/vulkan/vk_context.cc
Jeroen Bakker aa69ec7f80 Vulkan: Clearing Framebuffer + Scissors
This PR adds support for clearing framebuffers and scissor testing.
Tweaks had to be made to VKTexture to keep track of its layout
on the device. Based on the actual call the layout can switch
to a more optimum layout.

For example during upload of a texture the texture will be converted
to a transfer destination optimized layout. When reading from the
texture it will be converted to a transfer source optimized layout.

The order of the attachments in the framebuffer follows the next rules

- When only color attachments are there the color attachments will
  be placed in the slot they are defined. This way it will match
  the ShaderCreateInfo binding location.
- When a stencil/depth attachment is added it will be placed
  right after the color attachments. When there isn't a color
  attachment it will be the first attachment.

Pull Request: https://projects.blender.org/blender/blender/pulls/106044
2023-03-28 11:51:32 +02:00

156 lines
3.9 KiB
C++

/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2022 Blender Foundation. All rights reserved. */
/** \file
* \ingroup gpu
*/
#include "vk_context.hh"
#include "vk_backend.hh"
#include "vk_framebuffer.hh"
#include "vk_memory.hh"
#include "vk_state_manager.hh"
#include "GHOST_C-api.h"
namespace blender::gpu {
VKContext::VKContext(void *ghost_window, void *ghost_context)
{
VK_ALLOCATION_CALLBACKS;
ghost_window_ = ghost_window;
if (ghost_window) {
ghost_context = GHOST_GetDrawingContext((GHOST_WindowHandle)ghost_window);
}
ghost_context_ = ghost_context;
GHOST_GetVulkanHandles((GHOST_ContextHandle)ghost_context,
&vk_instance_,
&vk_physical_device_,
&vk_device_,
&vk_queue_family_,
&vk_queue_);
init_physical_device_limits();
/* Initialize the memory allocator. */
VmaAllocatorCreateInfo info = {};
/* Should use same vulkan version as GHOST (1.2), but set to 1.0 as 1.2 requires
* correct extensions and functions to be found by VMA, which isn't working as expected and
* requires more research. To continue development we lower the API to version 1.0. */
info.vulkanApiVersion = VK_API_VERSION_1_0;
info.physicalDevice = vk_physical_device_;
info.device = vk_device_;
info.instance = vk_instance_;
info.pAllocationCallbacks = vk_allocation_callbacks;
vmaCreateAllocator(&info, &mem_allocator_);
descriptor_pools_.init(vk_device_);
state_manager = new VKStateManager();
VKBackend::capabilities_init(*this);
/* For off-screen contexts. Default frame-buffer is empty. */
back_left = new VKFrameBuffer("back_left");
}
VKContext::~VKContext()
{
vmaDestroyAllocator(mem_allocator_);
}
void VKContext::init_physical_device_limits()
{
BLI_assert(vk_physical_device_ != VK_NULL_HANDLE);
VkPhysicalDeviceProperties properties = {};
vkGetPhysicalDeviceProperties(vk_physical_device_, &properties);
vk_physical_device_limits_ = properties.limits;
}
void VKContext::activate()
{
if (ghost_window_) {
VkImage image; /* TODO will be used for reading later... */
VkFramebuffer vk_framebuffer;
VkRenderPass render_pass;
VkExtent2D extent;
uint32_t fb_id;
GHOST_GetVulkanBackbuffer(
(GHOST_WindowHandle)ghost_window_, &image, &vk_framebuffer, &render_pass, &extent, &fb_id);
/* Recreate the gpu::VKFrameBuffer wrapper after every swap. */
if (has_active_framebuffer()) {
deactivate_framebuffer();
}
delete back_left;
VKFrameBuffer *framebuffer = new VKFrameBuffer(
"back_left", vk_framebuffer, render_pass, extent);
back_left = framebuffer;
framebuffer->bind(false);
}
}
void VKContext::deactivate()
{
}
void VKContext::begin_frame()
{
VkCommandBuffer command_buffer = VK_NULL_HANDLE;
GHOST_GetVulkanCommandBuffer(static_cast<GHOST_ContextHandle>(ghost_context_), &command_buffer);
command_buffer_.init(vk_device_, vk_queue_, command_buffer);
command_buffer_.begin_recording();
descriptor_pools_.reset();
}
void VKContext::end_frame()
{
command_buffer_.end_recording();
}
void VKContext::flush()
{
command_buffer_.submit();
}
void VKContext::finish()
{
if (has_active_framebuffer()) {
deactivate_framebuffer();
}
command_buffer_.submit();
}
void VKContext::memory_statistics_get(int * /*total_mem*/, int * /*free_mem*/)
{
}
void VKContext::activate_framebuffer(VKFrameBuffer &framebuffer)
{
if (has_active_framebuffer()) {
deactivate_framebuffer();
}
BLI_assert(active_fb == nullptr);
active_fb = &framebuffer;
command_buffer_.begin_render_pass(framebuffer);
}
bool VKContext::has_active_framebuffer() const
{
return active_fb != nullptr;
}
void VKContext::deactivate_framebuffer()
{
BLI_assert(active_fb != nullptr);
VKFrameBuffer *framebuffer = unwrap(active_fb);
command_buffer_.end_render_pass(*framebuffer);
active_fb = nullptr;
}
} // namespace blender::gpu