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
}
Exemple #6
0
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();
    }
}
Exemple #7
0
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;
}
Exemple #10
0
// 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, &params);
    }
    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);
}
Exemple #16
0
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();
}
Exemple #19
0
// 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();
}
Exemple #22
0
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 );
}