Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
VulkanBasic.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2022 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
22
23#include <string.h>
24#include <vulkan/vulkan_core.h>
25#include <functional>
26#include <memory>
27
28#define ACQUIRE_INST_VK_PROC(name) \
29 do { \
30 fVk##name = reinterpret_cast<PFN_vk##name>(getProc("vk" #name, backendContext.fInstance, \
31 VK_NULL_HANDLE)); \
32 if (fVk##name == nullptr) { \
33 SkDebugf("Function ptr for vk%s could not be acquired\n", #name); \
34 return 1; \
35 } \
36 } while(false)
37
38int main(int argc, char** argv) {
39 GrVkBackendContext backendContext;
40 VkDebugReportCallbackEXT debugCallback;
41 std::unique_ptr<skgpu::VulkanExtensions> extensions(new skgpu::VulkanExtensions());
42 std::unique_ptr<VkPhysicalDeviceFeatures2> features(new VkPhysicalDeviceFeatures2);
43
44 // First we need to create a GrVkBackendContext so that we can make a Vulkan GrDirectContext.
45 // The vast majority of this chunk of code is setting up the VkInstance and VkDevice objects.
46 // Normally a client will have their own way of creating these objects. This example uses Skia's
47 // test helper sk_gpu_test::CreateVkBackendContext to aid in this. Clients can look at this
48 // function as a guide on things to consider when setting up Vulkan for themselves, but they
49 // should not depend on that function. We may arbitrarily change it as it is meant only for Skia
50 // internal testing. Additionally it may do some odd things that a normal Vulkan user wouldn't
51 // do because it is only meant for Skia testing.
52 {
54 if (!sk_gpu_test::LoadVkLibraryAndGetProcAddrFuncs(&instProc)) {
55 return 1;
56 }
57
58 memset(features.get(), 0, sizeof(VkPhysicalDeviceFeatures2));
60 features->pNext = nullptr;
61 // Fill in features you want to enable here
62
63 backendContext.fInstance = VK_NULL_HANDLE;
64 backendContext.fDevice = VK_NULL_HANDLE;
65
66 if (!sk_gpu_test::CreateVkBackendContext(instProc, &backendContext, extensions.get(),
67 features.get(), &debugCallback)) {
68 return 1;
69 }
70 }
71
72 auto getProc = backendContext.fGetProc;
73 PFN_vkDestroyInstance fVkDestroyInstance;
74 PFN_vkDestroyDebugReportCallbackEXT fVkDestroyDebugReportCallbackEXT = nullptr;
75 PFN_vkDestroyDevice fVkDestroyDevice;
76 ACQUIRE_INST_VK_PROC(DestroyInstance);
77 if (debugCallback != VK_NULL_HANDLE) {
78 ACQUIRE_INST_VK_PROC(DestroyDebugReportCallbackEXT);
79 }
80 ACQUIRE_INST_VK_PROC(DestroyDevice);
81
82 // Create a GrDirectContext with our GrVkBackendContext
84 if (!context) {
85 fVkDestroyDevice(backendContext.fDevice, nullptr);
86 if (debugCallback != VK_NULL_HANDLE) {
87 fVkDestroyDebugReportCallbackEXT(backendContext.fInstance, debugCallback, nullptr);
88 }
89 fVkDestroyInstance(backendContext.fInstance, nullptr);
90 return 1;
91 }
92
94
95 // Create an SkSurface backed by a Vulkan VkImage. Often clients will be getting VkImages from
96 // swapchains. In those cases they should use SkSurfaces::WrapBackendTexture or
97 // SkSurfaces::WrapBackendRenderTarget to wrap those premade VkImages in Skia. See the
98 // HelloWorld example app to see how this is done.
101 if (!surface) {
102 context.reset();
103 fVkDestroyDevice(backendContext.fDevice, nullptr);
104 if (debugCallback != VK_NULL_HANDLE) {
105 fVkDestroyDebugReportCallbackEXT(backendContext.fInstance, debugCallback, nullptr);
106 } fVkDestroyInstance(backendContext.fInstance, nullptr);
107 return 1;
108 }
109
110 surface->getCanvas()->clear(SK_ColorRED);
111
112 // After drawing to our surface, we must first flush the recorded work (i.e. convert all our
113 // recorded SkCanvas calls into a VkCommandBuffer). Then we call submit to submit our
114 // VkCommandBuffers to the gpu queue.
115 context->flush(surface.get());
116 context->submit();
117
118 surface.reset();
119 context.reset();
120
121 // Skia doesn't own the VkDevice or VkInstance so the client must manage their lifetime. The
122 // client must not delete these objects until cleaning up all Skia objects that may have used
123 // them first.
124 fVkDestroyDevice(backendContext.fDevice, nullptr);
125 if (debugCallback != VK_NULL_HANDLE) {
126 fVkDestroyDebugReportCallbackEXT(backendContext.fInstance, debugCallback, nullptr);
127 } fVkDestroyInstance(backendContext.fInstance, nullptr);
128 return 0;
129}
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
Definition SkAlphaType.h:29
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
Definition SkColorType.h:24
constexpr SkColor SK_ColorRED
Definition SkColor.h:126
#define ACQUIRE_INST_VK_PROC(name)
T * get() const
Definition SkRefCnt.h:303
void reset(T *ptr=nullptr)
Definition SkRefCnt.h:310
VkSurfaceKHR surface
Definition main.cc:49
SK_API sk_sp< GrDirectContext > MakeVulkan(const GrVkBackendContext &, const GrContextOptions &)
SK_API sk_sp< SkSurface > RenderTarget(GrRecordingContext *context, skgpu::Budgeted budgeted, const SkImageInfo &imageInfo, int sampleCount, GrSurfaceOrigin surfaceOrigin, const SkSurfaceProps *surfaceProps, bool shouldCreateWithMips=false, bool isProtected=false)
Definition main.py:1
skgpu::VulkanGetProc fGetProc
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at)
void(VKAPI_PTR * PFN_vkDestroyDebugReportCallbackEXT)(VkInstance instance, VkDebugReportCallbackEXT callback, const VkAllocationCallbacks *pAllocator)
void(VKAPI_PTR * PFN_vkDestroyInstance)(VkInstance instance, const VkAllocationCallbacks *pAllocator)
void(VKAPI_PTR * PFN_vkDestroyDevice)(VkDevice device, const VkAllocationCallbacks *pAllocator)
#define VK_NULL_HANDLE
Definition vulkan_core.h:46
PFN_vkVoidFunction(VKAPI_PTR * PFN_vkGetInstanceProcAddr)(VkInstance instance, const char *pName)
@ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2