1 //
2 // Copyright 2019 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // OverlayVk.cpp:
7 // Implements the OverlayVk class.
8 //
9
10 #include "libANGLE/renderer/vulkan/OverlayVk.h"
11
12 #include "common/system_utils.h"
13 #include "libANGLE/Context.h"
14 #include "libANGLE/Overlay_font_autogen.h"
15 #include "libANGLE/renderer/vulkan/ContextVk.h"
16
17 #include <numeric>
18
19 namespace rx
20 {
OverlayVk(const gl::OverlayState & state)21 OverlayVk::OverlayVk(const gl::OverlayState &state) : OverlayImpl(state) {}
22 OverlayVk::~OverlayVk() = default;
23
onDestroy(const gl::Context * context)24 void OverlayVk::onDestroy(const gl::Context *context)
25 {
26 RendererVk *renderer = vk::GetImpl(context)->getRenderer();
27 VkDevice device = renderer->getDevice();
28
29 mFontImage.destroy(renderer);
30 mFontImageView.destroy(device);
31 }
32
createFont(ContextVk * contextVk)33 angle::Result OverlayVk::createFont(ContextVk *contextVk)
34 {
35 RendererVk *renderer = contextVk->getRenderer();
36
37 // Create a buffer to stage font data upload.
38 VkBufferCreateInfo bufferCreateInfo = {};
39 bufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
40 bufferCreateInfo.size = gl::overlay::kFontTotalDataSize;
41 bufferCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
42 bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
43
44 vk::RendererScoped<vk::BufferHelper> fontDataBuffer(renderer);
45
46 ANGLE_TRY(fontDataBuffer.get().init(contextVk, bufferCreateInfo,
47 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));
48
49 uint8_t *mappedFontData;
50 ANGLE_TRY(fontDataBuffer.get().map(contextVk, &mappedFontData));
51
52 const uint8_t *fontData = mState.getFontData();
53 memcpy(mappedFontData, fontData, gl::overlay::kFontTotalDataSize * sizeof(*fontData));
54
55 ANGLE_TRY(fontDataBuffer.get().flush(renderer, 0, fontDataBuffer.get().getSize()));
56 fontDataBuffer.get().unmap(renderer);
57
58 // Don't use robust resource init for overlay widgets.
59 constexpr bool kNoRobustInit = false;
60
61 // Create the font image.
62 ANGLE_TRY(mFontImage.init(
63 contextVk, gl::TextureType::_2D,
64 VkExtent3D{gl::overlay::kFontGlyphWidth, gl::overlay::kFontGlyphHeight, 1},
65 renderer->getFormat(angle::FormatID::R8_UNORM), 1,
66 VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, gl::LevelIndex(0),
67 gl::overlay::kFontMipCount, gl::overlay::kFontCharacters, kNoRobustInit, false));
68 ANGLE_TRY(mFontImage.initMemory(contextVk, false, renderer->getMemoryProperties(),
69 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
70 vk::MemoryAllocationType::FontImage));
71 ANGLE_TRY(mFontImage.initImageView(
72 contextVk, gl::TextureType::_2DArray, VK_IMAGE_ASPECT_COLOR_BIT, gl::SwizzleState(),
73 &mFontImageView, vk::LevelIndex(0), gl::overlay::kFontMipCount,
74 vk::ImageHelper::kDefaultImageViewUsageFlags));
75
76 // Copy font data from staging buffer.
77 vk::CommandBufferAccess access;
78 access.onBufferTransferRead(&fontDataBuffer.get());
79 access.onImageTransferWrite(gl::LevelIndex(0), gl::overlay::kFontMipCount, 0,
80 gl::overlay::kFontCharacters, VK_IMAGE_ASPECT_COLOR_BIT,
81 &mFontImage);
82 vk::OutsideRenderPassCommandBuffer *fontDataUpload;
83 ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &fontDataUpload));
84
85 VkBufferImageCopy copy = {};
86 copy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
87 copy.imageSubresource.layerCount = gl::overlay::kFontCharacters;
88 copy.imageExtent.depth = 1;
89
90 for (uint32_t mip = 0; mip < gl::overlay::kFontMipCount; ++mip)
91 {
92 copy.bufferOffset = gl::overlay::kFontMipDataOffset[mip];
93 copy.bufferRowLength = gl::overlay::kFontGlyphWidth >> mip;
94 copy.bufferImageHeight = gl::overlay::kFontGlyphHeight >> mip;
95 copy.imageSubresource.mipLevel = mip;
96 copy.imageExtent.width = gl::overlay::kFontGlyphWidth >> mip;
97 copy.imageExtent.height = gl::overlay::kFontGlyphHeight >> mip;
98
99 fontDataUpload->copyBufferToImage(fontDataBuffer.get().getBuffer().getHandle(),
100 mFontImage.getImage(),
101 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©);
102 }
103
104 return angle::Result::Continue;
105 }
106
onPresent(ContextVk * contextVk,vk::ImageHelper * imageToPresent,const vk::ImageView * imageToPresentView,bool is90DegreeRotation)107 angle::Result OverlayVk::onPresent(ContextVk *contextVk,
108 vk::ImageHelper *imageToPresent,
109 const vk::ImageView *imageToPresentView,
110 bool is90DegreeRotation)
111 {
112 if (mState.getEnabledWidgetCount() == 0)
113 {
114 return angle::Result::Continue;
115 }
116
117 // Lazily initialize the font on first use
118 if (!mFontImage.valid())
119 {
120 ANGLE_TRY(createFont(contextVk));
121 }
122
123 RendererVk *renderer = contextVk->getRenderer();
124
125 vk::RendererScoped<vk::BufferHelper> textDataBuffer(renderer);
126 vk::RendererScoped<vk::BufferHelper> graphDataBuffer(renderer);
127
128 VkBufferCreateInfo textBufferCreateInfo = {};
129 textBufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
130 textBufferCreateInfo.size = mState.getTextWidgetsBufferSize();
131 textBufferCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
132 textBufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
133
134 VkBufferCreateInfo graphBufferCreateInfo = textBufferCreateInfo;
135 graphBufferCreateInfo.size = mState.getGraphWidgetsBufferSize();
136
137 ANGLE_TRY(textDataBuffer.get().init(contextVk, textBufferCreateInfo,
138 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));
139 ANGLE_TRY(graphDataBuffer.get().init(contextVk, graphBufferCreateInfo,
140 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));
141
142 uint8_t *textData;
143 uint8_t *graphData;
144 ANGLE_TRY(textDataBuffer.get().map(contextVk, &textData));
145 ANGLE_TRY(graphDataBuffer.get().map(contextVk, &graphData));
146
147 uint32_t textWidgetCount = 0;
148 uint32_t graphWidgetCount = 0;
149
150 gl::Extents presentImageExtents(imageToPresent->getExtents().width,
151 imageToPresent->getExtents().height, 1);
152 mState.fillWidgetData(presentImageExtents, textData, graphData, &textWidgetCount,
153 &graphWidgetCount);
154
155 ANGLE_TRY(textDataBuffer.get().flush(renderer, 0, textDataBuffer.get().getSize()));
156 ANGLE_TRY(graphDataBuffer.get().flush(renderer, 0, graphDataBuffer.get().getSize()));
157 textDataBuffer.get().unmap(renderer);
158 graphDataBuffer.get().unmap(renderer);
159
160 UtilsVk::OverlayDrawParameters params;
161 params.textWidgetCount = textWidgetCount;
162 params.graphWidgetCount = graphWidgetCount;
163 params.rotateXY = is90DegreeRotation;
164
165 return contextVk->getUtils().drawOverlay(contextVk, &textDataBuffer.get(),
166 &graphDataBuffer.get(), &mFontImage, &mFontImageView,
167 imageToPresent, imageToPresentView, params);
168 }
169
170 } // namespace rx
171