Vulkan: Use new readback methods for texture encoding
This commit is contained in:
parent
c2cc128f1b
commit
59517318d6
|
@ -67,9 +67,6 @@ TextureConverter::~TextureConverter()
|
||||||
if (m_encoding_render_pass != VK_NULL_HANDLE)
|
if (m_encoding_render_pass != VK_NULL_HANDLE)
|
||||||
vkDestroyRenderPass(g_vulkan_context->GetDevice(), m_encoding_render_pass, nullptr);
|
vkDestroyRenderPass(g_vulkan_context->GetDevice(), m_encoding_render_pass, nullptr);
|
||||||
|
|
||||||
if (m_encoding_render_framebuffer != VK_NULL_HANDLE)
|
|
||||||
vkDestroyFramebuffer(g_vulkan_context->GetDevice(), m_encoding_render_framebuffer, nullptr);
|
|
||||||
|
|
||||||
for (auto& it : m_encoding_shaders)
|
for (auto& it : m_encoding_shaders)
|
||||||
vkDestroyShaderModule(g_vulkan_context->GetDevice(), it.second, nullptr);
|
vkDestroyShaderModule(g_vulkan_context->GetDevice(), it.second, nullptr);
|
||||||
|
|
||||||
|
@ -111,12 +108,6 @@ bool TextureConverter::Initialize()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!CreateEncodingDownloadTexture())
|
|
||||||
{
|
|
||||||
PanicAlert("Failed to create download texture");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!CreateDecodingTexture())
|
if (!CreateDecodingTexture())
|
||||||
{
|
{
|
||||||
PanicAlert("Failed to create decoding texture");
|
PanicAlert("Failed to create decoding texture");
|
||||||
|
@ -245,7 +236,9 @@ void TextureConverter::EncodeTextureToMemory(VkImageView src_texture, u8* dest_p
|
||||||
// Can't do our own draw within a render pass.
|
// Can't do our own draw within a render pass.
|
||||||
StateTracker::GetInstance()->EndRenderPass();
|
StateTracker::GetInstance()->EndRenderPass();
|
||||||
|
|
||||||
m_encoding_render_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
|
static_cast<VKTexture*>(m_encoding_render_texture.get())
|
||||||
|
->GetRawTexIdentifier()
|
||||||
|
->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
|
||||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||||
|
|
||||||
UtilityShaderDraw draw(g_command_buffer_mgr->GetCurrentCommandBuffer(),
|
UtilityShaderDraw draw(g_command_buffer_mgr->GetCurrentCommandBuffer(),
|
||||||
|
@ -276,23 +269,15 @@ void TextureConverter::EncodeTextureToMemory(VkImageView src_texture, u8* dest_p
|
||||||
render_height);
|
render_height);
|
||||||
|
|
||||||
VkRect2D render_region = {{0, 0}, {render_width, render_height}};
|
VkRect2D render_region = {{0, 0}, {render_width, render_height}};
|
||||||
draw.BeginRenderPass(m_encoding_render_framebuffer, render_region);
|
draw.BeginRenderPass(static_cast<VKTexture*>(m_encoding_render_texture.get())->GetFramebuffer(),
|
||||||
|
render_region);
|
||||||
draw.DrawWithoutVertexBuffer(4);
|
draw.DrawWithoutVertexBuffer(4);
|
||||||
draw.EndRenderPass();
|
draw.EndRenderPass();
|
||||||
|
|
||||||
// Transition the image before copying
|
MathUtil::Rectangle<int> copy_rect(0, 0, render_width, render_height);
|
||||||
m_encoding_render_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
|
m_encoding_readback_texture->CopyFromTexture(m_encoding_render_texture.get(), copy_rect, 0, 0,
|
||||||
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
copy_rect);
|
||||||
m_encoding_download_texture->CopyFromImage(
|
m_encoding_readback_texture->ReadTexels(copy_rect, dest_ptr, memory_stride);
|
||||||
g_command_buffer_mgr->GetCurrentCommandBuffer(), m_encoding_render_texture->GetImage(),
|
|
||||||
VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, render_width, render_height, 0, 0);
|
|
||||||
|
|
||||||
// Block until the GPU has finished copying to the staging texture.
|
|
||||||
Util::ExecuteCurrentCommandsAndRestoreState(false, true);
|
|
||||||
|
|
||||||
// Copy from staging texture to the final destination, adjusting pitch if necessary.
|
|
||||||
m_encoding_download_texture->ReadTexels(0, 0, render_width, render_height, dest_ptr,
|
|
||||||
memory_stride);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureConverter::EncodeTextureToMemoryYUYV(void* dst_ptr, u32 dst_width, u32 dst_stride,
|
void TextureConverter::EncodeTextureToMemoryYUYV(void* dst_ptr, u32 dst_width, u32 dst_stride,
|
||||||
|
@ -304,8 +289,9 @@ void TextureConverter::EncodeTextureToMemoryYUYV(void* dst_ptr, u32 dst_width, u
|
||||||
// Borrow framebuffer from EFB2RAM encoder.
|
// Borrow framebuffer from EFB2RAM encoder.
|
||||||
VkCommandBuffer command_buffer = g_command_buffer_mgr->GetCurrentCommandBuffer();
|
VkCommandBuffer command_buffer = g_command_buffer_mgr->GetCurrentCommandBuffer();
|
||||||
src_texture->TransitionToLayout(command_buffer, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
src_texture->TransitionToLayout(command_buffer, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||||
m_encoding_render_texture->TransitionToLayout(command_buffer,
|
static_cast<VKTexture*>(m_encoding_render_texture.get())
|
||||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
->GetRawTexIdentifier()
|
||||||
|
->TransitionToLayout(command_buffer, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||||
|
|
||||||
// Use fragment shader to convert RGBA to YUYV.
|
// Use fragment shader to convert RGBA to YUYV.
|
||||||
// Use linear sampler for downscaling. This texture is in BGRA order, so the data is already in
|
// Use linear sampler for downscaling. This texture is in BGRA order, so the data is already in
|
||||||
|
@ -317,7 +303,8 @@ void TextureConverter::EncodeTextureToMemoryYUYV(void* dst_ptr, u32 dst_width, u
|
||||||
m_encoding_render_pass, g_shader_cache->GetPassthroughVertexShader(),
|
m_encoding_render_pass, g_shader_cache->GetPassthroughVertexShader(),
|
||||||
VK_NULL_HANDLE, m_rgb_to_yuyv_shader);
|
VK_NULL_HANDLE, m_rgb_to_yuyv_shader);
|
||||||
VkRect2D region = {{0, 0}, {output_width, dst_height}};
|
VkRect2D region = {{0, 0}, {output_width, dst_height}};
|
||||||
draw.BeginRenderPass(m_encoding_render_framebuffer, region);
|
draw.BeginRenderPass(static_cast<VKTexture*>(m_encoding_render_texture.get())->GetFramebuffer(),
|
||||||
|
region);
|
||||||
draw.SetPSSampler(0, src_texture->GetView(), g_object_cache->GetLinearSampler());
|
draw.SetPSSampler(0, src_texture->GetView(), g_object_cache->GetLinearSampler());
|
||||||
draw.DrawQuad(0, 0, static_cast<int>(output_width), static_cast<int>(dst_height), src_rect.left,
|
draw.DrawQuad(0, 0, static_cast<int>(output_width), static_cast<int>(dst_height), src_rect.left,
|
||||||
src_rect.top, 0, src_rect.GetWidth(), src_rect.GetHeight(),
|
src_rect.top, 0, src_rect.GetWidth(), src_rect.GetHeight(),
|
||||||
|
@ -325,18 +312,11 @@ void TextureConverter::EncodeTextureToMemoryYUYV(void* dst_ptr, u32 dst_width, u
|
||||||
static_cast<int>(src_texture->GetHeight()));
|
static_cast<int>(src_texture->GetHeight()));
|
||||||
draw.EndRenderPass();
|
draw.EndRenderPass();
|
||||||
|
|
||||||
// Render pass transitions to TRANSFER_SRC.
|
|
||||||
m_encoding_render_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
|
|
||||||
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
|
||||||
|
|
||||||
// Copy from encoding texture to download buffer.
|
// Copy from encoding texture to download buffer.
|
||||||
m_encoding_download_texture->CopyFromImage(command_buffer, m_encoding_render_texture->GetImage(),
|
MathUtil::Rectangle<int> copy_rect(0, 0, output_width, dst_height);
|
||||||
VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, output_width,
|
m_encoding_readback_texture->CopyFromTexture(m_encoding_render_texture.get(), copy_rect, 0, 0,
|
||||||
dst_height, 0, 0);
|
copy_rect);
|
||||||
Util::ExecuteCurrentCommandsAndRestoreState(false, true);
|
m_encoding_readback_texture->ReadTexels(copy_rect, dst_ptr, dst_stride);
|
||||||
|
|
||||||
// Finally, copy to guest memory. This may have a different stride.
|
|
||||||
m_encoding_download_texture->ReadTexels(0, 0, output_width, dst_height, dst_ptr, dst_stride);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureConverter::DecodeYUYVTextureFromMemory(VKTexture* dst_texture, const void* src_ptr,
|
void TextureConverter::DecodeYUYVTextureFromMemory(VKTexture* dst_texture, const void* src_ptr,
|
||||||
|
@ -734,10 +714,10 @@ VkShaderModule TextureConverter::GetEncodingShader(const EFBCopyParams& params)
|
||||||
bool TextureConverter::CreateEncodingRenderPass()
|
bool TextureConverter::CreateEncodingRenderPass()
|
||||||
{
|
{
|
||||||
VkAttachmentDescription attachments[] = {
|
VkAttachmentDescription attachments[] = {
|
||||||
{0, ENCODING_TEXTURE_FORMAT, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_DONT_CARE,
|
{0, Util::GetVkFormatForHostTextureFormat(ENCODING_TEXTURE_FORMAT), VK_SAMPLE_COUNT_1_BIT,
|
||||||
VK_ATTACHMENT_STORE_OP_STORE, VK_ATTACHMENT_LOAD_OP_DONT_CARE,
|
VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_STORE,
|
||||||
VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE,
|
||||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}};
|
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}};
|
||||||
|
|
||||||
VkAttachmentReference color_attachment_references[] = {
|
VkAttachmentReference color_attachment_references[] = {
|
||||||
{0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}};
|
{0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}};
|
||||||
|
@ -769,43 +749,14 @@ bool TextureConverter::CreateEncodingRenderPass()
|
||||||
|
|
||||||
bool TextureConverter::CreateEncodingTexture()
|
bool TextureConverter::CreateEncodingTexture()
|
||||||
{
|
{
|
||||||
m_encoding_render_texture = Texture2D::Create(
|
TextureConfig config(ENCODING_TEXTURE_WIDTH, ENCODING_TEXTURE_HEIGHT, 1, 1,
|
||||||
ENCODING_TEXTURE_WIDTH, ENCODING_TEXTURE_HEIGHT, 1, 1, ENCODING_TEXTURE_FORMAT,
|
ENCODING_TEXTURE_FORMAT, true);
|
||||||
VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
|
|
||||||
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT |
|
|
||||||
VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
|
|
||||||
if (!m_encoding_render_texture)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
VkImageView framebuffer_attachments[] = {m_encoding_render_texture->GetView()};
|
m_encoding_render_texture = g_renderer->CreateTexture(config);
|
||||||
VkFramebufferCreateInfo framebuffer_info = {VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
|
m_encoding_readback_texture =
|
||||||
nullptr,
|
g_renderer->CreateStagingTexture(StagingTextureType::Readback, config);
|
||||||
0,
|
|
||||||
m_encoding_render_pass,
|
|
||||||
static_cast<u32>(ArraySize(framebuffer_attachments)),
|
|
||||||
framebuffer_attachments,
|
|
||||||
m_encoding_render_texture->GetWidth(),
|
|
||||||
m_encoding_render_texture->GetHeight(),
|
|
||||||
m_encoding_render_texture->GetLayers()};
|
|
||||||
|
|
||||||
VkResult res = vkCreateFramebuffer(g_vulkan_context->GetDevice(), &framebuffer_info, nullptr,
|
return m_encoding_render_texture && m_encoding_readback_texture;
|
||||||
&m_encoding_render_framebuffer);
|
|
||||||
if (res != VK_SUCCESS)
|
|
||||||
{
|
|
||||||
LOG_VULKAN_ERROR(res, "vkCreateFramebuffer failed: ");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TextureConverter::CreateEncodingDownloadTexture()
|
|
||||||
{
|
|
||||||
m_encoding_download_texture =
|
|
||||||
StagingTexture2D::Create(STAGING_BUFFER_TYPE_READBACK, ENCODING_TEXTURE_WIDTH,
|
|
||||||
ENCODING_TEXTURE_HEIGHT, ENCODING_TEXTURE_FORMAT);
|
|
||||||
|
|
||||||
return m_encoding_download_texture && m_encoding_download_texture->Map();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TextureConverter::CreateDecodingTexture()
|
bool TextureConverter::CreateDecodingTexture()
|
||||||
|
|
|
@ -16,6 +16,9 @@
|
||||||
#include "VideoCommon/TextureDecoder.h"
|
#include "VideoCommon/TextureDecoder.h"
|
||||||
#include "VideoCommon/VideoCommon.h"
|
#include "VideoCommon/VideoCommon.h"
|
||||||
|
|
||||||
|
class AbstractTexture;
|
||||||
|
class AbstractStagingTexture;
|
||||||
|
|
||||||
namespace Vulkan
|
namespace Vulkan
|
||||||
{
|
{
|
||||||
class StagingTexture2D;
|
class StagingTexture2D;
|
||||||
|
@ -58,7 +61,7 @@ public:
|
||||||
private:
|
private:
|
||||||
static const u32 ENCODING_TEXTURE_WIDTH = EFB_WIDTH * 4;
|
static const u32 ENCODING_TEXTURE_WIDTH = EFB_WIDTH * 4;
|
||||||
static const u32 ENCODING_TEXTURE_HEIGHT = 1024;
|
static const u32 ENCODING_TEXTURE_HEIGHT = 1024;
|
||||||
static const VkFormat ENCODING_TEXTURE_FORMAT = VK_FORMAT_B8G8R8A8_UNORM;
|
static const AbstractTextureFormat ENCODING_TEXTURE_FORMAT = AbstractTextureFormat::BGRA8;
|
||||||
static const size_t NUM_PALETTE_CONVERSION_SHADERS = 3;
|
static const size_t NUM_PALETTE_CONVERSION_SHADERS = 3;
|
||||||
|
|
||||||
// Maximum size of a texture based on BP registers.
|
// Maximum size of a texture based on BP registers.
|
||||||
|
@ -75,8 +78,6 @@ private:
|
||||||
|
|
||||||
bool CreateEncodingRenderPass();
|
bool CreateEncodingRenderPass();
|
||||||
bool CreateEncodingTexture();
|
bool CreateEncodingTexture();
|
||||||
bool CreateEncodingDownloadTexture();
|
|
||||||
|
|
||||||
bool CreateDecodingTexture();
|
bool CreateDecodingTexture();
|
||||||
|
|
||||||
bool CompileYUYVConversionShaders();
|
bool CompileYUYVConversionShaders();
|
||||||
|
@ -106,10 +107,9 @@ private:
|
||||||
|
|
||||||
// Texture encoding - RGBA8->GX format in memory
|
// Texture encoding - RGBA8->GX format in memory
|
||||||
std::map<EFBCopyParams, VkShaderModule> m_encoding_shaders;
|
std::map<EFBCopyParams, VkShaderModule> m_encoding_shaders;
|
||||||
|
std::unique_ptr<AbstractTexture> m_encoding_render_texture;
|
||||||
|
std::unique_ptr<AbstractStagingTexture> m_encoding_readback_texture;
|
||||||
VkRenderPass m_encoding_render_pass = VK_NULL_HANDLE;
|
VkRenderPass m_encoding_render_pass = VK_NULL_HANDLE;
|
||||||
std::unique_ptr<Texture2D> m_encoding_render_texture;
|
|
||||||
VkFramebuffer m_encoding_render_framebuffer = VK_NULL_HANDLE;
|
|
||||||
std::unique_ptr<StagingTexture2D> m_encoding_download_texture;
|
|
||||||
|
|
||||||
// Texture decoding - GX format in memory->RGBA8
|
// Texture decoding - GX format in memory->RGBA8
|
||||||
struct TextureDecodingPipeline
|
struct TextureDecodingPipeline
|
||||||
|
|
Loading…
Reference in New Issue