fix(rendering): per-image semaphores and depth-format shadow placeholder

Avoid semaphore reuse while the presentation engine still holds a
reference by switching from per-frame-slot to per-swapchain-image
semaphores with a rotating free semaphore for acquire.

Replace the R8G8B8A8_UNORM dummy white texture in CharacterPreview
with a proper D16_UNORM depth texture cleared to 1.0, matching the
sampler2DShadow expectation in shaders. AMD RADV enforces strict
format/sampler type compatibility.
This commit is contained in:
Kelsi 2026-04-03 17:52:48 -07:00
parent 4f7912cf45
commit b2cb98e969
4 changed files with 148 additions and 22 deletions

View file

@ -19,8 +19,6 @@ static constexpr uint32_t MAX_FRAMES_IN_FLIGHT = 2;
struct FrameData {
VkCommandPool commandPool = VK_NULL_HANDLE;
VkCommandBuffer commandBuffer = VK_NULL_HANDLE;
VkSemaphore imageAvailableSemaphore = VK_NULL_HANDLE;
VkSemaphore renderFinishedSemaphore = VK_NULL_HANDLE;
VkFence inFlightFence = VK_NULL_HANDLE;
};
@ -197,6 +195,12 @@ private:
FrameData frames[MAX_FRAMES_IN_FLIGHT];
uint32_t currentFrame = 0;
// Per-swapchain-image semaphores (avoids reuse while presentation engine holds them)
std::vector<VkSemaphore> imageAcquiredSemaphores_; // [swapchainImageCount], per-image
std::vector<VkSemaphore> renderFinishedSemaphores_; // [swapchainImageCount], per-image
VkSemaphore nextAcquireSemaphore_ = VK_NULL_HANDLE; // free semaphore for next acquire
VkSemaphore currentAcquireSemaphore_ = VK_NULL_HANDLE; // the one used for the current frame
// Immediate submit resources
VkCommandPool immCommandPool = VK_NULL_HANDLE;
VkFence immFence = VK_NULL_HANDLE;