1
1
This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/intern/ghost/intern/GHOST_ContextVK.h
Jeroen Bakker 7fb1f060ff Vulkan: Initial Compute Shaders support
This patch adds initial support for compute shaders to
the vulkan backend. As the development is oriented to the test-
cases we have the implementation is limited to what is used there.

It has been validated that with this patch that the following test
cases are running as expected
- `GPUVulkanTest.gpu_shader_compute_vbo`
- `GPUVulkanTest.gpu_shader_compute_ibo`
- `GPUVulkanTest.gpu_shader_compute_ssbo`
- `GPUVulkanTest.gpu_storage_buffer_create_update_read`
- `GPUVulkanTest.gpu_shader_compute_2d`

This patch includes:
- Allocating VkBuffer on device.
- Uploading data from CPU to VkBuffer.
- Binding VkBuffer as SSBO to a compute shader.
- Execute compute shader and altering VkBuffer.
- Download the VkBuffer to CPU ram.
- Validate that it worked.
- Use device only vertex buffer as SSBO
- Use device only index buffer as SSBO
- Use device only image buffers

GHOST API has been changed as the original design was created before
we even had support for compute shaders in blender. The function
`GHOST_getVulkanBackbuffer` has been separated to retrieve the command
buffer without a backbuffer (`GHOST_getVulkanCommandBuffer`). In order
to do correct command buffer processing we needed access to the queue
owned by GHOST. This is returned as part of the `GHOST_getVulkanHandles`
function.

Open topics (not considered part of this patch)
- Memory barriers & command buffer encoding
- Indirect compute dispatching
- Rest of the test cases
- Data conversions when requested data format is different than on device.
- GPUVulkanTest.gpu_shader_compute_1d is supported on AMD devices.
  NVIDIA doesn't seem to support 1d textures.

Pull-request: #104518
2023-02-21 15:04:52 +01:00

207 lines
5.7 KiB
C++

/* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup GHOST
*/
#pragma once
#include "GHOST_Context.h"
#ifdef _WIN32
# include "GHOST_SystemWin32.h"
#elif defined(__APPLE__)
# include "GHOST_SystemCocoa.h"
#else
# include "GHOST_SystemX11.h"
# ifdef WITH_GHOST_WAYLAND
# include "GHOST_SystemWayland.h"
# else
# define wl_surface void
# define wl_display void
# endif
#endif
#include <vector>
#ifdef __APPLE__
# include <MoltenVK/vk_mvk_moltenvk.h>
#else
# include <vulkan/vulkan.h>
#endif
#ifndef GHOST_OPENGL_VK_CONTEXT_FLAGS
/* leave as convenience define for the future */
# define GHOST_OPENGL_VK_CONTEXT_FLAGS 0
#endif
#ifndef GHOST_OPENGL_VK_RESET_NOTIFICATION_STRATEGY
# define GHOST_OPENGL_VK_RESET_NOTIFICATION_STRATEGY 0
#endif
typedef enum {
GHOST_kVulkanPlatformX11 = 0,
#ifdef WITH_GHOST_WAYLAND
GHOST_kVulkanPlatformWayland,
#endif
} GHOST_TVulkanPlatformType;
class GHOST_ContextVK : public GHOST_Context {
public:
/**
* Constructor.
*/
GHOST_ContextVK(bool stereoVisual,
#ifdef _WIN32
HWND hwnd,
#elif defined(__APPLE__)
/* FIXME CAMetalLayer but have issue with linking. */
void *metal_layer,
#else
GHOST_TVulkanPlatformType platform,
/* X11 */
Window window,
Display *display,
/* Wayland */
wl_surface *wayland_surface,
wl_display *wayland_display,
#endif
int contextMajorVersion,
int contextMinorVersion,
int m_debug);
/**
* Destructor.
*/
~GHOST_ContextVK();
/**
* Swaps front and back buffers of a window.
* \return A boolean success indicator.
*/
GHOST_TSuccess swapBuffers();
/**
* Activates the drawing context of this window.
* \return A boolean success indicator.
*/
GHOST_TSuccess activateDrawingContext();
/**
* Release the drawing context of the calling thread.
* \return A boolean success indicator.
*/
GHOST_TSuccess releaseDrawingContext();
/**
* Call immediately after new to initialize. If this fails then immediately delete the object.
* \return Indication as to whether initialization has succeeded.
*/
GHOST_TSuccess initializeDrawingContext();
/**
* Removes references to native handles from this context and then returns
* \return GHOST_kSuccess if it is OK for the parent to release the handles and
* GHOST_kFailure if releasing the handles will interfere with sharing
*/
GHOST_TSuccess releaseNativeHandles();
/**
* Gets the Vulkan context related resource handles.
* \return A boolean success indicator.
*/
GHOST_TSuccess getVulkanHandles(void *r_instance,
void *r_physical_device,
void *r_device,
uint32_t *r_graphic_queue_family,
void *r_queue);
GHOST_TSuccess getVulkanCommandBuffer(void *r_command_buffer);
/**
* Gets the Vulkan framebuffer related resource handles associated with the Vulkan context.
* Needs to be called after each swap events as the framebuffer will change.
* \return A boolean success indicator.
*/
GHOST_TSuccess getVulkanBackbuffer(
void *image, void *framebuffer, void *render_pass, void *extent, uint32_t *fb_id);
/**
* Sets the swap interval for swapBuffers.
* \param interval The swap interval to use.
* \return A boolean success indicator.
*/
GHOST_TSuccess setSwapInterval(int /* interval */)
{
return GHOST_kFailure;
}
/**
* Gets the current swap interval for swapBuffers.
* \param intervalOut Variable to store the swap interval if it can be read.
* \return Whether the swap interval can be read.
*/
GHOST_TSuccess getSwapInterval(int &)
{
return GHOST_kFailure;
};
private:
#ifdef _WIN32
HWND m_hwnd;
#elif defined(__APPLE__)
CAMetalLayer *m_metal_layer;
#else /* Linux */
GHOST_TVulkanPlatformType m_platform;
/* X11 */
Display *m_display;
Window m_window;
/* Wayland */
wl_surface *m_wayland_surface;
wl_display *m_wayland_display;
#endif
const int m_context_major_version;
const int m_context_minor_version;
const int m_debug;
VkInstance m_instance;
VkPhysicalDevice m_physical_device;
VkDevice m_device;
VkCommandPool m_command_pool;
uint32_t m_queue_family_graphic;
uint32_t m_queue_family_present;
VkQueue m_graphic_queue;
VkQueue m_present_queue;
/* For display only. */
VkSurfaceKHR m_surface;
VkSwapchainKHR m_swapchain;
std::vector<VkImage> m_swapchain_images;
std::vector<VkImageView> m_swapchain_image_views;
std::vector<VkFramebuffer> m_swapchain_framebuffers;
std::vector<VkCommandBuffer> m_command_buffers;
VkRenderPass m_render_pass;
VkExtent2D m_render_extent;
std::vector<VkSemaphore> m_image_available_semaphores;
std::vector<VkSemaphore> m_render_finished_semaphores;
std::vector<VkFence> m_in_flight_fences;
std::vector<VkFence> m_in_flight_images;
/** frame modulo swapchain_len. Used as index for sync objects. */
int m_currentFrame = 0;
/** Image index in the swapchain. Used as index for render objects. */
uint32_t m_currentImage = 0;
/** Used to unique framebuffer ids to return when swapchain is recreated. */
uint32_t m_swapchain_id = 0;
const char *getPlatformSpecificSurfaceExtension() const;
GHOST_TSuccess pickPhysicalDevice(std::vector<const char *> required_exts);
GHOST_TSuccess createSwapchain();
GHOST_TSuccess destroySwapchain();
GHOST_TSuccess createCommandPools();
GHOST_TSuccess createGraphicsCommandBuffers();
GHOST_TSuccess createGraphicsCommandBuffer();
GHOST_TSuccess recordCommandBuffers();
};