mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Merge pull request #17575 from hrydgard/vk-rip-out-input-attachments
Vulkan: Remove the remains of the input attachment experiment
This commit is contained in:
commit
8eb55a6fd7
17 changed files with 25 additions and 158 deletions
|
@ -265,7 +265,6 @@ static VkAttachmentStoreOp ConvertStoreAction(VKRRenderPassStoreAction action) {
|
||||||
// Also see https://www.khronos.org/registry/vulkan/specs/1.3-extensions/html/vkspec.html#synchronization-pipeline-barriers-subpass-self-dependencies
|
// Also see https://www.khronos.org/registry/vulkan/specs/1.3-extensions/html/vkspec.html#synchronization-pipeline-barriers-subpass-self-dependencies
|
||||||
|
|
||||||
VkRenderPass CreateRenderPass(VulkanContext *vulkan, const RPKey &key, RenderPassType rpType, VkSampleCountFlagBits sampleCount) {
|
VkRenderPass CreateRenderPass(VulkanContext *vulkan, const RPKey &key, RenderPassType rpType, VkSampleCountFlagBits sampleCount) {
|
||||||
bool selfDependency = RenderPassTypeHasInput(rpType);
|
|
||||||
bool isBackbuffer = rpType == RenderPassType::BACKBUFFER;
|
bool isBackbuffer = rpType == RenderPassType::BACKBUFFER;
|
||||||
bool hasDepth = RenderPassTypeHasDepth(rpType);
|
bool hasDepth = RenderPassTypeHasDepth(rpType);
|
||||||
bool multiview = RenderPassTypeHasMultiView(rpType);
|
bool multiview = RenderPassTypeHasMultiView(rpType);
|
||||||
|
@ -330,7 +329,7 @@ VkRenderPass CreateRenderPass(VulkanContext *vulkan, const RPKey &key, RenderPas
|
||||||
|
|
||||||
VkAttachmentReference colorReference{};
|
VkAttachmentReference colorReference{};
|
||||||
colorReference.attachment = colorAttachmentIndex;
|
colorReference.attachment = colorAttachmentIndex;
|
||||||
colorReference.layout = selfDependency ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
colorReference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||||
|
|
||||||
VkAttachmentReference depthReference{};
|
VkAttachmentReference depthReference{};
|
||||||
depthReference.attachment = depthAttachmentIndex;
|
depthReference.attachment = depthAttachmentIndex;
|
||||||
|
@ -339,20 +338,15 @@ VkRenderPass CreateRenderPass(VulkanContext *vulkan, const RPKey &key, RenderPas
|
||||||
VkSubpassDescription subpass{};
|
VkSubpassDescription subpass{};
|
||||||
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
||||||
subpass.flags = 0;
|
subpass.flags = 0;
|
||||||
if (selfDependency) {
|
|
||||||
subpass.inputAttachmentCount = 1;
|
|
||||||
subpass.pInputAttachments = &colorReference;
|
|
||||||
} else {
|
|
||||||
subpass.inputAttachmentCount = 0;
|
subpass.inputAttachmentCount = 0;
|
||||||
subpass.pInputAttachments = nullptr;
|
subpass.pInputAttachments = nullptr;
|
||||||
}
|
|
||||||
subpass.colorAttachmentCount = 1;
|
subpass.colorAttachmentCount = 1;
|
||||||
subpass.pColorAttachments = &colorReference;
|
subpass.pColorAttachments = &colorReference;
|
||||||
|
|
||||||
VkAttachmentReference colorResolveReference;
|
VkAttachmentReference colorResolveReference;
|
||||||
if (multisample) {
|
if (multisample) {
|
||||||
colorResolveReference.attachment = 0; // the non-msaa color buffer.
|
colorResolveReference.attachment = 0; // the non-msaa color buffer.
|
||||||
colorResolveReference.layout = selfDependency ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
colorResolveReference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||||
subpass.pResolveAttachments = &colorResolveReference;
|
subpass.pResolveAttachments = &colorResolveReference;
|
||||||
} else {
|
} else {
|
||||||
subpass.pResolveAttachments = nullptr;
|
subpass.pResolveAttachments = nullptr;
|
||||||
|
@ -396,17 +390,6 @@ VkRenderPass CreateRenderPass(VulkanContext *vulkan, const RPKey &key, RenderPas
|
||||||
numDeps++;
|
numDeps++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selfDependency) {
|
|
||||||
deps[numDeps].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
|
|
||||||
deps[numDeps].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
|
||||||
deps[numDeps].dstAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
|
|
||||||
deps[numDeps].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
|
||||||
deps[numDeps].dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
|
||||||
deps[numDeps].srcSubpass = 0;
|
|
||||||
deps[numDeps].dstSubpass = 0;
|
|
||||||
numDeps++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (numDeps > 0) {
|
if (numDeps > 0) {
|
||||||
rp.dependencyCount = (u32)numDeps;
|
rp.dependencyCount = (u32)numDeps;
|
||||||
rp.pDependencies = deps;
|
rp.pDependencies = deps;
|
||||||
|
@ -463,10 +446,6 @@ VkRenderPass CreateRenderPass(VulkanContext *vulkan, const RPKey &key, RenderPas
|
||||||
VkSubpassDescription2KHR subpass2{ VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2_KHR };
|
VkSubpassDescription2KHR subpass2{ VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2_KHR };
|
||||||
subpass2.colorAttachmentCount = subpass.colorAttachmentCount;
|
subpass2.colorAttachmentCount = subpass.colorAttachmentCount;
|
||||||
subpass2.flags = subpass.flags;
|
subpass2.flags = subpass.flags;
|
||||||
if (selfDependency) {
|
|
||||||
subpass2.inputAttachmentCount = subpass.inputAttachmentCount;
|
|
||||||
subpass2.pInputAttachments = &colorReference2;
|
|
||||||
}
|
|
||||||
subpass2.pColorAttachments = &colorReference2;
|
subpass2.pColorAttachments = &colorReference2;
|
||||||
if (hasDepth) {
|
if (hasDepth) {
|
||||||
subpass2.pDepthStencilAttachment = &depthReference2;
|
subpass2.pDepthStencilAttachment = &depthReference2;
|
||||||
|
@ -476,7 +455,7 @@ VkRenderPass CreateRenderPass(VulkanContext *vulkan, const RPKey &key, RenderPas
|
||||||
if (multisample) {
|
if (multisample) {
|
||||||
colorResolveReference2.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
colorResolveReference2.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
colorResolveReference2.attachment = colorResolveReference.attachment; // the non-msaa color buffer.
|
colorResolveReference2.attachment = colorResolveReference.attachment; // the non-msaa color buffer.
|
||||||
colorResolveReference2.layout = selfDependency ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
colorResolveReference2.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||||
subpass2.pResolveAttachments = &colorResolveReference2;
|
subpass2.pResolveAttachments = &colorResolveReference2;
|
||||||
} else {
|
} else {
|
||||||
subpass2.pResolveAttachments = nullptr;
|
subpass2.pResolveAttachments = nullptr;
|
||||||
|
|
|
@ -13,15 +13,14 @@ enum class RenderPassType {
|
||||||
// These eight are organized so that bit 0 is DEPTH and bit 1 is INPUT and bit 2 is MULTIVIEW, so
|
// These eight are organized so that bit 0 is DEPTH and bit 1 is INPUT and bit 2 is MULTIVIEW, so
|
||||||
// they can be OR-ed together in MergeRPTypes.
|
// they can be OR-ed together in MergeRPTypes.
|
||||||
HAS_DEPTH = 1,
|
HAS_DEPTH = 1,
|
||||||
COLOR_INPUT = 2, // input attachment
|
MULTIVIEW = 2,
|
||||||
MULTIVIEW = 4,
|
MULTISAMPLE = 4,
|
||||||
MULTISAMPLE = 8,
|
|
||||||
|
|
||||||
// This is the odd one out, and gets special handling in MergeRPTypes.
|
// This is the odd one out, and gets special handling in MergeRPTypes.
|
||||||
// If this flag is set, none of the other flags can be set.
|
// If this flag is set, none of the other flags can be set.
|
||||||
// For the backbuffer we can always use CLEAR/DONT_CARE, so bandwidth cost for a depth channel is negligible
|
// For the backbuffer we can always use CLEAR/DONT_CARE, so bandwidth cost for a depth channel is negligible
|
||||||
// so we don't bother with a non-depth version.
|
// so we don't bother with a non-depth version.
|
||||||
BACKBUFFER = 16,
|
BACKBUFFER = 8,
|
||||||
|
|
||||||
TYPE_COUNT = BACKBUFFER + 1,
|
TYPE_COUNT = BACKBUFFER + 1,
|
||||||
};
|
};
|
||||||
|
@ -107,10 +106,6 @@ inline bool RenderPassTypeHasDepth(RenderPassType type) {
|
||||||
return (type & RenderPassType::HAS_DEPTH) || type == RenderPassType::BACKBUFFER;
|
return (type & RenderPassType::HAS_DEPTH) || type == RenderPassType::BACKBUFFER;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool RenderPassTypeHasInput(RenderPassType type) {
|
|
||||||
return (type & RenderPassType::COLOR_INPUT) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool RenderPassTypeHasMultiView(RenderPassType type) {
|
inline bool RenderPassTypeHasMultiView(RenderPassType type) {
|
||||||
return (type & RenderPassType::MULTIVIEW) != 0;
|
return (type & RenderPassType::MULTIVIEW) != 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -261,31 +261,6 @@ VKRRenderPass *VulkanQueueRunner::GetRenderPass(const RPKey &key) {
|
||||||
return pass;
|
return pass;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Must match the subpass self-dependency declared above.
|
|
||||||
void VulkanQueueRunner::SelfDependencyBarrier(VKRImage &img, VkImageAspectFlags aspect, VulkanBarrier *recordBarrier) {
|
|
||||||
if (aspect & VK_IMAGE_ASPECT_COLOR_BIT) {
|
|
||||||
VkAccessFlags srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
|
||||||
VkAccessFlags dstAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
|
|
||||||
VkPipelineStageFlags srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
|
||||||
VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
|
||||||
recordBarrier->TransitionImage(
|
|
||||||
img.image,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
img.numLayers,
|
|
||||||
aspect,
|
|
||||||
VK_IMAGE_LAYOUT_GENERAL,
|
|
||||||
VK_IMAGE_LAYOUT_GENERAL,
|
|
||||||
srcAccessMask,
|
|
||||||
dstAccessMask,
|
|
||||||
srcStageMask,
|
|
||||||
dstStageMask
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
_assert_msg_(false, "Depth self-dependencies not yet supported");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void VulkanQueueRunner::PreprocessSteps(std::vector<VKRStep *> &steps) {
|
void VulkanQueueRunner::PreprocessSteps(std::vector<VKRStep *> &steps) {
|
||||||
// Optimizes renderpasses, then sequences them.
|
// Optimizes renderpasses, then sequences them.
|
||||||
// Planned optimizations:
|
// Planned optimizations:
|
||||||
|
@ -918,9 +893,6 @@ void VulkanQueueRunner::LogRenderPass(const VKRStep &pass, bool verbose) {
|
||||||
case VKRRenderCommand::REMOVED:
|
case VKRRenderCommand::REMOVED:
|
||||||
INFO_LOG(G3D, " (Removed)");
|
INFO_LOG(G3D, " (Removed)");
|
||||||
break;
|
break;
|
||||||
case VKRRenderCommand::SELF_DEPENDENCY_BARRIER:
|
|
||||||
INFO_LOG(G3D, " SelfBarrier()");
|
|
||||||
break;
|
|
||||||
case VKRRenderCommand::BIND_GRAPHICS_PIPELINE:
|
case VKRRenderCommand::BIND_GRAPHICS_PIPELINE:
|
||||||
INFO_LOG(G3D, " BindGraphicsPipeline(%x)", (int)(intptr_t)cmd.graphics_pipeline.pipeline);
|
INFO_LOG(G3D, " BindGraphicsPipeline(%x)", (int)(intptr_t)cmd.graphics_pipeline.pipeline);
|
||||||
break;
|
break;
|
||||||
|
@ -1361,21 +1333,6 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case VKRRenderCommand::SELF_DEPENDENCY_BARRIER:
|
|
||||||
{
|
|
||||||
_assert_(step.render.pipelineFlags & PipelineFlags::USES_INPUT_ATTACHMENT);
|
|
||||||
_assert_(fb);
|
|
||||||
VulkanBarrier barrier;
|
|
||||||
if (fb->sampleCount != VK_SAMPLE_COUNT_1_BIT) {
|
|
||||||
// Rendering is happening to the multisample buffer, not the color buffer.
|
|
||||||
SelfDependencyBarrier(fb->msaaColor, VK_IMAGE_ASPECT_COLOR_BIT, &barrier);
|
|
||||||
} else {
|
|
||||||
SelfDependencyBarrier(fb->color, VK_IMAGE_ASPECT_COLOR_BIT, &barrier);
|
|
||||||
}
|
|
||||||
barrier.Flush(cmd);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case VKRRenderCommand::PUSH_CONSTANTS:
|
case VKRRenderCommand::PUSH_CONSTANTS:
|
||||||
if (pipelineOK) {
|
if (pipelineOK) {
|
||||||
vkCmdPushConstants(cmd, pipelineLayout, c.push.stages, c.push.offset, c.push.size, c.push.data);
|
vkCmdPushConstants(cmd, pipelineLayout, c.push.stages, c.push.offset, c.push.size, c.push.data);
|
||||||
|
|
|
@ -39,7 +39,6 @@ enum class VKRRenderCommand : uint8_t {
|
||||||
DRAW,
|
DRAW,
|
||||||
DRAW_INDEXED,
|
DRAW_INDEXED,
|
||||||
PUSH_CONSTANTS,
|
PUSH_CONSTANTS,
|
||||||
SELF_DEPENDENCY_BARRIER,
|
|
||||||
DEBUG_ANNOTATION,
|
DEBUG_ANNOTATION,
|
||||||
NUM_RENDER_COMMANDS,
|
NUM_RENDER_COMMANDS,
|
||||||
};
|
};
|
||||||
|
@ -48,10 +47,9 @@ enum class PipelineFlags : u8 {
|
||||||
NONE = 0,
|
NONE = 0,
|
||||||
USES_BLEND_CONSTANT = (1 << 1),
|
USES_BLEND_CONSTANT = (1 << 1),
|
||||||
USES_DEPTH_STENCIL = (1 << 2), // Reads or writes the depth or stencil buffers.
|
USES_DEPTH_STENCIL = (1 << 2), // Reads or writes the depth or stencil buffers.
|
||||||
USES_INPUT_ATTACHMENT = (1 << 3),
|
USES_GEOMETRY_SHADER = (1 << 3),
|
||||||
USES_GEOMETRY_SHADER = (1 << 4),
|
USES_MULTIVIEW = (1 << 4), // Inherited from the render pass it was created with.
|
||||||
USES_MULTIVIEW = (1 << 5), // Inherited from the render pass it was created with.
|
USES_DISCARD = (1 << 5),
|
||||||
USES_DISCARD = (1 << 6),
|
|
||||||
};
|
};
|
||||||
ENUM_CLASS_BITOPS(PipelineFlags);
|
ENUM_CLASS_BITOPS(PipelineFlags);
|
||||||
|
|
||||||
|
@ -314,8 +312,6 @@ private:
|
||||||
static void SetupTransitionToTransferDst(VKRImage &img, VkImageAspectFlags aspect, VulkanBarrier *recordBarrier);
|
static void SetupTransitionToTransferDst(VKRImage &img, VkImageAspectFlags aspect, VulkanBarrier *recordBarrier);
|
||||||
static void SetupTransferDstWriteAfterWrite(VKRImage &img, VkImageAspectFlags aspect, VulkanBarrier *recordBarrier);
|
static void SetupTransferDstWriteAfterWrite(VKRImage &img, VkImageAspectFlags aspect, VulkanBarrier *recordBarrier);
|
||||||
|
|
||||||
static void SelfDependencyBarrier(VKRImage &img, VkImageAspectFlags aspect, VulkanBarrier *recordBarrier);
|
|
||||||
|
|
||||||
VulkanContext *vulkan_;
|
VulkanContext *vulkan_;
|
||||||
|
|
||||||
VkFramebuffer backbuffer_ = VK_NULL_HANDLE;
|
VkFramebuffer backbuffer_ = VK_NULL_HANDLE;
|
||||||
|
|
|
@ -659,10 +659,6 @@ VKRGraphicsPipeline *VulkanRenderManager::CreateGraphicsPipeline(VKRGraphicsPipe
|
||||||
WARN_LOG(G3D, "Not compiling pipeline that requires depth, for non depth renderpass type");
|
WARN_LOG(G3D, "Not compiling pipeline that requires depth, for non depth renderpass type");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ((pipelineFlags & PipelineFlags::USES_INPUT_ATTACHMENT) && !RenderPassTypeHasInput(rpType)) {
|
|
||||||
WARN_LOG(G3D, "Not compiling pipeline that requires input attachment, for non input renderpass type");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// Shouldn't hit this, these should have been filtered elsewhere. However, still a good check to do.
|
// Shouldn't hit this, these should have been filtered elsewhere. However, still a good check to do.
|
||||||
if (sampleCount == VK_SAMPLE_COUNT_1_BIT && RenderPassTypeHasMultisample(rpType)) {
|
if (sampleCount == VK_SAMPLE_COUNT_1_BIT && RenderPassTypeHasMultisample(rpType)) {
|
||||||
WARN_LOG(G3D, "Not compiling single sample pipeline for a multisampled render pass type");
|
WARN_LOG(G3D, "Not compiling single sample pipeline for a multisampled render pass type");
|
||||||
|
@ -712,10 +708,6 @@ void VulkanRenderManager::EndCurRenderStep() {
|
||||||
if (!curRenderStep_->render.framebuffer) {
|
if (!curRenderStep_->render.framebuffer) {
|
||||||
rpType = RenderPassType::BACKBUFFER;
|
rpType = RenderPassType::BACKBUFFER;
|
||||||
} else {
|
} else {
|
||||||
if (curPipelineFlags_ & PipelineFlags::USES_INPUT_ATTACHMENT) {
|
|
||||||
// Not allowed on backbuffers.
|
|
||||||
rpType = depthStencil ? (RenderPassType::HAS_DEPTH | RenderPassType::COLOR_INPUT) : RenderPassType::COLOR_INPUT;
|
|
||||||
}
|
|
||||||
// Framebuffers can be stereo, and if so, will control the render pass type to match.
|
// Framebuffers can be stereo, and if so, will control the render pass type to match.
|
||||||
// Pipelines can be mono and render fine to stereo etc, so not checking them here.
|
// Pipelines can be mono and render fine to stereo etc, so not checking them here.
|
||||||
// Note that we don't support rendering to just one layer of a multilayer framebuffer!
|
// Note that we don't support rendering to just one layer of a multilayer framebuffer!
|
||||||
|
@ -766,11 +758,6 @@ void VulkanRenderManager::EndCurRenderStep() {
|
||||||
curPipelineFlags_ = (PipelineFlags)0;
|
curPipelineFlags_ = (PipelineFlags)0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanRenderManager::BindCurrentFramebufferAsInputAttachment0(VkImageAspectFlags aspectBits) {
|
|
||||||
_dbg_assert_(curRenderStep_);
|
|
||||||
curRenderStep_->commands.push_back(VkRenderData{ VKRRenderCommand::SELF_DEPENDENCY_BARRIER });
|
|
||||||
}
|
|
||||||
|
|
||||||
void VulkanRenderManager::BindFramebufferAsRenderTarget(VKRFramebuffer *fb, VKRRenderPassLoadAction color, VKRRenderPassLoadAction depth, VKRRenderPassLoadAction stencil, uint32_t clearColor, float clearDepth, uint8_t clearStencil, const char *tag) {
|
void VulkanRenderManager::BindFramebufferAsRenderTarget(VKRFramebuffer *fb, VKRRenderPassLoadAction color, VKRRenderPassLoadAction depth, VKRRenderPassLoadAction stencil, uint32_t clearColor, float clearDepth, uint8_t clearStencil, const char *tag) {
|
||||||
_dbg_assert_(insideFrame_);
|
_dbg_assert_(insideFrame_);
|
||||||
// Eliminate dupes (bind of the framebuffer we already are rendering to), instantly convert to a clear if possible.
|
// Eliminate dupes (bind of the framebuffer we already are rendering to), instantly convert to a clear if possible.
|
||||||
|
|
|
@ -218,8 +218,6 @@ public:
|
||||||
// get an array texture view.
|
// get an array texture view.
|
||||||
VkImageView BindFramebufferAsTexture(VKRFramebuffer *fb, int binding, VkImageAspectFlags aspectBits, int layer);
|
VkImageView BindFramebufferAsTexture(VKRFramebuffer *fb, int binding, VkImageAspectFlags aspectBits, int layer);
|
||||||
|
|
||||||
void BindCurrentFramebufferAsInputAttachment0(VkImageAspectFlags aspectBits);
|
|
||||||
|
|
||||||
bool CopyFramebufferToMemory(VKRFramebuffer *src, VkImageAspectFlags aspectBits, int x, int y, int w, int h, Draw::DataFormat destFormat, uint8_t *pixels, int pixelStride, Draw::ReadbackMode mode, const char *tag);
|
bool CopyFramebufferToMemory(VKRFramebuffer *src, VkImageAspectFlags aspectBits, int x, int y, int w, int h, Draw::DataFormat destFormat, uint8_t *pixels, int pixelStride, Draw::ReadbackMode mode, const char *tag);
|
||||||
void CopyImageToMemorySync(VkImage image, int mipLevel, int x, int y, int w, int h, Draw::DataFormat destFormat, uint8_t *pixels, int pixelStride, const char *tag);
|
void CopyImageToMemorySync(VkImage image, int mipLevel, int x, int y, int w, int h, Draw::DataFormat destFormat, uint8_t *pixels, int pixelStride, const char *tag);
|
||||||
|
|
||||||
|
|
|
@ -438,7 +438,6 @@ public:
|
||||||
// These functions should be self explanatory.
|
// These functions should be self explanatory.
|
||||||
void BindFramebufferAsRenderTarget(Framebuffer *fbo, const RenderPassInfo &rp, const char *tag) override;
|
void BindFramebufferAsRenderTarget(Framebuffer *fbo, const RenderPassInfo &rp, const char *tag) override;
|
||||||
void BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChannel channelBit, int layer) override;
|
void BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChannel channelBit, int layer) override;
|
||||||
void BindCurrentFramebufferForColorInput() override;
|
|
||||||
|
|
||||||
void GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) override;
|
void GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) override;
|
||||||
|
|
||||||
|
@ -1011,9 +1010,9 @@ VKContext::VKContext(VulkanContext *vulkan)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Limited, through input attachments and self-dependencies.
|
// Vulkan can support this through input attachments and various extensions, but not worth
|
||||||
// We turn it off here already if buggy.
|
// the trouble.
|
||||||
caps_.framebufferFetchSupported = !bugs_.Has(Bugs::SUBPASS_FEEDBACK_BROKEN);
|
caps_.framebufferFetchSupported = false;
|
||||||
|
|
||||||
caps_.deviceID = deviceProps.deviceID;
|
caps_.deviceID = deviceProps.deviceID;
|
||||||
device_ = vulkan->GetDevice();
|
device_ = vulkan->GetDevice();
|
||||||
|
@ -1777,10 +1776,6 @@ void VKContext::BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChanne
|
||||||
boundImageView_[binding] = renderManager_.BindFramebufferAsTexture(fb->GetFB(), binding, aspect, layer);
|
boundImageView_[binding] = renderManager_.BindFramebufferAsTexture(fb->GetFB(), binding, aspect, layer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VKContext::BindCurrentFramebufferForColorInput() {
|
|
||||||
renderManager_.BindCurrentFramebufferAsInputAttachment0(VK_IMAGE_ASPECT_COLOR_BIT);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VKContext::GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) {
|
void VKContext::GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) {
|
||||||
VKFramebuffer *fb = (VKFramebuffer *)fbo;
|
VKFramebuffer *fb = (VKFramebuffer *)fbo;
|
||||||
if (fb) {
|
if (fb) {
|
||||||
|
|
|
@ -171,8 +171,8 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu
|
||||||
bool fetchFramebuffer = needFramebufferRead && id.Bit(FS_BIT_USE_FRAMEBUFFER_FETCH);
|
bool fetchFramebuffer = needFramebufferRead && id.Bit(FS_BIT_USE_FRAMEBUFFER_FETCH);
|
||||||
bool readFramebufferTex = needFramebufferRead && !id.Bit(FS_BIT_USE_FRAMEBUFFER_FETCH);
|
bool readFramebufferTex = needFramebufferRead && !id.Bit(FS_BIT_USE_FRAMEBUFFER_FETCH);
|
||||||
|
|
||||||
if (fetchFramebuffer && compat.shaderLanguage != GLSL_VULKAN && (compat.shaderLanguage != GLSL_3xx || !compat.lastFragData)) {
|
if (fetchFramebuffer && (compat.shaderLanguage != GLSL_3xx || !compat.lastFragData)) {
|
||||||
*errorString = "framebuffer fetch requires GLSL: vulkan or 3xx";
|
*errorString = "framebuffer fetch requires GLSL 3xx";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,9 +204,6 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu
|
||||||
if (readFramebufferTex) {
|
if (readFramebufferTex) {
|
||||||
// The framebuffer texture is always bound as an array.
|
// The framebuffer texture is always bound as an array.
|
||||||
p.F("layout (set = 0, binding = %d) uniform sampler2DArray fbotex;\n", DRAW_BINDING_2ND_TEXTURE);
|
p.F("layout (set = 0, binding = %d) uniform sampler2DArray fbotex;\n", DRAW_BINDING_2ND_TEXTURE);
|
||||||
} else if (fetchFramebuffer) {
|
|
||||||
p.F("layout (input_attachment_index = 0, set = 0, binding = %d) uniform subpassInput inputColor;\n", DRAW_BINDING_INPUT_ATTACHMENT);
|
|
||||||
*fragmentShaderFlags |= FragmentShaderFlags::INPUT_ATTACHMENT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shaderDepalMode != ShaderDepalMode::OFF) {
|
if (shaderDepalMode != ShaderDepalMode::OFF) {
|
||||||
|
|
|
@ -46,7 +46,6 @@ struct FShaderID;
|
||||||
|
|
||||||
// Can technically be deduced from the fragment shader ID, but this is safer.
|
// Can technically be deduced from the fragment shader ID, but this is safer.
|
||||||
enum class FragmentShaderFlags : u32 {
|
enum class FragmentShaderFlags : u32 {
|
||||||
INPUT_ATTACHMENT = 1,
|
|
||||||
USES_DISCARD = 2,
|
USES_DISCARD = 2,
|
||||||
};
|
};
|
||||||
ENUM_CLASS_BITOPS(FragmentShaderFlags);
|
ENUM_CLASS_BITOPS(FragmentShaderFlags);
|
||||||
|
|
|
@ -607,10 +607,6 @@ u32 GPUCommonHW::CheckGPUFeatures() const {
|
||||||
features |= GPU_USE_VS_RANGE_CULLING;
|
features |= GPU_USE_VS_RANGE_CULLING;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (draw_->GetDeviceCaps().framebufferFetchSupported) {
|
|
||||||
features |= GPU_USE_FRAMEBUFFER_FETCH;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (draw_->GetShaderLanguageDesc().bitwiseOps) {
|
if (draw_->GetShaderLanguageDesc().bitwiseOps) {
|
||||||
features |= GPU_USE_LIGHT_UBERSHADER;
|
features |= GPU_USE_LIGHT_UBERSHADER;
|
||||||
}
|
}
|
||||||
|
|
|
@ -123,17 +123,12 @@ void DrawEngineVulkan::InitDeviceObjects() {
|
||||||
bindings[8].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
bindings[8].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
||||||
bindings[8].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
bindings[8].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
||||||
bindings[8].binding = DRAW_BINDING_TESS_STORAGE_BUF_WV;
|
bindings[8].binding = DRAW_BINDING_TESS_STORAGE_BUF_WV;
|
||||||
// Note: This binding is not included if !gstate_c.Use(GPU_USE_FRAMEBUFFER_FETCH), using bindingCount below.
|
|
||||||
bindings[9].descriptorCount = 1;
|
|
||||||
bindings[9].descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
|
|
||||||
bindings[9].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
|
||||||
bindings[9].binding = DRAW_BINDING_INPUT_ATTACHMENT;
|
|
||||||
|
|
||||||
VulkanContext *vulkan = (VulkanContext *)draw_->GetNativeObject(Draw::NativeObject::CONTEXT);
|
VulkanContext *vulkan = (VulkanContext *)draw_->GetNativeObject(Draw::NativeObject::CONTEXT);
|
||||||
VkDevice device = vulkan->GetDevice();
|
VkDevice device = vulkan->GetDevice();
|
||||||
|
|
||||||
VkDescriptorSetLayoutCreateInfo dsl{ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO };
|
VkDescriptorSetLayoutCreateInfo dsl{ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO };
|
||||||
dsl.bindingCount = gstate_c.Use(GPU_USE_FRAMEBUFFER_FETCH) ? ARRAY_SIZE(bindings) : ARRAY_SIZE(bindings) - 1;
|
dsl.bindingCount = ARRAY_SIZE(bindings);
|
||||||
dsl.pBindings = bindings;
|
dsl.pBindings = bindings;
|
||||||
VkResult res = vkCreateDescriptorSetLayout(device, &dsl, nullptr, &descriptorSetLayout_);
|
VkResult res = vkCreateDescriptorSetLayout(device, &dsl, nullptr, &descriptorSetLayout_);
|
||||||
_dbg_assert_(VK_SUCCESS == res);
|
_dbg_assert_(VK_SUCCESS == res);
|
||||||
|
@ -141,17 +136,15 @@ void DrawEngineVulkan::InitDeviceObjects() {
|
||||||
|
|
||||||
static constexpr int DEFAULT_DESC_POOL_SIZE = 512;
|
static constexpr int DEFAULT_DESC_POOL_SIZE = 512;
|
||||||
std::vector<VkDescriptorPoolSize> dpTypes;
|
std::vector<VkDescriptorPoolSize> dpTypes;
|
||||||
dpTypes.resize(5);
|
dpTypes.resize(4);
|
||||||
dpTypes[0].descriptorCount = DEFAULT_DESC_POOL_SIZE * 3;
|
dpTypes[0].descriptorCount = DEFAULT_DESC_POOL_SIZE * 3;
|
||||||
dpTypes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
|
dpTypes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
|
||||||
dpTypes[1].descriptorCount = DEFAULT_DESC_POOL_SIZE * 3; // Don't use these for tess anymore, need max three per set.
|
dpTypes[1].descriptorCount = DEFAULT_DESC_POOL_SIZE * 3; // Don't use these for tess anymore, need max three per set.
|
||||||
dpTypes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
dpTypes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||||
dpTypes[2].descriptorCount = DEFAULT_DESC_POOL_SIZE * 3; // TODO: Use a separate layout when no spline stuff is needed to reduce the need for these.
|
dpTypes[2].descriptorCount = DEFAULT_DESC_POOL_SIZE * 3; // TODO: Use a separate layout when no spline stuff is needed to reduce the need for these.
|
||||||
dpTypes[2].type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
dpTypes[2].type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
||||||
dpTypes[3].descriptorCount = DEFAULT_DESC_POOL_SIZE; // TODO: Use a separate layout when no spline stuff is needed to reduce the need for these.
|
dpTypes[3].descriptorCount = DEFAULT_DESC_POOL_SIZE; // For the frame global uniform buffer. Might need to allocate multiple times.
|
||||||
dpTypes[3].type = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
|
dpTypes[3].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||||
dpTypes[4].descriptorCount = DEFAULT_DESC_POOL_SIZE; // For the frame global uniform buffer. Might need to allocate multiple times.
|
|
||||||
dpTypes[4].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
|
||||||
|
|
||||||
VkDescriptorPoolCreateInfo dp{ VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO };
|
VkDescriptorPoolCreateInfo dp{ VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO };
|
||||||
// Don't want to mess around with individually freeing these.
|
// Don't want to mess around with individually freeing these.
|
||||||
|
@ -386,7 +379,6 @@ VkDescriptorSet DrawEngineVulkan::GetOrCreateDescriptorSet(VkImageView imageView
|
||||||
key.base_ = base;
|
key.base_ = base;
|
||||||
key.light_ = light;
|
key.light_ = light;
|
||||||
key.bone_ = bone;
|
key.bone_ = bone;
|
||||||
key.secondaryIsInputAttachment = boundSecondaryIsInputAttachment_;
|
|
||||||
|
|
||||||
FrameData &frame = GetCurFrame();
|
FrameData &frame = GetCurFrame();
|
||||||
// See if we already have this descriptor set cached.
|
// See if we already have this descriptor set cached.
|
||||||
|
@ -425,15 +417,15 @@ VkDescriptorSet DrawEngineVulkan::GetOrCreateDescriptorSet(VkImageView imageView
|
||||||
}
|
}
|
||||||
|
|
||||||
if (boundSecondary_) {
|
if (boundSecondary_) {
|
||||||
tex[1].imageLayout = key.secondaryIsInputAttachment ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
tex[1].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||||
tex[1].imageView = boundSecondary_;
|
tex[1].imageView = boundSecondary_;
|
||||||
tex[1].sampler = samplerSecondaryNearest_;
|
tex[1].sampler = samplerSecondaryNearest_;
|
||||||
writes[n].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
writes[n].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||||
writes[n].pNext = nullptr;
|
writes[n].pNext = nullptr;
|
||||||
writes[n].dstBinding = key.secondaryIsInputAttachment ? DRAW_BINDING_INPUT_ATTACHMENT : DRAW_BINDING_2ND_TEXTURE;
|
writes[n].dstBinding = DRAW_BINDING_2ND_TEXTURE;
|
||||||
writes[n].pImageInfo = &tex[1];
|
writes[n].pImageInfo = &tex[1];
|
||||||
writes[n].descriptorCount = 1;
|
writes[n].descriptorCount = 1;
|
||||||
writes[n].descriptorType = key.secondaryIsInputAttachment ? VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT : VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
writes[n].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||||
writes[n].dstSet = desc;
|
writes[n].dstSet = desc;
|
||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -132,8 +132,7 @@ enum {
|
||||||
DRAW_BINDING_TESS_STORAGE_BUF = 6,
|
DRAW_BINDING_TESS_STORAGE_BUF = 6,
|
||||||
DRAW_BINDING_TESS_STORAGE_BUF_WU = 7,
|
DRAW_BINDING_TESS_STORAGE_BUF_WU = 7,
|
||||||
DRAW_BINDING_TESS_STORAGE_BUF_WV = 8,
|
DRAW_BINDING_TESS_STORAGE_BUF_WV = 8,
|
||||||
DRAW_BINDING_INPUT_ATTACHMENT = 9,
|
DRAW_BINDING_COUNT = 9,
|
||||||
DRAW_BINDING_COUNT = 10,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Handles transform, lighting and drawing.
|
// Handles transform, lighting and drawing.
|
||||||
|
@ -245,7 +244,6 @@ private:
|
||||||
|
|
||||||
// Secondary texture for shader blending
|
// Secondary texture for shader blending
|
||||||
VkImageView boundSecondary_ = VK_NULL_HANDLE;
|
VkImageView boundSecondary_ = VK_NULL_HANDLE;
|
||||||
bool boundSecondaryIsInputAttachment_ = false;
|
|
||||||
|
|
||||||
// CLUT texture for shader depal
|
// CLUT texture for shader depal
|
||||||
VkImageView boundDepal_ = VK_NULL_HANDLE;
|
VkImageView boundDepal_ = VK_NULL_HANDLE;
|
||||||
|
@ -264,7 +262,6 @@ private:
|
||||||
VkSampler sampler_;
|
VkSampler sampler_;
|
||||||
VkBuffer base_, light_, bone_; // All three UBO slots will be set to this. This will usually be identical
|
VkBuffer base_, light_, bone_; // All three UBO slots will be set to this. This will usually be identical
|
||||||
// for all draws in a frame, except when the buffer has to grow.
|
// for all draws in a frame, except when the buffer has to grow.
|
||||||
bool secondaryIsInputAttachment;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// We alternate between these.
|
// We alternate between these.
|
||||||
|
|
|
@ -280,7 +280,6 @@ u32 GPU_Vulkan::CheckGPUFeatures() const {
|
||||||
features |= GPU_USE_SINGLE_PASS_STEREO;
|
features |= GPU_USE_SINGLE_PASS_STEREO;
|
||||||
features |= GPU_USE_SIMPLE_STEREO_PERSPECTIVE;
|
features |= GPU_USE_SIMPLE_STEREO_PERSPECTIVE;
|
||||||
|
|
||||||
features &= ~GPU_USE_FRAMEBUFFER_FETCH; // Need to figure out if this can be supported with multiview rendering
|
|
||||||
if (features & GPU_USE_GS_CULLING) {
|
if (features & GPU_USE_GS_CULLING) {
|
||||||
// Many devices that support stereo and GS don't support GS during stereo.
|
// Many devices that support stereo and GS don't support GS during stereo.
|
||||||
features &= ~GPU_USE_GS_CULLING;
|
features &= ~GPU_USE_GS_CULLING;
|
||||||
|
@ -288,15 +287,6 @@ u32 GPU_Vulkan::CheckGPUFeatures() const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We need to turn off framebuffer fetch through input attachments if MSAA is on for now.
|
|
||||||
// This is fixable, just needs some shader generator work (subpassInputMS).
|
|
||||||
// Actually, I've decided to disable framebuffer fetch entirely for now. Perf isn't worth
|
|
||||||
// the compatibility problems.
|
|
||||||
|
|
||||||
// if (msaaLevel_ != 0) {
|
|
||||||
features &= ~GPU_USE_FRAMEBUFFER_FETCH;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Only a few low-power GPUs should probably avoid this.
|
// Only a few low-power GPUs should probably avoid this.
|
||||||
// Let's figure that out later.
|
// Let's figure that out later.
|
||||||
features |= GPU_USE_FRAGMENT_UBERSHADER;
|
features |= GPU_USE_FRAGMENT_UBERSHADER;
|
||||||
|
|
|
@ -356,9 +356,6 @@ VulkanPipeline *PipelineManagerVulkan::GetOrCreatePipeline(VulkanRenderManager *
|
||||||
return iter;
|
return iter;
|
||||||
|
|
||||||
PipelineFlags pipelineFlags = (PipelineFlags)0;
|
PipelineFlags pipelineFlags = (PipelineFlags)0;
|
||||||
if (fs->Flags() & FragmentShaderFlags::INPUT_ATTACHMENT) {
|
|
||||||
pipelineFlags |= PipelineFlags::USES_INPUT_ATTACHMENT;
|
|
||||||
}
|
|
||||||
if (fs->Flags() & FragmentShaderFlags::USES_DISCARD) {
|
if (fs->Flags() & FragmentShaderFlags::USES_DISCARD) {
|
||||||
pipelineFlags |= PipelineFlags::USES_DISCARD;
|
pipelineFlags |= PipelineFlags::USES_DISCARD;
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,7 +73,6 @@ struct VulkanPipeline {
|
||||||
|
|
||||||
bool UsesBlendConstant() const { return (pipelineFlags & PipelineFlags::USES_BLEND_CONSTANT) != 0; }
|
bool UsesBlendConstant() const { return (pipelineFlags & PipelineFlags::USES_BLEND_CONSTANT) != 0; }
|
||||||
bool UsesDepthStencil() const { return (pipelineFlags & PipelineFlags::USES_DEPTH_STENCIL) != 0; }
|
bool UsesDepthStencil() const { return (pipelineFlags & PipelineFlags::USES_DEPTH_STENCIL) != 0; }
|
||||||
bool UsesInputAttachment() const { return (pipelineFlags & PipelineFlags::USES_INPUT_ATTACHMENT) != 0; }
|
|
||||||
bool UsesGeometryShader() const { return (pipelineFlags & PipelineFlags::USES_GEOMETRY_SHADER) != 0; }
|
bool UsesGeometryShader() const { return (pipelineFlags & PipelineFlags::USES_GEOMETRY_SHADER) != 0; }
|
||||||
bool UsesDiscard() const { return (pipelineFlags & PipelineFlags::USES_DISCARD) != 0; }
|
bool UsesDiscard() const { return (pipelineFlags & PipelineFlags::USES_DISCARD) != 0; }
|
||||||
|
|
||||||
|
|
|
@ -520,7 +520,7 @@ enum class VulkanCacheDetectFlags {
|
||||||
};
|
};
|
||||||
|
|
||||||
#define CACHE_HEADER_MAGIC 0xff51f420
|
#define CACHE_HEADER_MAGIC 0xff51f420
|
||||||
#define CACHE_VERSION 45
|
#define CACHE_VERSION 46
|
||||||
|
|
||||||
struct VulkanCacheHeader {
|
struct VulkanCacheHeader {
|
||||||
uint32_t magic;
|
uint32_t magic;
|
||||||
|
|
|
@ -370,19 +370,12 @@ void DrawEngineVulkan::BindShaderBlendTex() {
|
||||||
bool bindResult = framebufferManager_->BindFramebufferAsColorTexture(1, curRenderVfb, BINDFBCOLOR_MAY_COPY | BINDFBCOLOR_UNCACHED, Draw::ALL_LAYERS);
|
bool bindResult = framebufferManager_->BindFramebufferAsColorTexture(1, curRenderVfb, BINDFBCOLOR_MAY_COPY | BINDFBCOLOR_UNCACHED, Draw::ALL_LAYERS);
|
||||||
_dbg_assert_(bindResult);
|
_dbg_assert_(bindResult);
|
||||||
boundSecondary_ = (VkImageView)draw_->GetNativeObject(Draw::NativeObject::BOUND_TEXTURE1_IMAGEVIEW);
|
boundSecondary_ = (VkImageView)draw_->GetNativeObject(Draw::NativeObject::BOUND_TEXTURE1_IMAGEVIEW);
|
||||||
boundSecondaryIsInputAttachment_ = false;
|
|
||||||
fboTexBound_ = true;
|
fboTexBound_ = true;
|
||||||
fboTexBindState_ = FBO_TEX_NONE;
|
fboTexBindState_ = FBO_TEX_NONE;
|
||||||
|
|
||||||
// Must dirty blend state here so we re-copy next time. Example: Lunar's spell effects.
|
// Must dirty blend state here so we re-copy next time. Example: Lunar's spell effects.
|
||||||
dirtyRequiresRecheck_ |= DIRTY_BLEND_STATE;
|
dirtyRequiresRecheck_ |= DIRTY_BLEND_STATE;
|
||||||
} else if (fboTexBindState_ == FBO_TEX_READ_FRAMEBUFFER) {
|
|
||||||
draw_->BindCurrentFramebufferForColorInput();
|
|
||||||
boundSecondary_ = (VkImageView)draw_->GetNativeObject(Draw::NativeObject::BOUND_FRAMEBUFFER_COLOR_IMAGEVIEW_RT, (void *)0);
|
|
||||||
boundSecondaryIsInputAttachment_ = true;
|
|
||||||
fboTexBindState_ = FBO_TEX_NONE;
|
|
||||||
} else {
|
} else {
|
||||||
boundSecondaryIsInputAttachment_ = false;
|
|
||||||
boundSecondary_ = VK_NULL_HANDLE;
|
boundSecondary_ = VK_NULL_HANDLE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue