From cf039acadcad91c0e35147e62e4a4fe3c8a0b8e7 Mon Sep 17 00:00:00 2001 From: baldurk Date: Mon, 18 May 2020 11:05:04 +0100 Subject: [PATCH] When possible with image viewer, manually unpack unsupported formats * This is similar to the remapping the replay proxy does, and should support most non-compressed formats. --- renderdoc/core/image_viewer.cpp | 91 ++++++++++++++++++++++++++++++- renderdoc/maths/formatpacking.cpp | 35 +++++++++++- renderdoc/maths/formatpacking.h | 2 +- 3 files changed, 125 insertions(+), 3 deletions(-) diff --git a/renderdoc/core/image_viewer.cpp b/renderdoc/core/image_viewer.cpp index 8398ce91f..e2190e04f 100644 --- a/renderdoc/core/image_viewer.cpp +++ b/renderdoc/core/image_viewer.cpp @@ -24,6 +24,7 @@ #include "common/dds_readwrite.h" #include "core/core.h" +#include "maths/formatpacking.h" #include "replay/replay_driver.h" #include "serialise/rdcfile.h" #include "stb/stb_image.h" @@ -175,7 +176,20 @@ public: void GetTextureData(ResourceId tex, const Subresource &sub, const GetTextureDataParams ¶ms, bytebuf &data) { - m_Proxy->GetTextureData(m_TextureID, sub, params, data); + if(tex != m_TextureID && tex != m_CustomTexID) + tex = m_TextureID; + + if(tex == m_TextureID && !m_RealTexData.empty() && params.remap == RemapTexture::NoRemap) + { + RDCASSERT(sub.sample == 0); + uint32_t idx = sub.slice * m_TexDetails.mips + sub.mip; + RDCASSERT(idx < m_RealTexData.size(), idx, m_RealTexData.size(), m_TexDetails.mips, sub.slice, + sub.mip); + data = m_RealTexData[idx]; + return; + } + + m_Proxy->GetTextureData(tex, sub, params, data); } // handle a couple of operations ourselves to return a simple fake log @@ -319,6 +333,10 @@ private: rdcarray m_Resources; SDFile m_File; TextureDescription m_TexDetails; + + // if we remapped the texture for display, this contains the real data to return from + // GetTextureData() + rdcarray m_RealTexData; }; ReplayStatus IMG_CreateReplayDevice(RDCFile *rdc, IReplayDriver **driver) @@ -747,7 +765,78 @@ void ImageViewer::RefreshFile() if(m_TextureID == ResourceId()) { if(m_Proxy->IsTextureSupported(texDetails)) + { m_TextureID = m_Proxy->CreateProxyTexture(texDetails); + } + else + { + if(dds) + { + // see if we can convert this format on the CPU for proxying + bool convertSupported = false; + ConvertComponents(texDetails.format, NULL, &convertSupported); + + if(convertSupported) + { + uint32_t srcStride = texDetails.format.ElementSize(); + + if(texDetails.format.type == ResourceFormatType::D16S8) + srcStride = 4; + else if(texDetails.format.type == ResourceFormatType::D32S8) + srcStride = 8; + + m_RealTexData.resize(texDetails.arraysize * texDetails.mips); + + for(uint32_t i = 0; i < texDetails.arraysize * texDetails.mips; i++) + { + const uint32_t mip = i % texDetails.mips; + + const uint32_t mipwidth = RDCMAX(1U, texDetails.width >> mip); + const uint32_t mipheight = RDCMAX(1U, texDetails.height >> mip); + const uint32_t mipdepth = RDCMAX(1U, texDetails.depth >> mip); + + byte *old = read_data.subdata[i]; + m_RealTexData[i].assign(old, read_data.subsizes[i]); + + read_data.subsizes[i] = sizeof(FloatVector) * mipwidth * mipheight * mipdepth; + byte *converted = new byte[read_data.subsizes[i]]; + + byte *src = old; + FloatVector *dst = (FloatVector *)converted; + + for(uint32_t z = 0; z < mipdepth; z++) + { + for(uint32_t y = 0; y < mipheight; y++) + { + for(uint32_t x = 0; x < mipwidth; x++) + { + *dst = ConvertComponents(texDetails.format, src); + dst++; + src += srcStride; + } + } + } + + read_data.subdata[i] = converted; + delete[] old; + } + + TextureDescription remapped = texDetails; + remapped.format = rgba32_float; + m_TextureID = m_Proxy->CreateProxyTexture(remapped); + } + else + { + RDCLOG("Format %s not supported for local display and can't be converted manually.", + texDetails.format.Name().c_str()); + } + } + else + { + RDCERR("Standard format %s expected to be supported for local display but can't.", + texDetails.format.Name().c_str()); + } + } } if(m_TextureID == ResourceId()) diff --git a/renderdoc/maths/formatpacking.cpp b/renderdoc/maths/formatpacking.cpp index d5e9630b9..944afe52a 100644 --- a/renderdoc/maths/formatpacking.cpp +++ b/renderdoc/maths/formatpacking.cpp @@ -279,10 +279,18 @@ float ConvertLinearToSRGB(float linear) return 1.055f * powf(linear, 1.0f / 2.4f) - 0.055f; } -FloatVector ConvertComponents(const ResourceFormat &fmt, const byte *data) +FloatVector ConvertComponents(const ResourceFormat &fmt, const byte *data, bool *success) { FloatVector ret(0.0f, 0.0f, 0.0f, 1.0f); + const uint64_t dummy = 0; + if(!data) + data = (const byte *)&dummy; + + // assume success, we'll set it to false if we hit an error + if(success) + *success = true; + if(fmt.type == ResourceFormatType::R10G10B10A2) { Vec4f v; @@ -419,6 +427,11 @@ FloatVector ConvertComponents(const ResourceFormat &fmt, const byte *data) { *comp = float(*i64); } + else + { + if(success) + *success = false; + } } else if(fmt.compByteWidth == 4) { @@ -437,6 +450,11 @@ FloatVector ConvertComponents(const ResourceFormat &fmt, const byte *data) { *comp = float(*i32); } + else + { + if(success) + *success = false; + } } else if(fmt.compByteWidth == 3 && compType == CompType::Depth) { @@ -483,6 +501,11 @@ FloatVector ConvertComponents(const ResourceFormat &fmt, const byte *data) *comp = f; } + else + { + if(success) + *success = false; + } } else if(fmt.compByteWidth == 1) { @@ -516,6 +539,11 @@ FloatVector ConvertComponents(const ResourceFormat &fmt, const byte *data) *comp = f; } + else + { + if(success) + *success = false; + } } else { @@ -540,6 +568,11 @@ FloatVector ConvertComponents(const ResourceFormat &fmt, const byte *data) if(fmt.BGRAOrder()) std::swap(ret.x, ret.z); } + else + { + if(success) + *success = false; + } return ret; } diff --git a/renderdoc/maths/formatpacking.h b/renderdoc/maths/formatpacking.h index bffb488d1..a8def2a55 100644 --- a/renderdoc/maths/formatpacking.h +++ b/renderdoc/maths/formatpacking.h @@ -110,4 +110,4 @@ float ConvertLinearToSRGB(float linear); typedef uint8_t byte; struct ResourceFormat; -FloatVector ConvertComponents(const ResourceFormat &fmt, const byte *data); +FloatVector ConvertComponents(const ResourceFormat &fmt, const byte *data, bool *success = NULL);