diff --git a/ext/native/thin3d/VulkanRenderManager.cpp b/ext/native/thin3d/VulkanRenderManager.cpp index 1ba685ee70..cc4d3a1497 100644 --- a/ext/native/thin3d/VulkanRenderManager.cpp +++ b/ext/native/thin3d/VulkanRenderManager.cpp @@ -62,7 +62,6 @@ void CreateImage(VulkanContext *vulkan, VkCommandBuffer cmd, VKRImage &img, int res = vkBindImageMemory(vulkan->GetDevice(), img.image, img.memory, 0); _dbg_assert_(res == VK_SUCCESS); - VkImageAspectFlags viewAspects = color ? VK_IMAGE_ASPECT_COLOR_BIT : VK_IMAGE_ASPECT_DEPTH_BIT; VkImageAspectFlags aspects = color ? VK_IMAGE_ASPECT_COLOR_BIT : (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT); VkImageViewCreateInfo ivci{ VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO }; @@ -70,12 +69,21 @@ void CreateImage(VulkanContext *vulkan, VkCommandBuffer cmd, VKRImage &img, int ivci.format = ici.format; ivci.image = img.image; ivci.viewType = VK_IMAGE_VIEW_TYPE_2D; - ivci.subresourceRange.aspectMask = viewAspects; + ivci.subresourceRange.aspectMask = aspects; ivci.subresourceRange.layerCount = 1; ivci.subresourceRange.levelCount = 1; res = vkCreateImageView(vulkan->GetDevice(), &ivci, nullptr, &img.imageView); _dbg_assert_(res == VK_SUCCESS); + // Separate view for texture sampling that only exposes depth. + if (!color) { + ivci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + res = vkCreateImageView(vulkan->GetDevice(), &ivci, nullptr, &img.depthSampleView); + _dbg_assert_(res == VK_SUCCESS); + } else { + img.depthSampleView = VK_NULL_HANDLE; + } + VkPipelineStageFlags dstStage; VkAccessFlagBits dstAccessMask; switch (initialLayout) { @@ -985,7 +993,7 @@ VkImageView VulkanRenderManager::BindFramebufferAsTexture(VKRFramebuffer *fb, in for (int i = (int)steps_.size() - 1; i >= 0; i--) { if (steps_[i]->stepType == VKRStepType::RENDER && steps_[i]->render.framebuffer == fb) { - if (aspectBit & VK_IMAGE_ASPECT_COLOR_BIT) { + if (aspectBit == VK_IMAGE_ASPECT_COLOR_BIT) { // If this framebuffer was rendered to earlier in this frame, make sure to pre-transition it to the correct layout. if (steps_[i]->render.finalColorLayout == VK_IMAGE_LAYOUT_UNDEFINED) { steps_[i]->render.finalColorLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; @@ -994,8 +1002,7 @@ VkImageView VulkanRenderManager::BindFramebufferAsTexture(VKRFramebuffer *fb, in _assert_msg_(false, "Unexpected color layout %d", (int)steps_[i]->render.finalColorLayout); // May need to shadow the framebuffer if we re-order passes later. } - } - if (aspectBit & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { + } else if (aspectBit == VK_IMAGE_ASPECT_DEPTH_BIT) { // If this framebuffer was rendered to earlier in this frame, make sure to pre-transition it to the correct layout. if (steps_[i]->render.finalDepthStencilLayout == VK_IMAGE_LAYOUT_UNDEFINED) { steps_[i]->render.finalDepthStencilLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; @@ -1004,7 +1011,7 @@ VkImageView VulkanRenderManager::BindFramebufferAsTexture(VKRFramebuffer *fb, in _assert_msg_(false, "Unexpected depth layout %d", (int)steps_[i]->render.finalDepthStencilLayout); // May need to shadow the framebuffer if we re-order passes later. } - } + } // We don't (yet?) support texturing from stencil images. steps_[i]->render.numReads++; break; } @@ -1014,13 +1021,13 @@ VkImageView VulkanRenderManager::BindFramebufferAsTexture(VKRFramebuffer *fb, in curRenderStep_->dependencies.insert(fb); if (!curRenderStep_->preTransitions.empty() && - curRenderStep_->preTransitions.back().fb == fb && - curRenderStep_->preTransitions.back().targetLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { + curRenderStep_->preTransitions.back().fb == fb && + curRenderStep_->preTransitions.back().targetLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { // We're done. - return aspectBit == VK_IMAGE_ASPECT_COLOR_BIT ? fb->color.imageView : fb->depth.imageView; + return aspectBit == VK_IMAGE_ASPECT_COLOR_BIT ? fb->color.imageView : fb->depth.depthSampleView; } else { curRenderStep_->preTransitions.push_back({ aspectBit, fb, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }); - return aspectBit == VK_IMAGE_ASPECT_COLOR_BIT ? fb->color.imageView : fb->depth.imageView; + return aspectBit == VK_IMAGE_ASPECT_COLOR_BIT ? fb->color.imageView : fb->depth.depthSampleView; } } diff --git a/ext/native/thin3d/VulkanRenderManager.h b/ext/native/thin3d/VulkanRenderManager.h index f5ff60e3ad..9bac655676 100644 --- a/ext/native/thin3d/VulkanRenderManager.h +++ b/ext/native/thin3d/VulkanRenderManager.h @@ -23,6 +23,7 @@ struct VKRImage { VkImage image; VkImageView imageView; + VkImageView depthSampleView; VkDeviceMemory memory; VkImageLayout layout; VkFormat format; @@ -67,6 +68,8 @@ public: vulkan_->Delete().QueueDeleteImageView(color.imageView); if (depth.imageView) vulkan_->Delete().QueueDeleteImageView(depth.imageView); + if (depth.depthSampleView) + vulkan_->Delete().QueueDeleteImageView(depth.depthSampleView); if (color.memory) vulkan_->Delete().QueueDeleteDeviceMemory(color.memory); if (depth.memory) diff --git a/ext/native/thin3d/thin3d_vulkan.cpp b/ext/native/thin3d/thin3d_vulkan.cpp index e74f5f1615..7e4b504515 100644 --- a/ext/native/thin3d/thin3d_vulkan.cpp +++ b/ext/native/thin3d/thin3d_vulkan.cpp @@ -1525,15 +1525,21 @@ void VKContext::BindFramebufferAsRenderTarget(Framebuffer *fbo, const RenderPass void VKContext::BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChannel channelBit, int attachment) { VKFramebuffer *fb = (VKFramebuffer *)fbo; - if (fb == curFramebuffer_) { - Crash(); - } + // TODO: There are cases where this is okay, actually. + _assert_(fb != curFramebuffer_); int aspect = 0; - if (channelBit & FBChannel::FB_COLOR_BIT) aspect |= VK_IMAGE_ASPECT_COLOR_BIT; - if (channelBit & FBChannel::FB_DEPTH_BIT) aspect |= VK_IMAGE_ASPECT_DEPTH_BIT; - if (channelBit & FBChannel::FB_STENCIL_BIT) aspect |= VK_IMAGE_ASPECT_STENCIL_BIT; - + switch (channelBit) { + case FBChannel::FB_COLOR_BIT: + aspect = VK_IMAGE_ASPECT_COLOR_BIT; + break; + case FBChannel::FB_DEPTH_BIT: + aspect = VK_IMAGE_ASPECT_DEPTH_BIT; + break; + default: + _assert_(false); + break; + } boundTextures_[binding] = nullptr; boundImageView_[binding] = renderManager_.BindFramebufferAsTexture(fb->GetFB(), binding, aspect, attachment); }