From 58ecb2cbd4ed6a678946bd7b4624e7a27129f936 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 17 Jan 2016 12:30:20 -0800 Subject: [PATCH 1/5] Fix a header declaration. Seemed to be needed for x64 Android, and is correct as bitfield anyway. --- ext/native/gfx/gl_common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/native/gfx/gl_common.h b/ext/native/gfx/gl_common.h index dc654ee77b..7a1bc97ef2 100644 --- a/ext/native/gfx/gl_common.h +++ b/ext/native/gfx/gl_common.h @@ -55,7 +55,7 @@ extern PFNGLDRAWTEXTURENVPROC glDrawTextureNV; typedef void (EGLAPIENTRYP PFNGLBLITFRAMEBUFFERNVPROC) ( GLint srcX0, GLint srcY0, GLint srcX1, GLuint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLuint dstY1, - GLint mask, GLenum filter); + GLbitfield mask, GLenum filter); #endif extern PFNGLBLITFRAMEBUFFERNVPROC glBlitFramebufferNV; From 73bcf1661223c7be64e9699b96bf491829ef86fc Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 17 Jan 2016 12:30:51 -0800 Subject: [PATCH 2/5] Flush before loading the CLUT. In case it's what was being rendered to. --- GPU/Directx9/FramebufferDX9.cpp | 3 +++ GPU/GLES/Framebuffer.cpp | 3 +++ 2 files changed, 6 insertions(+) diff --git a/GPU/Directx9/FramebufferDX9.cpp b/GPU/Directx9/FramebufferDX9.cpp index 7af5ab47c9..63f61d3eef 100644 --- a/GPU/Directx9/FramebufferDX9.cpp +++ b/GPU/Directx9/FramebufferDX9.cpp @@ -862,6 +862,9 @@ namespace DX9 { int w = std::min(pixels % vfb->fb_stride, (int)vfb->width); int h = std::min((pixels + vfb->fb_stride - 1) / vfb->fb_stride, (int)vfb->height); + // We might still have a pending draw to the fb in question, flush if so. + FlushBeforeCopy(); + // No need to download if we already have it. if (!vfb->memoryUpdated && vfb->clutUpdatedBytes < loadBytes) { // We intentionally don't call OptimizeDownloadRange() here - we don't want to over download. diff --git a/GPU/GLES/Framebuffer.cpp b/GPU/GLES/Framebuffer.cpp index a9e1401a45..3fbc371f57 100644 --- a/GPU/GLES/Framebuffer.cpp +++ b/GPU/GLES/Framebuffer.cpp @@ -1173,6 +1173,9 @@ void FramebufferManager::DownloadFramebufferForClut(u32 fb_address, u32 loadByte int w = std::min(pixels % vfb->fb_stride, (int)vfb->width); int h = std::min((pixels + vfb->fb_stride - 1) / vfb->fb_stride, (int)vfb->height); + // We might still have a pending draw to the fb in question, flush if so. + FlushBeforeCopy(); + // No need to download if we already have it. if (!vfb->memoryUpdated && vfb->clutUpdatedBytes < loadBytes) { // We intentionally don't call OptimizeDownloadRange() here - we don't want to over download. From f60aef2e16e67fcc9b130e7dc6ab5ee63a297884 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 17 Jan 2016 12:43:13 -0800 Subject: [PATCH 3/5] Add a more specific interface for video frames. Since we know more about them. No functional change yet. --- Core/HLE/sceMpeg.cpp | 7 ++++--- Core/HLE/scePsmf.cpp | 2 +- GPU/Directx9/GPU_DX9.cpp | 4 ++++ GPU/Directx9/GPU_DX9.h | 1 + GPU/GLES/GLES_GPU.cpp | 4 ++++ GPU/GLES/GLES_GPU.h | 1 + GPU/GPUInterface.h | 1 + GPU/Null/NullGpu.cpp | 4 ++++ GPU/Null/NullGpu.h | 1 + GPU/Software/SoftGpu.cpp | 5 +++++ GPU/Software/SoftGpu.h | 1 + 11 files changed, 27 insertions(+), 4 deletions(-) diff --git a/Core/HLE/sceMpeg.cpp b/Core/HLE/sceMpeg.cpp index 6e4495c06e..a66c648ce8 100644 --- a/Core/HLE/sceMpeg.cpp +++ b/Core/HLE/sceMpeg.cpp @@ -1094,7 +1094,7 @@ static u32 sceMpegAvcDecode(u32 mpeg, u32 auAddr, u32 frameWidth, u32 bufferAddr // playing all pmp_queue frames ctx->mediaengine->m_pFrameRGB = pmp_queue.front(); int bufferSize = ctx->mediaengine->writeVideoImage(buffer, frameWidth, ctx->videoPixelMode); - gpu->InvalidateCache(buffer, bufferSize, GPU_INVALIDATE_SAFE); + gpu->NotifyVideoUpload(buffer, bufferSize, frameWidth, ctx->videoPixelMode); ctx->avc.avcFrameStatus = 1; ctx->videoFrameCount++; @@ -1105,7 +1105,7 @@ static u32 sceMpegAvcDecode(u32 mpeg, u32 auAddr, u32 frameWidth, u32 bufferAddr } else if(ctx->mediaengine->stepVideo(ctx->videoPixelMode)) { int bufferSize = ctx->mediaengine->writeVideoImage(buffer, frameWidth, ctx->videoPixelMode); - gpu->InvalidateCache(buffer, bufferSize, GPU_INVALIDATE_SAFE); + gpu->NotifyVideoUpload(buffer, bufferSize, frameWidth, ctx->videoPixelMode); ctx->avc.avcFrameStatus = 1; ctx->videoFrameCount++; } else { @@ -1872,7 +1872,8 @@ static u32 sceMpegAvcCsc(u32 mpeg, u32 sourceAddr, u32 rangeAddr, int frameWidth int height = Memory::Read_U32(rangeAddr + 12); int destSize = ctx->mediaengine->writeVideoImageWithRange(destAddr, frameWidth, ctx->videoPixelMode, x, y, width, height); - gpu->InvalidateCache(destAddr, destSize, GPU_INVALIDATE_SAFE); + gpu->NotifyVideoUpload(destAddr, destSize, frameWidth, ctx->videoPixelMode); + // Do not use avcDecodeDelayMs 's value // Will cause video 's screen dislocation in Bleach heat of soul 6 // https://github.com/hrydgard/ppsspp/issues/5535 diff --git a/Core/HLE/scePsmf.cpp b/Core/HLE/scePsmf.cpp index 97ccfae66f..64c15ebfa7 100644 --- a/Core/HLE/scePsmf.cpp +++ b/Core/HLE/scePsmf.cpp @@ -1540,7 +1540,7 @@ static int scePsmfPlayerGetVideoData(u32 psmfPlayer, u32 videoDataAddr) int bufw = videoData->frameWidth == 0 ? 512 : videoData->frameWidth & ~1; // Always write the video frame, even after the video has ended. int displaybufSize = psmfplayer->mediaengine->writeVideoImage(videoData->displaybuf, bufw, videoPixelMode); - gpu->InvalidateCache(videoData->displaybuf, displaybufSize, GPU_INVALIDATE_SAFE); + gpu->NotifyVideoUpload(videoData->displaybuf, displaybufSize, bufw, videoPixelMode); __PsmfUpdatePts(psmfplayer, videoData); _PsmfPlayerFillRingbuffer(psmfplayer); diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index 6995992fff..ad74afb9f2 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -1952,6 +1952,10 @@ void DIRECTX9_GPU::InvalidateCacheInternal(u32 addr, int size, GPUInvalidationTy } } +void DIRECTX9_GPU::NotifyVideoUpload(u32 addr, int size, int width, int format) { + InvalidateCache(addr, size, GPU_INVALIDATE_SAFE); +} + void DIRECTX9_GPU::PerformMemoryCopyInternal(u32 dest, u32 src, int size) { if (!framebufferManager_.NotifyFramebufferCopy(src, dest, size, false, gstate_c.skipDrawReason)) { // We use a little hack for Download/Upload using a VRAM mirror. diff --git a/GPU/Directx9/GPU_DX9.h b/GPU/Directx9/GPU_DX9.h index a36add8c2c..9fe8e31fa3 100644 --- a/GPU/Directx9/GPU_DX9.h +++ b/GPU/Directx9/GPU_DX9.h @@ -48,6 +48,7 @@ public: void BeginFrame() override; void UpdateStats() override; void InvalidateCache(u32 addr, int size, GPUInvalidationType type) override; + void NotifyVideoUpload(u32 addr, int size, int width, int format) override; bool PerformMemoryCopy(u32 dest, u32 src, int size) override; bool PerformMemorySet(u32 dest, u8 v, int size) override; bool PerformMemoryDownload(u32 dest, int size) override; diff --git a/GPU/GLES/GLES_GPU.cpp b/GPU/GLES/GLES_GPU.cpp index 22bd84ae7e..ab6853331b 100644 --- a/GPU/GLES/GLES_GPU.cpp +++ b/GPU/GLES/GLES_GPU.cpp @@ -2201,6 +2201,10 @@ void GLES_GPU::InvalidateCacheInternal(u32 addr, int size, GPUInvalidationType t } } +void GLES_GPU::NotifyVideoUpload(u32 addr, int size, int width, int format) { + InvalidateCache(addr, size, GPU_INVALIDATE_SAFE); +} + void GLES_GPU::PerformMemoryCopyInternal(u32 dest, u32 src, int size) { if (!framebufferManager_.NotifyFramebufferCopy(src, dest, size, false, gstate_c.skipDrawReason)) { // We use a little hack for Download/Upload using a VRAM mirror. diff --git a/GPU/GLES/GLES_GPU.h b/GPU/GLES/GLES_GPU.h index 5ad5719902..e1bdc76ffe 100644 --- a/GPU/GLES/GLES_GPU.h +++ b/GPU/GLES/GLES_GPU.h @@ -52,6 +52,7 @@ public: void BeginFrame() override; void UpdateStats() override; void InvalidateCache(u32 addr, int size, GPUInvalidationType type) override; + void NotifyVideoUpload(u32 addr, int size, int width, int format) override; bool PerformMemoryCopy(u32 dest, u32 src, int size) override; bool PerformMemorySet(u32 dest, u8 v, int size) override; bool PerformMemoryDownload(u32 dest, int size) override; diff --git a/GPU/GPUInterface.h b/GPU/GPUInterface.h index 5cd115300c..5255972175 100644 --- a/GPU/GPUInterface.h +++ b/GPU/GPUInterface.h @@ -253,6 +253,7 @@ public: // Invalidate any cached content sourced from the specified range. // If size = -1, invalidate everything. virtual void InvalidateCache(u32 addr, int size, GPUInvalidationType type) = 0; + virtual void NotifyVideoUpload(u32 addr, int size, int width, int format) = 0; // Update either RAM from VRAM, or VRAM from RAM... or even VRAM from VRAM. virtual bool PerformMemoryCopy(u32 dest, u32 src, int size) = 0; virtual bool PerformMemorySet(u32 dest, u8 v, int size) = 0; diff --git a/GPU/Null/NullGpu.cpp b/GPU/Null/NullGpu.cpp index 9f6b881163..4e67b381d4 100644 --- a/GPU/Null/NullGpu.cpp +++ b/GPU/Null/NullGpu.cpp @@ -687,6 +687,10 @@ void NullGPU::InvalidateCache(u32 addr, int size, GPUInvalidationType type) { // Nothing to invalidate. } +void NullGPU::NotifyVideoUpload(u32 addr, int size, int width, int format) { + // Nothing to do. +} + bool NullGPU::PerformMemoryCopy(u32 dest, u32 src, int size) { // Nothing to update. InvalidateCache(dest, size, GPU_INVALIDATE_HINT); diff --git a/GPU/Null/NullGpu.h b/GPU/Null/NullGpu.h index db6f9000ed..7918054673 100644 --- a/GPU/Null/NullGpu.h +++ b/GPU/Null/NullGpu.h @@ -34,6 +34,7 @@ public: void CopyDisplayToOutput() override {} void UpdateStats() override; void InvalidateCache(u32 addr, int size, GPUInvalidationType type) override; + void NotifyVideoUpload(u32 addr, int size, int width, int format) override; bool PerformMemoryCopy(u32 dest, u32 src, int size) override; bool PerformMemorySet(u32 dest, u8 v, int size) override; bool PerformMemoryDownload(u32 dest, int size) override; diff --git a/GPU/Software/SoftGpu.cpp b/GPU/Software/SoftGpu.cpp index ad96fce331..7e9d48158c 100644 --- a/GPU/Software/SoftGpu.cpp +++ b/GPU/Software/SoftGpu.cpp @@ -873,6 +873,11 @@ void SoftGPU::InvalidateCache(u32 addr, int size, GPUInvalidationType type) // Nothing to invalidate. } +void SoftGPU::NotifyVideoUpload(u32 addr, int size, int width, int format) +{ + // Ignore. +} + bool SoftGPU::PerformMemoryCopy(u32 dest, u32 src, int size) { // Nothing to update. diff --git a/GPU/Software/SoftGpu.h b/GPU/Software/SoftGpu.h index 8cdd67ed69..e06e664c92 100644 --- a/GPU/Software/SoftGpu.h +++ b/GPU/Software/SoftGpu.h @@ -58,6 +58,7 @@ public: void CopyDisplayToOutput() override; void UpdateStats() override; void InvalidateCache(u32 addr, int size, GPUInvalidationType type) override; + void NotifyVideoUpload(u32 addr, int size, int width, int format) override; bool PerformMemoryCopy(u32 dest, u32 src, int size) override; bool PerformMemorySet(u32 dest, u8 v, int size) override; bool PerformMemoryDownload(u32 dest, int size) override; From 48729b90d8ee9489efa851f37c4f261ab97121d5 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 17 Jan 2016 12:45:28 -0800 Subject: [PATCH 4/5] Correct buffer size when writing a video range. --- Core/HW/MediaEngine.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Core/HW/MediaEngine.cpp b/Core/HW/MediaEngine.cpp index 4d43585244..ebeb6e91db 100644 --- a/Core/HW/MediaEngine.cpp +++ b/Core/HW/MediaEngine.cpp @@ -799,7 +799,8 @@ int MediaEngine::writeVideoImageWithRange(u32 bufferPtr, int frameWidth, int vid delete [] imgbuf; } - return videoImageSize; + // Account for the y offset as well. + return videoImageSize + videoLineSize * ypos; #endif // USE_FFMPEG return 0; } From b40c3fd839b6052a944390026fbd3413788e4d34 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 17 Jan 2016 12:52:40 -0800 Subject: [PATCH 5/5] Use video format when uploading to framebuffers. Expected to help Bounty Hound, #8392. --- GPU/Common/FramebufferCommon.cpp | 20 ++++++++++++++++++++ GPU/Common/FramebufferCommon.h | 1 + GPU/Directx9/GPU_DX9.cpp | 3 +++ GPU/GLES/GLES_GPU.cpp | 3 +++ 4 files changed, 27 insertions(+) diff --git a/GPU/Common/FramebufferCommon.cpp b/GPU/Common/FramebufferCommon.cpp index 37018a0f62..6a17a6ff19 100644 --- a/GPU/Common/FramebufferCommon.cpp +++ b/GPU/Common/FramebufferCommon.cpp @@ -487,6 +487,26 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(const Frame return vfb; } +void FramebufferManagerCommon::NotifyVideoUpload(u32 addr, int size, int width, GEBufferFormat fmt) { + // Note: UpdateFromMemory() is still called later. + // This is a special case where we have extra information prior to the invalidation. + + // TODO: Could possibly be an offset... + VirtualFramebuffer *vfb = GetVFBAt(addr); + if (vfb) { + if (vfb->format != fmt || vfb->drawnFormat != fmt) { + DEBUG_LOG(ME, "Changing format for %08x from %d to %d", addr, vfb->drawnFormat, fmt); + vfb->format = fmt; + vfb->drawnFormat = fmt; + + // Let's count this as a "render". This will also force us to use the correct format. + vfb->last_frame_render = gpuStats.numFlips; + } + + // TODO: Check width? + } +} + void FramebufferManagerCommon::UpdateFromMemory(u32 addr, int size, bool safe) { addr &= ~0x40000000; // TODO: Could go through all FBOs, but probably not important? diff --git a/GPU/Common/FramebufferCommon.h b/GPU/Common/FramebufferCommon.h index 62d9100c11..e236a64f6d 100644 --- a/GPU/Common/FramebufferCommon.h +++ b/GPU/Common/FramebufferCommon.h @@ -160,6 +160,7 @@ public: virtual void RebindFramebuffer() = 0; bool NotifyFramebufferCopy(u32 src, u32 dest, int size, bool isMemset, u32 skipDrawReason); + void NotifyVideoUpload(u32 addr, int size, int width, GEBufferFormat fmt); void UpdateFromMemory(u32 addr, int size, bool safe); virtual bool NotifyStencilUpload(u32 addr, int size, bool skipZero = false) = 0; // Returns true if it's sure this is a direct FBO->FBO transfer and it has already handle it. diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index ad74afb9f2..ab3b83acaf 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -1953,6 +1953,9 @@ void DIRECTX9_GPU::InvalidateCacheInternal(u32 addr, int size, GPUInvalidationTy } void DIRECTX9_GPU::NotifyVideoUpload(u32 addr, int size, int width, int format) { + if (Memory::IsVRAMAddress(addr)) { + framebufferManager_.NotifyVideoUpload(addr, size, width, (GEBufferFormat)format); + } InvalidateCache(addr, size, GPU_INVALIDATE_SAFE); } diff --git a/GPU/GLES/GLES_GPU.cpp b/GPU/GLES/GLES_GPU.cpp index ab6853331b..1d0aae3dcf 100644 --- a/GPU/GLES/GLES_GPU.cpp +++ b/GPU/GLES/GLES_GPU.cpp @@ -2202,6 +2202,9 @@ void GLES_GPU::InvalidateCacheInternal(u32 addr, int size, GPUInvalidationType t } void GLES_GPU::NotifyVideoUpload(u32 addr, int size, int width, int format) { + if (Memory::IsVRAMAddress(addr)) { + framebufferManager_.NotifyVideoUpload(addr, size, width, (GEBufferFormat)format); + } InvalidateCache(addr, size, GPU_INVALIDATE_SAFE); }