mirrored from https://skia.googlesource.com/skia
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
/
Copy pathVulkanBasic.cpp
138 lines (120 loc) · 6.22 KB
/
VulkanBasic.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/*
* Copyright 2022 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "include/core/SkAlphaType.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkColorType.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkSurface.h"
#include "include/core/SkTypes.h"
#include "include/gpu/ganesh/GrDirectContext.h"
#include "include/gpu/ganesh/SkSurfaceGanesh.h"
#include "include/gpu/ganesh/vk/GrVkDirectContext.h"
#include "include/gpu/vk/VulkanBackendContext.h"
#include "include/gpu/vk/VulkanExtensions.h"
#include "include/gpu/vk/VulkanMemoryAllocator.h"
// These are private files. Clients would need to look at these and implement
// similar solutions.
#include "src/gpu/vk/vulkanmemoryallocator/VulkanMemoryAllocatorPriv.h"
#include "src/gpu/GpuTypesPriv.h"
#include "tools/gpu/vk/VkTestUtils.h"
#include <string.h>
#include <vulkan/vulkan_core.h>
#include <functional>
#include <memory>
#define ACQUIRE_INST_VK_PROC(name) \
do { \
fVk##name = reinterpret_cast<PFN_vk##name>(getProc("vk" #name, backendContext.fInstance, \
VK_NULL_HANDLE)); \
if (fVk##name == nullptr) { \
SkDebugf("Function ptr for vk%s could not be acquired\n", #name); \
return 1; \
} \
} while(false)
int main(int argc, char** argv) {
skgpu::VulkanBackendContext backendContext;
VkDebugReportCallbackEXT debugCallback;
std::unique_ptr<skgpu::VulkanExtensions> extensions(new skgpu::VulkanExtensions());
std::unique_ptr<VkPhysicalDeviceFeatures2> features(new VkPhysicalDeviceFeatures2);
// First we need to create a VulkanBackendContext so that we can make a Vulkan GrDirectContext.
// The vast majority of this chunk of code is setting up the VkInstance and VkDevice objects.
// Normally a client will have their own way of creating these objects. This example uses Skia's
// test helper sk_gpu_test::CreateVkBackendContext to aid in this. Clients can look at this
// function as a guide on things to consider when setting up Vulkan for themselves, but they
// should not depend on that function. We may arbitrarily change it as it is meant only for Skia
// internal testing. Additionally it may do some odd things that a normal Vulkan user wouldn't
// do because it is only meant for Skia testing.
{
PFN_vkGetInstanceProcAddr instProc;
if (!sk_gpu_test::LoadVkLibraryAndGetProcAddrFuncs(&instProc)) {
return 1;
}
memset(features.get(), 0, sizeof(VkPhysicalDeviceFeatures2));
features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
features->pNext = nullptr;
// Fill in features you want to enable here
backendContext.fInstance = VK_NULL_HANDLE;
backendContext.fDevice = VK_NULL_HANDLE;
if (!sk_gpu_test::CreateVkBackendContext(instProc, &backendContext, extensions.get(),
features.get(), &debugCallback)) {
return 1;
}
}
auto getProc = backendContext.fGetProc;
PFN_vkDestroyInstance fVkDestroyInstance;
PFN_vkDestroyDebugReportCallbackEXT fVkDestroyDebugReportCallbackEXT = nullptr;
PFN_vkDestroyDevice fVkDestroyDevice;
ACQUIRE_INST_VK_PROC(DestroyInstance);
if (debugCallback != VK_NULL_HANDLE) {
ACQUIRE_INST_VK_PROC(DestroyDebugReportCallbackEXT);
}
ACQUIRE_INST_VK_PROC(DestroyDevice);
backendContext.fMemoryAllocator = skgpu::VulkanMemoryAllocators::Make(
backendContext, skgpu::ThreadSafe::kNo, std::nullopt);
// Create a GrDirectContext with our VulkanBackendContext
sk_sp<GrDirectContext> context = GrDirectContexts::MakeVulkan(backendContext);
if (!context) {
fVkDestroyDevice(backendContext.fDevice, nullptr);
if (debugCallback != VK_NULL_HANDLE) {
fVkDestroyDebugReportCallbackEXT(backendContext.fInstance, debugCallback, nullptr);
}
fVkDestroyInstance(backendContext.fInstance, nullptr);
return 1;
}
SkImageInfo imageInfo = SkImageInfo::Make(16, 16, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
// Create an SkSurface backed by a Vulkan VkImage. Often clients will be getting VkImages from
// swapchains. In those cases they should use SkSurfaces::WrapBackendTexture or
// SkSurfaces::WrapBackendRenderTarget to wrap those premade VkImages in Skia. See the
// HelloWorld example app to see how this is done.
sk_sp<SkSurface> surface =
SkSurfaces::RenderTarget(context.get(), skgpu::Budgeted::kYes, imageInfo);
if (!surface) {
context.reset();
fVkDestroyDevice(backendContext.fDevice, nullptr);
if (debugCallback != VK_NULL_HANDLE) {
fVkDestroyDebugReportCallbackEXT(backendContext.fInstance, debugCallback, nullptr);
} fVkDestroyInstance(backendContext.fInstance, nullptr);
return 1;
}
surface->getCanvas()->clear(SK_ColorRED);
// After drawing to our surface, we must first flush the recorded work (i.e. convert all our
// recorded SkCanvas calls into a VkCommandBuffer). Then we call submit to submit our
// VkCommandBuffers to the gpu queue.
context->flush(surface.get());
context->submit();
surface.reset();
context.reset();
// Skia doesn't own the VkDevice or VkInstance so the client must manage their lifetime. The
// client must not delete these objects until cleaning up all Skia objects that may have used
// them first.
fVkDestroyDevice(backendContext.fDevice, nullptr);
if (debugCallback != VK_NULL_HANDLE) {
fVkDestroyDebugReportCallbackEXT(backendContext.fInstance, debugCallback, nullptr);
} fVkDestroyInstance(backendContext.fInstance, nullptr);
return 0;
}