mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-03-13 19:29:14 +01:00
[dxvk] Apply render target bindings at draw time
This should help reduce the number of redundant render pass spills, especially in games which use deferred contexts for rendering. This optimization mostly helps in GPU-bound scenarios.
This commit is contained in:
parent
8606576d83
commit
1075990dbe
@ -98,19 +98,18 @@ namespace dxvk {
|
||||
|
||||
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) {
|
||||
bool sameAsCurr = m_state.om.framebuffer != nullptr
|
||||
&& m_state.om.framebuffer->renderTargets().matches(targets);
|
||||
|
||||
if (!sameAsCurr) {
|
||||
Rc<DxvkFramebuffer> fb = targets.hasAttachments()
|
||||
? m_device->createFramebuffer(targets)
|
||||
: nullptr;
|
||||
|
||||
this->bindFramebuffer(fb);
|
||||
if (m_state.om.framebuffer == nullptr || !m_state.om.framebuffer->renderTargets().matches(targets)) {
|
||||
m_state.om.renderTargets = targets;
|
||||
m_flags.set(DxvkContextFlag::GpDirtyFramebuffer);
|
||||
}
|
||||
}
|
||||
|
||||
@ -392,6 +391,8 @@ namespace dxvk {
|
||||
const VkClearRect& clearRect,
|
||||
VkImageAspectFlags clearAspects,
|
||||
const VkClearValue& clearValue) {
|
||||
this->updateFramebuffer();
|
||||
|
||||
// Check whether the render target view is an attachment
|
||||
// of the current framebuffer. If not, we need to create
|
||||
// a temporary framebuffer.
|
||||
@ -1798,6 +1799,23 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::updateFramebuffer() {
|
||||
if (m_flags.test(DxvkContextFlag::GpDirtyFramebuffer)) {
|
||||
m_flags.clr(DxvkContextFlag::GpDirtyFramebuffer);
|
||||
|
||||
this->spillRenderPass();
|
||||
|
||||
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.om.framebuffer = fb;
|
||||
|
||||
m_flags.set(DxvkContextFlag::GpDirtyPipelineState);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::updateIndexBufferBinding() {
|
||||
if (m_flags.test(DxvkContextFlag::GpDirtyIndexBuffer)) {
|
||||
m_flags.clr(DxvkContextFlag::GpDirtyIndexBuffer);
|
||||
@ -1881,6 +1899,7 @@ namespace dxvk {
|
||||
|
||||
|
||||
void DxvkContext::commitGraphicsState() {
|
||||
this->updateFramebuffer();
|
||||
this->startRenderPass();
|
||||
this->updateGraphicsPipeline();
|
||||
this->updateIndexBufferBinding();
|
||||
|
@ -662,9 +662,7 @@ namespace dxvk {
|
||||
const DxvkBindingState& bindingState,
|
||||
const Rc<DxvkPipelineLayout>& layout);
|
||||
|
||||
void updateViewports();
|
||||
void updateBlendConstants();
|
||||
void updateStencilReference();
|
||||
void updateFramebuffer();
|
||||
|
||||
void updateIndexBufferBinding();
|
||||
void updateVertexBufferBindings();
|
||||
|
@ -22,6 +22,7 @@ namespace dxvk {
|
||||
*/
|
||||
enum class DxvkContextFlag : uint64_t {
|
||||
GpRenderPassBound, ///< Render pass is currently bound
|
||||
GpDirtyFramebuffer, ///< Framebuffer binding is out of date
|
||||
GpDirtyPipeline, ///< Graphics pipeline binding is out of date
|
||||
GpDirtyPipelineState, ///< Graphics pipeline needs to be recompiled
|
||||
GpDirtyResources, ///< Graphics pipeline resource bindings are out of date
|
||||
@ -53,6 +54,7 @@ namespace dxvk {
|
||||
|
||||
|
||||
struct DxvkOutputMergerState {
|
||||
DxvkRenderTargets renderTargets;
|
||||
Rc<DxvkFramebuffer> framebuffer = nullptr;
|
||||
|
||||
DxvkBlendConstants blendConstants = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
|
Loading…
x
Reference in New Issue
Block a user