Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Scale directly into the buffer if possible.
This will be possible in the majority of cases, and avoid an extra copy.
A small cost compared to scaling, but even so.
  • Loading branch information
unknownbrackets committed Jun 25, 2016
1 parent 3db69b8 commit 4c94cd7
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 31 deletions.
48 changes: 27 additions & 21 deletions GPU/Common/TextureScalerCommon.cpp
Expand Up @@ -505,56 +505,45 @@ bool TextureScaler::IsEmptyOrFlat(u32* data, int pixels, int fmt) {
return true;
}

void TextureScaler::ScaleAlways(u32 *&data, u32 &dstFmt, int &width, int &height, int factor) {
if (!Scale(data, dstFmt, width, height, factor)) {
void TextureScaler::ScaleAlways(u32 *out, u32 *src, u32 &dstFmt, int &width, int &height, int factor) {
if (IsEmptyOrFlat(src, width*height, dstFmt)) {
// This means it was a flat texture. Vulkan wants the size up front, so we need to make it happen.
assert(IsEmptyOrFlat(data, width * height, dstFmt));

u32 pixel;
// Since it's flat, one pixel is enough. It might end up pointing to data, though.
u32 *pixelPointer = &pixel;
ConvertTo8888(dstFmt, data, pixelPointer, 1, 1);
ConvertTo8888(dstFmt, src, pixelPointer, 1, 1);
if (pixelPointer != &pixel) {
pixel = *pixelPointer;
}

bufOutput.resize(width * height * factor * factor);
dstFmt = Get8888Format();
data = bufOutput.data();
width *= factor;
height *= factor;

// ABCD. If A = D, and AB = CD, then they must all be equal (B = C, etc.)
if ((pixel & 0x000000FF) == (pixel >> 24) && (pixel & 0x0000FFFF) == (pixel >> 16)) {
memset(data, pixel & 0xFF, width * height * sizeof(u32));
memset(out, pixel & 0xFF, width * height * sizeof(u32));
} else {
// Let's hope this is vectorized.
for (int i = 0; i < width * height; ++i) {
data[i] = pixel;
out[i] = pixel;
}
}
} else {
ScaleInto(out, src, dstFmt, width, height, factor);
}
}

bool TextureScaler::Scale(u32* &data, u32 &dstFmt, int &width, int &height, int factor) {
// prevent processing empty or flat textures (this happens a lot in some games)
// doesn't hurt the standard case, will be very quick for textures with actual texture
if (IsEmptyOrFlat(data, width*height, dstFmt)) {
INFO_LOG(G3D, "TextureScaler: early exit -- empty/flat texture");
return false;
}

bool TextureScaler::ScaleInto(u32 *outputBuf, u32 *src, u32 &dstFmt, int &width, int &height, int factor) {
#ifdef SCALING_MEASURE_TIME
double t_start = real_time_now();
#endif

bufInput.resize(width*height); // used to store the input image image if it needs to be reformatted
bufOutput.resize(width*height*factor*factor); // used to store the upscaled image
u32 *inputBuf = bufInput.data();
u32 *outputBuf = bufOutput.data();

// convert texture to correct format for scaling
ConvertTo8888(dstFmt, data, inputBuf, width, height);
ConvertTo8888(dstFmt, src, inputBuf, width, height);

// deposterize
if (g_Config.bTexDeposterize) {
Expand Down Expand Up @@ -583,7 +572,6 @@ bool TextureScaler::Scale(u32* &data, u32 &dstFmt, int &width, int &height, int

// update values accordingly
dstFmt = Get8888Format();
data = outputBuf;
width *= factor;
height *= factor;

Expand All @@ -598,6 +586,24 @@ bool TextureScaler::Scale(u32* &data, u32 &dstFmt, int &width, int &height, int
return true;
}

bool TextureScaler::Scale(u32* &data, u32 &dstFmt, int &width, int &height, int factor) {
// prevent processing empty or flat textures (this happens a lot in some games)
// doesn't hurt the standard case, will be very quick for textures with actual texture
if (IsEmptyOrFlat(data, width*height, dstFmt)) {
DEBUG_LOG(G3D, "TextureScaler: early exit -- empty/flat texture");
return false;
}

bufOutput.resize(width*height*factor*factor); // used to store the upscaled image
u32 *outputBuf = bufOutput.data();

if (ScaleInto(outputBuf, data, dstFmt, width, height, factor)) {
data = outputBuf;
return true;
}
return false;
}

void TextureScaler::ScaleXBRZ(int factor, u32* source, u32* dest, int width, int height) {
xbrz::ScalerCfg cfg;
GlobalThreadPool::Loop(std::bind(&xbrz::scale, factor, source, dest, width, height, xbrz::ColorFormat::ARGB, cfg, placeholder::_1, placeholder::_2), 0, height);
Expand Down
3 changes: 2 additions & 1 deletion GPU/Common/TextureScalerCommon.h
Expand Up @@ -27,8 +27,9 @@ class TextureScaler {
TextureScaler();
~TextureScaler();

void ScaleAlways(u32 *&data, u32 &dstFmt, int &width, int &height, int factor);
void ScaleAlways(u32 *out, u32 *src, u32 &dstFmt, int &width, int &height, int factor);
bool Scale(u32 *&data, u32 &dstfmt, int &width, int &height, int factor);
bool ScaleInto(u32 *out, u32 *src, u32 &dstfmt, int &width, int &height, int factor);

enum { XBRZ = 0, HYBRID = 1, BICUBIC = 2, HYBRID_BICUBIC = 3 };

Expand Down
19 changes: 10 additions & 9 deletions GPU/Vulkan/TextureCacheVulkan.cpp
Expand Up @@ -1430,14 +1430,23 @@ void TextureCacheVulkan::LoadTextureLevel(TexCacheEntry &entry, uint8_t *writePt

if (scaleFactor > 1) {
u32 fmt = dstFmt;
scaler.ScaleAlways(pixelData, fmt, w, h, scaleFactor);
scaler.ScaleAlways((u32 *)writePtr, pixelData, fmt, w, h, scaleFactor);
pixelData = (u32 *)writePtr;
dstFmt = (VkFormat)fmt;

// We always end up at 8888. Other parts assume this.
assert(dstFmt == VULKAN_8888_FORMAT);
bpp = sizeof(u32);
decPitch = w * bpp;
rowBytes = w * bpp;

if (decPitch != rowPitch) {
// Rearrange in place to match the requested pitch.
// (it can only be larger than w * bpp, and a match is likely.)
for (int y = h - 1; y >= 0; --y) {
memcpy(writePtr + rowPitch * y, writePtr + decPitch * y, rowBytes);
}
}
}

if ((entry.status & TexCacheEntry::STATUS_CHANGE_FREQUENT) == 0) {
Expand All @@ -1447,12 +1456,4 @@ void TextureCacheVulkan::LoadTextureLevel(TexCacheEntry &entry, uint8_t *writePt
entry.SetAlphaStatus(TexCacheEntry::STATUS_ALPHA_UNKNOWN);
}
}

PROFILE_THIS_SCOPE("loadtex");
if (pixelData != (u32 *)writePtr) {
// This is used when texture scaling was enabled.
for (int y = 0; y < h; y++) {
memcpy(writePtr + rowPitch * y, (const uint8_t *)pixelData + decPitch * y, rowBytes);
}
}
}

0 comments on commit 4c94cd7

Please sign in to comment.