Merge pull request #3210 from degasus/efbcopy
TextureCache: Efb Copy Separation
This commit is contained in:
commit
18afbe6490
|
@ -87,7 +87,7 @@ void PSTextureEncoder::Shutdown()
|
||||||
SAFE_RELEASE(m_out);
|
SAFE_RELEASE(m_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PSTextureEncoder::Encode(u8* dst, const TextureCache::TCacheEntryBase *texture_entry,
|
void PSTextureEncoder::Encode(u8* dst, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
|
||||||
PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect,
|
PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect,
|
||||||
bool isIntensity, bool scaleByHalf)
|
bool isIntensity, bool scaleByHalf)
|
||||||
{
|
{
|
||||||
|
@ -101,9 +101,9 @@ void PSTextureEncoder::Encode(u8* dst, const TextureCache::TCacheEntryBase *text
|
||||||
|
|
||||||
// Set up all the state for EFB encoding
|
// Set up all the state for EFB encoding
|
||||||
{
|
{
|
||||||
const u32 words_per_row = texture_entry->BytesPerRow() / sizeof(u32);
|
const u32 words_per_row = bytes_per_row / sizeof(u32);
|
||||||
|
|
||||||
D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, FLOAT(words_per_row), FLOAT(texture_entry->NumBlocksY()));
|
D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, FLOAT(words_per_row), FLOAT(num_blocks_y));
|
||||||
D3D::context->RSSetViewports(1, &vp);
|
D3D::context->RSSetViewports(1, &vp);
|
||||||
|
|
||||||
EFBRectangle fullSrcRect;
|
EFBRectangle fullSrcRect;
|
||||||
|
@ -125,7 +125,7 @@ void PSTextureEncoder::Encode(u8* dst, const TextureCache::TCacheEntryBase *text
|
||||||
EFBEncodeParams params;
|
EFBEncodeParams params;
|
||||||
params.SrcLeft = srcRect.left;
|
params.SrcLeft = srcRect.left;
|
||||||
params.SrcTop = srcRect.top;
|
params.SrcTop = srcRect.top;
|
||||||
params.DestWidth = texture_entry->native_width;
|
params.DestWidth = native_width;
|
||||||
params.ScaleFactor = scaleByHalf ? 2 : 1;
|
params.ScaleFactor = scaleByHalf ? 2 : 1;
|
||||||
D3D::context->UpdateSubresource(m_encodeParams, 0, nullptr, ¶ms, 0, 0);
|
D3D::context->UpdateSubresource(m_encodeParams, 0, nullptr, ¶ms, 0, 0);
|
||||||
D3D::stateman->SetPixelConstants(m_encodeParams);
|
D3D::stateman->SetPixelConstants(m_encodeParams);
|
||||||
|
@ -140,12 +140,12 @@ void PSTextureEncoder::Encode(u8* dst, const TextureCache::TCacheEntryBase *text
|
||||||
targetRect.AsRECT(),
|
targetRect.AsRECT(),
|
||||||
Renderer::GetTargetWidth(),
|
Renderer::GetTargetWidth(),
|
||||||
Renderer::GetTargetHeight(),
|
Renderer::GetTargetHeight(),
|
||||||
SetStaticShader(texture_entry->format, srcFormat, isIntensity, scaleByHalf),
|
SetStaticShader(format, srcFormat, isIntensity, scaleByHalf),
|
||||||
VertexShaderCache::GetSimpleVertexShader(),
|
VertexShaderCache::GetSimpleVertexShader(),
|
||||||
VertexShaderCache::GetSimpleInputLayout());
|
VertexShaderCache::GetSimpleInputLayout());
|
||||||
|
|
||||||
// Copy to staging buffer
|
// Copy to staging buffer
|
||||||
D3D11_BOX srcBox = CD3D11_BOX(0, 0, 0, words_per_row, texture_entry->NumBlocksY(), 1);
|
D3D11_BOX srcBox = CD3D11_BOX(0, 0, 0, words_per_row, num_blocks_y, 1);
|
||||||
D3D::context->CopySubresourceRegion(m_outStage, 0, 0, 0, 0, m_out, 0, &srcBox);
|
D3D::context->CopySubresourceRegion(m_outStage, 0, 0, 0, 0, m_out, 0, &srcBox);
|
||||||
|
|
||||||
// Transfer staging buffer to GameCube/Wii RAM
|
// Transfer staging buffer to GameCube/Wii RAM
|
||||||
|
@ -154,11 +154,11 @@ void PSTextureEncoder::Encode(u8* dst, const TextureCache::TCacheEntryBase *text
|
||||||
CHECK(SUCCEEDED(hr), "map staging buffer (0x%x)", hr);
|
CHECK(SUCCEEDED(hr), "map staging buffer (0x%x)", hr);
|
||||||
|
|
||||||
u8* src = (u8*)map.pData;
|
u8* src = (u8*)map.pData;
|
||||||
u32 readStride = std::min(texture_entry->BytesPerRow(), map.RowPitch);
|
u32 readStride = std::min(bytes_per_row, map.RowPitch);
|
||||||
for (unsigned int y = 0; y < texture_entry->NumBlocksY(); ++y)
|
for (unsigned int y = 0; y < num_blocks_y; ++y)
|
||||||
{
|
{
|
||||||
memcpy(dst, src, readStride);
|
memcpy(dst, src, readStride);
|
||||||
dst += texture_entry->memory_stride;
|
dst += memory_stride;
|
||||||
src += map.RowPitch;
|
src += map.RowPitch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ public:
|
||||||
|
|
||||||
void Init();
|
void Init();
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
void Encode(u8* dst, const TextureCacheBase::TCacheEntryBase* texture_entry,
|
void Encode(u8* dst, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
|
||||||
PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect,
|
PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect,
|
||||||
bool isIntensity, bool scaleByHalf);
|
bool isIntensity, bool scaleByHalf);
|
||||||
|
|
||||||
|
|
|
@ -184,10 +184,8 @@ TextureCacheBase::TCacheEntryBase* TextureCache::CreateTexture(const TCacheEntry
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureCache::TCacheEntry::FromRenderTarget(u8* dst, unsigned int dstFormat, u32 dstStride,
|
void TextureCache::TCacheEntry::FromRenderTarget(u8* dst, PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect,
|
||||||
PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect,
|
bool scaleByHalf, unsigned int cbufid, const float *colmat)
|
||||||
bool isIntensity, bool scaleByHalf, unsigned int cbufid,
|
|
||||||
const float *colmat)
|
|
||||||
{
|
{
|
||||||
g_renderer->ResetAPIState();
|
g_renderer->ResetAPIState();
|
||||||
|
|
||||||
|
@ -236,11 +234,13 @@ void TextureCache::TCacheEntry::FromRenderTarget(u8* dst, unsigned int dstFormat
|
||||||
D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV());
|
D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV());
|
||||||
|
|
||||||
g_renderer->RestoreAPIState();
|
g_renderer->RestoreAPIState();
|
||||||
|
}
|
||||||
|
|
||||||
if (g_ActiveConfig.bSkipEFBCopyToRam)
|
void TextureCache::CopyEFB(u8* dst, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
|
||||||
this->Zero(dst);
|
PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect,
|
||||||
else
|
bool isIntensity, bool scaleByHalf)
|
||||||
g_encoder->Encode(dst, this, srcFormat, srcRect, isIntensity, scaleByHalf);
|
{
|
||||||
|
g_encoder->Encode(dst, format, native_width, bytes_per_row, num_blocks_y, memory_stride, srcFormat, srcRect, isIntensity, scaleByHalf);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char palette_shader[] =
|
const char palette_shader[] =
|
||||||
|
|
|
@ -34,10 +34,8 @@ private:
|
||||||
void Load(unsigned int width, unsigned int height,
|
void Load(unsigned int width, unsigned int height,
|
||||||
unsigned int expanded_width, unsigned int levels) override;
|
unsigned int expanded_width, unsigned int levels) override;
|
||||||
|
|
||||||
void FromRenderTarget(u8* dst, unsigned int dstFormat, u32 dstStride,
|
void FromRenderTarget(u8* dst, PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect,
|
||||||
PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect,
|
bool scaleByHalf, unsigned int cbufid, const float *colmat) override;
|
||||||
bool isIntensity, bool scaleByHalf, unsigned int cbufid,
|
|
||||||
const float *colmat) override;
|
|
||||||
|
|
||||||
void Bind(unsigned int stage) override;
|
void Bind(unsigned int stage) override;
|
||||||
bool Save(const std::string& filename, unsigned int level) override;
|
bool Save(const std::string& filename, unsigned int level) override;
|
||||||
|
@ -49,6 +47,10 @@ private:
|
||||||
|
|
||||||
void ConvertTexture(TCacheEntryBase* entry, TCacheEntryBase* unconverted, void* palette, TlutFormat format) override;
|
void ConvertTexture(TCacheEntryBase* entry, TCacheEntryBase* unconverted, void* palette, TlutFormat format) override;
|
||||||
|
|
||||||
|
void CopyEFB(u8* dst, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
|
||||||
|
PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect,
|
||||||
|
bool isIntensity, bool scaleByHalf) override;
|
||||||
|
|
||||||
void CompileShaders() override { }
|
void CompileShaders() override { }
|
||||||
void DeleteShaders() override { }
|
void DeleteShaders() override { }
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ public:
|
||||||
virtual void Init() = 0;
|
virtual void Init() = 0;
|
||||||
virtual void Shutdown() = 0;
|
virtual void Shutdown() = 0;
|
||||||
// Returns size in bytes of encoded block of memory
|
// Returns size in bytes of encoded block of memory
|
||||||
virtual void Encode(u8* dst, const TextureCacheBase::TCacheEntryBase* texture_entry,
|
virtual void Encode(u8* dst, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
|
||||||
PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect,
|
PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect,
|
||||||
bool isIntensity, bool scaleByHalf) = 0;
|
bool isIntensity, bool scaleByHalf) = 0;
|
||||||
|
|
||||||
|
|
|
@ -215,10 +215,8 @@ void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height,
|
||||||
TextureCache::SetStage();
|
TextureCache::SetStage();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureCache::TCacheEntry::FromRenderTarget(u8* dstPointer, unsigned int dstFormat, u32 dstStride,
|
void TextureCache::TCacheEntry::FromRenderTarget(u8* dstPointer, PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect,
|
||||||
PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect,
|
bool scaleByHalf, unsigned int cbufid, const float *colmat)
|
||||||
bool isIntensity, bool scaleByHalf, unsigned int cbufid,
|
|
||||||
const float *colmat)
|
|
||||||
{
|
{
|
||||||
g_renderer->ResetAPIState(); // reset any game specific settings
|
g_renderer->ResetAPIState(); // reset any game specific settings
|
||||||
|
|
||||||
|
@ -264,27 +262,27 @@ void TextureCache::TCacheEntry::FromRenderTarget(u8* dstPointer, unsigned int ds
|
||||||
|
|
||||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||||
|
|
||||||
if (g_ActiveConfig.bSkipEFBCopyToRam)
|
|
||||||
{
|
|
||||||
this->Zero(dstPointer);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TextureConverter::EncodeToRamFromTexture(
|
|
||||||
dstPointer,
|
|
||||||
this,
|
|
||||||
read_texture,
|
|
||||||
srcFormat == PEControl::Z24,
|
|
||||||
isIntensity,
|
|
||||||
scaleByHalf,
|
|
||||||
srcRect);
|
|
||||||
}
|
|
||||||
|
|
||||||
FramebufferManager::SetFramebuffer(0);
|
FramebufferManager::SetFramebuffer(0);
|
||||||
|
|
||||||
g_renderer->RestoreAPIState();
|
g_renderer->RestoreAPIState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TextureCache::CopyEFB(u8* dst, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
|
||||||
|
PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect,
|
||||||
|
bool isIntensity, bool scaleByHalf)
|
||||||
|
{
|
||||||
|
TextureConverter::EncodeToRamFromTexture(
|
||||||
|
dst,
|
||||||
|
format,
|
||||||
|
native_width,
|
||||||
|
bytes_per_row,
|
||||||
|
num_blocks_y,
|
||||||
|
memory_stride,
|
||||||
|
srcFormat,
|
||||||
|
isIntensity,
|
||||||
|
scaleByHalf,
|
||||||
|
srcRect);
|
||||||
|
}
|
||||||
|
|
||||||
TextureCache::TextureCache()
|
TextureCache::TextureCache()
|
||||||
{
|
{
|
||||||
CompileShaders();
|
CompileShaders();
|
||||||
|
|
|
@ -42,10 +42,8 @@ private:
|
||||||
void Load(unsigned int width, unsigned int height,
|
void Load(unsigned int width, unsigned int height,
|
||||||
unsigned int expanded_width, unsigned int level) override;
|
unsigned int expanded_width, unsigned int level) override;
|
||||||
|
|
||||||
void FromRenderTarget(u8 *dst, unsigned int dstFormat, u32 dstStride,
|
void FromRenderTarget(u8 *dst, PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect,
|
||||||
PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect,
|
bool scaleByHalf, unsigned int cbufid, const float *colmat) override;
|
||||||
bool isIntensity, bool scaleByHalf, unsigned int cbufid,
|
|
||||||
const float *colmat) override;
|
|
||||||
|
|
||||||
void Bind(unsigned int stage) override;
|
void Bind(unsigned int stage) override;
|
||||||
bool Save(const std::string& filename, unsigned int level) override;
|
bool Save(const std::string& filename, unsigned int level) override;
|
||||||
|
@ -56,6 +54,10 @@ private:
|
||||||
TCacheEntryBase* CreateTexture(const TCacheEntryConfig& config) override;
|
TCacheEntryBase* CreateTexture(const TCacheEntryConfig& config) override;
|
||||||
void ConvertTexture(TCacheEntryBase* entry, TCacheEntryBase* unconverted, void* palette, TlutFormat format) override;
|
void ConvertTexture(TCacheEntryBase* entry, TCacheEntryBase* unconverted, void* palette, TlutFormat format) override;
|
||||||
|
|
||||||
|
void CopyEFB(u8* dst, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
|
||||||
|
PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect,
|
||||||
|
bool isIntensity, bool scaleByHalf) override;
|
||||||
|
|
||||||
void CompileShaders() override;
|
void CompileShaders() override;
|
||||||
void DeleteShaders() override;
|
void DeleteShaders() override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -269,18 +269,27 @@ static void EncodeToRamUsingShader(GLuint srcTexture,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EncodeToRamFromTexture(u8 *dest_ptr, const TextureCache::TCacheEntryBase *texture_entry,
|
void EncodeToRamFromTexture(u8* dest_ptr, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
|
||||||
GLuint source_texture, bool bFromZBuffer, bool bIsIntensityFmt, int bScaleByHalf, const EFBRectangle& source)
|
PEControl::PixelFormat srcFormat, bool bIsIntensityFmt, int bScaleByHalf, const EFBRectangle& source)
|
||||||
{
|
{
|
||||||
SHADER& texconv_shader = GetOrCreateEncodingShader(texture_entry->format);
|
g_renderer->ResetAPIState();
|
||||||
|
|
||||||
|
SHADER& texconv_shader = GetOrCreateEncodingShader(format);
|
||||||
|
|
||||||
texconv_shader.Bind();
|
texconv_shader.Bind();
|
||||||
glUniform4i(s_encodingUniforms[texture_entry->format],
|
glUniform4i(s_encodingUniforms[format],
|
||||||
source.left, source.top, texture_entry->native_width, bScaleByHalf ? 2 : 1);
|
source.left, source.top, native_width, bScaleByHalf ? 2 : 1);
|
||||||
|
|
||||||
EncodeToRamUsingShader(source_texture,
|
const GLuint read_texture = (srcFormat == PEControl::Z24) ?
|
||||||
dest_ptr, texture_entry->BytesPerRow(), texture_entry->NumBlocksY(),
|
FramebufferManager::ResolveAndGetDepthTarget(source) :
|
||||||
texture_entry->memory_stride, bScaleByHalf > 0 && !bFromZBuffer);
|
FramebufferManager::ResolveAndGetRenderTarget(source);
|
||||||
|
|
||||||
|
EncodeToRamUsingShader(read_texture,
|
||||||
|
dest_ptr, bytes_per_row, num_blocks_y,
|
||||||
|
memory_stride, bScaleByHalf > 0 && srcFormat != PEControl::Z24);
|
||||||
|
|
||||||
|
FramebufferManager::SetFramebuffer(0);
|
||||||
|
g_renderer->RestoreAPIState();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc, u8* destAddr, u32 dstWidth, u32 dstStride, u32 dstHeight)
|
void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc, u8* destAddr, u32 dstWidth, u32 dstStride, u32 dstHeight)
|
||||||
|
|
|
@ -26,8 +26,8 @@ void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc,
|
||||||
void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, GLuint destTexture);
|
void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, GLuint destTexture);
|
||||||
|
|
||||||
// returns size of the encoded data (in bytes)
|
// returns size of the encoded data (in bytes)
|
||||||
void EncodeToRamFromTexture(u8* dest_ptr, const TextureCacheBase::TCacheEntryBase* texture_entry,
|
void EncodeToRamFromTexture(u8* dest_ptr, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
|
||||||
GLuint source_texture, bool bFromZBuffer, bool bIsIntensityFmt, int bScaleByHalf, const EFBRectangle& source);
|
PEControl::PixelFormat srcFormat, bool bIsIntensityFmt, int bScaleByHalf, const EFBRectangle& source);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1032,61 +1032,109 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// create the texture
|
u32 blockH = TexDecoder_GetBlockHeightInTexels(dstFormat);
|
||||||
TCacheEntryConfig config;
|
const u32 blockW = TexDecoder_GetBlockWidthInTexels(dstFormat);
|
||||||
config.rendertarget = true;
|
|
||||||
config.width = scaled_tex_w;
|
|
||||||
config.height = scaled_tex_h;
|
|
||||||
config.layers = FramebufferManagerBase::GetEFBLayers();
|
|
||||||
|
|
||||||
TCacheEntryBase* entry = AllocateTexture(config);
|
// Round up source height to multiple of block size
|
||||||
|
u32 actualHeight = ROUND_UP(tex_h, blockH);
|
||||||
|
const u32 actualWidth = ROUND_UP(tex_w, blockW);
|
||||||
|
|
||||||
entry->SetGeneralParameters(dstAddr, 0, dstFormat);
|
u32 num_blocks_y = actualHeight / blockH;
|
||||||
entry->SetDimensions(tex_w, tex_h, 1);
|
const u32 num_blocks_x = actualWidth / blockW;
|
||||||
|
|
||||||
entry->frameCount = FRAMECOUNT_INVALID;
|
// RGBA takes two cache lines per block; all others take one
|
||||||
entry->SetEfbCopy(dstStride);
|
const u32 bytes_per_block = dstFormat == GX_TF_RGBA8 ? 64 : 32;
|
||||||
entry->is_custom_tex = false;
|
|
||||||
|
|
||||||
entry->FromRenderTarget(dst, dstFormat, dstStride, srcFormat, srcRect, isIntensity, scaleByHalf, cbufid, colmat);
|
u32 bytes_per_row = num_blocks_x * bytes_per_block;
|
||||||
|
|
||||||
u64 hash = entry->CalculateHash();
|
bool copy_to_ram = !g_ActiveConfig.bSkipEFBCopyToRam;
|
||||||
entry->SetHashes(hash, hash);
|
bool copy_to_vram = true;
|
||||||
|
|
||||||
// Invalidate all textures that overlap the range of our efb copy.
|
if (copy_to_ram)
|
||||||
// Unless our efb copy has a weird stride, then we want avoid invalidating textures which
|
|
||||||
// we might be able to do a partial texture update on.
|
|
||||||
if (entry->memory_stride == entry->BytesPerRow())
|
|
||||||
{
|
{
|
||||||
TexCache::iterator iter = textures_by_address.begin();
|
g_texture_cache->CopyEFB(
|
||||||
while (iter != textures_by_address.end())
|
dst,
|
||||||
{
|
dstFormat,
|
||||||
if (iter->second->OverlapsMemoryRange(dstAddr, entry->size_in_bytes))
|
tex_w,
|
||||||
iter = FreeTexture(iter);
|
bytes_per_row,
|
||||||
else
|
num_blocks_y,
|
||||||
++iter;
|
dstStride,
|
||||||
}
|
srcFormat,
|
||||||
|
srcRect,
|
||||||
|
isIntensity,
|
||||||
|
scaleByHalf);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if (g_ActiveConfig.bDumpEFBTarget)
|
|
||||||
{
|
{
|
||||||
static int count = 0;
|
// Hack: Most games don't actually need the correct texture data in RAM
|
||||||
entry->Save(StringFromFormat("%sefb_frame_%i.png", File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(),
|
// and we can just keep a copy in VRAM. We zero the memory so we
|
||||||
count++), 0);
|
// can check it hasn't changed before using our copy in VRAM.
|
||||||
|
u8* ptr = dst;
|
||||||
|
for (u32 i = 0; i < num_blocks_y; i++)
|
||||||
|
{
|
||||||
|
memset(ptr, 0, bytes_per_row);
|
||||||
|
ptr += dstStride;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_bRecordFifoData)
|
if (g_bRecordFifoData)
|
||||||
{
|
{
|
||||||
// Mark the memory behind this efb copy as dynamicly generated for the Fifo log
|
// Mark the memory behind this efb copy as dynamicly generated for the Fifo log
|
||||||
u32 address = dstAddr;
|
u32 address = dstAddr;
|
||||||
for (u32 i = 0; i < entry->NumBlocksY(); i++)
|
for (u32 i = 0; i < num_blocks_y; i++)
|
||||||
{
|
{
|
||||||
FifoRecorder::GetInstance().UseMemory(address, entry->BytesPerRow(), MemoryUpdate::TEXTURE_MAP, true);
|
FifoRecorder::GetInstance().UseMemory(address, bytes_per_row, MemoryUpdate::TEXTURE_MAP, true);
|
||||||
address += entry->memory_stride;
|
address += dstStride;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
textures_by_address.emplace((u64)dstAddr, entry);
|
// Invalidate all textures that overlap the range of our efb copy.
|
||||||
|
// Unless our efb copy has a weird stride, then we want avoid invalidating textures which
|
||||||
|
// we might be able to do a partial texture update on.
|
||||||
|
if (dstStride == bytes_per_row || !copy_to_vram)
|
||||||
|
{
|
||||||
|
TexCache::iterator iter = textures_by_address.begin();
|
||||||
|
while (iter != textures_by_address.end())
|
||||||
|
{
|
||||||
|
if (iter->second->addr + iter->second->size_in_bytes <= dstAddr || iter->second->addr >= dstAddr + num_blocks_y * dstStride)
|
||||||
|
++iter;
|
||||||
|
else
|
||||||
|
iter = FreeTexture(iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (copy_to_vram)
|
||||||
|
{
|
||||||
|
// create the texture
|
||||||
|
TCacheEntryConfig config;
|
||||||
|
config.rendertarget = true;
|
||||||
|
config.width = scaled_tex_w;
|
||||||
|
config.height = scaled_tex_h;
|
||||||
|
config.layers = FramebufferManagerBase::GetEFBLayers();
|
||||||
|
|
||||||
|
TCacheEntryBase* entry = AllocateTexture(config);
|
||||||
|
|
||||||
|
entry->SetGeneralParameters(dstAddr, 0, dstFormat);
|
||||||
|
entry->SetDimensions(tex_w, tex_h, 1);
|
||||||
|
|
||||||
|
entry->frameCount = FRAMECOUNT_INVALID;
|
||||||
|
entry->SetEfbCopy(dstStride);
|
||||||
|
entry->is_custom_tex = false;
|
||||||
|
|
||||||
|
entry->FromRenderTarget(dst, srcFormat, srcRect, scaleByHalf, cbufid, colmat);
|
||||||
|
|
||||||
|
u64 hash = entry->CalculateHash();
|
||||||
|
entry->SetHashes(hash, hash);
|
||||||
|
|
||||||
|
if (g_ActiveConfig.bDumpEFBTarget)
|
||||||
|
{
|
||||||
|
static int count = 0;
|
||||||
|
entry->Save(StringFromFormat("%sefb_frame_%i.png", File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(),
|
||||||
|
count++), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
textures_by_address.emplace((u64)dstAddr, entry);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureCacheBase::TCacheEntryBase* TextureCacheBase::AllocateTexture(const TCacheEntryConfig& config)
|
TextureCacheBase::TCacheEntryBase* TextureCacheBase::AllocateTexture(const TCacheEntryConfig& config)
|
||||||
|
@ -1158,16 +1206,6 @@ void TextureCacheBase::TCacheEntryBase::SetEfbCopy(u32 stride)
|
||||||
size_in_bytes = memory_stride * NumBlocksY();
|
size_in_bytes = memory_stride * NumBlocksY();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fill gamecube memory backing this texture with zeros.
|
|
||||||
void TextureCacheBase::TCacheEntryBase::Zero(u8* ptr)
|
|
||||||
{
|
|
||||||
for (u32 i = 0; i < NumBlocksY(); i++)
|
|
||||||
{
|
|
||||||
memset(ptr, 0, BytesPerRow());
|
|
||||||
ptr += memory_stride;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
u64 TextureCacheBase::TCacheEntryBase::CalculateHash() const
|
u64 TextureCacheBase::TCacheEntryBase::CalculateHash() const
|
||||||
{
|
{
|
||||||
u8* ptr = Memory::GetPointer(addr);
|
u8* ptr = Memory::GetPointer(addr);
|
||||||
|
|
|
@ -101,10 +101,8 @@ public:
|
||||||
|
|
||||||
virtual void Load(unsigned int width, unsigned int height,
|
virtual void Load(unsigned int width, unsigned int height,
|
||||||
unsigned int expanded_width, unsigned int level) = 0;
|
unsigned int expanded_width, unsigned int level) = 0;
|
||||||
virtual void FromRenderTarget(u8* dst, unsigned int dstFormat, u32 dstStride,
|
virtual void FromRenderTarget(u8* dst, PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect,
|
||||||
PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect,
|
bool scaleByHalf, unsigned int cbufid, const float *colmat) = 0;
|
||||||
bool isIntensity, bool scaleByHalf, unsigned int cbufid,
|
|
||||||
const float *colmat) = 0;
|
|
||||||
|
|
||||||
bool OverlapsMemoryRange(u32 range_address, u32 range_size) const;
|
bool OverlapsMemoryRange(u32 range_address, u32 range_size) const;
|
||||||
|
|
||||||
|
@ -113,8 +111,6 @@ public:
|
||||||
u32 NumBlocksY() const;
|
u32 NumBlocksY() const;
|
||||||
u32 BytesPerRow() const;
|
u32 BytesPerRow() const;
|
||||||
|
|
||||||
void Zero(u8* ptr);
|
|
||||||
|
|
||||||
u64 CalculateHash() const;
|
u64 CalculateHash() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -130,6 +126,10 @@ public:
|
||||||
|
|
||||||
virtual TCacheEntryBase* CreateTexture(const TCacheEntryConfig& config) = 0;
|
virtual TCacheEntryBase* CreateTexture(const TCacheEntryConfig& config) = 0;
|
||||||
|
|
||||||
|
virtual void CopyEFB(u8* dst, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
|
||||||
|
PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect,
|
||||||
|
bool isIntensity, bool scaleByHalf) = 0;
|
||||||
|
|
||||||
virtual void CompileShaders() = 0; // currently only implemented by OGL
|
virtual void CompileShaders() = 0; // currently only implemented by OGL
|
||||||
virtual void DeleteShaders() = 0; // currently only implemented by OGL
|
virtual void DeleteShaders() = 0; // currently only implemented by OGL
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue