From 474db602ca07f998bef1e5b46b33626a7fbcf21e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 7 Mar 2017 13:23:35 +0100 Subject: [PATCH 1/5] UWP: Fix screen rotation in non-buffered rendering mode --- GPU/Common/GPUStateUtils.cpp | 2 ++ GPU/Common/ShaderUniforms.cpp | 10 ++++++++++ GPU/D3D11/ShaderManagerD3D11.h | 3 --- GPU/D3D11/StateMappingD3D11.cpp | 13 +++++++------ GPU/D3D11/StateMappingD3D11.h | 6 +++--- 5 files changed, 22 insertions(+), 12 deletions(-) diff --git a/GPU/Common/GPUStateUtils.cpp b/GPU/Common/GPUStateUtils.cpp index 4ee8ba04a0..5244e4f83a 100644 --- a/GPU/Common/GPUStateUtils.cpp +++ b/GPU/Common/GPUStateUtils.cpp @@ -18,6 +18,8 @@ #include #include +#include "base/display.h" + #include "Common/StringUtils.h" #include "Core/Config.h" #include "Core/System.h" diff --git a/GPU/Common/ShaderUniforms.cpp b/GPU/Common/ShaderUniforms.cpp index 9c76b106db..a804be5023 100644 --- a/GPU/Common/ShaderUniforms.cpp +++ b/GPU/Common/ShaderUniforms.cpp @@ -1,6 +1,7 @@ #include #include "ShaderUniforms.h" +#include "base/display.h" #include "math/dataconv.h" #include "math/lin/matrix4x4.h" #include "math/math_util.h" @@ -8,6 +9,7 @@ #include "GPU/GPUState.h" #include "GPU/Math3D.h" #include "Core/Reporting.h" +#include "Core/Config.h" static void ConvertProjMatrixToVulkan(Matrix4x4 &in) { const Vec3 trans(0, 0, gstate_c.vpZOffset * 0.5f + 0.5f); @@ -78,6 +80,11 @@ void BaseUpdateUniforms(UB_VS_FS_Base *ub, uint64_t dirtyUniforms, bool flipView } else { ConvertProjMatrixToVulkan(flippedMatrix); } + + if (g_Config.iRenderingMode == 0 && g_display_rotation != DisplayRotation::ROTATE_0) { + flippedMatrix = flippedMatrix * g_display_rot_matrix; + } + CopyMatrix4x4(ub->proj, flippedMatrix.getReadPtr()); } @@ -88,6 +95,9 @@ void BaseUpdateUniforms(UB_VS_FS_Base *ub, uint64_t dirtyUniforms, bool flipView } else { proj_through.setOrthoVulkan(0.0f, gstate_c.curRTWidth, 0, gstate_c.curRTHeight, 0, 1); } + if (g_Config.iRenderingMode == 0 && g_display_rotation != DisplayRotation::ROTATE_0) { + proj_through = proj_through * g_display_rot_matrix; + } CopyMatrix4x4(ub->proj_through, proj_through.getReadPtr()); } diff --git a/GPU/D3D11/ShaderManagerD3D11.h b/GPU/D3D11/ShaderManagerD3D11.h index 5b891d8289..c66eda8153 100644 --- a/GPU/D3D11/ShaderManagerD3D11.h +++ b/GPU/D3D11/ShaderManagerD3D11.h @@ -25,9 +25,6 @@ #include "Globals.h" #include "GPU/Common/ShaderCommon.h" #include "GPU/Common/ShaderId.h" -// #include "GPU/DX9/VertexShaderGeneratorD3D11.h" -// #include "GPU/DX9/FragmentShaderGeneratorD3D11.h" -#include "math/lin/matrix4x4.h" #include "GPU/Common/ShaderUniforms.h" class D3D11Context; diff --git a/GPU/D3D11/StateMappingD3D11.cpp b/GPU/D3D11/StateMappingD3D11.cpp index 75e809c3f8..78a9b5e0ff 100644 --- a/GPU/D3D11/StateMappingD3D11.cpp +++ b/GPU/D3D11/StateMappingD3D11.cpp @@ -320,7 +320,7 @@ void DrawEngineD3D11::ApplyDrawState(int prim) { gstate_c.Dirty(DIRTY_DEPTHRANGE); } - D3D11_VIEWPORT &vp = dynState_.viewport; + Draw::Viewport &vp = dynState_.viewport; vp.TopLeftX = vpAndScissor.viewportX; vp.TopLeftY = vpAndScissor.viewportY; vp.Width = vpAndScissor.viewportW; @@ -443,19 +443,20 @@ void DrawEngineD3D11::ApplyDrawStateLate(bool applyStencilRef, uint8_t stencilRe if (!gstate.isModeClear()) { if (fboTexNeedBind_) { framebufferManager_->BindFramebufferAsColorTexture(1, framebufferManager_->GetCurrentRenderVFB(), BINDFBCOLOR_MAY_COPY); - // No sampler required, we do a Load in the pixel shader - // context_->PSSetSamplers(1, 1, &stockD3D11.samplerPoint2DClamp); + // No sampler required, we do a plain Load in the pixel shader. fboTexBound_ = true; fboTexNeedBind_ = false; } textureCache_->ApplyTexture(); } - // Need to do this AFTER ApplyTexture because the process of depalettization can ruin the blend state. + // Need to do this AFTER ApplyTexture because the process of depallettization can ruin the blend state. float blendColor[4]; Uint8x4ToFloat4(blendColor, dynState_.blendColor); - context_->RSSetViewports(1, &dynState_.viewport); - context_->RSSetScissorRects(1, &dynState_.scissor); + + // we go through Draw here because it automatically handles screen rotation, as needed in UWP on mobiles. + draw_->SetViewports(1, &dynState_.viewport); + draw_->SetScissorRect(dynState_.scissor.left, dynState_.scissor.top, dynState_.scissor.right - dynState_.scissor.left, dynState_.scissor.bottom - dynState_.scissor.top); context_->RSSetState(rasterState_); if (device1_) { context1_->OMSetBlendState(blendState1_, blendColor, 0xFFFFFFFF); diff --git a/GPU/D3D11/StateMappingD3D11.h b/GPU/D3D11/StateMappingD3D11.h index 33505d98dd..05f6b51c90 100644 --- a/GPU/D3D11/StateMappingD3D11.h +++ b/GPU/D3D11/StateMappingD3D11.h @@ -3,9 +3,9 @@ #include #include +#include "thin3d/thin3d.h" + // TODO: Do this more progressively. No need to compute the entire state if the entire state hasn't changed. -// In Vulkan, we simply collect all the state together into a "pipeline key" - we don't actually set any state here -// (the caller is responsible for setting the little dynamic state that is supported, dynState). struct D3D11BlendKey { union { @@ -67,6 +67,6 @@ struct D3D11DynamicState { uint32_t blendColor; bool useStencil; uint8_t stencilRef; - D3D11_VIEWPORT viewport; + Draw::Viewport viewport; D3D11_RECT scissor; }; From ed1609636554496a9e2eb91231d599131fff0be5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 7 Mar 2017 15:19:20 +0100 Subject: [PATCH 2/5] Don't crash if not enough memory to save a state. Very annoying. Minor tweaks. --- Common/ChunkFile.h | 9 ++++++++- Core/MIPS/ARM/ArmCompVFPUNEON.cpp | 2 +- GPU/D3D11/ShaderManagerD3D11.cpp | 6 +++--- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/Common/ChunkFile.h b/Common/ChunkFile.h index ac923c15d2..ad318ff80c 100644 --- a/Common/ChunkFile.h +++ b/Common/ChunkFile.h @@ -576,6 +576,7 @@ public: ERROR_NONE, ERROR_BAD_FILE, ERROR_BROKEN_STATE, + ERROR_BAD_ALLOC, }; // May fail badly if ptr doesn't point to valid data. @@ -642,7 +643,13 @@ public: { // Get data size_t const sz = MeasurePtr(_class); - u8 *buffer = new u8[sz]; + u8 *buffer = nullptr; + try { + buffer = new u8[sz]; + } + catch (std::bad_alloc e) { + return ERROR_BAD_ALLOC; + } Error error = SavePtr(buffer, _class); // SaveFile takes ownership of buffer diff --git a/Core/MIPS/ARM/ArmCompVFPUNEON.cpp b/Core/MIPS/ARM/ArmCompVFPUNEON.cpp index 48e2f0fbd2..9db9a2e6ed 100644 --- a/Core/MIPS/ARM/ArmCompVFPUNEON.cpp +++ b/Core/MIPS/ARM/ArmCompVFPUNEON.cpp @@ -899,7 +899,7 @@ void ArmJit::CompNEON_Vmscl(MIPSOpcode op) { MatrixSize msz = GetMtxSize(op); - bool overlap = GetMatrixOverlap(_VD, _VS, msz); + bool overlap = GetMatrixOverlap(_VD, _VS, msz) != OVERLAP_NONE; if (overlap) { DISABLE; } diff --git a/GPU/D3D11/ShaderManagerD3D11.cpp b/GPU/D3D11/ShaderManagerD3D11.cpp index 449daa05bb..18046d7512 100644 --- a/GPU/D3D11/ShaderManagerD3D11.cpp +++ b/GPU/D3D11/ShaderManagerD3D11.cpp @@ -95,9 +95,9 @@ ShaderManagerD3D11::ShaderManagerD3D11(ID3D11Device *device, ID3D11DeviceContext memset(&ub_lights, 0, sizeof(ub_lights)); memset(&ub_bones, 0, sizeof(ub_bones)); - ILOG("sizeof(ub_base): %d", (int)sizeof(ub_base)); - ILOG("sizeof(ub_lights): %d", (int)sizeof(ub_lights)); - ILOG("sizeof(ub_bones): %d", (int)sizeof(ub_bones)); + INFO_LOG(G3D, "sizeof(ub_base): %d", (int)sizeof(ub_base)); + INFO_LOG(G3D, "sizeof(ub_lights): %d", (int)sizeof(ub_lights)); + INFO_LOG(G3D, "sizeof(ub_bones): %d", (int)sizeof(ub_bones)); D3D11_BUFFER_DESC desc{sizeof(ub_base), D3D11_USAGE_DYNAMIC, D3D11_BIND_CONSTANT_BUFFER, D3D11_CPU_ACCESS_WRITE }; ASSERT_SUCCESS(device_->CreateBuffer(&desc, nullptr, &push_base)); From ee48a075b01ee9b2d29bccd30a652866eb498c5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 7 Mar 2017 13:00:59 +0100 Subject: [PATCH 3/5] UWP: Implement display rotation in framebuffer manager, now games display right-way-up in buffered rendering mode. --- GPU/D3D11/FramebufferManagerD3D11.cpp | 42 +++++++++++++++++---------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/GPU/D3D11/FramebufferManagerD3D11.cpp b/GPU/D3D11/FramebufferManagerD3D11.cpp index c628a394d1..5c24684df4 100644 --- a/GPU/D3D11/FramebufferManagerD3D11.cpp +++ b/GPU/D3D11/FramebufferManagerD3D11.cpp @@ -18,6 +18,7 @@ #include #include +#include "base/display.h" #include "math/lin/matrix4x4.h" #include "ext/native/thin3d/thin3d.h" #include "base/basictypes.h" @@ -372,11 +373,14 @@ void FramebufferManagerD3D11::MakePixelTexture(const u8 *srcPixels, GEBufferForm } void FramebufferManagerD3D11::DrawActiveTexture(float x, float y, float w, float h, float destW, float destH, float u0, float v0, float u1, float v1, int uvRotation, bool linearFilter) { - float coord[20] = { - x,y,0, u0,v0, - x + w,y,0, u1,v0, - x + w,y + h,0, u1,v1, - x,y + h,0, u0,v1, + struct Coord { + Vec3 pos; float u, v; + }; + Coord coord[4] = { + {{x, y, 0}, u0, v0}, + {{x + w, y, 0}, u1, v0}, + {{x + w, y + h,0}, u1, v1}, + {{x, y + h, 0}, u0, v1}, }; static const short indices[4] = { 0, 1, 3, 2 }; @@ -389,15 +393,14 @@ void FramebufferManagerD3D11::DrawActiveTexture(float x, float y, float w, float case ROTATION_LOCKED_VERTICAL: rotation = 1; break; case ROTATION_LOCKED_VERTICAL180: rotation = 3; break; } - for (int i = 0; i < 4; i++) { - temp[i * 2] = coord[((i + rotation) & 3) * 5 + 3]; - temp[i * 2 + 1] = coord[((i + rotation) & 3) * 5 + 4]; + temp[i * 2] = coord[((i + rotation) & 3)].u; + temp[i * 2 + 1] = coord[((i + rotation) & 3)].v; } for (int i = 0; i < 4; i++) { - coord[i * 5 + 3] = temp[i * 2]; - coord[i * 5 + 4] = temp[i * 2 + 1]; + coord[i].u = temp[i * 2]; + coord[i].v = temp[i * 2 + 1]; } } @@ -406,18 +409,25 @@ void FramebufferManagerD3D11::DrawActiveTexture(float x, float y, float w, float float halfPixelX = invDestW * 0.5f; float halfPixelY = invDestH * 0.5f; for (int i = 0; i < 4; i++) { - coord[i * 5] = coord[i * 5] * invDestW - 1.0f - halfPixelX; - coord[i * 5 + 1] = -(coord[i * 5 + 1] * invDestH - 1.0f - halfPixelY); + coord[i].pos.x = coord[i].pos.x * invDestW - 1.0f - halfPixelX; + coord[i].pos.y = -(coord[i].pos.y * invDestH - 1.0f - halfPixelY); + } + + if (g_display_rotation != DisplayRotation::ROTATE_0) { + for (int i = 0; i < 4; i++) { + // backwards notation, should fix that... + coord[i].pos = coord[i].pos * g_display_rot_matrix; + } } // The above code is for FAN geometry but we can only do STRIP. So rearrange it a little. D3D11_MAPPED_SUBRESOURCE map; context_->Map(quadBuffer_, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); float *dest = (float *)map.pData; - memcpy(dest, coord, sizeof(float) * 5); - memcpy(dest + 5, coord + 5, sizeof(float) * 5); - memcpy(dest + 10, coord + 15, sizeof(float) * 5); - memcpy(dest + 15, coord + 10, sizeof(float) * 5); + memcpy(dest, coord, sizeof(Coord)); + memcpy(dest + 5, coord + 1, sizeof(Coord)); + memcpy(dest + 10, coord + 3, sizeof(Coord)); + memcpy(dest + 15, coord + 2, sizeof(Coord)); context_->Unmap(quadBuffer_, 0); context_->RSSetState(stockD3D11.rasterStateNoCull); From 529d84a57bf402b91e4e6d8a6446438e89494784 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 7 Mar 2017 15:22:34 +0100 Subject: [PATCH 4/5] Avoid a crash if trying to do two screen switches at once. Managed to make this happen while using the UWP File Open dialog - it lagged and I started another action while it hadn't returned. --- ext/native/ui/screen.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ext/native/ui/screen.cpp b/ext/native/ui/screen.cpp index 3dac293149..e12da51c97 100644 --- a/ext/native/ui/screen.cpp +++ b/ext/native/ui/screen.cpp @@ -25,7 +25,9 @@ void ScreenManager::switchScreen(Screen *screen) { // until that switch. // TODO: is this still true? if (nextScreen_ != 0) { - FLOG("Already had a nextScreen_"); + ELOG("Already had a nextScreen_! Asynchronous open while doing something? Deleting the new screen."); + delete screen; + return; } if (screen == 0) { WLOG("Swiching to a zero screen, this can't be good"); From afc27c30eb5a380d2e8e14f3193ee97f08cd754a Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 7 Mar 2017 20:10:18 +0100 Subject: [PATCH 5/5] Quick buildfix (should probably just enable exceptions on Android) --- Common/ChunkFile.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Common/ChunkFile.h b/Common/ChunkFile.h index ad318ff80c..e1f3986d59 100644 --- a/Common/ChunkFile.h +++ b/Common/ChunkFile.h @@ -17,6 +17,8 @@ #pragma once +#include "ppsspp_config.h" + // Extremely simple serialization framework. // Currently mis-named, a native ChunkFile is something different (a RIFF file) @@ -644,12 +646,16 @@ public: // Get data size_t const sz = MeasurePtr(_class); u8 *buffer = nullptr; +#if PPSSPP_PLATFORM(ANDROID) + buffer = new u8[sz]; +#else try { buffer = new u8[sz]; } catch (std::bad_alloc e) { return ERROR_BAD_ALLOC; } +#endif Error error = SavePtr(buffer, _class); // SaveFile takes ownership of buffer