Standardise layout of packed texture formats on disk/network

* We preserve each API's interpretation of bit order for packed formats like
  RGBA4 or R5G6B5 when displaying the raw data in the UI, but when we need to
  proxy it or save to disk, we always transform to D3D's order as standard.
* This allows us to proxy them reliably because we always have a standard bit
  order and APIs that need a different order transform when fetching data to the
  standard format, or setting proxy data from the standard format.
This commit is contained in:
baldurk
2020-05-18 11:04:06 +01:00
parent 5eb80370fd
commit f622ac36d6
17 changed files with 279 additions and 71 deletions
+8
View File
@@ -203,6 +203,14 @@ struct ResourceFormat
)");
DOCUMENT(R"(:return: ``True`` if the components are to be read in ``BGRA`` order.
.. note::
The convention is that components are in RGBA order. Whether that means first byte to last byte,
or in bit-packed formats red in the lowest bits.
With BGRA order this means blue is in the first byte/lowest bits, but alpha is still always
expected in the last byte/uppermost bits.
:rtype: ``bool``
)");
bool BGRAOrder() const { return (flags & ResourceFormat_BGRA) != 0; }
+4 -4
View File
@@ -1029,17 +1029,17 @@ void RenderDoc::ResamplePixels(const FramePixels &in, RDCThumb &out)
{
uint16_t *src565 = (uint16_t *)src;
Vec3f unorm = ConvertFromB5G6R5(*src565);
dst[0] = (byte)(unorm.z * 255.0f);
dst[0] = (byte)(unorm.x * 255.0f);
dst[1] = (byte)(unorm.y * 255.0f);
dst[2] = (byte)(unorm.x * 255.0f);
dst[2] = (byte)(unorm.z * 255.0f);
}
else if(in.buf5551)
{
uint16_t *src5551 = (uint16_t *)src;
Vec4f unorm = ConvertFromB5G5R5A1(*src5551);
dst[0] = (byte)(unorm.z * 255.0f);
dst[0] = (byte)(unorm.x * 255.0f);
dst[1] = (byte)(unorm.y * 255.0f);
dst[2] = (byte)(unorm.x * 255.0f);
dst[2] = (byte)(unorm.z * 255.0f);
}
else if(in.bgra)
{
+1
View File
@@ -2389,6 +2389,7 @@ void ReplayProxy::EnsureTexCached(ResourceId &texid, CompType &typeCast, const S
GetTextureDataParams params = proxy.params;
params.typeCast = typeCast;
params.standardLayout = true;
#if ENABLED(TRANSFER_RESOURCE_CONTENTS_DELTAS)
CacheTextureData(texid, s, params);
-10
View File
@@ -3641,16 +3641,6 @@ void D3D11Replay::SetProxyTextureData(ResourceId texid, const Subresource &sub,
bool D3D11Replay::IsTextureSupported(const TextureDescription &tex)
{
// these formats are inconsistently laid out between APIs, always remap
switch(tex.format.type)
{
case ResourceFormatType::R4G4:
case ResourceFormatType::R4G4B4A4:
case ResourceFormatType::R5G6B5:
case ResourceFormatType::R5G5B5A1: return false;
default: break;
}
DXGI_FORMAT f = MakeDXGIFormat(tex.format);
if(f == DXGI_FORMAT_UNKNOWN)
+21 -3
View File
@@ -2039,11 +2039,13 @@ ResourceFormat MakeResourceFormat(GLenum target, GLenum fmt)
ret.type = ResourceFormatType::R5G6B5;
ret.compType = CompType::UNorm;
ret.compCount = 3;
ret.SetBGRAOrder(true);
break;
case eGL_RGB5_A1:
ret.type = ResourceFormatType::R5G5B5A1;
ret.compType = CompType::UNorm;
ret.compCount = 4;
ret.SetBGRAOrder(true);
break;
case eGL_RGB9_E5:
ret.type = ResourceFormatType::R9G9B9E5;
@@ -2054,6 +2056,7 @@ ResourceFormat MakeResourceFormat(GLenum target, GLenum fmt)
ret.type = ResourceFormatType::R4G4B4A4;
ret.compType = CompType::UNorm;
ret.compCount = 4;
ret.SetBGRAOrder(true);
break;
case eGL_RGB10_A2:
case eGL_RGB10_A2UI:
@@ -2268,10 +2271,25 @@ GLenum MakeGLFormat(ResourceFormat fmt)
ret = eGL_RGB10_A2UI;
break;
case ResourceFormatType::R11G11B10: ret = eGL_R11F_G11F_B10F; break;
case ResourceFormatType::R5G6B5: ret = eGL_RGB565; break;
case ResourceFormatType::R5G5B5A1: ret = eGL_RGB5_A1; break;
case ResourceFormatType::R5G6B5:
// only support bgra order
if(fmt.BGRAOrder())
return eGL_RGB565;
else
return eGL_NONE;
case ResourceFormatType::R5G5B5A1:
// only support bgra order
if(fmt.BGRAOrder())
return eGL_RGB5_A1;
else
return eGL_NONE;
case ResourceFormatType::R9G9B9E5: ret = eGL_RGB9_E5; break;
case ResourceFormatType::R4G4B4A4: ret = eGL_RGBA4; break;
case ResourceFormatType::R4G4B4A4:
// only support bgra order
if(fmt.BGRAOrder())
return eGL_RGBA4;
else
return eGL_NONE;
case ResourceFormatType::D24S8: ret = eGL_DEPTH24_STENCIL8; break;
case ResourceFormatType::D32S8: ret = eGL_DEPTH32F_STENCIL8; break;
case ResourceFormatType::D16S8: return eGL_NONE;
+92 -18
View File
@@ -2319,7 +2319,11 @@ void GLReplay::GetTextureData(ResourceId tex, const Subresource &sub,
else if(params.remap == RemapTexture::RGBA32)
remapFormat = eGL_RGBA32F;
remapFormat = GetViewCastedFormat(remapFormat, BaseRemapType(params.typeCast));
CompType typeCast = params.typeCast;
if(typeCast == CompType::Typeless && IsSRGBFormat(intFormat))
typeCast = CompType::UNormSRGB;
remapFormat = GetViewCastedFormat(remapFormat, BaseRemapType(typeCast));
if(intFormat != remapFormat)
{
@@ -2723,19 +2727,50 @@ void GLReplay::GetTextureData(ResourceId tex, const Subresource &sub,
drv.glGetTexImage(target, (GLint)s.mip, fmt, type, data.data());
}
// GL puts D24 in the top bits (whether or not there's stencil). We choose to standardise it
// to be in the low bits, so swizzle here. for D24 with no stencil, the stencil bits are
// undefined so we can move them around and it means nothing.
if(intFormat == eGL_DEPTH24_STENCIL8 || intFormat == eGL_DEPTH_COMPONENT24)
if(params.standardLayout)
{
uint32_t *ptr = (uint32_t *)data.data();
for(GLsizei y = 0; y < height; y++)
// GL puts D24 in the top bits (whether or not there's stencil). We choose to standardise it
// to be in the low bits, so swizzle here. for D24 with no stencil, the stencil bits are
// undefined so we can move them around and it means nothing.
if(intFormat == eGL_DEPTH24_STENCIL8 || intFormat == eGL_DEPTH_COMPONENT24)
{
for(GLsizei x = 0; x < width; x++)
uint32_t *ptr = (uint32_t *)data.data();
for(GLsizei z = 0; z < depth; z++)
{
const uint32_t val = *ptr;
*ptr = (val >> 8) | ((val & 0xff) << 24);
for(GLsizei y = 0; y < height; y++)
{
for(GLsizei x = 0; x < width; x++)
{
const uint32_t val = *ptr;
*ptr = (val >> 8) | ((val & 0xff) << 24);
ptr++;
}
}
}
}
// GL's RGBA4/RGB5A1 is BGRA order, but it puts alpha in the bottom bits where we expect it
// in the top
if(intFormat == eGL_RGBA4)
{
uint16_t *ptr = (uint16_t *)data.data();
for(size_t i = 0; i < data.size(); i += sizeof(uint16_t))
{
const uint16_t val = *ptr;
*ptr = (val >> 4) | ((val & 0xf) << 12);
ptr++;
}
}
else if(intFormat == eGL_RGB5_A1)
{
uint16_t *ptr = (uint16_t *)data.data();
for(size_t i = 0; i < data.size(); i += sizeof(uint16_t))
{
const uint16_t val = *ptr;
*ptr = (val >> 1) | ((val & 0x1) << 15);
ptr++;
}
}
@@ -3246,6 +3281,40 @@ void GLReplay::SetProxyTextureData(ResourceId texid, const Subresource &sub, byt
data = swizzled.data();
}
// GL's RGBA4/RGB5A1 is BGRA order, but it puts alpha in the bottom bits where we expect it
// in the top
else if(texdetails.internalFormat == eGL_RGBA4)
{
const uint16_t *srcptr = (const uint16_t *)data;
swizzled.resize(dataSize);
uint16_t *dstptr = (uint16_t *)swizzled.data();
for(size_t i = 0; i < dataSize; i += 2)
{
const uint16_t val = *srcptr;
*dstptr = ((val & 0x0fff) << 4) | ((val & 0xf000) >> 12);
srcptr++;
dstptr++;
}
data = swizzled.data();
}
else if(texdetails.internalFormat == eGL_RGB5_A1)
{
const uint16_t *srcptr = (const uint16_t *)data;
swizzled.resize(dataSize);
uint16_t *dstptr = (uint16_t *)swizzled.data();
for(size_t i = 0; i < dataSize; i += 2)
{
const uint16_t val = *srcptr;
*dstptr = ((val & 0x7fff) << 1) | ((val & 0x8000) >> 12);
srcptr++;
dstptr++;
}
data = swizzled.data();
}
if(target == eGL_TEXTURE_1D)
{
@@ -3312,8 +3381,13 @@ void GLReplay::SetProxyTextureData(ResourceId texid, const Subresource &sub, byt
bool GLReplay::IsTextureSupported(const TextureDescription &tex)
{
// these formats are inconsistently laid out between APIs, always remap if the remote API is
// different
// GL can't decide if these formats are BGRA or RGBA order.
// The bit order in memory for e.g. R4G4B4A4 is:
// 15 .. .. 0
// R G B A
//
// but if you upload bits in that order with GL_RGBA it gets flipped.
// It's more reliable to report no support and force a remap
switch(tex.format.type)
{
case ResourceFormatType::R4G4:
@@ -3332,11 +3406,6 @@ bool GLReplay::IsTextureSupported(const TextureDescription &tex)
if(tex.format.type == ResourceFormatType::A8)
return false;
// BGRA is not accepted as an internal format in case of GL
// EXT_texture_format_BGRA8888 is required for creating BGRA proxy textures in case of GLES
if(tex.format.BGRAOrder())
return IsGLES && HasExt[EXT_texture_format_BGRA8888];
// don't support 1D/3D block compressed textures
if(tex.dimension != 2 &&
(tex.format.type == ResourceFormatType::BC1 || tex.format.type == ResourceFormatType::BC2 ||
@@ -3357,6 +3426,11 @@ bool GLReplay::IsTextureSupported(const TextureDescription &tex)
if(fmt == eGL_NONE)
return false;
// BGRA is not accepted as an internal format in case of GL
// EXT_texture_format_BGRA8888 is required for creating BGRA proxy textures in case of GLES
if(fmt == eGL_BGRA8_EXT && (!IsGLES || !HasExt[EXT_texture_format_BGRA8888]))
return false;
GLenum target = eGL_TEXTURE_2D;
switch(tex.type)
+30
View File
@@ -3628,6 +3628,36 @@ void VulkanReplay::GetTextureData(ResourceId tex, const Subresource &sub,
else
{
memcpy(data.data(), pData, dataSize);
// vulkan's bitpacking of some layouts puts alpha in the low bits, which is not our 'standard'
// layout and is not representable in our resource formats
if(params.standardLayout)
{
if(imCreateInfo.format == VK_FORMAT_R4G4B4A4_UNORM_PACK16 ||
imCreateInfo.format == VK_FORMAT_B4G4R4A4_UNORM_PACK16)
{
uint16_t *ptr = (uint16_t *)data.data();
for(uint32_t i = 0; i < dataSize; i += sizeof(uint16_t))
{
const uint16_t val = *ptr;
*ptr = (val >> 4) | ((val & 0xf) << 12);
ptr++;
}
}
else if(imCreateInfo.format == VK_FORMAT_R5G5B5A1_UNORM_PACK16 ||
imCreateInfo.format == VK_FORMAT_B5G5R5A1_UNORM_PACK16)
{
uint16_t *ptr = (uint16_t *)data.data();
for(uint32_t i = 0; i < dataSize; i += sizeof(uint16_t))
{
const uint16_t val = *ptr;
*ptr = (val >> 1) | ((val & 0x1) << 15);
ptr++;
}
}
}
}
vt->UnmapMemory(Unwrap(dev), readbackMem);
+7 -6
View File
@@ -1811,9 +1811,10 @@ ResourceFormat MakeResourceFormat(VkFormat fmt)
switch(fmt)
{
case VK_FORMAT_B4G4R4A4_UNORM_PACK16:
case VK_FORMAT_B5G6R5_UNORM_PACK16:
case VK_FORMAT_B5G5R5A1_UNORM_PACK16:
case VK_FORMAT_R4G4B4A4_UNORM_PACK16:
case VK_FORMAT_R5G6B5_UNORM_PACK16:
case VK_FORMAT_R5G5B5A1_UNORM_PACK16:
case VK_FORMAT_A1R5G5B5_UNORM_PACK16:
case VK_FORMAT_B8G8R8A8_UNORM:
case VK_FORMAT_B8G8R8A8_SNORM:
case VK_FORMAT_B8G8R8A8_USCALED:
@@ -2710,14 +2711,14 @@ VkFormat MakeVkFormat(ResourceFormat fmt)
break;
case ResourceFormatType::R11G11B10: ret = VK_FORMAT_B10G11R11_UFLOAT_PACK32; break;
case ResourceFormatType::R5G6B5:
ret = fmt.BGRAOrder() ? VK_FORMAT_B5G6R5_UNORM_PACK16 : VK_FORMAT_R5G6B5_UNORM_PACK16;
ret = fmt.BGRAOrder() ? VK_FORMAT_R5G6B5_UNORM_PACK16 : VK_FORMAT_B5G6R5_UNORM_PACK16;
break;
case ResourceFormatType::R5G5B5A1:
ret = fmt.BGRAOrder() ? VK_FORMAT_B5G5R5A1_UNORM_PACK16 : VK_FORMAT_R5G5B5A1_UNORM_PACK16;
ret = fmt.BGRAOrder() ? VK_FORMAT_R5G5B5A1_UNORM_PACK16 : VK_FORMAT_B5G5R5A1_UNORM_PACK16;
break;
case ResourceFormatType::R9G9B9E5: ret = VK_FORMAT_E5B9G9R9_UFLOAT_PACK32; break;
case ResourceFormatType::R4G4B4A4:
ret = fmt.BGRAOrder() ? VK_FORMAT_B4G4R4A4_UNORM_PACK16 : VK_FORMAT_R4G4B4A4_UNORM_PACK16;
ret = fmt.BGRAOrder() ? VK_FORMAT_R4G4B4A4_UNORM_PACK16 : VK_FORMAT_B4G4R4A4_UNORM_PACK16;
break;
case ResourceFormatType::R4G4: ret = VK_FORMAT_R4G4_UNORM_PACK8; break;
case ResourceFormatType::D16S8: ret = VK_FORMAT_D16_UNORM_S8_UINT; break;
+72 -11
View File
@@ -301,6 +301,9 @@ FloatVector ConvertComponents(const ResourceFormat &fmt, const byte *data)
ret.y = v.y;
ret.z = v.z;
ret.w = v.w;
if(fmt.BGRAOrder())
std::swap(ret.x, ret.z);
}
else if(fmt.type == ResourceFormatType::R11G11B10)
{
@@ -312,25 +315,46 @@ FloatVector ConvertComponents(const ResourceFormat &fmt, const byte *data)
else if(fmt.type == ResourceFormatType::R5G5B5A1)
{
Vec4f v = ConvertFromB5G5R5A1(*(const uint16_t *)data);
ret.x = v.z;
ret.x = v.x;
ret.y = v.y;
ret.z = v.x;
ret.z = v.z;
ret.w = v.w;
// conversely we *expect* BGRA order for this format and the above conversion implicitly flips
// when bit-unpacking. So if the format wasn't BGRA order, flip it back
if(!fmt.BGRAOrder())
std::swap(ret.x, ret.z);
}
else if(fmt.type == ResourceFormatType::R5G6B5)
{
Vec3f v = ConvertFromB5G6R5(*(const uint16_t *)data);
ret.x = v.z;
ret.x = v.x;
ret.y = v.y;
ret.z = v.x;
ret.z = v.z;
// conversely we *expect* BGRA order for this format and the above conversion implicitly flips
// when bit-unpacking. So if the format wasn't BGRA order, flip it back
if(!fmt.BGRAOrder())
std::swap(ret.x, ret.z);
}
else if(fmt.type == ResourceFormatType::R4G4B4A4)
{
Vec4f v = ConvertFromB4G4R4A4(*(const uint16_t *)data);
ret.x = v.z;
ret.x = v.x;
ret.y = v.y;
ret.z = v.x;
ret.z = v.z;
ret.w = v.w;
// conversely we *expect* BGRA order for this format and the above conversion implicitly flips
// when bit-unpacking. So if the format wasn't BGRA order, flip it back
if(!fmt.BGRAOrder())
std::swap(ret.x, ret.z);
}
else if(fmt.type == ResourceFormatType::R4G4)
{
Vec4f v = ConvertFromR4G4(*(const uint8_t *)data);
ret.x = v.x;
ret.y = v.y;
}
else if(fmt.type == ResourceFormatType::R9G9B9E5)
{
@@ -338,9 +362,35 @@ FloatVector ConvertComponents(const ResourceFormat &fmt, const byte *data)
ret.x = v.x;
ret.y = v.y;
ret.z = v.z;
RDCLOG("%x -> %f,%f,%f", *(const uint32_t *)data, v.x, v.y, v.z);
}
else
else if(fmt.type == ResourceFormatType::D16S8)
{
uint32_t val = *(const uint32_t *)data;
ret.x = float(val & 0x00ffff) / 65535.0f;
ret.y = float((val & 0xff0000) >> 16) / 255.0f;
ret.z = 0.0f;
}
else if(fmt.type == ResourceFormatType::D24S8)
{
uint32_t val = *(const uint32_t *)data;
ret.x = float(val & 0x00ffffff) / 16777215.0f;
ret.y = float((val & 0xff000000) >> 24) / 255.0f;
ret.z = 0.0f;
}
else if(fmt.type == ResourceFormatType::D32S8)
{
struct ds
{
float f;
uint32_t s;
} val;
val = *(const ds *)data;
ret.x = val.f;
ret.y = float(val.s) / 255.0f;
ret.z = 0.0f;
}
else if(fmt.type == ResourceFormatType::Regular || fmt.type == ResourceFormatType::A8 ||
fmt.type == ResourceFormatType::S8)
{
float *comp = &ret.x;
@@ -394,9 +444,9 @@ FloatVector ConvertComponents(const ResourceFormat &fmt, const byte *data)
const uint8_t *u8 = (const uint8_t *)data;
uint32_t depth = 0;
depth |= uint32_t(u8[1]);
depth |= uint32_t(u8[2]) << 8;
depth |= uint32_t(u8[3]) << 16;
depth |= uint32_t(u8[0]);
depth |= uint32_t(u8[1]) << 8;
depth |= uint32_t(u8[2]) << 16;
*comp = float(depth) / float(16777215.0f);
}
@@ -476,6 +526,17 @@ FloatVector ConvertComponents(const ResourceFormat &fmt, const byte *data)
data += fmt.compByteWidth;
}
if(fmt.type == ResourceFormatType::A8)
{
ret.w = ret.x;
ret.x = 0.0f;
}
else if(fmt.type == ResourceFormatType::S8)
{
ret.y = ret.x;
ret.x = 0.0f;
}
if(fmt.BGRAOrder())
std::swap(ret.x, ret.z);
}
+11 -6
View File
@@ -79,20 +79,25 @@ uint32_t ConvertToR11G11B10(Vec3f data);
inline Vec4f ConvertFromB5G5R5A1(uint16_t data)
{
return Vec4f((float)((data >> 0) & 0x1f) / 31.0f, (float)((data >> 5) & 0x1f) / 31.0f,
(float)((data >> 10) & 0x1f) / 31.0f, ((data & 0x8000) > 0) ? 1.0f : 0.0f);
return Vec4f((float)((data >> 10) & 0x1f) / 31.0f, (float)((data >> 5) & 0x1f) / 31.0f,
(float)((data >> 0) & 0x1f) / 31.0f, ((data & 0x8000) > 0) ? 1.0f : 0.0f);
}
inline Vec3f ConvertFromB5G6R5(uint16_t data)
{
return Vec3f((float)((data >> 0) & 0x1f) / 31.0f, (float)((data >> 5) & 0x3f) / 63.0f,
(float)((data >> 11) & 0x1f) / 31.0f);
return Vec3f((float)((data >> 11) & 0x1f) / 31.0f, (float)((data >> 5) & 0x3f) / 63.0f,
(float)((data >> 0) & 0x1f) / 31.0f);
}
inline Vec4f ConvertFromB4G4R4A4(uint16_t data)
{
return Vec4f((float)((data >> 0) & 0xf) / 15.0f, (float)((data >> 4) & 0xf) / 15.0f,
(float)((data >> 8) & 0xf) / 15.0f, (float)((data >> 12) & 0xf) / 15.0f);
return Vec4f((float)((data >> 8) & 0xf) / 15.0f, (float)((data >> 4) & 0xf) / 15.0f,
(float)((data >> 0) & 0xf) / 15.0f, (float)((data >> 12) & 0xf) / 15.0f);
}
inline Vec4f ConvertFromR4G4(uint8_t data)
{
return Vec4f((float)((data >> 0) & 0xf) / 15.0f, (float)((data >> 4) & 0xf) / 15.0f, 0.0f, 0.0f);
}
Vec3f ConvertFromR9G9B9E5(uint32_t data);
+1
View File
@@ -847,6 +847,7 @@ bool ReplayController::SaveTexture(const TextureSave &saveData, const char *path
GetTextureDataParams params;
params.forDiskSave = true;
params.standardLayout = true;
params.typeCast = sd.typeCast;
params.resolve = resolveSamples;
params.remap = remap;
+1
View File
@@ -43,6 +43,7 @@ template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, GetTextureDataParams &el)
{
SERIALISE_MEMBER(forDiskSave);
SERIALISE_MEMBER(standardLayout);
SERIALISE_MEMBER(typeCast);
SERIALISE_MEMBER(resolve);
SERIALISE_MEMBER(remap);
+8
View File
@@ -83,7 +83,15 @@ DECLARE_REFLECTION_ENUM(RemapTexture);
struct GetTextureDataParams
{
// this data is going to be saved to disk, so prepare it as needed. E.g. on GL flip Y order to
// match conventional axis for file formats.
bool forDiskSave = false;
// this data is going to be transferred cross-API e.g. in replay proxying, so standardise bit
// layout of any packed formats where API conventions differ (mostly only RGBA4 or other awkward
// ones where our resource formats don't enumerate all possible iterations). Saving to disk is
// also standardised to ensure the data matches any format description we also write to the
// format.
bool standardLayout = false;
CompType typeCast = CompType::Typeless;
bool resolve = false;
RemapTexture remap = RemapTexture::NoRemap;
+7
View File
@@ -848,11 +848,16 @@ void main()
t.hasData = true;
bool srgb = false;
bool bgr = false;
switch(t.fmt.internalFormat)
{
// only need to handle renderable SRGB formats here
case GL_SRGB8:
case GL_SRGB8_ALPHA8: srgb = true; break;
case GL_BGRA8_EXT:
case GL_RGBA4:
case GL_RGB5_A1:
case GL_RGB565: bgr = true;
default: break;
}
@@ -862,6 +867,8 @@ void main()
flags |= 1;
if(srgb)
flags |= 2;
if(bgr)
flags |= 4;
GLuint slices = t.isArray ? texSlices : 1u;
GLuint mips = t.isMSAA || t.isRect ? 1u : texMips;
+5 -5
View File
@@ -189,7 +189,7 @@ void MakeData(TexData &data, const TexConfig &cfg, Vec4i dimensions, uint32_t mi
case TextureType::BC7: bc7 = true; break;
case TextureType::R9G9B9E5: sharedExp = true; break;
case TextureType::G4R4: nybblePattern = 0x12; break;
case TextureType::A4R4G4B4: nybblePattern = 0x1234; break;
case TextureType::A4R4G4B4: nybblePattern = 0x3214; break;
case TextureType::R4G4B4A4: nybblePattern = 0x4321; break;
case TextureType::R5G6B5:
rgb5 = true;
@@ -302,15 +302,15 @@ void MakeData(TexData &data, const TexConfig &cfg, Vec4i dimensions, uint32_t mi
if(alphabitPlace == 0)
{
encodedPixel |= uint16_t(rgb[2] * 31) << 0;
encodedPixel |= uint16_t(rgb[0] * 31) << 0;
encodedPixel |= uint16_t(rgb[1] * 63) << 5;
encodedPixel |= uint16_t(rgb[0] * 31) << 11;
encodedPixel |= uint16_t(rgb[2] * 31) << 11;
}
else
{
encodedPixel |= uint16_t(rgb[2] * 31) << 0;
encodedPixel |= uint16_t(rgb[0] * 31) << 0;
encodedPixel |= uint16_t(rgb[1] * 31) << 5;
encodedPixel |= uint16_t(rgb[0] * 31) << 10;
encodedPixel |= uint16_t(rgb[2] * 31) << 10;
if(alphabitPlace == 1)
{
+4 -3
View File
@@ -1172,9 +1172,10 @@ void main()
bool srgb = false, bgra = false;
switch(t.fmt.viewFmt)
{
case VK_FORMAT_B4G4R4A4_UNORM_PACK16:
case VK_FORMAT_B5G6R5_UNORM_PACK16:
case VK_FORMAT_B5G5R5A1_UNORM_PACK16:
case VK_FORMAT_R4G4B4A4_UNORM_PACK16:
case VK_FORMAT_R5G6B5_UNORM_PACK16:
case VK_FORMAT_R5G5B5A1_UNORM_PACK16:
case VK_FORMAT_A1R5G5B5_UNORM_PACK16:
case VK_FORMAT_B8G8R8_UNORM:
case VK_FORMAT_B8G8R8_SNORM:
case VK_FORMAT_B8G8R8_USCALED:
+7 -5
View File
@@ -15,7 +15,9 @@ class Texture_Zoo():
self.textures = {}
self.controller: rd.ReplayController
self.controller = None
self.pipeType = rd.GraphicsAPI.D3D11
self.opengl_mode = False
self.d3d_mode = False
def sub(self, mip: int, slice: int, sample: int):
if self.fake_msaa:
@@ -70,6 +72,9 @@ class Texture_Zoo():
success: bool = self.controller.SaveTexture(save_data, path)
if not success:
if self.d3d_mode:
raise rdtest.TestFailureException("Couldn't save DDS to {} on D3D.".format(self.filename))
try:
os.remove(path)
except Exception:
@@ -369,7 +374,9 @@ class Texture_Zoo():
def check_capture(self, capture_filename: str, controller: rd.ReplayController):
self.controller = controller
self.pipeType = self.controller.GetAPIProperties().pipelineType
self.opengl_mode = (self.controller.GetAPIProperties().pipelineType == rd.GraphicsAPI.OpenGL)
self.d3d_mode = rd.IsD3D(self.controller.GetAPIProperties().pipelineType)
failed = False
@@ -442,11 +449,6 @@ class Texture_Zoo():
ret: Tuple[rd.ReplayStatus, rd.ReplayController] = cap.OpenCapture(rd.ReplayOptions(), None)
status, self.controller = ret
# Some packed formats can't be opened, allow that
if status == rd.ReplayStatus.ImageUnsupported and 'dds' in file.name:
rdtest.log.print("Couldn't open {} - unsupported".format(file.name))
continue
if status != rd.ReplayStatus.Succeeded:
rdtest.log.error("Couldn't open {}".format(file.name))
failed = True