mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
vulkan: Add the function realization of arm device to kms vulkan
Signed-off-by: ZiHan Huang <zack.huang@rock-chips.com>
This commit is contained in:
parent
53f961acf5
commit
2865310bca
5 changed files with 206 additions and 1 deletions
|
@ -886,6 +886,187 @@ VkResult VulkanContext::ReinitSurface() {
|
|||
case WINDOWSYSTEM_DISPLAY:
|
||||
{
|
||||
VkDisplaySurfaceCreateInfoKHR display{ VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR };
|
||||
#if !defined(__LIBRETRO__)
|
||||
/*
|
||||
And when not to use libretro need VkDisplaySurfaceCreateInfoKHR this extension,
|
||||
then you need to use dlopen to read vulkan loader in VulkanLoader.cpp.
|
||||
huangzihan China
|
||||
*/
|
||||
|
||||
if(!vkGetPhysicalDeviceDisplayPropertiesKHR ||
|
||||
!vkGetPhysicalDeviceDisplayPlanePropertiesKHR ||
|
||||
!vkGetDisplayModePropertiesKHR ||
|
||||
!vkGetDisplayPlaneSupportedDisplaysKHR ||
|
||||
!vkGetDisplayPlaneCapabilitiesKHR ) {
|
||||
_assert_msg_(false, "DISPLAY Vulkan cannot find any vulkan function symbols.");
|
||||
return VK_ERROR_INITIALIZATION_FAILED;
|
||||
}
|
||||
|
||||
//The following code is for reference:
|
||||
// https://github.com/vanfanel/ppsspp
|
||||
// When using the VK_KHR_display extension and not using LIBRETRO, a complete
|
||||
// VkDisplaySurfaceCreateInfoKHR is needed.
|
||||
|
||||
uint32_t display_count;
|
||||
uint32_t plane_count;
|
||||
|
||||
VkDisplayPropertiesKHR *display_props = NULL;
|
||||
VkDisplayPlanePropertiesKHR *plane_props = NULL;
|
||||
VkDisplayModePropertiesKHR* mode_props = NULL;
|
||||
|
||||
VkExtent2D image_size;
|
||||
// This is the chosen physical_device, it has been chosen elsewhere.
|
||||
VkPhysicalDevice phys_device = physical_devices_[physical_device_];
|
||||
VkDisplayModeKHR display_mode = VK_NULL_HANDLE;
|
||||
VkDisplayPlaneAlphaFlagBitsKHR alpha_mode = VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR;
|
||||
uint32_t plane = UINT32_MAX;
|
||||
|
||||
// For now, use the first available (connected) display.
|
||||
int display_index = 0;
|
||||
|
||||
VkResult result;
|
||||
bool ret = false;
|
||||
bool mode_found = false;
|
||||
|
||||
int i, j;
|
||||
|
||||
// 1 physical device can have N displays connected.
|
||||
// Vulkan only counts the connected displays.
|
||||
|
||||
// Get a list of displays on the physical device.
|
||||
display_count = 0;
|
||||
vkGetPhysicalDeviceDisplayPropertiesKHR(phys_device, &display_count, NULL);
|
||||
if (display_count == 0) {
|
||||
_assert_msg_(false, "DISPLAY Vulkan couldn't find any displays.");
|
||||
return VK_ERROR_INITIALIZATION_FAILED;
|
||||
}
|
||||
display_props = new VkDisplayPropertiesKHR[display_count];
|
||||
vkGetPhysicalDeviceDisplayPropertiesKHR(phys_device, &display_count, display_props);
|
||||
|
||||
// Get a list of display planes on the physical device.
|
||||
plane_count = 0;
|
||||
vkGetPhysicalDeviceDisplayPlanePropertiesKHR(phys_device, &plane_count, NULL);
|
||||
if (plane_count == 0) {
|
||||
_assert_msg_(false, "DISPLAY Vulkan couldn't find any planes on the physical device");
|
||||
return VK_ERROR_INITIALIZATION_FAILED;
|
||||
|
||||
}
|
||||
plane_props = new VkDisplayPlanePropertiesKHR[plane_count];
|
||||
vkGetPhysicalDeviceDisplayPlanePropertiesKHR(phys_device, &plane_count, plane_props);
|
||||
|
||||
// Get the Vulkan display we are going to use.
|
||||
VkDisplayKHR myDisplay = display_props[display_index].display;
|
||||
|
||||
// Get the list of display modes of the display
|
||||
uint32_t mode_count = 0;
|
||||
vkGetDisplayModePropertiesKHR(phys_device, myDisplay, &mode_count, NULL);
|
||||
if (mode_count == 0) {
|
||||
_assert_msg_(false, "DISPLAY Vulkan couldn't find any video modes on the display");
|
||||
return VK_ERROR_INITIALIZATION_FAILED;
|
||||
}
|
||||
mode_props = new VkDisplayModePropertiesKHR[mode_count];
|
||||
vkGetDisplayModePropertiesKHR(phys_device, myDisplay, &mode_count, mode_props);
|
||||
|
||||
// See if there's an appropiate mode available on the display
|
||||
display_mode = VK_NULL_HANDLE;
|
||||
for (i = 0; i < mode_count; ++i)
|
||||
{
|
||||
const VkDisplayModePropertiesKHR* mode = &mode_props[i];
|
||||
|
||||
if (mode->parameters.visibleRegion.width == pixel_xres &&
|
||||
mode->parameters.visibleRegion.height == pixel_yres)
|
||||
{
|
||||
display_mode = mode->displayMode;
|
||||
mode_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Free the mode list now.
|
||||
delete [] mode_props;
|
||||
|
||||
// If there are no useable modes found on the display, error out
|
||||
if (display_mode == VK_NULL_HANDLE)
|
||||
{
|
||||
_assert_msg_(false, "DISPLAY Vulkan couldn't find any video modes on the display");
|
||||
return VK_ERROR_INITIALIZATION_FAILED;
|
||||
}
|
||||
|
||||
/* Iterate on the list of planes of the physical device
|
||||
to find a plane that matches these criteria:
|
||||
-It must be compatible with the chosen display + mode.
|
||||
-It isn't currently bound to another display.
|
||||
-It supports per-pixel alpha, if possible. */
|
||||
for (i = 0; i < plane_count; i++) {
|
||||
uint32_t supported_displays_count = 0;
|
||||
VkDisplayKHR* supported_displays;
|
||||
VkDisplayPlaneCapabilitiesKHR plane_caps;
|
||||
|
||||
/* See if the plane is compatible with the current display. */
|
||||
vkGetDisplayPlaneSupportedDisplaysKHR(phys_device, i, &supported_displays_count, NULL);
|
||||
if (supported_displays_count == 0) {
|
||||
/* This plane doesn't support any displays. Continue to the next plane. */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Get the list of displays supported by this plane. */
|
||||
supported_displays = new VkDisplayKHR[supported_displays_count];
|
||||
vkGetDisplayPlaneSupportedDisplaysKHR(phys_device, i,
|
||||
&supported_displays_count, supported_displays);
|
||||
|
||||
/* The plane must be bound to the chosen display, or not in use.
|
||||
If none of these is true, iterate to another plane. */
|
||||
if ( !( (plane_props[i].currentDisplay == myDisplay) ||
|
||||
(plane_props[i].currentDisplay == VK_NULL_HANDLE)))
|
||||
continue;
|
||||
|
||||
/* Iterate the list of displays supported by this plane
|
||||
in order to find out if the chosen display is among them. */
|
||||
bool plane_supports_display = false;
|
||||
for (j = 0; j < supported_displays_count; j++) {
|
||||
if (supported_displays[j] == myDisplay) {
|
||||
plane_supports_display = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Free the list of displays supported by this plane. */
|
||||
delete [] supported_displays;
|
||||
|
||||
/* If the display is not supported by this plane, iterate to the next plane. */
|
||||
if (!plane_supports_display)
|
||||
continue;
|
||||
|
||||
/* Want a plane that supports the alpha mode we have chosen. */
|
||||
vkGetDisplayPlaneCapabilitiesKHR(phys_device, display_mode, i, &plane_caps);
|
||||
if (plane_caps.supportedAlpha & alpha_mode) {
|
||||
/* Yep, this plane is alright. */
|
||||
plane = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we couldn't find an appropiate plane, error out. */
|
||||
if (plane == UINT32_MAX) {
|
||||
_assert_msg_(false, "DISPLAY Vulkan couldn't find an appropiate plane");
|
||||
return VK_ERROR_INITIALIZATION_FAILED;
|
||||
}
|
||||
|
||||
// Finally, create the vulkan surface.
|
||||
image_size.width = pixel_xres;
|
||||
image_size.height = pixel_yres;
|
||||
|
||||
display.displayMode = display_mode;
|
||||
display.imageExtent = image_size;
|
||||
display.transform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
|
||||
display.alphaMode = alpha_mode;
|
||||
display.globalAlpha = 1.0f;
|
||||
display.planeIndex = plane;
|
||||
display.planeStackIndex = plane_props[plane].currentStackIndex;
|
||||
display.pNext = nullptr;
|
||||
delete [] display_props;
|
||||
delete [] plane_props;
|
||||
#endif
|
||||
display.flags = 0;
|
||||
retval = vkCreateDisplayPlaneSurfaceKHR(instance_, &display, nullptr, &surface_);
|
||||
break;
|
||||
|
|
|
@ -195,6 +195,11 @@ PFN_vkCreateWaylandSurfaceKHR vkCreateWaylandSurfaceKHR;
|
|||
#endif
|
||||
#if defined(VK_USE_PLATFORM_DISPLAY_KHR)
|
||||
PFN_vkCreateDisplayPlaneSurfaceKHR vkCreateDisplayPlaneSurfaceKHR;
|
||||
PFN_vkGetPhysicalDeviceDisplayPropertiesKHR vkGetPhysicalDeviceDisplayPropertiesKHR;
|
||||
PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR vkGetPhysicalDeviceDisplayPlanePropertiesKHR;
|
||||
PFN_vkGetDisplayModePropertiesKHR vkGetDisplayModePropertiesKHR;
|
||||
PFN_vkGetDisplayPlaneSupportedDisplaysKHR vkGetDisplayPlaneSupportedDisplaysKHR;
|
||||
PFN_vkGetDisplayPlaneCapabilitiesKHR vkGetDisplayPlaneCapabilitiesKHR;
|
||||
#endif
|
||||
|
||||
PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR;
|
||||
|
@ -564,6 +569,11 @@ void VulkanLoadInstanceFunctions(VkInstance instance, const VulkanExtensions &en
|
|||
#endif
|
||||
#if defined(VK_USE_PLATFORM_DISPLAY_KHR)
|
||||
LOAD_INSTANCE_FUNC(instance, vkCreateDisplayPlaneSurfaceKHR);
|
||||
LOAD_INSTANCE_FUNC(instance, vkGetPhysicalDeviceDisplayPropertiesKHR);
|
||||
LOAD_INSTANCE_FUNC(instance, vkGetPhysicalDeviceDisplayPlanePropertiesKHR);
|
||||
LOAD_INSTANCE_FUNC(instance, vkGetDisplayModePropertiesKHR);
|
||||
LOAD_INSTANCE_FUNC(instance, vkGetDisplayPlaneSupportedDisplaysKHR);
|
||||
LOAD_INSTANCE_FUNC(instance, vkGetDisplayPlaneCapabilitiesKHR);
|
||||
#endif
|
||||
|
||||
LOAD_INSTANCE_FUNC(instance, vkDestroySurfaceKHR);
|
||||
|
|
|
@ -194,6 +194,11 @@ extern PFN_vkCreateWaylandSurfaceKHR vkCreateWaylandSurfaceKHR;
|
|||
#endif
|
||||
#if defined(VK_USE_PLATFORM_DISPLAY_KHR)
|
||||
extern PFN_vkCreateDisplayPlaneSurfaceKHR vkCreateDisplayPlaneSurfaceKHR;
|
||||
extern PFN_vkGetPhysicalDeviceDisplayPropertiesKHR vkGetPhysicalDeviceDisplayPropertiesKHR;
|
||||
extern PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR vkGetPhysicalDeviceDisplayPlanePropertiesKHR;
|
||||
extern PFN_vkGetDisplayModePropertiesKHR vkGetDisplayModePropertiesKHR;
|
||||
extern PFN_vkGetDisplayPlaneSupportedDisplaysKHR vkGetDisplayPlaneSupportedDisplaysKHR;
|
||||
extern PFN_vkGetDisplayPlaneCapabilitiesKHR vkGetDisplayPlaneCapabilitiesKHR;
|
||||
#endif
|
||||
|
||||
extern PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR;
|
||||
|
|
|
@ -768,7 +768,7 @@ int main(int argc, char *argv[]) {
|
|||
#if !PPSSPP_PLATFORM(SWITCH)
|
||||
} else if (g_Config.iGPUBackend == (int)GPUBackend::VULKAN) {
|
||||
SDLVulkanGraphicsContext *ctx = new SDLVulkanGraphicsContext();
|
||||
if (!ctx->Init(window, x, y, mode, &error_message)) {
|
||||
if (!ctx->Init(window, x, y, mode | SDL_WINDOW_VULKAN, &error_message)) {
|
||||
printf("Vulkan init error '%s' - falling back to GL\n", error_message.c_str());
|
||||
g_Config.iGPUBackend = (int)GPUBackend::OPENGL;
|
||||
SetGPUBackend((GPUBackend)g_Config.iGPUBackend);
|
||||
|
|
|
@ -110,6 +110,15 @@ bool SDLVulkanGraphicsContext::Init(SDL_Window *&window, int x, int y, int mode,
|
|||
vulkan_->InitSurface(WINDOWSYSTEM_METAL_EXT, makeWindowMetalCompatible(sys_info.info.uikit.window), nullptr);
|
||||
break;
|
||||
#endif
|
||||
#endif
|
||||
#if defined(VK_USE_PLATFORM_DISPLAY_KHR)
|
||||
case WINDOWSYSTEM_DISPLAY:
|
||||
/*
|
||||
There is no problem passing null for the next two arguments, and reinit will be called later
|
||||
huangzihan china
|
||||
*/
|
||||
vulkan_->InitSurface(WINDOWSYSTEM_DISPLAY, nullptr, nullptr);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
fprintf(stderr, "Vulkan subsystem %d not supported\n", sys_info.subsystem);
|
||||
|
|
Loading…
Add table
Reference in a new issue