Avoid including platform-specific headers in VulkanContext.h

This commit is contained in:
Henrik Rydgård 2017-12-18 12:22:12 +01:00
parent 525cce095a
commit 2250ef799c
7 changed files with 102 additions and 131 deletions

View file

@ -95,13 +95,13 @@ VulkanContext::VulkanContext() {
GetInstanceLayerExtensionList(nullptr, instance_extension_properties_);
}
VkResult VulkanContext::CreateInstance(const char *app_name, int app_ver, uint32_t flags) {
VkResult VulkanContext::CreateInstance(const CreateInfo &info) {
if (!vkCreateInstance) {
init_error_ = "Vulkan not loaded - can't create instance";
return VK_ERROR_INITIALIZATION_FAILED;
}
flags_ = flags;
flags_ = info.flags;
// List extensions to try to enable.
instance_extensions_enabled_.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
@ -120,9 +120,9 @@ VkResult VulkanContext::CreateInstance(const char *app_name, int app_ver, uint32
}
VkApplicationInfo app_info { VK_STRUCTURE_TYPE_APPLICATION_INFO };
app_info.pApplicationName = app_name;
app_info.applicationVersion = app_ver;
app_info.pEngineName = app_name;
app_info.pApplicationName = info.app_name;
app_info.applicationVersion = info.app_ver;
app_info.pEngineName = info.app_name;
// Let's increment this when we make major engine/context changes.
app_info.engineVersion = 2;
app_info.apiVersion = VK_API_VERSION_1_0;
@ -583,65 +583,61 @@ void VulkanContext::DestroyDebugMsgCallback() {
}
}
void VulkanContext::InitSurface(WindowSystem winsys, void *data1, void *data2, int width, int height) {
winsys_ = winsys;
winsysData1_ = data1;
winsysData2_ = data2;
ReinitSurface(width, height);
}
void VulkanContext::ReinitSurface(int width, int height) {
if (surface_ != VK_NULL_HANDLE) {
ILOG("Destroying Vulkan surface (%d, %d)", width_, height_);
vkDestroySurfaceKHR(instance_, surface_, nullptr);
surface_ = VK_NULL_HANDLE;
}
ILOG("Creating Vulkan surface (%d, %d)", width, height);
switch (winsys_) {
#ifdef _WIN32
void VulkanContext::InitSurfaceWin32(HINSTANCE conn, HWND wnd) {
connection = conn;
window = wnd;
case WINDOWSYSTEM_WIN32:
{
HINSTANCE connection = (HINSTANCE)winsysData1_;
HWND window = (HWND)winsysData2_;
ReinitSurfaceWin32();
}
RECT rc;
GetClientRect(window, &rc);
width = rc.right - rc.left;
height = rc.bottom - rc.top;
void VulkanContext::ReinitSurfaceWin32() {
if (surface_ != VK_NULL_HANDLE) {
vkDestroySurfaceKHR(instance_, surface_, nullptr);
surface_ = VK_NULL_HANDLE;
VkWin32SurfaceCreateInfoKHR win32{ VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR };
win32.flags = 0;
win32.hwnd = window;
win32.hinstance = connection;
VkResult res = vkCreateWin32SurfaceKHR(instance_, &win32, nullptr, &surface_);
assert(res == VK_SUCCESS);
break;
}
RECT rc;
GetClientRect(window, &rc);
width_ = rc.right - rc.left;
height_ = rc.bottom - rc.top;
VkResult U_ASSERT_ONLY res;
VkWin32SurfaceCreateInfoKHR win32 = { VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR };
win32.flags = 0;
win32.hwnd = window;
win32.hinstance = connection;
res = vkCreateWin32SurfaceKHR(instance_, &win32, nullptr, &surface_);
assert(res == VK_SUCCESS);
}
#elif defined(__ANDROID__)
void VulkanContext::InitSurfaceAndroid(ANativeWindow *wnd, int width, int height) {
native_window = wnd;
ReinitSurfaceAndroid(width, height);
}
void VulkanContext::ReinitSurfaceAndroid(int width, int height) {
if (surface_ != VK_NULL_HANDLE) {
ILOG("Destroying Android Vulkan surface (%d, %d)", width_, height_);
vkDestroySurfaceKHR(instance_, surface_, nullptr);
surface_ = VK_NULL_HANDLE;
#endif
#if defined(__ANDROID__)
case WINDOWSYSTEM_ANDROID:
{
ANativeWindow *wnd = (ANativeWindow *)winsysData1_;
VkAndroidSurfaceCreateInfoKHR android{ VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR };
android.flags = 0;
android.window = wnd;
VkResult res = vkCreateAndroidSurfaceKHR(instance_, &android, nullptr, &surface_);
assert(res == VK_SUCCESS);
break;
}
#endif
default:
_assert_msg_(G3D, false, "Vulkan support for chosen window system not implemented");
break;
}
VkResult U_ASSERT_ONLY res;
ILOG("Creating Android Vulkan surface (%d, %d)", width, height);
VkAndroidSurfaceCreateInfoKHR android = { VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR };
android.flags = 0;
android.window = native_window;
res = vkCreateAndroidSurfaceKHR(instance_, &android, nullptr, &surface_);
assert(res == VK_SUCCESS);
width_ = width;
height_ = height;
}
#endif
bool VulkanContext::InitQueue() {
// Iterate over each queue to learn whether it supports presenting:
@ -732,11 +728,8 @@ bool VulkanContext::InitQueue() {
}
bool VulkanContext::InitSwapchain() {
VkResult U_ASSERT_ONLY res;
res = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physical_devices_[physical_device_], surface_, &surfCapabilities_);
VkResult res = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physical_devices_[physical_device_], surface_, &surfCapabilities_);
assert(res == VK_SUCCESS);
uint32_t presentModeCount;
res = vkGetPhysicalDeviceSurfacePresentModesKHR(physical_devices_[physical_device_], surface_, &presentModeCount, nullptr);
assert(res == VK_SUCCESS);

View file

@ -1,41 +1,16 @@
#ifndef UTIL_INIT
#define UTIL_INIT
#pragma once
#ifdef __ANDROID__
#undef NDEBUG // asserts
#endif
#include <cassert>
#include <string>
#include <vector>
#include <utility>
#include "base/logging.h"
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#define VK_USE_PLATFORM_WIN32_KHR
#define NOMINMAX /* Don't let Windows define min() or max() */
#define APP_NAME_STR_LEN 80
#include <Windows.h>
#elif defined(__ANDROID__) // _WIN32
#include <android/native_window_jni.h>
#define VK_USE_PLATFORM_ANDROID_KHR
#else
#define VK_USE_PLATFORM_XCB_KHR
#include <unistd.h>
#endif // _WIN32
#include "Common/Vulkan/VulkanLoader.h"
// Amount of time, in nanoseconds, to wait for a command buffer to complete
#define FENCE_TIMEOUT 10000000000
#if defined(NDEBUG) && defined(__GNUC__)
#define U_ASSERT_ONLY __attribute__((unused))
#else
#define U_ASSERT_ONLY
#endif
enum {
VULKAN_FLAG_VALIDATE = 1,
VULKAN_FLAG_PRESENT_MAILBOX = 2,
@ -54,6 +29,15 @@ enum {
std::string VulkanVendorString(uint32_t vendorId);
// Not all will be usable on all platforms, of course...
enum WindowSystem {
#ifdef _WIN32
WINDOWSYSTEM_WIN32,
#endif
#ifdef __ANDROID__
WINDOWSYSTEM_ANDROID,
#endif
};
struct VulkanPhysicalDeviceInfo {
VkFormat preferredDepthStencilFormat;
@ -117,7 +101,13 @@ public:
VulkanContext();
~VulkanContext();
VkResult CreateInstance(const char *app_name, int app_ver, uint32_t flags);
struct CreateInfo {
const char *app_name;
int app_ver;
uint32_t flags;
};
VkResult CreateInstance(const CreateInfo &info);
void DestroyInstance();
int GetBestPhysicalDevice();
@ -134,13 +124,9 @@ public:
VkPipelineCache CreatePipelineCache();
#ifdef _WIN32
void InitSurfaceWin32(HINSTANCE conn, HWND wnd);
void ReinitSurfaceWin32();
#elif __ANDROID__
void InitSurfaceAndroid(ANativeWindow *native_window, int width, int height);
void ReinitSurfaceAndroid(int width, int height);
#endif
// The parameters are whatever the chosen window system wants.
void InitSurface(WindowSystem winsys, void *data1, void *data2, int width = -1, int height = -1);
void ReinitSurface(int width = -1, int height = -1);
bool InitQueue();
bool InitObjects();
bool InitSwapchain();
@ -238,12 +224,11 @@ private:
bool CheckLayers(const std::vector<LayerProperties> &layer_props, const std::vector<const char *> &layer_names) const;
#ifdef _WIN32
HINSTANCE connection = nullptr; // hInstance - Windows Instance
HWND window = nullptr; // hWnd - window handle
#elif __ANDROID__ // _WIN32
ANativeWindow *native_window = nullptr;
#endif // _WIN32
WindowSystem winsys_;
// Don't use the real types here to avoid having to include platform-specific stuff
// that we really don't want in everything that uses VulkanContext.
void *winsysData1_;
void *winsysData2_;
VkInstance instance_ = VK_NULL_HANDLE;
VkDevice device_ = VK_NULL_HANDLE;
@ -320,6 +305,3 @@ void finalize_glslang();
bool GLSLtoSPV(const VkShaderStageFlagBits shader_type, const char *pshader, std::vector<uint32_t> &spirv, std::string *errorMessage = nullptr);
const char *VulkanResultToString(VkResult res);
#endif // UTIL_INIT

View file

@ -21,9 +21,7 @@ void VulkanTexture::CreateMappableImage() {
vulkan_->Delete().QueueDeleteDeviceMemory(mappableMemory);
}
bool U_ASSERT_ONLY pass;
VkImageCreateInfo image_create_info = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };
VkImageCreateInfo image_create_info{ VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };
image_create_info.imageType = VK_IMAGE_TYPE_2D;
image_create_info.format = format_;
image_create_info.extent.width = tex_width;
@ -40,7 +38,7 @@ void VulkanTexture::CreateMappableImage() {
image_create_info.flags = 0;
image_create_info.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
VkMemoryAllocateInfo mem_alloc = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO };
VkMemoryAllocateInfo mem_alloc{ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO };
mem_alloc.allocationSize = 0;
mem_alloc.memoryTypeIndex = 0;
@ -55,7 +53,7 @@ void VulkanTexture::CreateMappableImage() {
mem_alloc.allocationSize = mem_reqs.size;
// Find the memory type that is host mappable.
pass = vulkan_->MemoryTypeFromProperties(mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &mem_alloc.memoryTypeIndex);
bool pass = vulkan_->MemoryTypeFromProperties(mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &mem_alloc.memoryTypeIndex);
assert(pass);
res = vkAllocateMemory(vulkan_->GetDevice(), &mem_alloc, NULL, &mappableMemory);

View file

@ -46,7 +46,7 @@
// and use the same render pass configuration (clear to black). However, we can later change this so we switch
// to a non-clearing render pass in buffered mode, which might be a tiny bit faster.
#include <assert.h>
#include <cassert>
#include <crtdbg.h>
#include <sstream>
@ -93,13 +93,15 @@ bool WindowsVulkanContext::Init(HINSTANCE hInst, HWND hWnd, std::string *error_m
g_Vulkan = nullptr;
return false;
}
// int vulkanFlags = VULKAN_FLAG_PRESENT_FIFO_RELAXED;
int vulkanFlags = VULKAN_FLAG_PRESENT_MAILBOX;
VulkanContext::CreateInfo info{};
info.app_name = "PPSSPP";
info.app_ver = gitVer.ToInteger();
info.flags = VULKAN_FLAG_PRESENT_MAILBOX;
if (g_validate_) {
vulkanFlags |= VULKAN_FLAG_VALIDATE;
info.flags |= VULKAN_FLAG_VALIDATE;
}
if (VK_SUCCESS != g_Vulkan->CreateInstance("PPSSPP", gitVer.ToInteger(), vulkanFlags)) {
if (VK_SUCCESS != g_Vulkan->CreateInstance(info)) {
*error_message = g_Vulkan->InitError();
delete g_Vulkan;
g_Vulkan = nullptr;
@ -119,7 +121,7 @@ bool WindowsVulkanContext::Init(HINSTANCE hInst, HWND hWnd, std::string *error_m
int bits = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
g_Vulkan->InitDebugMsgCallback(&Vulkan_Dbg, bits, &g_LogOptions);
}
g_Vulkan->InitSurfaceWin32(hInst, hWnd);
g_Vulkan->InitSurface(WINDOWSYSTEM_WIN32, (void *)hInst, (void *)hWnd);
if (!g_Vulkan->InitObjects()) {
*error_message = g_Vulkan->InitError();
Shutdown();
@ -160,22 +162,16 @@ void WindowsVulkanContext::Shutdown() {
finalize_glslang();
}
void WindowsVulkanContext::SwapBuffers() {
}
void WindowsVulkanContext::Resize() {
draw_->HandleEvent(Draw::Event::LOST_BACKBUFFER, g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight());
g_Vulkan->DestroyObjects();
g_Vulkan->ReinitSurfaceWin32();
g_Vulkan->ReinitSurface();
g_Vulkan->InitObjects();
draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight());
}
void WindowsVulkanContext::SwapInterval(int interval) {
}
void *WindowsVulkanContext::GetAPIContext() {
return g_Vulkan;
}

View file

@ -26,8 +26,8 @@ public:
WindowsVulkanContext() : draw_(nullptr) {}
bool Init(HINSTANCE hInst, HWND window, std::string *error_message) override;
void Shutdown() override;
void SwapInterval(int interval) override;
void SwapBuffers() override;
void SwapInterval(int interval) override {}
void SwapBuffers() override {}
void Resize() override;
void *GetAPIContext();

View file

@ -284,13 +284,17 @@ bool AndroidVulkanContext::Init(ANativeWindow *wnd, int desiredBackbufferSizeX,
g_LogOptions.breakOnWarning = true;
g_LogOptions.msgBoxOnError = false;
ILOG("Creating vulkan context");
ILOG("Creating Vulkan context");
Version gitVer(PPSSPP_GIT_VERSION);
if (!g_Vulkan) {
g_Vulkan = new VulkanContext();
}
if (VK_SUCCESS != g_Vulkan->CreateInstance("PPSSPP", gitVer.ToInteger(), VULKAN_FLAG_PRESENT_MAILBOX | VULKAN_FLAG_PRESENT_FIFO_RELAXED)) {
VulkanContext::CreateInfo info{};
info.app_name = "PPSSPP";
info.app_ver = gitVer.ToInteger();
info.flags = VULKAN_FLAG_PRESENT_MAILBOX | VULKAN_FLAG_PRESENT_FIFO_RELAXED;
if (VK_SUCCESS != g_Vulkan->CreateInstance(info)) {
ELOG("Failed to create vulkan context: %s", g_Vulkan->InitError().c_str());
System_SendMessage("toast", "No Vulkan compatible device found. Using OpenGL instead.");
delete g_Vulkan;
@ -310,7 +314,7 @@ bool AndroidVulkanContext::Init(ANativeWindow *wnd, int desiredBackbufferSizeX,
g_Vulkan->ChooseDevice(physicalDevice);
// Here we can enable device extensions if we like.
ILOG("Creating vulkan device");
ILOG("Creating Vulkan device");
if (g_Vulkan->CreateDevice() != VK_SUCCESS) {
ILOG("Failed to create vulkan device: %s", g_Vulkan->InitError().c_str());
System_SendMessage("toast", "No Vulkan driver found. Using OpenGL instead.");
@ -326,7 +330,7 @@ bool AndroidVulkanContext::Init(ANativeWindow *wnd, int desiredBackbufferSizeX,
height = pixel_yres;
}
ILOG("InitSurfaceAndroid: width=%d height=%d", width, height);
g_Vulkan->InitSurfaceAndroid(wnd, width, height);
g_Vulkan->InitSurface(WINDOWSYSTEM_ANDROID, (void *)wnd, nullptr, width, height);
if (g_validate_) {
int bits = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
g_Vulkan->InitDebugMsgCallback(&Vulkan_Dbg, bits, &g_LogOptions);
@ -386,7 +390,7 @@ void AndroidVulkanContext::Resize() {
g_Vulkan->DestroyObjects();
// backbufferResize updated these values. TODO: Notify another way?
g_Vulkan->ReinitSurfaceAndroid(pixel_xres, pixel_yres);
g_Vulkan->ReinitSurface(pixel_xres, pixel_yres);
g_Vulkan->InitObjects();
draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight());
ILOG("AndroidVulkanContext::Resize end (%d, %d)", g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight());

View file

@ -78,8 +78,6 @@ void VulkanQueueRunner::DestroyDeviceObjects() {
}
void VulkanQueueRunner::InitBackbufferRenderPass() {
VkResult U_ASSERT_ONLY res;
VkAttachmentDescription attachments[2];
attachments[0].format = vulkan_->GetSwapchainFormat();
attachments[0].samples = VK_SAMPLE_COUNT_1_BIT;
@ -139,7 +137,7 @@ void VulkanQueueRunner::InitBackbufferRenderPass() {
rp_info.dependencyCount = 1;
rp_info.pDependencies = &dep;
res = vkCreateRenderPass(vulkan_->GetDevice(), &rp_info, nullptr, &backbufferRenderPass_);
VkResult res = vkCreateRenderPass(vulkan_->GetDevice(), &rp_info, nullptr, &backbufferRenderPass_);
assert(res == VK_SUCCESS);
}