Rework constant buffer loading, barrier fix

This commit is contained in:
Henrik Rydgård
2026-04-12 09:16:29 -06:00
parent 4c2be7f8af
commit d108fe25d1
9 changed files with 61 additions and 29 deletions
+2 -2
View File
@@ -84,7 +84,7 @@ std::string_view I18NCategory::T(std::string_view key, std::string_view def) {
}
if (key != "Font") {
// Font is allowed to be missing.
INFO_LOG(Log::UI, "Missing translation [%s] %.*s (%.*s)", name_.c_str(), STR_VIEW(key), STR_VIEW(def));
DEBUG_LOG(Log::UI, "Missing translation [%s] %.*s (%.*s)", name_.c_str(), STR_VIEW(key), STR_VIEW(def));
std::lock_guard<std::mutex> guard(missedKeyLock_);
std::string missedKey(key);
if (!def.empty())
@@ -107,7 +107,7 @@ const char *I18NCategory::T_cstr(const char *key, const char *def) {
}
std::string missedKey(key);
if (missedKey != "Font") {
INFO_LOG(Log::UI, "Missing translation %s (%s)", key, def);
DEBUG_LOG(Log::UI, "Missing translation %s (%s)", key, def);
std::lock_guard<std::mutex> guard(missedKeyLock_);
if (def)
+3
View File
@@ -58,6 +58,9 @@ void VulkanBarrierBatch::TransitionImage(
}
void VulkanBarrierBatch::TransitionBufferToShaderRead(VkBuffer buffer, VkDeviceSize offset, VkDeviceSize size) {
srcStageMask_ |= VK_PIPELINE_STAGE_TRANSFER_BIT;
dstStageMask_ |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
VkBufferMemoryBarrier &bufferBarrier = bufferBarriers_.push_uninitialized();
bufferBarrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
bufferBarrier.pNext = nullptr;
+3 -10
View File
@@ -212,19 +212,12 @@ void LoadPostShaderInfo(Draw::DrawContext *draw, const std::vector<Path> &direct
info.scaleFactor = 0;
section.Get("Name", &info.name);
section.Get("Scale", &info.scaleFactor);
bool hidden = false;
section.Get("Hidden", &info.hidden);
std::string cbufferFilename;
if (section.Get("ConstantBuffer", &cbufferFilename)) {
Path cbufferPath = path / cbufferFilename;
std::string temp;
size_t constantsSize;
uint8_t *contents = g_VFS.ReadFile(cbufferPath.c_str(), &constantsSize);
if (contents) {
info.constantBuffer.assign(contents, contents + constantsSize);
delete[] contents;
} else {
ERROR_LOG(Log::G3D, "Failed to read constant buffer file '%s' for texture shader '%s'", cbufferPath.c_str(), info.name.c_str());
continue;
}
info.constantBuffer = cbufferPath;
}
if (section.Get("Compute", &temp)) {
info.computeShaderFile = path / temp;
+2 -1
View File
@@ -91,7 +91,8 @@ struct TextureShaderInfo {
int scaleFactor;
// Some shaders need to pass some data to the shader, and this is the buffer for that. It's up to the shader to interpret it.
std::vector<u8> constantBuffer;
Path constantBuffer;
bool hidden = false;
bool operator == (const std::string &other) const {
return name == other;
+38 -14
View File
@@ -411,17 +411,9 @@ void TextureCacheVulkan::CompileScalingShader(VkCommandBuffer cmdInit) {
textureScalePipeline_ = TextureScalePipelineType::SINGLE_PASS;
}
if (!shaderInfo->constantBuffer.empty()) {
textureScaleCBuffer_.Create(vulkan, "TextureScale CBuffer", shaderInfo->constantBuffer.size(), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
VulkanPushPool *pushPool = drawEngine_->GetPushBufferForTextureData();
VkBuffer srcBuf;
VkDeviceSize offset = pushPool->Push(shaderInfo->constantBuffer.data(), shaderInfo->constantBuffer.size(), vulkan->GetPhysicalDeviceProperties().properties.limits.minUniformBufferOffsetAlignment, &srcBuf);
VkBufferCopy copyRegion{offset, 0, shaderInfo->constantBuffer.size()};
vkCmdCopyBuffer(cmdInit, srcBuf, textureScaleCBuffer_.Buffer(), 1, &copyRegion);
VulkanBarrierBatch barrier;
barrier.TransitionBufferToShaderRead(textureScaleCBuffer_.Buffer(), 0, shaderInfo->constantBuffer.size());
barrier.Flush(cmdInit);
}
// if it's empty, we're already done. otherwise we need to load it on first use.
cbufferInited_ = shaderInfo->constantBuffer.empty();
cbufferPath_ = shaderInfo->constantBuffer;
textureShader_ = g_Config.sTextureShaderName;
shaderScaleFactor_ = shaderInfo->scaleFactor;
@@ -442,6 +434,35 @@ static void BarrierComputeImage(VkCommandBuffer cmd, VkImage image) {
batch.Flush(cmd);
}
void TextureCacheVulkan::LoadConstantBuffer(VulkanContext *vulkan, VkCommandBuffer cmdInit) {
if (cbufferInited_) {
return;
}
_dbg_assert_(!cbufferPath_.empty());
std::string temp;
size_t constantsSize;
uint8_t *contents = g_VFS.ReadFile(cbufferPath_.c_str(), &constantsSize);
if (!contents) {
ERROR_LOG(Log::G3D, "Failed to read constant buffer file '%s'", cbufferPath_.c_str());
return;
}
textureScaleCBuffer_.Create(vulkan, "TextureScale CBuffer", constantsSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
VulkanPushPool *pushPool = drawEngine_->GetPushBufferForTextureData();
VkBuffer srcBuf = VK_NULL_HANDLE;
VkDeviceSize offset = pushPool->Push(contents, constantsSize, vulkan->GetPhysicalDeviceProperties().properties.limits.minUniformBufferOffsetAlignment, &srcBuf);
VkBufferCopy copyRegion{offset, 0, constantsSize};
vkCmdCopyBuffer(cmdInit, srcBuf, textureScaleCBuffer_.Buffer(), 1, &copyRegion);
VulkanBarrierBatch barrier;
barrier.TransitionBufferToShaderRead(textureScaleCBuffer_.Buffer(), 0, constantsSize);
barrier.Flush(cmdInit);
delete[] contents;
cbufferInited_ = true;
}
bool TextureCacheVulkan::RunMultipassCompute(VulkanContext *vulkan, VkCommandBuffer cmdInit, VkImageView dstView, VkBuffer texBuf, uint32_t bufferOffset, int srcSize, int srcWidth, int srcHeight, int dstWidth, int dstHeight) {
const bool fourX = dstWidth > srcWidth * 2 || dstHeight > srcHeight * 2;
VulkanBarrierBatch barrier;
@@ -449,6 +470,8 @@ bool TextureCacheVulkan::RunMultipassCompute(VulkanContext *vulkan, VkCommandBuf
std::vector<std::unique_ptr<VulkanTexture>> scratchTextures;
scratchTextures.reserve(multipassScratchDescs_.size());
LoadConstantBuffer(vulkan, cmdInit);
for (const MultipassScratchDesc &scratchDesc : multipassScratchDescs_) {
auto scratch = std::make_unique<VulkanTexture>(vulkan, scratchDesc.tag);
if (!scratch->CreateDirect(srcWidth * scratchDesc.widthScale, srcHeight * scratchDesc.heightScale, 1, 1, VK_FORMAT_R16G16B16A16_SFLOAT, VK_IMAGE_LAYOUT_GENERAL, scratchUsage, &barrier)) {
@@ -513,12 +536,13 @@ bool TextureCacheVulkan::RunMultipassCompute(VulkanContext *vulkan, VkCommandBuf
return true;
}
bool TextureCacheVulkan::ScaleBufferToImage(VkCommandBuffer cmdInit, VkImageView dstView, VkBuffer texBuf, uint32_t bufferOffset, int srcSize, int srcWidth, int srcHeight, int dstWidth, int dstHeight) {
bool TextureCacheVulkan::ScaleBufferToImage(VulkanContext *vulkan, VkCommandBuffer cmdInit, VkImageView dstView, VkBuffer texBuf, uint32_t bufferOffset, int srcSize, int srcWidth, int srcHeight, int dstWidth, int dstHeight) {
if (!draw_ || cmdInit == VK_NULL_HANDLE || dstView == VK_NULL_HANDLE) {
return false;
}
VulkanContext *vulkan = (VulkanContext *)draw_->GetNativeObject(Draw::NativeObject::CONTEXT);
LoadConstantBuffer(vulkan, cmdInit);
switch (textureScalePipeline_) {
case TextureScalePipelineType::SINGLE_PASS: {
if (singlePassCS_ == VK_NULL_HANDLE) {
@@ -878,7 +902,7 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) {
VkImageView view = entry->vkTex->CreateViewForMip(i);
VK_PROFILE_BEGIN(vulkan, cmdInit, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
"Compute Upload: %dx%d->%dx%d", mipUnscaledWidth, mipUnscaledHeight, mipWidth, mipHeight);
ScaleBufferToImage(cmdInit, view, texBuf, bufferOffset, srcSize, mipUnscaledWidth, mipUnscaledHeight, mipWidth, mipHeight);
ScaleBufferToImage(vulkan, cmdInit, view, texBuf, bufferOffset, srcSize, mipUnscaledWidth, mipUnscaledHeight, mipWidth, mipHeight);
VK_PROFILE_END(vulkan, cmdInit, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
vulkan->Delete().QueueDeleteImageView(view);
} else {
+7 -1
View File
@@ -127,7 +127,9 @@ private:
void ClearScalingShaders(VulkanContext *vulkan);
bool HasScalingShader() const;
bool RunMultipassCompute(VulkanContext *vulkan, VkCommandBuffer cmdInit, VkImageView dstView, VkBuffer texBuf, uint32_t bufferOffset, int srcSize, int srcWidth, int srcHeight, int dstWidth, int dstHeight);
bool ScaleBufferToImage(VkCommandBuffer cmdInit, VkImageView dstView, VkBuffer texBuf, uint32_t bufferOffset, int srcSize, int srcWidth, int srcHeight, int dstWidth, int dstHeight);
bool ScaleBufferToImage(VulkanContext *vulkan, VkCommandBuffer cmdInit, VkImageView dstView, VkBuffer texBuf, uint32_t bufferOffset, int srcSize, int srcWidth, int srcHeight, int dstWidth, int dstHeight);
void LoadConstantBuffer(VulkanContext *vulkan, VkCommandBuffer cmdInit);
VulkanComputeShaderManager computeShaderManager_;
@@ -147,7 +149,11 @@ private:
VkSampler curSampler_ = VK_NULL_HANDLE;
VkSampler samplerNearest_ = VK_NULL_HANDLE;
Path cbufferPath_;
VulkanBuffer textureScaleCBuffer_;
bool cbufferInited_ = true;
bool cbufferFailed_ = false;
};
VkFormat getClutDestFormatVulkan(GEPaletteFormat format);
+2 -1
View File
@@ -132,7 +132,8 @@ void VulkanComputeShaderManager::InitDeviceObjects(Draw::DrawContext *draw) {
bindings[3].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
bindings[3].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
bindings[3].binding = 3;
bindings[4].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
bindings[4].descriptorCount = 1;
bindings[4].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
bindings[4].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
bindings[4].binding = 4;
+3
View File
@@ -244,6 +244,9 @@ void TextureShaderScreen::CreateViews() {
std::vector<std::string> items;
int selected = -1;
for (int i = 0; i < (int)shaders_.size(); i++) {
if (shaders_[i].hidden) {
continue;
}
if (shaders_[i].section == g_Config.sTextureShaderName)
selected = i;
items.emplace_back(ps->T(shaders_[i].section, shaders_[i].name));
+1
View File
@@ -267,6 +267,7 @@ Author=PPSSPP contributors
Compute=tex_smiley_2x.csh
Scale=2
ConstantBuffer=smiley_16x16_rgba.bin
Hidden=True # this is an example shader that should not be shown in the list.
[RedBlue]
Type=StereoToMono
Name=Red/Blue glasses (anaglyph)