mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-23 06:09:50 -06:00
Move common EFB copy code into VideoCommon
Addded a few duplicated depth copy texture formats to the enum in TextureDecoder.h. These texture formats were already implemented in TextureCacheBase and the ogl/dx11 texture cache implementations.
This commit is contained in:
@ -87,55 +87,21 @@ void PSTextureEncoder::Shutdown()
|
||||
SAFE_RELEASE(m_out);
|
||||
}
|
||||
|
||||
size_t PSTextureEncoder::Encode(u8* dst, unsigned int dstFormat, size_t dstStride,
|
||||
void PSTextureEncoder::Encode(u8* dst, const TextureCache::TCacheEntryBase *texture_entry,
|
||||
PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect,
|
||||
bool isIntensity, bool scaleByHalf)
|
||||
{
|
||||
if (!m_ready) // Make sure we initialized OK
|
||||
return 0;
|
||||
|
||||
// Clamp srcRect to 640x528. BPS: The Strike tries to encode an 800x600
|
||||
// texture, which is invalid.
|
||||
EFBRectangle correctSrc = srcRect;
|
||||
correctSrc.ClampUL(0, 0, EFB_WIDTH, EFB_HEIGHT);
|
||||
|
||||
// Validate source rect size
|
||||
if (correctSrc.GetWidth() <= 0 || correctSrc.GetHeight() <= 0)
|
||||
return 0;
|
||||
return;
|
||||
|
||||
HRESULT hr;
|
||||
|
||||
unsigned int blockW = BLOCK_WIDTHS[dstFormat];
|
||||
unsigned int blockH = BLOCK_HEIGHTS[dstFormat];
|
||||
|
||||
// Round up source dims to multiple of block size
|
||||
unsigned int actualWidth = correctSrc.GetWidth() / (scaleByHalf ? 2 : 1);
|
||||
actualWidth = (actualWidth + blockW-1) & ~(blockW-1);
|
||||
unsigned int actualHeight = correctSrc.GetHeight() / (scaleByHalf ? 2 : 1);
|
||||
actualHeight = (actualHeight + blockH-1) & ~(blockH-1);
|
||||
|
||||
unsigned int numBlocksX = actualWidth/blockW;
|
||||
unsigned int numBlocksY = actualHeight/blockH;
|
||||
|
||||
unsigned int cacheLinesPerRow;
|
||||
if (dstFormat == 0x6) // RGBA takes two cache lines per block; all others take one
|
||||
cacheLinesPerRow = numBlocksX*2;
|
||||
else
|
||||
cacheLinesPerRow = numBlocksX;
|
||||
_assert_msg_(VIDEO, cacheLinesPerRow*32 <= MAX_BYTES_PER_BLOCK_ROW, "cache lines per row sanity check");
|
||||
|
||||
unsigned int totalCacheLines = cacheLinesPerRow * numBlocksY;
|
||||
_assert_msg_(VIDEO, totalCacheLines*32 <= MAX_BYTES_PER_ENCODE, "total encode size sanity check");
|
||||
|
||||
size_t encodeSize = 0;
|
||||
|
||||
// Reset API
|
||||
g_renderer->ResetAPIState();
|
||||
|
||||
// Set up all the state for EFB encoding
|
||||
|
||||
{
|
||||
D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, FLOAT(cacheLinesPerRow * 8), FLOAT(numBlocksY));
|
||||
D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, FLOAT(texture_entry->CacheLinesPerRow() * 8), FLOAT(texture_entry->NumBlocksY()));
|
||||
D3D::context->RSSetViewports(1, &vp);
|
||||
|
||||
EFBRectangle fullSrcRect;
|
||||
@ -155,9 +121,9 @@ size_t PSTextureEncoder::Encode(u8* dst, unsigned int dstFormat, size_t dstStrid
|
||||
FramebufferManager::GetResolvedEFBColorTexture()->GetSRV();
|
||||
|
||||
EFBEncodeParams params;
|
||||
params.SrcLeft = correctSrc.left;
|
||||
params.SrcTop = correctSrc.top;
|
||||
params.DestWidth = actualWidth;
|
||||
params.SrcLeft = srcRect.left;
|
||||
params.SrcTop = srcRect.top;
|
||||
params.DestWidth = texture_entry->native_width;
|
||||
params.ScaleFactor = scaleByHalf ? 2 : 1;
|
||||
D3D::context->UpdateSubresource(m_encodeParams, 0, nullptr, ¶ms, 0, 0);
|
||||
D3D::stateman->SetPixelConstants(m_encodeParams);
|
||||
@ -172,12 +138,12 @@ size_t PSTextureEncoder::Encode(u8* dst, unsigned int dstFormat, size_t dstStrid
|
||||
targetRect.AsRECT(),
|
||||
Renderer::GetTargetWidth(),
|
||||
Renderer::GetTargetHeight(),
|
||||
SetStaticShader(dstFormat, srcFormat, isIntensity, scaleByHalf),
|
||||
SetStaticShader(texture_entry->format, srcFormat, isIntensity, scaleByHalf),
|
||||
VertexShaderCache::GetSimpleVertexShader(),
|
||||
VertexShaderCache::GetSimpleInputLayout());
|
||||
|
||||
// Copy to staging buffer
|
||||
D3D11_BOX srcBox = CD3D11_BOX(0, 0, 0, cacheLinesPerRow * 8, numBlocksY, 1);
|
||||
D3D11_BOX srcBox = CD3D11_BOX(0, 0, 0, texture_entry->CacheLinesPerRow() * 8, texture_entry->NumBlocksY(), 1);
|
||||
D3D::context->CopySubresourceRegion(m_outStage, 0, 0, 0, 0, m_out, 0, &srcBox);
|
||||
|
||||
// Transfer staging buffer to GameCube/Wii RAM
|
||||
@ -186,16 +152,14 @@ size_t PSTextureEncoder::Encode(u8* dst, unsigned int dstFormat, size_t dstStrid
|
||||
CHECK(SUCCEEDED(hr), "map staging buffer (0x%x)", hr);
|
||||
|
||||
u8* src = (u8*)map.pData;
|
||||
for (unsigned int y = 0; y < numBlocksY; ++y)
|
||||
for (unsigned int y = 0; y < texture_entry->NumBlocksY(); ++y)
|
||||
{
|
||||
memcpy(dst, src, cacheLinesPerRow*32);
|
||||
dst += dstStride;
|
||||
memcpy(dst, src, texture_entry->CacheLinesPerRow() * 32);
|
||||
dst += texture_entry->memory_stride;
|
||||
src += map.RowPitch;
|
||||
}
|
||||
|
||||
D3D::context->Unmap(m_outStage, 0);
|
||||
|
||||
encodeSize = dstStride * numBlocksY;
|
||||
}
|
||||
|
||||
// Restore API
|
||||
@ -203,8 +167,6 @@ size_t PSTextureEncoder::Encode(u8* dst, unsigned int dstFormat, size_t dstStrid
|
||||
D3D::context->OMSetRenderTargets(1,
|
||||
&FramebufferManager::GetEFBColorTexture()->GetRTV(),
|
||||
FramebufferManager::GetEFBDepthTexture()->GetDSV());
|
||||
|
||||
return encodeSize;
|
||||
}
|
||||
|
||||
ID3D11PixelShader* PSTextureEncoder::SetStaticShader(unsigned int dstFormat, PEControl::PixelFormat srcFormat,
|
||||
|
@ -6,6 +6,8 @@
|
||||
|
||||
#include "VideoBackends/D3D/TextureEncoder.h"
|
||||
|
||||
#include "VideoCommon/TextureCacheBase.h"
|
||||
|
||||
struct ID3D11Texture2D;
|
||||
struct ID3D11RenderTargetView;
|
||||
struct ID3D11Buffer;
|
||||
@ -29,7 +31,7 @@ public:
|
||||
|
||||
void Init();
|
||||
void Shutdown();
|
||||
size_t Encode(u8* dst, unsigned int dstFormat, size_t dstStride,
|
||||
void Encode(u8* dst, const TextureCache::TCacheEntryBase *texture_entry,
|
||||
PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect,
|
||||
bool isIntensity, bool scaleByHalf);
|
||||
|
||||
|
@ -2,7 +2,6 @@
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "Core/HW/Memmap.h"
|
||||
#include "VideoBackends/D3D/D3DBase.h"
|
||||
#include "VideoBackends/D3D/D3DShader.h"
|
||||
#include "VideoBackends/D3D/D3DState.h"
|
||||
@ -185,7 +184,7 @@ TextureCache::TCacheEntryBase* TextureCache::CreateTexture(const TCacheEntryConf
|
||||
}
|
||||
}
|
||||
|
||||
void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFormat, u32 dstStride,
|
||||
void TextureCache::TCacheEntry::FromRenderTarget(u8* dst, unsigned int dstFormat, u32 dstStride,
|
||||
PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect,
|
||||
bool isIntensity, bool scaleByHalf, unsigned int cbufid,
|
||||
const float *colmat)
|
||||
@ -226,10 +225,13 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
|
||||
|
||||
// Create texture copy
|
||||
D3D::drawShadedTexQuad(
|
||||
(srcFormat == PEControl::Z24) ? FramebufferManager::GetEFBDepthTexture()->GetSRV() : FramebufferManager::GetEFBColorTexture()->GetSRV(),
|
||||
&sourcerect, Renderer::GetTargetWidth(), Renderer::GetTargetHeight(),
|
||||
(srcFormat == PEControl::Z24) ? PixelShaderCache::GetDepthMatrixProgram(true) : PixelShaderCache::GetColorMatrixProgram(true),
|
||||
VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout(), GeometryShaderCache::GetCopyGeometryShader());
|
||||
(srcFormat == PEControl::Z24 ? FramebufferManager::GetEFBDepthTexture() : FramebufferManager::GetEFBColorTexture())->GetSRV(),
|
||||
&sourcerect, Renderer::GetTargetWidth(),
|
||||
Renderer::GetTargetHeight(),
|
||||
srcFormat == PEControl::Z24 ? PixelShaderCache::GetDepthMatrixProgram(true) : PixelShaderCache::GetColorMatrixProgram(true),
|
||||
VertexShaderCache::GetSimpleVertexShader(),
|
||||
VertexShaderCache::GetSimpleInputLayout(),
|
||||
GeometryShaderCache::GetCopyGeometryShader());
|
||||
|
||||
D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV());
|
||||
|
||||
@ -237,14 +239,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
|
||||
|
||||
if (!g_ActiveConfig.bSkipEFBCopyToRam)
|
||||
{
|
||||
u8* dst = Memory::GetPointer(dstAddr);
|
||||
size_t encoded_size = g_encoder->Encode(dst, dstFormat, dstStride, srcFormat, srcRect, isIntensity, scaleByHalf);
|
||||
|
||||
size_in_bytes = (u32)encoded_size;
|
||||
|
||||
TextureCache::MakeRangeDynamic(dstAddr, (u32)encoded_size);
|
||||
|
||||
this->hash = GetHash64(dst, (int)encoded_size, g_ActiveConfig.iSafeTextureCache_ColorSamples);
|
||||
g_encoder->Encode(dst, this, srcFormat, srcRect, isIntensity, scaleByHalf);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,7 +34,7 @@ private:
|
||||
void Load(unsigned int width, unsigned int height,
|
||||
unsigned int expanded_width, unsigned int levels) override;
|
||||
|
||||
void FromRenderTarget(u32 dstAddr, unsigned int dstFormat, u32 dstStride,
|
||||
void FromRenderTarget(u8* dst, unsigned int dstFormat, u32 dstStride,
|
||||
PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect,
|
||||
bool isIntensity, bool scaleByHalf, unsigned int cbufid,
|
||||
const float *colmat) override;
|
||||
|
@ -5,96 +5,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "VideoCommon/BPMemory.h"
|
||||
#include "VideoCommon/TextureCacheBase.h"
|
||||
#include "VideoCommon/VideoCommon.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
|
||||
// 4-bit format: 8x8 texels / cache line
|
||||
// 8-bit format: 8x4 texels / cache line
|
||||
// 16-bit format: 4x4 texels / cache line
|
||||
// 32-bit format: 4x4 texels / 2 cache lines
|
||||
// Compressed format: 8x8 texels / cache line
|
||||
|
||||
// Document EFB encoding formats here with examples of where they are used.
|
||||
|
||||
// Format: 0 - R4
|
||||
// Used in The Legend of Zelda: The Wind Waker for character shadows (srcFormat 1,
|
||||
// isIntensity 1, scaleByHalf 1).
|
||||
|
||||
// Format: 1 - R8
|
||||
// FIXME: Unseen. May or may not be a duplicate of format 8.
|
||||
|
||||
// Format: 2 - A4 R4
|
||||
// FIXME: Unseen.
|
||||
|
||||
// Format: 3 - A8 R8
|
||||
// FIXME: Unseen.
|
||||
|
||||
// Format: 4 - R5 G6 B5
|
||||
// Used in Wind Waker for most render-to-texture effects like heat shimmer and
|
||||
// depth-of-field.
|
||||
|
||||
// Format: 5 - 1 R5 G5 B5 or 0 A3 R4 G4 B4
|
||||
// Used in Twilight Princess for character shadows.
|
||||
|
||||
// Format: 6 - A8 R8 A8 R8 | G8 B8 G8 B8
|
||||
// Used in Twilight Princess for bloom effect.
|
||||
|
||||
// Format: 7 - A8
|
||||
// Used in Metroid Prime 2 for the scan visor.
|
||||
|
||||
// Format: 8 - R8
|
||||
// Used in Twilight Princess for the map.
|
||||
|
||||
// Format: 9 - G8
|
||||
// FIXME: Unseen.
|
||||
|
||||
// Format: A - B8
|
||||
// Used in Metroid Prime 2 for the scan visor.
|
||||
|
||||
// Format: B - G8 R8
|
||||
// Used in Wind Waker for depth-of-field. Usually used with srcFormat 3 to
|
||||
// render depth textures. The bytes are swapped, so games have to correct it
|
||||
// in RAM before using it as a texture.
|
||||
|
||||
// Format: C - B8 G8
|
||||
// FIXME: Unseen.
|
||||
|
||||
const unsigned int BLOCK_WIDTHS[16] = {
|
||||
8, // R4
|
||||
8, // R8 (FIXME: duplicate of R8 below?)
|
||||
8, // A4 R4
|
||||
4, // A8 R8
|
||||
4, // R5 G6 B5
|
||||
4, // 1 R5 G5 B5 or 0 A3 R4 G4 B4
|
||||
4, // A8 R8 A8 R8 | G8 B8 G8 B8 (two cache lines)
|
||||
8, // A8
|
||||
8, // R8 (FIXME: duplicate of R8 above?)
|
||||
8, // G8
|
||||
8, // B8
|
||||
4, // G8 R8
|
||||
4, // B8 G8
|
||||
0, 0, 0 // Unknown formats
|
||||
};
|
||||
|
||||
const unsigned int BLOCK_HEIGHTS[16] = {
|
||||
8, // R4
|
||||
4, // R8 (FIXME: duplicate of R8 below?)
|
||||
4, // A4 R4
|
||||
4, // A8 R8
|
||||
4, // R5 G6 B5
|
||||
4, // 1 R5 G5 B5 or 0 A3 R4 G4 B4
|
||||
4, // A8 R8 A8 R8 | G8 B8 G8 B8 (two cache lines)
|
||||
4, // A8
|
||||
4, // R8 (FIXME: duplicate of R8 above?)
|
||||
4, // G8
|
||||
4, // B8
|
||||
4, // G8 R8
|
||||
4, // B8 G8
|
||||
0, 0, 0 // Unknown formats
|
||||
};
|
||||
|
||||
// Maximum number of bytes that can occur in a texture block-row generated by
|
||||
// the encoder
|
||||
static const UINT MAX_BYTES_PER_BLOCK_ROW = (EFB_WIDTH/4)*64;
|
||||
@ -111,7 +26,7 @@ public:
|
||||
virtual void Init() = 0;
|
||||
virtual void Shutdown() = 0;
|
||||
// Returns size in bytes of encoded block of memory
|
||||
virtual size_t Encode(u8* dst, unsigned int dstFormat, size_t dstStride,
|
||||
virtual void Encode(u8* dst, const TextureCache::TCacheEntryBase *texture_entry,
|
||||
PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect,
|
||||
bool isIntensity, bool scaleByHalf) = 0;
|
||||
|
||||
|
Reference in New Issue
Block a user