| // |
| // Copyright 2019 The ANGLE Project Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| // |
| // OverlayVk.cpp: |
| // Implements the OverlayVk class. |
| // |
| |
| #include "libANGLE/renderer/vulkan/OverlayVk.h" |
| |
| #include "common/system_utils.h" |
| #include "libANGLE/Context.h" |
| #include "libANGLE/Overlay_font_autogen.h" |
| #include "libANGLE/renderer/vulkan/ContextVk.h" |
| |
| #include <numeric> |
| |
| namespace rx |
| { |
| OverlayVk::OverlayVk(const gl::OverlayState &state) : OverlayImpl(state) {} |
| OverlayVk::~OverlayVk() = default; |
| |
| void OverlayVk::onDestroy(const gl::Context *context) |
| { |
| RendererVk *renderer = vk::GetImpl(context)->getRenderer(); |
| VkDevice device = renderer->getDevice(); |
| |
| mFontImage.destroy(renderer); |
| mFontImageView.destroy(device); |
| } |
| |
| angle::Result OverlayVk::createFont(ContextVk *contextVk) |
| { |
| RendererVk *renderer = contextVk->getRenderer(); |
| |
| // Create a buffer to stage font data upload. |
| VkBufferCreateInfo bufferCreateInfo = {}; |
| bufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; |
| bufferCreateInfo.size = gl::overlay::kFontTotalDataSize; |
| bufferCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; |
| bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; |
| |
| vk::RendererScoped<vk::BufferHelper> fontDataBuffer(renderer); |
| |
| ANGLE_TRY(fontDataBuffer.get().init(contextVk, bufferCreateInfo, |
| VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)); |
| |
| uint8_t *mappedFontData; |
| ANGLE_TRY(fontDataBuffer.get().map(contextVk, &mappedFontData)); |
| |
| const uint8_t *fontData = mState.getFontData(); |
| memcpy(mappedFontData, fontData, gl::overlay::kFontTotalDataSize * sizeof(*fontData)); |
| |
| ANGLE_TRY(fontDataBuffer.get().flush(renderer, 0, fontDataBuffer.get().getSize())); |
| fontDataBuffer.get().unmap(renderer); |
| |
| // Don't use robust resource init for overlay widgets. |
| constexpr bool kNoRobustInit = false; |
| |
| // Create the font image. |
| ANGLE_TRY(mFontImage.init( |
| contextVk, gl::TextureType::_2D, |
| VkExtent3D{gl::overlay::kFontGlyphWidth, gl::overlay::kFontGlyphHeight, 1}, |
| renderer->getFormat(angle::FormatID::R8_UNORM), 1, |
| VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, gl::LevelIndex(0), |
| gl::overlay::kFontMipCount, gl::overlay::kFontCharacters, kNoRobustInit, false)); |
| ANGLE_TRY(mFontImage.initMemory(contextVk, false, renderer->getMemoryProperties(), |
| VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)); |
| ANGLE_TRY(mFontImage.initImageView( |
| contextVk, gl::TextureType::_2DArray, VK_IMAGE_ASPECT_COLOR_BIT, gl::SwizzleState(), |
| &mFontImageView, vk::LevelIndex(0), gl::overlay::kFontMipCount)); |
| |
| // Copy font data from staging buffer. |
| vk::CommandBufferAccess access; |
| access.onBufferTransferRead(&fontDataBuffer.get()); |
| access.onImageTransferWrite(gl::LevelIndex(0), gl::overlay::kFontMipCount, 0, |
| gl::overlay::kFontCharacters, VK_IMAGE_ASPECT_COLOR_BIT, |
| &mFontImage); |
| vk::OutsideRenderPassCommandBuffer *fontDataUpload; |
| ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &fontDataUpload)); |
| |
| VkBufferImageCopy copy = {}; |
| copy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; |
| copy.imageSubresource.layerCount = gl::overlay::kFontCharacters; |
| copy.imageExtent.depth = 1; |
| |
| for (uint32_t mip = 0; mip < gl::overlay::kFontMipCount; ++mip) |
| { |
| copy.bufferOffset = gl::overlay::kFontMipDataOffset[mip]; |
| copy.bufferRowLength = gl::overlay::kFontGlyphWidth >> mip; |
| copy.bufferImageHeight = gl::overlay::kFontGlyphHeight >> mip; |
| copy.imageSubresource.mipLevel = mip; |
| copy.imageExtent.width = gl::overlay::kFontGlyphWidth >> mip; |
| copy.imageExtent.height = gl::overlay::kFontGlyphHeight >> mip; |
| |
| fontDataUpload->copyBufferToImage(fontDataBuffer.get().getBuffer().getHandle(), |
| mFontImage.getImage(), |
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©); |
| } |
| |
| return angle::Result::Continue; |
| } |
| |
| angle::Result OverlayVk::onPresent(ContextVk *contextVk, |
| vk::ImageHelper *imageToPresent, |
| const vk::ImageView *imageToPresentView, |
| bool is90DegreeRotation) |
| { |
| if (mState.getEnabledWidgetCount() == 0) |
| { |
| return angle::Result::Continue; |
| } |
| |
| // Lazily initialize the font on first use |
| if (!mFontImage.valid()) |
| { |
| ANGLE_TRY(createFont(contextVk)); |
| } |
| |
| RendererVk *renderer = contextVk->getRenderer(); |
| |
| vk::RendererScoped<vk::BufferHelper> textDataBuffer(renderer); |
| vk::RendererScoped<vk::BufferHelper> graphDataBuffer(renderer); |
| |
| VkBufferCreateInfo textBufferCreateInfo = {}; |
| textBufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; |
| textBufferCreateInfo.size = mState.getTextWidgetsBufferSize(); |
| textBufferCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; |
| textBufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; |
| |
| VkBufferCreateInfo graphBufferCreateInfo = textBufferCreateInfo; |
| graphBufferCreateInfo.size = mState.getGraphWidgetsBufferSize(); |
| |
| ANGLE_TRY(textDataBuffer.get().init(contextVk, textBufferCreateInfo, |
| VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)); |
| ANGLE_TRY(graphDataBuffer.get().init(contextVk, graphBufferCreateInfo, |
| VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)); |
| |
| uint8_t *textData; |
| uint8_t *graphData; |
| ANGLE_TRY(textDataBuffer.get().map(contextVk, &textData)); |
| ANGLE_TRY(graphDataBuffer.get().map(contextVk, &graphData)); |
| |
| uint32_t textWidgetCount = 0; |
| uint32_t graphWidgetCount = 0; |
| |
| gl::Extents presentImageExtents(imageToPresent->getExtents().width, |
| imageToPresent->getExtents().height, 1); |
| mState.fillWidgetData(presentImageExtents, textData, graphData, &textWidgetCount, |
| &graphWidgetCount); |
| |
| ANGLE_TRY(textDataBuffer.get().flush(renderer, 0, textDataBuffer.get().getSize())); |
| ANGLE_TRY(graphDataBuffer.get().flush(renderer, 0, graphDataBuffer.get().getSize())); |
| textDataBuffer.get().unmap(renderer); |
| graphDataBuffer.get().unmap(renderer); |
| |
| UtilsVk::OverlayDrawParameters params; |
| params.textWidgetCount = textWidgetCount; |
| params.graphWidgetCount = graphWidgetCount; |
| params.rotateXY = is90DegreeRotation; |
| |
| return contextVk->getUtils().drawOverlay(contextVk, &textDataBuffer.get(), |
| &graphDataBuffer.get(), &mFontImage, &mFontImageView, |
| imageToPresent, imageToPresentView, params); |
| } |
| |
| } // namespace rx |