diff --git a/renderdoc/core/image_viewer.cpp b/renderdoc/core/image_viewer.cpp index 50fa8c359..14b846419 100644 --- a/renderdoc/core/image_viewer.cpp +++ b/renderdoc/core/image_viewer.cpp @@ -138,12 +138,10 @@ public: } vector GetTextures() { return m_Proxy->GetTextures(); } FetchTexture GetTexture(ResourceId id) { return m_Proxy->GetTexture(m_TextureID); } - byte *GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip, bool forDiskSave, - FormatComponentType typeHint, bool resolve, bool forceRGBA8unorm, - float blackPoint, float whitePoint, size_t &dataSize) + byte *GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip, + const GetTextureDataParams ¶ms, size_t &dataSize) { - return m_Proxy->GetTextureData(m_TextureID, arrayIdx, mip, forDiskSave, typeHint, resolve, - forceRGBA8unorm, blackPoint, whitePoint, dataSize); + return m_Proxy->GetTextureData(m_TextureID, arrayIdx, mip, params, dataSize); } // handle a couple of operations ourselves to return a simple fake log @@ -250,7 +248,7 @@ public: { RDCERR("Calling proxy-render functions on an image viewer"); } - + bool IsTextureSupported(const ResourceFormat &format) { return true; } ResourceId CreateProxyBuffer(const FetchBuffer &templateBuf) { RDCERR("Calling proxy-render functions on an image viewer"); diff --git a/renderdoc/core/replay_proxy.cpp b/renderdoc/core/replay_proxy.cpp index cfe8a0d85..8f74e7924 100644 --- a/renderdoc/core/replay_proxy.cpp +++ b/renderdoc/core/replay_proxy.cpp @@ -1707,6 +1707,76 @@ bool ReplayProxy::SendReplayCommand(ReplayProxyPacket type) return true; } +template <> +string ToStrHelper::Get(const RemapTextureEnum &el) +{ + switch(el) + { + TOSTR_CASE_STRINGIZE(eRemap_None) + TOSTR_CASE_STRINGIZE(eRemap_RGBA8) + TOSTR_CASE_STRINGIZE(eRemap_RGBA16) + TOSTR_CASE_STRINGIZE(eRemap_RGBA32) + TOSTR_CASE_STRINGIZE(eRemap_D32S8) + default: break; + } + + return StringFormat::Fmt("RemapTextureEnum<%d>", el); +} + +// If a remap is required, modify the params that are used when getting the proxy texture data +// for replay on the current driver. +void ReplayProxy::RemapProxyTextureIfNeeded(ResourceFormat &format, GetTextureDataParams ¶ms) +{ + if(m_Proxy->IsTextureSupported(format)) + return; + + if(format.special) + { + switch(format.specialFormat) + { + case eSpecial_S8: + case eSpecial_D16S8: params.remap = eRemap_D32S8; break; + default: + // Remap ASTC/ETC/EAC + params.remap = eRemap_RGBA8; + break; + } + format.special = false; + } + else + { + if(format.compByteWidth == 4) + params.remap = eRemap_RGBA32; + else if(format.compByteWidth == 2) + params.remap = eRemap_RGBA16; + else if(format.compByteWidth == 1) + params.remap = eRemap_RGBA8; + } + + switch(params.remap) + { + case eRemap_None: RDCERR("IsTextureSupported == false, but we have no remap"); break; + case eRemap_RGBA8: + format.compCount = 4; + format.compByteWidth = 1; + format.compType = eCompType_UNorm; + // Range adaptation is only needed when remapping a higher precision format down to RGBA8. + params.whitePoint = 1.0f; + break; + case eRemap_RGBA16: + format.compCount = 4; + format.compByteWidth = 2; + format.compType = eCompType_UNorm; + break; + case eRemap_RGBA32: + format.compCount = 4; + format.compByteWidth = 4; + format.compType = eCompType_Float; + break; + case eRemap_D32S8: RDCERR("Remapping depth/stencil formats not implemented."); break; + } +} + void ReplayProxy::EnsureTexCached(ResourceId texid, uint32_t arrayIdx, uint32_t mip) { if(!m_Socket->Connected()) @@ -1719,20 +1789,24 @@ void ReplayProxy::EnsureTexCached(ResourceId texid, uint32_t arrayIdx, uint32_t if(m_TextureProxyCache.find(entry) == m_TextureProxyCache.end()) { - if(m_ProxyTextureIds.find(texid) == m_ProxyTextureIds.end()) + if(m_ProxyTextures.find(texid) == m_ProxyTextures.end()) { FetchTexture tex = GetTexture(texid); - m_ProxyTextureIds[texid] = m_Proxy->CreateProxyTexture(tex); + + ProxyTextureProperties proxy; + RemapProxyTextureIfNeeded(tex.format, proxy.params); + + proxy.id = m_Proxy->CreateProxyTexture(tex); + m_ProxyTextures[texid] = proxy; } - ResourceId proxyid = m_ProxyTextureIds[texid]; + const ProxyTextureProperties &proxy = m_ProxyTextures[texid]; size_t size; - byte *data = - GetTextureData(texid, arrayIdx, mip, false, eCompType_None, false, false, 0.0f, 0.0f, size); + byte *data = GetTextureData(texid, arrayIdx, mip, proxy.params, size); if(data) - m_Proxy->SetProxyTextureData(proxyid, arrayIdx, mip, data, size); + m_Proxy->SetProxyTextureData(proxy.id, arrayIdx, mip, data, size); delete[] data; @@ -1827,7 +1901,7 @@ bool ReplayProxy::Tick(int type, Serialiser *incomingPacket) case eReplayProxy_GetTextureData: { size_t dummy; - GetTextureData(ResourceId(), 0, 0, false, eCompType_None, false, false, 0.0f, 0.0f, dummy); + GetTextureData(ResourceId(), 0, 0, GetTextureDataParams(), dummy); break; } case eReplayProxy_InitPostVS: InitPostVSBuffers(0); break; @@ -2288,24 +2362,24 @@ void ReplayProxy::GetBufferData(ResourceId buff, uint64_t offset, uint64_t len, } } -byte *ReplayProxy::GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip, bool forDiskSave, - FormatComponentType typeHint, bool resolve, bool forceRGBA8unorm, - float blackPoint, float whitePoint, size_t &dataSize) +byte *ReplayProxy::GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip, + const GetTextureDataParams &_params, size_t &dataSize) { + GetTextureDataParams params = _params; // Serialiser is non-const + m_ToReplaySerialiser->Serialise("", tex); m_ToReplaySerialiser->Serialise("", arrayIdx); m_ToReplaySerialiser->Serialise("", mip); - m_ToReplaySerialiser->Serialise("", forDiskSave); - m_ToReplaySerialiser->Serialise("", typeHint); - m_ToReplaySerialiser->Serialise("", resolve); - m_ToReplaySerialiser->Serialise("", forceRGBA8unorm); - m_ToReplaySerialiser->Serialise("", blackPoint); - m_ToReplaySerialiser->Serialise("", whitePoint); + m_ToReplaySerialiser->Serialise("", params.forDiskSave); + m_ToReplaySerialiser->Serialise("", params.typeHint); + m_ToReplaySerialiser->Serialise("", params.resolve); + m_ToReplaySerialiser->Serialise("", params.remap); + m_ToReplaySerialiser->Serialise("", params.blackPoint); + m_ToReplaySerialiser->Serialise("", params.whitePoint); if(m_RemoteServer) { - byte *data = m_Remote->GetTextureData(tex, arrayIdx, mip, forDiskSave, typeHint, resolve, - forceRGBA8unorm, blackPoint, whitePoint, dataSize); + byte *data = m_Remote->GetTextureData(tex, arrayIdx, mip, params, dataSize); byte *compressed = new byte[LZ4_COMPRESSBOUND(dataSize)]; diff --git a/renderdoc/core/replay_proxy.h b/renderdoc/core/replay_proxy.h index 74892dc71..1e741b2a5 100644 --- a/renderdoc/core/replay_proxy.h +++ b/renderdoc/core/replay_proxy.h @@ -194,9 +194,9 @@ public: if(m_Proxy) { EnsureTexCached(texid, sliceFace, mip); - if(texid == ResourceId() || m_ProxyTextureIds[texid] == ResourceId()) + if(texid == ResourceId() || m_ProxyTextures[texid] == ResourceId()) return false; - return m_Proxy->GetMinMax(m_ProxyTextureIds[texid], sliceFace, mip, sample, typeHint, minval, + return m_Proxy->GetMinMax(m_ProxyTextures[texid], sliceFace, mip, sample, typeHint, minval, maxval); } @@ -210,10 +210,10 @@ public: if(m_Proxy) { EnsureTexCached(texid, sliceFace, mip); - if(texid == ResourceId() || m_ProxyTextureIds[texid] == ResourceId()) + if(texid == ResourceId() || m_ProxyTextures[texid] == ResourceId()) return false; - return m_Proxy->GetHistogram(m_ProxyTextureIds[texid], sliceFace, mip, sample, typeHint, - minval, maxval, channels, histogram); + return m_Proxy->GetHistogram(m_ProxyTextures[texid], sliceFace, mip, sample, typeHint, minval, + maxval, channels, histogram); } return false; @@ -224,9 +224,9 @@ public: if(m_Proxy) { EnsureTexCached(cfg.texid, cfg.sliceFace, cfg.mip); - if(cfg.texid == ResourceId() || m_ProxyTextureIds[cfg.texid] == ResourceId()) + if(cfg.texid == ResourceId() || m_ProxyTextures[cfg.texid] == ResourceId()) return false; - cfg.texid = m_ProxyTextureIds[cfg.texid]; + cfg.texid = m_ProxyTextures[cfg.texid]; // due to OpenGL having origin bottom-left compared to the rest of the world, // we need to flip going in or out of GL. @@ -248,10 +248,10 @@ public: if(m_Proxy) { EnsureTexCached(texture, sliceFace, mip); - if(texture == ResourceId() || m_ProxyTextureIds[texture] == ResourceId()) + if(texture == ResourceId() || m_ProxyTextures[texture] == ResourceId()) return; - texture = m_ProxyTextureIds[texture]; + texture = m_ProxyTextures[texture]; // due to OpenGL having origin bottom-left compared to the rest of the world, // we need to flip going in or out of GL. @@ -371,13 +371,13 @@ public: if(m_Proxy) { EnsureTexCached(texid, 0, mip); - if(texid == ResourceId() || m_ProxyTextureIds[texid] == ResourceId()) + if(texid == ResourceId() || m_ProxyTextures[texid] == ResourceId()) return ResourceId(); - texid = m_ProxyTextureIds[texid]; + texid = m_ProxyTextures[texid]; ResourceId customResourceId = m_Proxy->ApplyCustomShader(shader, texid, mip, arrayIdx, sampleIdx, typeHint); m_LocalTextures.insert(customResourceId); - m_ProxyTextureIds[customResourceId] = customResourceId; + m_ProxyTextures[customResourceId] = customResourceId; return customResourceId; } @@ -420,9 +420,8 @@ public: vector &outvars, const vector &data); void GetBufferData(ResourceId buff, uint64_t offset, uint64_t len, vector &retData); - byte *GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip, bool forDiskSave, - FormatComponentType typeHint, bool resolve, bool forceRGBA8unorm, - float blackPoint, float whitePoint, size_t &dataSize); + byte *GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip, + const GetTextureDataParams ¶ms, size_t &dataSize); void InitPostVSBuffers(uint32_t eventID); void InitPostVSBuffers(const vector &passEvents); @@ -470,6 +469,7 @@ public: RDCERR("Calling proxy-render functions on a proxy serialiser"); } + bool IsTextureSupported(const ResourceFormat &format) { return true; } ResourceId CreateProxyBuffer(const FetchBuffer &templateBuf) { RDCERR("Calling proxy-render functions on a proxy serialiser"); @@ -485,6 +485,7 @@ private: bool SendReplayCommand(ReplayProxyPacket type); void EnsureTexCached(ResourceId texid, uint32_t arrayIdx, uint32_t mip); + void RemapProxyTextureIfNeeded(ResourceFormat &format, GetTextureDataParams ¶ms); void EnsureBufCached(ResourceId bufid); struct TextureCacheEntry @@ -504,7 +505,19 @@ private: }; set m_TextureProxyCache; set m_LocalTextures; - map m_ProxyTextureIds; + + struct ProxyTextureProperties + { + ResourceId id; + GetTextureDataParams params; + + ProxyTextureProperties() {} + // Create a proxy Id with the default get-data parameters. + ProxyTextureProperties(ResourceId proxyid) : id(proxyid) {} + operator ResourceId() const { return id; } + bool operator==(const ResourceId &other) const { return id == other; } + }; + map m_ProxyTextures; set m_BufferProxyCache; map m_ProxyBufferIds; diff --git a/renderdoc/driver/d3d11/d3d11_analyse.cpp b/renderdoc/driver/d3d11/d3d11_analyse.cpp index 8ba4b9f81..a283f5fed 100644 --- a/renderdoc/driver/d3d11/d3d11_analyse.cpp +++ b/renderdoc/driver/d3d11/d3d11_analyse.cpp @@ -2574,10 +2574,8 @@ void D3D11DebugManager::PickPixel(ResourceId texture, uint32_t x, uint32_t y, ui m_pImmediateContext->Unmap(m_DebugRender.PickPixelStageTex, 0); } -byte *D3D11DebugManager::GetTextureData(ResourceId id, uint32_t arrayIdx, uint32_t mip, - bool forDiskSave, FormatComponentType typeHint, - bool resolve, bool forceRGBA8unorm, float blackPoint, - float whitePoint, size_t &dataSize) +byte *D3D11DebugManager::GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip, + const GetTextureDataParams ¶ms, size_t &dataSize) { ID3D11Resource *dummyTex = NULL; @@ -2587,10 +2585,10 @@ byte *D3D11DebugManager::GetTextureData(ResourceId id, uint32_t arrayIdx, uint32 dataSize = 0; size_t bytesize = 0; - if(WrappedID3D11Texture1D::m_TextureList.find(id) != WrappedID3D11Texture1D::m_TextureList.end()) + if(WrappedID3D11Texture1D::m_TextureList.find(tex) != WrappedID3D11Texture1D::m_TextureList.end()) { WrappedID3D11Texture1D *wrapTex = - (WrappedID3D11Texture1D *)WrappedID3D11Texture1D::m_TextureList[id].m_Texture; + (WrappedID3D11Texture1D *)WrappedID3D11Texture1D::m_TextureList[tex].m_Texture; D3D11_TEXTURE1D_DESC desc = {0}; wrapTex->GetDesc(&desc); @@ -2607,8 +2605,10 @@ byte *D3D11DebugManager::GetTextureData(ResourceId id, uint32_t arrayIdx, uint32 if(mip >= mips || arrayIdx >= desc.ArraySize) return NULL; - if(forceRGBA8unorm) + if(params.remap) { + RDCASSERT(params.remap == eRemap_RGBA8); + desc.Format = IsSRGBFormat(desc.Format) ? DXGI_FORMAT_R8G8B8A8_UNORM_SRGB : DXGI_FORMAT_R8G8B8A8_UNORM; desc.ArraySize = 1; @@ -2628,8 +2628,10 @@ byte *D3D11DebugManager::GetTextureData(ResourceId id, uint32_t arrayIdx, uint32 bytesize = GetByteSize(desc.Width, 1, 1, desc.Format, mip); - if(forceRGBA8unorm) + if(params.remap) { + RDCASSERT(params.remap == eRemap_RGBA8); + subresource = mip; desc.CPUAccessFlags = 0; @@ -2686,11 +2688,11 @@ byte *D3D11DebugManager::GetTextureData(ResourceId id, uint32_t arrayIdx, uint32 texDisplay.sampleIdx = 0; texDisplay.CustomShader = ResourceId(); texDisplay.sliceFace = arrayIdx; - texDisplay.rangemin = blackPoint; - texDisplay.rangemax = whitePoint; + texDisplay.rangemin = params.blackPoint; + texDisplay.rangemax = params.whitePoint; texDisplay.scale = 1.0f; - texDisplay.texid = id; - texDisplay.typeHint = typeHint; + texDisplay.texid = tex; + texDisplay.typeHint = params.typeHint; texDisplay.rawoutput = false; texDisplay.offx = 0; texDisplay.offy = 0; @@ -2711,11 +2713,11 @@ byte *D3D11DebugManager::GetTextureData(ResourceId id, uint32_t arrayIdx, uint32 m_pImmediateContext->CopyResource(UNWRAP(WrappedID3D11Texture1D, d), wrapTex->GetReal()); } } - else if(WrappedID3D11Texture2D1::m_TextureList.find(id) != + else if(WrappedID3D11Texture2D1::m_TextureList.find(tex) != WrappedID3D11Texture2D1::m_TextureList.end()) { WrappedID3D11Texture2D1 *wrapTex = - (WrappedID3D11Texture2D1 *)WrappedID3D11Texture2D1::m_TextureList[id].m_Texture; + (WrappedID3D11Texture2D1 *)WrappedID3D11Texture2D1::m_TextureList[tex].m_Texture; D3D11_TEXTURE2D_DESC desc = {0}; wrapTex->GetDesc(&desc); @@ -2743,8 +2745,10 @@ byte *D3D11DebugManager::GetTextureData(ResourceId id, uint32_t arrayIdx, uint32 if(mip >= mips || arrayIdx >= desc.ArraySize) return NULL; - if(forceRGBA8unorm) + if(params.remap) { + RDCASSERT(params.remap == eRemap_RGBA8); + desc.Format = IsSRGBFormat(desc.Format) ? DXGI_FORMAT_R8G8B8A8_UNORM_SRGB : DXGI_FORMAT_R8G8B8A8_UNORM; desc.ArraySize = 1; @@ -2764,8 +2768,10 @@ byte *D3D11DebugManager::GetTextureData(ResourceId id, uint32_t arrayIdx, uint32 bytesize = GetByteSize(desc.Width, desc.Height, 1, desc.Format, mip); - if(forceRGBA8unorm) + if(params.remap) { + RDCASSERT(params.remap == eRemap_RGBA8); + subresource = mip; desc.CPUAccessFlags = 0; @@ -2820,14 +2826,14 @@ byte *D3D11DebugManager::GetTextureData(ResourceId id, uint32_t arrayIdx, uint32 texDisplay.overlay = eTexOverlay_None; texDisplay.FlipY = false; texDisplay.mip = mip; - texDisplay.sampleIdx = resolve ? ~0U : arrayIdx; + texDisplay.sampleIdx = params.resolve ? ~0U : arrayIdx; texDisplay.CustomShader = ResourceId(); texDisplay.sliceFace = arrayIdx; - texDisplay.rangemin = blackPoint; - texDisplay.rangemax = whitePoint; + texDisplay.rangemin = params.blackPoint; + texDisplay.rangemax = params.whitePoint; texDisplay.scale = 1.0f; - texDisplay.texid = id; - texDisplay.typeHint = typeHint; + texDisplay.texid = tex; + texDisplay.typeHint = params.typeHint; texDisplay.rawoutput = false; texDisplay.offx = 0; texDisplay.offy = 0; @@ -2843,7 +2849,7 @@ byte *D3D11DebugManager::GetTextureData(ResourceId id, uint32_t arrayIdx, uint32 SAFE_RELEASE(wrappedrtv); } - else if(wasms && resolve) + else if(wasms && params.resolve) { desc.Usage = D3D11_USAGE_DEFAULT; desc.CPUAccessFlags = 0; @@ -2875,11 +2881,11 @@ byte *D3D11DebugManager::GetTextureData(ResourceId id, uint32_t arrayIdx, uint32 m_pImmediateContext->CopyResource(UNWRAP(WrappedID3D11Texture2D1, d), wrapTex->GetReal()); } } - else if(WrappedID3D11Texture3D1::m_TextureList.find(id) != + else if(WrappedID3D11Texture3D1::m_TextureList.find(tex) != WrappedID3D11Texture3D1::m_TextureList.end()) { WrappedID3D11Texture3D1 *wrapTex = - (WrappedID3D11Texture3D1 *)WrappedID3D11Texture3D1::m_TextureList[id].m_Texture; + (WrappedID3D11Texture3D1 *)WrappedID3D11Texture3D1::m_TextureList[tex].m_Texture; D3D11_TEXTURE3D_DESC desc = {0}; wrapTex->GetDesc(&desc); @@ -2896,9 +2902,13 @@ byte *D3D11DebugManager::GetTextureData(ResourceId id, uint32_t arrayIdx, uint32 if(mip >= mips) return NULL; - if(forceRGBA8unorm) + if(params.remap) + { + RDCASSERT(params.remap == eRemap_RGBA8); + desc.Format = IsSRGBFormat(desc.Format) ? DXGI_FORMAT_R8G8B8A8_UNORM_SRGB : DXGI_FORMAT_R8G8B8A8_UNORM; + } subresource = mip; @@ -2914,8 +2924,10 @@ byte *D3D11DebugManager::GetTextureData(ResourceId id, uint32_t arrayIdx, uint32 bytesize = GetByteSize(desc.Width, desc.Height, desc.Depth, desc.Format, mip); - if(forceRGBA8unorm) + if(params.remap) { + RDCASSERT(params.remap == eRemap_RGBA8); + subresource = mip; desc.CPUAccessFlags = 0; @@ -2979,11 +2991,11 @@ byte *D3D11DebugManager::GetTextureData(ResourceId id, uint32_t arrayIdx, uint32 texDisplay.sampleIdx = 0; texDisplay.CustomShader = ResourceId(); texDisplay.sliceFace = i << mip; - texDisplay.rangemin = blackPoint; - texDisplay.rangemax = whitePoint; + texDisplay.rangemin = params.blackPoint; + texDisplay.rangemax = params.whitePoint; texDisplay.scale = 1.0f; - texDisplay.texid = id; - texDisplay.typeHint = typeHint; + texDisplay.texid = tex; + texDisplay.typeHint = params.typeHint; texDisplay.rawoutput = false; texDisplay.offx = 0; texDisplay.offy = 0; @@ -3006,7 +3018,7 @@ byte *D3D11DebugManager::GetTextureData(ResourceId id, uint32_t arrayIdx, uint32 } else { - RDCERR("Trying to get texture data for unknown ID %llu!", id); + RDCERR("Trying to get texture data for unknown ID %llu!", tex); dataSize = 0; return new byte[0]; } diff --git a/renderdoc/driver/d3d11/d3d11_debug.h b/renderdoc/driver/d3d11/d3d11_debug.h index 0ae3eca65..3f2007a85 100644 --- a/renderdoc/driver/d3d11/d3d11_debug.h +++ b/renderdoc/driver/d3d11/d3d11_debug.h @@ -94,6 +94,7 @@ struct D3D11PostVSData }; struct CopyPixelParams; +struct GetTextureDataParams; class D3D11DebugManager { @@ -127,9 +128,8 @@ public: void GetBufferData(ID3D11Buffer *buff, uint64_t offset, uint64_t length, vector &retData, bool unwrap); - byte *GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip, bool forDiskSave, - FormatComponentType typeHint, bool resolve, bool forceRGBA8unorm, - float blackPoint, float whitePoint, size_t &dataSize); + byte *GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip, + const GetTextureDataParams ¶ms, size_t &dataSize); void FillCBufferVariables(const vector &invars, vector &outvars, bool flattenVec4s, diff --git a/renderdoc/driver/d3d11/d3d11_replay.cpp b/renderdoc/driver/d3d11/d3d11_replay.cpp index f0f74b979..2ac23b8ac 100644 --- a/renderdoc/driver/d3d11/d3d11_replay.cpp +++ b/renderdoc/driver/d3d11/d3d11_replay.cpp @@ -1448,13 +1448,10 @@ void D3D11Replay::GetBufferData(ResourceId buff, uint64_t offset, uint64_t len, m_pDevice->GetDebugManager()->GetBufferData(buff, offset, len, retData); } -byte *D3D11Replay::GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip, bool forDiskSave, - FormatComponentType typeHint, bool resolve, bool forceRGBA8unorm, - float blackPoint, float whitePoint, size_t &dataSize) +byte *D3D11Replay::GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip, + const GetTextureDataParams ¶ms, size_t &dataSize) { - return m_pDevice->GetDebugManager()->GetTextureData(tex, arrayIdx, mip, forDiskSave, typeHint, - resolve, forceRGBA8unorm, blackPoint, - whitePoint, dataSize); + return m_pDevice->GetDebugManager()->GetTextureData(tex, arrayIdx, mip, params, dataSize); } void D3D11Replay::ReplaceResource(ResourceId from, ResourceId to) @@ -1845,6 +1842,11 @@ void D3D11Replay::SetProxyTextureData(ResourceId texid, uint32_t arrayIdx, uint3 } } +bool D3D11Replay::IsTextureSupported(const ResourceFormat &format) +{ + return MakeDXGIFormat(format) != DXGI_FORMAT_UNKNOWN; +} + ResourceId D3D11Replay::CreateProxyBuffer(const FetchBuffer &templateBuf) { ResourceId ret; diff --git a/renderdoc/driver/d3d11/d3d11_replay.h b/renderdoc/driver/d3d11/d3d11_replay.h index 7726a7620..ea2fddc62 100644 --- a/renderdoc/driver/d3d11/d3d11_replay.h +++ b/renderdoc/driver/d3d11/d3d11_replay.h @@ -106,9 +106,8 @@ public: MeshFormat GetPostVSBuffers(uint32_t eventID, uint32_t instID, MeshDataStage stage); void GetBufferData(ResourceId buff, uint64_t offset, uint64_t len, vector &retData); - byte *GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip, bool forDiskSave, - FormatComponentType typeHint, bool resolve, bool forceRGBA8unorm, - float blackPoint, float whitePoint, size_t &dataSize); + byte *GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip, + const GetTextureDataParams ¶ms, size_t &dataSize); void BuildTargetShader(string source, string entry, const uint32_t compileFlags, ShaderStageType type, ResourceId *id, string *errors); @@ -122,6 +121,7 @@ public: ResourceId CreateProxyTexture(const FetchTexture &templateTex); void SetProxyTextureData(ResourceId texid, uint32_t arrayIdx, uint32_t mip, byte *data, size_t dataSize); + bool IsTextureSupported(const ResourceFormat &format); ResourceId CreateProxyBuffer(const FetchBuffer &templateBuf); void SetProxyBufferData(ResourceId bufid, byte *data, size_t dataSize); diff --git a/renderdoc/driver/d3d12/d3d12_replay.cpp b/renderdoc/driver/d3d12/d3d12_replay.cpp index 28de22d31..64b3ce21e 100644 --- a/renderdoc/driver/d3d12/d3d12_replay.cpp +++ b/renderdoc/driver/d3d12/d3d12_replay.cpp @@ -1271,9 +1271,8 @@ MeshFormat D3D12Replay::GetPostVSBuffers(uint32_t eventID, uint32_t instID, Mesh return MeshFormat(); } -byte *D3D12Replay::GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip, bool forDiskSave, - FormatComponentType typeHint, bool resolve, bool forceRGBA8unorm, - float blackPoint, float whitePoint, size_t &dataSize) +byte *D3D12Replay::GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip, + const GetTextureDataParams ¶ms, size_t &dataSize) { dataSize = 0; return NULL; @@ -1455,6 +1454,11 @@ void D3D12Replay::SetProxyTextureData(ResourceId texid, uint32_t arrayIdx, uint3 { } +bool D3D12Replay::IsTextureSupported(const ResourceFormat &format) +{ + return MakeDXGIFormat(format) != DXGI_FORMAT_UNKNOWN; +} + ResourceId D3D12Replay::CreateProxyBuffer(const FetchBuffer &templateBuf) { return ResourceId(); diff --git a/renderdoc/driver/d3d12/d3d12_replay.h b/renderdoc/driver/d3d12/d3d12_replay.h index 88938101d..aa269a85c 100644 --- a/renderdoc/driver/d3d12/d3d12_replay.h +++ b/renderdoc/driver/d3d12/d3d12_replay.h @@ -104,9 +104,8 @@ public: MeshFormat GetPostVSBuffers(uint32_t eventID, uint32_t instID, MeshDataStage stage); void GetBufferData(ResourceId buff, uint64_t offset, uint64_t len, vector &retData); - byte *GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip, bool forDiskSave, - FormatComponentType typeHint, bool resolve, bool forceRGBA8unorm, - float blackPoint, float whitePoint, size_t &dataSize); + byte *GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip, + const GetTextureDataParams ¶ms, size_t &dataSize); void BuildTargetShader(string source, string entry, const uint32_t compileFlags, ShaderStageType type, ResourceId *id, string *errors); @@ -120,6 +119,7 @@ public: ResourceId CreateProxyTexture(const FetchTexture &templateTex); void SetProxyTextureData(ResourceId texid, uint32_t arrayIdx, uint32_t mip, byte *data, size_t dataSize); + bool IsTextureSupported(const ResourceFormat &format); ResourceId CreateProxyBuffer(const FetchBuffer &templateBuf); void SetProxyBufferData(ResourceId bufid, byte *data, size_t dataSize); diff --git a/renderdoc/driver/dxgi/dxgi_common.cpp b/renderdoc/driver/dxgi/dxgi_common.cpp index 75f0cb20d..1321c05f8 100644 --- a/renderdoc/driver/dxgi/dxgi_common.cpp +++ b/renderdoc/driver/dxgi/dxgi_common.cpp @@ -1389,9 +1389,11 @@ DXGI_FORMAT MakeDXGIFormat(ResourceFormat fmt) RDCERR("Video format not unambiguously encoded"); ret = DXGI_FORMAT_AYUV; break; - case eSpecial_S8: RDCERR("D3D has no stencil-only format"); break; - case eSpecial_D16S8: RDCERR("D3D has no D16S8 format"); break; - default: RDCERR("Unrecognised/unsupported special format %u", fmt.specialFormat); break; + case eSpecial_S8: // D3D has no stencil-only format + case eSpecial_D16S8: // D3D has no D16S8 format + default: + // Return unknown to choose texture remap + break; } } else if(fmt.compCount == 4) @@ -1412,8 +1414,14 @@ DXGI_FORMAT MakeDXGIFormat(ResourceFormat fmt) { if(fmt.compByteWidth == 4) ret = DXGI_FORMAT_R32G32B32_TYPELESS; - // else if(fmt.compByteWidth == 2) ret = DXGI_FORMAT_R16G16B16_TYPELESS; // format doesn't exist - // else if(fmt.compByteWidth == 1) ret = DXGI_FORMAT_R8G8B8_TYPELESS; // format doesn't exist + else if(fmt.compByteWidth == 2) + { + // DXGI_FORMAT_R16G16B16_TYPELESS doesn't exist, return unknown to choose texture remap + } + else if(fmt.compByteWidth == 1) + { + // DXGI_FORMAT_R8G8B8_TYPELESS doesn't exist + } else RDCERR("Unrecognised 3-component byte width: %d", fmt.compByteWidth); } @@ -1464,9 +1472,6 @@ DXGI_FORMAT MakeDXGIFormat(ResourceFormat fmt) if(fmt.srgbCorrected) ret = GetSRGBFormat(ret); - if(ret == DXGI_FORMAT_UNKNOWN) - RDCERR("No known DXGI_FORMAT corresponding to resource format!"); - return ret; } diff --git a/renderdoc/driver/gl/gl_replay.cpp b/renderdoc/driver/gl/gl_replay.cpp index 8a6d8cebf..16842c6db 100644 --- a/renderdoc/driver/gl/gl_replay.cpp +++ b/renderdoc/driver/gl/gl_replay.cpp @@ -2160,9 +2160,8 @@ void GLReplay::FillCBufferVariables(ResourceId shader, string entryPoint, uint32 outvars, data); } -byte *GLReplay::GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip, bool forDiskSave, - FormatComponentType typeHint, bool resolve, bool forceRGBA8unorm, - float blackPoint, float whitePoint, size_t &dataSize) +byte *GLReplay::GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip, + const GetTextureDataParams ¶ms, size_t &dataSize) { WrappedOpenGL &gl = *m_pDriver; @@ -2219,8 +2218,10 @@ byte *GLReplay::GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip, arraysize = texDetails.depth; } - if(forceRGBA8unorm && intFormat != eGL_RGBA8 && intFormat != eGL_SRGB8_ALPHA8) + if(params.remap && intFormat != eGL_RGBA8 && intFormat != eGL_SRGB8_ALPHA8) { + RDCASSERT(params.remap == eRemap_RGBA8); + MakeCurrentReplayContext(m_DebugCtx); GLenum finalFormat = IsSRGBFormat(intFormat) ? eGL_SRGB8_ALPHA8 : eGL_RGBA8; @@ -2273,8 +2274,8 @@ byte *GLReplay::GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip, texDisplay.sampleIdx = ~0U; texDisplay.CustomShader = ResourceId(); texDisplay.sliceFace = arrayIdx; - texDisplay.rangemin = blackPoint; - texDisplay.rangemax = whitePoint; + texDisplay.rangemin = params.blackPoint; + texDisplay.rangemax = params.whitePoint; texDisplay.scale = 1.0f; texDisplay.texid = tex; texDisplay.typeHint = eCompType_None; @@ -2308,7 +2309,7 @@ byte *GLReplay::GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip, gl.glDeleteFramebuffers(1, &fbo); } - else if(resolve && samples > 1) + else if(params.resolve && samples > 1) { MakeCurrentReplayContext(m_DebugCtx); @@ -2437,7 +2438,7 @@ byte *GLReplay::GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip, // order is consistent (and we just need to take care to apply an extra vertical flip // for display when proxying). - if(forDiskSave) + if(params.forDiskSave) { // need to vertically flip the image now to get conventional row ordering // we either do this when copying out the slice of interest, or just @@ -2978,6 +2979,11 @@ void GLReplay::SetProxyTextureData(ResourceId texid, uint32_t arrayIdx, uint32_t } } +bool GLReplay::IsTextureSupported(const ResourceFormat &format) +{ + return true; +} + ResourceId GLReplay::CreateProxyBuffer(const FetchBuffer &templateBuf) { WrappedOpenGL &gl = *m_pDriver; diff --git a/renderdoc/driver/gl/gl_replay.h b/renderdoc/driver/gl/gl_replay.h index 9f9196aea..5ed78a0a5 100644 --- a/renderdoc/driver/gl/gl_replay.h +++ b/renderdoc/driver/gl/gl_replay.h @@ -151,9 +151,8 @@ public: MeshFormat GetPostVSBuffers(uint32_t eventID, uint32_t instID, MeshDataStage stage); void GetBufferData(ResourceId buff, uint64_t offset, uint64_t len, vector &ret); - byte *GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip, bool forDiskSave, - FormatComponentType typeHint, bool resolve, bool forceRGBA8unorm, - float blackPoint, float whitePoint, size_t &dataSize); + byte *GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip, + const GetTextureDataParams ¶ms, size_t &dataSize); void ReplaceResource(ResourceId from, ResourceId to); void RemoveReplacement(ResourceId id); @@ -200,6 +199,7 @@ public: ResourceId CreateProxyTexture(const FetchTexture &templateTex); void SetProxyTextureData(ResourceId texid, uint32_t arrayIdx, uint32_t mip, byte *data, size_t dataSize); + bool IsTextureSupported(const ResourceFormat &format); ResourceId CreateProxyBuffer(const FetchBuffer &templateBuf); void SetProxyBufferData(ResourceId bufid, byte *data, size_t dataSize); diff --git a/renderdoc/driver/vulkan/vk_replay.cpp b/renderdoc/driver/vulkan/vk_replay.cpp index 644f5cd71..a3f0619f1 100644 --- a/renderdoc/driver/vulkan/vk_replay.cpp +++ b/renderdoc/driver/vulkan/vk_replay.cpp @@ -4571,9 +4571,8 @@ MeshFormat VulkanReplay::GetPostVSBuffers(uint32_t eventID, uint32_t instID, Mes return GetDebugManager()->GetPostVSBuffers(eventID, instID, stage); } -byte *VulkanReplay::GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip, bool forDiskSave, - FormatComponentType typeHint, bool resolve, bool forceRGBA8unorm, - float blackPoint, float whitePoint, size_t &dataSize) +byte *VulkanReplay::GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip, + const GetTextureDataParams ¶ms, size_t &dataSize) { bool wasms = false; @@ -4640,7 +4639,7 @@ byte *VulkanReplay::GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t m wasms = true; } - if(forceRGBA8unorm) + if(params.remap) { // force readback texture to RGBA8 unorm imCreateInfo.format = @@ -4752,11 +4751,11 @@ byte *VulkanReplay::GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t m texDisplay.FlipY = false; texDisplay.mip = mip; texDisplay.sampleIdx = - imCreateInfo.imageType == VK_IMAGE_TYPE_3D ? 0 : (resolve ? ~0U : arrayIdx); + imCreateInfo.imageType == VK_IMAGE_TYPE_3D ? 0 : (params.resolve ? ~0U : arrayIdx); texDisplay.CustomShader = ResourceId(); texDisplay.sliceFace = imCreateInfo.imageType == VK_IMAGE_TYPE_3D ? i : arrayIdx; - texDisplay.rangemin = blackPoint; - texDisplay.rangemax = whitePoint; + texDisplay.rangemin = params.blackPoint; + texDisplay.rangemax = params.whitePoint; texDisplay.scale = 1.0f; texDisplay.texid = tex; texDisplay.typeHint = eCompType_None; @@ -4840,7 +4839,7 @@ byte *VulkanReplay::GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t m isDepth = false; isStencil = false; } - else if(wasms && resolve) + else if(wasms && params.resolve) { // force to 1 array slice, 1 mip imCreateInfo.arrayLayers = 1; @@ -5546,6 +5545,11 @@ void VulkanReplay::SetProxyTextureData(ResourceId texid, uint32_t arrayIdx, uint VULKANNOTIMP("SetProxyTextureData"); } +bool VulkanReplay::IsTextureSupported(const ResourceFormat &format) +{ + return true; +} + ResourceId VulkanReplay::CreateProxyBuffer(const FetchBuffer &templateBuf) { VULKANNOTIMP("CreateProxyBuffer"); diff --git a/renderdoc/driver/vulkan/vk_replay.h b/renderdoc/driver/vulkan/vk_replay.h index 7f51cb6ea..1ef86cf47 100644 --- a/renderdoc/driver/vulkan/vk_replay.h +++ b/renderdoc/driver/vulkan/vk_replay.h @@ -186,9 +186,8 @@ public: MeshFormat GetPostVSBuffers(uint32_t eventID, uint32_t instID, MeshDataStage stage); void GetBufferData(ResourceId buff, uint64_t offset, uint64_t len, vector &retData); - byte *GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip, bool forDiskSave, - FormatComponentType typeHint, bool resolve, bool forceRGBA8unorm, - float blackPoint, float whitePoint, size_t &dataSize); + byte *GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip, + const GetTextureDataParams ¶ms, size_t &dataSize); void ReplaceResource(ResourceId from, ResourceId to); void RemoveReplacement(ResourceId id); @@ -231,6 +230,7 @@ public: ResourceId CreateProxyTexture(const FetchTexture &templateTex); void SetProxyTextureData(ResourceId texid, uint32_t arrayIdx, uint32_t mip, byte *data, size_t dataSize); + bool IsTextureSupported(const ResourceFormat &format); ResourceId CreateProxyBuffer(const FetchBuffer &templateBuf); void SetProxyBufferData(ResourceId bufid, byte *data, size_t dataSize); diff --git a/renderdoc/replay/replay_driver.h b/renderdoc/replay/replay_driver.h index e4ffa9455..f2f76645f 100644 --- a/renderdoc/replay/replay_driver.h +++ b/renderdoc/replay/replay_driver.h @@ -37,6 +37,35 @@ struct FetchFrameRecord rdctype::array drawcallList; }; +enum RemapTextureEnum +{ + eRemap_None, + eRemap_RGBA8, + eRemap_RGBA16, + eRemap_RGBA32, + eRemap_D32S8 +}; + +struct GetTextureDataParams +{ + bool forDiskSave; + FormatComponentType typeHint; + bool resolve; + RemapTextureEnum remap; + float blackPoint; + float whitePoint; + + GetTextureDataParams() + : forDiskSave(false), + typeHint(eCompType_None), + resolve(false), + remap(eRemap_None), + blackPoint(0.0f), + whitePoint(0.0f) + { + } +}; + // these two interfaces define what an API driver implementation must provide // to the replay. At minimum it must implement IRemoteDriver which contains // all of the functionality that cannot be achieved elsewhere. An IReplayDriver @@ -88,9 +117,8 @@ public: virtual void GetBufferData(ResourceId buff, uint64_t offset, uint64_t len, vector &retData) = 0; - virtual byte *GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip, bool forDiskSave, - FormatComponentType typeHint, bool resolve, bool forceRGBA8unorm, - float blackPoint, float whitePoint, size_t &dataSize) = 0; + virtual byte *GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip, + const GetTextureDataParams ¶ms, size_t &dataSize) = 0; virtual void BuildTargetShader(string source, string entry, const uint32_t compileFlags, ShaderStageType type, ResourceId *id, string *errors) = 0; @@ -155,6 +183,7 @@ public: virtual ResourceId CreateProxyTexture(const FetchTexture &templateTex) = 0; virtual void SetProxyTextureData(ResourceId texid, uint32_t arrayIdx, uint32_t mip, byte *data, size_t dataSize) = 0; + virtual bool IsTextureSupported(const ResourceFormat &format) = 0; virtual ResourceId CreateProxyBuffer(const FetchBuffer &templateBuf) = 0; virtual void SetProxyBufferData(ResourceId bufid, byte *data, size_t dataSize) = 0; diff --git a/renderdoc/replay/replay_renderer.cpp b/renderdoc/replay/replay_renderer.cpp index f5ae9cb4c..523ac1997 100644 --- a/renderdoc/replay/replay_renderer.cpp +++ b/renderdoc/replay/replay_renderer.cpp @@ -469,8 +469,7 @@ bool ReplayRenderer::GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t } size_t sz = 0; - byte *bytes = m_pDevice->GetTextureData(liveId, arrayIdx, mip, false, eCompType_None, false, - false, 0.0f, 0.0f, sz); + byte *bytes = m_pDevice->GetTextureData(liveId, arrayIdx, mip, GetTextureDataParams(), sz); if(sz == 0 || bytes == NULL) create_array_uninit(*data, 0); @@ -729,10 +728,16 @@ bool ReplayRenderer::SaveTexture(const TextureSave &saveData, const char *path) { uint32_t mip = m + mipOffset; + GetTextureDataParams params; + params.forDiskSave = true; + params.typeHint = sd.typeHint; + params.resolve = resolveSamples; + params.remap = downcast ? eRemap_RGBA8 : eRemap_None; + params.blackPoint = sd.comp.blackPoint; + params.whitePoint = sd.comp.whitePoint; + size_t datasize = 0; - byte *bytes = - m_pDevice->GetTextureData(liveid, slice, mip, true, sd.typeHint, resolveSamples, downcast, - sd.comp.blackPoint, sd.comp.whitePoint, datasize); + byte *bytes = m_pDevice->GetTextureData(liveid, slice, mip, params, datasize); if(bytes == NULL) {