Remap texture formats across different APIs.

For example ASTC/ETC2 textures in Vulkan need to be forced to RGBA8 to be
displayed by D3D11.

IReplayDriver has virtual method IsTextureFormatSupported(ResourceFormat)
so each API can decide if a format should be converted.

Parameters to GetTextureData() are moved to a struct, to save any
non-default behaviour needed for fetching texture data into the proxy.

MakeDXGIFormat now returns DXGI_FORMAT_UNKNOWN for unsupported formats
instead of asserting. We use this to determine whether to remap.
This commit is contained in:
Michael Rennie
2016-09-28 11:47:10 +01:00
committed by baldurk
parent bfcfcd37b5
commit 5d23e39994
16 changed files with 279 additions and 127 deletions
+4 -6
View File
@@ -138,12 +138,10 @@ public:
}
vector<ResourceId> 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 &params, 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");
+92 -18
View File
@@ -1707,6 +1707,76 @@ bool ReplayProxy::SendReplayCommand(ReplayProxyPacket type)
return true;
}
template <>
string ToStrHelper<false, RemapTextureEnum>::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 &params)
{
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)];
+29 -16
View File
@@ -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<ShaderVariable> &outvars, const vector<byte> &data);
void GetBufferData(ResourceId buff, uint64_t offset, uint64_t len, vector<byte> &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 &params, size_t &dataSize);
void InitPostVSBuffers(uint32_t eventID);
void InitPostVSBuffers(const vector<uint32_t> &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 &params);
void EnsureBufCached(ResourceId bufid);
struct TextureCacheEntry
@@ -504,7 +505,19 @@ private:
};
set<TextureCacheEntry> m_TextureProxyCache;
set<ResourceId> m_LocalTextures;
map<ResourceId, ResourceId> 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<ResourceId, ProxyTextureProperties> m_ProxyTextures;
set<ResourceId> m_BufferProxyCache;
map<ResourceId, ResourceId> m_ProxyBufferIds;
+43 -31
View File
@@ -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 &params, 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];
}
+3 -3
View File
@@ -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<byte> &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 &params, size_t &dataSize);
void FillCBufferVariables(const vector<DXBC::CBufferVariable> &invars,
vector<ShaderVariable> &outvars, bool flattenVec4s,
+8 -6
View File
@@ -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 &params, 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;
+3 -3
View File
@@ -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<byte> &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 &params, 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);
+7 -3
View File
@@ -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 &params, 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();
+3 -3
View File
@@ -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<byte> &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 &params, 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);
+13 -8
View File
@@ -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;
}
+14 -8
View File
@@ -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 &params, 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;
+3 -3
View File
@@ -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<byte> &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 &params, 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);
+12 -8
View File
@@ -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 &params, 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");
+3 -3
View File
@@ -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<byte> &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 &params, 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);
+32 -3
View File
@@ -37,6 +37,35 @@ struct FetchFrameRecord
rdctype::array<FetchDrawcall> 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<byte> &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 &params, 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;
+10 -5
View File
@@ -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)
{