AbstractTexture: Support multisampled abstract texture
This commit is contained in:
parent
4316f5f56b
commit
6374a4c4a8
|
@ -52,33 +52,28 @@ DXGI_FORMAT GetDXGIFormatForHostFormat(AbstractTextureFormat format)
|
|||
|
||||
DXTexture::DXTexture(const TextureConfig& tex_config) : AbstractTexture(tex_config)
|
||||
{
|
||||
DXGI_FORMAT dxgi_format = GetDXGIFormatForHostFormat(m_config.format);
|
||||
if (m_config.rendertarget)
|
||||
{
|
||||
m_texture = D3DTexture2D::Create(
|
||||
m_config.width, m_config.height,
|
||||
(D3D11_BIND_FLAG)((int)D3D11_BIND_RENDER_TARGET | (int)D3D11_BIND_SHADER_RESOURCE),
|
||||
D3D11_USAGE_DEFAULT, dxgi_format, 1, m_config.layers);
|
||||
}
|
||||
else
|
||||
{
|
||||
const D3D11_TEXTURE2D_DESC texdesc =
|
||||
CD3D11_TEXTURE2D_DESC(dxgi_format, m_config.width, m_config.height, 1, m_config.levels,
|
||||
D3D11_BIND_SHADER_RESOURCE, D3D11_USAGE_DEFAULT, 0);
|
||||
DXGI_FORMAT tex_format = GetDXGIFormatForHostFormat(m_config.format);
|
||||
UINT bind_flags = D3D11_BIND_SHADER_RESOURCE;
|
||||
if (tex_config.rendertarget)
|
||||
bind_flags |= D3D11_BIND_RENDER_TARGET;
|
||||
|
||||
ID3D11Texture2D* pTexture;
|
||||
const HRESULT hr = D3D::device->CreateTexture2D(&texdesc, nullptr, &pTexture);
|
||||
CHECK(SUCCEEDED(hr), "Create texture of the TextureCache");
|
||||
CD3D11_TEXTURE2D_DESC texdesc(tex_format, tex_config.width, tex_config.height, tex_config.layers,
|
||||
tex_config.levels, bind_flags, D3D11_USAGE_DEFAULT, 0,
|
||||
tex_config.samples, 0, 0);
|
||||
|
||||
m_texture = new D3DTexture2D(pTexture, D3D11_BIND_SHADER_RESOURCE);
|
||||
ID3D11Texture2D* pTexture;
|
||||
HRESULT hr = D3D::device->CreateTexture2D(&texdesc, nullptr, &pTexture);
|
||||
CHECK(SUCCEEDED(hr), "Create backing DXTexture");
|
||||
|
||||
// TODO: better debug names
|
||||
D3D::SetDebugObjectName(m_texture->GetTex(), "a texture of the TextureCache");
|
||||
D3D::SetDebugObjectName(m_texture->GetSRV(),
|
||||
"shader resource view of a texture of the TextureCache");
|
||||
m_texture = new D3DTexture2D(
|
||||
pTexture, static_cast<D3D11_BIND_FLAG>(bind_flags), tex_format, DXGI_FORMAT_UNKNOWN,
|
||||
tex_config.rendertarget ? tex_format : DXGI_FORMAT_UNKNOWN, tex_config.samples > 1);
|
||||
|
||||
SAFE_RELEASE(pTexture);
|
||||
}
|
||||
D3D::SetDebugObjectName(m_texture->GetTex(), "a texture of the TextureCache");
|
||||
D3D::SetDebugObjectName(m_texture->GetSRV(),
|
||||
"shader resource view of a texture of the TextureCache");
|
||||
|
||||
SAFE_RELEASE(pTexture);
|
||||
}
|
||||
|
||||
DXTexture::~DXTexture()
|
||||
|
@ -147,6 +142,22 @@ void DXTexture::ScaleRectangleFromTexture(const AbstractTexture* source,
|
|||
g_renderer->RestoreAPIState();
|
||||
}
|
||||
|
||||
void DXTexture::ResolveFromTexture(const AbstractTexture* src, const MathUtil::Rectangle<int>& rect,
|
||||
u32 layer, u32 level)
|
||||
{
|
||||
const DXTexture* srcentry = static_cast<const DXTexture*>(src);
|
||||
_dbg_assert_(VIDEO, m_config.samples > 1 && m_config.width == srcentry->m_config.width &&
|
||||
m_config.height == srcentry->m_config.height && m_config.samples == 1);
|
||||
_dbg_assert_(VIDEO,
|
||||
rect.left + rect.GetWidth() <= static_cast<int>(srcentry->m_config.width) &&
|
||||
rect.top + rect.GetHeight() <= static_cast<int>(srcentry->m_config.height));
|
||||
|
||||
D3D::context->ResolveSubresource(
|
||||
m_texture->GetTex(), D3D11CalcSubresource(level, layer, m_config.levels),
|
||||
srcentry->m_texture->GetTex(), D3D11CalcSubresource(level, layer, srcentry->m_config.levels),
|
||||
GetDXGIFormatForHostFormat(m_config.format));
|
||||
}
|
||||
|
||||
void DXTexture::Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer,
|
||||
size_t buffer_size)
|
||||
{
|
||||
|
|
|
@ -26,6 +26,8 @@ public:
|
|||
void ScaleRectangleFromTexture(const AbstractTexture* source,
|
||||
const MathUtil::Rectangle<int>& srcrect,
|
||||
const MathUtil::Rectangle<int>& dstrect) override;
|
||||
void ResolveFromTexture(const AbstractTexture* src, const MathUtil::Rectangle<int>& rect,
|
||||
u32 layer, u32 level) override;
|
||||
void Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer,
|
||||
size_t buffer_size) override;
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ 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, AbstractTextureFormat::BGRA8,
|
||||
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 =
|
||||
|
|
|
@ -21,6 +21,10 @@ void NullTexture::ScaleRectangleFromTexture(const AbstractTexture* source,
|
|||
const MathUtil::Rectangle<int>& dstrect)
|
||||
{
|
||||
}
|
||||
void NullTexture::ResolveFromTexture(const AbstractTexture* src,
|
||||
const MathUtil::Rectangle<int>& rect, u32 layer, u32 level)
|
||||
{
|
||||
}
|
||||
|
||||
void NullTexture::Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer,
|
||||
size_t buffer_size)
|
||||
|
|
|
@ -26,6 +26,8 @@ public:
|
|||
void ScaleRectangleFromTexture(const AbstractTexture* source,
|
||||
const MathUtil::Rectangle<int>& srcrect,
|
||||
const MathUtil::Rectangle<int>& dstrect) override;
|
||||
void ResolveFromTexture(const AbstractTexture* src, const MathUtil::Rectangle<int>& rect,
|
||||
u32 layer, u32 level) override;
|
||||
void Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer,
|
||||
size_t buffer_size) override;
|
||||
};
|
||||
|
|
|
@ -80,38 +80,50 @@ bool UsePersistentStagingBuffers()
|
|||
|
||||
OGLTexture::OGLTexture(const TextureConfig& tex_config) : AbstractTexture(tex_config)
|
||||
{
|
||||
_dbg_assert_msg_(VIDEO, !tex_config.IsMultisampled() || tex_config.levels == 1,
|
||||
"OpenGL does not support multisampled textures with mip levels");
|
||||
|
||||
GLenum target =
|
||||
tex_config.IsMultisampled() ? GL_TEXTURE_2D_MULTISAMPLE_ARRAY : GL_TEXTURE_2D_ARRAY;
|
||||
glGenTextures(1, &m_texId);
|
||||
|
||||
glActiveTexture(GL_TEXTURE9);
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, m_texId);
|
||||
glBindTexture(target, m_texId);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, m_config.levels - 1);
|
||||
glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, m_config.levels - 1);
|
||||
|
||||
if (g_ogl_config.bSupportsTextureStorage)
|
||||
GLenum gl_internal_format = GetGLInternalFormatForTextureFormat(m_config.format, true);
|
||||
if (tex_config.IsMultisampled())
|
||||
{
|
||||
GLenum gl_internal_format = GetGLInternalFormatForTextureFormat(m_config.format, true);
|
||||
glTexStorage3D(GL_TEXTURE_2D_ARRAY, m_config.levels, gl_internal_format, m_config.width,
|
||||
m_config.height, m_config.layers);
|
||||
if (g_ogl_config.bSupportsTextureStorage)
|
||||
glTexStorage3DMultisample(target, tex_config.samples, gl_internal_format, m_config.width,
|
||||
m_config.height, m_config.layers, GL_FALSE);
|
||||
else
|
||||
glTexImage3DMultisample(target, tex_config.samples, gl_internal_format, m_config.width,
|
||||
m_config.height, m_config.layers, GL_FALSE);
|
||||
}
|
||||
else if (g_ogl_config.bSupportsTextureStorage)
|
||||
{
|
||||
glTexStorage3D(target, m_config.levels, gl_internal_format, m_config.width, m_config.height,
|
||||
m_config.layers);
|
||||
}
|
||||
|
||||
if (m_config.rendertarget)
|
||||
{
|
||||
// We can't render to compressed formats.
|
||||
_assert_(!IsCompressedFormat(m_config.format));
|
||||
|
||||
if (!g_ogl_config.bSupportsTextureStorage)
|
||||
if (!g_ogl_config.bSupportsTextureStorage && !tex_config.IsMultisampled())
|
||||
{
|
||||
for (u32 level = 0; level < m_config.levels; level++)
|
||||
{
|
||||
glTexImage3D(GL_TEXTURE_2D_ARRAY, level, GL_RGBA, std::max(m_config.width >> level, 1u),
|
||||
glTexImage3D(target, level, GL_RGBA, std::max(m_config.width >> level, 1u),
|
||||
std::max(m_config.height >> level, 1u), m_config.layers, 0, GL_RGBA,
|
||||
GL_UNSIGNED_BYTE, nullptr);
|
||||
}
|
||||
}
|
||||
glGenFramebuffers(1, &m_framebuffer);
|
||||
FramebufferManager::SetFramebuffer(m_framebuffer);
|
||||
FramebufferManager::FramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
||||
GL_TEXTURE_2D_ARRAY, m_texId, 0);
|
||||
FramebufferManager::FramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, m_texId,
|
||||
0);
|
||||
|
||||
// We broke the framebuffer binding here, and need to restore it, as the CreateTexture
|
||||
// method is in the base renderer class and can be called by VideoCommon.
|
||||
|
@ -156,47 +168,60 @@ void OGLTexture::CopyRectangleFromTexture(const AbstractTexture* src,
|
|||
}
|
||||
else
|
||||
{
|
||||
// If it isn't a single leveled/layered texture, we need to update the framebuffer.
|
||||
bool update_src_framebuffer =
|
||||
srcentry->m_framebuffer == 0 || srcentry->m_config.layers != 0 || src_level != 0;
|
||||
bool update_dst_framebuffer = m_framebuffer == 0 || m_config.layers != 0 || dst_level != 0;
|
||||
if (!m_framebuffer)
|
||||
glGenFramebuffers(1, &m_framebuffer);
|
||||
if (!srcentry->m_framebuffer)
|
||||
glGenFramebuffers(1, &const_cast<OGLTexture*>(srcentry)->m_framebuffer);
|
||||
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, srcentry->m_framebuffer);
|
||||
if (update_src_framebuffer)
|
||||
{
|
||||
glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, srcentry->m_texId,
|
||||
src_level, src_layer);
|
||||
}
|
||||
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_framebuffer);
|
||||
if (update_dst_framebuffer)
|
||||
{
|
||||
glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_texId, dst_level,
|
||||
dst_layer);
|
||||
}
|
||||
|
||||
glBlitFramebuffer(src_rect.left, src_rect.top, src_rect.right, src_rect.bottom, dst_rect.left,
|
||||
dst_rect.top, dst_rect.right, dst_rect.bottom, GL_COLOR_BUFFER_BIT,
|
||||
GL_NEAREST);
|
||||
|
||||
if (update_src_framebuffer)
|
||||
{
|
||||
FramebufferManager::FramebufferTexture(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
||||
GL_TEXTURE_2D_ARRAY, srcentry->m_texId, 0);
|
||||
}
|
||||
if (update_dst_framebuffer)
|
||||
{
|
||||
FramebufferManager::FramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
||||
GL_TEXTURE_2D_ARRAY, m_texId, 0);
|
||||
}
|
||||
|
||||
FramebufferManager::SetFramebuffer(0);
|
||||
BlitFramebuffer(const_cast<OGLTexture*>(srcentry), src_rect, src_layer, src_level, dst_rect,
|
||||
dst_layer, dst_level);
|
||||
}
|
||||
}
|
||||
|
||||
void OGLTexture::BlitFramebuffer(OGLTexture* srcentry, const MathUtil::Rectangle<int>& src_rect,
|
||||
u32 src_layer, u32 src_level,
|
||||
const MathUtil::Rectangle<int>& dst_rect, u32 dst_layer,
|
||||
u32 dst_level)
|
||||
{
|
||||
// If it isn't a single leveled/layered texture, we need to update the framebuffer.
|
||||
bool update_src_framebuffer =
|
||||
srcentry->m_framebuffer == 0 || srcentry->m_config.layers != 0 || src_level != 0;
|
||||
bool update_dst_framebuffer = m_framebuffer == 0 || m_config.layers != 0 || dst_level != 0;
|
||||
if (!m_framebuffer)
|
||||
glGenFramebuffers(1, &m_framebuffer);
|
||||
if (!srcentry->m_framebuffer)
|
||||
glGenFramebuffers(1, &const_cast<OGLTexture*>(srcentry)->m_framebuffer);
|
||||
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, srcentry->m_framebuffer);
|
||||
if (update_src_framebuffer)
|
||||
{
|
||||
glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, srcentry->m_texId,
|
||||
src_level, src_layer);
|
||||
}
|
||||
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_framebuffer);
|
||||
if (update_dst_framebuffer)
|
||||
{
|
||||
glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_texId, dst_level,
|
||||
dst_layer);
|
||||
}
|
||||
|
||||
glBlitFramebuffer(src_rect.left, src_rect.top, src_rect.right, src_rect.bottom, dst_rect.left,
|
||||
dst_rect.top, dst_rect.right, dst_rect.bottom, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
|
||||
if (update_src_framebuffer)
|
||||
{
|
||||
FramebufferManager::FramebufferTexture(
|
||||
GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
||||
srcentry->m_config.IsMultisampled() ? GL_TEXTURE_2D_MULTISAMPLE_ARRAY : GL_TEXTURE_2D_ARRAY,
|
||||
srcentry->m_texId, 0);
|
||||
}
|
||||
if (update_dst_framebuffer)
|
||||
{
|
||||
FramebufferManager::FramebufferTexture(
|
||||
GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
||||
m_config.IsMultisampled() ? GL_TEXTURE_2D_MULTISAMPLE_ARRAY : GL_TEXTURE_2D_ARRAY, m_texId,
|
||||
0);
|
||||
}
|
||||
|
||||
FramebufferManager::SetFramebuffer(0);
|
||||
}
|
||||
|
||||
void OGLTexture::ScaleRectangleFromTexture(const AbstractTexture* source,
|
||||
const MathUtil::Rectangle<int>& srcrect,
|
||||
const MathUtil::Rectangle<int>& dstrect)
|
||||
|
@ -222,6 +247,18 @@ void OGLTexture::ScaleRectangleFromTexture(const AbstractTexture* source,
|
|||
g_renderer->RestoreAPIState();
|
||||
}
|
||||
|
||||
void OGLTexture::ResolveFromTexture(const AbstractTexture* src,
|
||||
const MathUtil::Rectangle<int>& rect, u32 layer, u32 level)
|
||||
{
|
||||
const OGLTexture* srcentry = static_cast<const OGLTexture*>(src);
|
||||
_dbg_assert_(VIDEO, m_config.samples > 1 && m_config.width == srcentry->m_config.width &&
|
||||
m_config.height == srcentry->m_config.height && m_config.samples == 1);
|
||||
_dbg_assert_(VIDEO,
|
||||
rect.left + rect.GetWidth() <= static_cast<int>(srcentry->m_config.width) &&
|
||||
rect.top + rect.GetHeight() <= static_cast<int>(srcentry->m_config.height));
|
||||
BlitFramebuffer(const_cast<OGLTexture*>(srcentry), rect, layer, level, rect, layer, level);
|
||||
}
|
||||
|
||||
void OGLTexture::Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer,
|
||||
size_t buffer_size)
|
||||
{
|
||||
|
|
|
@ -26,6 +26,8 @@ public:
|
|||
void ScaleRectangleFromTexture(const AbstractTexture* source,
|
||||
const MathUtil::Rectangle<int>& srcrect,
|
||||
const MathUtil::Rectangle<int>& dstrect) override;
|
||||
void ResolveFromTexture(const AbstractTexture* src, const MathUtil::Rectangle<int>& rect,
|
||||
u32 layer, u32 level) override;
|
||||
void Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer,
|
||||
size_t buffer_size) override;
|
||||
|
||||
|
@ -33,6 +35,10 @@ public:
|
|||
GLuint GetFramebuffer() const;
|
||||
|
||||
private:
|
||||
void BlitFramebuffer(OGLTexture* srcentry, const MathUtil::Rectangle<int>& src_rect,
|
||||
u32 src_layer, u32 src_level, const MathUtil::Rectangle<int>& dst_rect,
|
||||
u32 dst_layer, u32 dst_level);
|
||||
|
||||
GLuint m_texId;
|
||||
GLuint m_framebuffer = 0;
|
||||
};
|
||||
|
|
|
@ -86,7 +86,7 @@ static EncodingProgram& GetOrCreateEncodingShader(const EFBCopyParams& params)
|
|||
|
||||
void Init()
|
||||
{
|
||||
TextureConfig config(renderBufferWidth, renderBufferHeight, 1, 1, AbstractTextureFormat::BGRA8,
|
||||
TextureConfig config(renderBufferWidth, renderBufferHeight, 1, 1, 1, AbstractTextureFormat::BGRA8,
|
||||
true);
|
||||
s_encoding_render_texture = g_renderer->CreateTexture(config);
|
||||
s_encoding_readback_texture =
|
||||
|
|
|
@ -86,6 +86,10 @@ void SWTexture::ScaleRectangleFromTexture(const AbstractTexture* source,
|
|||
memcpy(GetData(), destination_pixels.data(), destination_pixels.size());
|
||||
}
|
||||
}
|
||||
void SWTexture::ResolveFromTexture(const AbstractTexture* src, const MathUtil::Rectangle<int>& rect,
|
||||
u32 layer, u32 level)
|
||||
{
|
||||
}
|
||||
|
||||
void SWTexture::Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer,
|
||||
size_t buffer_size)
|
||||
|
|
|
@ -26,6 +26,8 @@ public:
|
|||
void ScaleRectangleFromTexture(const AbstractTexture* source,
|
||||
const MathUtil::Rectangle<int>& srcrect,
|
||||
const MathUtil::Rectangle<int>& dstrect) override;
|
||||
void ResolveFromTexture(const AbstractTexture* src, const MathUtil::Rectangle<int>& rect,
|
||||
u32 layer, u32 level) override;
|
||||
void Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer,
|
||||
size_t buffer_size) override;
|
||||
|
||||
|
|
|
@ -846,8 +846,8 @@ bool FramebufferManager::CreateReadbackTextures()
|
|||
return false;
|
||||
}
|
||||
|
||||
TextureConfig readback_texture_config(EFB_WIDTH, EFB_HEIGHT, 1, 1, AbstractTextureFormat::RGBA8,
|
||||
false);
|
||||
TextureConfig readback_texture_config(EFB_WIDTH, EFB_HEIGHT, 1, 1, 1,
|
||||
AbstractTextureFormat::RGBA8, false);
|
||||
m_color_readback_texture =
|
||||
g_renderer->CreateStagingTexture(StagingTextureType::Mutable, readback_texture_config);
|
||||
m_depth_readback_texture =
|
||||
|
|
|
@ -596,7 +596,7 @@ VkShaderModule TextureConverter::GetEncodingShader(const EFBCopyParams& params)
|
|||
|
||||
bool TextureConverter::CreateEncodingTexture()
|
||||
{
|
||||
TextureConfig config(ENCODING_TEXTURE_WIDTH, ENCODING_TEXTURE_HEIGHT, 1, 1,
|
||||
TextureConfig config(ENCODING_TEXTURE_WIDTH, ENCODING_TEXTURE_HEIGHT, 1, 1, 1,
|
||||
ENCODING_TEXTURE_FORMAT, true);
|
||||
|
||||
m_encoding_render_texture = g_renderer->CreateTexture(config);
|
||||
|
|
|
@ -42,9 +42,10 @@ std::unique_ptr<VKTexture> VKTexture::Create(const TextureConfig& tex_config)
|
|||
|
||||
// Allocate texture object
|
||||
VkFormat vk_format = Util::GetVkFormatForHostTextureFormat(tex_config.format);
|
||||
auto texture = Texture2D::Create(tex_config.width, tex_config.height, tex_config.levels,
|
||||
tex_config.layers, vk_format, VK_SAMPLE_COUNT_1_BIT,
|
||||
VK_IMAGE_VIEW_TYPE_2D_ARRAY, VK_IMAGE_TILING_OPTIMAL, usage);
|
||||
auto texture =
|
||||
Texture2D::Create(tex_config.width, tex_config.height, tex_config.levels, tex_config.layers,
|
||||
vk_format, static_cast<VkSampleCountFlagBits>(tex_config.samples),
|
||||
VK_IMAGE_VIEW_TYPE_2D_ARRAY, VK_IMAGE_TILING_OPTIMAL, usage);
|
||||
|
||||
if (!texture)
|
||||
{
|
||||
|
@ -56,8 +57,9 @@ std::unique_ptr<VKTexture> VKTexture::Create(const TextureConfig& tex_config)
|
|||
if (tex_config.rendertarget)
|
||||
{
|
||||
VkImageView framebuffer_attachments[] = {texture->GetView()};
|
||||
VkRenderPass render_pass = g_object_cache->GetRenderPass(
|
||||
texture->GetFormat(), VK_FORMAT_UNDEFINED, 1, VK_ATTACHMENT_LOAD_OP_DONT_CARE);
|
||||
VkRenderPass render_pass =
|
||||
g_object_cache->GetRenderPass(texture->GetFormat(), VK_FORMAT_UNDEFINED, tex_config.samples,
|
||||
VK_ATTACHMENT_LOAD_OP_DONT_CARE);
|
||||
VkFramebufferCreateInfo framebuffer_info = {
|
||||
VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
|
||||
nullptr,
|
||||
|
@ -195,6 +197,43 @@ void VKTexture::ScaleRectangleFromTexture(const AbstractTexture* source,
|
|||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
}
|
||||
|
||||
void VKTexture::ResolveFromTexture(const AbstractTexture* src, const MathUtil::Rectangle<int>& rect,
|
||||
u32 layer, u32 level)
|
||||
{
|
||||
const VKTexture* srcentry = static_cast<const VKTexture*>(src);
|
||||
_dbg_assert_(VIDEO, m_config.samples == 1 && m_config.width == srcentry->m_config.width &&
|
||||
m_config.height == srcentry->m_config.height &&
|
||||
srcentry->m_config.samples > 1);
|
||||
_dbg_assert_(VIDEO,
|
||||
rect.left + rect.GetWidth() <= static_cast<int>(srcentry->m_config.width) &&
|
||||
rect.top + rect.GetHeight() <= static_cast<int>(srcentry->m_config.height));
|
||||
|
||||
// Resolving is considered to be a transfer operation.
|
||||
StateTracker::GetInstance()->EndRenderPass();
|
||||
VkImageLayout old_src_layout = srcentry->m_texture->GetLayout();
|
||||
srcentry->m_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
|
||||
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
||||
m_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||
|
||||
VkImageResolve resolve = {
|
||||
{VK_IMAGE_ASPECT_COLOR_BIT, level, layer, 1}, // srcSubresource
|
||||
{rect.left, rect.top, 0}, // srcOffset
|
||||
{VK_IMAGE_ASPECT_COLOR_BIT, level, layer, 1}, // dstSubresource
|
||||
{rect.left, rect.top, 0}, // dstOffset
|
||||
{static_cast<u32>(rect.GetWidth()), static_cast<u32>(rect.GetHeight()), 1} // extent
|
||||
};
|
||||
vkCmdResolveImage(g_command_buffer_mgr->GetCurrentCommandBuffer(),
|
||||
srcentry->m_texture->GetImage(), srcentry->m_texture->GetLayout(),
|
||||
m_texture->GetImage(), m_texture->GetLayout(), 1, &resolve);
|
||||
|
||||
// Restore old source texture layout. Destination is assumed to be bound as a shader resource.
|
||||
srcentry->m_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
|
||||
old_src_layout);
|
||||
m_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
|
||||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
}
|
||||
|
||||
void VKTexture::Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer,
|
||||
size_t buffer_size)
|
||||
{
|
||||
|
|
|
@ -28,6 +28,8 @@ public:
|
|||
void ScaleRectangleFromTexture(const AbstractTexture* source,
|
||||
const MathUtil::Rectangle<int>& src_rect,
|
||||
const MathUtil::Rectangle<int>& dst_rect) override;
|
||||
void ResolveFromTexture(const AbstractTexture* src, const MathUtil::Rectangle<int>& rect,
|
||||
u32 layer, u32 level) override;
|
||||
|
||||
void Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer,
|
||||
size_t buffer_size) override;
|
||||
|
|
|
@ -29,7 +29,7 @@ bool AbstractTexture::Save(const std::string& filename, unsigned int level)
|
|||
|
||||
// Use a temporary staging texture for the download. Certainly not optimal,
|
||||
// but this is not a frequently-executed code path..
|
||||
TextureConfig readback_texture_config(level_width, level_height, 1, 1,
|
||||
TextureConfig readback_texture_config(level_width, level_height, 1, 1, 1,
|
||||
AbstractTextureFormat::RGBA8, false);
|
||||
auto readback_texture =
|
||||
g_renderer->CreateStagingTexture(StagingTextureType::Readback, readback_texture_config);
|
||||
|
|
|
@ -24,6 +24,8 @@ public:
|
|||
virtual void ScaleRectangleFromTexture(const AbstractTexture* source,
|
||||
const MathUtil::Rectangle<int>& srcrect,
|
||||
const MathUtil::Rectangle<int>& dstrect) = 0;
|
||||
virtual void ResolveFromTexture(const AbstractTexture* src, const MathUtil::Rectangle<int>& rect,
|
||||
u32 layer, u32 level) = 0;
|
||||
virtual void Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer,
|
||||
size_t buffer_size) = 0;
|
||||
|
||||
|
|
|
@ -739,7 +739,7 @@ void Renderer::RenderFrameDump()
|
|||
m_frame_dump_render_texture->GetConfig().height == static_cast<u32>(target_height))
|
||||
{
|
||||
// Recreate texture objects. Release before creating so we don't temporarily use twice the RAM.
|
||||
TextureConfig config(target_width, target_height, 1, 1, AbstractTextureFormat::RGBA8, true);
|
||||
TextureConfig config(target_width, target_height, 1, 1, 1, AbstractTextureFormat::RGBA8, true);
|
||||
m_frame_dump_render_texture.reset();
|
||||
m_frame_dump_render_texture = CreateTexture(config);
|
||||
_assert_(m_frame_dump_render_texture);
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
|
||||
bool TextureConfig::operator==(const TextureConfig& o) const
|
||||
{
|
||||
return std::tie(width, height, levels, layers, format, rendertarget) ==
|
||||
std::tie(o.width, o.height, o.levels, o.layers, o.format, o.rendertarget);
|
||||
return std::tie(width, height, levels, layers, samples, format, rendertarget) ==
|
||||
std::tie(o.width, o.height, o.levels, o.layers, o.samples, o.format, o.rendertarget);
|
||||
}
|
||||
|
||||
bool TextureConfig::operator!=(const TextureConfig& o) const
|
||||
|
@ -38,3 +38,8 @@ size_t TextureConfig::GetMipStride(u32 level) const
|
|||
{
|
||||
return AbstractTexture::CalculateStrideForFormat(format, std::max(width >> level, 1u));
|
||||
}
|
||||
|
||||
bool TextureConfig::IsMultisampled() const
|
||||
{
|
||||
return samples > 1;
|
||||
}
|
||||
|
|
|
@ -31,10 +31,10 @@ enum class StagingTextureType
|
|||
struct TextureConfig
|
||||
{
|
||||
constexpr TextureConfig() = default;
|
||||
constexpr TextureConfig(u32 width_, u32 height_, u32 levels_, u32 layers_,
|
||||
constexpr TextureConfig(u32 width_, u32 height_, u32 levels_, u32 layers_, u32 samples_,
|
||||
AbstractTextureFormat format_, bool rendertarget_)
|
||||
: width(width_), height(height_), levels(levels_), layers(layers_), format(format_),
|
||||
rendertarget(rendertarget_)
|
||||
: width(width_), height(height_), levels(levels_), layers(layers_), samples(samples_),
|
||||
format(format_), rendertarget(rendertarget_)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -44,11 +44,13 @@ struct TextureConfig
|
|||
MathUtil::Rectangle<int> GetMipRect(u32 level) const;
|
||||
size_t GetStride() const;
|
||||
size_t GetMipStride(u32 level) const;
|
||||
bool IsMultisampled() const;
|
||||
|
||||
u32 width = 0;
|
||||
u32 height = 0;
|
||||
u32 levels = 1;
|
||||
u32 layers = 1;
|
||||
u32 samples = 1;
|
||||
AbstractTextureFormat format = AbstractTextureFormat::RGBA8;
|
||||
bool rendertarget = false;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue