Project
Loading...
Searching...
No Matches
GPUDisplayBackendVulkan.h
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
14
15#ifndef GPUDISPLAYBACKENDVULKAN_H
16#define GPUDISPLAYBACKENDVULKAN_H
17
18#include "GPUDisplayBackend.h"
19#include <vulkan/vulkan.hpp>
20
21#include <vector>
22#include <unordered_map>
23#include <mutex>
24#include <utils/vecpod.h>
25
26namespace o2::gpu
27{
28
30{
31 public:
34
35 uint32_t DepthBits() override;
36
37 protected:
39 vk::SurfaceCapabilitiesKHR capabilities;
40 std::vector<vk::SurfaceFormatKHR> formats;
41 std::vector<vk::PresentModeKHR> presentModes;
42 };
43 struct VulkanBuffer {
44 vk::Buffer buffer;
45 vk::DeviceMemory memory;
46 size_t size = 0;
47 int32_t deviceMemory;
48 void* mapped = nullptr; // Persistent mapping of host-visible buffers (deviceMemory 0 / 2)
49 };
50 struct VulkanImage {
51 vk::Image image;
52 vk::ImageView view;
53 vk::DeviceMemory memory;
54 uint32_t sizex = 0, sizey = 0;
55 vk::Format format;
56 };
58 std::unique_ptr<char[]> data;
59 float x0, x1, y0, y1;
60 };
63 size_t nVertices;
64 float color[4];
65 };
66
67 uint32_t drawVertices(const vboList& v, const drawType t) override;
68 void ActivateColor(std::array<float, 4>& color) override;
69 void SetVSync(bool enable) override { mMustUpdateSwapChain = true; };
70 void setDepthBuffer() override {};
71 bool backendNeedRedraw() override;
72 int32_t InitBackendA() override;
73 void ExitBackendA() override;
74 void loadDataToGPU(size_t totalVertizes) override;
75 bool prepareDraw(const hmm_mat4& proj, const hmm_mat4& view, bool requestScreenshot, bool toMixBuffer, float includeMixImage) override;
76 void finishDraw(bool doScreenshot, bool toMixBuffer, float includeMixImage) override;
77 void finishFrame(bool doScreenshot, bool toMixBuffer, float includeMixImage) override;
78 void prepareText() override;
79 void finishText() override;
80 void mixImages(vk::CommandBuffer cmdBuffer, float mixSlaveImage);
81 void cmdPushDescriptors(vk::CommandBuffer commandBuffer, vk::PipelineLayout layout, const VulkanBuffer& ubo, vk::ImageView textureView = {}); // Push descriptors: UBO at binding 0, optional texture at binding 2
82 void pointSizeFactor(float factor) override;
83 void lineWidthFactor(float factor) override;
84 bool useNativeSmoothLines() const;
85 bool useSmoothLineShader() const;
86 bool canLimitToVSync() const override { return true; } // Present wait
87 void waitPresentFences();
88 void resizeScene(uint32_t width, uint32_t height) override;
89 float getYFactor() const override { return -1.0f; }
90 int32_t getMaxMSAA() const override { return mMaxMSAAsupported; }
91
92 using FeatureChain = vk::StructureChain<vk::PhysicalDeviceFeatures2, vk::PhysicalDeviceVulkan11Features, vk::PhysicalDeviceVulkan12Features, vk::PhysicalDeviceVulkan13Features, vk::PhysicalDeviceVulkan14Features, vk::PhysicalDeviceSwapchainMaintenance1FeaturesKHR, vk::PhysicalDevicePresentIdFeaturesKHR, vk::PhysicalDevicePresentWaitFeaturesKHR>;
93 double checkDevice(vk::PhysicalDevice device, const std::vector<const char*>& reqDeviceExtensions, const FeatureChain& reqDeviceFeatures, bool silent = false);
94 vk::Extent2D chooseSwapExtent(const vk::SurfaceCapabilitiesKHR& capabilities);
95 vk::PresentModeKHR chooseSwapPresentMode();
96 VulkanBuffer createBuffer(size_t size, const void* srcData = nullptr, vk::BufferUsageFlags type = vk::BufferUsageFlagBits::eVertexBuffer, int32_t deviceMemory = 1);
97 void writeToBuffer(VulkanBuffer& buffer, size_t size, const void* srcData);
99 VulkanImage createImage(uint32_t sizex, uint32_t sizey, const void* srcData = nullptr, size_t srcSize = 0, vk::Format format = vk::Format::eR8G8B8A8Srgb);
100 void writeToImage(VulkanImage& image, const void* srcData, size_t srcSize);
102 void clearVertexBuffers();
103
104 void startFillCommandBuffer(vk::CommandBuffer& commandBuffer, uint32_t imageIndex, bool toMixBuffer = false);
105 void endFillCommandBuffer(vk::CommandBuffer& commandBuffer);
106 vk::CommandBuffer getSingleTimeCommandBuffer();
107 void waitTimeline(uint64_t value);
108 template <class... Args>
109 uint64_t queueSubmit(uint64_t* timelineSignalValue, Args&&... args); // Submit under mQueueMutex; if timelineSignalValue (the entry in pSignalSemaphoreValues) is set, write the next timeline value there first. Returns the current timeline value
110 void submitSingleTimeCommandBuffer(vk::CommandBuffer commandBuffer);
111 void readImageToPixels(vk::Image image, vk::ImageView view, vk::ImageLayout layout, std::vector<char>& pixels);
112 void downsampleToFramebuffer(vk::CommandBuffer& commandBuffer);
113 void cmdDownsample(vk::CommandBuffer commandBuffer, vk::ImageView src, vk::ImageView dst, uint32_t width, uint32_t height, int32_t factor); // Exact box filter (fragmentDownsample.frag) for factors other than 2, src in eShaderReadOnlyOptimal, dst in eColorAttachmentOptimal
114
115 void updateSwapChainDetails(const vk::PhysicalDevice& device);
116 void createDevice();
117 void loadShaders();
120 void createSemaphores();
122 void createSwapChain(vk::SwapchainKHR oldSwapChain = {});
123 void createOffscreenBuffers(bool forScreenshot = false, bool forMixing = false);
124 void createPipeline();
125 void clearDevice();
126 void clearTextureSampler();
127 void clearCommandBuffers();
128 void clearSemaphores();
131 void clearSwapChain(bool keepSwapChain = false);
132 void clearPipeline();
133 void recreateRendering(bool forScreenshot = false, bool forMixing = false);
135
136 void addFontSymbol(int32_t symbol, int32_t sizex, int32_t sizey, int32_t offsetx, int32_t offsety, int32_t advance, void* data) override;
137 void initializeTextDrawing() override;
138 void clearFontSymbols() override;
139 void OpenGLPrint(const char* s, float x, float y, float* color, float scale) override;
140
144
145 vk::Instance mInstance;
146 vk::DebugUtilsMessengerEXT mDebugMessenger;
147 vk::PhysicalDevice mPhysicalDevice;
148 vk::Device mDevice;
149 vk::Queue mGraphicsQueue;
150 vk::SurfaceKHR mSurface;
151 vk::SurfaceFormatKHR mSurfaceFormat;
152 vk::PresentModeKHR mPresentMode;
153 vk::SwapchainKHR mSwapChain;
155 uint8_t mSwapChainSuboptimal = 0; // Bitmask if last acquire / present / ... returned SUBOPTIMAL: recreate only on the first one
156 bool mFrameSkipped = false; // No image acquired in this frame (timeout)
157 void handleSwapChainResult(vk::Result retVal, uint8_t suboptimalBit);
158 std::vector<vk::Image> mSwapChainImages;
159 std::vector<vk::ImageView> mSwapChainImageViews;
160 std::vector<vk::ImageView*> mRenderTargetView;
161 std::vector<vk::Image> mRenderTargetImage;
162 std::vector<VulkanImage> mMSAAImages;
163 std::vector<VulkanImage> mDownsampleImages;
164 std::vector<VulkanImage> mZImages;
165 std::vector<VulkanImage> mMixImages;
166 std::unordered_map<std::string, vk::ShaderModuleCreateInfo> mShaders; // Embedded SPIR-V, chained into the pipeline shader stages (maintenance5, no shader modules)
167 vk::PipelineLayout mPipelineLayout;
168 vk::PipelineLayout mPipelineLayoutTexture;
169 std::vector<vk::Pipeline> mPipelines;
170 vk::CommandPool mCommandPool;
171 vk::PipelineCache mPipelineCache;
172
174 uint32_t mImageCount = 0;
175 uint32_t mFramesInFlight = 0;
176 int32_t mCurrentFrame = 0;
177 uint32_t mCurrentImageIndex = 0;
178 vk::CommandBuffer mCurrentCommandBuffer;
180
181 std::vector<vk::CommandBuffer> mCommandBuffers;
182 std::vector<vk::CommandBuffer> mCommandBuffersDownsample;
183 std::vector<vk::CommandBuffer> mCommandBuffersText;
184 std::vector<vk::CommandBuffer> mCommandBuffersTexture;
185 std::vector<vk::CommandBuffer> mCommandBuffersMix;
186 std::vector<vk::CommandBuffer> mCommandBuffersPresent;
187 std::vector<vk::CommandBufferSubmitInfo> mFrameCommandBuffers; // All command buffers of the current frame, submitted as one batch, ordered by barriers
188 std::vector<bool> mCommandBufferUpToDate; // Per image: main and mix command buffers recorded and still valid (cached across frames), set after the main pass of the frame
189 std::vector<vk::Semaphore> mImageAvailableSemaphore;
190 std::vector<vk::Semaphore> mPresentSemaphore;
191 vk::Semaphore mTimelineSemaphore; // Signaled with an increasing value by every queue submit, replaces fences
192 uint64_t mTimelineValue = 0; // Last value used for a submit
193 std::vector<uint64_t> mFrameTimelineValue; // Per frame slot: value of its last submit, slot (and its acquire semaphore) free once reached
194 std::vector<uint64_t> mImageTimelineValue; // Per swapchain image: value of the last submit using its resources
195 std::mutex mQueueMutex; // Queue submissions must be externally synchronized
196 std::vector<VulkanBuffer> mUniformBuffersMat[3];
197 uint32_t mUpdateUBOdrawMatrix = -1; // Bitmask per swapchain image: UBO must be rewritten when the image is drawn next, set to -1 to update all
198 uint32_t mUpdateUBOtextMatrix = -1;
199 uint32_t mUpdateUBOmixMatrix = -1;
200 float mLastMVP[16] = {};
201 vk::DescriptorSetLayout mUniformDescriptor;
202 vk::DescriptorSetLayout mUniformDescriptorTexture;
203
206
207 std::vector<FontSymbolVulkan> mFontSymbols;
209 std::vector<VulkanBuffer> mFontVertexBuffer;
210 std::vector<TextDrawCommand> mTextDrawCommands;
211 vk::Sampler mTextureSampler;
213 bool mHasDrawnText = false;
214
215 // Device capabilities, set in createDevice (optional features are enabled only if supported)
216 uint32_t mMaxMSAAsupported = 0;
217 bool mZSupported = false;
218 bool mStencilSupported = false;
219 float mMaxLineWidth = 1.f, mMaxPointSize = 1.f;
220 bool mStrictLines = false; // Wide lines are rectangles, not parallelograms
221 bool mSmoothLinesSupported = false; // Optional Vulkan 1.4 feature smoothLines
222 bool mFifoLatestReadySupported = false; // Optional present mode FIFO_LATEST_READY (VK_KHR / VK_EXT_present_mode_fifo_latest_ready)
223
224 vk::SampleCountFlagBits mMSAASampleCount = vk::SampleCountFlagBits::e16;
225 bool mZActive = false;
226 bool mSmoothLines = false;
228 bool mPresentModeForVSyncLimit = false; // Swapchain created with FIFO for the refresh rate FPS limit
229 std::vector<vk::Fence> mPresentFences; // Per swapchain image, signaled when its last present is done (swapchain_maintenance1)
230 uint64_t mLastPresentId = 0; // Last present ID of the current swapchain, 0 = none
231 bool mDownsampleFSAA = false;
233
235};
236} // namespace o2::gpu
237
238#endif
int32_t retVal
void OpenGLPrint(const char *s, float x, float y, float *color, float scale) override
std::vector< vk::CommandBuffer > mCommandBuffersMix
std::vector< vk::CommandBuffer > mCommandBuffers
std::vector< vk::Semaphore > mPresentSemaphore
std::vector< vk::Image > mRenderTargetImage
std::vector< vk::Pipeline > mPipelines
void resizeScene(uint32_t width, uint32_t height) override
void submitSingleTimeCommandBuffer(vk::CommandBuffer commandBuffer)
std::vector< VulkanImage > mDownsampleImages
void writeToBuffer(VulkanBuffer &buffer, size_t size, const void *srcData)
std::vector< vk::ImageView > mSwapChainImageViews
std::vector< vk::CommandBufferSubmitInfo > mFrameCommandBuffers
void pointSizeFactor(float factor) override
std::vector< FontSymbolVulkan > mFontSymbols
std::vector< vk::ImageView * > mRenderTargetView
bool prepareDraw(const hmm_mat4 &proj, const hmm_mat4 &view, bool requestScreenshot, bool toMixBuffer, float includeMixImage) override
void addFontSymbol(int32_t symbol, int32_t sizex, int32_t sizey, int32_t offsetx, int32_t offsety, int32_t advance, void *data) override
void mixImages(vk::CommandBuffer cmdBuffer, float mixSlaveImage)
void recreateRendering(bool forScreenshot=false, bool forMixing=false)
std::vector< VulkanBuffer > mFontVertexBuffer
double checkDevice(vk::PhysicalDevice device, const std::vector< const char * > &reqDeviceExtensions, const FeatureChain &reqDeviceFeatures, bool silent=false)
void endFillCommandBuffer(vk::CommandBuffer &commandBuffer)
uint32_t drawVertices(const vboList &v, const drawType t) override
std::vector< vk::CommandBuffer > mCommandBuffersPresent
std::vector< vk::CommandBuffer > mCommandBuffersDownsample
void ActivateColor(std::array< float, 4 > &color) override
uint64_t queueSubmit(uint64_t *timelineSignalValue, Args &&... args)
std::vector< VulkanBuffer > mUniformBuffersMat[3]
void updateSwapChainDetails(const vk::PhysicalDevice &device)
void handleSwapChainResult(vk::Result retVal, uint8_t suboptimalBit)
vk::StructureChain< vk::PhysicalDeviceFeatures2, vk::PhysicalDeviceVulkan11Features, vk::PhysicalDeviceVulkan12Features, vk::PhysicalDeviceVulkan13Features, vk::PhysicalDeviceVulkan14Features, vk::PhysicalDeviceSwapchainMaintenance1FeaturesKHR, vk::PhysicalDevicePresentIdFeaturesKHR, vk::PhysicalDevicePresentWaitFeaturesKHR > FeatureChain
void finishDraw(bool doScreenshot, bool toMixBuffer, float includeMixImage) override
void writeToImage(VulkanImage &image, const void *srcData, size_t srcSize)
std::unordered_map< std::string, vk::ShaderModuleCreateInfo > mShaders
vk::DescriptorSetLayout mUniformDescriptorTexture
void downsampleToFramebuffer(vk::CommandBuffer &commandBuffer)
void createSwapChain(vk::SwapchainKHR oldSwapChain={})
vk::Extent2D chooseSwapExtent(const vk::SurfaceCapabilitiesKHR &capabilities)
VulkanImage createImage(uint32_t sizex, uint32_t sizey, const void *srcData=nullptr, size_t srcSize=0, vk::Format format=vk::Format::eR8G8B8A8Srgb)
std::vector< TextDrawCommand > mTextDrawCommands
void cmdPushDescriptors(vk::CommandBuffer commandBuffer, vk::PipelineLayout layout, const VulkanBuffer &ubo, vk::ImageView textureView={})
void finishFrame(bool doScreenshot, bool toMixBuffer, float includeMixImage) override
void clearSwapChain(bool keepSwapChain=false)
std::vector< vk::Semaphore > mImageAvailableSemaphore
void startFillCommandBuffer(vk::CommandBuffer &commandBuffer, uint32_t imageIndex, bool toMixBuffer=false)
std::vector< vk::CommandBuffer > mCommandBuffersTexture
vk::DebugUtilsMessengerEXT mDebugMessenger
void cmdDownsample(vk::CommandBuffer commandBuffer, vk::ImageView src, vk::ImageView dst, uint32_t width, uint32_t height, int32_t factor)
VulkanBuffer createBuffer(size_t size, const void *srcData=nullptr, vk::BufferUsageFlags type=vk::BufferUsageFlagBits::eVertexBuffer, int32_t deviceMemory=1)
void createOffscreenBuffers(bool forScreenshot=false, bool forMixing=false)
void lineWidthFactor(float factor) override
void readImageToPixels(vk::Image image, vk::ImageView view, vk::ImageLayout layout, std::vector< char > &pixels)
std::vector< vk::CommandBuffer > mCommandBuffersText
void loadDataToGPU(size_t totalVertizes) override
std::tuple< uint32_t, uint32_t, int32_t > vboList
GLeglImageOES image
Definition glcorearb.h:4021
GLint GLenum GLint x
Definition glcorearb.h:403
GLenum src
Definition glcorearb.h:1767
GLuint buffer
Definition glcorearb.h:655
GLsizeiptr size
Definition glcorearb.h:659
GLuint color
Definition glcorearb.h:1272
const GLdouble * v
Definition glcorearb.h:832
GLint GLsizei GLsizei height
Definition glcorearb.h:270
GLint GLsizei width
Definition glcorearb.h:270
GLint y
Definition glcorearb.h:270
GLsizei const GLfloat * value
Definition glcorearb.h:819
GLint GLint GLsizei GLint GLenum GLenum type
Definition glcorearb.h:275
GLenum GLenum dst
Definition glcorearb.h:1767
GLboolean * data
Definition glcorearb.h:298
GLint GLint GLsizei GLint GLenum GLenum const void * pixels
Definition glcorearb.h:275
GLboolean enable
Definition glcorearb.h:3991
GLint GLint GLsizei GLint GLenum format
Definition glcorearb.h:275
typename std::vector< T, vecpod_allocator< T > > vecpod
Definition vecpod.h:31