void CFullscreenTriangleDrawer::DrawDX11( ID3D11ShaderResourceView* pTextureSRV ) { ID3D11Device* pDevice = static_cast<ID3D11Device*>( gD3DDevice ); ID3D11DeviceContext* pContext = NULL; pDevice->GetImmediateContext( &pContext ); CDX11StateGuard stateGuard; pContext->IASetInputLayout( NULL ); pContext->IASetIndexBuffer( NULL, DXGI_FORMAT_UNKNOWN, 0 ); pContext->IASetVertexBuffers( 0, 0, NULL, NULL, NULL ); pContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST ); pContext->VSSetShader( m_pVertexShader11, NULL, 0 ); pContext->PSSetShader( m_pPixelShader11, NULL, 0 ); ID3D11SamplerState* pNullSampler[] = { NULL }; pContext->PSSetSamplers( 0, 1, pNullSampler ); pContext->PSSetShaderResources( 0, 1, &pTextureSRV ); pContext->OMSetBlendState( m_pBlendState11, NULL, 0xFFFFFFFF ); // Draw pContext->Draw( 3, 0 ); }
//--------------------------------------------------------------------------- void FontRenderer::FontDrawingBegin( RenderContext* rc ) { assert( m_vertexBuffer != NULL ); assert( m_indexBuffer != NULL ); m_currentRC = rc; m_fontDrawOps.clear(); ID3D11DeviceContext* dc = m_currentRC->Context(); UINT viewportCount = 1; D3D11_VIEWPORT vp; dc->RSGetViewports(&viewportCount, &vp); UINT stride = sizeof(FontTextVertex); UINT offset = 0; dc->IASetInputLayout(m_vertexLayout); dc->IASetIndexBuffer(m_indexBuffer, DXGI_FORMAT_R32_UINT, 0); dc->IASetVertexBuffers(0, 1, &m_vertexBuffer, &stride, &offset); dc->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); dc->VSSetShader( m_vertexShader, 0, 0 ); dc->PSSetShader( m_pixelShader, 0, 0 ); dc->PSSetSamplers( 0, 1, &m_samplerState ); dc->RSSetState(m_rasterState); float blendFactor[4] = {1.0f}; dc->OMSetBlendState(m_blendState, blendFactor, 0xffffffff); m_activeFont = NULL; // needs to be set! }
//----------------------------------------------------------------------------- void CPUTRenderStateBlockDX11::SetRenderStates( CPUTRenderParameters &renderParams ) { ID3D11DeviceContext *pContext = ((CPUTRenderParametersDX*)&renderParams)->mpContext; pContext->OMSetBlendState( mpBlendState, mStateDesc.BlendFactor, mStateDesc.SampleMask ); pContext->OMSetDepthStencilState( mpDepthStencilState, 0 ); // TODO: read stecil ref from config file pContext->RSSetState( mpRasterizerState ); pContext->PSSetSamplers( 0, mNumSamplers, mpSamplerState ); pContext->VSSetSamplers( 0, mNumSamplers, mpSamplerState ); pContext->GSSetSamplers( 0, mNumSamplers, mpSamplerState ); } // CPUTRenderStateBlockDX11::SetRenderState()
~CDX11StateGuard() { ID3D11Device* pDevice = static_cast<ID3D11Device*>( gD3DDevice ); ID3D11DeviceContext* pContext = NULL; pDevice->GetImmediateContext( &pContext ); // Apply saved state pContext->OMSetBlendState( m_pBlendState, m_BlendFactor, m_SampleMask ); pContext->RSSetState( m_pRasterizerState ); pContext->IASetPrimitiveTopology( m_PrimitiveTopology ); pContext->IASetIndexBuffer( m_pIndexBuffer, m_IndexBufferFormat, m_IndexBufferOffset ); pContext->IASetInputLayout( m_pInputLayout ); pContext->IASetVertexBuffers( 0, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT, m_pVertexBuffers, m_pVertexBufferStrides, m_pVertexBufferOffsets ); pContext->VSSetShader( m_pVertexShader, m_ppVertexShaderClassInstances, m_VertexShaderClassInstancesCount ); pContext->PSSetShader( m_pPixelShader, m_ppPixelShaderClassInstances, m_PixelShaderClassInstancesCount ); pContext->PSSetSamplers( 0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, m_ppPixelShaderSamplers ); pContext->PSSetShaderResources( 0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, m_ppPixelShaderResources ); // Release references SAFE_RELEASE( m_pBlendState ); SAFE_RELEASE( m_pRasterizerState ); SAFE_RELEASE( m_pIndexBuffer ); SAFE_RELEASE( m_pInputLayout ); for ( UINT i = 0; i < D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT; ++i ) { SAFE_RELEASE( m_pVertexBuffers[i] ); } SAFE_RELEASE( m_pVertexShader ); for ( UINT i = 0; i < m_VertexShaderClassInstancesCount; ++i ) { SAFE_RELEASE( m_ppVertexShaderClassInstances[i] ); } SAFE_RELEASE( m_pPixelShader ); for ( UINT i = 0; i < m_PixelShaderClassInstancesCount; ++i ) { SAFE_RELEASE( m_ppPixelShaderClassInstances[i] ); } for ( UINT i = 0; i < D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; ++i ) { SAFE_RELEASE( m_ppPixelShaderSamplers[i] ); } for ( UINT i = 0; i < D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; ++i ) { SAFE_RELEASE( m_ppPixelShaderResources[i] ); } }
static void SetDefaultGraphicsState () { #if SUPPORT_D3D11 // D3D11 case if (s_DeviceType == kUnityGfxRendererD3D11) { ID3D11DeviceContext* ctx = NULL; g_D3D11Device->GetImmediateContext (&ctx); ctx->OMSetDepthStencilState (g_D3D11DepthState, 0); ctx->RSSetState (g_D3D11RasterState); ctx->OMSetBlendState (g_D3D11BlendState, NULL, 0xFFFFFFFF); ctx->Release(); } #endif }
void Clear11::clearFramebuffer(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer) { // First determine if a scissored clear is needed, this will always require drawing a quad. // // Otherwise, iterate over the color buffers which require clearing and determine if they can be // cleared with ID3D11DeviceContext::ClearRenderTargetView... This requires: // 1) The render target is being cleared to a float value (will be cast to integer when clearing integer // render targets as expected but does not work the other way around) // 2) The format of the render target has no color channels that are currently masked out. // Clear the easy-to-clear buffers on the spot and accumulate the ones that require special work. // // Also determine if the depth stencil can be cleared with ID3D11DeviceContext::ClearDepthStencilView // by checking if the stencil write mask covers the entire stencil. // // To clear the remaining buffers, quads must be drawn containing an int, uint or float vertex color // attribute. gl::Extents framebufferSize; if (frameBuffer->getFirstColorbuffer() != NULL) { gl::Renderbuffer *renderBuffer = frameBuffer->getFirstColorbuffer(); framebufferSize.width = renderBuffer->getWidth(); framebufferSize.height = renderBuffer->getHeight(); framebufferSize.depth = 1; } else if (frameBuffer->getDepthOrStencilbuffer() != NULL) { gl::Renderbuffer *renderBuffer = frameBuffer->getDepthOrStencilbuffer(); framebufferSize.width = renderBuffer->getWidth(); framebufferSize.height = renderBuffer->getHeight(); framebufferSize.depth = 1; } else { UNREACHABLE(); return; } if (clearParams.scissorEnabled && (clearParams.scissor.x >= framebufferSize.width || clearParams.scissor.y >= framebufferSize.height || clearParams.scissor.x + clearParams.scissor.width <= 0 || clearParams.scissor.y + clearParams.scissor.height <= 0)) { // Scissor is enabled and the scissor rectangle is outside the renderbuffer return; } bool needScissoredClear = clearParams.scissorEnabled && (clearParams.scissor.x > 0 || clearParams.scissor.y > 0 || clearParams.scissor.x + clearParams.scissor.width < framebufferSize.width || clearParams.scissor.y + clearParams.scissor.height < framebufferSize.height); GLuint clientVersion = mRenderer->getCurrentClientVersion(); std::vector<RenderTarget11*> maskedClearRenderTargets; RenderTarget11* maskedClearDepthStencil = NULL; ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) { if (clearParams.clearColor[colorAttachment] && frameBuffer->isEnabledColorAttachment(colorAttachment)) { gl::Renderbuffer *renderbuffer = frameBuffer->getColorbuffer(colorAttachment); if (renderbuffer) { RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(renderbuffer->getRenderTarget()); if (!renderTarget) { ERR("Render target pointer unexpectedly null."); return; } GLenum internalFormat = renderbuffer->getInternalFormat(); GLenum actualFormat = renderbuffer->getActualFormat(); GLenum componentType = gl::GetComponentType(internalFormat, clientVersion); if (clearParams.colorClearType == GL_FLOAT && !(componentType == GL_FLOAT || componentType == GL_UNSIGNED_NORMALIZED || componentType == GL_SIGNED_NORMALIZED)) { ERR("It is undefined behaviour to clear a render buffer which is not normalized fixed point or floating-" "point to floating point values (color attachment %u has internal format 0x%X).", colorAttachment, internalFormat); } GLuint internalRedBits = gl::GetRedBits(internalFormat, clientVersion); GLuint internalGreenBits = gl::GetGreenBits(internalFormat, clientVersion); GLuint internalBlueBits = gl::GetBlueBits(internalFormat, clientVersion); GLuint internalAlphaBits = gl::GetAlphaBits(internalFormat, clientVersion); if ((internalRedBits == 0 || !clearParams.colorMaskRed) && (internalGreenBits == 0 || !clearParams.colorMaskGreen) && (internalBlueBits == 0 || !clearParams.colorMaskBlue) && (internalAlphaBits == 0 || !clearParams.colorMaskAlpha)) { // Every channel either does not exist in the render target or is masked out continue; } else if (needScissoredClear || clearParams.colorClearType != GL_FLOAT || (internalRedBits > 0 && !clearParams.colorMaskRed) || (internalGreenBits > 0 && !clearParams.colorMaskGreen) || (internalBlueBits > 0 && !clearParams.colorMaskBlue) || (internalAlphaBits > 0 && !clearParams.colorMaskAlpha)) { // A scissored or masked clear is required maskedClearRenderTargets.push_back(renderTarget); } else { // ID3D11DeviceContext::ClearRenderTargetView is possible ID3D11RenderTargetView *framebufferRTV = renderTarget->getRenderTargetView(); if (!framebufferRTV) { ERR("Render target view pointer unexpectedly null."); return; } // Check if the actual format has a channel that the internal format does not and set them to the // default values GLuint actualRedBits = gl::GetRedBits(actualFormat, clientVersion); GLuint actualGreenBits = gl::GetGreenBits(actualFormat, clientVersion); GLuint actualBlueBits = gl::GetBlueBits(actualFormat, clientVersion); GLuint actualAlphaBits = gl::GetAlphaBits(actualFormat, clientVersion); const float clearValues[4] = { ((internalRedBits == 0 && actualRedBits > 0) ? 0.0f : clearParams.colorFClearValue.red), ((internalGreenBits == 0 && actualGreenBits > 0) ? 0.0f : clearParams.colorFClearValue.green), ((internalBlueBits == 0 && actualBlueBits > 0) ? 0.0f : clearParams.colorFClearValue.blue), ((internalAlphaBits == 0 && actualAlphaBits > 0) ? 1.0f : clearParams.colorFClearValue.alpha), }; deviceContext->ClearRenderTargetView(framebufferRTV, clearValues); } } } } if (clearParams.clearDepth || clearParams.clearStencil) { gl::Renderbuffer *renderbuffer = frameBuffer->getDepthOrStencilbuffer(); if (renderbuffer) { RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(renderbuffer->getDepthStencil()); if (!renderTarget) { ERR("Depth stencil render target pointer unexpectedly null."); return; } GLenum actualFormat = renderbuffer->getActualFormat(); unsigned int stencilUnmasked = frameBuffer->hasStencil() ? (1 << gl::GetStencilBits(actualFormat, clientVersion)) - 1 : 0; bool needMaskedStencilClear = clearParams.clearStencil && (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked; if (needScissoredClear || needMaskedStencilClear) { maskedClearDepthStencil = renderTarget; } else { ID3D11DepthStencilView *framebufferDSV = renderTarget->getDepthStencilView(); if (!framebufferDSV) { ERR("Depth stencil view pointer unexpectedly null."); return; } UINT clearFlags = (clearParams.clearDepth ? D3D11_CLEAR_DEPTH : 0) | (clearParams.clearStencil ? D3D11_CLEAR_STENCIL : 0); FLOAT depthClear = gl::clamp01(clearParams.depthClearValue); UINT8 stencilClear = clearParams.stencilClearValue & 0xFF; deviceContext->ClearDepthStencilView(framebufferDSV, clearFlags, depthClear, stencilClear); } } } if (maskedClearRenderTargets.size() > 0 || maskedClearDepthStencil) { // To clear the render targets and depth stencil in one pass: // // Render a quad clipped to the scissor rectangle which draws the clear color and a blend // state that will perform the required color masking. // // The quad's depth is equal to the depth clear value with a depth stencil state that // will enable or disable depth test/writes if the depth buffer should be cleared or not. // // The rasterizer state's stencil is set to always pass or fail based on if the stencil // should be cleared or not with a stencil write mask of the stencil clear value. // // ====================================================================================== // // Luckily, the gl spec (ES 3.0.2 pg 183) states that the results of clearing a render- // buffer that is not normalized fixed point or floating point with floating point values // are undefined so we can just write floats to them and D3D11 will bit cast them to // integers. // // Also, we don't have to worry about attempting to clear a normalized fixed/floating point // buffer with integer values because there is no gl API call which would allow it, // glClearBuffer* calls only clear a single renderbuffer at a time which is verified to // be a compatible clear type. // Bind all the render targets which need clearing ASSERT(maskedClearRenderTargets.size() <= mRenderer->getMaxRenderTargets()); std::vector<ID3D11RenderTargetView*> rtvs(maskedClearRenderTargets.size()); for (unsigned int i = 0; i < maskedClearRenderTargets.size(); i++) { ID3D11RenderTargetView *renderTarget = maskedClearRenderTargets[i]->getRenderTargetView(); if (!renderTarget) { ERR("Render target pointer unexpectedly null."); return; } rtvs[i] = renderTarget; } ID3D11DepthStencilView *dsv = maskedClearDepthStencil ? maskedClearDepthStencil->getDepthStencilView() : NULL; ID3D11BlendState *blendState = getBlendState(clearParams, maskedClearRenderTargets); const FLOAT blendFactors[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; const UINT sampleMask = 0xFFFFFFFF; ID3D11DepthStencilState *dsState = getDepthStencilState(clearParams); const UINT stencilClear = clearParams.stencilClearValue & 0xFF; // Set the vertices UINT vertexStride = 0; const UINT startIdx = 0; const ClearShader* shader = NULL; D3D11_MAPPED_SUBRESOURCE mappedResource; HRESULT result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); if (FAILED(result)) { ERR("Failed to map masked clear vertex buffer, HRESULT: 0x%X.", result); return; } const gl::Rectangle *scissorPtr = clearParams.scissorEnabled ? &clearParams.scissor : NULL; switch (clearParams.colorClearType) { case GL_FLOAT: ApplyVertices(framebufferSize, scissorPtr, clearParams.colorFClearValue, clearParams.depthClearValue, mappedResource.pData); vertexStride = sizeof(d3d11::PositionDepthColorVertex<float>); shader = &mFloatClearShader; break; case GL_UNSIGNED_INT: ApplyVertices(framebufferSize, scissorPtr, clearParams.colorUIClearValue, clearParams.depthClearValue, mappedResource.pData); vertexStride = sizeof(d3d11::PositionDepthColorVertex<unsigned int>); shader = &mUintClearShader; break; case GL_INT: ApplyVertices(framebufferSize, scissorPtr, clearParams.colorIClearValue, clearParams.depthClearValue, mappedResource.pData); vertexStride = sizeof(d3d11::PositionDepthColorVertex<int>); shader = &mIntClearShader; break; default: UNREACHABLE(); break; } deviceContext->Unmap(mVertexBuffer, 0); // Set the viewport to be the same size as the framebuffer D3D11_VIEWPORT viewport; viewport.TopLeftX = 0; viewport.TopLeftY = 0; viewport.Width = framebufferSize.width; viewport.Height = framebufferSize.height; viewport.MinDepth = 0; viewport.MaxDepth = 1; deviceContext->RSSetViewports(1, &viewport); // Apply state deviceContext->OMSetBlendState(blendState, blendFactors, sampleMask); deviceContext->OMSetDepthStencilState(dsState, stencilClear); deviceContext->RSSetState(mRasterizerState); // Apply shaders deviceContext->IASetInputLayout(shader->inputLayout); deviceContext->VSSetShader(shader->vertexShader, NULL, 0); deviceContext->PSSetShader(shader->pixelShader, NULL, 0); deviceContext->GSSetShader(NULL, NULL, 0); // Apply vertex buffer deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &vertexStride, &startIdx); deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); // Apply render targets deviceContext->OMSetRenderTargets(rtvs.size(), (rtvs.empty() ? NULL : &rtvs[0]), dsv); // Draw the clear quad deviceContext->Draw(4, 0); // Clean up mRenderer->markAllStateDirty(); } }
gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams, const gl::Framebuffer::Data &fboData) { const auto &colorAttachments = fboData.mColorAttachments; const auto &drawBufferStates = fboData.mDrawBufferStates; const auto *depthAttachment = fboData.mDepthAttachment; const auto *stencilAttachment = fboData.mStencilAttachment; ASSERT(colorAttachments.size() == drawBufferStates.size()); // Iterate over the color buffers which require clearing and determine if they can be // cleared with ID3D11DeviceContext::ClearRenderTargetView or ID3D11DeviceContext1::ClearView. // This requires: // 1) The render target is being cleared to a float value (will be cast to integer when clearing integer // render targets as expected but does not work the other way around) // 2) The format of the render target has no color channels that are currently masked out. // Clear the easy-to-clear buffers on the spot and accumulate the ones that require special work. // // If these conditions are met, and: // - No scissored clear is needed, then clear using ID3D11DeviceContext::ClearRenderTargetView. // - A scissored clear is needed then clear using ID3D11DeviceContext1::ClearView if available. // Otherwise draw a quad. // // Also determine if the depth stencil can be cleared with ID3D11DeviceContext::ClearDepthStencilView // by checking if the stencil write mask covers the entire stencil. // // To clear the remaining buffers, quads must be drawn containing an int, uint or float vertex color // attribute. gl::Extents framebufferSize; auto iter = std::find_if(colorAttachments.begin(), colorAttachments.end(), [](const gl::FramebufferAttachment *attachment) { return attachment != nullptr; }); if (iter != colorAttachments.end()) { framebufferSize.width = (*iter)->getWidth(); framebufferSize.height = (*iter)->getHeight(); framebufferSize.depth = 1; } else if (depthAttachment != nullptr) { framebufferSize.width = depthAttachment->getWidth(); framebufferSize.height = depthAttachment->getHeight(); framebufferSize.depth = 1; } else if (stencilAttachment != nullptr) { framebufferSize.width = stencilAttachment->getWidth(); framebufferSize.height = stencilAttachment->getHeight(); framebufferSize.depth = 1; } else { UNREACHABLE(); return gl::Error(GL_INVALID_OPERATION); } if (clearParams.scissorEnabled && (clearParams.scissor.x >= framebufferSize.width || clearParams.scissor.y >= framebufferSize.height || clearParams.scissor.x + clearParams.scissor.width <= 0 || clearParams.scissor.y + clearParams.scissor.height <= 0)) { // Scissor is enabled and the scissor rectangle is outside the renderbuffer return gl::Error(GL_NO_ERROR); } bool needScissoredClear = clearParams.scissorEnabled && (clearParams.scissor.x > 0 || clearParams.scissor.y > 0 || clearParams.scissor.x + clearParams.scissor.width < framebufferSize.width || clearParams.scissor.y + clearParams.scissor.height < framebufferSize.height); std::vector<MaskedRenderTarget> maskedClearRenderTargets; RenderTarget11* maskedClearDepthStencil = NULL; ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported(); for (size_t colorAttachment = 0; colorAttachment < colorAttachments.size(); colorAttachment++) { if (clearParams.clearColor[colorAttachment] && colorAttachments[colorAttachment] != nullptr && drawBufferStates[colorAttachment] != GL_NONE) { const gl::FramebufferAttachment *attachment = colorAttachments[colorAttachment]; RenderTarget11 *renderTarget = NULL; gl::Error error = d3d11::GetAttachmentRenderTarget(attachment, &renderTarget); if (error.isError()) { return error; } const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(attachment->getInternalFormat()); if (clearParams.colorClearType == GL_FLOAT && !(formatInfo.componentType == GL_FLOAT || formatInfo.componentType == GL_UNSIGNED_NORMALIZED || formatInfo.componentType == GL_SIGNED_NORMALIZED)) { ERR("It is undefined behaviour to clear a render buffer which is not normalized fixed point or floating-" "point to floating point values (color attachment %u has internal format 0x%X).", colorAttachment, attachment->getInternalFormat()); } if ((formatInfo.redBits == 0 || !clearParams.colorMaskRed) && (formatInfo.greenBits == 0 || !clearParams.colorMaskGreen) && (formatInfo.blueBits == 0 || !clearParams.colorMaskBlue) && (formatInfo.alphaBits == 0 || !clearParams.colorMaskAlpha)) { // Every channel either does not exist in the render target or is masked out continue; } else if ((!mSupportsClearView && needScissoredClear) || clearParams.colorClearType != GL_FLOAT || (formatInfo.redBits > 0 && !clearParams.colorMaskRed) || (formatInfo.greenBits > 0 && !clearParams.colorMaskGreen) || (formatInfo.blueBits > 0 && !clearParams.colorMaskBlue) || (formatInfo.alphaBits > 0 && !clearParams.colorMaskAlpha)) { // A masked clear is required, or a scissored clear is required and ID3D11DeviceContext1::ClearView is unavailable MaskedRenderTarget maskAndRt; bool clearColor = clearParams.clearColor[colorAttachment]; maskAndRt.colorMask[0] = (clearColor && clearParams.colorMaskRed); maskAndRt.colorMask[1] = (clearColor && clearParams.colorMaskGreen); maskAndRt.colorMask[2] = (clearColor && clearParams.colorMaskBlue); maskAndRt.colorMask[3] = (clearColor && clearParams.colorMaskAlpha); maskAndRt.renderTarget = renderTarget; maskedClearRenderTargets.push_back(maskAndRt); } else { // ID3D11DeviceContext::ClearRenderTargetView or ID3D11DeviceContext1::ClearView is possible ID3D11RenderTargetView *framebufferRTV = renderTarget->getRenderTargetView(); if (!framebufferRTV) { return gl::Error(GL_OUT_OF_MEMORY, "Internal render target view pointer unexpectedly null."); } const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(renderTarget->getDXGIFormat()); // Check if the actual format has a channel that the internal format does not and set them to the // default values const float clearValues[4] = { ((formatInfo.redBits == 0 && dxgiFormatInfo.redBits > 0) ? 0.0f : clearParams.colorFClearValue.red), ((formatInfo.greenBits == 0 && dxgiFormatInfo.greenBits > 0) ? 0.0f : clearParams.colorFClearValue.green), ((formatInfo.blueBits == 0 && dxgiFormatInfo.blueBits > 0) ? 0.0f : clearParams.colorFClearValue.blue), ((formatInfo.alphaBits == 0 && dxgiFormatInfo.alphaBits > 0) ? 1.0f : clearParams.colorFClearValue.alpha), }; if (needScissoredClear) { // We shouldn't reach here if deviceContext1 is unavailable. ASSERT(deviceContext1); D3D11_RECT rect; rect.left = clearParams.scissor.x; rect.right = clearParams.scissor.x + clearParams.scissor.width; rect.top = clearParams.scissor.y; rect.bottom = clearParams.scissor.y + clearParams.scissor.height; deviceContext1->ClearView(framebufferRTV, clearValues, &rect, 1); } else { deviceContext->ClearRenderTargetView(framebufferRTV, clearValues); } } } } if (clearParams.clearDepth || clearParams.clearStencil) { const gl::FramebufferAttachment *attachment = (depthAttachment != nullptr) ? depthAttachment : stencilAttachment; ASSERT(attachment != nullptr); RenderTarget11 *renderTarget = NULL; gl::Error error = d3d11::GetAttachmentRenderTarget(attachment, &renderTarget); if (error.isError()) { return error; } const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(renderTarget->getDXGIFormat()); unsigned int stencilUnmasked = (stencilAttachment != nullptr) ? (1 << dxgiFormatInfo.stencilBits) - 1 : 0; bool needMaskedStencilClear = clearParams.clearStencil && (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked; if (needScissoredClear || needMaskedStencilClear) { maskedClearDepthStencil = renderTarget; } else { ID3D11DepthStencilView *framebufferDSV = renderTarget->getDepthStencilView(); if (!framebufferDSV) { return gl::Error(GL_OUT_OF_MEMORY, "Internal depth stencil view pointer unexpectedly null."); } UINT clearFlags = (clearParams.clearDepth ? D3D11_CLEAR_DEPTH : 0) | (clearParams.clearStencil ? D3D11_CLEAR_STENCIL : 0); FLOAT depthClear = gl::clamp01(clearParams.depthClearValue); UINT8 stencilClear = clearParams.stencilClearValue & 0xFF; deviceContext->ClearDepthStencilView(framebufferDSV, clearFlags, depthClear, stencilClear); } } if (maskedClearRenderTargets.size() > 0 || maskedClearDepthStencil) { // To clear the render targets and depth stencil in one pass: // // Render a quad clipped to the scissor rectangle which draws the clear color and a blend // state that will perform the required color masking. // // The quad's depth is equal to the depth clear value with a depth stencil state that // will enable or disable depth test/writes if the depth buffer should be cleared or not. // // The rasterizer state's stencil is set to always pass or fail based on if the stencil // should be cleared or not with a stencil write mask of the stencil clear value. // // ====================================================================================== // // Luckily, the gl spec (ES 3.0.2 pg 183) states that the results of clearing a render- // buffer that is not normalized fixed point or floating point with floating point values // are undefined so we can just write floats to them and D3D11 will bit cast them to // integers. // // Also, we don't have to worry about attempting to clear a normalized fixed/floating point // buffer with integer values because there is no gl API call which would allow it, // glClearBuffer* calls only clear a single renderbuffer at a time which is verified to // be a compatible clear type. // Bind all the render targets which need clearing ASSERT(maskedClearRenderTargets.size() <= mRenderer->getRendererCaps().maxDrawBuffers); std::vector<ID3D11RenderTargetView*> rtvs(maskedClearRenderTargets.size()); for (unsigned int i = 0; i < maskedClearRenderTargets.size(); i++) { RenderTarget11 *renderTarget = maskedClearRenderTargets[i].renderTarget; ID3D11RenderTargetView *rtv = renderTarget->getRenderTargetView(); if (!rtv) { return gl::Error(GL_OUT_OF_MEMORY, "Internal render target view pointer unexpectedly null."); } rtvs[i] = rtv; } ID3D11DepthStencilView *dsv = maskedClearDepthStencil ? maskedClearDepthStencil->getDepthStencilView() : NULL; ID3D11BlendState *blendState = getBlendState(maskedClearRenderTargets); const FLOAT blendFactors[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; const UINT sampleMask = 0xFFFFFFFF; ID3D11DepthStencilState *dsState = getDepthStencilState(clearParams); const UINT stencilClear = clearParams.stencilClearValue & 0xFF; // Set the vertices UINT vertexStride = 0; const UINT startIdx = 0; const ClearShader* shader = NULL; D3D11_MAPPED_SUBRESOURCE mappedResource; HRESULT result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); if (FAILED(result)) { return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal masked clear vertex buffer, HRESULT: 0x%X.", result); } const gl::Rectangle *scissorPtr = clearParams.scissorEnabled ? &clearParams.scissor : NULL; switch (clearParams.colorClearType) { case GL_FLOAT: ApplyVertices(framebufferSize, scissorPtr, clearParams.colorFClearValue, clearParams.depthClearValue, mappedResource.pData); vertexStride = sizeof(d3d11::PositionDepthColorVertex<float>); shader = &mFloatClearShader; break; case GL_UNSIGNED_INT: ApplyVertices(framebufferSize, scissorPtr, clearParams.colorUIClearValue, clearParams.depthClearValue, mappedResource.pData); vertexStride = sizeof(d3d11::PositionDepthColorVertex<unsigned int>); shader = &mUintClearShader; break; case GL_INT: ApplyVertices(framebufferSize, scissorPtr, clearParams.colorIClearValue, clearParams.depthClearValue, mappedResource.pData); vertexStride = sizeof(d3d11::PositionDepthColorVertex<int>); shader = &mIntClearShader; break; default: UNREACHABLE(); break; } deviceContext->Unmap(mVertexBuffer, 0); // Set the viewport to be the same size as the framebuffer D3D11_VIEWPORT viewport; viewport.TopLeftX = 0; viewport.TopLeftY = 0; viewport.Width = framebufferSize.width; viewport.Height = framebufferSize.height; viewport.MinDepth = 0; viewport.MaxDepth = 1; deviceContext->RSSetViewports(1, &viewport); // Apply state deviceContext->OMSetBlendState(blendState, blendFactors, sampleMask); deviceContext->OMSetDepthStencilState(dsState, stencilClear); deviceContext->RSSetState(mRasterizerState); // Apply shaders deviceContext->IASetInputLayout(shader->inputLayout); deviceContext->VSSetShader(shader->vertexShader, NULL, 0); deviceContext->PSSetShader(shader->pixelShader, NULL, 0); deviceContext->GSSetShader(NULL, NULL, 0); // Apply vertex buffer deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &vertexStride, &startIdx); deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); // Apply render targets deviceContext->OMSetRenderTargets(rtvs.size(), (rtvs.empty() ? NULL : &rtvs[0]), dsv); // Draw the clear quad deviceContext->Draw(4, 0); // Clean up mRenderer->markAllStateDirty(); } return gl::Error(GL_NO_ERROR); }
/** Binds a pipeline-state */ void D3D11GraphicsEngineQueued::BindPipelineState(const PipelineState* state) { D3D11PipelineState* s = (D3D11PipelineState*)state; D3D11PipelineState* b = (D3D11PipelineState*)BoundPipelineStateByThread[GetCurrentThreadId()]; ID3D11DeviceContext* context = GetDeferredContextByThread(); if(!b) b = (D3D11PipelineState*)&DefaultPipelineState; // Bind state if(b->BlendState != s->BlendState) SC_DBG(context->OMSetBlendState(s->BlendState, (float *)&D3DXVECTOR4(0, 0, 0, 0), 0xFFFFFFFF), GothicRendererInfo::SC_BS); if(b->SamplerState != s->SamplerState) SC_DBG(context->PSSetSamplers(0, 1, &s->SamplerState), GothicRendererInfo::SC_SMPL); if(b->DepthStencilState != s->DepthStencilState) SC_DBG(context->OMSetDepthStencilState(s->DepthStencilState, 0), GothicRendererInfo::SC_DSS); if(b->RasterizerState != s->RasterizerState) SC_DBG(context->RSSetState(s->RasterizerState), GothicRendererInfo::SC_RS); // Bind constantbuffers (They are likely to change for every object) if(!s->ConstantBuffersVS.empty() && s->ConstantBuffersVS != b->ConstantBuffersVS)SC_DBG(context->VSSetConstantBuffers(0, s->ConstantBuffersVS.size(), &s->ConstantBuffersVS[0]),GothicRendererInfo::SC_CB); if(!s->ConstantBuffersPS.empty() && s->ConstantBuffersPS != b->ConstantBuffersPS)SC_DBG(context->PSSetConstantBuffers(0, s->ConstantBuffersPS.size(), &s->ConstantBuffersPS[0]),GothicRendererInfo::SC_CB); if(!s->ConstantBuffersHDS.empty() && s->ConstantBuffersHDS != b->ConstantBuffersHDS)SC_DBG(context->HSSetConstantBuffers(0, s->ConstantBuffersHDS.size(), &s->ConstantBuffersHDS[0]),GothicRendererInfo::SC_CB); if(!s->ConstantBuffersHDS.empty() && s->ConstantBuffersHDS != b->ConstantBuffersHDS)SC_DBG(context->DSSetConstantBuffers(0, s->ConstantBuffersHDS.size(), &s->ConstantBuffersHDS[0]),GothicRendererInfo::SC_CB); if(!s->ConstantBuffersGS.empty() && s->ConstantBuffersGS != b->ConstantBuffersGS)SC_DBG(context->GSSetConstantBuffers(0, s->ConstantBuffersGS.size(), &s->ConstantBuffersGS[0]),GothicRendererInfo::SC_CB); // Vertexbuffers UINT off[] = {0,0}; if(memcmp(s->BaseState.VertexBuffers, b->BaseState.VertexBuffers, sizeof(b->BaseState.VertexBuffers)) != 0) SC_DBG(context->IASetVertexBuffers(0, s->VertexBuffers.size(), &s->VertexBuffers[0], s->BaseState.VertexStride, off), GothicRendererInfo::SC_VB); if(!s->StructuredBuffersVS.empty() && memcmp(s->BaseState.StructuredBuffersVS, b->BaseState.StructuredBuffersVS, sizeof(b->BaseState.StructuredBuffersVS)) != 0) SC_DBG(context->VSSetShaderResources(0, 1, &s->StructuredBuffersVS[0]), GothicRendererInfo::SC_VB); if(s->IndexBuffer != b->IndexBuffer) SC_DBG(context->IASetIndexBuffer(s->IndexBuffer, s->BaseState.IndexStride == 4 ? DXGI_FORMAT_R32_UINT : DXGI_FORMAT_R16_UINT, 0), GothicRendererInfo::SC_IB); // Shaders if(s->VertexShader != b->VertexShader) SC_DBG(context->VSSetShader(s->VertexShader, NULL, NULL), GothicRendererInfo::SC_VS); if(s->InputLayout != b->InputLayout) SC_DBG(context->IASetInputLayout(s->InputLayout), GothicRendererInfo::SC_IL); if(s->PixelShader != b->PixelShader) SC_DBG(context->PSSetShader(s->PixelShader, NULL, NULL), GothicRendererInfo::SC_PS); if(s->HullShader != b->HullShader) SC_DBG(context->HSSetShader(s->HullShader, NULL, NULL), GothicRendererInfo::SC_HS); if(s->DomainShader != b->DomainShader) SC_DBG(context->DSSetShader(s->DomainShader, NULL, NULL), GothicRendererInfo::SC_DS); if(s->GeometryShader != b->GeometryShader) SC_DBG(context->GSSetShader(s->GeometryShader, NULL, NULL), GothicRendererInfo::SC_GS); // Rendertargets if(memcmp(s->RenderTargetViews, b->RenderTargetViews, sizeof(void*) * s->NumRenderTargetViews) != 0 || s->DepthStencilView != b->DepthStencilView) SC_DBG(context->OMSetRenderTargets(s->NumRenderTargetViews, s->RenderTargetViews, s->DepthStencilView), GothicRendererInfo::SC_RTVDSV); // Textures if(memcmp(s->Textures, b->Textures, sizeof(void*) * s->BaseState.NumTextures) != 0) SC_DBG(context->PSSetShaderResources(0, s->BaseState.NumTextures, s->Textures), GothicRendererInfo::SC_TX); // Primitive topology //Context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); // Replace old state // FIXME: Might not threadsave BoundPipelineStateByThread[GetCurrentThreadId()] = s; }
// parameters should be validated/clamped by caller EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) { if (!mSwapChain) { return EGL_SUCCESS; } ID3D11Device *device = mRenderer->getDevice(); ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); // Set vertices D3D11_MAPPED_SUBRESOURCE mappedResource; HRESULT result = deviceContext->Map(mQuadVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); if (FAILED(result)) { return EGL_BAD_ACCESS; } d3d11::PositionTexCoordVertex *vertices = static_cast<d3d11::PositionTexCoordVertex*>(mappedResource.pData); // Create a quad in homogeneous coordinates float x1 = (x / float(mWidth)) * 2.0f - 1.0f; float y1 = (y / float(mHeight)) * 2.0f - 1.0f; float x2 = ((x + width) / float(mWidth)) * 2.0f - 1.0f; float y2 = ((y + height) / float(mHeight)) * 2.0f - 1.0f; float u1 = x / float(mWidth); float v1 = y / float(mHeight); float u2 = (x + width) / float(mWidth); float v2 = (y + height) / float(mHeight); d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v1); d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v2); d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v1); d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v2); deviceContext->Unmap(mQuadVB, 0); static UINT stride = sizeof(d3d11::PositionTexCoordVertex); static UINT startIdx = 0; deviceContext->IASetVertexBuffers(0, 1, &mQuadVB, &stride, &startIdx); // Apply state deviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF); static const float blendFactor[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; deviceContext->OMSetBlendState(NULL, blendFactor, 0xFFFFFFF); deviceContext->RSSetState(NULL); // Apply shaders deviceContext->IASetInputLayout(mPassThroughIL); deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); deviceContext->VSSetShader(mPassThroughVS, NULL, 0); deviceContext->PSSetShader(mPassThroughPS, NULL, 0); deviceContext->GSSetShader(NULL, NULL, 0); // Apply render targets mRenderer->setOneTimeRenderTarget(mBackBufferRTView); // Set the viewport D3D11_VIEWPORT viewport; viewport.TopLeftX = 0; viewport.TopLeftY = 0; viewport.Width = mWidth; viewport.Height = mHeight; viewport.MinDepth = 0.0f; viewport.MaxDepth = 1.0f; deviceContext->RSSetViewports(1, &viewport); // Apply textures deviceContext->PSSetShaderResources(0, 1, &mOffscreenSRView); deviceContext->PSSetSamplers(0, 1, &mPassThroughSampler); // Draw deviceContext->Draw(4, 0); result = mSwapChain->Present(mSwapInterval, 0); if (result == DXGI_ERROR_DEVICE_REMOVED) { HRESULT removedReason = device->GetDeviceRemovedReason(); ERR("Present failed: the D3D11 device was removed: 0x%08X", removedReason); return EGL_CONTEXT_LOST; } else if (result == DXGI_ERROR_DEVICE_RESET) { ERR("Present failed: the D3D11 device was reset from a bad command."); return EGL_CONTEXT_LOST; } else if (FAILED(result)) { ERR("Present failed with error code 0x%08X", result); } // Unbind static ID3D11ShaderResourceView *const nullSRV = NULL; deviceContext->PSSetShaderResources(0, 1, &nullSRV); mRenderer->unapplyRenderTargets(); mRenderer->markAllStateDirty(); return EGL_SUCCESS; }
// parameters should be validated/clamped by caller EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) { if (!mSwapChain) { return EGL_SUCCESS; } if (mRenderToBackBuffer) { // When rendering directly to the backbuffer, we must swap the whole buffer. if (!(x == 0 && y == 0 && width == mWidth && height == mHeight)) { ERR("When rendering directly to the backbuffer, swapRect can only be called on the entire backbuffer."); ASSERT(false); return EGL_FALSE; } } HRESULT result = S_OK; ID3D11Device *device = mRenderer->getDevice(); if (!mRenderToBackBuffer) { ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); // Set vertices D3D11_MAPPED_SUBRESOURCE mappedResource; result = deviceContext->Map(mQuadVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); if (FAILED(result)) { return EGL_BAD_ACCESS; } d3d11::PositionTexCoordVertex *vertices = static_cast<d3d11::PositionTexCoordVertex*>(mappedResource.pData); // Create a quad in homogeneous coordinates float x1 = (x / float(mWidth)) * 2.0f - 1.0f; float y1 = (y / float(mHeight)) * 2.0f - 1.0f; float x2 = ((x + width) / float(mWidth)) * 2.0f - 1.0f; float y2 = ((y + height) / float(mHeight)) * 2.0f - 1.0f; float u1 = x / float(mWidth); float v1 = y / float(mHeight); float u2 = (x + width) / float(mWidth); float v2 = (y + height) / float(mHeight); d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v1); d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v2); d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v1); d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v2); deviceContext->Unmap(mQuadVB, 0); static UINT stride = sizeof(d3d11::PositionTexCoordVertex); static UINT startIdx = 0; deviceContext->IASetVertexBuffers(0, 1, &mQuadVB, &stride, &startIdx); // Apply state deviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF); static const float blendFactor[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; deviceContext->OMSetBlendState(NULL, blendFactor, 0xFFFFFFF); deviceContext->RSSetState(NULL); // Apply shaders deviceContext->IASetInputLayout(mPassThroughIL); deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); deviceContext->VSSetShader(mPassThroughVS, NULL, 0); deviceContext->PSSetShader(mPassThroughPS, NULL, 0); deviceContext->GSSetShader(NULL, NULL, 0); // Apply render targets mRenderer->setOneTimeRenderTarget(mBackBufferRTView); // Set the viewport D3D11_VIEWPORT viewport; viewport.TopLeftX = 0; viewport.TopLeftY = 0; viewport.Width = static_cast<FLOAT>(mWidth); viewport.Height = static_cast<FLOAT>(mHeight); viewport.MinDepth = 0.0f; viewport.MaxDepth = 1.0f; deviceContext->RSSetViewports(1, &viewport); // Apply textures mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, mOffscreenSRView); deviceContext->PSSetSamplers(0, 1, &mPassThroughSampler); // Draw deviceContext->Draw(4, 0); } #if ANGLE_VSYNC == ANGLE_DISABLED result = mSwapChain->Present(0, 0); #else // Use IDXGISwapChain1::Present1 with a dirty rect if DXGI 1.2 is available. if (mSwapChain1 != nullptr) { RECT rect = { static_cast<LONG>(x), static_cast<LONG>(mHeight - y - height), static_cast<LONG>(x + width), static_cast<LONG>(mHeight - y) }; DXGI_PRESENT_PARAMETERS params = { 1, &rect, nullptr, nullptr }; result = mSwapChain1->Present1(mSwapInterval, 0, ¶ms); } else { result = mSwapChain->Present(mSwapInterval, 0); } #endif if (result == DXGI_ERROR_DEVICE_REMOVED) { HRESULT removedReason = device->GetDeviceRemovedReason(); UNUSED_TRACE_VARIABLE(removedReason); ERR("Present failed: the D3D11 device was removed: 0x%08X", removedReason); return EGL_CONTEXT_LOST; } else if (result == DXGI_ERROR_DEVICE_RESET) { ERR("Present failed: the D3D11 device was reset from a bad command."); return EGL_CONTEXT_LOST; } else if (FAILED(result)) { ERR("Present failed with error code 0x%08X", result); } // Unbind mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL); mRenderer->unapplyRenderTargets(); mRenderer->markAllStateDirty(); return EGL_SUCCESS; }
/// Called by D3D11 device to active this state block. /// @param oldState The current state, used to make sure we don't set redundant states on the device. Pass NULL to reset all states. void GFXD3D11StateBlock::activate(GFXD3D11StateBlock* oldState) { PROFILE_SCOPE( GFXD3D11StateBlock_Activate ); ID3D11DeviceContext* pDevCxt = D3D11DEVICECONTEXT; mBlendDesc.AlphaToCoverageEnable = false; mBlendDesc.IndependentBlendEnable = mDesc.separateAlphaBlendEnable; mBlendDesc.RenderTarget[0].BlendEnable = mDesc.blendEnable; mBlendDesc.RenderTarget[0].BlendOp = GFXD3D11BlendOp[mDesc.blendOp]; mBlendDesc.RenderTarget[0].BlendOpAlpha = GFXD3D11BlendOp[mDesc.separateAlphaBlendOp]; mBlendDesc.RenderTarget[0].DestBlend = GFXD3D11Blend[mDesc.blendDest]; mBlendDesc.RenderTarget[0].DestBlendAlpha = GFXD3D11Blend[mDesc.separateAlphaBlendDest]; mBlendDesc.RenderTarget[0].SrcBlend = GFXD3D11Blend[mDesc.blendSrc]; mBlendDesc.RenderTarget[0].SrcBlendAlpha = GFXD3D11Blend[mDesc.separateAlphaBlendSrc]; mBlendDesc.RenderTarget[0].RenderTargetWriteMask = mColorMask; float blendFactor[] = { 1.0f, 1.0f, 1.0f, 1.0f }; pDevCxt->OMSetBlendState(mBlendState, blendFactor, 0xFFFFFFFF); mDepthStencilDesc.DepthWriteMask = mDesc.zWriteEnable ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO; mDepthStencilDesc.DepthEnable = mDesc.zEnable; mDepthStencilDesc.DepthFunc = GFXD3D11CmpFunc[mDesc.zFunc]; mDepthStencilDesc.StencilWriteMask = mDesc.stencilWriteMask; mDepthStencilDesc.StencilReadMask = mDesc.stencilMask; mDepthStencilDesc.StencilEnable = mDesc.stencilEnable; mDepthStencilDesc.FrontFace.StencilFunc = GFXD3D11CmpFunc[mDesc.stencilFunc]; mDepthStencilDesc.FrontFace.StencilFailOp = GFXD3D11StencilOp[mDesc.stencilFailOp]; mDepthStencilDesc.FrontFace.StencilDepthFailOp = GFXD3D11StencilOp[mDesc.stencilZFailOp]; mDepthStencilDesc.FrontFace.StencilPassOp = GFXD3D11StencilOp[mDesc.stencilPassOp]; if (mDesc.stencilEnable) mDepthStencilDesc.BackFace = mDepthStencilDesc.FrontFace; else { mDepthStencilDesc.BackFace.StencilFunc = GFXD3D11CmpFunc[GFXCmpAlways]; mDepthStencilDesc.BackFace.StencilFailOp = GFXD3D11StencilOp[GFXStencilOpKeep]; mDepthStencilDesc.BackFace.StencilDepthFailOp = GFXD3D11StencilOp[GFXStencilOpKeep]; mDepthStencilDesc.BackFace.StencilPassOp = GFXD3D11StencilOp[GFXStencilOpKeep]; } pDevCxt->OMSetDepthStencilState(mDepthStencilState, mDesc.stencilRef); mRasterizerDesc.CullMode = GFXD3D11CullMode[mDesc.cullMode]; mRasterizerDesc.FillMode = GFXD3D11FillMode[mDesc.fillMode]; mRasterizerDesc.DepthBias = mDesc.zBias; mRasterizerDesc.SlopeScaledDepthBias = mDesc.zSlopeBias; mRasterizerDesc.AntialiasedLineEnable = FALSE; mRasterizerDesc.MultisampleEnable = FALSE; mRasterizerDesc.ScissorEnable = FALSE; if (mDesc.zEnable) mRasterizerDesc.DepthClipEnable = true; else mRasterizerDesc.DepthClipEnable = false; mRasterizerDesc.FrontCounterClockwise = FALSE; mRasterizerDesc.DepthBiasClamp = 0.0f; pDevCxt->RSSetState(mRasterizerState); U32 numSamplers = GFX->getNumSamplers(); for (U32 i = 0; i < numSamplers; i++) { mSamplerDesc[i].AddressU = GFXD3D11TextureAddress[mDesc.samplers[i].addressModeU]; mSamplerDesc[i].AddressV = GFXD3D11TextureAddress[mDesc.samplers[i].addressModeV]; mSamplerDesc[i].AddressW = GFXD3D11TextureAddress[mDesc.samplers[i].addressModeW]; mSamplerDesc[i].MaxAnisotropy = mDesc.samplers[i].maxAnisotropy; mSamplerDesc[i].MipLODBias = mDesc.samplers[i].mipLODBias; mSamplerDesc[i].MinLOD = 0; mSamplerDesc[i].MaxLOD = FLT_MAX; if(mDesc.samplers[i].magFilter == GFXTextureFilterPoint && mDesc.samplers[i].minFilter == GFXTextureFilterPoint && mDesc.samplers[i].mipFilter == GFXTextureFilterPoint) mSamplerDesc[i].Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; else if(mDesc.samplers[i].magFilter == GFXTextureFilterPoint && mDesc.samplers[i].minFilter == GFXTextureFilterPoint && mDesc.samplers[i].mipFilter == GFXTextureFilterLinear) mSamplerDesc[i].Filter = D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR; else if(mDesc.samplers[i].magFilter == GFXTextureFilterLinear && mDesc.samplers[i].minFilter == GFXTextureFilterPoint && mDesc.samplers[i].mipFilter == GFXTextureFilterPoint) mSamplerDesc[i].Filter = D3D11_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT; else if(mDesc.samplers[i].magFilter == GFXTextureFilterLinear && mDesc.samplers[i].minFilter == GFXTextureFilterPoint && mDesc.samplers[i].mipFilter == GFXTextureFilterLinear) mSamplerDesc[i].Filter = D3D11_FILTER_MIN_POINT_MAG_MIP_LINEAR; else if(mDesc.samplers[i].magFilter == GFXTextureFilterPoint && mDesc.samplers[i].minFilter == GFXTextureFilterLinear && mDesc.samplers[i].mipFilter == GFXTextureFilterPoint) mSamplerDesc[i].Filter = D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT; else if(mDesc.samplers[i].magFilter == GFXTextureFilterPoint && mDesc.samplers[i].minFilter == GFXTextureFilterLinear && mDesc.samplers[i].mipFilter == GFXTextureFilterLinear) mSamplerDesc[i].Filter = D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR; else if(mDesc.samplers[i].magFilter == GFXTextureFilterLinear && mDesc.samplers[i].minFilter == GFXTextureFilterLinear && mDesc.samplers[i].mipFilter == GFXTextureFilterPoint) mSamplerDesc[i].Filter = D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT; else if(mDesc.samplers[i].magFilter == GFXTextureFilterLinear && mDesc.samplers[i].minFilter == GFXTextureFilterLinear && mDesc.samplers[i].mipFilter == GFXTextureFilterLinear) mSamplerDesc[i].Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; else mSamplerDesc[i].Filter = D3D11_FILTER_ANISOTROPIC; mSamplerDesc[i].BorderColor[0] = 0.0f; mSamplerDesc[i].BorderColor[1] = 0.0f; mSamplerDesc[i].BorderColor[2] = 0.0f; mSamplerDesc[i].BorderColor[3] = 0.0f; mSamplerDesc[i].ComparisonFunc = D3D11_COMPARISON_NEVER; } //TODO samplers for vertex shader // Set all the samplers with one call //pDevCxt->VSSetSamplers(0, numSamplers, &mSamplerStates[0]); pDevCxt->PSSetSamplers(0, numSamplers, &mSamplerStates[0]); }
void BillboardTrees::Render() { if (!m_loadingComplete) return; auto renderStateMgr = RenderStateMgr::Instance(); ID3D11DeviceContext* context = m_deviceResources->GetD3DDeviceContext(); // Set IA stage UINT stride = sizeof(PointSize); UINT offset = 0; if (ShaderChangement::PrimitiveType != D3D11_PRIMITIVE_TOPOLOGY_POINTLIST) { context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); ShaderChangement::PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST; } if (ShaderChangement::InputLayout != m_treeInputLayout.Get()) { context->IASetInputLayout(m_treeInputLayout.Get()); ShaderChangement::InputLayout = m_treeInputLayout.Get(); } context->IASetVertexBuffers(0, 1, m_treeSpriteVB.GetAddressOf(), &stride, &offset); ID3D11Buffer* cbuffers[2] = { m_perFrameCB->GetBuffer(), m_treeSettingsCB.GetBuffer() }; ID3D11SamplerState* samplers[1] = { renderStateMgr->LinearSam() }; // Bind shaders, constant buffers, srvs and samplers context->VSSetShader(m_treeVS.Get(), 0, 0); ShaderChangement::VS = m_treeVS.Get(); context->GSSetShader(m_treeGS.Get(), 0, 0); context->GSSetConstantBuffers(0, 1, cbuffers); switch (m_renderOptions) { case BillTreeRenderOption::Light3: // Light context->PSSetShader(m_treeLight3PS.Get(), 0, 0); ShaderChangement::PS = m_treeLight3PS.Get(); break; case BillTreeRenderOption::Light3TexClip: // LightTexClip context->PSSetShader(m_treeLight3TexClipPS.Get(), 0, 0); ShaderChangement::PS = m_treeLight3TexClipPS.Get(); break; case BillTreeRenderOption::Light3TexClipFog: // LightTexClipFog context->PSSetShader(m_treeLight3TexClipFogPS.Get(), 0, 0); ShaderChangement::PS = m_treeLight3TexClipFogPS.Get(); break; default: throw ref new Platform::InvalidArgumentException("No such render option"); } context->PSSetConstantBuffers(0, 2, cbuffers); context->PSSetSamplers(0, 1, samplers); context->PSSetShaderResources(0, 1, m_treeTextureMapArraySRV.GetAddressOf()); float blendFactor[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; if (m_alphaToCoverage) context->OMSetBlendState(renderStateMgr->AlphaToCoverBS(), blendFactor, 0xffffffff); context->Draw(m_treeCount, 0); // Recover render state if (m_alphaToCoverage) context->OMSetBlendState(nullptr, blendFactor, 0xffffffff); // Remove gs context->GSSetShader(nullptr, 0, 0); ShaderChangement::GS = nullptr; }
void VegetationRendering::draw(ID3D11Device* device, const GameTime& gameTime) { ID3D11DeviceContext* deviceContext; device->GetImmediateContext(&deviceContext); D3D11_VIEWPORT viewport; unsigned numViewports = 1; deviceContext->RSGetViewports(&numViewports, &viewport); camera->setAspectRatio(viewport.Width / viewport.Height); deviceContext->RSSetState(rsCullBack); deviceContext->OMSetBlendState(bsDefault, Vector4(0,0,0,0), 0xFFFFFFFF); terrain->draw(device, gameTime); //tessellationTerrain->draw(device, gameTime); if (complexTreesEnabled) trunk->draw(device, gameTime); deviceContext->RSSetState(rsCullNone); if(treeModelsEnabled) { separateLeafModel->draw(device, gameTime); billboardLeafModel->draw(device, gameTime); } if (defaultTreesEnabled) { for(int i = 0; i < trunk->getDrawInstanceCount(); ++i) { Matrix trunkWorld = Matrix::createTranslation(trunk->getTreePositions()[i]); /*if(defaultDetailedEnabled) { defaultTrunkDetailedModel->setWorld(trunkWorld); defaultTrunkDetailedModel->draw(device, gameTime); } else {*/ defaultTrunkModel->setWorld(trunkWorld); defaultTrunkModel->draw(device, gameTime); //} } } if (complexGrassEnabled) complexGrass->draw(device, gameTime); if (defaultGrassEnabled) { for(int i = 0; i < complexGrass->getDrawInstanceCount(); ++i) { Matrix grassWorld = Matrix::createScale(complexGrass->getScale()) * Matrix::createTranslation(complexGrass->getGrassPatchPositions()[i]); if(defaultDetailedEnabled) { defaultGrassDetailedModel->setWorld(grassWorld); defaultGrassDetailedModel->draw(device, gameTime); } else { defaultGrassModel->setWorld(grassWorld); defaultGrassModel->draw(device, gameTime); } } } deviceContext->OMSetBlendState(bsAlphaToCoverage, Vector4(0,0,0,0), 0xFFFFFFFF); if (gsGrassEnabled) gsGrass->draw(device, gameTime); deviceContext->Release(); }
void DeferredPipeline::Lighting::unset_blending(ID3D11DeviceContext & device_context) { device_context.OMSetBlendState(nullptr, 0, 0xffffffff); }
void DeferredPipeline::Lighting::set_additive_blending(ID3D11DeviceContext & device_context) { float blend_factor[] = {1.0f, 1.0f, 1.0f, 1.0f}; device_context.OMSetBlendState(_om_additive_blend, blend_factor, 0xffffffff); }
bool D11State::init() { HRESULT hr; ID3D11Texture2D* pBackBuffer = NULL; hr = pSwapChain->GetBuffer(0, __uuidof(*pBackBuffer), (LPVOID*)&pBackBuffer); if (FAILED(hr)) { ods("D3D11: pSwapChain->GetBuffer failure!"); return false; } hr = pDevice->CreateDeferredContext(0, &pDeviceContext); // Depending on the device settings a deferred context may not be createable // for example if it is a SINGLETHREADED device. // (See http://msdn.microsoft.com/en-us/library/windows/desktop/ff476505%28v=vs.85%29.aspx) // We handle the expected failure and failure fallback in the same way - // by trying to use an immediate context. if (FAILED(hr) || !pDeviceContext) { ods("D3D11: Failed to create DeferredContext (0x%x). Getting ImmediateContext", hr); pDevice->GetImmediateContext(&pDeviceContext); D11CreateStateBlock(pDeviceContext, &pOrigStateBlock); D11CreateStateBlock(pDeviceContext, &pMyStateBlock); pOrigStateBlock->Capture(); bDeferredContext = false; } else { bDeferredContext = true; } D3D11_TEXTURE2D_DESC backBufferSurfaceDesc; pBackBuffer->GetDesc(&backBufferSurfaceDesc); ZeroMemory(&vp, sizeof(vp)); vp.Width = static_cast<float>(backBufferSurfaceDesc.Width); vp.Height = static_cast<float>(backBufferSurfaceDesc.Height); vp.MinDepth = 0; vp.MaxDepth = 1; vp.TopLeftX = 0; vp.TopLeftY = 0; pDeviceContext->RSSetViewports(1, &vp); hr = pDevice->CreateRenderTargetView(pBackBuffer, NULL, &pRTV); if (FAILED(hr)) { ods("D3D11: pDevice->CreateRenderTargetView failed!"); return false; } pDeviceContext->OMSetRenderTargets(1, &pRTV, NULL); // Settings for an "over" operation. // https://en.wikipedia.org/w/index.php?title=Alpha_compositing&oldid=580659153#Description D3D11_BLEND_DESC blend; ZeroMemory(&blend, sizeof(blend)); blend.RenderTarget[0].BlendEnable = TRUE; blend.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE; blend.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; blend.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; blend.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE; blend.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA; blend.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; blend.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; pDevice->CreateBlendState(&blend, &pBlendState); if (FAILED(hr)) { ods("D3D11: pDevice->CreateBlendState failed!"); return false; } pDeviceContext->OMSetBlendState(pBlendState, NULL, 0xffffffff); hr = pDevice->CreateVertexShader(g_vertex_shader, sizeof(g_vertex_shader), NULL, &pVertexShader); if (FAILED(hr)) { ods("D3D11: Failed to create vertex shader."); return false; } hr = pDevice->CreatePixelShader(g_pixel_shader, sizeof(g_pixel_shader), NULL, &pPixelShader); if (FAILED(hr)) { ods("D3D11: Failed to create pixel shader."); return false; } pTexture = NULL; pSRView = NULL; // Define the input layout D3D11_INPUT_ELEMENT_DESC layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; hr = pDevice->CreateInputLayout(layout, ARRAY_NUM_ELEMENTS(layout), g_vertex_shader, sizeof(g_vertex_shader), &pVertexLayout); if (FAILED(hr)) { ods("D3D11: pDevice->CreateInputLayout failure!"); return false; } pDeviceContext->IASetInputLayout(pVertexLayout); D3D11_BUFFER_DESC bd; ZeroMemory(&bd, sizeof(bd)); bd.Usage = D3D11_USAGE_DYNAMIC; bd.ByteWidth = VERTEXBUFFER_SIZE; bd.BindFlags = D3D11_BIND_VERTEX_BUFFER; bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; bd.MiscFlags = 0; hr = pDevice->CreateBuffer(&bd, NULL, &pVertexBuffer); if (FAILED(hr)) { ods("D3D11: pDevice->CreateBuffer failure!"); return false; } DWORD indices[] = { 0,1,3, 1,2,3, }; ZeroMemory(&bd, sizeof(bd)); bd.Usage = D3D11_USAGE_IMMUTABLE; bd.ByteWidth = sizeof(DWORD) * 6; bd.BindFlags = D3D11_BIND_INDEX_BUFFER; bd.CPUAccessFlags = 0; bd.MiscFlags = 0; D3D11_SUBRESOURCE_DATA InitData; ZeroMemory(&InitData, sizeof(InitData)); InitData.pSysMem = indices; hr = pDevice->CreateBuffer(&bd, &InitData, &pIndexBuffer); if (FAILED(hr)) { ods("D3D11: pDevice->CreateBuffer failure!"); return false; } // Set index buffer pDeviceContext->IASetIndexBuffer(pIndexBuffer, DXGI_FORMAT_R32_UINT, 0); // Set primitive topology pDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); if (!bDeferredContext) { pMyStateBlock->Capture(); pOrigStateBlock->Apply(); } pBackBuffer->Release(); return true; }
void D3D11CanvasWindowGraphics::Render() { RECT clientRc; GetClientRect(m_hWnd, &clientRc); RectF clientRcf((float)clientRc.left, (float)clientRc.top, (float)clientRc.right, (float)clientRc.bottom); D2D1_RECT_F clientRectf = D2D1::RectF((FLOAT)clientRc.left, (FLOAT)clientRc.top, (FLOAT)clientRc.right, (FLOAT)clientRc.bottom); ID3D11DeviceContext* pContext = m_driver->GetD3D11Context(); // Clear to black static const float BG_COLOR[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; pContext->ClearRenderTargetView(m_backBufferRTV, BG_COLOR); // TODO: CLEAN UP THIS MESS!!! if (m_image) { // Set up rasterizer RECT clientRc; GetClientRect(m_hWnd, &clientRc); RectF clientRcf((float)clientRc.left, (float)clientRc.top, (float)clientRc.right, (float)clientRc.bottom); D3D11_VIEWPORT vp = CD3D11_VIEWPORT( clientRcf.left, clientRcf.top, clientRcf.right - clientRcf.left, clientRcf.bottom - clientRcf.top); pContext->RSSetViewports(1, &vp); // Set up output merger ID3D11RenderTargetView* rtv = m_backBufferRTV; pContext->OMSetRenderTargets(1, &rtv, NULL); pContext->OMSetBlendState(m_driver->GetOverBlend(), NULL, 0xFFFFFFFF); D3D11ImagePtr d3d11Image = std::static_pointer_cast<D3D11Image, DriverImage>( m_image->GetDriverImage()); ID3D11ShaderResourceView* srv = d3d11Image->GetSRV(); ID3D11SamplerState* ss = m_driver->GetBilinearSampler(); // Set up pixel shader pContext->PSSetShader(m_driver->GetTexturedPixelShader(), NULL, 0); pContext->PSSetShaderResources(0, 1, &srv); pContext->PSSetSamplers(0, 1, &ss); m_driver->RenderQuad(m_camera->GetCanvasToClip(clientRcf), m_image->GetCanvasRect()); srv = NULL; pContext->PSSetShaderResources(0, 1, &srv); } // Render something into Direct2D target ComPtr<ID2D1RenderTarget> pD2DTarget = m_d2dTarget->AcquireTarget(); pD2DTarget->BeginDraw(); // Clear to transparent black pD2DTarget->Clear(D2D1::ColorF(D2D1::ColorF::Black, 0.0f)); // Create brush for drawing stuff ID2D1SolidColorBrush* brush; pD2DTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Blue), &brush); Matrix3x2f canvasToViewport = m_camera->GetCanvasToViewport(clientRcf); // Draw the extensible image's tile structure const ExtensibleImage::TileMap& tiles = m_extensibleImage->GetTileMap(); for (ExtensibleImage::TileMap::const_iterator it = tiles.begin(); it != tiles.end(); ++it) { const RectF& canvasRect = it->second->GetCanvasRect(); ID2D1Factory* d2dFactory; pD2DTarget->GetFactory(&d2dFactory); ID2D1RectangleGeometry* rectGeom; d2dFactory->CreateRectangleGeometry( D2D1::RectF(canvasRect.left, canvasRect.top, canvasRect.right, canvasRect.bottom), &rectGeom); ID2D1TransformedGeometry* transGeom; d2dFactory->CreateTransformedGeometry(rectGeom, D2D1::Matrix3x2F(canvasToViewport.m11, canvasToViewport.m12, canvasToViewport.m21, canvasToViewport.m22, canvasToViewport.m31, canvasToViewport.m32), &transGeom); rectGeom->Release(); pD2DTarget->DrawGeometry(transGeom, brush); transGeom->Release(); d2dFactory->Release(); } // Draw some text RenderPrintf(pD2DTarget, m_textFormat, clientRectf, brush, L"Welcome to Paint Sandbox!"); brush->Release(); pD2DTarget->EndDraw(); m_d2dTarget->ReleaseTarget(); // Transfer Direct2D target to display //m_driver->RenderD2DTarget(m_d2dTarget); // Set up rasterizer D3D11_VIEWPORT vp = CD3D11_VIEWPORT( clientRcf.left, clientRcf.top, clientRcf.right - clientRcf.left, clientRcf.bottom - clientRcf.top); pContext->RSSetViewports(1, &vp); // Set up output merger ID3D11RenderTargetView* rtv = m_backBufferRTV; pContext->OMSetRenderTargets(1, &rtv, NULL); pContext->OMSetBlendState(m_driver->GetOverBlend(), NULL, 0xFFFFFFFF); ID3D11ShaderResourceView* srv = m_d2dTarget->AcquireSRV(); ID3D11SamplerState* ss = m_driver->GetBilinearSampler(); // Set up pixel shader pContext->PSSetShader(m_driver->GetTexturedPixelShader(), NULL, 0); pContext->PSSetShaderResources(0, 1, &srv); pContext->PSSetSamplers(0, 1, &ss); m_driver->RenderQuad(Matrix3x2f::IDENTITY, RectF(-1.0f, 1.0f, 1.0f, -1.0f)); srv = NULL; pContext->PSSetShaderResources(0, 1, &srv); m_d2dTarget->ReleaseSRV(); }
// Render function // (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop) void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data) { ID3D11DeviceContext* ctx = g_pd3dDeviceContext; // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { if (g_pVB) { g_pVB->Release(); g_pVB = NULL; } g_VertexBufferSize = draw_data->TotalVtxCount + 5000; D3D11_BUFFER_DESC desc; memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); desc.Usage = D3D11_USAGE_DYNAMIC; desc.ByteWidth = g_VertexBufferSize * sizeof(ImDrawVert); desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; desc.MiscFlags = 0; if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) return; } if (!g_pIB || g_IndexBufferSize < draw_data->TotalIdxCount) { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; D3D11_BUFFER_DESC desc; memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); desc.Usage = D3D11_USAGE_DYNAMIC; desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); desc.BindFlags = D3D11_BIND_INDEX_BUFFER; desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } // Copy and convert all vertices into a single contiguous buffer D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) return; if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) return; ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert)); memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx)); vtx_dst += cmd_list->VtxBuffer.Size; idx_dst += cmd_list->IdxBuffer.Size; } ctx->Unmap(g_pVB, 0); ctx->Unmap(g_pIB, 0); // Setup orthographic projection matrix into our constant buffer { D3D11_MAPPED_SUBRESOURCE mapped_resource; if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; float L = 0.0f; float R = ImGui::GetIO().DisplaySize.x; float B = ImGui::GetIO().DisplaySize.y; float T = 0.0f; float mvp[4][4] = { { 2.0f/(R-L), 0.0f, 0.0f, 0.0f }, { 0.0f, 2.0f/(T-B), 0.0f, 0.0f }, { 0.0f, 0.0f, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); ctx->Unmap(g_pVertexConstantBuffer, 0); } // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) struct BACKUP_DX11_STATE { UINT ScissorRectsCount, ViewportsCount; D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; ID3D11RasterizerState* RS; ID3D11BlendState* BlendState; FLOAT BlendFactor[4]; UINT SampleMask; UINT StencilRef; ID3D11DepthStencilState* DepthStencilState; ID3D11ShaderResourceView* PSShaderResource; ID3D11SamplerState* PSSampler; ID3D11PixelShader* PS; ID3D11VertexShader* VS; UINT PSInstancesCount, VSInstancesCount; ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; DXGI_FORMAT IndexBufferFormat; ID3D11InputLayout* InputLayout; }; BACKUP_DX11_STATE old; old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); ctx->RSGetState(&old.RS); ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); ctx->OMGetDepthStencilState(&old.DepthStencilState, &old.StencilRef); ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); ctx->PSGetSamplers(0, 1, &old.PSSampler); old.PSInstancesCount = old.VSInstancesCount = 256; ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); ctx->IAGetInputLayout(&old.InputLayout); // Setup viewport D3D11_VIEWPORT vp; memset(&vp, 0, sizeof(D3D11_VIEWPORT)); vp.Width = ImGui::GetIO().DisplaySize.x; vp.Height = ImGui::GetIO().DisplaySize.y; vp.MinDepth = 0.0f; vp.MaxDepth = 1.0f; vp.TopLeftX = vp.TopLeftY = 0.0f; ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; ctx->IASetInputLayout(g_pInputLayout); ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); ctx->VSSetShader(g_pVertexShader, NULL, 0); ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); ctx->PSSetShader(g_pPixelShader, NULL, 0); ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); ctx->OMSetDepthStencilState(g_pDepthStencilState, 0); ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; int idx_offset = 0; for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) { const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; if (pcmd->UserCallback) { pcmd->UserCallback(cmd_list, pcmd); } else { const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); ctx->RSSetScissorRects(1, &r); ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.Size; } // Restore modified DX state ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); ctx->RSSetViewports(old.ViewportsCount, old.Viewports); ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); ctx->OMSetDepthStencilState(old.DepthStencilState, old.StencilRef); if (old.DepthStencilState) old.DepthStencilState->Release(); ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); ctx->IASetPrimitiveTopology(old.PrimitiveTopology); ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); }
// Render function // (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop) void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data) { // Avoid rendering when minimized if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f) return; ID3D11DeviceContext* ctx = g_pd3dDeviceContext; // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { if (g_pVB) { g_pVB->Release(); g_pVB = NULL; } g_VertexBufferSize = draw_data->TotalVtxCount + 5000; D3D11_BUFFER_DESC desc; memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); desc.Usage = D3D11_USAGE_DYNAMIC; desc.ByteWidth = g_VertexBufferSize * sizeof(ImDrawVert); desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; desc.MiscFlags = 0; if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) return; } if (!g_pIB || g_IndexBufferSize < draw_data->TotalIdxCount) { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; D3D11_BUFFER_DESC desc; memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); desc.Usage = D3D11_USAGE_DYNAMIC; desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); desc.BindFlags = D3D11_BIND_INDEX_BUFFER; desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } // Upload vertex/index data into a single contiguous GPU buffer D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) return; if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) return; ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert)); memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx)); vtx_dst += cmd_list->VtxBuffer.Size; idx_dst += cmd_list->IdxBuffer.Size; } ctx->Unmap(g_pVB, 0); ctx->Unmap(g_pIB, 0); // Setup orthographic projection matrix into our constant buffer // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). { D3D11_MAPPED_SUBRESOURCE mapped_resource; if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; float L = draw_data->DisplayPos.x; float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x; float T = draw_data->DisplayPos.y; float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y; float mvp[4][4] = { { 2.0f/(R-L), 0.0f, 0.0f, 0.0f }, { 0.0f, 2.0f/(T-B), 0.0f, 0.0f }, { 0.0f, 0.0f, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); ctx->Unmap(g_pVertexConstantBuffer, 0); } // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) struct BACKUP_DX11_STATE { UINT ScissorRectsCount, ViewportsCount; D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; ID3D11RasterizerState* RS; ID3D11BlendState* BlendState; FLOAT BlendFactor[4]; UINT SampleMask; UINT StencilRef; ID3D11DepthStencilState* DepthStencilState; ID3D11ShaderResourceView* PSShaderResource; ID3D11SamplerState* PSSampler; ID3D11PixelShader* PS; ID3D11VertexShader* VS; UINT PSInstancesCount, VSInstancesCount; ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; DXGI_FORMAT IndexBufferFormat; ID3D11InputLayout* InputLayout; }; BACKUP_DX11_STATE old; old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); ctx->RSGetState(&old.RS); ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); ctx->OMGetDepthStencilState(&old.DepthStencilState, &old.StencilRef); ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); ctx->PSGetSamplers(0, 1, &old.PSSampler); old.PSInstancesCount = old.VSInstancesCount = 256; ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); ctx->IAGetInputLayout(&old.InputLayout); // Setup desired DX state ImGui_ImplDX11_SetupRenderState(draw_data, ctx); // Render command lists // (Because we merged all buffers into a single one, we maintain our own offset into them) int global_idx_offset = 0; int global_vtx_offset = 0; ImVec2 clip_off = draw_data->DisplayPos; for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) { const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; if (pcmd->UserCallback != NULL) { // User callback, registered via ImDrawList::AddCallback() // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.) if (pcmd->UserCallback == ImDrawCallback_ResetRenderState) ImGui_ImplDX11_SetupRenderState(draw_data, ctx); else pcmd->UserCallback(cmd_list, pcmd); } else { // Apply scissor/clipping rectangle const D3D11_RECT r = { (LONG)(pcmd->ClipRect.x - clip_off.x), (LONG)(pcmd->ClipRect.y - clip_off.y), (LONG)(pcmd->ClipRect.z - clip_off.x), (LONG)(pcmd->ClipRect.w - clip_off.y) }; ctx->RSSetScissorRects(1, &r); // Bind texture, Draw ID3D11ShaderResourceView* texture_srv = (ID3D11ShaderResourceView*)pcmd->TextureId; ctx->PSSetShaderResources(0, 1, &texture_srv); ctx->DrawIndexed(pcmd->ElemCount, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset); } } global_idx_offset += cmd_list->IdxBuffer.Size; global_vtx_offset += cmd_list->VtxBuffer.Size; } // Restore modified DX state ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); ctx->RSSetViewports(old.ViewportsCount, old.Viewports); ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); ctx->OMSetDepthStencilState(old.DepthStencilState, old.StencilRef); if (old.DepthStencilState) old.DepthStencilState->Release(); ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); ctx->IASetPrimitiveTopology(old.PrimitiveTopology); ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); }
EGLint SwapChain11::copyOffscreenToBackbuffer(EGLint x, EGLint y, EGLint width, EGLint height) { if (!mSwapChain) { return EGL_SUCCESS; } initPassThroughResources(); ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); // Set vertices D3D11_MAPPED_SUBRESOURCE mappedResource; HRESULT result = deviceContext->Map(mQuadVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); if (FAILED(result)) { return EGL_BAD_ACCESS; } d3d11::PositionTexCoordVertex *vertices = static_cast<d3d11::PositionTexCoordVertex*>(mappedResource.pData); // Create a quad in homogeneous coordinates float x1 = (x / float(mWidth)) * 2.0f - 1.0f; float y1 = (y / float(mHeight)) * 2.0f - 1.0f; float x2 = ((x + width) / float(mWidth)) * 2.0f - 1.0f; float y2 = ((y + height) / float(mHeight)) * 2.0f - 1.0f; float u1 = x / float(mWidth); float v1 = y / float(mHeight); float u2 = (x + width) / float(mWidth); float v2 = (y + height) / float(mHeight); // Invert the quad vertices depending on the surface orientation. if ((mOrientation & EGL_SURFACE_ORIENTATION_INVERT_X_ANGLE) != 0) { std::swap(x1, x2); } if ((mOrientation & EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE) != 0) { std::swap(y1, y2); } d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v1); d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v2); d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v1); d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v2); deviceContext->Unmap(mQuadVB, 0); static UINT stride = sizeof(d3d11::PositionTexCoordVertex); static UINT startIdx = 0; deviceContext->IASetVertexBuffers(0, 1, &mQuadVB, &stride, &startIdx); // Apply state deviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF); static const float blendFactor[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; deviceContext->OMSetBlendState(NULL, blendFactor, 0xFFFFFFF); deviceContext->RSSetState(mPassThroughRS); // Apply shaders deviceContext->IASetInputLayout(mPassThroughIL); deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); deviceContext->VSSetShader(mPassThroughVS, NULL, 0); deviceContext->PSSetShader(mPassThroughPS, NULL, 0); deviceContext->GSSetShader(NULL, NULL, 0); auto stateManager = mRenderer->getStateManager(); // Apply render targets stateManager->setOneTimeRenderTarget(mBackBufferRTView, nullptr); // Set the viewport D3D11_VIEWPORT viewport; viewport.TopLeftX = 0; viewport.TopLeftY = 0; viewport.Width = static_cast<FLOAT>(mWidth); viewport.Height = static_cast<FLOAT>(mHeight); viewport.MinDepth = 0.0f; viewport.MaxDepth = 1.0f; deviceContext->RSSetViewports(1, &viewport); // Apply textures stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, mOffscreenSRView); deviceContext->PSSetSamplers(0, 1, &mPassThroughSampler); // Draw deviceContext->Draw(4, 0); // Rendering to the swapchain is now complete. Now we can call Present(). // Before that, we perform any cleanup on the D3D device. We do this before Present() to make sure the // cleanup is caught under the current eglSwapBuffers() PIX/Graphics Diagnostics call rather than the next one. stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL); mRenderer->markAllStateDirty(); return EGL_SUCCESS; }
gl::Error PixelTransfer11::copyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget, GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea) { ANGLE_TRY(loadResources()); gl::Extents destSize = destRenderTarget->getExtents(); ASSERT(destArea.x >= 0 && destArea.x + destArea.width <= destSize.width && destArea.y >= 0 && destArea.y + destArea.height <= destSize.height && destArea.z >= 0 && destArea.z + destArea.depth <= destSize.depth ); const gl::Buffer &sourceBuffer = *unpack.pixelBuffer.get(); ASSERT(mRenderer->supportsFastCopyBufferToTexture(destinationFormat)); ID3D11PixelShader *pixelShader = findBufferToTexturePS(destinationFormat); ASSERT(pixelShader); // The SRV must be in the proper read format, which may be different from the destination format // EG: for half float data, we can load full precision floats with implicit conversion GLenum unsizedFormat = gl::GetInternalFormatInfo(destinationFormat).format; GLenum sourceFormat = gl::GetSizedInternalFormat(unsizedFormat, sourcePixelsType); const d3d11::Format &sourceFormatInfo = d3d11::Format::Get(sourceFormat, mRenderer->getRenderer11DeviceCaps()); DXGI_FORMAT srvFormat = sourceFormatInfo.srvFormat; ASSERT(srvFormat != DXGI_FORMAT_UNKNOWN); Buffer11 *bufferStorage11 = GetAs<Buffer11>(sourceBuffer.getImplementation()); ID3D11ShaderResourceView *bufferSRV = nullptr; ANGLE_TRY_RESULT(bufferStorage11->getSRV(srvFormat), bufferSRV); ASSERT(bufferSRV != nullptr); ID3D11RenderTargetView *textureRTV = GetAs<RenderTarget11>(destRenderTarget)->getRenderTargetView(); ASSERT(textureRTV != nullptr); CopyShaderParams shaderParams; setBufferToTextureCopyParams(destArea, destSize, sourceFormat, unpack, offset, &shaderParams); ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); ID3D11Buffer *nullBuffer = nullptr; UINT zero = 0; // Are we doing a 2D or 3D copy? ID3D11GeometryShader *geometryShader = ((destSize.depth > 1) ? mBufferToTextureGS : NULL); auto stateManager = mRenderer->getStateManager(); deviceContext->VSSetShader(mBufferToTextureVS, NULL, 0); deviceContext->GSSetShader(geometryShader, NULL, 0); deviceContext->PSSetShader(pixelShader, NULL, 0); stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, bufferSRV); deviceContext->IASetInputLayout(NULL); deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero); deviceContext->OMSetBlendState(NULL, NULL, 0xFFFFFFF); deviceContext->OMSetDepthStencilState(mCopyDepthStencilState, 0xFFFFFFFF); deviceContext->RSSetState(mCopyRasterizerState); stateManager->setOneTimeRenderTarget(textureRTV, nullptr); if (!StructEquals(mParamsData, shaderParams)) { d3d11::SetBufferData(deviceContext, mParamsConstantBuffer, shaderParams); mParamsData = shaderParams; } deviceContext->VSSetConstantBuffers(0, 1, &mParamsConstantBuffer); // Set the viewport D3D11_VIEWPORT viewport; viewport.TopLeftX = 0; viewport.TopLeftY = 0; viewport.Width = static_cast<FLOAT>(destSize.width); viewport.Height = static_cast<FLOAT>(destSize.height); viewport.MinDepth = 0.0f; viewport.MaxDepth = 1.0f; deviceContext->RSSetViewports(1, &viewport); UINT numPixels = (destArea.width * destArea.height * destArea.depth); deviceContext->Draw(numPixels, 0); // Unbind textures and render targets and vertex buffer stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL); deviceContext->VSSetConstantBuffers(0, 1, &nullBuffer); mRenderer->markAllStateDirty(); return gl::NoError(); }
void DrawCoordinate() { struct CB { XMMATRIX mWorldViewProj; }; ID3D11Device* pDevice = WE::D3DDevice(); ID3D11DeviceContext* pImmediateContext = WE::ImmediateContext(); static ID3D11VertexShader* g_pVertexShader = NULL; static ID3D11PixelShader* g_pPixelShader = NULL; static ID3D11Buffer* g_pCB = NULL; static const char* g_strBuffer = " cbuffer cbPerObject : register( b0 ) \r\n" " { \r\n" " matrix g_mWorldViewProjection : packoffset( c0 ); \r\n" " }; \r\n" " \r\n" " struct VS_In \r\n" " { \r\n" " uint id : SV_VERTEXID; \r\n" " }; \r\n" " \r\n" " struct VS_Out \r\n" " { \r\n" " float4 pos : SV_POSITION; \r\n" " float4 color : COLOR; \r\n" " }; \r\n" " \r\n" " \r\n" " cbuffer cbImmutable \r\n" " { \r\n" " static float4 g_positions[6] = \r\n" " { \r\n" " float4( 0.0f, 0.0f, 0.0f, 1.0f ), \r\n" " float4( 1.0f, 0.0f, 0.0f, 1.0f ), \r\n" " float4( 0.0f, 0.0f, 0.0f, 1.0f ), \r\n" " float4( 0.0f, 1.0f, 0.0f, 1.0f ), \r\n" " float4( 0.0f, 0.0f, 0.0f, 1.0f ), \r\n" " float4( 0.0f, 0.0f, 1.0f, 1.0f ), \r\n" " }; \r\n" " \r\n" " static float4 g_colors[6] = \r\n" " { \r\n" " float4( 1.0f, 0.0f, 0.0f, 1.0f ), \r\n" " float4( 1.0f, 0.0f, 0.0f, 1.0f ), \r\n" " float4( 0.0f, 1.0f, 0.0f, 1.0f ), \r\n" " float4( 0.0f, 1.0f, 0.0f, 1.0f ), \r\n" " float4( 0.0f, 0.0f, 1.0f, 1.0f ), \r\n" " float4( 0.0f, 0.0f, 1.0f, 1.0f ), \r\n" " }; \r\n" " }; \r\n" " VS_Out VSMain(VS_In input) \r\n" " { \r\n" " VS_Out output; \r\n" " \r\n" " output.pos = mul( g_positions[input.id] * 5, g_mWorldViewProjection ); \r\n" " output.color = g_colors[input.id]; \r\n" " return output; \r\n" " } \r\n" " \r\n" " float4 PSMain(VS_Out input) : SV_Target \r\n" " { \r\n" " return input.color; \r\n" " return float4( 1.0f, 1.0f, 0.0f, 1.0f ); \r\n" " } \r\n" ""; HRESULT hr; if ( g_pVertexShader == NULL ) { // Create shaders ID3DBlob* pVSBlob = NULL; ID3DBlob* pPSBlob = NULL; UINT dwBufferSize = ( UINT )strlen( g_strBuffer ) + 1; V( WE::CompileShaderFromMemory( g_strBuffer, dwBufferSize, NULL, "VSMain", "vs_5_0", &pVSBlob ) ); V( WE::CompileShaderFromMemory( g_strBuffer, dwBufferSize, NULL, "PSMain", "ps_5_0", &pPSBlob ) ); V( pDevice->CreateVertexShader( pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), NULL, &g_pVertexShader ) ); V( pDevice->CreatePixelShader( pPSBlob->GetBufferPointer(), pPSBlob->GetBufferSize(), NULL, &g_pPixelShader ) ); SAFE_RELEASE( pVSBlob ); SAFE_RELEASE( pPSBlob ); // Create the constant buffers D3D11_BUFFER_DESC Desc; Desc.Usage = D3D11_USAGE_DYNAMIC; Desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; Desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; Desc.MiscFlags = 0; Desc.ByteWidth = sizeof( CB ); V( pDevice->CreateBuffer( &Desc, NULL, &g_pCB ) ); } D3D11_MAPPED_SUBRESOURCE MappedResource; V(pImmediateContext->Map( g_pCB, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ) ); CB* pPerFrame = ( CB* )MappedResource.pData; pPerFrame->mWorldViewProj = XMMatrixTranspose( WE::Camera()->GetViewProjMtx() ); pImmediateContext->Unmap( g_pCB, 0 ); pImmediateContext->VSSetConstantBuffers( 0, 1, &g_pCB ); pImmediateContext->OMSetDepthStencilState( NULL, 0 ); float vBlendFactor[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; pImmediateContext->OMSetBlendState( NULL, vBlendFactor, 0xFFFFFFFF ); pImmediateContext->RSSetState( NULL ); pImmediateContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_LINELIST ); pImmediateContext->VSSetShader( g_pVertexShader, NULL, 0 ); pImmediateContext->PSSetShader( g_pPixelShader, NULL, 0 ); pImmediateContext->GSSetShader( NULL, NULL, 0 ); // Draw pImmediateContext->Draw( 6, 0 ); }