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;
|
||||
|
||||
// TODO: Move the color conversion to the thread as well.
|
||||
// Actually may be better to re-decode using expand32?
|
||||
// Since we're copying, change the format meanwhile. Not much extra cost.
|
||||
if (replacedInfo.fmt != ReplacedTextureFormat::F_8888) {
|
||||
saveBuf.resize((pitch * h) / sizeof(u16));
|
||||
switch (replacedInfo.fmt) {
|
||||
|
|
|
@ -794,6 +794,7 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) {
|
|||
}
|
||||
|
||||
ReplacedTextureDecodeInfo replacedInfo;
|
||||
bool willSaveTex = false;
|
||||
if (replacer_.Enabled() && !replaced.Valid()) {
|
||||
replacedInfo.cachekey = entry->CacheKey();
|
||||
replacedInfo.hash = entry->fullhash;
|
||||
|
@ -802,6 +803,7 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) {
|
|||
replacedInfo.isFinal = (entry->status & TexCacheEntry::STATUS_TO_SCALE) == 0;
|
||||
replacedInfo.scaleFactor = scaleFactor;
|
||||
replacedInfo.fmt = FromVulkanFormat(actualFmt);
|
||||
willSaveTex = replacer_.WillSave(replacedInfo);
|
||||
}
|
||||
|
||||
if (entry->vkTex) {
|
||||
|
@ -821,6 +823,7 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) {
|
|||
if (replaced.Valid()) {
|
||||
replaced.GetSize(i, mipWidth, mipHeight);
|
||||
}
|
||||
|
||||
int bpp = actualFmt == VULKAN_8888_FORMAT ? 4 : 2;
|
||||
int stride = (mipWidth * bpp + 15) & ~15;
|
||||
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.
|
||||
int pushAlignment = std::max(16, (int)vulkan->GetPhysicalDeviceProperties().properties.limits.optimalBufferCopyOffsetAlignment);
|
||||
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;
|
||||
if (replaced.Valid()) {
|
||||
// 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);
|
||||
} else {
|
||||
if (fakeMipmap) {
|
||||
data = drawEngine_->GetPushBufferForTextureData()->PushAligned(size, &bufferOffset, &texBuf, pushAlignment);
|
||||
LoadTextureLevel(*entry, (uint8_t *)data, stride, level, scaleFactor, dstFmt);
|
||||
loadLevel(size, stride, scaleFactor);
|
||||
entry->vkTex->UploadMip(cmdInit, 0, mipWidth, mipHeight, texBuf, bufferOffset, stride / bpp);
|
||||
} else {
|
||||
if (computeUpload) {
|
||||
int srcBpp = dstFmt == VULKAN_8888_FORMAT ? 4 : 2;
|
||||
int srcStride = mipUnscaledWidth * srcBpp;
|
||||
int srcSize = srcStride * mipUnscaledHeight;
|
||||
|
||||
data = drawEngine_->GetPushBufferForTextureData()->PushAligned(srcSize, &bufferOffset, &texBuf, pushAlignment);
|
||||
loadLevel(srcSize, srcStride, 1);
|
||||
dataScaled = false;
|
||||
LoadTextureLevel(*entry, (uint8_t *)data, srcStride, i, 1, dstFmt);
|
||||
|
||||
// This format can be used with storage images.
|
||||
VkImageView view = entry->vkTex->CreateViewForMip(i);
|
||||
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);
|
||||
vulkan->Delete().QueueDeleteImageView(view);
|
||||
} else {
|
||||
data = drawEngine_->GetPushBufferForTextureData()->PushAligned(size, &bufferOffset, &texBuf, pushAlignment);
|
||||
LoadTextureLevel(*entry, (uint8_t *)data, stride, i, scaleFactor, dstFmt);
|
||||
loadLevel(size, stride, scaleFactor);
|
||||
VK_PROFILE_BEGIN(vulkan, cmdInit, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
"Copy Upload: %dx%d", mipWidth, mipHeight);
|
||||
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.
|
||||
int w = dataScaled ? mipWidth : mipUnscaledWidth;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue