TextureCacheVulkan: Move the texture scaling upload shader and passes to common

So the Metal backend can use them too. No functional change.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Henrik RydgårdandClaude Opus 5.5 committed 2026-10-19 12:02:22 +02:00
1 parent 0978a3e363
commit 55109b39fb
4 files changed
+115 -96

No files matched your search

+2 -80
View File
@@ -55,60 +55,6 @@ using namespace PPSSPP_VK;
#define TEXCACHE_MAX_SLAB_SIZE (32 * 1024 * 1024)
#define TEXCACHE_SLAB_PRESSURE 4
const char *uploadShader = R"(
#version 450
#extension GL_ARB_separate_shader_objects : enable
// 8x8 is the most common compute shader workgroup size, and works great on all major
// hardware vendors. TODO: However, we should probably change to 16x16, as Qualcomm now has
// support for bigger groups...
layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
uniform layout(set = 0, binding = 0, rgba8) writeonly image2D img;
layout(std430, set = 0, binding = 1) buffer Buf {
uint data[];
} buf;
layout(push_constant) uniform Params {
int width;
int height;
} params;
// The cbuffer, if present, is self-declared for layout flexibility
#define CBUFFER_SET 0
#define CBUFFER_BINDING 4
uint readColoru(uvec2 p) {
return buf.data[p.y * params.width + p.x];
}
vec4 readColorf(uvec2 p) {
// Unpack the color (we could look it up in a CLUT here if we wanted...)
// The imageStore repack is free.
return unpackUnorm4x8(readColoru(p));
}
void writeColorf(ivec2 p, vec4 c) {
imageStore(img, p, c);
}
%s
// Note that main runs once per INPUT pixel, unlike the old model.
void main() {
uvec2 xy = gl_GlobalInvocationID.xy;
// Kill off any out-of-image threads to avoid stray writes.
// Should only happen on the tiniest mipmaps as PSP textures are power-of-2,
// and we use a 8x8 workgroup size. Probably not really necessary.
if (xy.x >= params.width || xy.y >= params.height)
return;
// applyScaling will write the upscaled pixels, using writeColorf above.
// It's expected to write a square of scale*scale pixels, at the location xy*scale.
applyScaling(xy);
}
)";
static int VkFormatBytesPerPixel(VkFormat format) {
switch (format) {
@@ -301,31 +247,7 @@ bool TextureCacheVulkan::CompileMultipassShader(VulkanContext *vulkan, const Tex
if (!shaderInfo.computeShaderFiles.empty()) {
shaderFiles = shaderInfo.computeShaderFiles;
}
if (shaderInfo.scaleFactor == 2) {
multipassScratchDescs_ = {
{ "nnedi3_vertical", 1, 2 },
{ "nnedi3_horizontal", 2, 2 },
};
multipassStageDescs_ = {
{ 0, -1, 0, 1, 1, 1, 2, false },
{ 1, 0, 1, 1, 2, 2, 2, false },
{ 2, 1, -1, 2, 2, 2, 2, false },
};
} else if (shaderInfo.scaleFactor == 4) {
multipassScratchDescs_ = {
{ "nnedi3_vertical", 1, 2 },
{ "nnedi3_horizontal", 2, 2 },
{ "nnedi3_vertical2", 2, 4 },
{ "nnedi3_horizontal2", 4, 4 },
};
multipassStageDescs_ = {
{ 0, -1, 0, 1, 1, 1, 2, false },
{ 2, 0, 1, 1, 2, 2, 2, false },
{ 1, 1, 2, 2, 2, 2, 4, false },
{ 2, 2, 3, 2, 4, 4, 4, false },
{ 3, 3, -1, 4, 4, 4, 4, true },
};
} else {
if (!GetTextureScaleMultipassLayout(shaderInfo.scaleFactor, &multipassScratchDescs_, &multipassStageDescs_)) {
ERROR_LOG(Log::G3D, "Unsupported multipass scale factor %d in section '%s'", shaderInfo.scaleFactor, shaderInfo.section.c_str());
return false;
}
@@ -395,7 +317,7 @@ void TextureCacheVulkan::CompileScalingShader() {
}
} else {
std::string shaderSource = ReadShaderSrc(shaderInfo->computeShaderFiles[0]);
std::string fullUploadShader = StringFromFormat(uploadShader, shaderSource.c_str());
std::string fullUploadShader = StringFromFormat(textureScaleUploadShader, shaderSource.c_str());
singlePassCS_ = CompileShaderModule(vulkan, VK_SHADER_STAGE_COMPUTE_BIT, fullUploadShader.c_str(), &error);
_dbg_assert_msg_(singlePassCS_ != VK_NULL_HANDLE, "failed to compile upload shader");
if (singlePassCS_ == VK_NULL_HANDLE)