mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-07-11 01:25:07 +02:00
Rework constant buffer loading, barrier fix
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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, ©Region);
|
||||
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, ©Region);
|
||||
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 {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user