diff --git a/parallel-rdp-standalone/CMakeLists.txt b/parallel-rdp-standalone/CMakeLists.txt index b0abed0..b77f751 100644 --- a/parallel-rdp-standalone/CMakeLists.txt +++ b/parallel-rdp-standalone/CMakeLists.txt @@ -23,7 +23,6 @@ if(ENABLE_IPO AND (CMAKE_BUILD_TYPE STREQUAL "Release")) endif() if(WIN32) - find_package(OpenGL REQUIRED) add_definitions(-DVK_USE_PLATFORM_WIN32_KHR) endif() @@ -52,6 +51,8 @@ add_library(${NAME_PLUGIN_M64P} SHARED vulkan/semaphore_manager.cpp vulkan/shader.cpp vulkan/texture_format.cpp + vulkan/wsi.cpp + vulkan/wsi_timing.cpp util/logging.cpp util/thread_id.cpp util/aligned_alloc.cpp @@ -60,8 +61,9 @@ add_library(${NAME_PLUGIN_M64P} SHARED util/thread_name.cpp volk/volk.c gfx_m64p.c - glguts.c - parallel_imp.cpp) + vkguts.c + parallel_imp.cpp + wsi_platform.cpp) target_include_directories(${NAME_PLUGIN_M64P} PUBLIC parallel-rdp @@ -71,7 +73,7 @@ target_include_directories(${NAME_PLUGIN_M64P} PUBLIC util) if(WIN32) - target_link_libraries(${NAME_PLUGIN_M64P} ${OPENGL_LIBRARIES} -lwinmm) + target_link_libraries(${NAME_PLUGIN_M64P} -lwinmm) endif() target_compile_options(${NAME_PLUGIN_M64P} PRIVATE -march=x86-64-v3) diff --git a/parallel-rdp-standalone/gfx_m64p.c b/parallel-rdp-standalone/gfx_m64p.c index 53f25ef..dbbd2d6 100644 --- a/parallel-rdp-standalone/gfx_m64p.c +++ b/parallel-rdp-standalone/gfx_m64p.c @@ -50,7 +50,7 @@ #include #include "gfx_m64p.h" -#include "glguts.h" +#include "vkguts.h" #include "parallel_imp.h" #include "m64p_types.h" @@ -67,10 +67,18 @@ static ptr_ConfigSetDefaultBool ConfigSetDefaultBool = NULL; static ptr_ConfigGetParamInt ConfigGetParamInt = NULL; static ptr_ConfigGetParamBool ConfigGetParamBool = NULL; static ptr_ConfigSetParameter ConfigSetParameter = NULL; +static ptr_ConfigReceiveNetplayConfig ConfigReceiveNetplayConfig = NULL; static bool vk_initialized; static bool warn_hle; static bool plugin_initialized; + +bool window_fullscreen; +bool window_widescreen; +int32_t window_width; +int32_t window_height; +int32_t window_vsync; + void (*debug_callback)(void *, int, const char *); void *debug_call_context; @@ -145,6 +153,7 @@ EXPORT m64p_error CALL PluginStartup(m64p_dynlib_handle _CoreLibHandle, void *Co ConfigGetParamInt = (ptr_ConfigGetParamInt)DLSYM(CoreLibHandle, "ConfigGetParamInt"); ConfigGetParamBool = (ptr_ConfigGetParamBool)DLSYM(CoreLibHandle, "ConfigGetParamBool"); ConfigSetParameter = (ptr_ConfigSetParameter)DLSYM(CoreLibHandle, "ConfigSetParameter"); + ConfigReceiveNetplayConfig = (ptr_ConfigReceiveNetplayConfig)DLSYM(CoreLibHandle, "ConfigReceiveNetplayConfig"); ConfigOpenSection("Video-Parallel", &configVideoParallel); ConfigSetDefaultBool(configVideoParallel, KEY_FULLSCREEN, 0, "Use fullscreen mode if True, or windowed mode if False"); @@ -248,7 +257,11 @@ EXPORT int CALL RomOpen(void) window_width = ConfigGetParamInt(configVideoParallel, KEY_SCREEN_WIDTH); window_height = ConfigGetParamInt(configVideoParallel, KEY_SCREEN_HEIGHT); window_widescreen = ConfigGetParamBool(configVideoParallel, KEY_WIDESCREEN); - window_vsync = ConfigGetParamBool(configVideoParallel, KEY_VSYNC); + m64p_error netplay_init = ConfigReceiveNetplayConfig(NULL, 0); // A bit of a hack to determine if netplay is enabled + if (netplay_init != M64ERR_NOT_INIT) + window_vsync = 0; + else + window_vsync = ConfigGetParamBool(configVideoParallel, KEY_VSYNC); vk_rescaling = ConfigGetParamInt(configVideoParallel, KEY_UPSCALING); vk_ssreadbacks = ConfigGetParamBool(configVideoParallel, KEY_SSREADBACKS); vk_ssdither = ConfigGetParamBool(configVideoParallel, KEY_SSDITHER); @@ -322,17 +335,8 @@ EXPORT void CALL ChangeWindow(void) EXPORT void CALL ReadScreen2(void *dest, int *width, int *height, int front) { - struct frame_buffer fb = {0}; - screen_read(&fb, false); - - *width = fb.width; - *height = fb.height; - - if (dest) - { - fb.pixels = dest; - screen_read(&fb, false); - } + *width = window_width; + *height = window_height; } EXPORT void CALL SetRenderingCallback(void (*callback)(int)) @@ -344,6 +348,7 @@ EXPORT void CALL ResizeVideoOutput(int width, int height) { window_width = width; window_height = height; + vk_resize(); } EXPORT void CALL FBWrite(unsigned int addr, unsigned int size) diff --git a/parallel-rdp-standalone/glguts.c b/parallel-rdp-standalone/glguts.c deleted file mode 100644 index bbe147c..0000000 --- a/parallel-rdp-standalone/glguts.c +++ /dev/null @@ -1,411 +0,0 @@ -#include "glguts.h" -#include "gfx_m64p.h" -#include "parallel_imp.h" -#include "m64p_config.h" - -#include -#include -#include -#include -#include -#include - -/* definitions of pointers to Core video extension functions */ -static ptr_VidExt_Init CoreVideo_Init = NULL; -static ptr_VidExt_Quit CoreVideo_Quit = NULL; -static ptr_VidExt_ListFullscreenModes CoreVideo_ListFullscreenModes = NULL; -static ptr_VidExt_SetVideoMode CoreVideo_SetVideoMode = NULL; -static ptr_VidExt_SetCaption CoreVideo_SetCaption = NULL; -static ptr_VidExt_ToggleFullScreen CoreVideo_ToggleFullScreen = NULL; -static ptr_VidExt_ResizeWindow CoreVideo_ResizeWindow = NULL; -static ptr_VidExt_GL_GetProcAddress CoreVideo_GL_GetProcAddress = NULL; -static ptr_VidExt_GL_SetAttribute CoreVideo_GL_SetAttribute = NULL; -static ptr_VidExt_GL_GetAttribute CoreVideo_GL_GetAttribute = NULL; -static ptr_VidExt_GL_SwapBuffers CoreVideo_GL_SwapBuffers = NULL; -static ptr_ConfigReceiveNetplayConfig ConfigReceiveNetplayConfig = NULL; - -static PFNGLCREATESHADERPROC glCreateShader; -static PFNGLSHADERSOURCEPROC glShaderSource; -static PFNGLCOMPILESHADERPROC glCompileShader; -static PFNGLGETSHADERIVPROC glGetShaderiv; -static PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog; -static PFNGLCREATEPROGRAMPROC glCreateProgram; -static PFNGLATTACHSHADERPROC glAttachShader; -static PFNGLLINKPROGRAMPROC glLinkProgram; -static PFNGLGETPROGRAMIVPROC glGetProgramiv; -static PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog; -static PFNGLDELETESHADERPROC glDeleteShader; -static PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays; -static PFNGLDELETEPROGRAMPROC glDeleteProgram; -static PFNGLUSEPROGRAMPROC glUseProgram; -static PFNGLGENVERTEXARRAYSPROC glGenVertexArrays; -static PFNGLBINDVERTEXARRAYPROC glBindVertexArray; -static PFNGLBINDBUFFERPROC glBindBuffer; -static PFNGLGENBUFFERSPROC glGenBuffers; -static PFNGLDELETEBUFFERSPROC glDeleteBuffers; -static PFNGLBUFFERSTORAGEPROC glBufferStorage; -static PFNGLMAPBUFFERRANGEPROC glMapBufferRange; -static PFNGLUNMAPBUFFERPROC glUnmapBuffer; -static PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation; -static PFNGLUNIFORM1IPROC glUniform1i; - -static bool toggle_fs; -static int rotate_buffer; - -// framebuffer texture states -int32_t window_width; -int32_t window_height; -int32_t window_fullscreen; -int32_t window_widescreen; -int32_t window_vsync; - -#define SHADER_HEADER "#version 330 core\n" -#define TEX_FORMAT GL_RGBA -#define TEX_TYPE GL_UNSIGNED_BYTE -#define TEX_NUM 3 - -static GLuint program; -static GLuint vao; -static GLuint buffer; -static GLuint texture[TEX_NUM]; -static uint8_t *buffer_data; -static uint32_t buffer_size = (640*8) * (480*8) * sizeof(uint32_t); - -int32_t tex_width[TEX_NUM]; -int32_t tex_height[TEX_NUM]; -int display_width; -int display_height; - -#ifdef GL_DEBUG -static void gl_check_errors(void) -{ - GLenum err; - static int32_t invalid_op_count = 0; - while ((err = glGetError()) != GL_NO_ERROR) - { - // if gl_check_errors is called from a thread with no valid - // GL context, it would be stuck in an infinite loop here, since - // glGetError itself causes GL_INVALID_OPERATION, so check for a few - // cycles and abort if there are too many errors of that kind - if (err == GL_INVALID_OPERATION) - { - if (++invalid_op_count >= 100) - { - printf("gl_check_errors: invalid OpenGL context!"); - } - } - else - { - invalid_op_count = 0; - } - - char *err_str; - switch (err) - { - case GL_INVALID_OPERATION: - err_str = "INVALID_OPERATION"; - break; - case GL_INVALID_ENUM: - err_str = "INVALID_ENUM"; - break; - case GL_INVALID_VALUE: - err_str = "INVALID_VALUE"; - break; - case GL_OUT_OF_MEMORY: - err_str = "OUT_OF_MEMORY"; - break; - case GL_INVALID_FRAMEBUFFER_OPERATION: - err_str = "INVALID_FRAMEBUFFER_OPERATION"; - break; - default: - err_str = "unknown"; - } - printf("gl_check_errors: %d (%s)", err, err_str); - } -} -#else -#define gl_check_errors(...) -#endif - -static GLuint gl_shader_compile(GLenum type, const GLchar *source) -{ - GLuint shader = glCreateShader(type); - glShaderSource(shader, 1, &source, NULL); - glCompileShader(shader); - - GLint param; - glGetShaderiv(shader, GL_COMPILE_STATUS, ¶m); - - if (!param) - { - GLchar log[4096]; - glGetShaderInfoLog(shader, sizeof(log), NULL, log); - printf("%s shader error: %s\n", type == GL_FRAGMENT_SHADER ? "Frag" : "Vert", log); - } - - return shader; -} - -static GLuint gl_shader_link(GLuint vert, GLuint frag) -{ - GLuint program = glCreateProgram(); - glAttachShader(program, vert); - glAttachShader(program, frag); - glLinkProgram(program); - - GLint param; - glGetProgramiv(program, GL_LINK_STATUS, ¶m); - - if (!param) - { - GLchar log[4096]; - glGetProgramInfoLog(program, sizeof(log), NULL, log); - printf("Shader link error: %s\n", log); - } - - glDeleteShader(frag); - glDeleteShader(vert); - - return program; -} - -void screen_write(struct frame_buffer *fb) -{ - bool buffer_size_changed = tex_width[rotate_buffer] != fb->width || tex_height[rotate_buffer] != fb->height; - char* offset = NULL; - offset += rotate_buffer * buffer_size; - - glBindTexture(GL_TEXTURE_2D, texture[rotate_buffer]); - // check if the framebuffer size has changed - if (buffer_size_changed) - { - tex_width[rotate_buffer] = fb->width; - tex_height[rotate_buffer] = fb->height; - // set pitch for all unpacking operations - glPixelStorei(GL_UNPACK_ROW_LENGTH, fb->pitch); - // reallocate texture buffer on GPU - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, tex_width[rotate_buffer], - tex_height[rotate_buffer], 0, TEX_FORMAT, TEX_TYPE, offset); - } - else - { - // copy local buffer to GPU texture buffer - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, tex_width[rotate_buffer], tex_height[rotate_buffer], - TEX_FORMAT, TEX_TYPE, offset); - } - - rotate_buffer = (rotate_buffer + 1) % TEX_NUM; -} - -void screen_read(struct frame_buffer *fb, bool alpha) -{ - GLint vp[4]; - glGetIntegerv(GL_VIEWPORT, vp); - - fb->width = vp[2] & ~3; - fb->height = vp[3]; - fb->pitch = fb->width; - - if (fb->pixels) - { - glReadPixels(vp[0], vp[1], fb->width, fb->height, alpha ? GL_RGBA : GL_RGB, TEX_TYPE, fb->pixels); - } -} - -void gl_screen_render() -{ - display_width = (window_widescreen ? 854 : 640) * vk_rescaling; - display_height = 480 * vk_rescaling; - - int win_width = window_width; - int win_height = window_height; - int win_x = 0; - int win_y = 0; - int32_t hw = display_height * win_width; - int32_t wh = display_width * win_height; - - // add letterboxes or pillarboxes if the window has a different aspect ratio - // than the current display mode - if (hw > wh) { - int32_t w_max = wh / display_height; - win_x += (win_width - w_max) / 2; - win_width = w_max; - } else if (hw < wh) { - int32_t h_max = hw / display_width; - win_y += (win_height - h_max) / 2; - win_height = h_max; - } - // configure viewport - glViewport(win_x, win_y, win_width, win_height); - - // draw fullscreen triangle - glDrawArrays(GL_TRIANGLES, 0, 3); -} - -void gl_screen_clear(void) -{ - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); -} - -void gl_screen_close(void) -{ - glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); - glDeleteTextures(TEX_NUM, &texture[0]); - glDeleteVertexArrays(1, &vao); - glDeleteBuffers(1, &buffer); - glDeleteProgram(program); -} - -uint8_t* screen_get_texture_data() -{ - return buffer_data + (rotate_buffer * buffer_size); -} - -void screen_init() -{ - memset(tex_width, 0, sizeof(int32_t) * TEX_NUM); - memset(tex_height, 0, sizeof(int32_t) * TEX_NUM); - toggle_fs = false; - rotate_buffer = 0; - /* Get the core Video Extension function pointers from the library handle */ - CoreVideo_Init = (ptr_VidExt_Init)DLSYM(CoreLibHandle, "VidExt_Init"); - CoreVideo_Quit = (ptr_VidExt_Quit)DLSYM(CoreLibHandle, "VidExt_Quit"); - CoreVideo_ListFullscreenModes = (ptr_VidExt_ListFullscreenModes)DLSYM(CoreLibHandle, "VidExt_ListFullscreenModes"); - CoreVideo_SetVideoMode = (ptr_VidExt_SetVideoMode)DLSYM(CoreLibHandle, "VidExt_SetVideoMode"); - CoreVideo_SetCaption = (ptr_VidExt_SetCaption)DLSYM(CoreLibHandle, "VidExt_SetCaption"); - CoreVideo_ToggleFullScreen = (ptr_VidExt_ToggleFullScreen)DLSYM(CoreLibHandle, "VidExt_ToggleFullScreen"); - CoreVideo_ResizeWindow = (ptr_VidExt_ResizeWindow)DLSYM(CoreLibHandle, "VidExt_ResizeWindow"); - CoreVideo_GL_GetProcAddress = (ptr_VidExt_GL_GetProcAddress)DLSYM(CoreLibHandle, "VidExt_GL_GetProcAddress"); - CoreVideo_GL_SetAttribute = (ptr_VidExt_GL_SetAttribute)DLSYM(CoreLibHandle, "VidExt_GL_SetAttribute"); - CoreVideo_GL_GetAttribute = (ptr_VidExt_GL_GetAttribute)DLSYM(CoreLibHandle, "VidExt_GL_GetAttribute"); - CoreVideo_GL_SwapBuffers = (ptr_VidExt_GL_SwapBuffers)DLSYM(CoreLibHandle, "VidExt_GL_SwapBuffers"); - ConfigReceiveNetplayConfig = (ptr_ConfigReceiveNetplayConfig)DLSYM(CoreLibHandle, "ConfigReceiveNetplayConfig"); - - CoreVideo_Init(); - - CoreVideo_GL_SetAttribute(M64P_GL_CONTEXT_PROFILE_MASK, M64P_GL_CONTEXT_PROFILE_CORE); - CoreVideo_GL_SetAttribute(M64P_GL_CONTEXT_MAJOR_VERSION, 3); - CoreVideo_GL_SetAttribute(M64P_GL_CONTEXT_MINOR_VERSION, 3); - - m64p_error netplay_init = ConfigReceiveNetplayConfig(NULL, 0); // A bit of a hack to determine if netplay is enabled - if (netplay_init == M64ERR_NOT_INIT) - CoreVideo_GL_SetAttribute(M64P_GL_SWAP_CONTROL, window_vsync); - - CoreVideo_SetVideoMode(window_width, window_height, 0, window_fullscreen ? M64VIDEO_FULLSCREEN : M64VIDEO_WINDOWED, M64VIDEOFLAG_SUPPORT_RESIZING); - - CoreVideo_SetCaption("Mupen64Plus-Parallel"); - - glCreateShader = (PFNGLCREATESHADERPROC) CoreVideo_GL_GetProcAddress("glCreateShader"); - glShaderSource = (PFNGLSHADERSOURCEPROC) CoreVideo_GL_GetProcAddress("glShaderSource"); - glCompileShader = (PFNGLCOMPILESHADERPROC) CoreVideo_GL_GetProcAddress("glCompileShader"); - glGetShaderiv = (PFNGLGETSHADERIVPROC) CoreVideo_GL_GetProcAddress("glGetShaderiv"); - glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC) CoreVideo_GL_GetProcAddress("glGetShaderInfoLog"); - glCreateProgram = (PFNGLCREATEPROGRAMPROC) CoreVideo_GL_GetProcAddress("glCreateProgram"); - glAttachShader = (PFNGLATTACHSHADERPROC) CoreVideo_GL_GetProcAddress("glAttachShader"); - glLinkProgram = (PFNGLLINKPROGRAMPROC) CoreVideo_GL_GetProcAddress("glLinkProgram"); - glGetProgramiv = (PFNGLGETPROGRAMIVPROC) CoreVideo_GL_GetProcAddress("glGetProgramiv"); - glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC) CoreVideo_GL_GetProcAddress("glGetProgramInfoLog"); - glDeleteShader = (PFNGLDELETESHADERPROC) CoreVideo_GL_GetProcAddress("glDeleteShader"); - glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSPROC) CoreVideo_GL_GetProcAddress("glDeleteVertexArrays"); - glDeleteProgram = (PFNGLDELETEPROGRAMPROC) CoreVideo_GL_GetProcAddress("glDeleteProgram"); - glUseProgram = (PFNGLUSEPROGRAMPROC) CoreVideo_GL_GetProcAddress("glUseProgram"); - glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC) CoreVideo_GL_GetProcAddress("glGenVertexArrays"); - glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC) CoreVideo_GL_GetProcAddress("glBindVertexArray"); - glBindBuffer = (PFNGLBINDBUFFERPROC) CoreVideo_GL_GetProcAddress("glBindBuffer"); - glGenBuffers = (PFNGLGENBUFFERSPROC) CoreVideo_GL_GetProcAddress("glGenBuffers"); - glDeleteBuffers = (PFNGLDELETEBUFFERSPROC) CoreVideo_GL_GetProcAddress("glDeleteBuffers"); - glBufferStorage = (PFNGLBUFFERSTORAGEPROC) CoreVideo_GL_GetProcAddress("glBufferStorage"); - glMapBufferRange = (PFNGLMAPBUFFERRANGEPROC) CoreVideo_GL_GetProcAddress("glMapBufferRange"); - glUnmapBuffer = (PFNGLUNMAPBUFFERPROC) CoreVideo_GL_GetProcAddress("glUnmapBuffer"); - glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC) CoreVideo_GL_GetProcAddress("glGetUniformLocation"); - glUniform1i = (PFNGLUNIFORM1IPROC) CoreVideo_GL_GetProcAddress("glUniform1i"); - - // shader sources for drawing a clipped full-screen triangle. the geometry - // is defined by the vertex ID, so a VBO is not required. - const GLchar *vert_shader = - SHADER_HEADER - "out vec2 uv;\n" - "void main(void) {\n" - " uv = vec2((gl_VertexID << 1) & 2, gl_VertexID & 2);\n" - " gl_Position = vec4(uv * vec2(2.0, -2.0) + vec2(-1.0, 1.0), 0.0, 1.0);\n" - "}\n"; - - const GLchar *frag_shader = - SHADER_HEADER - "in vec2 uv;\n" - "layout(location = 0) out vec4 color;\n" - "uniform sampler2D tex0;\n" - "void main(void) {\n" - "color = texture(tex0, uv);\n" - "}\n"; - - // compile and link OpenGL program - GLuint vert = gl_shader_compile(GL_VERTEX_SHADER, vert_shader); - GLuint frag = gl_shader_compile(GL_FRAGMENT_SHADER, frag_shader); - program = gl_shader_link(vert, frag); - glUseProgram(program); - - // prepare dummy VAO - glGenVertexArrays(1, &vao); - glBindVertexArray(vao); - - // prepare texture - glGenTextures(TEX_NUM, &texture[0]); - for (int i = 0; i < TEX_NUM; ++i) - { - glBindTexture(GL_TEXTURE_2D, texture[i]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - } - - glGenBuffers(1, &buffer); - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer); - glBufferStorage(GL_PIXEL_UNPACK_BUFFER, buffer_size * TEX_NUM, 0, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT); - buffer_data = glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, buffer_size * TEX_NUM, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT); - - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - - // check if there was an error when using any of the commands above - gl_check_errors(); -} - -void screen_swap(bool blank) -{ - if (toggle_fs) - { - CoreVideo_ToggleFullScreen(); - toggle_fs = false; - } - - gl_screen_clear(); - - if (!blank) - { - gl_screen_render(); - } - - (*render_callback)(1); - CoreVideo_GL_SwapBuffers(); -} - -void screen_set_fullscreen(bool _fullscreen) -{ - toggle_fs = true; -} - -bool screen_get_fullscreen() -{ - return false; -} - -void screen_toggle_fullscreen() -{ - screen_set_fullscreen(!screen_get_fullscreen()); -} - -void screen_close(void) -{ - gl_screen_close(); - - CoreVideo_Quit(); -} diff --git a/parallel-rdp-standalone/glguts.h b/parallel-rdp-standalone/glguts.h deleted file mode 100644 index a06ff8a..0000000 --- a/parallel-rdp-standalone/glguts.h +++ /dev/null @@ -1,46 +0,0 @@ -#pragma once - -#include "m64p_vidext.h" -#include -#include - -#ifdef __cplusplus -extern "C" -{ -#endif - - struct video_pixel - { - uint8_t r; - uint8_t g; - uint8_t b; - uint8_t a; - }; - - struct frame_buffer - { - struct video_pixel *pixels; - uint32_t width; - uint32_t height; - uint32_t pitch; - bool valid; - }; - - void screen_write(struct frame_buffer *fb); - void screen_read(struct frame_buffer *fb, bool alpha); - void screen_init(); - void screen_update(void); - void screen_toggle_fullscreen(void); - void screen_close(void); - void screen_swap(bool blank); - uint8_t* screen_get_texture_data(); - - extern int32_t window_width; - extern int32_t window_height; - extern int32_t window_fullscreen; - extern int32_t window_widescreen; - extern int32_t window_vsync; - -#ifdef __cplusplus -} -#endif diff --git a/parallel-rdp-standalone/parallel_imp.cpp b/parallel-rdp-standalone/parallel_imp.cpp index f80ce82..8e0fe25 100644 --- a/parallel-rdp-standalone/parallel_imp.cpp +++ b/parallel-rdp-standalone/parallel_imp.cpp @@ -1,9 +1,11 @@ +// Adapted from https://github.com/Themaister/parallel-rdp/blob/master/integration_example.cpp #include "parallel_imp.h" +#include "vkguts.h" #include #include #include "rdp_device.hpp" -#include "context.hpp" -#include "device.hpp" +#include "wsi.hpp" +#include "wsi_platform.h" using namespace Vulkan; using namespace std; @@ -12,9 +14,9 @@ static int cmd_cur; static int cmd_ptr; static uint32_t cmd_data[0x00040000 >> 2]; -static unique_ptr frontend; -static unique_ptr device; -static unique_ptr context; +static RDP::CommandProcessor* processor; +static WSI* wsi; +static QT_WSIPlatform* wsi_platform; int32_t vk_rescaling; bool vk_ssreadbacks; @@ -38,94 +40,231 @@ static const unsigned cmd_len_lut[64] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, }; -void vk_blit(unsigned &width, unsigned &height) +static const uint32_t vertex_spirv[] = + {0x07230203,0x00010000,0x000d000a,0x00000034, + 0x00000000,0x00020011,0x00000001,0x0006000b, + 0x00000001,0x4c534c47,0x6474732e,0x3035342e, + 0x00000000,0x0003000e,0x00000000,0x00000001, + 0x0008000f,0x00000000,0x00000004,0x6e69616d, + 0x00000000,0x00000008,0x00000016,0x0000002b, + 0x00040047,0x00000008,0x0000000b,0x0000002a, + 0x00050048,0x00000014,0x00000000,0x0000000b, + 0x00000000,0x00050048,0x00000014,0x00000001, + 0x0000000b,0x00000001,0x00050048,0x00000014, + 0x00000002,0x0000000b,0x00000003,0x00050048, + 0x00000014,0x00000003,0x0000000b,0x00000004, + 0x00030047,0x00000014,0x00000002,0x00040047, + 0x0000002b,0x0000001e,0x00000000,0x00020013, + 0x00000002,0x00030021,0x00000003,0x00000002, + 0x00040015,0x00000006,0x00000020,0x00000001, + 0x00040020,0x00000007,0x00000001,0x00000006, + 0x0004003b,0x00000007,0x00000008,0x00000001, + 0x0004002b,0x00000006,0x0000000a,0x00000000, + 0x00020014,0x0000000b,0x00030016,0x0000000f, + 0x00000020,0x00040017,0x00000010,0x0000000f, + 0x00000004,0x00040015,0x00000011,0x00000020, + 0x00000000,0x0004002b,0x00000011,0x00000012, + 0x00000001,0x0004001c,0x00000013,0x0000000f, + 0x00000012,0x0006001e,0x00000014,0x00000010, + 0x0000000f,0x00000013,0x00000013,0x00040020, + 0x00000015,0x00000003,0x00000014,0x0004003b, + 0x00000015,0x00000016,0x00000003,0x0004002b, + 0x0000000f,0x00000017,0xbf800000,0x0004002b, + 0x0000000f,0x00000018,0x00000000,0x0004002b, + 0x0000000f,0x00000019,0x3f800000,0x0007002c, + 0x00000010,0x0000001a,0x00000017,0x00000017, + 0x00000018,0x00000019,0x00040020,0x0000001b, + 0x00000003,0x00000010,0x0004002b,0x00000006, + 0x0000001f,0x00000001,0x0004002b,0x0000000f, + 0x00000023,0x40400000,0x0007002c,0x00000010, + 0x00000024,0x00000017,0x00000023,0x00000018, + 0x00000019,0x0007002c,0x00000010,0x00000027, + 0x00000023,0x00000017,0x00000018,0x00000019, + 0x00040017,0x00000029,0x0000000f,0x00000002, + 0x00040020,0x0000002a,0x00000003,0x00000029, + 0x0004003b,0x0000002a,0x0000002b,0x00000003, + 0x0004002b,0x0000000f,0x0000002f,0x3f000000, + 0x0005002c,0x00000029,0x00000033,0x0000002f, + 0x0000002f,0x00050036,0x00000002,0x00000004, + 0x00000000,0x00000003,0x000200f8,0x00000005, + 0x0004003d,0x00000006,0x00000009,0x00000008, + 0x000500aa,0x0000000b,0x0000000c,0x00000009, + 0x0000000a,0x000300f7,0x0000000e,0x00000000, + 0x000400fa,0x0000000c,0x0000000d,0x0000001d, + 0x000200f8,0x0000000d,0x00050041,0x0000001b, + 0x0000001c,0x00000016,0x0000000a,0x0003003e, + 0x0000001c,0x0000001a,0x000200f9,0x0000000e, + 0x000200f8,0x0000001d,0x000500aa,0x0000000b, + 0x00000020,0x00000009,0x0000001f,0x000300f7, + 0x00000022,0x00000000,0x000400fa,0x00000020, + 0x00000021,0x00000026,0x000200f8,0x00000021, + 0x00050041,0x0000001b,0x00000025,0x00000016, + 0x0000000a,0x0003003e,0x00000025,0x00000024, + 0x000200f9,0x00000022,0x000200f8,0x00000026, + 0x00050041,0x0000001b,0x00000028,0x00000016, + 0x0000000a,0x0003003e,0x00000028,0x00000027, + 0x000200f9,0x00000022,0x000200f8,0x00000022, + 0x000200f9,0x0000000e,0x000200f8,0x0000000e, + 0x00050041,0x0000001b,0x0000002c,0x00000016, + 0x0000000a,0x0004003d,0x00000010,0x0000002d, + 0x0000002c,0x0007004f,0x00000029,0x0000002e, + 0x0000002d,0x0000002d,0x00000000,0x00000001, + 0x0005008e,0x00000029,0x00000030,0x0000002e, + 0x0000002f,0x00050081,0x00000029,0x00000032, + 0x00000030,0x00000033,0x0003003e,0x0000002b, + 0x00000032,0x000100fd,0x00010038}; + +static const uint32_t fragment_spirv[] = + {0x07230203,0x00010000,0x000d000a,0x00000015, + 0x00000000,0x00020011,0x00000001,0x0006000b, + 0x00000001,0x4c534c47,0x6474732e,0x3035342e, + 0x00000000,0x0003000e,0x00000000,0x00000001, + 0x0007000f,0x00000004,0x00000004,0x6e69616d, + 0x00000000,0x00000009,0x00000011,0x00030010, + 0x00000004,0x00000007,0x00040047,0x00000009, + 0x0000001e,0x00000000,0x00040047,0x0000000d, + 0x00000022,0x00000000,0x00040047,0x0000000d, + 0x00000021,0x00000000,0x00040047,0x00000011, + 0x0000001e,0x00000000,0x00020013,0x00000002, + 0x00030021,0x00000003,0x00000002,0x00030016, + 0x00000006,0x00000020,0x00040017,0x00000007, + 0x00000006,0x00000004,0x00040020,0x00000008, + 0x00000003,0x00000007,0x0004003b,0x00000008, + 0x00000009,0x00000003,0x00090019,0x0000000a, + 0x00000006,0x00000001,0x00000000,0x00000000, + 0x00000000,0x00000001,0x00000000,0x0003001b, + 0x0000000b,0x0000000a,0x00040020,0x0000000c, + 0x00000000,0x0000000b,0x0004003b,0x0000000c, + 0x0000000d,0x00000000,0x00040017,0x0000000f, + 0x00000006,0x00000002,0x00040020,0x00000010, + 0x00000001,0x0000000f,0x0004003b,0x00000010, + 0x00000011,0x00000001,0x0004002b,0x00000006, + 0x00000013,0x00000000,0x00050036,0x00000002, + 0x00000004,0x00000000,0x00000003,0x000200f8, + 0x00000005,0x0004003d,0x0000000b,0x0000000e, + 0x0000000d,0x0004003d,0x0000000f,0x00000012, + 0x00000011,0x00070058,0x00000007,0x00000014, + 0x0000000e,0x00000012,0x00000002,0x00000013, + 0x0003003e,0x00000009,0x00000014,0x000100fd, + 0x00010038}; + +static void calculate_viewport(float* x, float* y, float* width, float* height) { - if (running) - { + int32_t display_width = (window_widescreen ? 854 : 640) * vk_rescaling; + int32_t display_height = 480 * vk_rescaling; - RDP::ScanoutOptions opts = {}; - opts.persist_frame_on_invalid_input = true; - opts.vi.aa = vk_vi_aa; - opts.vi.scale = vk_vi_scale; - opts.vi.dither_filter = vk_dither_filter; - opts.vi.divot_filter = vk_divot_filter; - opts.vi.gamma_dither = vk_gamma_dither; - opts.blend_previous_frame = vk_interlacing; - opts.upscale_deinterlacing = !vk_interlacing; - opts.downscale_steps = vk_downscaling_steps; - opts.crop_overscan_pixels = vk_overscan; - if (vk_vertical_stretch) { - opts.crop_rect.top = vk_vertical_stretch; - opts.crop_rect.bottom = vk_vertical_stretch; - opts.crop_rect.enable = true; - } + *width = window_width; + *height = window_height; + *x = 0; + *y = 0; + int32_t hw = display_height * *width; + int32_t wh = display_width * *height; - RDP::VIScanoutBuffer scanout; - frontend->scanout_async_buffer(scanout, opts); + // add letterboxes or pillarboxes if the window has a different aspect ratio + // than the current display mode + if (hw > wh) { + int32_t w_max = wh / display_height; + *x += (*width - w_max) / 2; + *width = w_max; + } else if (hw < wh) { + int32_t h_max = hw / display_width; + *y += (*height - h_max) / 2; + *height = h_max; + } +} - if (!scanout.width || !scanout.height) - { - width = 0; - height = 0; - return; - } - - width = scanout.width; - height = scanout.height; - - scanout.fence->wait(); - uint8_t* color_data = screen_get_texture_data(); - memcpy(color_data, device->map_host_buffer(*scanout.buffer, Vulkan::MEMORY_ACCESS_READ_BIT), - width * height * sizeof(uint32_t)); - device->unmap_host_buffer(*scanout.buffer, Vulkan::MEMORY_ACCESS_READ_BIT); +static void render_frame(Vulkan::Device &device) +{ + RDP::ScanoutOptions opts = {}; + opts.persist_frame_on_invalid_input = true; + opts.vi.aa = vk_vi_aa; + opts.vi.scale = vk_vi_scale; + opts.vi.dither_filter = vk_dither_filter; + opts.vi.divot_filter = vk_divot_filter; + opts.vi.gamma_dither = vk_gamma_dither; + opts.blend_previous_frame = vk_interlacing; + opts.upscale_deinterlacing = !vk_interlacing; + opts.downscale_steps = vk_downscaling_steps; + opts.crop_overscan_pixels = vk_overscan; + if (vk_vertical_stretch) { + opts.crop_rect.top = vk_vertical_stretch; + opts.crop_rect.bottom = vk_vertical_stretch; + opts.crop_rect.enable = true; } + Vulkan::ImageHandle image = processor->scanout(opts); + if (image.get() == NULL && skip_swap_clear) + return; + + // Normally reflection is automated. + Vulkan::ResourceLayout vertex_layout = {}; + Vulkan::ResourceLayout fragment_layout = {}; + fragment_layout.output_mask = 1 << 0; + fragment_layout.sets[0].sampled_image_mask = 1 << 0; + + // This request is cached. + auto *program = device.request_program(vertex_spirv, sizeof(vertex_spirv), + fragment_spirv, sizeof(fragment_spirv), + &vertex_layout, + &fragment_layout); + + // Blit image on screen. + auto cmd = device.request_command_buffer(); + { + auto rp = device.get_swapchain_render_pass(Vulkan::SwapchainRenderPass::ColorOnly); + cmd->begin_render_pass(rp); + if (image.get() != NULL) + { + VkViewport vp = cmd->get_viewport(); + calculate_viewport(&vp.x, &vp.y, &vp.width, &vp.height); + + cmd->set_program(program); + + // Basic default render state. + cmd->set_opaque_state(); + cmd->set_depth_test(false, false); + cmd->set_cull_mode(VK_CULL_MODE_NONE); + + cmd->set_texture(0, 0, image->get_view(), Vulkan::StockSampler::LinearClamp); + cmd->set_viewport(vp); + + // The vertices are constants in the shader. + // Draws fullscreen quad using oversized triangle. + cmd->draw(3); + } + cmd->end_render_pass(); + } + device.submit(cmd); } void vk_rasterize() { - - if (frontend && running) + if (processor && running) { - frontend->set_vi_register(RDP::VIRegister::Control, *GET_GFX_INFO(VI_STATUS_REG)); - frontend->set_vi_register(RDP::VIRegister::Origin, *GET_GFX_INFO(VI_ORIGIN_REG)); - frontend->set_vi_register(RDP::VIRegister::Width, *GET_GFX_INFO(VI_WIDTH_REG)); - frontend->set_vi_register(RDP::VIRegister::Intr, *GET_GFX_INFO(VI_INTR_REG)); - frontend->set_vi_register(RDP::VIRegister::VCurrentLine, *GET_GFX_INFO(VI_V_CURRENT_LINE_REG)); - frontend->set_vi_register(RDP::VIRegister::Timing, *GET_GFX_INFO(VI_V_BURST_REG)); - frontend->set_vi_register(RDP::VIRegister::VSync, *GET_GFX_INFO(VI_V_SYNC_REG)); - frontend->set_vi_register(RDP::VIRegister::HSync, *GET_GFX_INFO(VI_H_SYNC_REG)); - frontend->set_vi_register(RDP::VIRegister::Leap, *GET_GFX_INFO(VI_LEAP_REG)); - frontend->set_vi_register(RDP::VIRegister::HStart, *GET_GFX_INFO(VI_H_START_REG)); - frontend->set_vi_register(RDP::VIRegister::VStart, *GET_GFX_INFO(VI_V_START_REG)); - frontend->set_vi_register(RDP::VIRegister::VBurst, *GET_GFX_INFO(VI_V_BURST_REG)); - frontend->set_vi_register(RDP::VIRegister::XScale, *GET_GFX_INFO(VI_X_SCALE_REG)); - frontend->set_vi_register(RDP::VIRegister::YScale, *GET_GFX_INFO(VI_Y_SCALE_REG)); + processor->set_vi_register(RDP::VIRegister::Control, *GET_GFX_INFO(VI_STATUS_REG)); + processor->set_vi_register(RDP::VIRegister::Origin, *GET_GFX_INFO(VI_ORIGIN_REG)); + processor->set_vi_register(RDP::VIRegister::Width, *GET_GFX_INFO(VI_WIDTH_REG)); + processor->set_vi_register(RDP::VIRegister::Intr, *GET_GFX_INFO(VI_INTR_REG)); + processor->set_vi_register(RDP::VIRegister::VCurrentLine, *GET_GFX_INFO(VI_V_CURRENT_LINE_REG)); + processor->set_vi_register(RDP::VIRegister::Timing, *GET_GFX_INFO(VI_V_BURST_REG)); + processor->set_vi_register(RDP::VIRegister::VSync, *GET_GFX_INFO(VI_V_SYNC_REG)); + processor->set_vi_register(RDP::VIRegister::HSync, *GET_GFX_INFO(VI_H_SYNC_REG)); + processor->set_vi_register(RDP::VIRegister::Leap, *GET_GFX_INFO(VI_LEAP_REG)); + processor->set_vi_register(RDP::VIRegister::HStart, *GET_GFX_INFO(VI_H_START_REG)); + processor->set_vi_register(RDP::VIRegister::VStart, *GET_GFX_INFO(VI_V_START_REG)); + processor->set_vi_register(RDP::VIRegister::VBurst, *GET_GFX_INFO(VI_V_BURST_REG)); + processor->set_vi_register(RDP::VIRegister::XScale, *GET_GFX_INFO(VI_X_SCALE_REG)); + processor->set_vi_register(RDP::VIRegister::YScale, *GET_GFX_INFO(VI_Y_SCALE_REG)); RDP::Quirks quirks; quirks.set_native_texture_lod(vk_native_texture_lod); quirks.set_native_resolution_tex_rect(vk_native_tex_rect); - frontend->set_quirks(quirks); + processor->set_quirks(quirks); - frontend->begin_frame_context(); - - unsigned width = 0; - unsigned height = 0; - vk_blit(width, height); - - if (width == 0 || height == 0) - { - if (!skip_swap_clear) - screen_swap(true); - return; - } - - struct frame_buffer buf = {0}; - buf.valid = true; - buf.height = height; - buf.width = width; - buf.pitch = width; - screen_write(&buf); - screen_swap(false); + auto &device = wsi->get_device(); + wsi->begin_frame(); + render_frame(device); + wsi->end_frame(); + wsi->get_device().promote_read_write_caches_to_read_only(); } } @@ -133,7 +272,6 @@ void vk_process_commands() { if (running) { - const uint32_t DP_CURRENT = *GET_GFX_INFO(DPC_CURRENT_REG) & 0x00FFFFF8; const uint32_t DP_END = *GET_GFX_INFO(DPC_END_REG) & 0x00FFFFF8; @@ -188,14 +326,14 @@ void vk_process_commands() return; } - if (command >= 8 && frontend) - frontend->enqueue_command(cmd_length * 2, &cmd_data[2 * cmd_cur]); + if (command >= 8 && processor) + processor->enqueue_command(cmd_length * 2, &cmd_data[2 * cmd_cur]); if (RDP::Op(command) == RDP::Op::SyncFull) { // For synchronous RDP: - if (vk_synchronous && frontend) - frontend->wait_for_timeline(frontend->signal_timeline()); + if (vk_synchronous && processor) + processor->wait_for_timeline(processor->signal_timeline()); *gfx.MI_INTR_REG |= DP_INTERRUPT; gfx.CheckInterrupts(); } @@ -209,36 +347,55 @@ void vk_process_commands() } } +void vk_resize() +{ + QT_WSIPlatform* platform = (QT_WSIPlatform*)&wsi->get_platform(); + platform->do_resize(); +} + void vk_destroy() { - running = false; - frontend.reset(); - device.reset(); - context.reset(); - screen_close(); + running = false; + if (processor) + { + delete processor; + processor = nullptr; + } + if (wsi) + { + delete wsi; + wsi = nullptr; + } + if (wsi_platform) + { + delete wsi_platform; + wsi_platform = nullptr; + } } bool vk_init() { running = false; screen_init(); - context.reset(new Context); - device.reset(new Device); - frontend.reset(); - + screen_set_mode(); + wsi = new WSI; + wsi_platform = new QT_WSIPlatform; + wsi->set_platform(wsi_platform); + wsi->set_present_mode(window_vsync ? PresentMode::SyncToVBlank: PresentMode::UnlockedMaybeTear); + wsi->set_backbuffer_srgb(false); + Context::SystemHandles handles = {}; if (!::Vulkan::Context::init_loader(nullptr)) return false; - if (!context->init_instance_and_device(nullptr, 0, nullptr, 0, ::Vulkan::CONTEXT_CREATION_DISABLE_BINDLESS_BIT)) + if (!wsi->init_simple(1, handles)) return false; uintptr_t aligned_rdram = reinterpret_cast(gfx.RDRAM); uintptr_t offset = 0; - - if (device->get_device_features().supports_external_memory_host) + if (wsi->get_device().get_device_features().supports_external_memory_host) { - size_t align = device->get_device_features().host_memory_properties.minImportedHostPointerAlignment; + size_t align = wsi->get_device().get_device_features().host_memory_properties.minImportedHostPointerAlignment; offset = aligned_rdram & (align - 1); if (offset) @@ -248,8 +405,6 @@ bool vk_init() aligned_rdram -= offset; } - device->set_context(*context); - device->init_frame_contexts(3); ::RDP::CommandProcessorFlags flags = 0; switch (vk_rescaling) @@ -274,19 +429,22 @@ bool vk_init() if (vk_ssdither) flags |= RDP::COMMAND_PROCESSOR_FLAG_SUPER_SAMPLED_DITHER_BIT; - frontend.reset(new RDP::CommandProcessor(*device, reinterpret_cast(aligned_rdram), - offset, rdram_size, rdram_size / 2, flags)); - if (!frontend->device_is_supported()) + processor = new RDP::CommandProcessor(wsi->get_device(), reinterpret_cast(aligned_rdram), + offset, rdram_size, rdram_size / 2, flags); + if (!processor->device_is_supported()) { - frontend.reset(); + delete processor; + processor = nullptr; return false; } RDP::Quirks quirks; quirks.set_native_texture_lod(vk_native_texture_lod); quirks.set_native_resolution_tex_rect(vk_native_tex_rect); - frontend->set_quirks(quirks); + processor->set_quirks(quirks); + if (window_fullscreen) + screen_toggle_fullscreen(); running = true; return true; } diff --git a/parallel-rdp-standalone/parallel_imp.h b/parallel-rdp-standalone/parallel_imp.h index fff84e7..9f94b82 100644 --- a/parallel-rdp-standalone/parallel_imp.h +++ b/parallel-rdp-standalone/parallel_imp.h @@ -1,7 +1,8 @@ +#pragma once #include "gfx_m64p.h" -#include "glguts.h" #include "gfxstructdefs.h" +#include #ifdef __cplusplus extern "C" @@ -27,6 +28,7 @@ extern "C" void vk_process_commands(); bool vk_init(); void vk_destroy(); + void vk_resize(); #ifdef __cplusplus } diff --git a/parallel-rdp-standalone/vkguts.c b/parallel-rdp-standalone/vkguts.c new file mode 100644 index 0000000..7754a20 --- /dev/null +++ b/parallel-rdp-standalone/vkguts.c @@ -0,0 +1,56 @@ +#include "vkguts.h" +#include "gfx_m64p.h" +#include +#include + + +/* definitions of pointers to Core video extension functions */ +static ptr_VidExt_Init CoreVideo_Init = NULL; +static ptr_VidExt_Quit CoreVideo_Quit = NULL; +static ptr_VidExt_SetCaption CoreVideo_SetCaption = NULL; +static ptr_VidExt_ToggleFullScreen CoreVideo_ToggleFullScreen = NULL; +static ptr_VidExt_ResizeWindow CoreVideo_ResizeWindow = NULL; +static ptr_VidExt_GetVkSurface CoreVideo_GetVkSurface = NULL; +static ptr_VidExt_GetVkInstExtensions CoreVideo_GetVkInstExtensions = NULL; +static ptr_VidExt_SetVideoMode CoreVideo_SetVideoMode = NULL; + +void screen_init() +{ + /* Get the core Video Extension function pointers from the library handle */ + CoreVideo_Init = (ptr_VidExt_Init)DLSYM(CoreLibHandle, "VidExt_Init"); + CoreVideo_Quit = (ptr_VidExt_Quit)DLSYM(CoreLibHandle, "VidExt_Quit"); + CoreVideo_SetCaption = (ptr_VidExt_SetCaption)DLSYM(CoreLibHandle, "VidExt_SetCaption"); + CoreVideo_ToggleFullScreen = (ptr_VidExt_ToggleFullScreen)DLSYM(CoreLibHandle, "VidExt_ToggleFullScreen"); + CoreVideo_ResizeWindow = (ptr_VidExt_ResizeWindow)DLSYM(CoreLibHandle, "VidExt_ResizeWindow"); + CoreVideo_GetVkSurface = (ptr_VidExt_GetVkSurface)DLSYM(CoreLibHandle, "VidExt_GetVkSurface"); + CoreVideo_GetVkInstExtensions = (ptr_VidExt_GetVkInstExtensions)DLSYM(CoreLibHandle, "VidExt_GetVkInstExtensions"); + CoreVideo_SetVideoMode = (ptr_VidExt_SetVideoMode)DLSYM(CoreLibHandle, "VidExt_SetVideoMode"); + + CoreVideo_Init(); + CoreVideo_SetCaption("Mupen64Plus-Parallel"); +} + +void screen_set_mode() +{ + CoreVideo_SetVideoMode(window_width, window_height, 0, M64VIDEO_WINDOWED, 0); +} + +void screen_close() +{ + CoreVideo_Quit(); +} + +void screen_toggle_fullscreen() +{ + CoreVideo_ToggleFullScreen(); +} + +VkSurfaceKHR screen_get_surface(VkInstance instance) +{ + return (VkSurfaceKHR)CoreVideo_GetVkSurface((void*)instance); +} + +m64p_error screen_get_instance_extensions(const char ** ext[], uint32_t* ext_num) +{ + return CoreVideo_GetVkInstExtensions(ext, ext_num); +} diff --git a/parallel-rdp-standalone/vkguts.h b/parallel-rdp-standalone/vkguts.h new file mode 100644 index 0000000..6a911f7 --- /dev/null +++ b/parallel-rdp-standalone/vkguts.h @@ -0,0 +1,26 @@ +#pragma once + +#include "m64p_vidext.h" +#include "volk.h" +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + void screen_init(); + void screen_close(); + void screen_toggle_fullscreen(); + void screen_set_mode(); + VkSurfaceKHR screen_get_surface(VkInstance instance); + m64p_error screen_get_instance_extensions(const char** ext[], uint32_t* ext_num); + + extern bool window_fullscreen; + extern bool window_widescreen; + extern int32_t window_width; + extern int32_t window_height; + extern int32_t window_vsync; + +#ifdef __cplusplus +} +#endif diff --git a/parallel-rdp-standalone/wsi_platform.cpp b/parallel-rdp-standalone/wsi_platform.cpp new file mode 100644 index 0000000..f2ca420 --- /dev/null +++ b/parallel-rdp-standalone/wsi_platform.cpp @@ -0,0 +1,48 @@ +#include "wsi_platform.h" +#include "vkguts.h" +#include "gfx_m64p.h" + +VkSurfaceKHR QT_WSIPlatform::create_surface(VkInstance instance, VkPhysicalDevice gpu) +{ + return screen_get_surface(instance); +} + +void QT_WSIPlatform::destroy_surface(VkInstance instance, VkSurfaceKHR surface) +{ +} + +std::vector QT_WSIPlatform::get_instance_extensions() +{ + const char** ext; + uint32_t ext_num; + screen_get_instance_extensions(&ext, &ext_num); + std::vector return_value; + for (int i=0; i< ext_num; ++i) + return_value.push_back(ext[i]); + return return_value; +} + +uint32_t QT_WSIPlatform::get_surface_width() +{ + return window_width; +} + +uint32_t QT_WSIPlatform::get_surface_height() +{ + return window_height; +} + +bool QT_WSIPlatform::alive(Vulkan::WSI &wsi) +{ + return true; +} + +void QT_WSIPlatform::poll_input() +{ + +} + +void QT_WSIPlatform::do_resize() +{ + resize = true; +} diff --git a/parallel-rdp-standalone/wsi_platform.h b/parallel-rdp-standalone/wsi_platform.h new file mode 100644 index 0000000..1d62a3e --- /dev/null +++ b/parallel-rdp-standalone/wsi_platform.h @@ -0,0 +1,16 @@ +#pragma once + +#include "wsi.hpp" + +class QT_WSIPlatform : public Vulkan::WSIPlatform +{ +public: + VkSurfaceKHR create_surface(VkInstance instance, VkPhysicalDevice gpu) override; + void destroy_surface(VkInstance instance, VkSurfaceKHR surface) override; + std::vector get_instance_extensions() override; + uint32_t get_surface_width() override; + uint32_t get_surface_height() override; + bool alive(Vulkan::WSI &wsi) override; + void poll_input() override; + void do_resize(); +};