gl::Error StateManager11::syncFramebuffer(gl::Framebuffer *framebuffer) { Framebuffer11 *framebuffer11 = GetImplAs<Framebuffer11>(framebuffer); gl::Error error = framebuffer11->invalidateSwizzles(); if (error.isError()) { return error; } if (framebuffer11->hasAnyInternalDirtyBit()) { ASSERT(framebuffer->id() != 0); framebuffer11->syncInternalState(); } if (!mRenderTargetIsDirty) { return gl::Error(GL_NO_ERROR); } mRenderTargetIsDirty = false; // Check for zero-sized default framebuffer, which is a special case. // in this case we do not wish to modify any state and just silently return false. // this will not report any gl error but will cause the calling method to return. if (framebuffer->id() == 0) { ASSERT(!framebuffer11->hasAnyInternalDirtyBit()); const gl::Extents &size = framebuffer->getFirstColorbuffer()->getSize(); if (size.width == 0 || size.height == 0) { return gl::Error(GL_NO_ERROR); } } // Get the color render buffer and serial // Also extract the render target dimensions and view unsigned int renderTargetWidth = 0; unsigned int renderTargetHeight = 0; RTVArray framebufferRTVs; bool missingColorRenderTarget = true; framebufferRTVs.fill(nullptr); const auto &colorRTs = framebuffer11->getCachedColorRenderTargets(); size_t appliedRTIndex = 0; bool skipInactiveRTs = mRenderer->getWorkarounds().mrtPerfWorkaround; const auto &drawStates = framebuffer->getDrawBufferStates(); for (size_t rtIndex = 0; rtIndex < colorRTs.size(); ++rtIndex) { const RenderTarget11 *renderTarget = colorRTs[rtIndex]; // Skip inactive rendertargets if the workaround is enabled. if (skipInactiveRTs && (!renderTarget || drawStates[rtIndex] == GL_NONE)) { continue; } if (renderTarget) { framebufferRTVs[appliedRTIndex] = renderTarget->getRenderTargetView(); ASSERT(framebufferRTVs[appliedRTIndex]); if (missingColorRenderTarget) { renderTargetWidth = renderTarget->getWidth(); renderTargetHeight = renderTarget->getHeight(); missingColorRenderTarget = false; } } // Unset conflicting texture SRVs const auto *attachment = framebuffer->getColorbuffer(rtIndex); ASSERT(attachment); unsetConflictingAttachmentResources(attachment, renderTarget->getTexture()); appliedRTIndex++; } // Get the depth stencil buffers ID3D11DepthStencilView *framebufferDSV = nullptr; const auto *depthStencilRenderTarget = framebuffer11->getCachedDepthStencilRenderTarget(); if (depthStencilRenderTarget) { framebufferDSV = depthStencilRenderTarget->getDepthStencilView(); ASSERT(framebufferDSV); // If there is no render buffer, the width, height and format values come from // the depth stencil if (missingColorRenderTarget) { renderTargetWidth = depthStencilRenderTarget->getWidth(); renderTargetHeight = depthStencilRenderTarget->getHeight(); } // Unset conflicting texture SRVs const auto *attachment = framebuffer->getDepthOrStencilbuffer(); ASSERT(attachment); unsetConflictingAttachmentResources(attachment, depthStencilRenderTarget->getTexture()); } // TODO(jmadill): Use context caps? UINT drawBuffers = mRenderer->getNativeCaps().maxDrawBuffers; // Apply the render target and depth stencil mRenderer->getDeviceContext()->OMSetRenderTargets(drawBuffers, framebufferRTVs.data(), framebufferDSV); // The D3D11 blend state is heavily dependent on the current render target. mBlendStateIsDirty = true; setViewportBounds(renderTargetWidth, renderTargetHeight); return gl::Error(GL_NO_ERROR); }
gl::Error StateManager11::syncFramebuffer(const gl::Framebuffer *framebuffer) { // Get the color render buffer and serial // Also extract the render target dimensions and view unsigned int renderTargetWidth = 0; unsigned int renderTargetHeight = 0; DXGI_FORMAT renderTargetFormat = DXGI_FORMAT_UNKNOWN; RenderTargetArray framebufferRTVs; bool missingColorRenderTarget = true; framebufferRTVs.fill(nullptr); const Framebuffer11 *framebuffer11 = GetImplAs<Framebuffer11>(framebuffer); const gl::AttachmentList &colorbuffers = framebuffer11->getColorAttachmentsForRender(); for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment) { const gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment]; if (colorbuffer) { // the draw buffer must be either "none", "back" for the default buffer or the same // index as this color (in order) // check for zero-sized default framebuffer, which is a special case. // in this case we do not wish to modify any state and just silently return false. // this will not report any gl error but will cause the calling method to return. const gl::Extents &size = colorbuffer->getSize(); if (size.width == 0 || size.height == 0) { return gl::Error(GL_NO_ERROR); } // Extract the render target dimensions and view RenderTarget11 *renderTarget = NULL; gl::Error error = colorbuffer->getRenderTarget(&renderTarget); if (error.isError()) { return error; } ASSERT(renderTarget); framebufferRTVs[colorAttachment] = renderTarget->getRenderTargetView(); ASSERT(framebufferRTVs[colorAttachment]); if (missingColorRenderTarget) { renderTargetWidth = renderTarget->getWidth(); renderTargetHeight = renderTarget->getHeight(); renderTargetFormat = renderTarget->getDXGIFormat(); missingColorRenderTarget = false; } // Unbind render target SRVs from the shader here to prevent D3D11 warnings. if (colorbuffer->type() == GL_TEXTURE) { uintptr_t rtResource = reinterpret_cast<uintptr_t>(GetViewResource(framebufferRTVs[colorAttachment])); const gl::ImageIndex &index = colorbuffer->getTextureImageIndex(); // The index doesn't need to be corrected for the small compressed texture // workaround // because a rendertarget is never compressed. unsetConflictingSRVs(gl::SAMPLER_VERTEX, rtResource, index); unsetConflictingSRVs(gl::SAMPLER_PIXEL, rtResource, index); } } } // Get the depth stencil buffers ID3D11DepthStencilView *framebufferDSV = NULL; const gl::FramebufferAttachment *depthStencil = framebuffer->getDepthOrStencilbuffer(); if (depthStencil) { RenderTarget11 *depthStencilRenderTarget = NULL; gl::Error error = depthStencil->getRenderTarget(&depthStencilRenderTarget); if (error.isError()) { return error; } ASSERT(depthStencilRenderTarget); framebufferDSV = depthStencilRenderTarget->getDepthStencilView(); ASSERT(framebufferDSV); // If there is no render buffer, the width, height and format values come from // the depth stencil if (missingColorRenderTarget) { renderTargetWidth = depthStencilRenderTarget->getWidth(); renderTargetHeight = depthStencilRenderTarget->getHeight(); } // Unbind render target SRVs from the shader here to prevent D3D11 warnings. if (depthStencil->type() == GL_TEXTURE) { uintptr_t depthStencilResource = reinterpret_cast<uintptr_t>(GetViewResource(framebufferDSV)); const gl::ImageIndex &index = depthStencil->getTextureImageIndex(); // The index doesn't need to be corrected for the small compressed texture workaround // because a rendertarget is never compressed. unsetConflictingSRVs(gl::SAMPLER_VERTEX, depthStencilResource, index); unsetConflictingSRVs(gl::SAMPLER_PIXEL, depthStencilResource, index); } } if (setRenderTargets(framebufferRTVs, framebufferDSV)) { setViewportBounds(renderTargetWidth, renderTargetHeight); } gl::Error error = framebuffer11->invalidateSwizzles(); if (error.isError()) { return error; } return gl::Error(GL_NO_ERROR); }