mirror of
https://gitee.com/openharmony/graphic_graphic_2d
synced 2024-11-23 07:02:25 +00:00
回退vulkan shell提交
Signed-off-by: 凯鑫 <liukaixin@huawei.com>
This commit is contained in:
parent
91a856ed0d
commit
9915ae2b46
@ -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",
|
||||
|
@ -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>();
|
||||
|
@ -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_;
|
||||
|
@ -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"
|
||||
}
|
||||
}
|
@ -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
|
@ -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_
|
@ -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
|
@ -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_
|
@ -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
|
@ -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_
|
@ -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
|
@ -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_
|
@ -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
|
@ -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_
|
@ -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_
|
@ -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
|
@ -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
|
@ -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_
|
@ -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
|
@ -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_
|
@ -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_
|
@ -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
|
@ -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_
|
@ -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
|
@ -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_
|
@ -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_
|
@ -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
|
@ -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_
|
@ -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
|
@ -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_
|
@ -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
|
@ -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
|
@ -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_
|
@ -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
|
@ -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_
|
Loading…
Reference in New Issue
Block a user