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);
|
res = vkBindImageMemory(vulkan->GetDevice(), img.image, img.memory, 0);
|
||||||
_dbg_assert_(res == VK_SUCCESS);
|
_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);
|
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 };
|
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.format = ici.format;
|
||||||
ivci.image = img.image;
|
ivci.image = img.image;
|
||||||
ivci.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
ivci.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||||
ivci.subresourceRange.aspectMask = viewAspects;
|
ivci.subresourceRange.aspectMask = aspects;
|
||||||
ivci.subresourceRange.layerCount = 1;
|
ivci.subresourceRange.layerCount = 1;
|
||||||
ivci.subresourceRange.levelCount = 1;
|
ivci.subresourceRange.levelCount = 1;
|
||||||
res = vkCreateImageView(vulkan->GetDevice(), &ivci, nullptr, &img.imageView);
|
res = vkCreateImageView(vulkan->GetDevice(), &ivci, nullptr, &img.imageView);
|
||||||
_dbg_assert_(res == VK_SUCCESS);
|
_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;
|
VkPipelineStageFlags dstStage;
|
||||||
VkAccessFlagBits dstAccessMask;
|
VkAccessFlagBits dstAccessMask;
|
||||||
switch (initialLayout) {
|
switch (initialLayout) {
|
||||||
|
@ -985,7 +993,7 @@ VkImageView VulkanRenderManager::BindFramebufferAsTexture(VKRFramebuffer *fb, in
|
||||||
|
|
||||||
for (int i = (int)steps_.size() - 1; i >= 0; i--) {
|
for (int i = (int)steps_.size() - 1; i >= 0; i--) {
|
||||||
if (steps_[i]->stepType == VKRStepType::RENDER && steps_[i]->render.framebuffer == fb) {
|
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 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) {
|
if (steps_[i]->render.finalColorLayout == VK_IMAGE_LAYOUT_UNDEFINED) {
|
||||||
steps_[i]->render.finalColorLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
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);
|
_assert_msg_(false, "Unexpected color layout %d", (int)steps_[i]->render.finalColorLayout);
|
||||||
// May need to shadow the framebuffer if we re-order passes later.
|
// May need to shadow the framebuffer if we re-order passes later.
|
||||||
}
|
}
|
||||||
}
|
} else if (aspectBit == VK_IMAGE_ASPECT_DEPTH_BIT) {
|
||||||
if (aspectBit & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
|
|
||||||
// If this framebuffer was rendered to earlier in this frame, make sure to pre-transition it to the correct layout.
|
// 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) {
|
if (steps_[i]->render.finalDepthStencilLayout == VK_IMAGE_LAYOUT_UNDEFINED) {
|
||||||
steps_[i]->render.finalDepthStencilLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
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);
|
_assert_msg_(false, "Unexpected depth layout %d", (int)steps_[i]->render.finalDepthStencilLayout);
|
||||||
// May need to shadow the framebuffer if we re-order passes later.
|
// 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++;
|
steps_[i]->render.numReads++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1014,13 +1021,13 @@ VkImageView VulkanRenderManager::BindFramebufferAsTexture(VKRFramebuffer *fb, in
|
||||||
curRenderStep_->dependencies.insert(fb);
|
curRenderStep_->dependencies.insert(fb);
|
||||||
|
|
||||||
if (!curRenderStep_->preTransitions.empty() &&
|
if (!curRenderStep_->preTransitions.empty() &&
|
||||||
curRenderStep_->preTransitions.back().fb == fb &&
|
curRenderStep_->preTransitions.back().fb == fb &&
|
||||||
curRenderStep_->preTransitions.back().targetLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
|
curRenderStep_->preTransitions.back().targetLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
|
||||||
// We're done.
|
// 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 {
|
} else {
|
||||||
curRenderStep_->preTransitions.push_back({ aspectBit, fb, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL });
|
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 {
|
struct VKRImage {
|
||||||
VkImage image;
|
VkImage image;
|
||||||
VkImageView imageView;
|
VkImageView imageView;
|
||||||
|
VkImageView depthSampleView;
|
||||||
VkDeviceMemory memory;
|
VkDeviceMemory memory;
|
||||||
VkImageLayout layout;
|
VkImageLayout layout;
|
||||||
VkFormat format;
|
VkFormat format;
|
||||||
|
@ -67,6 +68,8 @@ public:
|
||||||
vulkan_->Delete().QueueDeleteImageView(color.imageView);
|
vulkan_->Delete().QueueDeleteImageView(color.imageView);
|
||||||
if (depth.imageView)
|
if (depth.imageView)
|
||||||
vulkan_->Delete().QueueDeleteImageView(depth.imageView);
|
vulkan_->Delete().QueueDeleteImageView(depth.imageView);
|
||||||
|
if (depth.depthSampleView)
|
||||||
|
vulkan_->Delete().QueueDeleteImageView(depth.depthSampleView);
|
||||||
if (color.memory)
|
if (color.memory)
|
||||||
vulkan_->Delete().QueueDeleteDeviceMemory(color.memory);
|
vulkan_->Delete().QueueDeleteDeviceMemory(color.memory);
|
||||||
if (depth.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) {
|
void VKContext::BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChannel channelBit, int attachment) {
|
||||||
VKFramebuffer *fb = (VKFramebuffer *)fbo;
|
VKFramebuffer *fb = (VKFramebuffer *)fbo;
|
||||||
|
|
||||||
if (fb == curFramebuffer_) {
|
// TODO: There are cases where this is okay, actually.
|
||||||
Crash();
|
_assert_(fb != curFramebuffer_);
|
||||||
}
|
|
||||||
|
|
||||||
int aspect = 0;
|
int aspect = 0;
|
||||||
if (channelBit & FBChannel::FB_COLOR_BIT) aspect |= VK_IMAGE_ASPECT_COLOR_BIT;
|
switch (channelBit) {
|
||||||
if (channelBit & FBChannel::FB_DEPTH_BIT) aspect |= VK_IMAGE_ASPECT_DEPTH_BIT;
|
case FBChannel::FB_COLOR_BIT:
|
||||||
if (channelBit & FBChannel::FB_STENCIL_BIT) aspect |= VK_IMAGE_ASPECT_STENCIL_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;
|
boundTextures_[binding] = nullptr;
|
||||||
boundImageView_[binding] = renderManager_.BindFramebufferAsTexture(fb->GetFB(), binding, aspect, attachment);
|
boundImageView_[binding] = renderManager_.BindFramebufferAsTexture(fb->GetFB(), binding, aspect, attachment);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue