回退vulkan shell提交

Signed-off-by: 凯鑫 <liukaixin@huawei.com>
This commit is contained in:
凯鑫 2023-12-27 10:29:31 +08:00
parent 91a856ed0d
commit 9915ae2b46
35 changed files with 5 additions and 3998 deletions

View File

@ -44,19 +44,6 @@ ohos_executable("drawing_engine_sample") {
if (ace_enable_gpu) {
if (graphic_2d_feature_enable_vulkan) {
sources += [
"$graphic_2d_root/utils/vulkan_shell/vulkan_application.cpp",
"$graphic_2d_root/utils/vulkan_shell/vulkan_backbuffer.cpp",
"$graphic_2d_root/utils/vulkan_shell/vulkan_command_buffer.cpp",
"$graphic_2d_root/utils/vulkan_shell/vulkan_debug_report.cpp",
"$graphic_2d_root/utils/vulkan_shell/vulkan_device.cpp",
"$graphic_2d_root/utils/vulkan_shell/vulkan_image.cpp",
"$graphic_2d_root/utils/vulkan_shell/vulkan_interface.cpp",
"$graphic_2d_root/utils/vulkan_shell/vulkan_native_surface_ohos.cpp",
"$graphic_2d_root/utils/vulkan_shell/vulkan_proc_table.cpp",
"$graphic_2d_root/utils/vulkan_shell/vulkan_surface.cpp",
"$graphic_2d_root/utils/vulkan_shell/vulkan_swapchain.cpp",
"$graphic_2d_root/utils/vulkan_shell/vulkan_utilities.cpp",
"$graphic_2d_root/utils/vulkan_shell/vulkan_window.cpp",
"drawing_engine/drawing_surface/surface_frame_ohos_vulkan.cpp",
"drawing_engine/drawing_surface/surface_ohos_vulkan.cpp",
"drawing_engine/vulkan_render_backend.cpp",
@ -121,18 +108,8 @@ ohos_executable("drawing_engine_sample") {
deps += [ "$graphic_2d_root/rosen/modules/2d_graphics:2d_graphics" ]
}
defines += [
"VK_USE_PLATFORM_OHOS",
"NDEBUG",
]
if (graphic_2d_feature_enable_vulkan) {
include_dirs += [
"$graphic_2d_root/utils/vulkan_shell",
"$graphic_2d_root/frameworks/surface/include",
"$graphic_2d_root/rosen/modules/2d_graphics/include",
"$graphic_2d_root/interfaces/inner_api/surface",
"//third_party/skia",
]
if (graphic_2d_feature_enable_flutter_vulkan) {
include_dirs += [ "//third_party/flutter/engine/flutter/vulkan" ]
}
public_deps += [
"$graphic_2d_root:libvulkan",

View File

@ -95,8 +95,8 @@ std::unique_ptr<SurfaceFrame> SurfaceOhosVulkan::RequestFrame(int32_t width, int
}
if (mVulkanWindow_ == nullptr) {
auto vulkan_surface_ohos = std::make_unique<vulkan::RSVulkanNativeSurfaceOHOS>(mNativeWindow_);
mVulkanWindow_ = new vulkan::RSVulkanWindow(std::move(vulkan_surface_ohos));
auto vulkan_surface_ohos = std::make_unique<vulkan::VulkanNativeSurfaceOHOS>(mNativeWindow_);
mVulkanWindow_ = new vulkan::VulkanWindow(std::move(vulkan_surface_ohos));
}
surface_ = std::make_shared<Drawing::Surface>();

View File

@ -57,7 +57,7 @@ private:
#endif
std::unique_ptr<SurfaceFrameOhosVulkan> frame_;
struct NativeWindow *mNativeWindow_ = nullptr;
vulkan::RSVulkanWindow *mVulkanWindow_ = nullptr;
vulkan::VulkanWindow *mVulkanWindow_ = nullptr;
#ifdef ENABLE_NATIVEBUFFER
std::list<NativeWindowBuffer*> surfaceList_;
std::unordered_map<NativeWindowBuffer*, NativeBufferUtils::NativeSurfaceInfo> surfaceMap_;

View File

@ -1,110 +0,0 @@
#
# Copyright (c) 2023 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import("//build/ohos.gni")
import("//foundation/graphic/graphic_2d/graphic_config.gni")
if (graphic_2d_feature_enable_vulkan) {
config("vulkan_shell_config") {
visibility = [ ":*" ]
include_dirs = [
"vulkan_application.h",
"vulkan_backbuffer.h",
"vulkan_command_buffer.h",
"vulkan_debug_report.h",
"vulkan_device.h",
"vulkan_handle.h",
"vulkan_hilog.h",
"vulkan_image.h",
"vulkan_interface.h",
"vulkan_native_surface.h",
"vulkan_native_surface_ohos.h",
"vulkan_proc_table.h",
"vulkan_provider.h",
"vulkan_surface.h",
"vulkan_swapchain.h",
"vulkan_utilities.h",
"vulkan_window.h",
]
cflags = [
"-Wall",
"-Wno-unused-function",
"-Wno-unused-variable",
"-Wno-missing-braces",
"-Wno-unused-private-field",
"-Werror",
"-g3",
]
}
config("vulkan_shell_public_config") {
include_dirs = [
"$graphic_2d_root/frameworks/surface/include",
"$graphic_2d_root/rosen/modules/2d_graphics/include",
"$graphic_2d_root/interfaces/inner_api/surface",
"//third_party/skia",
]
cflags = [ "-Wno-error=deprecated-declarations" ]
defines = [
"VK_USE_PLATFORM_OHOS",
"NDEBUG",
]
}
ohos_shared_library("vulkan_shell") {
sources = [
"vulkan_application.cpp",
"vulkan_backbuffer.cpp",
"vulkan_command_buffer.cpp",
"vulkan_debug_report.cpp",
"vulkan_device.cpp",
"vulkan_image.cpp",
"vulkan_interface.cpp",
"vulkan_native_surface_ohos.cpp",
"vulkan_proc_table.cpp",
"vulkan_surface.cpp",
"vulkan_swapchain.cpp",
"vulkan_utilities.cpp",
"vulkan_window.cpp",
]
if (graphic_2d_feature_enable_vulkan) {
defines = [ "RS_ENABLE_VK" ]
}
configs = [ ":vulkan_shell_config" ]
public_configs = [ ":vulkan_shell_public_config" ]
external_deps = [
"c_utils:utils",
"hilog:libhilog",
]
public_deps = [
"$graphic_2d_root:libsurface",
"$graphic_2d_root/frameworks/vulkan_layers:vulkan_swapchain_layer",
"//third_party/skia:skia_ohos",
"//third_party/vulkan-headers:vulkan_headers",
]
part_name = "graphic_2d"
subsystem_name = "graphic"
}
}

View File

@ -1,207 +0,0 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "vulkan_application.h"
#include <utility>
#include <vector>
#include "vulkan_device.h"
#include "vulkan_hilog.h"
#include "vulkan_proc_table.h"
#include "vulkan_utilities.h"
namespace OHOS::Rosen::vulkan {
RSVulkanApplication::RSVulkanApplication(RSVulkanProcTable& procVk, const std::string& applicationName,
std::vector<std::string> enabledExtensions, uint32_t applicationVersion, uint32_t apiVersion)
: vk_(procVk), apiVersion_(apiVersion), valid_(false)
{
std::vector<VkExtensionProperties> supportedExtensions = GetSupportedInstanceExtensions(vk_);
bool enableInstanceDebugging =
IsDebuggingEnabled() && ExtensionSupported(supportedExtensions, RSVulkanDebugReport::DebugExtensionName());
if (enableInstanceDebugging) {
enabledExtensions.emplace_back(RSVulkanDebugReport::DebugExtensionName());
}
const char* extensions[enabledExtensions.size()];
for (size_t i = 0; i < enabledExtensions.size(); i++) {
extensions[i] = enabledExtensions[i].c_str();
}
const std::vector<std::string> enabledLayers = InstanceLayersToEnable(vk_);
const char* layers[enabledLayers.size()];
for (size_t i = 0; i < enabledLayers.size(); i++) {
layers[i] = enabledLayers[i].c_str();
}
const VkApplicationInfo info = {
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
.pNext = nullptr,
.pApplicationName = applicationName.c_str(),
.applicationVersion = applicationVersion,
.pEngineName = "Rosen",
.engineVersion = VK_MAKE_VERSION(1, 0, 0),
.apiVersion = apiVersion_,
};
const VkInstanceCreateInfo createInfo = {
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.pApplicationInfo = &info,
.enabledLayerCount = static_cast<uint32_t>(enabledLayers.size()),
.ppEnabledLayerNames = layers,
.enabledExtensionCount = static_cast<uint32_t>(enabledExtensions.size()),
.ppEnabledExtensionNames = extensions,
};
VkInstance instance = VK_NULL_HANDLE;
if (VK_CALL_LOG_ERROR(vk_.CreateInstance(&createInfo, nullptr, &instance)) != VK_SUCCESS) {
LOGE("Could not create application instance.");
return;
}
if (!vk_.SetupInstanceProcAddresses(instance)) {
LOGE("Could not setup instance proc addresses.");
return;
}
instance_ = { instance, [this](VkInstance i) {
LOGI("Destroying Vulkan instance");
vk_.DestroyInstance(i, nullptr);
} };
if (enableInstanceDebugging) {
auto debug_report = std::make_unique<RSVulkanDebugReport>(vk_, instance_);
if (!debug_report->IsValid()) {
LOGE("Vulkan debugging was enabled but could not be setup for this instance.");
} else {
debugReport_ = std::move(debug_report);
LOGI("Debug reporting is enabled.");
}
}
valid_ = true;
}
RSVulkanApplication::~RSVulkanApplication() = default;
bool RSVulkanApplication::IsValid() const
{
return valid_;
}
uint32_t RSVulkanApplication::GetAPIVersion() const
{
return apiVersion_;
}
const RSVulkanHandle<VkInstance>& RSVulkanApplication::GetInstance() const
{
return instance_;
}
void RSVulkanApplication::ReleaseInstanceOwnership()
{
instance_.ReleaseOwnership();
}
std::vector<VkPhysicalDevice> RSVulkanApplication::GetPhysicalDevices() const
{
if (!IsValid()) {
return {};
}
uint32_t deviceCount = 0;
if (VK_CALL_LOG_ERROR(vk_.EnumeratePhysicalDevices(instance_, &deviceCount, nullptr)) != VK_SUCCESS) {
LOGE("Could not enumerate physical device.");
return {};
}
if (deviceCount == 0) {
// No available devices.
LOGE("No physical devices found.");
return {};
}
std::vector<VkPhysicalDevice> physical_devices;
physical_devices.resize(deviceCount);
if (VK_CALL_LOG_ERROR(vk_.EnumeratePhysicalDevices(instance_, &deviceCount, physical_devices.data())) !=
VK_SUCCESS) {
LOGE("Could not enumerate physical device.");
return {};
}
return physical_devices;
}
std::unique_ptr<RSVulkanDevice> RSVulkanApplication::AcquireFirstCompatibleLogicalDevice() const
{
for (auto device_handle : GetPhysicalDevices()) {
auto logical_device = std::make_unique<RSVulkanDevice>(vk_, device_handle);
if (logical_device->IsValid()) {
return logical_device;
}
}
LOGE("Could not acquire compatible logical device.");
return nullptr;
}
std::vector<VkExtensionProperties> RSVulkanApplication::GetSupportedInstanceExtensions(
const RSVulkanProcTable& vk) const
{
if (!vk.EnumerateInstanceExtensionProperties) {
return std::vector<VkExtensionProperties>();
}
uint32_t count = 0;
if (VK_CALL_LOG_ERROR(vk.EnumerateInstanceExtensionProperties(nullptr, &count, nullptr)) != VK_SUCCESS) {
return std::vector<VkExtensionProperties>();
}
if (count == 0) {
return std::vector<VkExtensionProperties>();
}
std::vector<VkExtensionProperties> properties;
properties.resize(count);
if (VK_CALL_LOG_ERROR(vk.EnumerateInstanceExtensionProperties(nullptr, &count, properties.data())) != VK_SUCCESS) {
return std::vector<VkExtensionProperties>();
}
return properties;
}
bool RSVulkanApplication::ExtensionSupported(
const std::vector<VkExtensionProperties>& supportedInstanceExtensions, std::string extensionName)
{
uint32_t count = supportedInstanceExtensions.size();
for (size_t i = 0; i < count; i++) {
if (strncmp(supportedInstanceExtensions[i].extensionName, extensionName.c_str(), extensionName.size()) == 0) {
return true;
}
}
return false;
}
} // namespace OHOS::Rosen::vulkan

View File

@ -1,65 +0,0 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef RS_VULKAN_VULKAN_APPLICATION_H_
#define RS_VULKAN_VULKAN_APPLICATION_H_
#include <memory>
#include <string>
#include <vector>
#include "vulkan_debug_report.h"
#include "vulkan_handle.h"
namespace OHOS::Rosen::vulkan {
class RSVulkanDevice;
class RSVulkanProcTable;
/// Applications using Vulkan acquire a RSVulkanApplication that attempts to
/// create a VkInstance (with debug reporting optionally enabled).
class RSVulkanApplication {
public:
RSVulkanApplication(RSVulkanProcTable& vk, const std::string& applicationName,
std::vector<std::string> enabledExtensions, uint32_t applicationVersion = VK_MAKE_VERSION(1, 0, 0),
uint32_t apiVersion = VK_MAKE_VERSION(1, 0, 0));
~RSVulkanApplication();
bool IsValid() const;
uint32_t GetAPIVersion() const;
const RSVulkanHandle<VkInstance>& GetInstance() const;
void ReleaseInstanceOwnership();
std::unique_ptr<RSVulkanDevice> AcquireFirstCompatibleLogicalDevice() const;
private:
RSVulkanProcTable& vk_;
RSVulkanHandle<VkInstance> instance_;
uint32_t apiVersion_ = 0;
std::unique_ptr<RSVulkanDebugReport> debugReport_;
bool valid_ = false;
std::vector<VkPhysicalDevice> GetPhysicalDevices() const;
std::vector<VkExtensionProperties> GetSupportedInstanceExtensions(const RSVulkanProcTable& vk) const;
bool ExtensionSupported(const std::vector<VkExtensionProperties>& supportedExtensions, std::string extensionName);
};
} // namespace OHOS::Rosen::vulkan
#endif // RS_VULKAN_VULKAN_APPLICATION_H_

View File

@ -1,159 +0,0 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "vulkan_backbuffer.h"
#include <limits>
#include "include/gpu/vk/GrVkTypes.h"
#include "vulkan/vulkan.h"
#include "vulkan_hilog.h"
#include "vulkan_proc_table.h"
namespace OHOS::Rosen::vulkan {
RSVulkanBackbuffer::RSVulkanBackbuffer(
const RSVulkanProcTable& procVk, const RSVulkanHandle<VkDevice>& device, const RSVulkanHandle<VkCommandPool>& pool)
: vk_(procVk), device_(device), usageCommandBuffer_(procVk, device, pool),
renderCommandBuffer_(procVk, device, pool), valid_(false)
{
if (!usageCommandBuffer_.IsValid() || !renderCommandBuffer_.IsValid()) {
LOGE("Command buffers were not valid.");
return;
}
if (!CreateSemaphores()) {
LOGE("Could not create semaphores.");
return;
}
if (!CreateFences()) {
LOGE("Could not create fences.");
return;
}
valid_ = true;
}
RSVulkanBackbuffer::~RSVulkanBackbuffer()
{
WaitFences();
}
bool RSVulkanBackbuffer::IsValid() const
{
return valid_;
}
bool RSVulkanBackbuffer::CreateSemaphores()
{
const VkSemaphoreCreateInfo createInfo = {
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
};
auto semaphoreCollect = [this](VkSemaphore semaphore) { vk_.DestroySemaphore(device_, semaphore, nullptr); };
for (size_t i = 0; i < semaphores_.size(); i++) {
VkSemaphore semaphore = VK_NULL_HANDLE;
if (VK_CALL_LOG_ERROR(vk_.CreateSemaphore(device_, &createInfo, nullptr, &semaphore)) != VK_SUCCESS) {
return false;
}
semaphores_[i] = { semaphore, semaphoreCollect };
}
return true;
}
bool RSVulkanBackbuffer::CreateFences()
{
const VkFenceCreateInfo createInfo = {
.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
.pNext = nullptr,
.flags = VK_FENCE_CREATE_SIGNALED_BIT,
};
auto fenceCollect = [this](VkFence fence) { vk_.DestroyFence(device_, fence, nullptr); };
for (size_t i = 0; i < useFences_.size(); i++) {
VkFence fence = VK_NULL_HANDLE;
if (VK_CALL_LOG_ERROR(vk_.CreateFence(device_, &createInfo, nullptr, &fence)) != VK_SUCCESS) {
return false;
}
useFences_[i] = { fence, fenceCollect };
}
return true;
}
bool RSVulkanBackbuffer::WaitFences()
{
VkFence fences[useFences_.size()];
for (size_t i = 0; i < useFences_.size(); i++) {
fences[i] = useFences_[i];
}
VkResult result = VK_CALL_LOG_ERROR(vk_.WaitForFences(
device_, static_cast<uint32_t>(useFences_.size()), fences, true, std::numeric_limits<uint64_t>::max()));
return result == VK_SUCCESS;
}
bool RSVulkanBackbuffer::ResetFences()
{
VkFence fences[useFences_.size()];
for (size_t i = 0; i < useFences_.size(); i++) {
fences[i] = useFences_[i];
}
return VK_CALL_LOG_ERROR(vk_.ResetFences(device_, static_cast<uint32_t>(useFences_.size()), fences)) == VK_SUCCESS;
}
const RSVulkanHandle<VkFence>& RSVulkanBackbuffer::GetUsageFence() const
{
return useFences_[0];
}
const RSVulkanHandle<VkFence>& RSVulkanBackbuffer::GetRenderFence() const
{
return useFences_[1];
}
const RSVulkanHandle<VkSemaphore>& RSVulkanBackbuffer::GetUsageSemaphore() const
{
return semaphores_[0];
}
const RSVulkanHandle<VkSemaphore>& RSVulkanBackbuffer::GetRenderSemaphore() const
{
return semaphores_[1];
}
RSVulkanCommandBuffer& RSVulkanBackbuffer::GetUsageCommandBuffer()
{
return usageCommandBuffer_;
}
RSVulkanCommandBuffer& RSVulkanBackbuffer::GetRenderCommandBuffer()
{
return renderCommandBuffer_;
}
} // namespace OHOS::Rosen::vulkan

View File

@ -1,88 +0,0 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef RS_VULKAN_VULKAN_BACKBUFFER_H_
#define RS_VULKAN_VULKAN_BACKBUFFER_H_
#include <array>
#include "include/core/SkSize.h"
#include "include/core/SkSurface.h"
#include "vulkan_command_buffer.h"
#include "vulkan_handle.h"
namespace OHOS::Rosen::vulkan {
class RSVulkanBackbuffer {
public:
RSVulkanBackbuffer(
const RSVulkanProcTable& vk, const RSVulkanHandle<VkDevice>& device, const RSVulkanHandle<VkCommandPool>& pool);
~RSVulkanBackbuffer();
bool IsValid() const;
bool WaitFences();
bool ResetFences();
const RSVulkanHandle<VkFence>& GetUsageFence() const;
const RSVulkanHandle<VkFence>& GetRenderFence() const;
const RSVulkanHandle<VkSemaphore>& GetUsageSemaphore() const;
const RSVulkanHandle<VkSemaphore>& GetRenderSemaphore() const;
RSVulkanCommandBuffer& GetUsageCommandBuffer();
RSVulkanCommandBuffer& GetRenderCommandBuffer();
void SetMultiThreading()
{
multiThreading_ = true;
}
void UnsetMultiThreading()
{
multiThreading_ = false;
}
bool IsMultiThreading()
{
return multiThreading_;
}
private:
const RSVulkanProcTable& vk_;
const RSVulkanHandle<VkDevice>& device_;
static const size_t SEMAPHORE_SIZE = 2;
static const size_t FENCE_SIZE = 2;
std::array<RSVulkanHandle<VkSemaphore>, SEMAPHORE_SIZE> semaphores_;
std::array<RSVulkanHandle<VkFence>, FENCE_SIZE> useFences_;
RSVulkanCommandBuffer usageCommandBuffer_;
RSVulkanCommandBuffer renderCommandBuffer_;
bool valid_ = false;
bool CreateSemaphores();
bool CreateFences();
bool multiThreading_ = false;
};
} // namespace OHOS::Rosen::vulkan
#endif // RS_VULKAN_VULKAN_BACKBUFFER_H_

View File

@ -1,90 +0,0 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "vulkan_command_buffer.h"
#include "vulkan_hilog.h"
#include "vulkan_proc_table.h"
namespace OHOS::Rosen::vulkan {
RSVulkanCommandBuffer::RSVulkanCommandBuffer(
const RSVulkanProcTable& procVk, const RSVulkanHandle<VkDevice>& device, const RSVulkanHandle<VkCommandPool>& pool)
: vk_(procVk), device_(device), commandPool_(pool), valid_(false)
{
const VkCommandBufferAllocateInfo allocateInfo = {
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
.pNext = nullptr,
.commandPool = commandPool_,
.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
.commandBufferCount = 1,
};
VkCommandBuffer commandBuffer = VK_NULL_HANDLE;
if (VK_CALL_LOG_ERROR(vk_.AllocateCommandBuffers(device_, &allocateInfo, &commandBuffer)) != VK_SUCCESS) {
LOGE("Could not allocate command buffers.");
return;
}
auto bufferCollect = [this](VkCommandBuffer commandBuffer) {
vk_.FreeCommandBuffers(device_, commandPool_, 1, &commandBuffer);
};
handle_ = { commandBuffer, bufferCollect };
valid_ = true;
}
RSVulkanCommandBuffer::~RSVulkanCommandBuffer() = default;
bool RSVulkanCommandBuffer::IsValid() const
{
return valid_;
}
VkCommandBuffer RSVulkanCommandBuffer::Handle() const
{
return handle_;
}
bool RSVulkanCommandBuffer::Begin() const
{
const VkCommandBufferBeginInfo commandBufferBeginInfo {
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
.pNext = nullptr,
.flags = 0,
.pInheritanceInfo = nullptr,
};
return VK_CALL_LOG_ERROR(vk_.BeginCommandBuffer(handle_, &commandBufferBeginInfo)) == VK_SUCCESS;
}
bool RSVulkanCommandBuffer::End() const
{
return VK_CALL_LOG_ERROR(vk_.EndCommandBuffer(handle_)) == VK_SUCCESS;
}
bool RSVulkanCommandBuffer::InsertPipelineBarrier(VkPipelineStageFlagBits srcStageFlags,
VkPipelineStageFlagBits destStageFlags, uint32_t dependencyFlags,
uint32_t memoryBarrierCount, const VkMemoryBarrier* memoryBarriers, uint32_t bufferMemoryBarrierCount,
const VkBufferMemoryBarrier* bufferMemoryBarriers, uint32_t imageMemoryBarrierCount,
const VkImageMemoryBarrier* imageMemoryBarriers) const
{
vk_.CmdPipelineBarrier(handle_, srcStageFlags, destStageFlags, dependencyFlags, memoryBarrierCount, memoryBarriers,
bufferMemoryBarrierCount, bufferMemoryBarriers, imageMemoryBarrierCount, imageMemoryBarriers);
return true;
}
} // namespace OHOS::Rosen::vulkan

View File

@ -1,56 +0,0 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef RS_VULKAN_VULKAN_COMMAND_BUFFER_H_
#define RS_VULKAN_VULKAN_COMMAND_BUFFER_H_
#include "vulkan_handle.h"
namespace OHOS::Rosen::vulkan {
class RSVulkanProcTable;
class RSVulkanCommandBuffer {
public:
RSVulkanCommandBuffer(const RSVulkanProcTable& vk, const RSVulkanHandle<VkDevice>& device,
const RSVulkanHandle<VkCommandPool>& pool);
~RSVulkanCommandBuffer();
bool IsValid() const;
VkCommandBuffer Handle() const;
bool Begin() const;
bool End() const;
bool InsertPipelineBarrier(VkPipelineStageFlagBits srcStageFlags, VkPipelineStageFlagBits destStageFlags,
uint32_t dependencyFlags, uint32_t memoryBarrierCount,
const VkMemoryBarrier* memoryBarriers, uint32_t bufferMemoryBarrierCount,
const VkBufferMemoryBarrier* bufferMemoryBarriers, uint32_t imageMemoryBarrierCount,
const VkImageMemoryBarrier* imageMemoryBarriers) const;
private:
const RSVulkanProcTable& vk_;
const RSVulkanHandle<VkDevice>& device_;
const RSVulkanHandle<VkCommandPool>& commandPool_;
RSVulkanHandle<VkCommandBuffer> handle_;
bool valid_;
};
} // namespace OHOS::Rosen::vulkan
#endif // RS_VULKAN_VULKAN_COMMAND_BUFFER_H_

View File

@ -1,198 +0,0 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "vulkan_debug_report.h"
#include <iomanip>
#include <vector>
#include "vulkan_utilities.h"
namespace OHOS::Rosen::vulkan {
static const VkDebugReportFlagsEXT kVulkanErrorFlags =
VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT | VK_DEBUG_REPORT_ERROR_BIT_EXT;
static const VkDebugReportFlagsEXT kVulkanInfoFlags =
VK_DEBUG_REPORT_INFORMATION_BIT_EXT | VK_DEBUG_REPORT_DEBUG_BIT_EXT;
std::string RSVulkanDebugReport::DebugExtensionName()
{
return VK_EXT_DEBUG_REPORT_EXTENSION_NAME;
}
static const char* VkDebugReportFlagsEXTToString(VkDebugReportFlagsEXT reportFlags)
{
if (reportFlags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT) {
return "Flag: Information";
} else if (reportFlags & VK_DEBUG_REPORT_WARNING_BIT_EXT) {
return "Flag: Warning";
} else if (reportFlags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) {
return "Flag: Performance Warning";
} else if (reportFlags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
return "Flag: Error";
} else if (reportFlags & VK_DEBUG_REPORT_DEBUG_BIT_EXT) {
return "Flag: Debug";
}
return "Flag: UNKNOWN";
}
static const char* VkDebugReportObjectTypeEXTToString(VkDebugReportObjectTypeEXT type)
{
switch (type) {
case VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT:
return "Type: Unknown";
case VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT:
return "Type: Instance";
case VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT:
return "Type: Physical Device";
case VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT:
return "Type: Device";
case VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT:
return "Type: Queue";
case VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT:
return "Type: Semaphore";
case VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT:
return "Type: Command Buffer";
case VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT:
return "Type: Fence";
case VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT:
return "Type: Device Memory";
case VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT:
return "Type: Buffer";
case VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT:
return "Type: Image";
case VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT:
return "Type: Event";
case VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT:
return "Type: Query Pool";
case VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT:
return "Type: Buffer View";
case VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT:
return "Type: Image_view";
case VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT:
return "Type: Shader Module";
case VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_CACHE_EXT:
return "Type: Pipeline Cache";
case VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_LAYOUT_EXT:
return "Type: Pipeline Layout";
case VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT:
return "Type: Render Pass";
case VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT:
return "Type: Pipeline";
case VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT:
return "Type: Descriptor Set Layout";
case VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT:
return "Type: Sampler";
case VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT:
return "Type: Descriptor Pool";
case VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT:
return "Type: Descriptor Set";
case VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT:
return "Type: Framebuffer";
case VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT:
return "Type: Command Pool";
case VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT:
return "Type: Surface";
case VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT:
return "Type: Swapchain";
case VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT:
return "Type: Debug";
default:
break;
}
return "Type: Unknown";
}
static VKAPI_ATTR VkBool32 OnVulkanDebugReportCallback(VkDebugReportFlagsEXT reportFlags,
VkDebugReportObjectTypeEXT object_type, uint64_t object, size_t location, int32_t message_code,
const char* layer_prefix, const char* message, void* user_data)
{
std::vector<std::pair<std::string, std::string>> reportItems;
reportItems.emplace_back("Severity", VkDebugReportFlagsEXTToString(reportFlags));
reportItems.emplace_back("Object Type", VkDebugReportObjectTypeEXTToString(object_type));
reportItems.emplace_back("Object Handle", std::to_string(object));
if (location != 0) {
reportItems.emplace_back("Location", std::to_string(location));
}
if (message_code != 0) {
reportItems.emplace_back("Message Code", std::to_string(message_code));
}
if (layer_prefix != nullptr) {
reportItems.emplace_back("Layer", layer_prefix);
}
if (message != nullptr) {
reportItems.emplace_back("Message", message);
}
size_t padding = 0;
for (const auto& item : reportItems) {
padding = std::max(padding, item.first.size());
}
padding += 1;
return VK_FALSE;
}
RSVulkanDebugReport::RSVulkanDebugReport(const RSVulkanProcTable& p_vk, const RSVulkanHandle<VkInstance>& application)
: vk(p_vk), application_(application), valid_(false)
{
if (!IsDebuggingEnabled() || !vk.CreateDebugReportCallbackEXT || !vk.DestroyDebugReportCallbackEXT) {
return;
}
if (!application_) {
return;
}
VkDebugReportFlagsEXT reportFlags = kVulkanErrorFlags;
if (ValidationLayerInfoMessagesEnabled())
reportFlags |= kVulkanInfoFlags;
const VkDebugReportCallbackCreateInfoEXT createInfo = {
.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT,
.pNext = nullptr,
.flags = reportFlags,
.pfnCallback = &vulkan::OnVulkanDebugReportCallback,
.pUserData = nullptr,
};
VkDebugReportCallbackEXT handle = VK_NULL_HANDLE;
if (VK_CALL_LOG_ERROR(vk.CreateDebugReportCallbackEXT(application_, &createInfo, nullptr, &handle)) !=
VK_SUCCESS) {
return;
}
handle_ = { handle,
[this](VkDebugReportCallbackEXT handle) { vk.DestroyDebugReportCallbackEXT(application_, handle, nullptr); } };
valid_ = true;
}
RSVulkanDebugReport::~RSVulkanDebugReport() = default;
bool RSVulkanDebugReport::IsValid() const
{
return valid_;
}
} // namespace OHOS::Rosen::vulkan

View File

@ -1,44 +0,0 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef RS_VULKAN_VULKAN_DEBUG_REPORT_H_
#define RS_VULKAN_VULKAN_DEBUG_REPORT_H_
#include "vulkan_handle.h"
#include "vulkan_interface.h"
#include "vulkan_proc_table.h"
namespace OHOS::Rosen::vulkan {
class RSVulkanDebugReport {
public:
static std::string DebugExtensionName();
RSVulkanDebugReport(const RSVulkanProcTable& vk, const RSVulkanHandle<VkInstance>& application);
~RSVulkanDebugReport();
bool IsValid() const;
private:
const RSVulkanProcTable& vk;
const RSVulkanHandle<VkInstance>& application_;
RSVulkanHandle<VkDebugReportCallbackEXT> handle_ = VK_NULL_HANDLE;
bool valid_ = false;
};
} // namespace OHOS::Rosen::vulkan
#endif // RS_VULKAN_VULKAN_DEBUG_REPORT_H_

View File

@ -1,359 +0,0 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "vulkan_device.h"
#include <limits>
#include <map>
#include <vector>
#include "include/gpu/vk/GrVkBackendContext.h"
#include "vulkan_hilog.h"
#include "vulkan_proc_table.h"
#include "vulkan_surface.h"
#include "vulkan_utilities.h"
namespace OHOS::Rosen::vulkan {
constexpr auto K_VULKAN_INVALID_GRAPHICS_QUEUE_INDEX = std::numeric_limits<uint32_t>::max();
static uint32_t FindQueueIndex(const std::vector<VkQueueFamilyProperties>& properties, VkQueueFlagBits flagBits)
{
for (uint32_t i = 0, count = static_cast<uint32_t>(properties.size()); i < count; i++) {
if (properties[i].queueFlags & flagBits) {
return i;
}
}
return K_VULKAN_INVALID_GRAPHICS_QUEUE_INDEX;
}
RSVulkanDevice::RSVulkanDevice(RSVulkanProcTable& procVk, RSVulkanHandle<VkPhysicalDevice> physicalDevice)
: vk(procVk), physicalDevice_(std::move(physicalDevice)), graphicQueueIndex_(std::numeric_limits<uint32_t>::max()),
computeQueueIndex_(std::numeric_limits<uint32_t>::max()), valid_(false)
{
if (!physicalDevice_ || !vk.AreInstanceProcsSetup()) {
return;
}
std::vector<VkQueueFamilyProperties> properties = GetQueueFamilyProperties();
graphicQueueIndex_ = FindQueueIndex(properties, VK_QUEUE_GRAPHICS_BIT);
computeQueueIndex_ = FindQueueIndex(properties, VK_QUEUE_COMPUTE_BIT);
if (graphicQueueIndex_ == K_VULKAN_INVALID_GRAPHICS_QUEUE_INDEX) {
LOGE("Could not find the graphics queue index.");
return;
}
const float priorities[1] = { 1.0f };
std::vector<VkDeviceQueueCreateInfo> queueCreate { {
.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.queueFamilyIndex = graphicQueueIndex_,
.queueCount = 1,
.pQueuePriorities = priorities,
} };
if (computeQueueIndex_ != K_VULKAN_INVALID_GRAPHICS_QUEUE_INDEX && computeQueueIndex_ != graphicQueueIndex_) {
queueCreate.push_back({
.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.queueFamilyIndex = graphicQueueIndex_,
.queueCount = 1,
.pQueuePriorities = priorities,
});
}
const char* extensions[] = {
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
};
auto enabledLayers = DeviceLayersToEnable(vk, physicalDevice_);
const char* layers[enabledLayers.size()];
for (size_t i = 0; i < enabledLayers.size(); i++) {
layers[i] = enabledLayers[i].c_str();
}
const VkDeviceCreateInfo create_info = {
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.queueCreateInfoCount = queueCreate.size(),
.pQueueCreateInfos = queueCreate.data(),
.enabledLayerCount = static_cast<uint32_t>(enabledLayers.size()),
.ppEnabledLayerNames = layers,
.enabledExtensionCount = sizeof(extensions) / sizeof(const char*),
.ppEnabledExtensionNames = extensions,
.pEnabledFeatures = nullptr,
};
VkDevice device = VK_NULL_HANDLE;
if (VK_CALL_LOG_ERROR(vk.CreateDevice(physicalDevice_, &create_info, nullptr, &device)) != VK_SUCCESS) {
LOGE("Could not create device.");
return;
}
device_ = { device, [this](VkDevice device) { vk.DestroyDevice(device, nullptr); } };
if (!vk.SetupDeviceProcAddresses(device_)) {
LOGE("Could not setup device proc addresses.");
return;
}
VkQueue queue = VK_NULL_HANDLE;
vk.GetDeviceQueue(device_, graphicQueueIndex_, 0, &queue);
if (queue == VK_NULL_HANDLE) {
LOGE("Could not get the device queue handle.");
return;
}
queue_ = queue;
const VkCommandPoolCreateInfo commandPoolCreateInfo = {
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
.pNext = nullptr,
.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
.queueFamilyIndex = 0,
};
VkCommandPool commandPool = VK_NULL_HANDLE;
if (VK_CALL_LOG_ERROR(vk.CreateCommandPool(device_, &commandPoolCreateInfo, nullptr, &commandPool)) !=
VK_SUCCESS) {
LOGE("Could not create the command pool.");
return;
}
commandPool_ = { commandPool, [this](VkCommandPool pool) { vk.DestroyCommandPool(device_, pool, nullptr); } };
valid_ = true;
}
RSVulkanDevice::~RSVulkanDevice()
{
WaitIdle();
}
bool RSVulkanDevice::IsValid() const
{
return valid_;
}
bool RSVulkanDevice::WaitIdle() const
{
return VK_CALL_LOG_ERROR(vk.DeviceWaitIdle(device_)) == VK_SUCCESS;
}
const RSVulkanHandle<VkDevice>& RSVulkanDevice::GetHandle() const
{
return device_;
}
void RSVulkanDevice::ReleaseDeviceOwnership()
{
device_.ReleaseOwnership();
}
const RSVulkanHandle<VkPhysicalDevice>& RSVulkanDevice::GetPhysicalDeviceHandle() const
{
return physicalDevice_;
}
const RSVulkanHandle<VkQueue>& RSVulkanDevice::GetQueueHandle() const
{
return queue_;
}
const RSVulkanHandle<VkCommandPool>& RSVulkanDevice::GetCommandPool() const
{
return commandPool_;
}
uint32_t RSVulkanDevice::GetGraphicsQueueIndex() const
{
return graphicQueueIndex_;
}
bool RSVulkanDevice::GetSurfaceCapabilities(
const RSVulkanSurface& surface, VkSurfaceCapabilitiesKHR* capabilities) const
{
if (!surface.IsValid() || capabilities == nullptr) {
LOGE("GetSurfaceCapabilities surface is not valid or capabilities is null");
return false;
}
bool success = VK_CALL_LOG_ERROR(vk.GetPhysicalDeviceSurfaceCapabilitiesKHR(
physicalDevice_, surface.Handle(), capabilities)) == VK_SUCCESS;
if (!success) {
LOGE("GetPhysicalDeviceSurfaceCapabilitiesKHR not success");
return false;
}
// Check if the physical device surface capabilities are valid. If so, there
// is nothing more to do.
if (capabilities->currentExtent.width != 0xFFFFFFFF && capabilities->currentExtent.height != 0xFFFFFFFF) {
return true;
}
// Ask the native surface for its size as a fallback.
SkISize size = surface.GetSize();
if (size.width() == 0 || size.height() == 0) {
LOGE("GetSurfaceCapabilities surface size is 0");
return false;
}
capabilities->currentExtent.width = size.width();
capabilities->currentExtent.height = size.height();
return true;
}
bool RSVulkanDevice::GetPhysicalDeviceFeatures(VkPhysicalDeviceFeatures* DeviceFeatures) const
{
if (DeviceFeatures == nullptr || !physicalDevice_) {
return false;
}
vk.GetPhysicalDeviceFeatures(physicalDevice_, DeviceFeatures);
return true;
}
bool RSVulkanDevice::GetPhysicalDeviceFeaturesSkia(uint32_t* skFeatures) const
{
if (skFeatures == nullptr) {
return false;
}
VkPhysicalDeviceFeatures DeviceFeatures;
if (!GetPhysicalDeviceFeatures(&DeviceFeatures)) {
return false;
}
uint32_t flags = 0;
if (DeviceFeatures.geometryShader) {
flags |= kGeometryShader_GrVkFeatureFlag;
}
if (DeviceFeatures.dualSrcBlend) {
flags |= kDualSrcBlend_GrVkFeatureFlag;
}
if (DeviceFeatures.sampleRateShading) {
flags |= kSampleRateShading_GrVkFeatureFlag;
}
*skFeatures = flags;
return true;
}
std::vector<VkQueueFamilyProperties> RSVulkanDevice::GetQueueFamilyProperties() const
{
uint32_t count = 0;
vk.GetPhysicalDeviceQueueFamilyProperties(physicalDevice_, &count, nullptr);
std::vector<VkQueueFamilyProperties> properties;
properties.resize(count, {});
vk.GetPhysicalDeviceQueueFamilyProperties(physicalDevice_, &count, properties.data());
return properties;
}
int RSVulkanDevice::ChooseSurfaceFormat(
const RSVulkanSurface& surface, std::vector<VkFormat> desiredFormats, VkSurfaceFormatKHR* format) const
{
if (!surface.IsValid() || format == nullptr) {
LOGE("ChooseSurfaceFormat surface not valid or format == null");
return -1;
}
uint32_t formatCount = 0;
if (VK_CALL_LOG_ERROR(vk.GetPhysicalDeviceSurfaceFormatsKHR(
physicalDevice_, surface.Handle(), &formatCount, nullptr)) != VK_SUCCESS) {
LOGE("ChooseSurfaceFormat sGetPhysicalDeviceSurfaceFormatsKHR not success");
return -1;
}
if (formatCount == 0) {
LOGE("ChooseSurfaceFormat format count = 0");
return -1;
}
VkSurfaceFormatKHR formats[formatCount];
if (VK_CALL_LOG_ERROR(vk.GetPhysicalDeviceSurfaceFormatsKHR(
physicalDevice_, surface.Handle(), &formatCount, formats)) != VK_SUCCESS) {
LOGE("ChooseSurfaceFormat sGetPhysicalDeviceSurfaceFormatsKHR not success 2");
return -1;
}
std::map<VkFormat, VkSurfaceFormatKHR> supportedFormats;
for (uint32_t i = 0; i < formatCount; i++) {
supportedFormats[formats[i].format] = formats[i];
}
// Try to find the first supported format in the list of desired formats.
for (size_t i = 0; i < desiredFormats.size(); ++i) {
auto found = supportedFormats.find(desiredFormats[i]);
if (found != supportedFormats.end()) {
*format = found->second;
return static_cast<int>(i);
}
}
LOGE("ChooseSurfaceFormat failded");
return -1;
}
bool RSVulkanDevice::ChoosePresentMode(const RSVulkanSurface& surface, VkPresentModeKHR* presentMode) const
{
if (!surface.IsValid() || presentMode == nullptr) {
LOGE("ChoosePresentMode surface not valid or presentmode is null");
return false;
}
*presentMode = VK_PRESENT_MODE_FIFO_KHR;
return true;
}
bool RSVulkanDevice::QueueSubmit(std::vector<VkPipelineStageFlags> waitDestPipelineStages,
const std::vector<VkSemaphore>& waitSemaphores, const std::vector<VkSemaphore>& signalSemaphores,
const std::vector<VkCommandBuffer>& commandBuffers, const RSVulkanHandle<VkFence>& fence) const
{
if (waitSemaphores.size() != waitDestPipelineStages.size()) {
return false;
}
const VkSubmitInfo submitInfo = {
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
.pNext = nullptr,
.waitSemaphoreCount = static_cast<uint32_t>(waitSemaphores.size()),
.pWaitSemaphores = waitSemaphores.data(),
.pWaitDstStageMask = waitDestPipelineStages.data(),
.commandBufferCount = static_cast<uint32_t>(commandBuffers.size()),
.pCommandBuffers = commandBuffers.data(),
.signalSemaphoreCount = static_cast<uint32_t>(signalSemaphores.size()),
.pSignalSemaphores = signalSemaphores.data(),
};
if (VK_CALL_LOG_ERROR(vk.QueueSubmit(queue_, 1, &submitInfo, fence)) != VK_SUCCESS) {
return false;
}
return true;
}
} // namespace OHOS::Rosen::vulkan

View File

@ -1,80 +0,0 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef RS_VULKAN_VULKAN_DEVICE_H_
#define RS_VULKAN_VULKAN_DEVICE_H_
#include <vector>
#include "vulkan_handle.h"
namespace OHOS::Rosen::vulkan {
class RSVulkanProcTable;
class RSVulkanSurface;
class RSVulkanDevice {
public:
RSVulkanDevice(RSVulkanProcTable& vk, RSVulkanHandle<VkPhysicalDevice> physicalDevice);
~RSVulkanDevice();
bool IsValid() const;
const RSVulkanHandle<VkDevice>& GetHandle() const;
const RSVulkanHandle<VkPhysicalDevice>& GetPhysicalDeviceHandle() const;
const RSVulkanHandle<VkQueue>& GetQueueHandle() const;
const RSVulkanHandle<VkCommandPool>& GetCommandPool() const;
uint32_t GetGraphicsQueueIndex() const;
void ReleaseDeviceOwnership();
bool GetSurfaceCapabilities(const RSVulkanSurface& surface, VkSurfaceCapabilitiesKHR* capabilities) const;
bool GetPhysicalDeviceFeatures(VkPhysicalDeviceFeatures* features) const;
bool GetPhysicalDeviceFeaturesSkia(uint32_t* features) const;
int ChooseSurfaceFormat(
const RSVulkanSurface& surface, std::vector<VkFormat> desiredFormats, VkSurfaceFormatKHR* format) const;
bool ChoosePresentMode(const RSVulkanSurface& surface, VkPresentModeKHR* presentMode) const;
bool QueueSubmit(std::vector<VkPipelineStageFlags> waitDestPipelineStages,
const std::vector<VkSemaphore>& waitSemaphores, const std::vector<VkSemaphore>& signalSemaphores,
const std::vector<VkCommandBuffer>& commandBuffers, const RSVulkanHandle<VkFence>& fence) const;
bool WaitIdle() const;
RSVulkanProcTable& vk;
RSVulkanHandle<VkPhysicalDevice> physicalDevice_ = VK_NULL_HANDLE;
RSVulkanHandle<VkDevice> device_ = VK_NULL_HANDLE;
private:
RSVulkanHandle<VkQueue> queue_ = VK_NULL_HANDLE;
RSVulkanHandle<VkCommandPool> commandPool_ = VK_NULL_HANDLE;
uint32_t graphicQueueIndex_ = 0;
uint32_t computeQueueIndex_ = 0;
bool valid_ = false;
std::vector<VkQueueFamilyProperties> GetQueueFamilyProperties() const;
};
} // namespace OHOS::Rosen::vulkan
#endif // RS_VULKAN_VULKAN_DEVICE_H_

View File

@ -1,100 +0,0 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef RS_VULKAN_VULKAN_HANDLE_H_
#define RS_VULKAN_VULKAN_HANDLE_H_
#include <functional>
#include "vulkan_interface.h"
namespace OHOS::Rosen::vulkan {
template<class T>
class RSVulkanHandle {
public:
using Handle = T;
using Disposer = std::function<void(Handle)>;
RSVulkanHandle() : vkHandle_(VK_NULL_HANDLE) {}
RSVulkanHandle(Handle handle, Disposer disposer = nullptr) : vkHandle_(handle), vkDisposer_(disposer) {}
RSVulkanHandle(RSVulkanHandle&& other) : vkHandle_(other.vkHandle_), vkDisposer_(other.vkDisposer_)
{
other.vkHandle_ = VK_NULL_HANDLE;
other.vkDisposer_ = nullptr;
}
~RSVulkanHandle()
{
DisposeIfNecessary();
}
RSVulkanHandle& operator=(RSVulkanHandle&& other)
{
if (vkHandle_ != other.vkHandle_) {
DisposeIfNecessary();
}
vkHandle_ = other.vkHandle_;
other.vkHandle_ = VK_NULL_HANDLE;
vkDisposer_ = other.vkDisposer_;
other.vkDisposer_ = nullptr;
return *this;
}
operator bool() const
{
return vkHandle_ != VK_NULL_HANDLE;
}
operator Handle() const
{
return vkHandle_;
}
/// Relinquish responsibility of collecting the underlying handle when this
/// object is collected. It is the responsibility of the caller to ensure that
/// the lifetime of the handle extends past the lifetime of this object.
void ReleaseOwnership()
{
vkDisposer_ = nullptr;
}
void Reset()
{
DisposeIfNecessary();
}
private:
Handle vkHandle_ = nullptr;
Disposer vkDisposer_ = nullptr;
void DisposeIfNecessary()
{
if (vkHandle_ == VK_NULL_HANDLE) {
return;
}
if (vkDisposer_) {
vkDisposer_(vkHandle_);
}
vkHandle_ = VK_NULL_HANDLE;
vkDisposer_ = nullptr;
}
};
} // namespace OHOS::Rosen::vulkan
#endif // RS_VULKAN_VULKAN_HANDLE_H_

View File

@ -1,38 +0,0 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef VULKAN_HILOG_H
#define VULKAN_HILOG_H
#include <hilog/log.h>
#define LOGD(fmt, ...) \
::OHOS::HiviewDFX::HiLog::Debug( \
::OHOS::HiviewDFX::HiLogLabel{LOG_CORE, 0xD001400, "VulkanShell"}, \
"%{public}s: " fmt, __func__, ##__VA_ARGS__)
#define LOGI(fmt, ...) \
::OHOS::HiviewDFX::HiLog::Info( \
::OHOS::HiviewDFX::HiLogLabel{LOG_CORE, 0xD001400, "VulkanShell"}, \
"%{public}s: " fmt, __func__, ##__VA_ARGS__)
#define LOGW(fmt, ...) \
::OHOS::HiviewDFX::HiLog::Warn( \
::OHOS::HiviewDFX::HiLogLabel{LOG_CORE, 0xD001400, "VulkanShell"}, \
"%{public}s: " fmt, __func__, ##__VA_ARGS__)
#define LOGE(fmt, ...) \
::OHOS::HiviewDFX::HiLog::Error( \
::OHOS::HiviewDFX::HiLogLabel{LOG_CORE, 0xD001400, "VulkanShell"}, \
"%{public}s: " fmt, __func__, ##__VA_ARGS__)
#endif

View File

@ -1,67 +0,0 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "vulkan_image.h"
#include "vulkan_command_buffer.h"
#include "vulkan_proc_table.h"
namespace OHOS::Rosen::vulkan {
RSVulkanImage::RSVulkanImage(RSVulkanHandle<VkImage> image)
: handle_(std::move(image)), layout_(VK_IMAGE_LAYOUT_UNDEFINED), accessFlags_(0), valid_(false)
{
if (!handle_) {
return;
}
valid_ = true;
}
RSVulkanImage::~RSVulkanImage() = default;
bool RSVulkanImage::IsValid() const
{
return valid_;
}
bool RSVulkanImage::InsertImageMemoryBarrier(const RSVulkanCommandBuffer& commandBuffer,
VkPipelineStageFlagBits srcPiplineBits, VkPipelineStageFlagBits destPiplineBits,
VkAccessFlagBits destAccessFlags, VkImageLayout destLayout)
{
const VkImageMemoryBarrier imageMemoryBarrier = {
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
.pNext = nullptr,
.srcAccessMask = accessFlags_,
.dstAccessMask = destAccessFlags,
.oldLayout = layout_,
.newLayout = destLayout,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = handle_,
.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 },
};
bool success = commandBuffer.InsertPipelineBarrier(srcPiplineBits, destPiplineBits, 0, 0, nullptr, 0, nullptr, 1,
&imageMemoryBarrier);
if (success) {
accessFlags_ = destAccessFlags;
layout_ = destLayout;
}
return success;
}
} // namespace OHOS::Rosen::vulkan

View File

@ -1,46 +0,0 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef RS_VULKAN_VULKAN_IMAGE_H_
#define RS_VULKAN_VULKAN_IMAGE_H_
#include "vulkan_handle.h"
namespace OHOS::Rosen::vulkan {
class RSVulkanProcTable;
class RSVulkanCommandBuffer;
class RSVulkanImage {
public:
explicit RSVulkanImage(RSVulkanHandle<VkImage> image);
~RSVulkanImage();
bool IsValid() const;
bool InsertImageMemoryBarrier(const RSVulkanCommandBuffer& commandBuffer, VkPipelineStageFlagBits srcPiplineBits,
VkPipelineStageFlagBits destPiplineBits, VkAccessFlagBits destAccessFlags, VkImageLayout destLayout);
private:
RSVulkanHandle<VkImage> handle_;
VkImageLayout layout_;
uint32_t accessFlags_ = 0;
bool valid_ = false;
};
} // namespace OHOS::Rosen::vulkan
#endif // RS_VULKAN_VULKAN_IMAGE_H_

View File

@ -1,85 +0,0 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "vulkan_interface.h"
namespace OHOS::Rosen::vulkan {
std::string VulkanResultToString(VkResult result)
{
switch (result) {
case VK_SUCCESS:
return "RS_VK_SUCCESS";
case VK_NOT_READY:
return "RS_VK_NOT_READY";
case VK_TIMEOUT:
return "RS_VK_TIMEOUT";
case VK_EVENT_SET:
return "RS_VK_EVENT_SET";
case VK_EVENT_RESET:
return "RS_VK_EVENT_RESET";
case VK_INCOMPLETE:
return "RS_VK_INCOMPLETE";
case VK_ERROR_OUT_OF_HOST_MEMORY:
return "RS_VK_ERROR_OUT_OF_HOST_MEMORY";
case VK_ERROR_OUT_OF_DEVICE_MEMORY:
return "RS_VK_ERROR_OUT_OF_DEVICE_MEMORY";
case VK_ERROR_INITIALIZATION_FAILED:
return "RS_VK_ERROR_INITIALIZATION_FAILED";
case VK_ERROR_DEVICE_LOST:
return "RS_VK_ERROR_DEVICE_LOST";
case VK_ERROR_MEMORY_MAP_FAILED:
return "RS_VK_ERROR_MEMORY_MAP_FAILED";
case VK_ERROR_LAYER_NOT_PRESENT:
return "RS_VK_ERROR_LAYER_NOT_PRESENT";
case VK_ERROR_EXTENSION_NOT_PRESENT:
return "RS_VK_ERROR_EXTENSION_NOT_PRESENT";
case VK_ERROR_FEATURE_NOT_PRESENT:
return "RS_VK_ERROR_FEATURE_NOT_PRESENT";
case VK_ERROR_INCOMPATIBLE_DRIVER:
return "RS_VK_ERROR_INCOMPATIBLE_DRIVER";
case VK_ERROR_TOO_MANY_OBJECTS:
return "RS_VK_ERROR_TOO_MANY_OBJECTS";
case VK_ERROR_FORMAT_NOT_SUPPORTED:
return "RS_VK_ERROR_FORMAT_NOT_SUPPORTED";
case VK_ERROR_FRAGMENTED_POOL:
return "RS_VK_ERROR_FRAGMENTED_POOL";
case VK_ERROR_SURFACE_LOST_KHR:
return "RS_VK_ERROR_SURFACE_LOST_KHR";
case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR:
return "RS_VK_ERROR_NATIVE_WINDOW_IN_USE_KHR";
case VK_SUBOPTIMAL_KHR:
return "RS_VK_SUBOPTIMAL_KHR";
case VK_ERROR_OUT_OF_DATE_KHR:
return "RS_VK_ERROR_OUT_OF_DATE_KHR";
case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR:
return "RS_VK_ERROR_INCOMPATIBLE_DISPLAY_KHR";
case VK_ERROR_VALIDATION_FAILED_EXT:
return "RS_VK_ERROR_VALIDATION_FAILED_EXT";
case VK_ERROR_INVALID_SHADER_NV:
return "RS_VK_ERROR_INVALID_SHADER_NV";
case VK_RESULT_MAX_ENUM:
return "RS_VK_RESULT_MAX_ENUM";
case VK_ERROR_INVALID_EXTERNAL_HANDLE:
return "RS_VK_ERROR_INVALID_EXTERNAL_HANDLE";
case VK_ERROR_OUT_OF_POOL_MEMORY:
return "RS_VK_ERROR_OUT_OF_POOL_MEMORY";
default:
return "RS_Unknown Error";
}
return "";
}
} // namespace OHOS::Rosen::vulkan

View File

@ -1,54 +0,0 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef RS_VULKAN_VULKAN_INTERFACE_H_
#define RS_VULKAN_VULKAN_INTERFACE_H_
#include <string>
#ifndef VK_USE_PLATFORM_OHOS
#define VK_USE_PLATFORM_OHOS
#endif // VK_USE_PLATFORM_OHOS
#if !VULKAN_LINK_STATICALLY
#define VK_NO_PROTOTYPES 1
#endif // !VULKAN_LINK_STATICALLY
#include "vulkan/vulkan.h"
#ifndef NDEBUG
#define VK_CALL_LOG_ERROR(expression) \
({ \
__typeof__(expression) _rc = (expression); \
if (_rc != VK_SUCCESS) { \
LOGE("Vulkan call '" #expression "' failed with error %s", vulkan::VulkanResultToString(_rc)); \
} \
_rc; \
})
#else // NDEBUG
#define VK_CALL_LOG_ERROR(expression) (expression)
#endif // NDEBUG
namespace OHOS::Rosen::vulkan {
std::string VulkanResultToString(VkResult result);
} // namespace OHOS::Rosen::vulkan
#endif // RS_VULKAN_VULKAN_INTERFACE_H_

View File

@ -1,43 +0,0 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef RS_VULKAN_VULKAN_NATIVE_SURFACE_H_
#define RS_VULKAN_VULKAN_NATIVE_SURFACE_H_
#include "include/core/SkSize.h"
#include "vulkan_handle.h"
#include "vulkan_proc_table.h"
namespace OHOS::Rosen::vulkan {
class RSVulkanNativeSurface {
public:
virtual ~RSVulkanNativeSurface() = default;
virtual const char* GetExtensionName() const = 0;
virtual uint32_t GetSkiaExtensionName() const = 0;
virtual VkSurfaceKHR CreateSurfaceHandle(
RSVulkanProcTable& vk, const RSVulkanHandle<VkInstance>& instance) const = 0;
virtual bool IsValid() const = 0;
virtual SkISize GetSize() const = 0;
};
} // namespace OHOS::Rosen::vulkan
#endif // RS_VULKAN_VULKAN_NATIVE_SURFACE_H_

View File

@ -1,87 +0,0 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "vulkan_native_surface_ohos.h"
#include <graphic_common.h>
#include "include/gpu/vk/GrVkBackendContext.h"
#include "vulkan_hilog.h"
#include "window.h"
namespace OHOS::Rosen::vulkan {
RSVulkanNativeSurfaceOHOS::RSVulkanNativeSurfaceOHOS(struct NativeWindow* nativeWindow) : nativeWindow_(nativeWindow)
{
if (nativeWindow_ == nullptr) {
return;
}
}
RSVulkanNativeSurfaceOHOS::~RSVulkanNativeSurfaceOHOS()
{
if (nativeWindow_ == nullptr) {
return;
}
}
const char* RSVulkanNativeSurfaceOHOS::GetExtensionName() const
{
return VK_OHOS_SURFACE_EXTENSION_NAME;
}
uint32_t RSVulkanNativeSurfaceOHOS::GetSkiaExtensionName() const
{
return kKHR_ohos_surface_GrVkExtensionFlag;
}
VkSurfaceKHR RSVulkanNativeSurfaceOHOS::CreateSurfaceHandle(
RSVulkanProcTable& vk, const RSVulkanHandle<VkInstance>& instance) const
{
if (!vk.IsValid() || !instance) {
LOGE("CreateSurfaceHandle vk or instance is not valid");
return VK_NULL_HANDLE;
}
const VkSurfaceCreateInfoOHOS create_info = {
.sType = VK_STRUCTURE_TYPE_SURFACE_CREATE_INFO_OHOS,
.pNext = nullptr,
.flags = 0,
.window = nativeWindow_,
};
VkSurfaceKHR surface = VK_NULL_HANDLE;
if (VK_CALL_LOG_ERROR(vk.CreateSurfaceOHOS(instance, &create_info, nullptr, &surface)) != VK_SUCCESS) {
LOGE("CreateSurfaceHandle CreateOHOSSurfaceKHR not success");
return VK_NULL_HANDLE;
}
return surface;
}
bool RSVulkanNativeSurfaceOHOS::IsValid() const
{
return nativeWindow_ != nullptr;
}
SkISize RSVulkanNativeSurfaceOHOS::GetSize() const
{
int width, height;
int err = NativeWindowHandleOpt(nativeWindow_, GET_BUFFER_GEOMETRY, &height, &width);
return nativeWindow_ == nullptr || err != OHOS::GSERROR_OK ? SkISize::Make(0, 0) : SkISize::Make(width, height);
}
} // namespace OHOS::Rosen::vulkan

View File

@ -1,48 +0,0 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef RS_VULKAN_VULKAN_NATIVE_SURFACE_OHOS_H_
#define RS_VULKAN_VULKAN_NATIVE_SURFACE_OHOS_H_
#include "vulkan_native_surface.h"
#include "window.h"
namespace OHOS::Rosen::vulkan {
class RSVulkanNativeSurfaceOHOS : public RSVulkanNativeSurface {
public:
/// Create a native surface from the valid NativeWindow reference. Ownership
/// of the NativeWindow is assumed by this instance.
explicit RSVulkanNativeSurfaceOHOS(struct NativeWindow* nativeWindow);
~RSVulkanNativeSurfaceOHOS();
const char* GetExtensionName() const override;
uint32_t GetSkiaExtensionName() const override;
VkSurfaceKHR CreateSurfaceHandle(RSVulkanProcTable& vk, const RSVulkanHandle<VkInstance>& instance) const override;
bool IsValid() const override;
SkISize GetSize() const override;
private:
struct NativeWindow* nativeWindow_;
};
} // namespace OHOS::Rosen::vulkan
#endif // RS_VULKAN_VULKAN_NATIVE_SURFACE_OHOS_H_

View File

@ -1,230 +0,0 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "vulkan_proc_table.h"
#include <dlfcn.h>
#include "vulkan_hilog.h"
#define ACQUIRE_PROC(name, context) \
if (!((name) = AcquireProc("vk" #name, (context)))) { \
LOGE("Could not acquire proc: vk" #name); \
}
namespace OHOS::Rosen::vulkan {
RSVulkanProcTable::RSVulkanProcTable() : vkHandle_(nullptr), acquiredMandatoryProcAddresses_(false)
{
acquiredMandatoryProcAddresses_ = OpenLibraryHandle() && SetupLoaderProcAddresses();
}
RSVulkanProcTable::~RSVulkanProcTable()
{
CloseLibraryHandle();
}
bool RSVulkanProcTable::HasAcquiredMandatoryProcAddresses() const
{
return acquiredMandatoryProcAddresses_;
}
bool RSVulkanProcTable::IsValid() const
{
return instance_ && device_;
}
bool RSVulkanProcTable::AreInstanceProcsSetup() const
{
return instance_;
}
bool RSVulkanProcTable::AreDeviceProcsSetup() const
{
return device_;
}
bool RSVulkanProcTable::SetupLoaderProcAddresses()
{
if (!vkHandle_) {
return true;
}
GetInstanceProcAddr =
#if VULKAN_LINK_STATICALLY
&vkGetInstanceProcAddr;
#else
reinterpret_cast<PFN_vkGetInstanceProcAddr>(dlsym(vkHandle_, "vkGetInstanceProcAddr"));
GetDeviceProcAddr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(dlsym(vkHandle_, "vkGetDeviceProcAddr"));
EnumerateInstanceExtensionProperties = reinterpret_cast<PFN_vkEnumerateInstanceExtensionProperties>(
dlsym(vkHandle_, "vkEnumerateInstanceExtensionProperties"));
CreateInstance = reinterpret_cast<PFN_vkCreateInstance>(dlsym(vkHandle_, "vkCreateInstance"));
#endif
if (!GetInstanceProcAddr) {
LOGE("Could not acquire vkGetInstanceProcAddr.");
return false;
}
RSVulkanHandle<VkInstance> null_instance(VK_NULL_HANDLE, nullptr);
ACQUIRE_PROC(EnumerateInstanceLayerProperties, null_instance);
return true;
}
bool RSVulkanProcTable::SetupInstanceProcAddresses(const RSVulkanHandle<VkInstance>& vkHandle)
{
ACQUIRE_PROC(CreateDevice, vkHandle);
ACQUIRE_PROC(DestroyDevice, vkHandle);
ACQUIRE_PROC(DestroyInstance, vkHandle);
ACQUIRE_PROC(EnumerateDeviceLayerProperties, vkHandle);
ACQUIRE_PROC(EnumeratePhysicalDevices, vkHandle);
ACQUIRE_PROC(GetPhysicalDeviceFeatures, vkHandle);
ACQUIRE_PROC(GetPhysicalDeviceQueueFamilyProperties, vkHandle);
ACQUIRE_PROC(GetPhysicalDeviceSurfaceCapabilitiesKHR, vkHandle);
ACQUIRE_PROC(GetPhysicalDeviceSurfaceFormatsKHR, vkHandle);
ACQUIRE_PROC(GetPhysicalDeviceSurfacePresentModesKHR, vkHandle);
ACQUIRE_PROC(GetPhysicalDeviceSurfaceSupportKHR, vkHandle);
ACQUIRE_PROC(DestroySurfaceKHR, vkHandle);
ACQUIRE_PROC(CreateSurfaceOHOS, vkHandle);
ACQUIRE_PROC(GetPhysicalDeviceMemoryProperties, vkHandle);
ACQUIRE_PROC(GetPhysicalDeviceMemoryProperties2, vkHandle);
// The debug report functions are optional. We don't want proc acquisition to
// fail here because the optional methods were not present (since ACQUIRE_PROC
// returns false on failure). Wrap the optional proc acquisitions in an
// anonymous lambda and invoke it. We don't really care about the result since
// users of Debug reporting functions check for their presence explicitly.
instance_ = { vkHandle, nullptr };
return true;
}
bool RSVulkanProcTable::SetupDeviceProcAddresses(const RSVulkanHandle<VkDevice>& vkHandle)
{
ACQUIRE_PROC(AllocateCommandBuffers, vkHandle);
ACQUIRE_PROC(AllocateMemory, vkHandle);
ACQUIRE_PROC(BeginCommandBuffer, vkHandle);
ACQUIRE_PROC(BindImageMemory, vkHandle);
ACQUIRE_PROC(BindImageMemory2, vkHandle);
ACQUIRE_PROC(CmdPipelineBarrier, vkHandle);
ACQUIRE_PROC(CreateCommandPool, vkHandle);
ACQUIRE_PROC(CreateFence, vkHandle);
ACQUIRE_PROC(CreateImage, vkHandle);
ACQUIRE_PROC(CreateImageView, vkHandle);
ACQUIRE_PROC(CreateSemaphore, vkHandle);
ACQUIRE_PROC(DestroyCommandPool, vkHandle);
ACQUIRE_PROC(DestroyFence, vkHandle);
ACQUIRE_PROC(DestroyImage, vkHandle);
ACQUIRE_PROC(DestroySemaphore, vkHandle);
ACQUIRE_PROC(DeviceWaitIdle, vkHandle);
ACQUIRE_PROC(EndCommandBuffer, vkHandle);
ACQUIRE_PROC(FreeCommandBuffers, vkHandle);
ACQUIRE_PROC(FreeMemory, vkHandle);
ACQUIRE_PROC(GetDeviceQueue, vkHandle);
ACQUIRE_PROC(GetImageMemoryRequirements, vkHandle);
ACQUIRE_PROC(QueueSubmit, vkHandle);
ACQUIRE_PROC(QueueWaitIdle, vkHandle);
ACQUIRE_PROC(ResetCommandBuffer, vkHandle);
ACQUIRE_PROC(ResetFences, vkHandle);
ACQUIRE_PROC(WaitForFences, vkHandle);
ACQUIRE_PROC(AcquireNextImageKHR, vkHandle);
ACQUIRE_PROC(CreateSwapchainKHR, vkHandle);
ACQUIRE_PROC(DestroySwapchainKHR, vkHandle);
ACQUIRE_PROC(GetSwapchainImagesKHR, vkHandle);
ACQUIRE_PROC(QueuePresentKHR, vkHandle);
ACQUIRE_PROC(GetNativeBufferPropertiesOHOS, vkHandle);
ACQUIRE_PROC(QueueSignalReleaseImageOHOS, vkHandle);
device_ = { vkHandle, nullptr };
return true;
}
bool RSVulkanProcTable::OpenLibraryHandle()
{
LOGI("VulkanProcTable OpenLibararyHandle.");
#if VULKAN_LINK_STATICALLY
static char kDummyLibraryHandle = '\0';
handle_ = reinterpret_cast<decltype(handle_)>(&kDummyLibraryHandle);
return true;
#else // VULKAN_LINK_STATICALLY
LOGI("VulkanProcTable OpenLibararyHandle: dlopen libvulkan.so.");
dlerror(); // clear existing errors on thread.
vkHandle_ = dlopen("/system/lib64/libvulkan.so", RTLD_NOW | RTLD_LOCAL);
if (vkHandle_ == nullptr) {
LOGE("Could not open the vulkan library: %s", dlerror());
return false;
}
return true;
#endif // VULKAN_LINK_STATICALLY
}
bool RSVulkanProcTable::CloseLibraryHandle()
{
#if VULKAN_LINK_STATICALLY
handle_ = nullptr;
return true;
#else
if (vkHandle_ != nullptr) {
dlerror(); // clear existing errors on thread.
if (dlclose(vkHandle_) != 0) {
LOGE("Could not close the vulkan library handle. This indicates a leak. %s", dlerror());
}
vkHandle_ = nullptr;
}
return vkHandle_ == nullptr;
#endif
}
PFN_vkVoidFunction RSVulkanProcTable::AcquireProc(
const char* procName, const RSVulkanHandle<VkInstance>& instance) const
{
if (procName == nullptr || !GetInstanceProcAddr) {
return nullptr;
}
// A VK_NULL_HANDLE as the instance is an acceptable parameter.
return GetInstanceProcAddr(instance, procName);
}
PFN_vkVoidFunction RSVulkanProcTable::AcquireProc(const char* procName, const RSVulkanHandle<VkDevice>& device) const
{
if (procName == nullptr || !device || !GetDeviceProcAddr) {
return nullptr;
}
return GetDeviceProcAddr(device, procName);
}
GrVkGetProc RSVulkanProcTable::CreateSkiaGetProc() const
{
if (!IsValid()) {
return nullptr;
}
return [this](const char* procName, VkInstance instance, VkDevice device) {
if (device != VK_NULL_HANDLE) {
auto result = AcquireProc(procName, { device, nullptr });
if (result != nullptr) {
return result;
}
}
return AcquireProc(procName, { instance, nullptr });
};
}
} // namespace OHOS::Rosen::vulkan

View File

@ -1,159 +0,0 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef RS_VULKAN_VULKAN_PROC_TABLE_H_
#define RS_VULKAN_VULKAN_PROC_TABLE_H_
#include "include/core/SkRefCnt.h"
#include "include/gpu/vk/GrVkBackendContext.h"
#include "vulkan_handle.h"
#include "vulkan_interface.h"
namespace OHOS::Rosen::vulkan {
class RSVulkanProcTable {
public:
template<class T>
class RSProc {
public:
using Proto = T;
explicit RSProc(T proc = nullptr) : proc_(proc) {}
~RSProc()
{
proc_ = nullptr;
}
RSProc operator=(T proc)
{
proc_ = proc;
return *this;
}
RSProc operator=(PFN_vkVoidFunction proc)
{
proc_ = reinterpret_cast<Proto>(proc);
return *this;
}
operator bool() const
{
return proc_ != nullptr;
}
operator T() const
{
return proc_;
}
private:
T proc_;
};
RSVulkanProcTable();
~RSVulkanProcTable();
bool HasAcquiredMandatoryProcAddresses() const;
bool IsValid() const;
bool AreInstanceProcsSetup() const;
bool AreDeviceProcsSetup() const;
bool SetupInstanceProcAddresses(const RSVulkanHandle<VkInstance>& instance);
bool SetupDeviceProcAddresses(const RSVulkanHandle<VkDevice>& device);
GrVkGetProc CreateSkiaGetProc() const;
#define VK_DEFINE_PROC(name) RSProc<PFN_vk##name> (name)
VK_DEFINE_PROC(AcquireNextImageKHR);
VK_DEFINE_PROC(AllocateCommandBuffers);
VK_DEFINE_PROC(AllocateMemory);
VK_DEFINE_PROC(BeginCommandBuffer);
VK_DEFINE_PROC(BindImageMemory);
VK_DEFINE_PROC(BindImageMemory2);
VK_DEFINE_PROC(CmdPipelineBarrier);
VK_DEFINE_PROC(CreateCommandPool);
VK_DEFINE_PROC(CreateDebugReportCallbackEXT);
VK_DEFINE_PROC(CreateDevice);
VK_DEFINE_PROC(CreateFence);
VK_DEFINE_PROC(CreateImage);
VK_DEFINE_PROC(CreateImageView);
VK_DEFINE_PROC(CreateInstance);
VK_DEFINE_PROC(CreateSemaphore);
VK_DEFINE_PROC(CreateSwapchainKHR);
VK_DEFINE_PROC(DestroyCommandPool);
VK_DEFINE_PROC(DestroyDebugReportCallbackEXT);
VK_DEFINE_PROC(DestroyDevice);
VK_DEFINE_PROC(DestroyFence);
VK_DEFINE_PROC(DestroyImage);
VK_DEFINE_PROC(DestroyInstance);
VK_DEFINE_PROC(DestroySemaphore);
VK_DEFINE_PROC(DestroySurfaceKHR);
VK_DEFINE_PROC(DestroySwapchainKHR);
VK_DEFINE_PROC(DeviceWaitIdle);
VK_DEFINE_PROC(EndCommandBuffer);
VK_DEFINE_PROC(EnumerateDeviceLayerProperties);
VK_DEFINE_PROC(EnumerateInstanceExtensionProperties);
VK_DEFINE_PROC(EnumerateInstanceLayerProperties);
VK_DEFINE_PROC(EnumeratePhysicalDevices);
VK_DEFINE_PROC(FreeCommandBuffers);
VK_DEFINE_PROC(FreeMemory);
VK_DEFINE_PROC(GetDeviceProcAddr);
VK_DEFINE_PROC(GetDeviceQueue);
VK_DEFINE_PROC(GetImageMemoryRequirements);
VK_DEFINE_PROC(GetInstanceProcAddr);
VK_DEFINE_PROC(GetPhysicalDeviceFeatures);
VK_DEFINE_PROC(GetPhysicalDeviceQueueFamilyProperties);
VK_DEFINE_PROC(QueueSubmit);
VK_DEFINE_PROC(QueueWaitIdle);
VK_DEFINE_PROC(ResetCommandBuffer);
VK_DEFINE_PROC(ResetFences);
VK_DEFINE_PROC(WaitForFences);
VK_DEFINE_PROC(GetPhysicalDeviceSurfaceCapabilitiesKHR);
VK_DEFINE_PROC(GetPhysicalDeviceSurfaceFormatsKHR);
VK_DEFINE_PROC(GetPhysicalDeviceSurfacePresentModesKHR);
VK_DEFINE_PROC(GetPhysicalDeviceSurfaceSupportKHR);
VK_DEFINE_PROC(GetSwapchainImagesKHR);
VK_DEFINE_PROC(QueuePresentKHR);
VK_DEFINE_PROC(CreateSurfaceOHOS);
VK_DEFINE_PROC(GetPhysicalDeviceMemoryProperties);
VK_DEFINE_PROC(GetPhysicalDeviceMemoryProperties2);
VK_DEFINE_PROC(GetNativeBufferPropertiesOHOS);
VK_DEFINE_PROC(QueueSignalReleaseImageOHOS);
#undef VK_DEFINE_PROC
private:
void* vkHandle_ = nullptr;
bool acquiredMandatoryProcAddresses_ = false;
RSVulkanHandle<VkInstance> instance_ = VK_NULL_HANDLE;
RSVulkanHandle<VkDevice> device_ = VK_NULL_HANDLE;
bool OpenLibraryHandle();
bool SetupLoaderProcAddresses();
bool CloseLibraryHandle();
PFN_vkVoidFunction AcquireProc(const char* procName, const RSVulkanHandle<VkInstance>& instance) const;
PFN_vkVoidFunction AcquireProc(const char* procName, const RSVulkanHandle<VkDevice>& device) const;
};
} // namespace OHOS::Rosen::vulkan
#endif // RS_VULKAN_VULKAN_PROC_TABLE_H_

View File

@ -1,46 +0,0 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef RS_VULKAN_VULKAN_PROVIDER_H_
#define RS_VULKAN_VULKAN_PROVIDER_H_
#include "vulkan_handle.h"
#include "vulkan_proc_table.h"
namespace OHOS::Rosen::vulkan {
class RSVulkanProvider {
public:
virtual const vulkan::RSVulkanProcTable& vk() = 0;
virtual const vulkan::RSVulkanHandle<VkDevice>& vk_device() = 0;
vulkan::RSVulkanHandle<VkFence> CreateFence()
{
const VkFenceCreateInfo create_info = {
.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
};
VkFence fence;
if (VK_CALL_LOG_ERROR(vk().CreateFence(vk_device(), &create_info, nullptr, &fence)) != VK_SUCCESS)
return vulkan::RSVulkanHandle<VkFence>();
return { fence, [this](VkFence fence) { vk().DestroyFence(vk_device(), fence, nullptr); } };
}
};
} // namespace OHOS::Rosen::vulkan
#endif // RS_VULKAN_VULKAN_PROVIDER_H_

View File

@ -1,67 +0,0 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "vulkan_surface.h"
#include "vulkan_application.h"
#include "vulkan_hilog.h"
#include "vulkan_native_surface.h"
namespace OHOS::Rosen::vulkan {
RSVulkanSurface::RSVulkanSurface(
RSVulkanProcTable& procVk, RSVulkanApplication& application, std::unique_ptr<RSVulkanNativeSurface> nativeSurface)
: vk(procVk), application_(application), nativeSurface_(std::move(nativeSurface)), valid_(false)
{
if (nativeSurface_ == nullptr || !nativeSurface_->IsValid()) {
LOGE("Native surface was invalid.");
return;
}
VkSurfaceKHR surface = nativeSurface_->CreateSurfaceHandle(vk, application.GetInstance());
if (surface == VK_NULL_HANDLE) {
LOGE("Could not create the surface handle.");
return;
}
surface_ = { surface,
[this](VkSurfaceKHR surface) { vk.DestroySurfaceKHR(application_.GetInstance(), surface, nullptr); } };
valid_ = true;
}
RSVulkanSurface::~RSVulkanSurface() = default;
bool RSVulkanSurface::IsValid() const
{
return valid_;
}
const RSVulkanHandle<VkSurfaceKHR>& RSVulkanSurface::Handle() const
{
return surface_;
}
const RSVulkanNativeSurface& RSVulkanSurface::GetNativeSurface() const
{
return *nativeSurface_;
}
SkISize RSVulkanSurface::GetSize() const
{
return valid_ ? nativeSurface_->GetSize() : SkISize::Make(0, 0);
}
} // namespace OHOS::Rosen::vulkan

View File

@ -1,54 +0,0 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef RS_VULKAN_VULKAN_SURFACE_H_
#define RS_VULKAN_VULKAN_SURFACE_H_
#include "include/core/SkSize.h"
#include "vulkan_handle.h"
namespace OHOS::Rosen::vulkan {
class RSVulkanProcTable;
class RSVulkanApplication;
class RSVulkanNativeSurface;
class RSVulkanSurface {
public:
RSVulkanSurface(
RSVulkanProcTable& vk, RSVulkanApplication& application, std::unique_ptr<RSVulkanNativeSurface> nativeSurface);
~RSVulkanSurface();
bool IsValid() const;
/// Returns the current size of the surface or (0, 0) if invalid.
SkISize GetSize() const;
const RSVulkanHandle<VkSurfaceKHR>& Handle() const;
const RSVulkanNativeSurface& GetNativeSurface() const;
private:
RSVulkanProcTable& vk;
RSVulkanApplication& application_;
std::unique_ptr<RSVulkanNativeSurface> nativeSurface_;
RSVulkanHandle<VkSurfaceKHR> surface_;
bool valid_ = false;
};
} // namespace OHOS::Rosen::vulkan
#endif // RS_VULKAN_VULKAN_SURFACE_H_

View File

@ -1,623 +0,0 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "vulkan_swapchain.h"
#include "include/gpu/GrBackendSurface.h"
#include "include/gpu/GrDirectContext.h"
#include "include/gpu/vk/GrVkTypes.h"
#include "vulkan_backbuffer.h"
#include "vulkan_device.h"
#include "vulkan_hilog.h"
#include "vulkan_image.h"
#include "vulkan_proc_table.h"
#include "vulkan_surface.h"
namespace OHOS::Rosen::vulkan {
namespace {
struct FormatInfo {
VkFormat format_;
SkColorType colorType_;
sk_sp<SkColorSpace> colorSpace_;
};
} // namespace
static std::vector<FormatInfo> DesiredFormatInfos()
{
return { { VK_FORMAT_R8G8B8A8_UNORM, kRGBA_8888_SkColorType, SkColorSpace::MakeSRGB() },
{ VK_FORMAT_B8G8R8A8_UNORM, kRGBA_8888_SkColorType, SkColorSpace::MakeSRGB() },
{ VK_FORMAT_R8G8B8A8_SRGB, kSRGBA_8888_SkColorType, SkColorSpace::MakeSRGBLinear() },
{ VK_FORMAT_B8G8R8A8_SRGB, kBGRA_8888_SkColorType, SkColorSpace::MakeSRGBLinear() },
{ VK_FORMAT_R16G16B16A16_SFLOAT, kRGBA_F16_SkColorType, SkColorSpace::MakeSRGBLinear() } };
}
std::mutex RSVulkanSwapchain::mapMutex_;
std::unordered_map<std::thread::id, RSVulkanSwapchain*> RSVulkanSwapchain::toBePresent_;
RSVulkanSwapchain::RSVulkanSwapchain(const RSVulkanProcTable& procVk, const RSVulkanDevice& device,
const RSVulkanSurface& surface, GrDirectContext* skiaContext, std::unique_ptr<RSVulkanSwapchain> oldSwapchain,
uint32_t queueFamilyIndex)
: vk(procVk), device_(device), capabilities_(), surfaceFormat_(),
currentPipelineStage_(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT), currentBackbufferIndex_(0), currentImageIndex_(0),
valid_(false)
{
if (!device_.IsValid() || !surface.IsValid() || skiaContext == nullptr) {
LOGE("Device or surface is invalid.");
return;
}
if (!device_.GetSurfaceCapabilities(surface, &capabilities_)) {
LOGE("Could not find surface capabilities.");
return;
}
const auto formatInfos = DesiredFormatInfos();
std::vector<VkFormat> desired_formats(formatInfos.size());
for (size_t i = 0; i < formatInfos.size(); ++i) {
if (skiaContext->colorTypeSupportedAsSurface(formatInfos[i].colorType_)) {
desired_formats[i] = formatInfos[i].format_;
} else {
desired_formats[i] = VK_FORMAT_UNDEFINED;
}
}
int formatIndex = device_.ChooseSurfaceFormat(surface, desired_formats, &surfaceFormat_);
if (formatIndex < 0) {
LOGE("Could not choose surface format.");
return;
}
VkPresentModeKHR presentMode = VK_PRESENT_MODE_FIFO_KHR;
if (!device_.ChoosePresentMode(surface, &presentMode)) {
LOGE("Could not choose present mode.");
return;
}
// Check if the surface can present.
VkBool32 supported = VK_FALSE;
if (VK_CALL_LOG_ERROR(vk.GetPhysicalDeviceSurfaceSupportKHR(device_.GetPhysicalDeviceHandle(), // physical device
queueFamilyIndex, // queue family
surface.Handle(), // surface to test
&supported)) != VK_SUCCESS) {
LOGE("Could not get physical device surface support.");
return;
}
if (supported != VK_TRUE) {
LOGE("Surface was not supported by the physical device.");
return;
}
// Construct the Swapchain
VkSwapchainKHR oldSwapchainHandle = VK_NULL_HANDLE;
if (oldSwapchain != nullptr && oldSwapchain->IsValid()) {
oldSwapchainHandle = oldSwapchain->swapchain_;
}
VkSurfaceKHR surfaceHandle = surface.Handle();
const VkSwapchainCreateInfoKHR createInfo = {
.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
.pNext = nullptr,
.flags = 0,
.surface = surfaceHandle,
.minImageCount = capabilities_.minImageCount,
.imageFormat = surfaceFormat_.format,
.imageColorSpace = surfaceFormat_.colorSpace,
.imageExtent = capabilities_.currentExtent,
.imageArrayLayers = 1,
.imageUsage =
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE,
.queueFamilyIndexCount = 0,
.pQueueFamilyIndices = nullptr,
.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR,
.compositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR,
.presentMode = presentMode,
.clipped = VK_FALSE,
.oldSwapchain = oldSwapchainHandle,
};
VkSwapchainKHR swapchain = VK_NULL_HANDLE;
if (VK_CALL_LOG_ERROR(vk.CreateSwapchainKHR(device_.GetHandle(), &createInfo, nullptr, &swapchain)) !=
VK_SUCCESS) {
LOGE("Could not create the swapchain.");
return;
}
swapchain_ = { swapchain, [this](VkSwapchainKHR swapchain) {
device_.WaitIdle();
vk.DestroySwapchainKHR(device_.GetHandle(), swapchain, nullptr);
} };
if (!CreateSwapchainImages(
skiaContext, formatInfos[formatIndex].colorType_, formatInfos[formatIndex].colorSpace_)) {
LOGE("Could not create swapchain images.");
return;
}
valid_ = true;
}
RSVulkanSwapchain::~RSVulkanSwapchain() = default;
bool RSVulkanSwapchain::IsValid() const
{
return valid_;
}
std::vector<VkImage> RSVulkanSwapchain::GetImages() const
{
uint32_t count = 0;
if (VK_CALL_LOG_ERROR(vk.GetSwapchainImagesKHR(device_.GetHandle(), swapchain_, &count, nullptr)) != VK_SUCCESS) {
return {};
}
if (count == 0) {
return {};
}
std::vector<VkImage> images;
images.resize(count);
if (VK_CALL_LOG_ERROR(vk.GetSwapchainImagesKHR(device_.GetHandle(), swapchain_, &count, images.data())) !=
VK_SUCCESS) {
return {};
}
return images;
}
SkISize RSVulkanSwapchain::GetSize() const
{
VkExtent2D vkExtents = capabilities_.currentExtent;
if (vkExtents.width < capabilities_.minImageExtent.width) {
vkExtents.width = capabilities_.minImageExtent.width;
} else if (vkExtents.width > capabilities_.maxImageExtent.width) {
vkExtents.width = capabilities_.maxImageExtent.width;
}
if (vkExtents.height < capabilities_.minImageExtent.height) {
vkExtents.height = capabilities_.minImageExtent.height;
} else if (vkExtents.height > capabilities_.maxImageExtent.height) {
vkExtents.height = capabilities_.maxImageExtent.height;
}
return SkISize::Make(vkExtents.width, vkExtents.height);
}
sk_sp<SkSurface> RSVulkanSwapchain::CreateSkiaSurface(GrDirectContext* gr_context, VkImage image, const SkISize& size,
SkColorType color_type, sk_sp<SkColorSpace> color_space) const
{
if (gr_context == nullptr) {
LOGE("gr_context == nullptr");
return nullptr;
}
if (color_type == kUnknown_SkColorType) {
// Unexpected Vulkan format.
LOGE("color_type == kUnknown_SkColorType");
return nullptr;
}
GrVkImageInfo imageInfo;
imageInfo.fImage = image;
imageInfo.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
imageInfo.fImageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
imageInfo.fFormat = surfaceFormat_.format;
imageInfo.fImageUsageFlags =
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
imageInfo.fSampleCount = 1;
imageInfo.fLevelCount = 1;
GrBackendRenderTarget backendRenderTarget(size.fWidth, size.fHeight, 0, imageInfo);
SkSurfaceProps props(0, SkPixelGeometry::kUnknown_SkPixelGeometry);
LOGI("SkSurface::MakeFromBackendRenderTarget");
return SkSurface::MakeFromBackendRenderTarget(gr_context, // context
backendRenderTarget, // backend render target
kTopLeft_GrSurfaceOrigin, // origin
color_type, // color type
std::move(color_space), // color space
&props); // surface properties
}
bool RSVulkanSwapchain::CreateSwapchainImages(
GrDirectContext* skiaContext, SkColorType color_type, sk_sp<SkColorSpace> color_space)
{
std::vector<VkImage> images = GetImages();
if (images.size() == 0) {
LOGE("images.size() == 0");
return false;
}
const SkISize surface_size = GetSize();
for (const VkImage& image : images) {
// Populate the backbuffer.
auto backbuffer = std::make_unique<RSVulkanBackbuffer>(vk, device_.GetHandle(), device_.GetCommandPool());
if (!backbuffer || !backbuffer->IsValid()) {
return false;
}
backbuffers_.emplace_back(std::move(backbuffer));
// Populate the image.
auto vulkan_image = std::make_unique<RSVulkanImage>(image);
if (!vulkan_image->IsValid()) {
LOGE("vulkan_image Not Valid()");
return false;
}
images_.emplace_back(std::move(vulkan_image));
// Populate the surface.
auto surface = CreateSkiaSurface(skiaContext, image, surface_size, color_type, color_space);
if (surface == nullptr) {
LOGE("surface is nullptr");
return false;
}
surfaces_.emplace_back(std::move(surface));
}
if (backbuffers_.size() != images_.size()) {
LOGI("backbuffers_.size() != images_.size()");
}
if (images_.size() != surfaces_.size()) {
LOGI("images_.size() != surfaces_.size()");
}
return true;
}
RSVulkanBackbuffer* RSVulkanSwapchain::GetNextBackbuffer()
{
auto availableBackbuffers = backbuffers_.size();
if (availableBackbuffers == 0) {
return nullptr;
}
auto nextBackbufferIndex = (currentBackbufferIndex_ + 1) % backbuffers_.size();
auto& backbuffer = backbuffers_[nextBackbufferIndex];
if (!backbuffer->IsValid()) {
return nullptr;
}
currentBackbufferIndex_ = nextBackbufferIndex;
return backbuffer.get();
}
RSVulkanSwapchain::AcquireResult RSVulkanSwapchain::AcquireSurface(int bufferCount)
{
AcquireResult error = { AcquireStatus::ERROR_SURFACE_LOST, nullptr };
if (!IsValid()) {
LOGE("Swapchain was invalid.");
return error;
}
auto backbuffer = GetNextBackbuffer();
if (backbuffer == nullptr) {
LOGE("Could not get the next backbuffer.");
return error;
}
if (!backbuffer->IsMultiThreading()) {
if (!backbuffer->WaitFences()) {
LOGE("Failed waiting on fences.");
return error;
}
if (!backbuffer->ResetFences()) {
LOGE("Could not reset fences.");
return error;
}
}
uint32_t nextImageIndex = 0;
VkResult acquireResult = VK_CALL_LOG_ERROR(vk.AcquireNextImageKHR(device_.GetHandle(), //
swapchain_, //
std::numeric_limits<uint64_t>::max(), //
backbuffer->GetUsageSemaphore(), //
VK_NULL_HANDLE, //
&nextImageIndex));
if (bufferCount == 1) {
nextImageIndex = 0;
}
switch (acquireResult) {
case VK_SUCCESS:
break;
case VK_ERROR_SURFACE_LOST_KHR:
return { AcquireStatus::ERROR_SURFACE_LOST, nullptr };
case VK_ERROR_OUT_OF_DATE_KHR:
return { AcquireStatus::ERROR_SURFACE_OUT_OF_DATE, nullptr };
default:
LOGE("Unexpected result from AcquireNextImageKHR: %d", acquireResult);
return { AcquireStatus::ERROR_SURFACE_LOST, nullptr };
}
// Simple sanity checking of image index.
if (nextImageIndex >= images_.size()) {
LOGE("Image index returned was out-of-bounds.");
return error;
}
auto& image = images_[nextImageIndex];
if (!image->IsValid()) {
LOGE("Image at index was invalid.");
return error;
}
if (!backbuffer->GetUsageCommandBuffer().Begin()) {
LOGE("Could not begin recording to the command buffer.");
return error;
}
VkPipelineStageFlagBits destinationPipelineStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
VkImageLayout destinationImageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
if (!image->InsertImageMemoryBarrier(backbuffer->GetUsageCommandBuffer(), // command buffer
currentPipelineStage_, // src_pipeline_bits
destinationPipelineStage, // dest_pipeline_bits
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // destAccessFlags
destinationImageLayout)) { // destLayout
LOGE("Could not insert image memory barrier.");
return error;
} else {
currentPipelineStage_ = destinationPipelineStage;
}
if (!backbuffer->GetUsageCommandBuffer().End()) {
LOGE("Could not end recording to the command buffer.");
return error;
}
std::vector<VkSemaphore> waitSemaphores = { backbuffer->GetUsageSemaphore() };
std::vector<VkSemaphore> signalSemaphores = {};
std::vector<VkCommandBuffer> commandBuffers = { backbuffer->GetUsageCommandBuffer().Handle() };
if (!device_.QueueSubmit({ destinationPipelineStage }, // waitDestPipelineStages
waitSemaphores, // waitSemaphores
signalSemaphores, // signalSemaphores
commandBuffers, // commandBuffers
backbuffer->GetUsageFence())) { // fence
LOGE("Could not submit to the device queue.");
return error;
}
// reset to not under multi-threading by default
// the reality will be judged later in flush stage
backbuffer->UnsetMultiThreading();
sk_sp<SkSurface> surface = surfaces_[nextImageIndex];
if (surface == nullptr) {
LOGE("Could not access surface at the image index.");
return error;
}
GrBackendRenderTarget backendRT = surface->getBackendRenderTarget(SkSurface::kFlushRead_BackendHandleAccess);
if (!backendRT.isValid()) {
LOGE("Could not get backend render target.");
return error;
}
backendRT.setVkImageLayout(destinationImageLayout);
currentImageIndex_ = nextImageIndex;
return { AcquireStatus::SUCCESS, surface };
}
bool RSVulkanSwapchain::FlushCommands()
{
if (!IsValid()) {
LOGE("Swapchain was invalid.");
return false;
}
sk_sp<SkSurface> surface = surfaces_[currentImageIndex_];
const std::unique_ptr<RSVulkanImage>& image = images_[currentImageIndex_];
auto backbuffer = backbuffers_[currentBackbufferIndex_].get();
surface->flush();
if (!backbuffer->GetRenderCommandBuffer().Begin()) {
LOGE("Could not start recording to the command buffer.");
return false;
}
VkPipelineStageFlagBits destinationPipelineStage = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
VkImageLayout destinationImageLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
if (!image->InsertImageMemoryBarrier(backbuffer->GetRenderCommandBuffer(), // command buffer
currentPipelineStage_, // src_pipeline_bits
destinationPipelineStage, // dest_pipeline_bits
VK_ACCESS_MEMORY_READ_BIT, // destAccessFlags
destinationImageLayout)) { // destLayout
LOGE("Could not insert memory barrier.");
return false;
} else {
currentPipelineStage_ = destinationPipelineStage;
}
if (!backbuffer->GetRenderCommandBuffer().End()) {
LOGE("Could not end recording to the command buffer.");
return false;
}
return true;
}
void RSVulkanSwapchain::AddToPresent()
{
std::lock_guard<std::mutex> lock(mapMutex_);
toBePresent_[std::this_thread::get_id()] = this;
}
void RSVulkanSwapchain::PresentAll(RSVulkanHandle<VkFence>& shared_fence)
{
if (toBePresent_.empty()) {
LOGE("nothing to be presented");
return;
}
std::lock_guard<std::mutex> lock(mapMutex_);
// ---------------------------------------------------------------------------
// Submit all the command buffer to the device queue. Tell it to signal the render
// semaphore.
// ---------------------------------------------------------------------------
std::vector<VkSemaphore> waitSemaphores = {};
std::vector<VkSemaphore> queueSignalSemaphores;
std::vector<VkCommandBuffer> commandBuffers;
std::vector<VkSwapchainKHR> swapchains;
std::vector<uint32_t> present_image_indices;
queueSignalSemaphores.reserve(toBePresent_.size());
commandBuffers.reserve(toBePresent_.size());
swapchains.reserve(toBePresent_.size());
present_image_indices.reserve(toBePresent_.size());
RSVulkanSwapchain* tmpSwapChain = nullptr;
for (const auto& entry : toBePresent_) {
auto swapchain = entry.second;
if (!tmpSwapChain)
tmpSwapChain = swapchain;
auto backbuffer = swapchain->backbuffers_[swapchain->currentBackbufferIndex_].get();
backbuffer->SetMultiThreading();
queueSignalSemaphores.push_back(backbuffer->GetRenderSemaphore());
commandBuffers.push_back(backbuffer->GetRenderCommandBuffer().Handle());
swapchains.push_back(swapchain->swapchain_);
present_image_indices.push_back(static_cast<uint32_t>(swapchain->currentImageIndex_));
}
const RSVulkanProcTable& tmpVk = tmpSwapChain->vk;
const RSVulkanDevice& device = tmpSwapChain->device_;
if (!device.QueueSubmit({}, waitSemaphores, queueSignalSemaphores,
commandBuffers, shared_fence)) {
LOGE("Could not submit to the device queue");
return;
}
// ----------------------------------------
// present multiple swapchain all at once
// ----------------------------------------
const VkPresentInfoKHR presentInfo = {
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
.pNext = nullptr,
.waitSemaphoreCount = static_cast<uint32_t>(queueSignalSemaphores.size()),
.pWaitSemaphores = queueSignalSemaphores.data(),
.swapchainCount = static_cast<uint32_t>(swapchains.size()),
.pSwapchains = swapchains.data(),
.pImageIndices = present_image_indices.data(),
.pResults = nullptr,
};
if (VK_CALL_LOG_ERROR(tmpVk.QueuePresentKHR(device.GetQueueHandle(), &presentInfo)) != VK_SUCCESS) {
LOGE("Could not submit the present operation");
return;
}
toBePresent_.clear();
}
bool RSVulkanSwapchain::Submit()
{
LOGI("RSVulkanSwapchain::Submit()");
if (!IsValid()) {
LOGE("Swapchain was invalid.");
return false;
}
sk_sp<SkSurface> surface = surfaces_[currentImageIndex_];
const std::unique_ptr<RSVulkanImage>& image = images_[currentImageIndex_];
auto backbuffer = backbuffers_[currentBackbufferIndex_].get();
surface->flushAndSubmit(true);
if (!backbuffer->GetRenderCommandBuffer().Begin()) {
LOGE("Could not start recording to the command buffer.");
return false;
}
VkPipelineStageFlagBits destinationPipelineStage = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
VkImageLayout destinationImageLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
if (!image->InsertImageMemoryBarrier(backbuffer->GetRenderCommandBuffer(), // command buffer
currentPipelineStage_, // src_pipeline_bits
destinationPipelineStage, // dest_pipeline_bits
VK_ACCESS_MEMORY_READ_BIT, // destAccessFlags
destinationImageLayout)) { // destLayout
LOGE("Could not insert memory barrier.");
return false;
} else {
currentPipelineStage_ = destinationPipelineStage;
}
if (!backbuffer->GetRenderCommandBuffer().End()) {
LOGE("Could not end recording to the command buffer.");
return false;
}
std::vector<VkSemaphore> waitSemaphores = {};
std::vector<VkSemaphore> queueSignalSemaphores = { backbuffer->GetRenderSemaphore() };
std::vector<VkCommandBuffer> commandBuffers = { backbuffer->GetRenderCommandBuffer().Handle() };
if (!device_.QueueSubmit({}, // waitDestPipelineStages
waitSemaphores, // waitSemaphores
queueSignalSemaphores, // signalSemaphores
commandBuffers, // commandBuffers
backbuffer->GetRenderFence() // fence
)) {
LOGE("Could not submit to the device queue.");
return false;
}
backbuffer->UnsetMultiThreading();
// ---------------------------------------------------------------------------
// Step 5:
// Submit the present operation and wait on the render semaphore.
// ---------------------------------------------------------------------------
VkSwapchainKHR swapchain = swapchain_;
uint32_t presentImageIndex = static_cast<uint32_t>(currentImageIndex_);
const VkPresentInfoKHR presentInfo = {
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
.pNext = nullptr,
.waitSemaphoreCount = static_cast<uint32_t>(queueSignalSemaphores.size()),
.pWaitSemaphores = queueSignalSemaphores.data(),
.swapchainCount = 1,
.pSwapchains = &swapchain,
.pImageIndices = &presentImageIndex,
.pResults = nullptr,
};
if (VK_CALL_LOG_ERROR(vk.QueuePresentKHR(device_.GetQueueHandle(), &presentInfo)) != VK_SUCCESS) {
LOGE("Could not submit the present operation.");
return false;
}
return true;
}
} // namespace OHOS::Rosen::vulkan

View File

@ -1,97 +0,0 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef RS_VULKAN_VULKAN_SWAPCHAIN_H_
#define RS_VULKAN_VULKAN_SWAPCHAIN_H_
#include <memory>
#include <mutex>
#include <thread>
#include <unordered_map>
#include <utility>
#include <vector>
#include "include/core/SkSize.h"
#include "include/core/SkSurface.h"
#include "vulkan_handle.h"
namespace OHOS::Rosen::vulkan {
class RSVulkanProcTable;
class RSVulkanDevice;
class RSVulkanSurface;
class RSVulkanBackbuffer;
class RSVulkanImage;
class RSVulkanSwapchain {
public:
RSVulkanSwapchain(const RSVulkanProcTable& vk, const RSVulkanDevice& device, const RSVulkanSurface& surface,
GrDirectContext* skiaContext, std::unique_ptr<RSVulkanSwapchain> oldSwapchain, uint32_t queueFamilyIndex);
~RSVulkanSwapchain();
bool IsValid() const;
enum class AcquireStatus {
SUCCESS,
ERROR_SURFACE_LOST,
ERROR_SURFACE_OUT_OF_DATE,
};
using AcquireResult = std::pair<AcquireStatus, sk_sp<SkSurface>>;
AcquireResult AcquireSurface(int bufferCount = -1);
/// Submit a previously acquired. There must not be consecutive calls to
/// |Submit| without and interleaving |AcquireFrame|.
bool Submit();
SkISize GetSize() const;
bool FlushCommands();
void AddToPresent();
static void PresentAll(RSVulkanHandle<VkFence>& sharedFence);
private:
const RSVulkanProcTable& vk;
const RSVulkanDevice& device_;
VkSurfaceCapabilitiesKHR capabilities_;
VkSurfaceFormatKHR surfaceFormat_;
RSVulkanHandle<VkSwapchainKHR> swapchain_;
std::vector<std::unique_ptr<RSVulkanBackbuffer>> backbuffers_;
std::vector<std::unique_ptr<RSVulkanImage>> images_;
std::vector<sk_sp<SkSurface>> surfaces_;
VkPipelineStageFlagBits currentPipelineStage_;
size_t currentBackbufferIndex_ = 0;
size_t currentImageIndex_ = 0;
bool valid_ = false;
static std::mutex mapMutex_;
static std::unordered_map<std::thread::id, RSVulkanSwapchain*> toBePresent_;
std::vector<VkImage> GetImages() const;
bool CreateSwapchainImages(GrDirectContext* skiaContext, SkColorType colorType, sk_sp<SkColorSpace> colorSpace);
sk_sp<SkSurface> CreateSkiaSurface(GrDirectContext* skiaContext, VkImage image, const SkISize& size,
SkColorType colorType, sk_sp<SkColorSpace> colorSpace) const;
RSVulkanBackbuffer* GetNextBackbuffer();
};
} // namespace OHOS::Rosen::vulkan
#endif // RS_VULKAN_VULKAN_SWAPCHAIN_H_

View File

@ -1,47 +0,0 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "vulkan_swapchain.h"
namespace OHOS::Rosen::vulkan {
RSVulkanSwapchain::RSVulkanSwapchain(const RSVulkanProcTable& procVk, const RSVulkanDevice& device,
const RSVulkanSurface& surface, GrDirectContext* skiaContext, std::unique_ptr<RSVulkanSwapchain> oldSwapchain,
uint32_t queueFamilyIndex)
{}
RSVulkanSwapchain::~RSVulkanSwapchain() = default;
bool RSVulkanSwapchain::IsValid() const
{
return false;
}
RSVulkanSwapchain::AcquireResult RSVulkanSwapchain::AcquireSurface()
{
return { AcquireStatus::ERROR_SURFACE_LOST, nullptr };
}
bool RSVulkanSwapchain::Submit()
{
return false;
}
SkISize RSVulkanSwapchain::GetSize() const
{
return SkISize::Make(0, 0);
}
} // namespace OHOS::Rosen::vulkan

View File

@ -1,113 +0,0 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "vulkan_utilities.h"
#include <algorithm>
#include <unordered_set>
namespace OHOS::Rosen::vulkan {
bool IsDebuggingEnabled()
{
#ifndef NDEBUG
return true;
#else
return false;
#endif
}
bool ValidationLayerInfoMessagesEnabled()
{
return false;
}
bool ValidationErrorsFatal()
{
return true;
}
static std::vector<std::string> InstanceOrDeviceLayersToEnable(
const RSVulkanProcTable& vk, VkPhysicalDevice physical_device)
{
if (!IsDebuggingEnabled()) {
return {};
}
// NOTE: The loader is sensitive to the ordering here. Please do not rearrange
// this list.
const std::vector<std::string> candidates = { "VK_LAYER_GOOGLE_threading", "VK_LAYER_LUNARG_parameter_validation",
"VK_LAYER_LUNARG_object_tracker", "VK_LAYER_LUNARG_core_validation", "VK_LAYER_LUNARG_device_limits",
"VK_LAYER_LUNARG_image", "VK_LAYER_LUNARG_swapchain", "VK_LAYER_GOOGLE_unique_objects" };
uint32_t count = 0;
if (physical_device == VK_NULL_HANDLE) {
if (VK_CALL_LOG_ERROR(vk.EnumerateInstanceLayerProperties(&count, nullptr)) != VK_SUCCESS) {
return {};
}
} else {
if (VK_CALL_LOG_ERROR(vk.EnumerateDeviceLayerProperties(physical_device, &count, nullptr)) != VK_SUCCESS) {
return {};
}
}
std::vector<VkLayerProperties> properties;
properties.resize(count);
if (physical_device == VK_NULL_HANDLE) {
if (VK_CALL_LOG_ERROR(vk.EnumerateInstanceLayerProperties(&count, properties.data())) != VK_SUCCESS) {
return {};
}
} else {
if (VK_CALL_LOG_ERROR(vk.EnumerateDeviceLayerProperties(physical_device, &count, properties.data())) !=
VK_SUCCESS) {
return {};
}
}
std::unordered_set<std::string> available_extensions;
std::vector<std::string> available_candidates;
for (size_t i = 0; i < count; i++) {
available_extensions.emplace(properties[i].layerName);
}
for (const auto& candidate : candidates) {
auto found = available_extensions.find(candidate);
if (found != available_extensions.end()) {
available_candidates.emplace_back(candidate);
}
}
return available_candidates;
}
std::vector<std::string> InstanceLayersToEnable(const RSVulkanProcTable& vk)
{
return InstanceOrDeviceLayersToEnable(vk, VK_NULL_HANDLE);
}
std::vector<std::string> DeviceLayersToEnable(
const RSVulkanProcTable& vk, const RSVulkanHandle<VkPhysicalDevice>& physical_device)
{
if (!physical_device) {
return {};
}
return InstanceOrDeviceLayersToEnable(vk, physical_device);
}
} // namespace OHOS::Rosen::vulkan

View File

@ -1,38 +0,0 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef RS_VULKAN_VULKAN_UTILITIES_H_
#define RS_VULKAN_VULKAN_UTILITIES_H_
#include <string>
#include <vector>
#include "vulkan_handle.h"
#include "vulkan_proc_table.h"
namespace OHOS::Rosen::vulkan {
bool IsDebuggingEnabled();
bool ValidationLayerInfoMessagesEnabled();
bool ValidationErrorsFatal();
std::vector<std::string> InstanceLayersToEnable(const RSVulkanProcTable& vk);
std::vector<std::string> DeviceLayersToEnable(
const RSVulkanProcTable& vk, const RSVulkanHandle<VkPhysicalDevice>& physicalDevice);
} // namespace OHOS::Rosen::vulkan
#endif // RS_VULKAN_VULKAN_UTILITIES_H_

View File

@ -1,379 +0,0 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "vulkan_window.h"
#include <memory>
#include <string>
#include "include/gpu/GrDirectContext.h"
#include "vulkan_application.h"
#include "vulkan_device.h"
#include "vulkan_hilog.h"
#include "vulkan_native_surface.h"
#include "vulkan_surface.h"
#include "vulkan_swapchain.h"
namespace OHOS::Rosen::vulkan {
static const int K_GR_CACHE_MAX_COUNT = 8192;
static const size_t K_GR_CACHE_MAX_BYTE_SIZE = 512 * (1 << 20);
RSVulkanProcTable* RSVulkanWindow::vk = nullptr;
std::unique_ptr<RSVulkanApplication> RSVulkanWindow::application;
std::unique_ptr<RSVulkanDevice> RSVulkanWindow::logicalDevice;
std::thread::id RSVulkanWindow::deviceThread;
std::vector<RSVulkanHandle<VkFence>> RSVulkanWindow::sharedFences;
uint32_t RSVulkanWindow::sharedFenceIndex = false;
bool RSVulkanWindow::presenting_ = false;
void RSVulkanWindow::InitializeVulkan(size_t threadNum)
{
if (sharedFences.size() < threadNum) {
sharedFences.resize(threadNum);
sharedFenceIndex = 0;
}
if (logicalDevice != nullptr) {
LOGI("Vulkan Already Initialized");
return;
}
LOGI("First Initialize Vulkan");
deviceThread = std::this_thread::get_id();
vk = new RSVulkanProcTable();
if (!vk->HasAcquiredMandatoryProcAddresses()) {
LOGE("Proc table has not acquired mandatory proc addresses.");
return;
}
// Create the application instance.
std::vector<std::string> extensions = {
VK_KHR_SURFACE_EXTENSION_NAME, // parent extension
VK_OHOS_SURFACE_EXTENSION_NAME // child extension
};
application = std::make_unique<RSVulkanApplication>(*vk, "Rosen", std::move(extensions));
if (!application->IsValid() || !vk->AreInstanceProcsSetup()) {
// Make certain the application instance was created and it setup the
// instance proc table entries.
LOGE("Instance proc addresses have not been setup.");
return;
}
// Create the device.
logicalDevice = application->AcquireFirstCompatibleLogicalDevice();
if (logicalDevice == nullptr || !logicalDevice->IsValid() || !vk->AreDeviceProcsSetup()) {
// Make certain the device was created and it setup the device proc table
// entries.
LOGE("Device proc addresses have not been setup.");
return;
}
}
RSVulkanWindow::RSVulkanWindow(std::unique_ptr<RSVulkanNativeSurface> nativeSurface, bool isOffscreen)
: valid_(false), isOffscreen_(isOffscreen)
{
LOGE("VulkanWindow init enter");
InitializeVulkan();
if (logicalDevice == nullptr) {
LOGE("InitializeVulkan failed");
return;
}
if (!isOffscreen && (nativeSurface == nullptr || !nativeSurface->IsValid())) {
LOGE("Native surface is invalid.");
return;
}
// Create the logical surface from the native platform surface.
if (!isOffscreen) {
surface_ = std::make_unique<RSVulkanSurface>(*vk, *application, std::move(nativeSurface));
if (!surface_->IsValid()) {
LOGE("Vulkan surface is invalid.");
return;
}
}
// Create the Skia GrContext.
if (!CreateSkiaGrContext()) {
LOGE("Could not create Skia context.");
return;
}
// Create the swapchain.
if (!isOffscreen && !RecreateSwapchain()) {
LOGE("Could not setup the swapchain initially.");
return;
}
LOGE("VulkanWindow init success");
valid_ = true;
}
RSVulkanWindow::~RSVulkanWindow() = default;
bool RSVulkanWindow::IsValid() const
{
return valid_;
}
GrDirectContext* RSVulkanWindow::GetSkiaGrContext()
{
return skiaGrContext_.get();
}
GrVkBackendContext& RSVulkanWindow::GetSkiaBackendContext()
{
return skBackendContext_;
}
bool RSVulkanWindow::CreateSkiaGrContext()
{
if (!CreateSkiaBackendContext(&skBackendContext_)) {
LOGE("CreateSkiaGrContext CreateSkiaBackendContext is false");
return false;
}
sk_sp<GrDirectContext> context = GrDirectContext::MakeVulkan(skBackendContext_);
if (context == nullptr) {
LOGE("CreateSkiaGrContext context is null");
return false;
}
context->setResourceCacheLimits(K_GR_CACHE_MAX_COUNT, K_GR_CACHE_MAX_BYTE_SIZE);
skiaGrContext_ = context;
return true;
}
bool RSVulkanWindow::CreateSkiaBackendContext(GrVkBackendContext* context)
{
auto getProc = vk->CreateSkiaGetProc();
if (getProc == nullptr) {
LOGE("CreateSkiaBackendContext getProc is null");
return false;
}
uint32_t skiaFeatures = 0;
if (!logicalDevice->GetPhysicalDeviceFeaturesSkia(&skiaFeatures)) {
LOGE("CreateSkiaBackendContext GetPhysicalDeviceFeaturesSkia is false");
return false;
}
context->fInstance = application->GetInstance();
context->fPhysicalDevice = logicalDevice->GetPhysicalDeviceHandle();
context->fDevice = logicalDevice->GetHandle();
context->fQueue = logicalDevice->GetQueueHandle();
context->fGraphicsQueueIndex = logicalDevice->GetGraphicsQueueIndex();
context->fMinAPIVersion = application->GetAPIVersion();
uint32_t extensionFlags = kKHR_surface_GrVkExtensionFlag;
if (!isOffscreen_) {
extensionFlags |= kKHR_swapchain_GrVkExtensionFlag;
extensionFlags |= surface_->GetNativeSurface().GetSkiaExtensionName();
}
context->fExtensions = extensionFlags;
context->fFeatures = skiaFeatures;
context->fGetProc = std::move(getProc);
context->fOwnsInstanceAndDevice = false;
return true;
}
sk_sp<SkSurface> RSVulkanWindow::AcquireSurface(int bufferCount)
{
if (isOffscreen_ || !IsValid()) {
LOGE("Surface is invalid or offscreen.");
return nullptr;
}
auto surface_size = surface_->GetSize();
if (surface_size != SkISize::Make(0, 0) && surface_size != swapchain_->GetSize()) {
LOGE("Swapchain and surface sizes are out of sync. Recreating swapchain.");
if (!RecreateSwapchain()) {
LOGE("Could not recreate swapchain.");
valid_ = false;
return nullptr;
}
}
while (true) {
sk_sp<SkSurface> surface;
auto acquireResult = RSVulkanSwapchain::AcquireStatus::ERROR_SURFACE_LOST;
std::tie(acquireResult, surface) = swapchain_->AcquireSurface(bufferCount);
if (acquireResult == RSVulkanSwapchain::AcquireStatus::SUCCESS) {
// Successfully acquired a surface from the swapchain. Nothing more to do.
return surface;
}
if (acquireResult == RSVulkanSwapchain::AcquireStatus::ERROR_SURFACE_LOST) {
// Surface is lost. This is an unrecoverable error.
LOGE("Swapchain reported surface was lost.");
return nullptr;
}
if (acquireResult == RSVulkanSwapchain::AcquireStatus::ERROR_SURFACE_OUT_OF_DATE) {
LOGE("AcquireSurface surface out of date");
if (RecreateSwapchain()) {
continue;
} else {
LOGE("Swapchain reported surface was out of date but "
"could not recreate the swapchain at the new "
"configuration.");
valid_ = false;
return nullptr;
}
}
break;
}
LOGE("Unhandled VulkanSwapchain::AcquireResult");
return nullptr;
}
bool RSVulkanWindow::SwapBuffers()
{
if (isOffscreen_ || !IsValid()) {
LOGE("Window was invalid or offscreen.");
return false;
}
if (deviceThread != std::this_thread::get_id()) {
LOGI("MT mode in VulkanWindow::SwapBuffers()");
swapchain_->AddToPresent();
return swapchain_->FlushCommands();
}
LOGI("ST mode in VulkanWindow::SwapBuffers()");
return swapchain_->Submit();
}
void RSVulkanWindow::PresentAll()
{
//-----------------------------------------
// create shared fences if not already
//-----------------------------------------
if (!sharedFences[sharedFenceIndex]) {
const VkFenceCreateInfo create_info = {
.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
.pNext = nullptr,
.flags = VK_FENCE_CREATE_SIGNALED_BIT,
};
auto fenceCollect = [](VkFence fence) {
RSVulkanWindow::vk->DestroyFence(RSVulkanWindow::logicalDevice->GetHandle(), fence, nullptr);
};
VkFence fence = VK_NULL_HANDLE;
if (VK_CALL_LOG_ERROR(vk->CreateFence(logicalDevice->GetHandle(), &create_info, nullptr, &fence)) !=
VK_SUCCESS) {
return;
}
sharedFences[sharedFenceIndex] = { fence, fenceCollect };
}
RSVulkanSwapchain::PresentAll(sharedFences[sharedFenceIndex]);
sharedFenceIndex++;
if (sharedFenceIndex >= sharedFences.size()) {
sharedFenceIndex = 0;
}
presenting_ = true;
}
bool RSVulkanWindow::WaitForSharedFence()
{
if (presenting_) {
if (sharedFences[sharedFenceIndex]) {
VkFence fence = sharedFences[sharedFenceIndex];
return VK_CALL_LOG_ERROR(vk->WaitForFences(logicalDevice->GetHandle(), 1, &fence, true,
std::numeric_limits<uint64_t>::max())) == VK_SUCCESS;
}
}
return false;
}
bool RSVulkanWindow::ResetSharedFence()
{
if (presenting_) {
presenting_ = false;
if (sharedFences[sharedFenceIndex]) {
VkFence fence = sharedFences[sharedFenceIndex];
return VK_CALL_LOG_ERROR(vk->ResetFences(logicalDevice->GetHandle(), 1, &fence)) == VK_SUCCESS;
}
}
return false;
}
VkDevice RSVulkanWindow::GetDevice()
{
return logicalDevice->GetHandle();
}
VkPhysicalDevice RSVulkanWindow::GetPhysicalDevice()
{
return logicalDevice->GetPhysicalDeviceHandle();
}
RSVulkanProcTable& RSVulkanWindow::GetVkProcTable()
{
return *vk;
}
bool RSVulkanWindow::RecreateSwapchain()
{
if (isOffscreen_) {
LOGE("offscreen vulkan window, don't need swapchian");
return false;
}
// This way, we always lose our reference to the old swapchain. Even if we
// cannot create a new one to replace it.
auto old_swapchain = std::move(swapchain_);
if (!vk->IsValid()) {
LOGE("RecreateSwapchain vk not valid");
return false;
}
if (logicalDevice == nullptr || !logicalDevice->IsValid()) {
LOGE("RecreateSwapchain logicalDevice not valid");
return false;
}
if (surface_ == nullptr || !surface_->IsValid()) {
LOGE("RecreateSwapchain surface_ not valid");
return false;
}
if (skiaGrContext_ == nullptr) {
LOGE("RecreateSwapchain skiaGrContext_ not valid");
return false;
}
auto swapchain = std::make_unique<RSVulkanSwapchain>(*vk, *logicalDevice, *surface_, skiaGrContext_.get(),
std::move(old_swapchain), logicalDevice->GetGraphicsQueueIndex());
if (!swapchain->IsValid()) {
LOGE("RecreateSwapchain swapchain not valid");
return false;
}
swapchain_ = std::move(swapchain);
return true;
}
} // namespace OHOS::Rosen::vulkan

View File

@ -1,93 +0,0 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef RS_VULKAN_VULKAN_WINDOW_H_
#define RS_VULKAN_VULKAN_WINDOW_H_
#include <memory>
#include <native_window.h>
#include <thread>
#include <tuple>
#include <utility>
#include <vector>
#include "include/core/SkRefCnt.h"
#include "include/core/SkSize.h"
#include "include/core/SkSurface.h"
#include "include/gpu/GrDirectContext.h"
#include "include/gpu/vk/GrVkBackendContext.h"
#include "vulkan_proc_table.h"
namespace OHOS::Rosen::vulkan {
class RSVulkanNativeSurface;
class RSVulkanDevice;
class RSVulkanSurface;
class RSVulkanSwapchain;
class RSVulkanImage;
class RSVulkanApplication;
class RSVulkanBackbuffer;
class RSVulkanWindow {
public:
typedef std::shared_ptr<RSVulkanWindow> Ptr;
explicit RSVulkanWindow(std::unique_ptr<RSVulkanNativeSurface> nativeSurface, bool isOffscreen = false);
~RSVulkanWindow();
bool IsValid() const;
GrDirectContext* GetSkiaGrContext();
GrVkBackendContext& GetSkiaBackendContext();
sk_sp<SkSurface> AcquireSurface(int bufferCount = -1);
bool SwapBuffers();
bool FlushCommands();
static void PresentAll();
static void InitializeVulkan(size_t threadNum = 0);
static bool WaitForSharedFence();
static bool ResetSharedFence();
static VkDevice GetDevice();
static VkPhysicalDevice GetPhysicalDevice();
static RSVulkanProcTable& GetVkProcTable();
public:
static RSVulkanProcTable* vk;
static std::unique_ptr<RSVulkanApplication> application;
static std::unique_ptr<RSVulkanDevice> logicalDevice;
static std::thread::id deviceThread;
static std::vector<RSVulkanHandle<VkFence>> sharedFences;
static uint32_t sharedFenceIndex;
static bool presenting_;
bool valid_ = false;
bool isOffscreen_ = false;
std::unique_ptr<RSVulkanSurface> surface_;
std::unique_ptr<RSVulkanSwapchain> swapchain_;
sk_sp<GrDirectContext> skiaGrContext_;
GrVkBackendContext skBackendContext_;
bool CreateSkiaGrContext();
bool CreateSkiaBackendContext(GrVkBackendContext* context);
bool RecreateSwapchain();
};
} // namespace OHOS::Rosen::vulkan
#endif // RS_VULKAN_VULKAN_WINDOW_H_