Commit 3c9db653 authored by Peng Huang's avatar Peng Huang Committed by Commit Bot

vulkan: add branch prediction hints

Bug: None
Change-Id: I72116c939a055ad8458d9163d1279d21fd10cde3
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2333315
Auto-Submit: Peng Huang <penghuang@chromium.org>
Commit-Queue: Vasiliy Telezhnikov <vasilyt@chromium.org>
Reviewed-by: default avatarVasiliy Telezhnikov <vasilyt@chromium.org>
Cr-Commit-Position: refs/heads/master@{#795518}
parent 1f9a9579
......@@ -6,7 +6,9 @@
#include <utility>
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/threading/scoped_blocking_call.h"
#include "build/build_config.h"
#include "components/viz/common/gpu/vulkan_context_provider.h"
#include "gpu/command_buffer/service/memory_tracking.h"
......@@ -31,7 +33,7 @@ std::unique_ptr<SkiaOutputDeviceVulkan> SkiaOutputDeviceVulkan::Create(
auto output_device = std::make_unique<SkiaOutputDeviceVulkan>(
util::PassKey<SkiaOutputDeviceVulkan>(), context_provider, surface_handle,
memory_tracker, did_swap_buffer_complete_callback);
if (!output_device->Initialize())
if (UNLIKELY(!output_device->Initialize()))
return nullptr;
return output_device;
}
......@@ -48,22 +50,27 @@ SkiaOutputDeviceVulkan::SkiaOutputDeviceVulkan(
SkiaOutputDeviceVulkan::~SkiaOutputDeviceVulkan() {
DCHECK(!scoped_write_);
for (auto it = sk_surface_size_pairs_.begin();
it != sk_surface_size_pairs_.end(); ++it) {
memory_type_tracker_->TrackMemFree(it->bytes_allocated);
for (const auto& sk_surface_size_pair : sk_surface_size_pairs_) {
memory_type_tracker_->TrackMemFree(sk_surface_size_pair.bytes_allocated);
}
sk_surface_size_pairs_.clear();
if (!vulkan_surface_)
if (UNLIKELY(!vulkan_surface_))
return;
vkQueueWaitIdle(context_provider_->GetDeviceQueue()->GetVulkanQueue());
{
base::ScopedBlockingCall scoped_blocking_call(
FROM_HERE, base::BlockingType::MAY_BLOCK);
vkQueueWaitIdle(context_provider_->GetDeviceQueue()->GetVulkanQueue());
}
vulkan_surface_->Destroy();
}
#if defined(OS_WIN)
gpu::SurfaceHandle SkiaOutputDeviceVulkan::GetChildSurfaceHandle() {
if (vulkan_surface_->accelerated_widget() != surface_handle_)
if (LIKELY(vulkan_surface_->accelerated_widget() != surface_handle_))
return vulkan_surface_->accelerated_widget();
return gpu::kNullSurfaceHandle;
}
......@@ -76,14 +83,14 @@ bool SkiaOutputDeviceVulkan::Reshape(const gfx::Size& size,
gfx::OverlayTransform transform) {
DCHECK(!scoped_write_);
if (!vulkan_surface_)
if (UNLIKELY(!vulkan_surface_))
return false;
return RecreateSwapChain(size, color_space.ToSkColorSpace(), transform);
}
void SkiaOutputDeviceVulkan::PreGrContextSubmit() {
if (scoped_write_) {
if (LIKELY(scoped_write_)) {
auto& sk_surface =
sk_surface_size_pairs_[scoped_write_->image_index()].sk_surface;
DCHECK(sk_surface);
......@@ -116,14 +123,15 @@ void SkiaOutputDeviceVulkan::PostSubBuffer(
StartSwapBuffers(std::move(feedback));
if (is_new_swap_chain_ && rect == gfx::Rect(vulkan_surface_->image_size())) {
if (UNLIKELY(is_new_swap_chain_ &&
rect == gfx::Rect(vulkan_surface_->image_size()))) {
is_new_swap_chain_ = false;
}
if (!is_new_swap_chain_) {
if (LIKELY(!is_new_swap_chain_)) {
auto image_index = vulkan_surface_->swap_chain()->current_image_index();
for (size_t i = 0; i < damage_of_images_.size(); ++i) {
if (i == image_index) {
if (UNLIKELY(i == image_index)) {
damage_of_images_[i] = gfx::Rect();
} else {
damage_of_images_[i].Union(rect);
......@@ -131,7 +139,7 @@ void SkiaOutputDeviceVulkan::PostSubBuffer(
}
}
if (!rect.IsEmpty()) {
if (LIKELY(!rect.IsEmpty())) {
// If the swapchain is new created, but rect doesn't cover the whole buffer,
// we will still present it even it causes a artifact in this frame and
// recovered when the next frame is presented. We do that because the old
......@@ -154,18 +162,21 @@ SkSurface* SkiaOutputDeviceVulkan::BeginPaint(
DCHECK(!scoped_write_);
scoped_write_.emplace(vulkan_surface_->swap_chain());
if (!scoped_write_->success()) {
if (UNLIKELY(!scoped_write_->success())) {
scoped_write_.reset();
if (vulkan_surface_->swap_chain()->state() != VK_ERROR_SURFACE_LOST_KHR)
if (UNLIKELY(vulkan_surface_->swap_chain()->state() !=
VK_ERROR_SURFACE_LOST_KHR))
return nullptr;
auto result = RecreateSwapChain(vulkan_surface_->image_size(), color_space_,
vulkan_surface_->transform());
// If vulkan surface is lost, we will try to recreate swap chain.
if (!RecreateSwapChain(vulkan_surface_->image_size(), color_space_,
vulkan_surface_->transform())) {
if (UNLIKELY(!result)) {
LOG(DFATAL) << "Failed to recreate vulkan swap chain.";
return nullptr;
}
scoped_write_.emplace(vulkan_surface_->swap_chain());
if (!scoped_write_->success()) {
if (UNLIKELY(!scoped_write_->success())) {
scoped_write_.reset();
return nullptr;
}
......@@ -174,7 +185,7 @@ SkSurface* SkiaOutputDeviceVulkan::BeginPaint(
auto& sk_surface =
sk_surface_size_pairs_[scoped_write_->image_index()].sk_surface;
if (!sk_surface) {
if (UNLIKELY(!sk_surface)) {
SkSurfaceProps surface_props =
SkSurfaceProps(0, SkSurfaceProps::kLegacyFontHost_InitType);
const auto surface_format = vulkan_surface_->surface_format().format;
......@@ -213,15 +224,16 @@ SkSurface* SkiaOutputDeviceVulkan::BeginPaint(
SkSurface::kFlushRead_BackendHandleAccess);
backend.setVkImageLayout(scoped_write_->image_layout());
}
VkSemaphore vk_semaphore = scoped_write_->begin_semaphore();
if (vk_semaphore != VK_NULL_HANDLE) {
GrBackendSemaphore semaphore;
semaphore.initVulkan(vk_semaphore);
auto result =
sk_surface->wait(1, &semaphore, /*deleteSemaphoresAfterWait=*/false);
DCHECK(result);
}
VkSemaphore vk_semaphore = scoped_write_->begin_semaphore();
DCHECK(vk_semaphore != VK_NULL_HANDLE);
GrBackendSemaphore semaphore;
semaphore.initVulkan(vk_semaphore);
auto result =
sk_surface->wait(1, &semaphore, /*deleteSemaphoresAfterWait=*/false);
DCHECK(result);
DCHECK(scoped_write_->end_semaphore() != VK_NULL_HANDLE);
GrBackendSemaphore end_semaphore;
end_semaphore.initVulkan(scoped_write_->end_semaphore());
end_semaphores->push_back(std::move(end_semaphore));
......@@ -237,7 +249,7 @@ void SkiaOutputDeviceVulkan::EndPaint() {
auto backend = sk_surface->getBackendRenderTarget(
SkSurface::kFlushRead_BackendHandleAccess);
GrVkImageInfo vk_image_info;
if (!backend.getVkImageInfo(&vk_image_info))
if (UNLIKELY(!backend.getVkImageInfo(&vk_image_info)))
NOTREACHED() << "Failed to get the image info.";
DCHECK_EQ(vk_image_info.fImageLayout, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
scoped_write_.reset();
......@@ -259,12 +271,13 @@ bool SkiaOutputDeviceVulkan::Initialize() {
auto vulkan_surface =
context_provider_->GetVulkanImplementation()->CreateViewSurface(
accelerated_widget);
if (!vulkan_surface) {
if (UNLIKELY(!vulkan_surface)) {
LOG(ERROR) << "Failed to create vulkan surface.";
return false;
}
if (!vulkan_surface->Initialize(context_provider_->GetDeviceQueue(),
gpu::VulkanSurface::FORMAT_RGBA_32)) {
auto result = vulkan_surface->Initialize(context_provider_->GetDeviceQueue(),
gpu::VulkanSurface::FORMAT_RGBA_32);
if (UNLIKELY(!result)) {
LOG(ERROR) << "Failed to initialize vulkan surface.";
return false;
}
......@@ -304,11 +317,12 @@ bool SkiaOutputDeviceVulkan::RecreateSwapChain(
// Call vulkan_surface_->Reshape() will recreate vulkan swapchain if it is
// necessary.
if (!vulkan_surface_->Reshape(size, transform))
if (UNLIKELY(!vulkan_surface_->Reshape(size, transform)))
return false;
if (vulkan_surface_->swap_chain_generation() != generation ||
!SkColorSpace::Equals(color_space.get(), color_space_.get())) {
bool recreate = vulkan_surface_->swap_chain_generation() != generation ||
!SkColorSpace::Equals(color_space.get(), color_space_.get());
if (LIKELY(recreate)) {
// swapchain is changed, we need recreate all cached sk surfaces.
for (const auto& sk_surface_size_pair : sk_surface_size_pairs_) {
memory_type_tracker_->TrackMemFree(sk_surface_size_pair.bytes_allocated);
......@@ -329,7 +343,7 @@ bool SkiaOutputDeviceVulkan::RecreateSwapChain(
void SkiaOutputDeviceVulkan::OnPostSubBufferFinished(
std::vector<ui::LatencyInfo> latency_info,
gfx::SwapResult result) {
if (result == gfx::SwapResult::SWAP_ACK) {
if (LIKELY(result == gfx::SwapResult::SWAP_ACK)) {
auto image_index = vulkan_surface_->swap_chain()->current_image_index();
FinishSwapBuffers(gfx::SwapCompletionResult(result),
vulkan_surface_->image_size(), std::move(latency_info),
......
......@@ -5,6 +5,7 @@
#include "gpu/vulkan/vulkan_swap_chain.h"
#include "base/bind.h"
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
......@@ -85,18 +86,26 @@ void VulkanSwapChain::Destroy() {
WaitUntilPostSubBufferAsyncFinished();
VkDevice device = device_queue_->GetVulkanDevice();
for (auto& fence_and_semaphores : fence_and_semaphores_queue_) {
vkWaitForFences(device, 1, &fence_and_semaphores.fence, VK_TRUE,
UINT64_MAX);
vkDestroyFence(device, fence_and_semaphores.fence,
nullptr /* pAllocator */);
vkDestroySemaphore(device, fence_and_semaphores.semaphores[0],
nullptr /* pAllocator */);
vkDestroySemaphore(device, fence_and_semaphores.semaphores[1],
nullptr /* pAllocator */);
if (UNLIKELY(!fence_and_semaphores_queue_.empty())) {
VkDevice device = device_queue_->GetVulkanDevice();
{
// Make sure the last enqueued fence is passed, so we can release all
// other fences and semaphores safely.
base::ScopedBlockingCall scoped_blocking_call(
FROM_HERE, base::BlockingType::MAY_BLOCK);
vkWaitForFences(device, 1, &fence_and_semaphores_queue_.back().fence,
VK_TRUE, UINT64_MAX);
}
for (auto& fence_and_semaphores : fence_and_semaphores_queue_) {
vkDestroyFence(device, fence_and_semaphores.fence,
nullptr /* pAllocator */);
vkDestroySemaphore(device, fence_and_semaphores.semaphores[0],
nullptr /* pAllocator */);
vkDestroySemaphore(device, fence_and_semaphores.semaphores[1],
nullptr /* pAllocator */);
}
fence_and_semaphores_queue_.clear();
}
fence_and_semaphores_queue_.clear();
DCHECK(!is_writing_);
DestroySwapImages();
......@@ -108,10 +117,10 @@ gfx::SwapResult VulkanSwapChain::PostSubBuffer(const gfx::Rect& rect) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(!has_pending_post_sub_buffer_);
if (!PresentBuffer(rect))
if (UNLIKELY(!PresentBuffer(rect)))
return gfx::SwapResult::SWAP_FAILED;
if (!AcquireNextImage())
if (UNLIKELY(!AcquireNextImage()))
return gfx::SwapResult::SWAP_FAILED;
return gfx::SwapResult::SWAP_ACK;
......@@ -124,7 +133,7 @@ void VulkanSwapChain::PostSubBufferAsync(
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(!has_pending_post_sub_buffer_);
if (!PresentBuffer(rect)) {
if (UNLIKELY(!PresentBuffer(rect))) {
task_runner_->PostTask(
FROM_HERE,
base::BindOnce(std::move(callback), gfx::SwapResult::SWAP_FAILED));
......@@ -183,7 +192,7 @@ bool VulkanSwapChain::InitializeSwapChain(
.oldSwapchain = VK_NULL_HANDLE,
};
if (old_swap_chain) {
if (LIKELY(old_swap_chain)) {
base::AutoLock auto_lock(old_swap_chain->lock_);
old_swap_chain->WaitUntilPostSubBufferAsyncFinished();
swap_chain_create_info.oldSwapchain = old_swap_chain->swap_chain_;
......@@ -199,13 +208,13 @@ bool VulkanSwapChain::InitializeSwapChain(
result = vkCreateSwapchainKHR(device, &swap_chain_create_info, nullptr,
&new_swap_chain);
if (old_swap_chain) {
if (LIKELY(old_swap_chain)) {
auto* fence_helper = device_queue_->GetFenceHelper();
fence_helper->EnqueueVulkanObjectCleanupForSubmittedWork(
std::move(old_swap_chain));
}
if (VK_SUCCESS != result) {
if (UNLIKELY(VK_SUCCESS != result)) {
LOG(FATAL) << "vkCreateSwapchainKHR() failed: " << result;
return false;
}
......@@ -214,7 +223,7 @@ bool VulkanSwapChain::InitializeSwapChain(
size_ = gfx::Size(swap_chain_create_info.imageExtent.width,
swap_chain_create_info.imageExtent.height);
if (!post_sub_buffer_task_runner_) {
if (UNLIKELY(!post_sub_buffer_task_runner_)) {
post_sub_buffer_task_runner_ = base::ThreadPool::CreateSequencedTaskRunner(
{base::TaskPriority::USER_BLOCKING,
base::TaskShutdownBehavior::BLOCK_SHUTDOWN, base::MayBlock()});
......@@ -239,7 +248,7 @@ bool VulkanSwapChain::InitializeSwapImages(
uint32_t image_count = 0;
result = vkGetSwapchainImagesKHR(device, swap_chain_, &image_count, nullptr);
if (VK_SUCCESS != result) {
if (UNLIKELY(VK_SUCCESS != result)) {
LOG(FATAL) << "vkGetSwapchainImagesKHR(nullptr) failed: " << result;
return false;
}
......@@ -247,7 +256,7 @@ bool VulkanSwapChain::InitializeSwapImages(
std::vector<VkImage> images(image_count);
result =
vkGetSwapchainImagesKHR(device, swap_chain_, &image_count, images.data());
if (VK_SUCCESS != result) {
if (UNLIKELY(VK_SUCCESS != result)) {
LOG(FATAL) << "vkGetSwapchainImagesKHR(images) failed: " << result;
return false;
}
......@@ -287,15 +296,15 @@ bool VulkanSwapChain::BeginWriteCurrentImage(VkImage* image,
DCHECK(end_semaphore);
DCHECK(!is_writing_);
if (state_ != VK_SUCCESS)
if (UNLIKELY(state_ != VK_SUCCESS))
return false;
if (!acquired_image_)
if (UNLIKELY(!acquired_image_))
return false;
auto& current_image_data = images_[*acquired_image_];
if (!new_acquired_) {
if (UNLIKELY(!new_acquired_)) {
// In this case, {Begin,End}WriteCurrentImage has been called, but
// PostSubBuffer() is not call, so |acquire_semaphore| has been wait on for
// the previous write request, release it with FenceHelper.
......@@ -306,7 +315,7 @@ bool VulkanSwapChain::BeginWriteCurrentImage(VkImage* image,
current_image_data.acquire_semaphore = current_image_data.present_semaphore;
current_image_data.present_semaphore =
CreateSemaphore(device_queue_->GetVulkanDevice());
if (current_image_data.present_semaphore == VK_NULL_HANDLE)
if (UNLIKELY(current_image_data.present_semaphore == VK_NULL_HANDLE))
return false;
}
......@@ -369,7 +378,7 @@ bool VulkanSwapChain::PresentBuffer(const gfx::Rect& rect) {
VkQueue queue = device_queue_->GetVulkanQueue();
auto result = vkQueuePresentKHR(queue, &present_info);
if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) {
if (UNLIKELY(result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR)) {
LOG(DFATAL) << "vkQueuePresentKHR() failed: " << result;
state_ = result;
return false;
......@@ -409,7 +418,7 @@ bool VulkanSwapChain::AcquireNextImage() {
// TODO(penghuang): make VulkanDeviceQueue threadsafe.
VkDevice device = device_queue_->GetVulkanDevice();
auto fence_and_semaphores = GetOrCreateFenceAndSemaphores();
if (fence_and_semaphores.fence == VK_NULL_HANDLE) {
if (UNLIKELY(fence_and_semaphores.fence == VK_NULL_HANDLE)) {
DCHECK(fence_and_semaphores.semaphores[0] == VK_NULL_HANDLE);
DCHECK(fence_and_semaphores.semaphores[1] == VK_NULL_HANDLE);
return false;
......@@ -424,12 +433,12 @@ bool VulkanSwapChain::AcquireNextImage() {
uint32_t next_image;
auto result = ({
base::ScopedBlockingCall scoped_blocking_call(
FROM_HERE, base::BlockingType::WILL_BLOCK);
FROM_HERE, base::BlockingType::MAY_BLOCK);
vkAcquireNextImageKHR(device, swap_chain_, kTimeout, acquire_semaphore,
acquire_fence, &next_image);
});
if (result == VK_TIMEOUT) {
if (UNLIKELY(result == VK_TIMEOUT)) {
LOG(ERROR) << "vkAcquireNextImageKHR() hangs.";
vkDestroySemaphore(device, acquire_semaphore, nullptr);
vkDestroySemaphore(device, present_semaphore, nullptr);
......@@ -438,7 +447,7 @@ bool VulkanSwapChain::AcquireNextImage() {
return false;
}
if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) {
if (UNLIKELY(result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR)) {
LOG(DFATAL) << "vkAcquireNextImageKHR() failed: " << result;
vkDestroySemaphore(device, acquire_semaphore, nullptr);
vkDestroySemaphore(device, present_semaphore, nullptr);
......@@ -481,13 +490,13 @@ VulkanSwapChain::GetOrCreateFenceAndSemaphores() {
VkDevice device = device_queue_->GetVulkanDevice();
FenceAndSemaphores fence_and_semaphores;
do {
if (!fence_and_semaphores_queue_.empty()) {
if (LIKELY(!fence_and_semaphores_queue_.empty())) {
fence_and_semaphores = fence_and_semaphores_queue_.front();
auto result = vkGetFenceStatus(device, fence_and_semaphores.fence);
if (result == VK_SUCCESS) {
if (LIKELY(result == VK_SUCCESS)) {
fence_and_semaphores_queue_.pop_front();
vkResetFences(device, 1, &fence_and_semaphores.fence);
} else if (result == VK_NOT_READY) {
} else if (LIKELY(result == VK_NOT_READY)) {
// If fence is not passed, new fence and semaphores will be created.
fence_and_semaphores = {};
} else {
......@@ -497,7 +506,7 @@ VulkanSwapChain::GetOrCreateFenceAndSemaphores() {
}
}
if (fence_and_semaphores.fence == VK_NULL_HANDLE) {
if (UNLIKELY(fence_and_semaphores.fence == VK_NULL_HANDLE)) {
constexpr VkFenceCreateInfo fence_create_info = {
.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
};
......@@ -510,13 +519,13 @@ VulkanSwapChain::GetOrCreateFenceAndSemaphores() {
}
}
if (fence_and_semaphores.semaphores[0] == VK_NULL_HANDLE)
if (UNLIKELY(fence_and_semaphores.semaphores[0] == VK_NULL_HANDLE))
fence_and_semaphores.semaphores[0] = CreateSemaphore(device);
if (fence_and_semaphores.semaphores[1] == VK_NULL_HANDLE)
if (UNLIKELY(fence_and_semaphores.semaphores[1] == VK_NULL_HANDLE))
fence_and_semaphores.semaphores[1] = CreateSemaphore(device);
if (fence_and_semaphores.semaphores[0] == VK_NULL_HANDLE ||
fence_and_semaphores.semaphores[1] == VK_NULL_HANDLE) {
if (UNLIKELY(fence_and_semaphores.semaphores[0] == VK_NULL_HANDLE ||
fence_and_semaphores.semaphores[1] == VK_NULL_HANDLE)) {
break;
}
......@@ -543,7 +552,7 @@ VulkanSwapChain::ScopedWrite::ScopedWrite(VulkanSwapChain* swap_chain)
success_ = swap_chain_->BeginWriteCurrentImage(
&image_, &image_index_, &image_layout_, &begin_semaphore_,
&end_semaphore_);
if (success_) {
if (LIKELY(success_)) {
DCHECK(begin_semaphore_ != VK_NULL_HANDLE);
DCHECK(end_semaphore_ != VK_NULL_HANDLE);
} else {
......@@ -553,7 +562,7 @@ VulkanSwapChain::ScopedWrite::ScopedWrite(VulkanSwapChain* swap_chain)
}
VulkanSwapChain::ScopedWrite::~ScopedWrite() {
if (success_) {
if (LIKELY(success_)) {
DCHECK(begin_semaphore_ != VK_NULL_HANDLE);
DCHECK(end_semaphore_ != VK_NULL_HANDLE);
swap_chain_->EndWriteCurrentImage();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment