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 vk::Renderer *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 vk::Renderer *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
69 ANGLE_TRY(contextVk->initImageAllocation(&mFontImage, false, renderer->getMemoryProperties(),
70 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
71 vk::MemoryAllocationType::FontImage));
72
73 ANGLE_TRY(mFontImage.initLayerImageView(
74 contextVk, gl::TextureType::_2DArray, VK_IMAGE_ASPECT_COLOR_BIT, gl::SwizzleState(),
75 &mFontImageView, vk::LevelIndex(0), gl::overlay::kFontMipCount, 0,
76 mFontImage.getLayerCount()));
77
78 // Copy font data from staging buffer.
79 vk::CommandBufferAccess access;
80 access.onBufferTransferRead(&fontDataBuffer.get());
81 access.onImageTransferWrite(gl::LevelIndex(0), gl::overlay::kFontMipCount, 0,
82 gl::overlay::kFontCharacters, VK_IMAGE_ASPECT_COLOR_BIT,
83 &mFontImage);
84 vk::OutsideRenderPassCommandBuffer *fontDataUpload;
85 ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &fontDataUpload));
86
87 VkBufferImageCopy copy = {};
88 copy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
89 copy.imageSubresource.layerCount = gl::overlay::kFontCharacters;
90 copy.imageExtent.depth = 1;
91
92 for (uint32_t mip = 0; mip < gl::overlay::kFontMipCount; ++mip)
93 {
94 copy.bufferOffset = gl::overlay::kFontMipDataOffset[mip];
95 copy.bufferRowLength = gl::overlay::kFontGlyphWidth >> mip;
96 copy.bufferImageHeight = gl::overlay::kFontGlyphHeight >> mip;
97 copy.imageSubresource.mipLevel = mip;
98 copy.imageExtent.width = gl::overlay::kFontGlyphWidth >> mip;
99 copy.imageExtent.height = gl::overlay::kFontGlyphHeight >> mip;
100
101 fontDataUpload->copyBufferToImage(fontDataBuffer.get().getBuffer().getHandle(),
102 mFontImage.getImage(),
103 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©);
104 }
105
106 return angle::Result::Continue;
107 }
108
onPresent(ContextVk * contextVk,vk::ImageHelper * imageToPresent,const vk::ImageView * imageToPresentView,bool is90DegreeRotation)109 angle::Result OverlayVk::onPresent(ContextVk *contextVk,
110 vk::ImageHelper *imageToPresent,
111 const vk::ImageView *imageToPresentView,
112 bool is90DegreeRotation)
113 {
114 if (mState.getEnabledWidgetCount() == 0)
115 {
116 return angle::Result::Continue;
117 }
118
119 // Lazily initialize the font on first use
120 if (!mFontImage.valid())
121 {
122 ANGLE_TRY(createFont(contextVk));
123 }
124
125 vk::Renderer *renderer = contextVk->getRenderer();
126
127 vk::RendererScoped<vk::BufferHelper> textDataBuffer(renderer);
128 vk::RendererScoped<vk::BufferHelper> graphDataBuffer(renderer);
129
130 VkBufferCreateInfo textBufferCreateInfo = {};
131 textBufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
132 textBufferCreateInfo.size = mState.getTextWidgetsBufferSize();
133 textBufferCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
134 textBufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
135
136 VkBufferCreateInfo graphBufferCreateInfo = textBufferCreateInfo;
137 graphBufferCreateInfo.size = mState.getGraphWidgetsBufferSize();
138
139 ANGLE_TRY(textDataBuffer.get().init(contextVk, textBufferCreateInfo,
140 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));
141 ANGLE_TRY(graphDataBuffer.get().init(contextVk, graphBufferCreateInfo,
142 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));
143
144 uint8_t *textData;
145 uint8_t *graphData;
146 ANGLE_TRY(textDataBuffer.get().map(contextVk, &textData));
147 ANGLE_TRY(graphDataBuffer.get().map(contextVk, &graphData));
148
149 uint32_t textWidgetCount = 0;
150 uint32_t graphWidgetCount = 0;
151
152 gl::Extents presentImageExtents(imageToPresent->getExtents().width,
153 imageToPresent->getExtents().height, 1);
154 mState.fillWidgetData(presentImageExtents, textData, graphData, &textWidgetCount,
155 &graphWidgetCount);
156
157 ANGLE_TRY(textDataBuffer.get().flush(renderer, 0, textDataBuffer.get().getSize()));
158 ANGLE_TRY(graphDataBuffer.get().flush(renderer, 0, graphDataBuffer.get().getSize()));
159 textDataBuffer.get().unmap(renderer);
160 graphDataBuffer.get().unmap(renderer);
161
162 UtilsVk::OverlayDrawParameters params;
163 params.textWidgetCount = textWidgetCount;
164 params.graphWidgetCount = graphWidgetCount;
165 params.rotateXY = is90DegreeRotation;
166
167 return contextVk->getUtils().drawOverlay(contextVk, &textDataBuffer.get(),
168 &graphDataBuffer.get(), &mFontImage, &mFontImageView,
169 imageToPresent, imageToPresentView, params);
170 }
171
172 } // namespace rx
173