diff --git a/src/d3d11/d3d11_context.cpp b/src/d3d11/d3d11_context.cpp index 9aff8553..a8b1d53c 100644 --- a/src/d3d11/d3d11_context.cpp +++ b/src/d3d11/d3d11_context.cpp @@ -2591,20 +2591,20 @@ namespace dxvk { // target bindings are updated. Set up the attachments. for (UINT i = 0; i < m_state.om.renderTargetViews.size(); i++) { if (m_state.om.renderTargetViews.at(i) != nullptr) { - attachments.setColorTarget(i, + attachments.color[i] = { m_state.om.renderTargetViews.at(i)->GetImageView(), - m_state.om.renderTargetViews.at(i)->GetRenderLayout()); + m_state.om.renderTargetViews.at(i)->GetRenderLayout() }; } } if (m_state.om.depthStencilView != nullptr) { - attachments.setDepthTarget( + attachments.depth = { m_state.om.depthStencilView->GetImageView(), - m_state.om.depthStencilView->GetRenderLayout()); + m_state.om.depthStencilView->GetRenderLayout() }; } // Create and bind the framebuffer object to the context - EmitCs([cAttachments = attachments] (DxvkContext* ctx) { + EmitCs([cAttachments = std::move(attachments)] (DxvkContext* ctx) { ctx->bindRenderTargets(cAttachments); }); } diff --git a/src/dxgi/dxgi_presenter.cpp b/src/dxgi/dxgi_presenter.cpp index 21afa4a7..116ea212 100644 --- a/src/dxgi/dxgi_presenter.cpp +++ b/src/dxgi/dxgi_presenter.cpp @@ -169,26 +169,27 @@ namespace dxvk { VK_FORMAT_UNDEFINED); } - const DxvkSwapSemaphores sem = m_swapchain->getSemaphorePair(); + auto swapSemas = m_swapchain->getSemaphorePair(); + auto swapImage = m_swapchain->getImageView(swapSemas.acquireSync); - auto framebuffer = m_swapchain->getFramebuffer(sem.acquireSync); - auto framebufferSize = framebuffer->size(); - - m_context->bindFramebuffer(framebuffer); + DxvkRenderTargets renderTargets; + renderTargets.color[0].view = swapImage; + renderTargets.color[0].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + m_context->bindRenderTargets(renderTargets); VkViewport viewport; viewport.x = 0.0f; viewport.y = 0.0f; - viewport.width = static_cast(framebufferSize.width); - viewport.height = static_cast(framebufferSize.height); + viewport.width = float(swapImage->imageInfo().extent.width); + viewport.height = float(swapImage->imageInfo().extent.height); viewport.minDepth = 0.0f; viewport.maxDepth = 1.0f; VkRect2D scissor; scissor.offset.x = 0; scissor.offset.y = 0; - scissor.extent.width = framebufferSize.width; - scissor.extent.height = framebufferSize.height; + scissor.extent.width = swapImage->imageInfo().extent.width; + scissor.extent.height = swapImage->imageInfo().extent.height; m_context->setViewports(1, &viewport, &scissor); @@ -214,9 +215,11 @@ namespace dxvk { m_device->submitCommandList( m_context->endRecording(), - sem.acquireSync, sem.presentSync); + swapSemas.acquireSync, + swapSemas.presentSync); - m_swapchain->present(sem.presentSync); + m_swapchain->present( + swapSemas.presentSync); } diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index b642e58b..084fe00c 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -85,31 +85,17 @@ namespace dxvk { } - void DxvkContext::bindFramebuffer(const Rc& fb) { - if (m_state.om.framebuffer != fb) { - this->spillRenderPass(); - - if (fb != nullptr) { - m_state.gp.state.msSampleCount = fb->sampleCount(); - m_state.gp.state.omRenderPass = fb->renderPass(); - - m_flags.set(DxvkContextFlag::GpDirtyPipelineState); - } - - m_state.om.framebuffer = fb; - } - - m_state.om.renderTargets = fb != nullptr - ? fb->renderTargets() - : DxvkRenderTargets(); - m_flags.clr(DxvkContextFlag::GpDirtyFramebuffer); - } - - void DxvkContext::bindRenderTargets(const DxvkRenderTargets& targets) { m_state.om.renderTargets = targets; - if (m_state.om.framebuffer == nullptr || !m_state.om.framebuffer->renderTargets().matches(targets)) { + // TODO execute pending clears + + // Set up default render pass ops + this->resetRenderPassOps( + m_state.om.renderTargets, + m_state.om.renderPassOps); + + if (m_state.om.framebuffer == nullptr || !m_state.om.framebuffer->hasTargets(targets)) { // Create a new framebuffer object next // time we start rendering something m_flags.set(DxvkContextFlag::GpDirtyFramebuffer); @@ -403,27 +389,36 @@ namespace dxvk { // Check whether the render target view is an attachment // of the current framebuffer. If not, we need to create // a temporary framebuffer. - uint32_t attachmentIndex = MaxNumRenderTargets; + int32_t attachmentIndex = -1; if (m_state.om.framebuffer != nullptr) attachmentIndex = m_state.om.framebuffer->findAttachment(imageView); - if (attachmentIndex == MaxNumRenderTargets) { + if (attachmentIndex < 0) { this->spillRenderPass(); + DxvkAttachmentOps op; + op.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + op.loadLayout = imageView->imageInfo().layout; + op.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + op.storeLayout = imageView->imageInfo().layout; + // Set up and bind a temporary framebuffer DxvkRenderTargets attachments; + DxvkRenderPassOps ops; if (clearAspects & VK_IMAGE_ASPECT_COLOR_BIT) { - attachments.setColorTarget(0, imageView, - imageView->pickLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)); + attachments.color[0].view = imageView; + attachments.color[0].layout = imageView->pickLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + ops.colorOps[0] = op; } else { - attachments.setDepthTarget(imageView, - imageView->pickLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)); + attachments.depth.view = imageView; + attachments.depth.layout = imageView->pickLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + ops.depthOps = op; } this->renderPassBindFramebuffer( - m_device->createFramebuffer(attachments)); + m_device->createFramebuffer(attachments), ops); } else { // Make sure that the currently bound // framebuffer can be rendered to @@ -436,7 +431,7 @@ namespace dxvk { clearInfo.colorAttachment = attachmentIndex; clearInfo.clearValue = clearValue; - if (attachmentIndex == MaxNumRenderTargets) + if (attachmentIndex < 0) clearInfo.colorAttachment = 0; m_cmd->cmdClearAttachments( @@ -444,7 +439,7 @@ namespace dxvk { // If we used a temporary framebuffer, we'll have to unbind it // again in order to not disturb subsequent rendering commands. - if (attachmentIndex == MaxNumRenderTargets) + if (attachmentIndex < 0) this->renderPassUnbindFramebuffer(); } @@ -1524,12 +1519,23 @@ namespace dxvk { if (!m_flags.test(DxvkContextFlag::GpRenderPassBound) && (m_state.om.framebuffer != nullptr)) { m_flags.set(DxvkContextFlag::GpRenderPassBound); - this->renderPassBindFramebuffer(m_state.om.framebuffer); + + this->renderPassBindFramebuffer( + m_state.om.framebuffer, + m_state.om.renderPassOps); + + // Don't discard image contents if we have + // to spill the current render pass + this->resetRenderPassOps( + m_state.om.renderTargets, + m_state.om.renderPassOps); } } void DxvkContext::spillRenderPass() { + // TODO execute pending clears + if (m_flags.test(DxvkContextFlag::GpRenderPassBound)) { m_flags.clr(DxvkContextFlag::GpRenderPassBound); this->renderPassUnbindFramebuffer(); @@ -1537,7 +1543,9 @@ namespace dxvk { } - void DxvkContext::renderPassBindFramebuffer(const Rc& framebuffer) { + void DxvkContext::renderPassBindFramebuffer( + const Rc& framebuffer, + const DxvkRenderPassOps& ops) { const DxvkFramebufferSize fbSize = framebuffer->size(); VkRect2D renderArea; @@ -1547,7 +1555,7 @@ namespace dxvk { VkRenderPassBeginInfo info; info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; info.pNext = nullptr; - info.renderPass = framebuffer->renderPass(); + info.renderPass = framebuffer->getRenderPassHandle(ops); info.framebuffer = framebuffer->handle(); info.renderArea = renderArea; info.clearValueCount = 0; @@ -1565,6 +1573,31 @@ namespace dxvk { } + void DxvkContext::resetRenderPassOps( + const DxvkRenderTargets& renderTargets, + DxvkRenderPassOps& renderPassOps) { + renderPassOps.depthOps = renderTargets.depth.view != nullptr + ? DxvkAttachmentOps { + VK_ATTACHMENT_LOAD_OP_LOAD, renderTargets.depth.view->imageInfo().layout, + VK_ATTACHMENT_STORE_OP_STORE, renderTargets.depth.view->imageInfo().layout } + : DxvkAttachmentOps { }; + + for (uint32_t i = 0; i < MaxNumRenderTargets; i++) { + renderPassOps.colorOps[i] = renderTargets.color[i].view != nullptr + ? DxvkAttachmentOps { + VK_ATTACHMENT_LOAD_OP_LOAD, renderTargets.color[i].view->imageInfo().layout, + VK_ATTACHMENT_STORE_OP_STORE, renderTargets.color[i].view->imageInfo().layout } + : DxvkAttachmentOps { }; + } + + // TODO provide a sane alternative for this + if (renderPassOps.colorOps[0].loadLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) { + renderPassOps.colorOps[0].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + renderPassOps.colorOps[0].loadLayout = VK_IMAGE_LAYOUT_UNDEFINED; + } + } + + void DxvkContext::unbindComputePipeline() { m_flags.set( DxvkContextFlag::CpDirtyPipeline, @@ -1724,7 +1757,7 @@ namespace dxvk { DxvkAttachment depthAttachment; if (bindPoint == VK_PIPELINE_BIND_POINT_GRAPHICS && m_state.om.framebuffer != nullptr) - depthAttachment = m_state.om.framebuffer->renderTargets().getDepthTarget(); + depthAttachment = m_state.om.framebuffer->getDepthTarget(); for (uint32_t i = 0; i < layout->bindingCount(); i++) { const auto& binding = layout->binding(i); @@ -1836,8 +1869,8 @@ namespace dxvk { auto fb = m_device->createFramebuffer(m_state.om.renderTargets); - m_state.gp.state.msSampleCount = fb->sampleCount(); - m_state.gp.state.omRenderPass = fb->renderPass(); + m_state.gp.state.msSampleCount = fb->getSampleCount(); + m_state.gp.state.omRenderPass = fb->getDefaultRenderPassHandle(); m_state.om.framebuffer = fb; m_flags.set(DxvkContextFlag::GpDirtyPipelineState); diff --git a/src/dxvk/dxvk_context.h b/src/dxvk/dxvk_context.h index 81f9a460..e3743fa7 100644 --- a/src/dxvk/dxvk_context.h +++ b/src/dxvk/dxvk_context.h @@ -71,13 +71,6 @@ namespace dxvk { void endQuery( const DxvkQueryRevision& query); - /** - * \brief Sets framebuffer - * \param [in] fb Framebuffer - */ - void bindFramebuffer( - const Rc& fb); - /** * \brief Sets render targets * @@ -650,9 +643,15 @@ namespace dxvk { void spillRenderPass(); void renderPassBindFramebuffer( - const Rc& framebuffer); + const Rc& framebuffer, + const DxvkRenderPassOps& ops); + void renderPassUnbindFramebuffer(); + void resetRenderPassOps( + const DxvkRenderTargets& renderTargets, + DxvkRenderPassOps& renderPassOps); + void unbindComputePipeline(); void updateComputePipeline(); diff --git a/src/dxvk/dxvk_context_state.h b/src/dxvk/dxvk_context_state.h index 59692883..5516e362 100644 --- a/src/dxvk/dxvk_context_state.h +++ b/src/dxvk/dxvk_context_state.h @@ -54,7 +54,10 @@ namespace dxvk { struct DxvkOutputMergerState { + std::array clearValue; + DxvkRenderTargets renderTargets; + DxvkRenderPassOps renderPassOps; Rc framebuffer = nullptr; DxvkBlendConstants blendConstants = { 0.0f, 0.0f, 0.0f, 0.0f }; diff --git a/src/dxvk/dxvk_device.cpp b/src/dxvk/dxvk_device.cpp index c961d638..72aaa4b2 100644 --- a/src/dxvk/dxvk_device.cpp +++ b/src/dxvk/dxvk_device.cpp @@ -117,11 +117,11 @@ namespace dxvk { m_properties.limits.maxFramebufferHeight, m_properties.limits.maxFramebufferLayers }; - auto format = renderTargets.renderPassFormat(); - auto renderPass = m_renderPassPool->getRenderPass(format); + auto renderPassFormat = DxvkFramebuffer::getRenderPassFormat(renderTargets); + auto renderPassObject = m_renderPassPool->getRenderPass(renderPassFormat); return new DxvkFramebuffer(m_vkd, - renderPass, renderTargets, defaultSize); + renderPassObject, renderTargets, defaultSize); } diff --git a/src/dxvk/dxvk_framebuffer.cpp b/src/dxvk/dxvk_framebuffer.cpp index 1128de2c..46865662 100644 --- a/src/dxvk/dxvk_framebuffer.cpp +++ b/src/dxvk/dxvk_framebuffer.cpp @@ -2,142 +2,117 @@ namespace dxvk { - DxvkRenderTargets:: DxvkRenderTargets() { } - DxvkRenderTargets::~DxvkRenderTargets() { } - - - DxvkRenderPassFormat DxvkRenderTargets::renderPassFormat() const { - DxvkRenderPassFormat result; - - for (uint32_t i = 0; i < MaxNumRenderTargets; i++) { - if (m_colorTargets.at(i).view != nullptr) { - result.setColorFormat(i, DxvkRenderTargetFormat { - m_colorTargets.at(i).view->info().format, - m_colorTargets.at(i).view->imageInfo().layout, - m_colorTargets.at(i).view->imageInfo().layout, - m_colorTargets.at(i).layout }); - result.setSampleCount(m_colorTargets.at(i).view->imageInfo().sampleCount); - } - } - - if (m_depthTarget.view != nullptr) { - result.setDepthFormat(DxvkRenderTargetFormat { - m_depthTarget.view->info().format, - m_depthTarget.view->imageInfo().layout, - m_depthTarget.view->imageInfo().layout, - m_depthTarget.layout }); - result.setSampleCount(m_depthTarget.view->imageInfo().sampleCount); - } - - return result; - } - - - uint32_t DxvkRenderTargets::getAttachments(VkImageView* viewHandles) const { - uint32_t numViews = 0; - - if (m_depthTarget.view != nullptr) - viewHandles[numViews++] = m_depthTarget.view->handle(); - - for (uint32_t i = 0; i < MaxNumRenderTargets; i++) { - if (m_colorTargets.at(i).view != nullptr) - viewHandles[numViews++] = m_colorTargets.at(i).view->handle(); - } - - return numViews; - } - - - DxvkFramebufferSize DxvkRenderTargets::getImageSize( - const DxvkFramebufferSize& defaultSize) const { - if (m_depthTarget.view != nullptr) - return this->renderTargetSize(m_depthTarget.view); - - for (uint32_t i = 0; i < MaxNumRenderTargets; i++) { - if (m_colorTargets.at(i).view != nullptr) - return this->renderTargetSize(m_colorTargets.at(i).view); - } - - return defaultSize; - } - - - bool DxvkRenderTargets::hasAttachments() const { - bool result = m_depthTarget.view != nullptr; - - for (uint32_t i = 0; (i < MaxNumRenderTargets) && !result; i++) - result |= m_colorTargets.at(i).view != nullptr; - - return result; - } - - - bool DxvkRenderTargets::matches(const DxvkRenderTargets& other) const { - bool equal = m_depthTarget.view == other.m_depthTarget.view - && m_depthTarget.layout == other.m_depthTarget.layout; - - for (uint32_t i = 0; i < MaxNumRenderTargets && equal; i++) { - equal &= m_colorTargets.at(i).view == other.m_colorTargets.at(i).view - && m_colorTargets.at(i).layout == other.m_colorTargets.at(i).layout; - } - - return equal; - } - - - DxvkFramebufferSize DxvkRenderTargets::renderTargetSize( - const Rc& renderTarget) const { - auto extent = renderTarget->mipLevelExtent(0); - auto layers = renderTarget->info().numLayers; - return DxvkFramebufferSize { extent.width, extent.height, layers }; - } - - DxvkFramebuffer::DxvkFramebuffer( const Rc& vkd, const Rc& renderPass, const DxvkRenderTargets& renderTargets, const DxvkFramebufferSize& defaultSize) - : m_vkd (vkd), - m_renderPass (renderPass), - m_renderTargets (renderTargets), - m_framebufferSize (renderTargets.getImageSize(defaultSize)) { + : m_vkd (vkd), + m_renderPass (renderPass), + m_renderTargets (renderTargets), + m_renderSize (computeRenderSize(defaultSize)) { std::array views; - uint32_t viewCount = renderTargets.getAttachments(views.data()); + + uint32_t viewId = 0; + + for (uint32_t i = 0; i < MaxNumRenderTargets; i++) { + if (m_renderTargets.color[i].view != nullptr) { + views[viewId] = m_renderTargets.color[i].view->handle(); + m_attachments[viewId] = &m_renderTargets.color[i]; + viewId += 1; + } + } + + if (m_renderTargets.depth.view != nullptr) { + views[viewId] = m_renderTargets.depth.view->handle(); + m_attachments[viewId] = &m_renderTargets.depth; + viewId += 1; + } VkFramebufferCreateInfo info; info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; info.pNext = nullptr; info.flags = 0; - info.renderPass = renderPass->handle(); - info.attachmentCount = viewCount; + info.renderPass = m_renderPass->getDefaultHandle(); + info.attachmentCount = viewId; info.pAttachments = views.data(); - info.width = m_framebufferSize.width; - info.height = m_framebufferSize.height; - info.layers = m_framebufferSize.layers; + info.width = m_renderSize.width; + info.height = m_renderSize.height; + info.layers = m_renderSize.layers; - if (m_vkd->vkCreateFramebuffer(m_vkd->device(), &info, nullptr, &m_framebuffer) != VK_SUCCESS) - throw DxvkError("DxvkFramebuffer: Failed to create framebuffer object"); + if (m_vkd->vkCreateFramebuffer(m_vkd->device(), &info, nullptr, &m_handle) != VK_SUCCESS) + Logger::err("DxvkFramebuffer: Failed to create framebuffer object"); } DxvkFramebuffer::~DxvkFramebuffer() { - m_vkd->vkDestroyFramebuffer( - m_vkd->device(), m_framebuffer, nullptr); + m_vkd->vkDestroyFramebuffer(m_vkd->device(), m_handle, nullptr); } - uint32_t DxvkFramebuffer::findAttachment( - const Rc& view) const { - if (m_renderTargets.getDepthTarget().view == view) - return 0; - - for (uint32_t i = 0; i < MaxNumRenderTargets; i++) { - if (m_renderTargets.getColorTarget(i).view == view) - return i; + int32_t DxvkFramebuffer::findAttachment(const Rc& view) const { + for (uint32_t i = 0; i < m_attachmentCount; i++) { + if (m_attachments[i]->view == view) + return int32_t(i); } - return MaxNumRenderTargets; + return -1; + } + + + bool DxvkFramebuffer::hasTargets(const DxvkRenderTargets& renderTargets) { + bool eq = m_renderTargets.depth.view == renderTargets.depth.view + && m_renderTargets.depth.layout == renderTargets.depth.layout; + + for (uint32_t i = 0; i < MaxNumRenderTargets && eq; i++) { + eq &= m_renderTargets.color[i].view == renderTargets.color[i].view + && m_renderTargets.color[i].layout == renderTargets.color[i].layout; + } + + return eq; + } + + + DxvkRenderPassFormat DxvkFramebuffer::getRenderPassFormat(const DxvkRenderTargets& renderTargets) { + DxvkRenderPassFormat format; + + for (uint32_t i = 0; i < MaxNumRenderTargets; i++) { + if (renderTargets.color[i].view != nullptr) { + format.sampleCount = renderTargets.color[i].view->imageInfo().sampleCount; + format.color[i].format = renderTargets.color[i].view->info().format; + format.color[i].layout = renderTargets.color[i].layout; + } + } + + if (renderTargets.depth.view != nullptr) { + format.sampleCount = renderTargets.depth.view->imageInfo().sampleCount; + format.depth.format = renderTargets.depth.view->info().format; + format.depth.layout = renderTargets.depth.layout; + } + + return format; + } + + + DxvkFramebufferSize DxvkFramebuffer::computeRenderSize( + const DxvkFramebufferSize& defaultSize) const { + if (m_renderTargets.depth.view != nullptr) + return this->computeRenderTargetSize(m_renderTargets.depth.view); + + for (uint32_t i = 0; i < MaxNumRenderTargets; i++) { + if (m_renderTargets.color[i].view != nullptr) + return this->computeRenderTargetSize(m_renderTargets.color[i].view); + } + + return defaultSize; + } + + + DxvkFramebufferSize DxvkFramebuffer::computeRenderTargetSize( + const Rc& renderTarget) const { + auto extent = renderTarget->mipLevelExtent(0); + auto layers = renderTarget->info().numLayers; + return DxvkFramebufferSize { extent.width, extent.height, layers }; } } \ No newline at end of file diff --git a/src/dxvk/dxvk_framebuffer.h b/src/dxvk/dxvk_framebuffer.h index b5edad79..592b6d96 100644 --- a/src/dxvk/dxvk_framebuffer.h +++ b/src/dxvk/dxvk_framebuffer.h @@ -19,6 +19,12 @@ namespace dxvk { }; + /** + * \brief Framebuffer attachment + * + * Stores an attachment, as well as the image layout + * that will be used for rendering to the attachment. + */ struct DxvkAttachment { Rc view = nullptr; VkImageLayout layout = VK_IMAGE_LAYOUT_UNDEFINED; @@ -26,127 +32,23 @@ namespace dxvk { /** - * \brief Render target description + * \brief Render targets * - * Stores render targets for a framebuffer object - * and provides methods to query the render pass - * format. Note that all render target views must - * have the same size and number of array layers. + * Stores all depth-stencil and color + * attachments attached to a framebuffer. */ - class DxvkRenderTargets { - - public: - - DxvkRenderTargets(); - ~DxvkRenderTargets(); - - /** - * \brief Retrieves color target - * - * \param [in] id Color attachment ID - * \returns Render target view - */ - DxvkAttachment getColorTarget(uint32_t id) const { - return m_colorTargets.at(id); - } - - /** - * \brief Retrieves depth-stencil target - * \returns Depth-stencil target view - */ - DxvkAttachment getDepthTarget() const { - return m_depthTarget; - } - - /** - * \brief Sets color target - * - * \param [in] id Color attachment ID - * \param [in] view Render target view - * \param [in] layout Layout to use for rendering - */ - void setColorTarget( - uint32_t id, - const Rc& view, - VkImageLayout layout) { - m_colorTargets.at(id) = { view, layout }; - } - - /** - * \brief Sets depth-stencil target - * - * \param [in] layout Layout to use for rendering - * \param [in] view Depth-stencil target view - */ - void setDepthTarget( - const Rc& view, - VkImageLayout layout) { - m_depthTarget = { view, layout }; - } - - /** - * \brief Render pass format - * - * Computes the render pass format based on - * the color and depth-stencil attachments. - * \returns Render pass format - */ - DxvkRenderPassFormat renderPassFormat() const; - - /** - * \brief Creates attachment list - * - * \param [out] viewHandles Attachment handles - * \returns Framebuffer attachment count - */ - uint32_t getAttachments(VkImageView* viewHandles) const; - - /** - * \brief Framebuffer size - * - * The width, height and layer count of the - * attached render targets. - * \param [in] defaultSize Size to use when - * there are no framebuffer attachments. - * \returns Framebuffer size - */ - DxvkFramebufferSize getImageSize( - const DxvkFramebufferSize& defaultSize) const; - - /** - * \brief Checks whether any attachments are defined - * \returns \c false if no attachments are defined - */ - bool hasAttachments() const; - - /** - * \brief Compares two sets of render targets - * - * Checks whether two sets of render targets - * are identical, including the image layout. - * \param [in] other Render target set to compare to - * \returns \c true if the render targets are the same - */ - bool matches(const DxvkRenderTargets& other) const; - - private: - - std::array m_colorTargets; - DxvkAttachment m_depthTarget; - - DxvkFramebufferSize renderTargetSize( - const Rc& renderTarget) const; - + struct DxvkRenderTargets { + DxvkAttachment depth; + DxvkAttachment color[MaxNumRenderTargets]; }; /** - * \brief DXVK framebuffer + * \brief Framebuffer * * A framebuffer either stores a set of image views * that will be used as render targets, or in case - * no render targets are being used, fixed viewport - * dimensions. + * no render targets are attached, fixed dimensions. */ class DxvkFramebuffer : public DxvkResource { @@ -157,6 +59,7 @@ namespace dxvk { const Rc& renderPass, const DxvkRenderTargets& renderTargets, const DxvkFramebufferSize& defaultSize); + ~DxvkFramebuffer(); /** @@ -164,15 +67,7 @@ namespace dxvk { * \returns Framebuffer handle */ VkFramebuffer handle() const { - return m_framebuffer; - } - - /** - * \brief Render pass handle - * \returns Render pass handle - */ - VkRenderPass renderPass() const { - return m_renderPass->handle(); + return m_handle; } /** @@ -180,45 +75,124 @@ namespace dxvk { * \returns Framebuffer size */ DxvkFramebufferSize size() const { - return m_framebufferSize; - } - - /** - * \brief Render target info - * \returns Render target info - */ - const DxvkRenderTargets& renderTargets() const { - return m_renderTargets; + return m_renderSize; } /** * \brief Sample count * \returns Sample count */ - VkSampleCountFlagBits sampleCount() const { - return m_renderPass->sampleCount(); + VkSampleCountFlagBits getSampleCount() const { + return m_renderPass->getSampleCount(); } /** - * \brief Retrieves index of a given attachment + * \brief Retrieves default render pass handle * - * \param [in] view The image view to look up - * \returns The attachment index, or \c 0 for a depth-stencil - * attachment, or \c MaxNumRenderTargets if the given - * view is not a framebuffer attachment. + * Retrieves the render pass handle that was used + * to create the Vulkan framebuffer object with, + * and that should be used to create pipelines. + * \returns The default render pass handle */ - uint32_t findAttachment( - const Rc& view) const; + VkRenderPass getDefaultRenderPassHandle() const { + return m_renderPass->getDefaultHandle(); + } + + /** + * \brief Retrieves render pass handle + * + * Retrieves a render pass handle that can + * be used to begin a render pass instance. + * \param [in] ops Render pass ops + * \returns The render pass handle + */ + VkRenderPass getRenderPassHandle(const DxvkRenderPassOps& ops) const { + return m_renderPass->getHandle(ops); + } + + /** + * \brief Depth-stencil target + * \returns Depth-stencil target + */ + const DxvkAttachment& getDepthTarget() const { + return m_renderTargets.depth; + } + + /** + * \brief Color target + * + * \param [in] id Target Index + * \returns The color target + */ + const DxvkAttachment& getColorTarget(uint32_t id) const { + return m_renderTargets.color[id]; + } + + /** + * \brief Number of framebuffer attachment + * \returns Total attachment count + */ + uint32_t numAttachments() const { + return m_attachmentCount; + } + + /** + * \brief Retrieves attachment by index + * + * \param [in] id Framebuffer attachment ID + * \returns The framebuffer attachment + */ + const DxvkAttachment& getAttachment(uint32_t id) const { + return *m_attachments[id]; + } + + /** + * \brief Finds attachment index by view + * + * Color attachments start at 0 + * \param [in] view Image view + * \returns Attachment index + */ + int32_t findAttachment(const Rc& view) const; + + /** + * \brief Checks whether the framebuffer's targets match + * + * \param [in] renderTargets Render targets to check + * \returns \c true if the render targets are the same + * as the ones used for this framebuffer object. + */ + bool hasTargets( + const DxvkRenderTargets& renderTargets); + + /** + * \brief Generatess render pass format + * + * This render pass format can be used to + * look up a compatible render pass. + * \param [in] renderTargets Render targets + * \returns The render pass format + */ + static DxvkRenderPassFormat getRenderPassFormat( + const DxvkRenderTargets& renderTargets); private: - Rc m_vkd; - Rc m_renderPass; + const Rc m_vkd; + const Rc m_renderPass; + const DxvkRenderTargets m_renderTargets; + const DxvkFramebufferSize m_renderSize; - DxvkRenderTargets m_renderTargets; - DxvkFramebufferSize m_framebufferSize = { 0, 0, 0 }; + uint32_t m_attachmentCount = 0; + std::array m_attachments; - VkFramebuffer m_framebuffer = VK_NULL_HANDLE; + VkFramebuffer m_handle = VK_NULL_HANDLE; + + DxvkFramebufferSize computeRenderSize( + const DxvkFramebufferSize& defaultSize) const; + + DxvkFramebufferSize computeRenderTargetSize( + const Rc& renderTarget) const; }; diff --git a/src/dxvk/dxvk_renderpass.cpp b/src/dxvk/dxvk_renderpass.cpp index e93f46de..e24109c4 100644 --- a/src/dxvk/dxvk_renderpass.cpp +++ b/src/dxvk/dxvk_renderpass.cpp @@ -4,29 +4,56 @@ namespace dxvk { - bool DxvkRenderPassFormat::matchesFormat(const DxvkRenderPassFormat& other) const { - bool equal = m_samples == other.m_samples; + DxvkRenderPass::DxvkRenderPass( + const Rc& vkd, + const DxvkRenderPassFormat& fmt) + : m_vkd(vkd), m_format(fmt), + m_default(createRenderPass(DxvkRenderPassOps())) { - equal &= m_depth.format == other.m_depth.format - && m_depth.initialLayout == other.m_depth.initialLayout - && m_depth.finalLayout == other.m_depth.finalLayout - && m_depth.renderLayout == other.m_depth.renderLayout; - - for (uint32_t i = 0; i < MaxNumRenderTargets && equal; i++) { - equal &= m_color[i].format == other.m_color[i].format - && m_color[i].initialLayout == other.m_color[i].initialLayout - && m_color[i].finalLayout == other.m_color[i].finalLayout - && m_color[i].renderLayout == other.m_color[i].renderLayout; - } - - return equal; } - DxvkRenderPass::DxvkRenderPass( - const Rc& vkd, - const DxvkRenderPassFormat& fmt) - : m_vkd(vkd), m_format(fmt) { + DxvkRenderPass::~DxvkRenderPass() { + m_vkd->vkDestroyRenderPass(m_vkd->device(), m_default, nullptr); + + for (const auto& i : m_instances) { + m_vkd->vkDestroyRenderPass( + m_vkd->device(), i.handle, nullptr); + } + } + + + bool DxvkRenderPass::hasCompatibleFormat( + const DxvkRenderPassFormat& fmt) const { + bool eq = m_format.sampleCount == fmt.sampleCount; + + for (uint32_t i = 0; i < MaxNumRenderTargets && eq; i++) { + eq &= m_format.color[i].format == fmt.color[i].format + && m_format.color[i].layout == fmt.color[i].layout; + } + + eq &= m_format.depth.format == fmt.depth.format + && m_format.depth.layout == fmt.depth.layout; + + return eq; + } + + + VkRenderPass DxvkRenderPass::getHandle(const DxvkRenderPassOps& ops) { + std::lock_guard lock(m_mutex); + + for (const auto& i : m_instances) { + if (compareOps(i.ops, ops)) + return i.handle; + } + + VkRenderPass handle = this->createRenderPass(ops); + m_instances.push_back({ ops, handle }); + return handle; + } + + + VkRenderPass DxvkRenderPass::createRenderPass(const DxvkRenderPassOps& ops) { std::vector attachments; VkAttachmentReference depthRef; @@ -34,51 +61,47 @@ namespace dxvk { // Render passes may not require the previous // contents of the attachments to be preserved. - const DxvkRenderTargetFormat depthFmt = fmt.getDepthFormat(); - - if (depthFmt.format != VK_FORMAT_UNDEFINED) { - VkAttachmentDescription desc; - desc.flags = 0; - desc.format = depthFmt.format; - desc.samples = fmt.getSampleCount(); - desc.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; - desc.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - desc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD; - desc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; - desc.initialLayout = depthFmt.initialLayout; - desc.finalLayout = depthFmt.finalLayout; - - depthRef.attachment = attachments.size(); - depthRef.layout = depthFmt.renderLayout; - - attachments.push_back(desc); - } - for (uint32_t i = 0; i < MaxNumRenderTargets; i++) { - const DxvkRenderTargetFormat colorFmt = fmt.getColorFormat(i); - colorRef[i].attachment = VK_ATTACHMENT_UNUSED; colorRef[i].layout = VK_IMAGE_LAYOUT_UNDEFINED; - if (colorFmt.format != VK_FORMAT_UNDEFINED) { + if (m_format.color[i].format != VK_FORMAT_UNDEFINED) { VkAttachmentDescription desc; desc.flags = 0; - desc.format = colorFmt.format; - desc.samples = fmt.getSampleCount(); - desc.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; - desc.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + desc.format = m_format.color[i].format; + desc.samples = m_format.sampleCount; + desc.loadOp = ops.colorOps[i].loadOp; + desc.storeOp = ops.colorOps[i].storeOp; desc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; desc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - desc.initialLayout = colorFmt.initialLayout; - desc.finalLayout = colorFmt.finalLayout; + desc.initialLayout = ops.colorOps[i].loadLayout; + desc.finalLayout = ops.colorOps[i].storeLayout; colorRef[i].attachment = attachments.size(); - colorRef[i].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + colorRef[i].layout = m_format.color[i].layout; attachments.push_back(desc); } } + if (m_format.depth.format != VK_FORMAT_UNDEFINED) { + VkAttachmentDescription desc; + desc.flags = 0; + desc.format = m_format.depth.format; + desc.samples = m_format.sampleCount; + desc.loadOp = ops.depthOps.loadOp; + desc.storeOp = ops.depthOps.storeOp; + desc.stencilLoadOp = ops.depthOps.loadOp; + desc.stencilStoreOp = ops.depthOps.storeOp; + desc.initialLayout = ops.depthOps.loadLayout; + desc.finalLayout = ops.depthOps.storeLayout; + + depthRef.attachment = attachments.size(); + depthRef.layout = m_format.depth.layout; + + attachments.push_back(desc); + } + VkSubpassDescription subpass; subpass.flags = 0; subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; @@ -87,11 +110,14 @@ namespace dxvk { subpass.colorAttachmentCount = colorRef.size(); subpass.pColorAttachments = colorRef.data(); subpass.pResolveAttachments = nullptr; - subpass.pDepthStencilAttachment = depthFmt.format != VK_FORMAT_UNDEFINED ? &depthRef : nullptr; + subpass.pDepthStencilAttachment = &depthRef; subpass.preserveAttachmentCount = 0; subpass.pPreserveAttachments = nullptr; - std::array subpassDeps = {{ + if (m_format.depth.format == VK_FORMAT_UNDEFINED) + subpass.pDepthStencilAttachment = nullptr; + + const std::array subpassDeps = {{ { VK_SUBPASS_EXTERNAL, 0, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | @@ -139,14 +165,33 @@ namespace dxvk { info.dependencyCount = subpassDeps.size(); info.pDependencies = subpassDeps.data(); - if (m_vkd->vkCreateRenderPass(m_vkd->device(), &info, nullptr, &m_renderPass) != VK_SUCCESS) - throw DxvkError("DxvkRenderPass::DxvkRenderPass: Failed to create render pass object"); + VkRenderPass renderPass = VK_NULL_HANDLE; + + if (m_vkd->vkCreateRenderPass(m_vkd->device(), &info, nullptr, &renderPass) != VK_SUCCESS) { + Logger::err("DxvkRenderPass: Failed to create render pass object"); + return VK_NULL_HANDLE; + } + + return renderPass; } - DxvkRenderPass::~DxvkRenderPass() { - m_vkd->vkDestroyRenderPass( - m_vkd->device(), m_renderPass, nullptr); + bool DxvkRenderPass::compareOps( + const DxvkRenderPassOps& a, + const DxvkRenderPassOps& b) { + bool eq = a.depthOps.loadOp == b.depthOps.loadOp + && a.depthOps.loadLayout == b.depthOps.loadLayout + && a.depthOps.storeOp == b.depthOps.storeOp + && a.depthOps.storeLayout == b.depthOps.storeLayout; + + for (uint32_t i = 0; i < MaxNumRenderTargets && eq; i++) { + eq &= a.colorOps[i].loadOp == b.colorOps[i].loadOp + && a.colorOps[i].loadLayout == b.colorOps[i].loadLayout + && a.colorOps[i].storeOp == b.colorOps[i].storeOp + && a.colorOps[i].storeLayout == b.colorOps[i].storeLayout; + } + + return eq; } @@ -161,29 +206,17 @@ namespace dxvk { } - Rc DxvkRenderPassPool::getRenderPass( - const DxvkRenderPassFormat& fmt) { + Rc DxvkRenderPassPool::getRenderPass(const DxvkRenderPassFormat& fmt) { std::lock_guard lock(m_mutex); - Rc renderPass = nullptr; - - for (uint32_t i = 0; i < m_renderPasses.size() && renderPass == nullptr; i++) { - if (m_renderPasses[i]->matchesFormat(fmt)) - renderPass = m_renderPasses[i]; + for (const auto& r : m_renderPasses) { + if (r->hasCompatibleFormat(fmt)) + return r; } - if (renderPass != nullptr) - return renderPass; - - renderPass = this->createRenderPass(fmt); - m_renderPasses.push_back(renderPass); - return renderPass; - } - - - Rc DxvkRenderPassPool::createRenderPass( - const DxvkRenderPassFormat& fmt) { - return new DxvkRenderPass(m_vkd, fmt); + Rc rp = new DxvkRenderPass(m_vkd, fmt); + m_renderPasses.push_back(rp); + return rp; } } \ No newline at end of file diff --git a/src/dxvk/dxvk_renderpass.h b/src/dxvk/dxvk_renderpass.h index 0883967a..a65c5253 100644 --- a/src/dxvk/dxvk_renderpass.h +++ b/src/dxvk/dxvk_renderpass.h @@ -1,7 +1,7 @@ #pragma once #include -#include +#include #include "dxvk_hash.h" #include "dxvk_include.h" @@ -10,50 +10,84 @@ namespace dxvk { /** - * \brief Format and layout info for a sigle render target + * \brief Format and layout for a render target * - * Stores the format, initial layout and - * final layout of a render target. + * Stores the image format of the attachment and + * the image layout that is used while rendering. */ - struct DxvkRenderTargetFormat { - VkFormat format = VK_FORMAT_UNDEFINED; - VkImageLayout initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - VkImageLayout finalLayout = VK_IMAGE_LAYOUT_UNDEFINED; - VkImageLayout renderLayout = VK_IMAGE_LAYOUT_UNDEFINED; + struct DxvkAttachmentFormat { + VkFormat format = VK_FORMAT_UNDEFINED; + VkImageLayout layout = VK_IMAGE_LAYOUT_UNDEFINED; }; /** * \brief Render pass format * - * Stores the formats of all render targets - * that are used by a framebuffer object. + * Stores the attachment formats for all depth and + * color attachments, as well as the sample count. */ - class DxvkRenderPassFormat { + struct DxvkRenderPassFormat { + VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT; + DxvkAttachmentFormat depth; + DxvkAttachmentFormat color[MaxNumRenderTargets]; + }; + + + /** + * \brief Attachment transitions + * + * Stores the load/store ops and the initial + * and final layout of a single attachment. + */ + struct DxvkAttachmentOps { + VkAttachmentLoadOp loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + VkImageLayout loadLayout = VK_IMAGE_LAYOUT_UNDEFINED; + VkAttachmentStoreOp storeOp = VK_ATTACHMENT_STORE_OP_STORE; + VkImageLayout storeLayout = VK_IMAGE_LAYOUT_GENERAL; + }; + + + /** + * \brief Render pass transitions + * + * Stores transitions for all depth and color attachments. + * This is used to select a specific render pass object + * from a group of render passes with the same format. + */ + struct DxvkRenderPassOps { + DxvkAttachmentOps depthOps; + DxvkAttachmentOps colorOps[MaxNumRenderTargets]; + }; + + + /** + * \brief Render pass object + * + * Manages a set of compatible render passes, i.e. + * render passes which share the same format but + * may differ in their attachment operations. + */ + class DxvkRenderPass : public RcObject { public: - /** - * \brief Retrieves color target format - * - * If the color target has not been defined, - * this will return \c VK_FORMAT_UNDEFINED. - * \param [in] id Color target index - * \returns Color target format - */ - DxvkRenderTargetFormat getColorFormat(uint32_t id) const { - return m_color.at(id); - } + DxvkRenderPass( + const Rc& vkd, + const DxvkRenderPassFormat& fmt); + + ~DxvkRenderPass(); /** - * \brief Retrieves depth-stencil format + * \brief Checks whether a format is compatible * - * If the color target has not been defined, - * this will return \c VK_FORMAT_UNDEFINED. + * Two render pass formats are considered compatible + * if all the relevant attachment formats match. + * \param [in] fmt The render pass format to check + * \returns \c true if this render pass is compatible. */ - DxvkRenderTargetFormat getDepthFormat() const { - return m_depth; - } + bool hasCompatibleFormat( + const DxvkRenderPassFormat& fmt) const; /** * \brief Retrieves sample count @@ -63,103 +97,53 @@ namespace dxvk { * \returns Sample count */ VkSampleCountFlagBits getSampleCount() const { - return m_samples; + return m_format.sampleCount; } /** - * \brief Sets color target format + * \brief Returns handle of default render pass * - * \param [in] id Color target index - * \param [in] fmt Color target format + * The default render pass handle should be used to + * create pipelines and framebuffer objects. It can + * \e not be used for \c vkCmdBeginRenderPass calls. + * \returns The default render pass handle */ - void setColorFormat(uint32_t id, DxvkRenderTargetFormat fmt) { - m_color.at(id) = fmt; + VkRenderPass getDefaultHandle() const { + return m_default; } /** - * \brief Sets depth-stencil format - * \param [in] fmt Depth-stencil format - */ - void setDepthFormat(DxvkRenderTargetFormat fmt) { - m_depth = fmt; - } - - /** - * \brief Sets sample count - * \param [in] samples Sample count - */ - void setSampleCount(VkSampleCountFlagBits samples) { - m_samples = samples; - } - - /** - * \brief Checks whether two render pass formats are compatible + * \brief Returns handle to a specialized render pass * - * \param [in] other The render pass format to compare to - * \returns \c true if the render pass formats are compatible - */ - bool matchesFormat(const DxvkRenderPassFormat& other) const; - - private: - - std::array m_color; - DxvkRenderTargetFormat m_depth; - VkSampleCountFlagBits m_samples = VK_SAMPLE_COUNT_1_BIT; - - }; - - - /** - * \brief DXVK render pass - * - * Render pass objects are used internally to identify render - * target formats and - */ - class DxvkRenderPass : public RcObject { - - public: - - DxvkRenderPass( - const Rc& vkd, - const DxvkRenderPassFormat& fmt); - ~DxvkRenderPass(); - - /** - * \brief Render pass handle - * - * Internal use only. + * Returns a handle to a render pass with the given + * set of parameters. This should be used for calls + * to \c vkCmdBeginRenderPass. + * \param [in] ops Attachment ops * \returns Render pass handle */ - VkRenderPass handle() const { - return m_renderPass; - } - - /** - * \brief Render pass sample count - * \returns Render pass sample count - */ - VkSampleCountFlagBits sampleCount() const { - return m_format.getSampleCount(); - } - - /** - * \brief Checks render pass format compatibility - * - * This render pass object can be used with compatible render - * pass formats. Two render pass formats are compatible if the - * used attachments match in image format and layout. - * \param [in] format The render pass format to test - * \returns \c true if the formats match - */ - bool matchesFormat(const DxvkRenderPassFormat& format) const { - return m_format.matchesFormat(format); - } + VkRenderPass getHandle( + const DxvkRenderPassOps& ops); private: - Rc m_vkd; - DxvkRenderPassFormat m_format; - VkRenderPass m_renderPass; + struct Instance { + DxvkRenderPassOps ops; + VkRenderPass handle; + }; + + Rc m_vkd; + DxvkRenderPassFormat m_format; + VkRenderPass m_default; + + sync::Spinlock m_mutex; + std::vector m_instances; + + VkRenderPass createRenderPass( + const DxvkRenderPassOps& ops); + + static bool compareOps( + const DxvkRenderPassOps& a, + const DxvkRenderPassOps& b); }; @@ -167,35 +151,35 @@ namespace dxvk { /** * \brief Render pass pool * - * Thread-safe class that manages the render pass - * objects that are used within an application. + * Manages render pass objects. For each render + * pass format, a new render pass object will + * be created, but no two render pass objects + * will have the same format. */ class DxvkRenderPassPool : public RcObject { public: - DxvkRenderPassPool(const Rc& vkd); + DxvkRenderPassPool( + const Rc& vkd); ~DxvkRenderPassPool(); /** * \brief Retrieves a render pass object * - * \param [in] fmt Render target formats - * \returns Compatible render pass object + * \param [in] fmt The render pass format + * \returns Matching render pass object */ Rc getRenderPass( - const DxvkRenderPassFormat& fmt); + const DxvkRenderPassFormat& fmt); private: - Rc m_vkd; + const Rc m_vkd; std::mutex m_mutex; std::vector> m_renderPasses; - Rc createRenderPass( - const DxvkRenderPassFormat& fmt); - }; } \ No newline at end of file diff --git a/src/dxvk/dxvk_swapchain.cpp b/src/dxvk/dxvk_swapchain.cpp index 23c0d2b0..36573346 100644 --- a/src/dxvk/dxvk_swapchain.cpp +++ b/src/dxvk/dxvk_swapchain.cpp @@ -34,7 +34,7 @@ namespace dxvk { } - Rc DxvkSwapchain::getFramebuffer( + Rc DxvkSwapchain::getImageView( const Rc& wakeSync) { VkResult status = this->acquireNextImage(wakeSync); @@ -136,17 +136,6 @@ namespace dxvk { if (m_vkd->vkCreateSwapchainKHR(m_vkd->device(), &swapInfo, nullptr, &m_handle) != VK_SUCCESS) throw DxvkError("DxvkSwapchain: Failed to recreate swap chain"); - // Create the render pass object - DxvkRenderPassFormat renderTargetFormat; - - renderTargetFormat.setColorFormat(0, - DxvkRenderTargetFormat { fmt.format, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR }); - - m_renderPass = new DxvkRenderPass( - m_vkd, renderTargetFormat); - // Retrieve swap images auto swapImages = this->retrieveSwapImages(); @@ -181,16 +170,8 @@ namespace dxvk { viewInfo.numLayers = swapInfo.imageArrayLayers; for (size_t i = 0; i < swapImages.size(); i++) { - Rc image = new DxvkImage(m_vkd, imageInfo, swapImages.at(i)); - Rc iview = m_device->createImageView(image, viewInfo); - - DxvkRenderTargets renderTargets; - renderTargets.setColorTarget(0, iview, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - - m_framebuffers.at(i) = new DxvkFramebuffer( - m_vkd, m_renderPass, renderTargets, - DxvkFramebufferSize()); + m_framebuffers.at(i) = m_device->createImageView( + new DxvkImage(m_vkd, imageInfo, swapImages.at(i)), viewInfo); m_semaphoreSet.at(i).acquireSync = m_device->createSemaphore(); m_semaphoreSet.at(i).presentSync = m_device->createSemaphore(); diff --git a/src/dxvk/dxvk_swapchain.h b/src/dxvk/dxvk_swapchain.h index cb5ff103..97661d47 100644 --- a/src/dxvk/dxvk_swapchain.h +++ b/src/dxvk/dxvk_swapchain.h @@ -53,20 +53,20 @@ namespace dxvk { * * Retrieves a set of semaphores for the acquire * and present operations. This must be called - * \e before \c getFramebuffer. + * \e before \c getImageView. * \returns Semaphore pair */ DxvkSwapSemaphores getSemaphorePair(); /** - * \brief Retrieves the framebuffer for the current frame + * \brief Retrieves the image view for the current frame * * If necessary, this will automatically recreate the - * underlying swapchain object and framebuffer objects. + * underlying swapchain object and image view objects. * \param [in] wakeSync Semaphore to signal - * \returns The framebuffer object + * \returns The image view object */ - Rc getFramebuffer( + Rc getImageView( const Rc& wakeSync); /** @@ -83,7 +83,7 @@ namespace dxvk { /** * \brief Changes swapchain properties * - * This must not be called between \ref getFramebuffer + * This must not be called between \ref getImageView * and \ref present as this method may recreate the swap * chain and framebuffer objects immediately. * \param [in] props New swapchain properties @@ -102,8 +102,7 @@ namespace dxvk { uint32_t m_imageIndex = 0; uint32_t m_frameIndex = 0; - Rc m_renderPass; - std::vector> m_framebuffers; + std::vector> m_framebuffers; std::vector m_semaphoreSet; VkResult acquireNextImage( diff --git a/src/dxvk/hud/dxvk_hud.cpp b/src/dxvk/hud/dxvk_hud.cpp index 057427c8..66172a06 100644 --- a/src/dxvk/hud/dxvk_hud.cpp +++ b/src/dxvk/hud/dxvk_hud.cpp @@ -170,8 +170,8 @@ namespace dxvk::hud { viewInfo.numLayers = 1; m_renderTargetView = m_device->createImageView(m_renderTarget, viewInfo); - m_renderTargetInfo.setColorTarget(0, m_renderTargetView, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + m_renderTargetInfo.color[0] = { m_renderTargetView, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }; }