AbstractTexture: Drop slow map readback path

This commit is contained in:
Stenzek 2017-11-19 17:46:00 +10:00
parent 193763ca3a
commit db1d9de933
10 changed files with 0 additions and 300 deletions

View file

@ -84,7 +84,6 @@ DXTexture::DXTexture(const TextureConfig& tex_config) : AbstractTexture(tex_conf
DXTexture::~DXTexture()
{
m_texture->Release();
SAFE_RELEASE(m_staging_texture);
}
D3DTexture2D* DXTexture::GetRawTexIdentifier() const
@ -97,74 +96,6 @@ void DXTexture::Bind(unsigned int stage)
D3D::stateman->SetTexture(stage, m_texture->GetSRV());
}
std::optional<AbstractTexture::RawTextureInfo> DXTexture::MapFullImpl()
{
CD3D11_TEXTURE2D_DESC staging_texture_desc(DXGI_FORMAT_R8G8B8A8_UNORM, m_config.width,
m_config.height, 1, 1, 0, D3D11_USAGE_STAGING,
D3D11_CPU_ACCESS_READ);
HRESULT hr = D3D::device->CreateTexture2D(&staging_texture_desc, nullptr, &m_staging_texture);
if (FAILED(hr))
{
WARN_LOG(VIDEO, "Failed to create texture dumping readback texture: %X", static_cast<u32>(hr));
return {};
}
// Copy the selected data to the staging texture
D3D::context->CopyResource(m_staging_texture, m_texture->GetTex());
// Map the staging texture to client memory, and encode it as a .png image.
D3D11_MAPPED_SUBRESOURCE map;
hr = D3D::context->Map(m_staging_texture, 0, D3D11_MAP_READ, 0, &map);
if (FAILED(hr))
{
WARN_LOG(VIDEO, "Failed to map texture dumping readback texture: %X", static_cast<u32>(hr));
return {};
}
return AbstractTexture::RawTextureInfo{reinterpret_cast<u8*>(map.pData), map.RowPitch,
m_config.width, m_config.height};
}
std::optional<AbstractTexture::RawTextureInfo> DXTexture::MapRegionImpl(u32 level, u32 x, u32 y,
u32 width, u32 height)
{
CD3D11_TEXTURE2D_DESC staging_texture_desc(DXGI_FORMAT_R8G8B8A8_UNORM, width, height, 1, 1, 0,
D3D11_USAGE_STAGING, D3D11_CPU_ACCESS_READ);
HRESULT hr = D3D::device->CreateTexture2D(&staging_texture_desc, nullptr, &m_staging_texture);
if (FAILED(hr))
{
WARN_LOG(VIDEO, "Failed to create texture dumping readback texture: %X", static_cast<u32>(hr));
return {};
}
// Copy the selected data to the staging texture
CD3D11_BOX src_box(x, y, 0, width, height, 1);
D3D::context->CopySubresourceRegion(m_staging_texture, 0, 0, 0, 0, m_texture->GetTex(),
D3D11CalcSubresource(level, 0, m_config.levels), &src_box);
// Map the staging texture to client memory, and encode it as a .png image.
D3D11_MAPPED_SUBRESOURCE map;
hr = D3D::context->Map(m_staging_texture, 0, D3D11_MAP_READ, 0, &map);
if (FAILED(hr))
{
WARN_LOG(VIDEO, "Failed to map texture dumping readback texture: %X", static_cast<u32>(hr));
return {};
}
return AbstractTexture::RawTextureInfo{reinterpret_cast<u8*>(map.pData), map.RowPitch,
m_config.width, m_config.height};
}
void DXTexture::Unmap()
{
if (!m_staging_texture)
return;
D3D::context->Unmap(m_staging_texture, 0);
}
void DXTexture::CopyRectangleFromTexture(const AbstractTexture* src,
const MathUtil::Rectangle<int>& src_rect, u32 src_layer,
u32 src_level, const MathUtil::Rectangle<int>& dst_rect,

View file

@ -20,7 +20,6 @@ public:
~DXTexture();
void Bind(unsigned int stage) override;
void Unmap() override;
void CopyRectangleFromTexture(const AbstractTexture* src,
const MathUtil::Rectangle<int>& src_rect, u32 src_layer,
@ -35,12 +34,7 @@ public:
D3DTexture2D* GetRawTexIdentifier() const;
private:
std::optional<RawTextureInfo> MapFullImpl() override;
std::optional<RawTextureInfo> MapRegionImpl(u32 level, u32 x, u32 y, u32 width,
u32 height) override;
D3DTexture2D* m_texture;
ID3D11Texture2D* m_staging_texture = nullptr;
};
class DXStagingTexture final : public AbstractStagingTexture

View file

@ -167,75 +167,6 @@ void OGLTexture::Bind(unsigned int stage)
}
}
std::optional<AbstractTexture::RawTextureInfo> OGLTexture::MapFullImpl()
{
if (GLInterface->GetMode() != GLInterfaceMode::MODE_OPENGL)
return {};
m_staging_data.reserve(m_config.width * m_config.height * 4);
glActiveTexture(GL_TEXTURE9);
glBindTexture(GL_TEXTURE_2D_ARRAY, m_texId);
glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_staging_data.data());
OGLTexture::SetStage();
return AbstractTexture::RawTextureInfo{reinterpret_cast<u8*>(m_staging_data.data()),
m_config.width * 4, m_config.width, m_config.height};
}
std::optional<AbstractTexture::RawTextureInfo> OGLTexture::MapRegionImpl(u32 level, u32 x, u32 y,
u32 width, u32 height)
{
if (GLInterface->GetMode() != GLInterfaceMode::MODE_OPENGL)
return {};
m_staging_data.reserve(m_config.width * m_config.height * 4);
glActiveTexture(GL_TEXTURE9);
glBindTexture(GL_TEXTURE_2D_ARRAY, m_texId);
if (g_ogl_config.bSupportTextureSubImage)
{
glGetTextureSubImage(GL_TEXTURE_2D_ARRAY, level, GLint(x), GLint(y), 0, GLsizei(width),
GLsizei(height), 0, GL_RGBA, GL_UNSIGNED_BYTE, GLsizei(width * height * 4),
m_staging_data.data());
}
else
{
MapRegionSlow(level, x, y, width, height);
}
OGLTexture::SetStage();
return AbstractTexture::RawTextureInfo{m_staging_data.data(), width * 4, width, height};
}
void OGLTexture::MapRegionSlow(u32 level, u32 x, u32 y, u32 width, u32 height)
{
glActiveTexture(GL_TEXTURE9);
glBindTexture(GL_TEXTURE_2D_ARRAY, m_texId);
glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_staging_data.data());
// Now copy the region out of the staging data
const u32 partial_stride = width * 4;
std::vector<u8> partial_data;
partial_data.resize(partial_stride * height);
const u32 staging_stride = m_config.width * 4;
const u32 x_offset = x * 4;
auto staging_location = m_staging_data.begin() + staging_stride * y;
auto partial_location = partial_data.begin();
for (size_t i = 0; i < height; ++i)
{
auto starting_location = staging_location + x_offset;
std::copy(starting_location, starting_location + partial_stride, partial_location);
staging_location += staging_stride;
partial_location += partial_stride;
}
// Now swap the region back in for the staging data
m_staging_data.swap(partial_data);
}
void OGLTexture::CopyRectangleFromTexture(const AbstractTexture* src,
const MathUtil::Rectangle<int>& src_rect, u32 src_layer,
u32 src_level, const MathUtil::Rectangle<int>& dst_rect,

View file

@ -38,14 +38,8 @@ public:
static void SetStage();
private:
std::optional<RawTextureInfo> MapFullImpl() override;
std::optional<RawTextureInfo> MapRegionImpl(u32 level, u32 x, u32 y, u32 width,
u32 height) override;
void MapRegionSlow(u32 level, u32 x, u32 y, u32 width, u32 height);
GLuint m_texId;
GLuint m_framebuffer = 0;
std::vector<u8> m_staging_data;
};
class OGLStagingTexture final : public AbstractStagingTexture

