diff --git a/renderdoc/driver/d3d11/d3d11_context1_wrap.cpp b/renderdoc/driver/d3d11/d3d11_context1_wrap.cpp index 5dbf90b37..40765a110 100644 --- a/renderdoc/driver/d3d11/d3d11_context1_wrap.cpp +++ b/renderdoc/driver/d3d11/d3d11_context1_wrap.cpp @@ -303,7 +303,7 @@ bool WrappedID3D11DeviceContext::Serialise_UpdateSubresource1( subHeight = RDCMAX(1U, desc.Height >> mipLevel); } - UINT SourceRowPitch = GetByteSize(subWidth, 1, 1, fmt, 0); + UINT SourceRowPitch = GetRowPitch(subWidth, fmt, 0); UINT SourceDepthPitch = GetByteSize(subWidth, subHeight, 1, fmt, 0); if(IsReplayingAndReading() && m_CurEventID > 0) diff --git a/renderdoc/driver/d3d11/d3d11_context_wrap.cpp b/renderdoc/driver/d3d11/d3d11_context_wrap.cpp index 0e34a7637..3858788d1 100644 --- a/renderdoc/driver/d3d11/d3d11_context_wrap.cpp +++ b/renderdoc/driver/d3d11/d3d11_context_wrap.cpp @@ -6079,8 +6079,8 @@ void WrappedID3D11DeviceContext::UpdateSubresource(ID3D11Resource *pDstResource, UINT boxTop = pDstBox ? pDstBox->top : 0; - UINT DstRowPitch = GetByteSize(subWidth, 1, 1, fmt, 0); - UINT DstBoxRowPitch = GetByteSize(boxWidth, 1, 1, fmt, 0); + UINT DstRowPitch = GetRowPitch(subWidth, fmt, 0); + UINT DstBoxRowPitch = GetRowPitch(boxWidth, fmt, 0); UINT DstSlicePitch = GetByteSize(subWidth, subHeight, 1, fmt, 0); // for block formats, rows are in blocks (so height is squished essentially) @@ -7192,7 +7192,7 @@ void MapIntercept::Init(ID3D11Texture1D *tex, UINT sub, void *appMemory) if(IsYUVPlanarFormat(fmt)) numRows = GetYUVNumRows(fmt, numRows); - app.RowPitch = GetByteSize(width, 1, 1, fmt, mip); + app.RowPitch = GetRowPitch(width, fmt, mip); app.DepthPitch = GetByteSize(width, height, 1, fmt, mip); if(d3d.DepthPitch == 0) @@ -7227,7 +7227,7 @@ void MapIntercept::Init(ID3D11Texture2D *tex, UINT sub, void *appMemory) if(IsYUVPlanarFormat(fmt)) numRows = GetYUVNumRows(fmt, numRows); - app.RowPitch = GetByteSize(width, 1, 1, fmt, mip); + app.RowPitch = GetRowPitch(width, fmt, mip); app.DepthPitch = GetByteSize(width, height, 1, fmt, mip); if(d3d.DepthPitch == 0) @@ -7261,7 +7261,7 @@ void MapIntercept::Init(ID3D11Texture3D *tex, UINT sub, void *appMemory) if(IsYUVPlanarFormat(fmt)) numRows = GetYUVNumRows(fmt, numRows); - app.RowPitch = GetByteSize(width, 1, 1, fmt, mip); + app.RowPitch = GetRowPitch(width, fmt, mip); app.DepthPitch = GetByteSize(width, height, 1, fmt, mip); } diff --git a/renderdoc/driver/d3d11/d3d11_device_wrap.cpp b/renderdoc/driver/d3d11/d3d11_device_wrap.cpp index 90b307d7d..382f4ddee 100644 --- a/renderdoc/driver/d3d11/d3d11_device_wrap.cpp +++ b/renderdoc/driver/d3d11/d3d11_device_wrap.cpp @@ -350,7 +350,7 @@ std::vector WrappedID3D11Device::Serialise_CreateTexture SubresourceContents = NULL; // calculate tightly packed pitches - descs[i].SysMemPitch = GetByteSize(w, 1, 1, fmt, mip); + descs[i].SysMemPitch = GetRowPitch(w, fmt, mip); descs[i].SysMemSlicePitch = GetByteSize(w, h, 1, fmt, mip); } } diff --git a/renderdoc/driver/d3d11/d3d11_initstate.cpp b/renderdoc/driver/d3d11/d3d11_initstate.cpp index 410b8b75f..c467ab797 100644 --- a/renderdoc/driver/d3d11/d3d11_initstate.cpp +++ b/renderdoc/driver/d3d11/d3d11_initstate.cpp @@ -301,7 +301,7 @@ uint32_t WrappedID3D11Device::GetSize_InitialState(ResourceId id, ID3D11DeviceCh { UINT mip = GetMipForSubresource(tex, sub); - const UINT RowPitch = GetByteSize(desc.Width, 1, 1, desc.Format, mip); + const UINT RowPitch = GetRowPitch(desc.Width, desc.Format, mip); ret += RowPitch; ret += (uint32_t)WriteSerialiser::GetChunkAlignment(); @@ -760,7 +760,7 @@ bool WrappedID3D11Device::Serialise_InitialState(SerialiserType &ser, ResourceId // use the RowPitch provided when we mapped in the first place, since we read the whole // buffer including padding subData[sub].SysMemPitch = RowPitch; - subData[sub].SysMemSlicePitch = ContentsLength; + subData[sub].SysMemSlicePitch = RowPitch * numRows; } } diff --git a/renderdoc/driver/dxgi/dxgi_common.cpp b/renderdoc/driver/dxgi/dxgi_common.cpp index fb6a7b8ef..0ec5e8e4a 100644 --- a/renderdoc/driver/dxgi/dxgi_common.cpp +++ b/renderdoc/driver/dxgi/dxgi_common.cpp @@ -311,6 +311,99 @@ UINT GetByteSize(int Width, int Height, int Depth, DXGI_FORMAT Format, int mip) return ret; } +UINT GetRowPitch(int Width, DXGI_FORMAT Format, int mip) +{ + // only YUV formats can have different rowpitch to their actual width + if(!IsYUVFormat(Format)) + return GetByteSize(Width, 1, 1, Format, mip); + + UINT ret = RDCMAX(Width >> mip, 1); + + switch(Format) + { + case DXGI_FORMAT_AYUV: + // 4:4:4 lossless packed, 8-bit. Equivalent size to R8G8B8A8 + ret *= 4; + break; + case DXGI_FORMAT_Y410: + // 4:4:4 lossless packed. Equivalent size to R10G10B10A2, unlike most 10-bit/16-bit formats is + // not equivalent to the 16-bit format. + ret *= 4; + break; + case DXGI_FORMAT_Y416: + // 4:4:4 lossless packed. Equivalent size to R16G16B16A16 + ret *= 8; + break; + case DXGI_FORMAT_NV12: + // 4:2:0 planar. Since we can assume even width and height, resulting row pitch is 1 byte per + // pixel - 1 byte luma each, and half subsampled chroma U/V in 1 byte total per pixel. + break; + case DXGI_FORMAT_P010: + // 10-bit formats are stored identically to 16-bit formats + // deliberate fallthrough + case DXGI_FORMAT_P016: + // Similar to NV12 but 16-bit elements + ret *= 2; + break; + case DXGI_FORMAT_420_OPAQUE: + // same size as NV12 - planar 4:2:0 but opaque layout + break; + case DXGI_FORMAT_YUY2: + // 4:2:2 packed 8-bit, so 1 byte per pixel for luma and 1 byte per pixel for chroma (2 chroma + // samples, with 50% subsampling = 1 byte per pixel) + ret *= 2; + break; + case DXGI_FORMAT_Y210: + // 10-bit formats are stored identically to 16-bit formats + // deliberate fallthrough + case DXGI_FORMAT_Y216: + // 4:2:2 packed 16-bit + ret *= 4; + break; + case DXGI_FORMAT_NV11: + // similar to NV12 - planar 4:1:1 4 horizontal downsampling but no vertical downsampling. For + // row pitch calculation amounts to the same result. + ret = ret; + break; + case DXGI_FORMAT_AI44: + // special format, 1 byte per pixel, palletised values in 4 most significant bits, alpha in 4 + // least significant bits. + // deliberate fallthrough + case DXGI_FORMAT_IA44: + // same as above but swapped MSB/LSB + break; + case DXGI_FORMAT_P8: + // 8 bits of palletised data + break; + case DXGI_FORMAT_A8P8: + // 8 bits palletised data, 8 bits alpha data. Seems to be packed (no indication in docs of + // planar) + ret *= 2; + break; + case DXGI_FORMAT_P208: + // 4:2:2 planar 8-bit. 1 byte per pixel of luma, then separately 1 byte per pixel of chroma. + // Identical pitch to 4:2:0, just more rows in second plane + break; + case DXGI_FORMAT_V208: + // unclear, seems to be packed 4:4:0 8-bit. Thus 1 byte per pixel for luma, 2 chroma samples + // every 2 rows = 1 byte per pixel for chroma + ret *= 2; + break; + case DXGI_FORMAT_V408: + // unclear, seems to be packed 4:4:4 8-bit + ret *= 4; + break; + + case DXGI_FORMAT_UNKNOWN: + RDCERR("Getting row pitch of unknown DXGI format"); + ret = 0; + break; + default: RDCERR("Unrecognised DXGI Format: %d", Format); break; + } + + return ret; +} + bool IsBlockFormat(DXGI_FORMAT f) { switch(f) diff --git a/renderdoc/driver/dxgi/dxgi_common.h b/renderdoc/driver/dxgi/dxgi_common.h index 996afd442..533c3764a 100644 --- a/renderdoc/driver/dxgi/dxgi_common.h +++ b/renderdoc/driver/dxgi/dxgi_common.h @@ -32,6 +32,7 @@ ResourceFormat MakeResourceFormat(DXGI_FORMAT fmt); DXGI_FORMAT MakeDXGIFormat(ResourceFormat fmt); UINT GetByteSize(int Width, int Height, int Depth, DXGI_FORMAT Format, int mip); +UINT GetRowPitch(int Width, DXGI_FORMAT Format, int mip); DXGI_FORMAT GetTypelessFormat(DXGI_FORMAT f); DXGI_FORMAT GetTypedFormat(DXGI_FORMAT f);