From 4f7c23fe79aca5e6ea1b9f55c315b1a7c91ca573 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 24 Oct 2019 01:29:24 +0200 Subject: [PATCH] DarkStalkers: Fix display on OpenGL ES. --- GPU/Software/SoftGpu.cpp | 16 +++++++++++---- Windows/GPU/WindowsVulkanContext.cpp | 1 + ext/native/base/display.cpp | 2 +- ext/native/math/lin/matrix4x4.h | 6 +++++- ext/native/thin3d/DataFormat.h | 1 + ext/native/thin3d/thin3d_gl.cpp | 30 +++++++++++++++++++++++----- ext/native/thin3d/thin3d_vulkan.cpp | 2 ++ 7 files changed, 47 insertions(+), 11 deletions(-) diff --git a/GPU/Software/SoftGpu.cpp b/GPU/Software/SoftGpu.cpp index c468b45b6..0b715dd95 100644 --- a/GPU/Software/SoftGpu.cpp +++ b/GPU/Software/SoftGpu.cpp @@ -191,15 +191,23 @@ void SoftGPU::CopyToCurrentFboFromDisplayRam(int srcwidth, int srcheight) { Draw::Pipeline *pipeline = texColor; if (PSP_CoreParameter().compat.flags().DarkStalkersPresentHack && displayFormat_ == GE_FORMAT_5551 && g_DarkStalkerStretch) { u8 *data = Memory::GetPointer(0x04088000); - desc.format = Draw::DataFormat::A1R5G5B5_UNORM_PACK16; + if (draw_->GetDataFormatSupport(Draw::DataFormat::A1B5G5R5_UNORM_PACK16) & Draw::FMT_TEXTURE) { + // The perfect one. + desc.format = Draw::DataFormat::A1B5G5R5_UNORM_PACK16; + } else if (draw_->GetDataFormatSupport(Draw::DataFormat::A1R5G5B5_UNORM_PACK16) & Draw::FMT_TEXTURE) { + // RB swapped, compensate with a shader. + desc.format = Draw::DataFormat::A1R5G5B5_UNORM_PACK16; + pipeline = texColorRBSwizzle; + } else { + // Shouldn't happen (once I'm done with the backends). + } desc.width = displayStride_ == 0 ? srcwidth : displayStride_; desc.height = srcheight; desc.initData.push_back(data); - u0 = 64.0f / 512.0f; - u1 = 448.0f / 512.0f; + u0 = 64.5f / 512.0f; + u1 = 447.5f / 512.0f; v1 = 16.0f / 272.0f; v0 = 240.0f / 272.0f; - pipeline = texColorRBSwizzle; g_DarkStalkerStretch = false; } else if (!Memory::IsValidAddress(displayFramebuf_) || srcwidth == 0 || srcheight == 0) { hasImage = false; diff --git a/Windows/GPU/WindowsVulkanContext.cpp b/Windows/GPU/WindowsVulkanContext.cpp index 09f9f16a0..7797b5828 100644 --- a/Windows/GPU/WindowsVulkanContext.cpp +++ b/Windows/GPU/WindowsVulkanContext.cpp @@ -116,6 +116,7 @@ bool WindowsVulkanContext::Init(HINSTANCE hInst, HWND hWnd, std::string *error_m if (!g_Config.sVulkanDevice.empty()) g_Config.sVulkanDevice = g_Vulkan->GetPhysicalDeviceProperties(deviceNum).properties.deviceName; } + g_Vulkan->ChooseDevice(deviceNum); if (g_Vulkan->CreateDevice() != VK_SUCCESS) { *error_message = g_Vulkan->InitError(); diff --git a/ext/native/base/display.cpp b/ext/native/base/display.cpp index 3e912788d..c67363955 100644 --- a/ext/native/base/display.cpp +++ b/ext/native/base/display.cpp @@ -17,7 +17,7 @@ float pixel_in_dps_y = 1.0f; float display_hz = 60.0f; DisplayRotation g_display_rotation; -Lin::Matrix4x4 g_display_rot_matrix; +Lin::Matrix4x4 g_display_rot_matrix = Lin::Matrix4x4::identity(); template void RotateRectToDisplayImpl(DisplayRect &rect, T curRTWidth, T curRTHeight) { diff --git a/ext/native/math/lin/matrix4x4.h b/ext/native/math/lin/matrix4x4.h index c9464384a..a9e312de7 100644 --- a/ext/native/math/lin/matrix4x4.h +++ b/ext/native/math/lin/matrix4x4.h @@ -57,7 +57,11 @@ public: empty(); xx=yy=zz=f; ww=1.0f; } - + static Matrix4x4 identity() { + Matrix4x4 id; + id.setIdentity(); + return id; + } void setIdentity() { setScaling(1.0f); } diff --git a/ext/native/thin3d/DataFormat.h b/ext/native/thin3d/DataFormat.h index 467f9e4a0..f1e168763 100644 --- a/ext/native/thin3d/DataFormat.h +++ b/ext/native/thin3d/DataFormat.h @@ -30,6 +30,7 @@ enum class DataFormat : uint8_t { R5G5B5A1_UNORM_PACK16, // A1 in the LOWER bit B5G5R5A1_UNORM_PACK16, // A1 in the LOWER bit A1R5G5B5_UNORM_PACK16, // A1 in the UPPER bit. + A1B5G5R5_UNORM_PACK16, // A1 in the UPPER bit. OpenGL-only. R16_FLOAT, R16G16_FLOAT, diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index d31e63f89..9b164ec2a 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -277,7 +277,7 @@ bool OpenGLShaderModule::Compile(GLRenderManager *render, ShaderLanguage languag class OpenGLInputLayout : public InputLayout { public: - OpenGLInputLayout(GLRenderManager *render) : render_(render), stride(0) {} + OpenGLInputLayout(GLRenderManager *render) : render_(render) {} ~OpenGLInputLayout(); void Compile(const InputLayoutDesc &desc); @@ -286,7 +286,7 @@ public: } GLRInputLayout *inputLayout_ = nullptr; - int stride; + int stride = 0; private: GLRenderManager *render_; }; @@ -718,6 +718,15 @@ public: FBColorDepth colorDepth = FBO_8888; }; +// TODO: SSE/NEON optimize, and move to ColorConv.cpp. +void MoveABit(u16 *dest, const u16 *src, size_t count) { + for (int i = 0; i < count; i++) { + u16 data = src[i]; + data = (data >> 15) | (data << 1); + dest[i] = data; + } +} + void OpenGLTexture::SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, const uint8_t *data) { if (width != width_ || height != height_ || depth != depth_) { // When switching to texStorage we need to handle this correctly. @@ -729,12 +738,20 @@ void OpenGLTexture::SetImageData(int x, int y, int z, int width, int height, int if (stride == 0) stride = width; - size_t alignment = DataFormatSizeInBytes(format_); // Make a copy of data with stride eliminated. uint8_t *texData = new uint8_t[(size_t)(width * height * alignment)]; - for (int y = 0; y < height; y++) { - memcpy(texData + y * width * alignment, data + y * stride * alignment, width * alignment); + + // Emulate support for DataFormat::A1R5G5B5_UNORM_PACK16. + if (format_ == DataFormat::A1R5G5B5_UNORM_PACK16) { + format_ = DataFormat::R5G5B5A1_UNORM_PACK16; + for (int y = 0; y < height; y++) { + MoveABit((u16 *)(texData + y * width * alignment), (const u16 *)(data + y * stride * alignment), width); + } + } else { + for (int y = 0; y < height; y++) { + memcpy(texData + y * width * alignment, data + y * stride * alignment, width * alignment); + } } render_->TextureImage(tex_, level, width, height, format_, texData); } @@ -1220,6 +1237,9 @@ uint32_t OpenGLContext::GetDataFormatSupport(DataFormat fmt) const { case DataFormat::R8G8B8A8_UNORM: return FMT_RENDERTARGET | FMT_TEXTURE | FMT_INPUTLAYOUT | FMT_AUTOGEN_MIPS; + case DataFormat::A1R5G5B5_UNORM_PACK16: + return FMT_TEXTURE; // we will emulate this! Very fast to convert from R5G5B5A1_UNORM_PACK16 during upload. + case DataFormat::R32_FLOAT: case DataFormat::R32G32_FLOAT: case DataFormat::R32G32B32_FLOAT: diff --git a/ext/native/thin3d/thin3d_vulkan.cpp b/ext/native/thin3d/thin3d_vulkan.cpp index 72c88feed..cb2fc0d4e 100644 --- a/ext/native/thin3d/thin3d_vulkan.cpp +++ b/ext/native/thin3d/thin3d_vulkan.cpp @@ -1371,6 +1371,8 @@ uint32_t VKContext::GetDataFormatSupport(DataFormat fmt) const { return 0; case DataFormat::A4R4G4B4_UNORM_PACK16: return 0; + case DataFormat::A1R5G5B5_UNORM_PACK16: + return FMT_RENDERTARGET | FMT_TEXTURE; case DataFormat::R8G8B8A8_UNORM: return FMT_RENDERTARGET | FMT_TEXTURE | FMT_INPUTLAYOUT;