View file

@ -107,12 +107,6 @@ u8* SWTexture::GetData()
return m_data.data();
}
std::optional<AbstractTexture::RawTextureInfo> SWTexture::MapFullImpl()
{
return AbstractTexture::RawTextureInfo{GetData(), m_config.width * 4, m_config.width,
m_config.height};
}
SWStagingTexture::SWStagingTexture(StagingTextureType type, const TextureConfig& config)
: AbstractStagingTexture(type, config)
{

View file

@ -35,8 +35,6 @@ public:
u8* GetData();
private:
std::optional<RawTextureInfo> MapFullImpl() override;
std::vector<u8> m_data;
};

View file

@ -113,56 +113,6 @@ void VKTexture::Bind(unsigned int stage)
StateTracker::GetInstance()->SetTexture(stage, m_texture->GetView());
}
std::optional<AbstractTexture::RawTextureInfo> VKTexture::MapFullImpl()
{
// No support for optimization of full copy
return MapRegionImpl(0, 0, 0, m_config.width, m_config.height);
}
std::optional<AbstractTexture::RawTextureInfo> VKTexture::MapRegionImpl(u32 level, u32 x, u32 y,
u32 width, u32 height)
{
m_staging_texture = StagingTexture2D::Create(STAGING_BUFFER_TYPE_READBACK, width, height,
TEXTURECACHE_TEXTURE_FORMAT);
// Transition image to transfer source, and invalidate the current state,
// since we'll be executing the command buffer.
m_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
StateTracker::GetInstance()->EndRenderPass();
// Copy to download buffer.
m_staging_texture->CopyFromImage(g_command_buffer_mgr->GetCurrentCommandBuffer(),
m_texture->GetImage(), VK_IMAGE_ASPECT_COLOR_BIT, x, y, width,
height, level, 0);
// Restore original state of texture.
m_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
// Block until the GPU has finished copying to the staging texture.
Util::ExecuteCurrentCommandsAndRestoreState(false, true);
// Map the staging texture so we can copy the contents out.
if (!m_staging_texture->Map())
{
PanicAlert("Failed to map staging texture");
return {};
}
return AbstractTexture::RawTextureInfo{reinterpret_cast<u8*>(m_staging_texture->GetMapPointer()),
static_cast<u32>(m_staging_texture->GetRowStride()), width,
height};
}
void VKTexture::Unmap()
{
if (!m_staging_texture)
return;
m_staging_texture->Unmap();
}
void VKTexture::CopyRectangleFromTexture(const AbstractTexture* src,
const MathUtil::Rectangle<int>& src_rect, u32 src_layer,
u32 src_level, const MathUtil::Rectangle<int>& dst_rect,

View file

@ -22,7 +22,6 @@ public:
~VKTexture();
void Bind(unsigned int stage) override;
void Unmap() override;
void CopyRectangleFromTexture(const AbstractTexture* src,
const MathUtil::Rectangle<int>& src_rect, u32 src_layer,
@ -45,12 +44,7 @@ private:
VKTexture(const TextureConfig& tex_config, std::unique_ptr<Texture2D> texture,
VkFramebuffer framebuffer);
std::optional<RawTextureInfo> MapFullImpl() override;
std::optional<RawTextureInfo> MapRegionImpl(u32 level, u32 x, u32 y, u32 width,
u32 height) override;
std::unique_ptr<Texture2D> m_texture;
std::unique_ptr<StagingTexture2D> m_staging_texture;
VkFramebuffer m_framebuffer;
};

View file

@ -51,73 +51,6 @@ bool AbstractTexture::Save(const std::string& filename, unsigned int level)
level_height);
}
std::optional<AbstractTexture::RawTextureInfo> AbstractTexture::Map()
{
if (m_currently_mapped)
{
Unmap();
m_currently_mapped = false;
}
auto result = MapFullImpl();
if (!result.has_value())
{
m_currently_mapped = false;
return {};
}
m_currently_mapped = true;
return result;
}
std::optional<AbstractTexture::RawTextureInfo> AbstractTexture::Map(u32 level, u32 x, u32 y,
u32 width, u32 height)
{
_assert_(level < m_config.levels);
u32 max_level_width = std::max(m_config.width >> level, 1u);
u32 max_level_height = std::max(m_config.height >> level, 1u);
_assert_(width < max_level_width);
_assert_(height < max_level_height);
auto result = MapRegionImpl(level, x, y, width, height);
if (!result.has_value())
{
m_currently_mapped = false;
return {};
}
m_currently_mapped = true;
return result;
}
std::optional<AbstractTexture::RawTextureInfo> AbstractTexture::Map(u32 level)
{
_assert_(level < m_config.levels);
u32 level_width = std::max(m_config.width >> level, 1u);
u32 level_height = std::max(m_config.height >> level, 1u);
return Map(level, 0, 0, level_width, level_height);
}
void AbstractTexture::Unmap()
{
}
std::optional<AbstractTexture::RawTextureInfo> AbstractTexture::MapFullImpl()
{
return {};
}
std::optional<AbstractTexture::RawTextureInfo>
AbstractTexture::MapRegionImpl(u32 level, u32 x, u32 y, u32 width, u32 height)
{
return {};
}
bool AbstractTexture::IsCompressedFormat(AbstractTextureFormat format)
{
switch (format)

View file

@ -5,7 +5,6 @@
#pragma once
#include <cstddef>
#include <optional>
#include <string>
#include "Common/CommonTypes.h"
@ -20,19 +19,6 @@ public:
virtual void Bind(unsigned int stage) = 0;
struct RawTextureInfo
{
const u8* data;
u32 stride;
u32 width;
u32 height;
};
std::optional<RawTextureInfo> Map();
std::optional<RawTextureInfo> Map(u32 level, u32 x, u32 y, u32 width, u32 height);
std::optional<RawTextureInfo> Map(u32 level);
virtual void Unmap();
virtual void CopyRectangleFromTexture(const AbstractTexture* src,
const MathUtil::Rectangle<int>& src_rect, u32 src_layer,
u32 src_level, const MathUtil::Rectangle<int>& dst_rect,
@ -52,10 +38,5 @@ public:
const TextureConfig& GetConfig() const;
protected:
virtual std::optional<RawTextureInfo> MapFullImpl();
virtual std::optional<RawTextureInfo> MapRegionImpl(u32 level, u32 x, u32 y, u32 width,
u32 height);
bool m_currently_mapped = false;
const TextureConfig m_config;
};