diff --git a/GPU/Common/DepalettizeShaderCommon.cpp b/GPU/Common/DepalettizeShaderCommon.cpp index 871fea767c..3e9cd383ab 100644 --- a/GPU/Common/DepalettizeShaderCommon.cpp +++ b/GPU/Common/DepalettizeShaderCommon.cpp @@ -21,6 +21,7 @@ #include "GPU/Common/ShaderId.h" #include "GPU/Common/ShaderCommon.h" +#include "Common/StringUtils.h" #include "Common/Log.h" #include "Core/Reporting.h" #include "GPU/GPUState.h" @@ -242,8 +243,16 @@ void GenerateDepalShaderFloat(char *buffer, GEBufferFormat pixelFormat, ShaderLa } break; case GE_FORMAT_DEPTH16: - sprintf(lookupMethod, "index.r * (1.0 / 256.0)"); + { + // TODO: I think we can handle most scenarios here, but texturing from depth buffers requires an extension on ES 2.0 anyway. + if ((mask & (mask + 1)) == 0 && shift < 16) { + index_multiplier = 1.0f / (float)(1 << shift); + truncate_cpy(lookupMethod, "index.r"); + } else { + formatOK = false; + } break; + } default: break; } diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index 06d6b08328..3a8e443ba5 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -1170,9 +1170,9 @@ bool FramebufferManagerCommon::NotifyFramebufferCopy(u32 src, u32 dst, int size, if (dstBuffer && srcBuffer && !isMemset) { if (srcBuffer == dstBuffer) { - WARN_LOG_REPORT_ONCE(dstsrccpy, G3D, "Intra-buffer memcpy (not supported) %08x -> %08x (size: %x)", src, dst, size); + WARN_LOG_ONCE(dstsrccpy, G3D, "Intra-buffer memcpy (not supported) %08x -> %08x (size: %x)", src, dst, size); } else { - WARN_LOG_REPORT_ONCE(dstnotsrccpy, G3D, "Inter-buffer memcpy %08x -> %08x (size: %x)", src, dst, size); + WARN_LOG_ONCE(dstnotsrccpy, G3D, "Inter-buffer memcpy %08x -> %08x (size: %x)", src, dst, size); // Just do the blit! BlitFramebuffer(dstBuffer, 0, dstY, srcBuffer, 0, srcY, srcBuffer->width, srcH, 0); SetColorUpdated(dstBuffer, skipDrawReason); @@ -1195,7 +1195,7 @@ bool FramebufferManagerCommon::NotifyFramebufferCopy(u32 src, u32 dst, int size, WARN_LOG_ONCE(btdcpy, G3D, "Memcpy fbo download %08x -> %08x", src, dst); FlushBeforeCopy(); if (srcH == 0 || srcY + srcH > srcBuffer->bufferHeight) { - WARN_LOG_REPORT_ONCE(btdcpyheight, G3D, "Memcpy fbo download %08x -> %08x skipped, %d+%d is taller than %d", src, dst, srcY, srcH, srcBuffer->bufferHeight); + WARN_LOG_ONCE(btdcpyheight, G3D, "Memcpy fbo download %08x -> %08x skipped, %d+%d is taller than %d", src, dst, srcY, srcH, srcBuffer->bufferHeight); } else if (g_Config.bBlockTransferGPU && !srcBuffer->memoryUpdated && !PSP_CoreParameter().compat.flags().DisableReadbacks) { ReadFramebufferToMemory(srcBuffer, 0, srcY, srcBuffer->width, srcH); srcBuffer->usageFlags = (srcBuffer->usageFlags | FB_USAGE_DOWNLOAD) & ~FB_USAGE_DOWNLOAD_CLEAR; diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 2789d1ff29..14f49ffa90 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -764,7 +764,7 @@ bool TextureCacheCommon::AttachFramebuffer(TexCacheEntry *entry, u32 address, Vi const u32 mirrorMask = 0x00600000; u32 addr = address & 0x3FFFFFFF; - u32 texaddr = (entry->addr + texaddrOffset) & ~mirrorMask; + u32 texaddr = entry->addr + texaddrOffset; if (entry->addr & 0x04000000) { addr &= ~mirrorMask; texaddr &= ~mirrorMask; @@ -800,8 +800,9 @@ bool TextureCacheCommon::AttachFramebuffer(TexCacheEntry *entry, u32 address, Vi // Check works for D16 too (???) const bool matchingClutFormat = - (framebuffer->format == GE_FORMAT_8888 && entry->format == GE_TFMT_CLUT32) || - (framebuffer->format != GE_FORMAT_8888 && entry->format == GE_TFMT_CLUT16); + (channel != NOTIFY_FB_COLOR && entry->format == GE_TFMT_CLUT16) || + (channel == NOTIFY_FB_COLOR && framebuffer->format == GE_FORMAT_8888 && entry->format == GE_TFMT_CLUT32) || + (channel == NOTIFY_FB_COLOR && framebuffer->format != GE_FORMAT_8888 && entry->format == GE_TFMT_CLUT16); const bool clutFormat = IsClutFormat((GETextureFormat)(entry->format)); diff --git a/ext/native/thin3d/VulkanQueueRunner.cpp b/ext/native/thin3d/VulkanQueueRunner.cpp index 0ede7acccc..0130f901db 100644 --- a/ext/native/thin3d/VulkanQueueRunner.cpp +++ b/ext/native/thin3d/VulkanQueueRunner.cpp @@ -1047,22 +1047,44 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c return; } - // Write-after-write hazards. Fixed flicker in God of War on ARM (before we added another fix). - // TODO: depth too - if (step.render.framebuffer && step.render.framebuffer->color.layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) { - VkImageMemoryBarrier barrier{}; - barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - barrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - barrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - barrier.subresourceRange.layerCount = 1; - barrier.subresourceRange.levelCount = 1; - barrier.image = step.render.framebuffer->color.image; - barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT; - barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - vkCmdPipelineBarrier(cmd, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier); + // Write-after-write hazards. Fixed flicker in God of War on ARM (before we added another fix that removed these). + if (step.render.framebuffer) { + int n = 0; + int stage = 0; + VkImageMemoryBarrier barriers[2]{}; + if (step.render.framebuffer->color.layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) { + barriers[n].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barriers[n].oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + barriers[n].newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + barriers[n].subresourceRange.layerCount = 1; + barriers[n].subresourceRange.levelCount = 1; + barriers[n].image = step.render.framebuffer->color.image; + barriers[n].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + barriers[n].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT; + barriers[n].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + barriers[n].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barriers[n].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + stage |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + n++; + } + if (step.render.framebuffer->depth.layout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL) { + barriers[n].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barriers[n].oldLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL; + barriers[n].newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + barriers[n].subresourceRange.layerCount = 1; + barriers[n].subresourceRange.levelCount = 1; + barriers[n].image = step.render.framebuffer->depth.image; + barriers[n].srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + barriers[n].dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; + barriers[n].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + barriers[n].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barriers[n].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + stage |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + n++; + } + if (stage) { + vkCmdPipelineBarrier(cmd, stage, stage, 0, 0, nullptr, 0, nullptr, n, barriers); + } } // This is supposed to bind a vulkan render pass to the command buffer.