TextureCache: Implement deferred/batched EFB copies

This commit is contained in:
Stenzek
2018-11-03 00:17:00 +10:00
parent 710b893b91
commit 8e2c063d62
29 changed files with 314 additions and 141 deletions

View File

@ -46,13 +46,8 @@ PSTextureEncoder::~PSTextureEncoder() = default;
void PSTextureEncoder::Init()
{
// TODO: Move this to a constant somewhere in common.
TextureConfig encoding_texture_config(EFB_WIDTH * 4, 1024, 1, 1, 1, AbstractTextureFormat::BGRA8,
true);
m_encoding_render_texture = g_renderer->CreateTexture(encoding_texture_config);
m_encoding_readback_texture =
g_renderer->CreateStagingTexture(StagingTextureType::Readback, encoding_texture_config);
ASSERT(m_encoding_render_texture && m_encoding_readback_texture);
m_encoding_render_texture = g_renderer->CreateTexture(TextureCache::GetEncodingTextureConfig());
ASSERT(m_encoding_render_texture);
// Create constant buffer for uploading data to shaders
D3D11_BUFFER_DESC bd = CD3D11_BUFFER_DESC(sizeof(EFBEncodeParams), D3D11_BIND_CONSTANT_BUFFER);
@ -71,9 +66,9 @@ void PSTextureEncoder::Shutdown()
}
void PSTextureEncoder::Encode(
u8* dst, const EFBCopyParams& params, u32 native_width, u32 bytes_per_row, u32 num_blocks_y,
u32 memory_stride, const EFBRectangle& src_rect, bool scale_by_half, float y_scale, float gamma,
bool clamp_top, bool clamp_bottom,
AbstractStagingTexture* dst, const EFBCopyParams& params, u32 native_width, u32 bytes_per_row,
u32 num_blocks_y, u32 memory_stride, const EFBRectangle& src_rect, bool scale_by_half,
float y_scale, float gamma, bool clamp_top, bool clamp_bottom,
const TextureCacheBase::CopyFilterCoefficientArray& filter_coefficients)
{
// Resolve MSAA targets before copying.
@ -133,14 +128,7 @@ void PSTextureEncoder::Encode(
// Copy to staging buffer
MathUtil::Rectangle<int> copy_rect(0, 0, words_per_row, num_blocks_y);
m_encoding_readback_texture->CopyFromTexture(m_encoding_render_texture.get(), copy_rect, 0, 0,
copy_rect);
m_encoding_readback_texture->Flush();
if (m_encoding_readback_texture->Map())
{
m_encoding_readback_texture->ReadTexels(copy_rect, dst, memory_stride);
m_encoding_readback_texture->Unmap();
}
dst->CopyFromTexture(m_encoding_render_texture.get(), copy_rect, 0, 0, copy_rect);
}
g_renderer->RestoreAPIState();

View File

@ -38,9 +38,9 @@ public:
void Init();
void Shutdown();
void Encode(u8* dst, const EFBCopyParams& params, u32 native_width, u32 bytes_per_row,
u32 num_blocks_y, u32 memory_stride, const EFBRectangle& src_rect, bool scale_by_half,
float y_scale, float gamma, bool clamp_top, bool clamp_bottom,
void Encode(AbstractStagingTexture* dst, const EFBCopyParams& params, u32 native_width,
u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride, const EFBRectangle& src_rect,
bool scale_by_half, float y_scale, float gamma, bool clamp_top, bool clamp_bottom,
const TextureCacheBase::CopyFilterCoefficientArray& filter_coefficients);
private:
@ -48,7 +48,6 @@ private:
ID3D11Buffer* m_encode_params = nullptr;
std::unique_ptr<AbstractTexture> m_encoding_render_texture;
std::unique_ptr<AbstractStagingTexture> m_encoding_readback_texture;
std::map<EFBCopyParams, ID3D11PixelShader*> m_encoding_shaders;
};
}

View File

@ -31,8 +31,8 @@ namespace DX11
{
static std::unique_ptr<PSTextureEncoder> g_encoder;
void TextureCache::CopyEFB(u8* dst, const EFBCopyParams& params, u32 native_width,
u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
void TextureCache::CopyEFB(AbstractStagingTexture* dst, const EFBCopyParams& params,
u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
const EFBRectangle& src_rect, bool scale_by_half, float y_scale,
float gamma, bool clamp_top, bool clamp_bottom,
const CopyFilterCoefficientArray& filter_coefficients)

View File

@ -22,18 +22,11 @@ public:
~TextureCache();
private:
u64 EncodeToRamFromTexture(u32 address, void* source_texture, u32 SourceW, u32 SourceH,
bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf,
const EFBRectangle& source)
{
return 0;
};
void ConvertTexture(TCacheEntry* destination, TCacheEntry* source, const void* palette,
TLUTFormat format) override;
void CopyEFB(u8* dst, const EFBCopyParams& params, u32 native_width, u32 bytes_per_row,
u32 num_blocks_y, u32 memory_stride, const EFBRectangle& src_rect,
void CopyEFB(AbstractStagingTexture* dst, const EFBCopyParams& params, u32 native_width,
u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride, const EFBRectangle& src_rect,
bool scale_by_half, float y_scale, float gamma, bool clamp_top, bool clamp_bottom,
const CopyFilterCoefficientArray& filter_coefficients) override;

View File

@ -25,8 +25,8 @@ public:
{
}
void CopyEFB(u8* dst, const EFBCopyParams& params, u32 native_width, u32 bytes_per_row,
u32 num_blocks_y, u32 memory_stride, const EFBRectangle& src_rect,
void CopyEFB(AbstractStagingTexture* dst, const EFBCopyParams& params, u32 native_width,
u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride, const EFBRectangle& src_rect,
bool scale_by_half, float y_scale, float gamma, bool clamp_top, bool clamp_bottom,
const CopyFilterCoefficientArray& filter_coefficients) override
{

View File

@ -159,8 +159,8 @@ void main()
//#define TIME_TEXTURE_DECODING 1
void TextureCache::CopyEFB(u8* dst, const EFBCopyParams& params, u32 native_width,
u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
void TextureCache::CopyEFB(AbstractStagingTexture* dst, const EFBCopyParams& params,
u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
const EFBRectangle& src_rect, bool scale_by_half, float y_scale,
float gamma, bool clamp_top, bool clamp_bottom,
const CopyFilterCoefficientArray& filter_coefficients)

View File

@ -63,8 +63,8 @@ private:
void ConvertTexture(TCacheEntry* destination, TCacheEntry* source, const void* palette,
TLUTFormat format) override;
void CopyEFB(u8* dst, const EFBCopyParams& params, u32 native_width, u32 bytes_per_row,
u32 num_blocks_y, u32 memory_stride, const EFBRectangle& src_rect,
void CopyEFB(AbstractStagingTexture* dst, const EFBCopyParams& params, u32 native_width,
u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride, const EFBRectangle& src_rect,
bool scale_by_half, float y_scale, float gamma, bool clamp_top, bool clamp_bottom,
const CopyFilterCoefficientArray& filter_coefficients) override;

View File

@ -46,7 +46,6 @@ struct EncodingProgram
std::map<EFBCopyParams, EncodingProgram> s_encoding_programs;
std::unique_ptr<AbstractTexture> s_encoding_render_texture;
std::unique_ptr<AbstractStagingTexture> s_encoding_readback_texture;
const int renderBufferWidth = EFB_WIDTH * 4;
const int renderBufferHeight = 1024;
@ -93,16 +92,11 @@ static EncodingProgram& GetOrCreateEncodingShader(const EFBCopyParams& params)
void Init()
{
TextureConfig config(renderBufferWidth, renderBufferHeight, 1, 1, 1, AbstractTextureFormat::BGRA8,
true);
s_encoding_render_texture = g_renderer->CreateTexture(config);
s_encoding_readback_texture =
g_renderer->CreateStagingTexture(StagingTextureType::Readback, config);
s_encoding_render_texture = g_renderer->CreateTexture(TextureCache::GetEncodingTextureConfig());
}
void Shutdown()
{
s_encoding_readback_texture.reset();
s_encoding_render_texture.reset();
for (auto& program : s_encoding_programs)
@ -112,8 +106,9 @@ void Shutdown()
// dst_line_size, writeStride in bytes
static void EncodeToRamUsingShader(GLuint srcTexture, u8* destAddr, u32 dst_line_size,
u32 dstHeight, u32 writeStride, bool linearFilter, float y_scale)
static void EncodeToRamUsingShader(GLuint srcTexture, AbstractStagingTexture* destAddr,
u32 dst_line_size, u32 dstHeight, u32 writeStride,
bool linearFilter, float y_scale)
{
FramebufferManager::SetFramebuffer(
static_cast<OGLTexture*>(s_encoding_render_texture.get())->GetFramebuffer());
@ -137,15 +132,14 @@ static void EncodeToRamUsingShader(GLuint srcTexture, u8* destAddr, u32 dst_line
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
MathUtil::Rectangle<int> copy_rect(0, 0, dst_line_size / 4, dstHeight);
s_encoding_readback_texture->CopyFromTexture(s_encoding_render_texture.get(), copy_rect, 0, 0,
copy_rect);
s_encoding_readback_texture->ReadTexels(copy_rect, destAddr, writeStride);
destAddr->CopyFromTexture(s_encoding_render_texture.get(), copy_rect, 0, 0, copy_rect);
}
void EncodeToRamFromTexture(u8* dest_ptr, const EFBCopyParams& params, u32 native_width,
u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
const EFBRectangle& src_rect, bool scale_by_half, float y_scale,
float gamma, float clamp_top, float clamp_bottom,
void EncodeToRamFromTexture(AbstractStagingTexture* dest, const EFBCopyParams& params,
u32 native_width, u32 bytes_per_row, u32 num_blocks_y,
u32 memory_stride, const EFBRectangle& src_rect, bool scale_by_half,
float y_scale, float gamma, float clamp_top, float clamp_bottom,
const TextureCacheBase::CopyFilterCoefficientArray& filter_coefficients)
{
g_renderer->ResetAPIState();
@ -165,7 +159,7 @@ void EncodeToRamFromTexture(u8* dest_ptr, const EFBCopyParams& params, u32 nativ
FramebufferManager::ResolveAndGetDepthTarget(src_rect) :
FramebufferManager::ResolveAndGetRenderTarget(src_rect);
EncodeToRamUsingShader(read_texture, dest_ptr, bytes_per_row, num_blocks_y, memory_stride,
EncodeToRamUsingShader(read_texture, dest, bytes_per_row, num_blocks_y, memory_stride,
scale_by_half && !params.depth, y_scale);
g_renderer->RestoreAPIState();

View File

@ -10,6 +10,9 @@
#include "VideoCommon/TextureCacheBase.h"
#include "VideoCommon/VideoCommon.h"
struct EFBCopyParams;
class AbstractStagingTexture;
namespace OGL
{
// Converts textures between formats using shaders
@ -21,7 +24,7 @@ void Shutdown();
// returns size of the encoded data (in bytes)
void EncodeToRamFromTexture(
u8* dest_ptr, const EFBCopyParams& params, u32 native_width, u32 bytes_per_row,
AbstractStagingTexture* dest, const EFBCopyParams& params, u32 native_width, u32 bytes_per_row,
u32 num_blocks_y, u32 memory_stride, const EFBRectangle& src_rect, bool scale_by_half,
float y_scale, float gamma, float clamp_top, float clamp_bottom,
const TextureCacheBase::CopyFilterCoefficientArray& filter_coefficients);

View File

@ -57,6 +57,8 @@ public:
void Unmap() override;
void Flush() override;
void SetMapStride(size_t stride) { m_map_stride = stride; }
private:
std::vector<u8> m_data;
};

View File

@ -16,8 +16,8 @@ public:
TLUTFormat format) override
{
}
void CopyEFB(u8* dst, const EFBCopyParams& params, u32 native_width, u32 bytes_per_row,
u32 num_blocks_y, u32 memory_stride, const EFBRectangle& src_rect,
void CopyEFB(AbstractStagingTexture* dst, const EFBCopyParams& params, u32 native_width,
u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride, const EFBRectangle& src_rect,
bool scale_by_half, float y_scale, float gamma, bool clamp_top, bool clamp_bottom,
const CopyFilterCoefficientArray& filter_coefficients) override
{

View File

@ -5,12 +5,14 @@
#include "VideoBackends/Software/TextureEncoder.h"
#include "Common/Align.h"
#include "Common/Assert.h"
#include "Common/CommonFuncs.h"
#include "Common/CommonTypes.h"
#include "Common/MsgHandler.h"
#include "Common/Swap.h"
#include "VideoBackends/Software/EfbInterface.h"
#include "VideoBackends/Software/SWTexture.h"
#include "VideoCommon/BPMemory.h"
#include "VideoCommon/LookUpTables.h"
@ -1468,18 +1470,26 @@ void EncodeEfbCopy(u8* dst, const EFBCopyParams& params, u32 native_width, u32 b
}
}
void Encode(u8* dst, const EFBCopyParams& params, u32 native_width, u32 bytes_per_row,
u32 num_blocks_y, u32 memory_stride, const EFBRectangle& src_rect, bool scale_by_half,
float y_scale, float gamma)
void Encode(AbstractStagingTexture* dst, const EFBCopyParams& params, u32 native_width,
u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride, const EFBRectangle& src_rect,
bool scale_by_half, float y_scale, float gamma)
{
// HACK: Override the memory stride for this staging texture with new copy stride.
// This is required because the texture encoder assumes that we're writing directly to memory,
// and each row is tightly packed with no padding, whereas our encoding abstract texture has
// a width of 2560. When we copy the texture back later on, it'll use the tightly packed stride.
ASSERT(memory_stride <= (dst->GetConfig().width * dst->GetTexelSize()));
static_cast<SW::SWStagingTexture*>(dst)->SetMapStride(memory_stride);
if (params.copy_format == EFBCopyFormat::XFB)
{
EfbInterface::EncodeXFB(dst, native_width, src_rect, y_scale, gamma);
EfbInterface::EncodeXFB(reinterpret_cast<u8*>(dst->GetMappedPointer()), native_width, src_rect,
y_scale, gamma);
}
else
{
EncodeEfbCopy(dst, params, native_width, bytes_per_row, num_blocks_y, memory_stride, src_rect,
scale_by_half);
EncodeEfbCopy(reinterpret_cast<u8*>(dst->GetMappedPointer()), params, native_width,
bytes_per_row, num_blocks_y, memory_stride, src_rect, scale_by_half);
}
}
}

View File

@ -10,7 +10,7 @@
namespace TextureEncoder
{
void Encode(u8* dst, const EFBCopyParams& params, u32 native_width, u32 bytes_per_row,
u32 num_blocks_y, u32 memory_stride, const EFBRectangle& src_rect, bool scale_by_half,
float y_scale, float gamma);
void Encode(AbstractStagingTexture* dst, const EFBCopyParams& params, u32 native_width,
u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride, const EFBRectangle& src_rect,
bool scale_by_half, float y_scale, float gamma);
}

View File

@ -98,8 +98,8 @@ void TextureCache::ConvertTexture(TCacheEntry* destination, TCacheEntry* source,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
}
void TextureCache::CopyEFB(u8* dst, const EFBCopyParams& params, u32 native_width,
u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
void TextureCache::CopyEFB(AbstractStagingTexture* dst, const EFBCopyParams& params,
u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
const EFBRectangle& src_rect, bool scale_by_half, float y_scale,
float gamma, bool clamp_top, bool clamp_bottom,
const CopyFilterCoefficientArray& filter_coefficients)

View File

@ -36,8 +36,8 @@ public:
void ConvertTexture(TCacheEntry* destination, TCacheEntry* source, const void* palette,
TLUTFormat format) override;
void CopyEFB(u8* dst, const EFBCopyParams& params, u32 native_width, u32 bytes_per_row,
u32 num_blocks_y, u32 memory_stride, const EFBRectangle& src_rect,
void CopyEFB(AbstractStagingTexture* dst, const EFBCopyParams& params, u32 native_width,
u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride, const EFBRectangle& src_rect,
bool scale_by_half, float y_scale, float gamma, bool clamp_top, bool clamp_bottom,
const CopyFilterCoefficientArray& filter_coefficients) override;

View File

@ -207,10 +207,10 @@ void TextureConverter::ConvertTexture(TextureCacheBase::TCacheEntry* dst_entry,
}
void TextureConverter::EncodeTextureToMemory(
VkImageView src_texture, u8* dest_ptr, const EFBCopyParams& params, u32 native_width,
u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride, const EFBRectangle& src_rect,
bool scale_by_half, float y_scale, float gamma, bool clamp_top, bool clamp_bottom,
const TextureCacheBase::CopyFilterCoefficientArray& filter_coefficients)
VkImageView src_texture, AbstractStagingTexture* dest, const EFBCopyParams& params,
u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
const EFBRectangle& src_rect, bool scale_by_half, float y_scale, float gamma, bool clamp_top,
bool clamp_bottom, const TextureCacheBase::CopyFilterCoefficientArray& filter_coefficients)
{
VkShaderModule shader = GetEncodingShader(params);
if (shader == VK_NULL_HANDLE)
@ -273,9 +273,7 @@ void TextureConverter::EncodeTextureToMemory(
draw.EndRenderPass();
MathUtil::Rectangle<int> copy_rect(0, 0, render_width, render_height);
m_encoding_readback_texture->CopyFromTexture(m_encoding_render_texture.get(), copy_rect, 0, 0,
copy_rect);
m_encoding_readback_texture->ReadTexels(copy_rect, dest_ptr, memory_stride);
dest->CopyFromTexture(m_encoding_render_texture.get(), copy_rect, 0, 0, copy_rect);
}
bool TextureConverter::SupportsTextureDecoding(TextureFormat format, TLUTFormat palette_format)
@ -610,14 +608,8 @@ VkShaderModule TextureConverter::GetEncodingShader(const EFBCopyParams& params)
bool TextureConverter::CreateEncodingTexture()
{
TextureConfig config(ENCODING_TEXTURE_WIDTH, ENCODING_TEXTURE_HEIGHT, 1, 1, 1,
ENCODING_TEXTURE_FORMAT, true);
m_encoding_render_texture = g_renderer->CreateTexture(config);
m_encoding_readback_texture =
g_renderer->CreateStagingTexture(StagingTextureType::Readback, config);
return m_encoding_render_texture && m_encoding_readback_texture;
m_encoding_render_texture = g_renderer->CreateTexture(TextureCache::GetEncodingTextureConfig());
return m_encoding_render_texture != nullptr;
}
bool TextureConverter::CreateDecodingTexture()

View File

@ -21,7 +21,6 @@ class AbstractStagingTexture;
namespace Vulkan
{
class StagingTexture2D;
class Texture2D;
class VKTexture;
@ -38,14 +37,12 @@ public:
TextureCache::TCacheEntry* src_entry, const void* palette,
TLUTFormat palette_format);
// Uses an encoding shader to copy src_texture to dest_ptr.
// NOTE: Executes the current command buffer.
void
EncodeTextureToMemory(VkImageView src_texture, u8* dest_ptr, const EFBCopyParams& params,
u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
const EFBRectangle& src_rect, bool scale_by_half, float y_scale,
float gamma, bool clamp_top, bool clamp_bottom,
const TextureCacheBase::CopyFilterCoefficientArray& filter_coefficients);
// Uses an encoding shader to copy src_texture to dest.
void EncodeTextureToMemory(
VkImageView src_texture, AbstractStagingTexture* dest, const EFBCopyParams& params,
u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
const EFBRectangle& src_rect, bool scale_by_half, float y_scale, float gamma, bool clamp_top,
bool clamp_bottom, const TextureCacheBase::CopyFilterCoefficientArray& filter_coefficients);
bool SupportsTextureDecoding(TextureFormat format, TLUTFormat palette_format);
void DecodeTexture(VkCommandBuffer command_buffer, TextureCache::TCacheEntry* entry,
@ -54,9 +51,6 @@ public:
const u8* palette, TLUTFormat palette_format);
private:
static const u32 ENCODING_TEXTURE_WIDTH = EFB_WIDTH * 4;
static const u32 ENCODING_TEXTURE_HEIGHT = 1024;
static const AbstractTextureFormat ENCODING_TEXTURE_FORMAT = AbstractTextureFormat::BGRA8;
static const size_t NUM_PALETTE_CONVERSION_SHADERS = 3;
// Maximum size of a texture based on BP registers.
@ -100,7 +94,6 @@ private:
// Texture encoding - RGBA8->GX format in memory
std::map<EFBCopyParams, VkShaderModule> m_encoding_shaders;
std::unique_ptr<AbstractTexture> m_encoding_render_texture;
std::unique_ptr<AbstractStagingTexture> m_encoding_readback_texture;
// Texture decoding - GX format in memory->RGBA8
struct TextureDecodingPipeline

View File

@ -466,6 +466,7 @@ void VKStagingTexture::CopyFromTexture(Texture2D* src, const MathUtil::Rectangle
m_needs_flush = false;
g_command_buffer_mgr->RemoveFencePointCallback(
this);
m_staging_buffer->InvalidateCPUCache();
});
}