mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Vulkan: Save textures using a memory copy.
This commit is contained in:
parent
cc119c923c
commit
34d0acac4e
2 changed files with 23 additions and 10 deletions
|
@ -628,8 +628,7 @@ void TextureReplacer::NotifyTextureDecoded(const ReplacedTextureDecodeInfo &repl
|
||||||
|
|
||||||
SimpleBuf<u32> saveBuf;
|
SimpleBuf<u32> saveBuf;
|
||||||
|
|
||||||
// TODO: Move the color conversion to the thread as well.
|
// Since we're copying, change the format meanwhile. Not much extra cost.
|
||||||
// Actually may be better to re-decode using expand32?
|
|
||||||
if (replacedInfo.fmt != ReplacedTextureFormat::F_8888) {
|
if (replacedInfo.fmt != ReplacedTextureFormat::F_8888) {
|
||||||
saveBuf.resize((pitch * h) / sizeof(u16));
|
saveBuf.resize((pitch * h) / sizeof(u16));
|
||||||
switch (replacedInfo.fmt) {
|
switch (replacedInfo.fmt) {
|
||||||
|
|
|
@ -794,6 +794,7 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ReplacedTextureDecodeInfo replacedInfo;
|
ReplacedTextureDecodeInfo replacedInfo;
|
||||||
|
bool willSaveTex = false;
|
||||||
if (replacer_.Enabled() && !replaced.Valid()) {
|
if (replacer_.Enabled() && !replaced.Valid()) {
|
||||||
replacedInfo.cachekey = entry->CacheKey();
|
replacedInfo.cachekey = entry->CacheKey();
|
||||||
replacedInfo.hash = entry->fullhash;
|
replacedInfo.hash = entry->fullhash;
|
||||||
|
@ -802,6 +803,7 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) {
|
||||||
replacedInfo.isFinal = (entry->status & TexCacheEntry::STATUS_TO_SCALE) == 0;
|
replacedInfo.isFinal = (entry->status & TexCacheEntry::STATUS_TO_SCALE) == 0;
|
||||||
replacedInfo.scaleFactor = scaleFactor;
|
replacedInfo.scaleFactor = scaleFactor;
|
||||||
replacedInfo.fmt = FromVulkanFormat(actualFmt);
|
replacedInfo.fmt = FromVulkanFormat(actualFmt);
|
||||||
|
willSaveTex = replacer_.WillSave(replacedInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entry->vkTex) {
|
if (entry->vkTex) {
|
||||||
|
@ -821,6 +823,7 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) {
|
||||||
if (replaced.Valid()) {
|
if (replaced.Valid()) {
|
||||||
replaced.GetSize(i, mipWidth, mipHeight);
|
replaced.GetSize(i, mipWidth, mipHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
int bpp = actualFmt == VULKAN_8888_FORMAT ? 4 : 2;
|
int bpp = actualFmt == VULKAN_8888_FORMAT ? 4 : 2;
|
||||||
int stride = (mipWidth * bpp + 15) & ~15;
|
int stride = (mipWidth * bpp + 15) & ~15;
|
||||||
int size = stride * mipHeight;
|
int size = stride * mipHeight;
|
||||||
|
@ -829,6 +832,20 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) {
|
||||||
// NVIDIA reports a min alignment of 1 but that can't be healthy... let's align by 16 as a minimum.
|
// NVIDIA reports a min alignment of 1 but that can't be healthy... let's align by 16 as a minimum.
|
||||||
int pushAlignment = std::max(16, (int)vulkan->GetPhysicalDeviceProperties().properties.limits.optimalBufferCopyOffsetAlignment);
|
int pushAlignment = std::max(16, (int)vulkan->GetPhysicalDeviceProperties().properties.limits.optimalBufferCopyOffsetAlignment);
|
||||||
void *data;
|
void *data;
|
||||||
|
std::vector<uint8_t> saveData;
|
||||||
|
|
||||||
|
auto loadLevel = [&](int sz, int lstride, int lfactor) {
|
||||||
|
if (willSaveTex) {
|
||||||
|
saveData.resize(sz);
|
||||||
|
data = &saveData[0];
|
||||||
|
} else {
|
||||||
|
data = drawEngine_->GetPushBufferForTextureData()->PushAligned(sz, &bufferOffset, &texBuf, pushAlignment);
|
||||||
|
}
|
||||||
|
LoadTextureLevel(*entry, (uint8_t *)data, lstride, level, lfactor, dstFmt);
|
||||||
|
if (willSaveTex)
|
||||||
|
bufferOffset = drawEngine_->GetPushBufferForTextureData()->PushAligned(&saveData[0], sz, pushAlignment, &texBuf);
|
||||||
|
};
|
||||||
|
|
||||||
bool dataScaled = true;
|
bool dataScaled = true;
|
||||||
if (replaced.Valid()) {
|
if (replaced.Valid()) {
|
||||||
// Directly load the replaced image.
|
// Directly load the replaced image.
|
||||||
|
@ -842,18 +859,16 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) {
|
||||||
VK_PROFILE_END(vulkan, cmdInit, VK_PIPELINE_STAGE_TRANSFER_BIT);
|
VK_PROFILE_END(vulkan, cmdInit, VK_PIPELINE_STAGE_TRANSFER_BIT);
|
||||||
} else {
|
} else {
|
||||||
if (fakeMipmap) {
|
if (fakeMipmap) {
|
||||||
data = drawEngine_->GetPushBufferForTextureData()->PushAligned(size, &bufferOffset, &texBuf, pushAlignment);
|
loadLevel(size, stride, scaleFactor);
|
||||||
LoadTextureLevel(*entry, (uint8_t *)data, stride, level, scaleFactor, dstFmt);
|
|
||||||
entry->vkTex->UploadMip(cmdInit, 0, mipWidth, mipHeight, texBuf, bufferOffset, stride / bpp);
|
entry->vkTex->UploadMip(cmdInit, 0, mipWidth, mipHeight, texBuf, bufferOffset, stride / bpp);
|
||||||
} else {
|
} else {
|
||||||
if (computeUpload) {
|
if (computeUpload) {
|
||||||
int srcBpp = dstFmt == VULKAN_8888_FORMAT ? 4 : 2;
|
int srcBpp = dstFmt == VULKAN_8888_FORMAT ? 4 : 2;
|
||||||
int srcStride = mipUnscaledWidth * srcBpp;
|
int srcStride = mipUnscaledWidth * srcBpp;
|
||||||
int srcSize = srcStride * mipUnscaledHeight;
|
int srcSize = srcStride * mipUnscaledHeight;
|
||||||
|
loadLevel(srcSize, srcStride, 1);
|
||||||
data = drawEngine_->GetPushBufferForTextureData()->PushAligned(srcSize, &bufferOffset, &texBuf, pushAlignment);
|
|
||||||
dataScaled = false;
|
dataScaled = false;
|
||||||
LoadTextureLevel(*entry, (uint8_t *)data, srcStride, i, 1, dstFmt);
|
|
||||||
// This format can be used with storage images.
|
// This format can be used with storage images.
|
||||||
VkImageView view = entry->vkTex->CreateViewForMip(i);
|
VkImageView view = entry->vkTex->CreateViewForMip(i);
|
||||||
VkDescriptorSet descSet = computeShaderManager_.GetDescriptorSet(view, texBuf, bufferOffset, srcSize);
|
VkDescriptorSet descSet = computeShaderManager_.GetDescriptorSet(view, texBuf, bufferOffset, srcSize);
|
||||||
|
@ -867,8 +882,7 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) {
|
||||||
VK_PROFILE_END(vulkan, cmdInit, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
|
VK_PROFILE_END(vulkan, cmdInit, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
|
||||||
vulkan->Delete().QueueDeleteImageView(view);
|
vulkan->Delete().QueueDeleteImageView(view);
|
||||||
} else {
|
} else {
|
||||||
data = drawEngine_->GetPushBufferForTextureData()->PushAligned(size, &bufferOffset, &texBuf, pushAlignment);
|
loadLevel(size, stride, scaleFactor);
|
||||||
LoadTextureLevel(*entry, (uint8_t *)data, stride, i, scaleFactor, dstFmt);
|
|
||||||
VK_PROFILE_BEGIN(vulkan, cmdInit, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
VK_PROFILE_BEGIN(vulkan, cmdInit, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
"Copy Upload: %dx%d", mipWidth, mipHeight);
|
"Copy Upload: %dx%d", mipWidth, mipHeight);
|
||||||
entry->vkTex->UploadMip(cmdInit, i, mipWidth, mipHeight, texBuf, bufferOffset, stride / bpp);
|
entry->vkTex->UploadMip(cmdInit, i, mipWidth, mipHeight, texBuf, bufferOffset, stride / bpp);
|
||||||
|
@ -879,7 +893,7 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) {
|
||||||
// When hardware texture scaling is enabled, this saves the original.
|
// When hardware texture scaling is enabled, this saves the original.
|
||||||
int w = dataScaled ? mipWidth : mipUnscaledWidth;
|
int w = dataScaled ? mipWidth : mipUnscaledWidth;
|
||||||
int h = dataScaled ? mipHeight : mipUnscaledHeight;
|
int h = dataScaled ? mipHeight : mipUnscaledHeight;
|
||||||
// NOTE: Reading the decoded texture here may be very slow, if we just wrote it to write-combined memory.
|
// At this point, data should be saveData, and not slow.
|
||||||
replacer_.NotifyTextureDecoded(replacedInfo, data, stride, i, w, h);
|
replacer_.NotifyTextureDecoded(replacedInfo, data, stride, i, w, h);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue