mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Fix longstanding depth/stencil view issue in Vulkan. Cleans up validation.
We didn't specify DEPTH|STENCIL as aspects for views we rendered to, only DEPTH. Who knows how many of the driver bugs we "found" are this. DEPTH|STENCIL views can't be sampled though, so we create a separate DEPTH view for that. This keeps Katamari working.
This commit is contained in:
parent
b323397c54
commit
d54e0b3231
3 changed files with 33 additions and 17 deletions
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue