Edit

kc3-lang/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp

Branch :

  • Show log

    Commit

  • Author : Tobin Ehlis
    Date : 2020-08-26 11:27:13
    Hash : d7276586
    Message : Vulkan:Use roundUpPow2 where possible Utility function roundUpPow2 is more optimal than roundUp so use it. Bug: b/166462979 Change-Id: I616fa9f487b818137b1b496d93e292c3bd1f428c Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2377119 Reviewed-by: Courtney Goeltzenleuchter <courtneygo@google.com> Reviewed-by: Cody Northrop <cnorthrop@google.com> Commit-Queue: Tobin Ehlis <tobine@google.com>

  • src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp
  • //
    // Copyright 2013 The ANGLE Project Authors. All rights reserved.
    // Use of this source code is governed by a BSD-style license that can be
    // found in the LICENSE file.
    //
    
    // PixelTransfer11.cpp:
    //   Implementation for buffer-to-texture and texture-to-buffer copies.
    //   Used to implement pixel transfers from unpack and to pack buffers.
    //
    
    #include "libANGLE/renderer/d3d/d3d11/PixelTransfer11.h"
    
    #include "libANGLE/Buffer.h"
    #include "libANGLE/Context.h"
    #include "libANGLE/Texture.h"
    #include "libANGLE/formatutils.h"
    #include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
    #include "libANGLE/renderer/d3d/d3d11/Context11.h"
    #include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
    #include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
    #include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h"
    #include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
    #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
    #include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
    #include "libANGLE/renderer/serial_utils.h"
    
    // Precompiled shaders
    #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_gs.h"
    #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4f.h"
    #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4i.h"
    #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4ui.h"
    #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_vs.h"
    
    namespace rx
    {
    
    PixelTransfer11::PixelTransfer11(Renderer11 *renderer)
        : mRenderer(renderer),
          mResourcesLoaded(false),
          mBufferToTextureVS(),
          mBufferToTextureGS(),
          mParamsConstantBuffer(),
          mCopyRasterizerState(),
          mCopyDepthStencilState()
    {}
    
    PixelTransfer11::~PixelTransfer11() {}
    
    angle::Result PixelTransfer11::loadResources(const gl::Context *context)
    {
        if (mResourcesLoaded)
        {
            return angle::Result::Continue;
        }
    
        D3D11_RASTERIZER_DESC rasterDesc;
        rasterDesc.FillMode              = D3D11_FILL_SOLID;
        rasterDesc.CullMode              = D3D11_CULL_NONE;
        rasterDesc.FrontCounterClockwise = FALSE;
        rasterDesc.DepthBias             = 0;
        rasterDesc.SlopeScaledDepthBias  = 0.0f;
        rasterDesc.DepthBiasClamp        = 0.0f;
        rasterDesc.DepthClipEnable       = TRUE;
        rasterDesc.ScissorEnable         = FALSE;
        rasterDesc.MultisampleEnable     = FALSE;
        rasterDesc.AntialiasedLineEnable = FALSE;
    
        Context11 *context11 = GetImplAs<Context11>(context);
    
        ANGLE_TRY(mRenderer->allocateResource(context11, rasterDesc, &mCopyRasterizerState));
    
        D3D11_DEPTH_STENCIL_DESC depthStencilDesc;
        depthStencilDesc.DepthEnable                  = true;
        depthStencilDesc.DepthWriteMask               = D3D11_DEPTH_WRITE_MASK_ALL;
        depthStencilDesc.DepthFunc                    = D3D11_COMPARISON_ALWAYS;
        depthStencilDesc.StencilEnable                = FALSE;
        depthStencilDesc.StencilReadMask              = D3D11_DEFAULT_STENCIL_READ_MASK;
        depthStencilDesc.StencilWriteMask             = D3D11_DEFAULT_STENCIL_WRITE_MASK;
        depthStencilDesc.FrontFace.StencilFailOp      = D3D11_STENCIL_OP_KEEP;
        depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
        depthStencilDesc.FrontFace.StencilPassOp      = D3D11_STENCIL_OP_KEEP;
        depthStencilDesc.FrontFace.StencilFunc        = D3D11_COMPARISON_ALWAYS;
        depthStencilDesc.BackFace.StencilFailOp       = D3D11_STENCIL_OP_KEEP;
        depthStencilDesc.BackFace.StencilDepthFailOp  = D3D11_STENCIL_OP_KEEP;
        depthStencilDesc.BackFace.StencilPassOp       = D3D11_STENCIL_OP_KEEP;
        depthStencilDesc.BackFace.StencilFunc         = D3D11_COMPARISON_ALWAYS;
    
        ANGLE_TRY(mRenderer->allocateResource(context11, depthStencilDesc, &mCopyDepthStencilState));
    
        D3D11_BUFFER_DESC constantBufferDesc   = {};
        constantBufferDesc.ByteWidth           = roundUpPow2<UINT>(sizeof(CopyShaderParams), 32u);
        constantBufferDesc.Usage               = D3D11_USAGE_DYNAMIC;
        constantBufferDesc.BindFlags           = D3D11_BIND_CONSTANT_BUFFER;
        constantBufferDesc.CPUAccessFlags      = D3D11_CPU_ACCESS_WRITE;
        constantBufferDesc.MiscFlags           = 0;
        constantBufferDesc.StructureByteStride = 0;
    
        ANGLE_TRY(mRenderer->allocateResource(context11, constantBufferDesc, &mParamsConstantBuffer));
        mParamsConstantBuffer.setDebugName("PixelTransfer11 constant buffer");
    
        // init shaders
        ANGLE_TRY(mRenderer->allocateResource(context11, ShaderData(g_VS_BufferToTexture),
                                              &mBufferToTextureVS));
        mBufferToTextureVS.setDebugName("BufferToTexture VS");
    
        ANGLE_TRY(mRenderer->allocateResource(context11, ShaderData(g_GS_BufferToTexture),
                                              &mBufferToTextureGS));
        mBufferToTextureGS.setDebugName("BufferToTexture GS");
    
        ANGLE_TRY(buildShaderMap(context));
    
        StructZero(&mParamsData);
    
        mResourcesLoaded = true;
    
        return angle::Result::Continue;
    }
    
    void PixelTransfer11::setBufferToTextureCopyParams(const gl::Box &destArea,
                                                       const gl::Extents &destSize,
                                                       GLenum internalFormat,
                                                       const gl::PixelUnpackState &unpack,
                                                       unsigned int offset,
                                                       CopyShaderParams *parametersOut)
    {
        StructZero(parametersOut);
    
        float texelCenterX = 0.5f / static_cast<float>(destSize.width);
        float texelCenterY = 0.5f / static_cast<float>(destSize.height);
    
        unsigned int bytesPerPixel  = gl::GetSizedInternalFormatInfo(internalFormat).pixelBytes;
        unsigned int alignmentBytes = static_cast<unsigned int>(unpack.alignment);
        unsigned int alignmentPixels =
            (alignmentBytes <= bytesPerPixel ? 1 : alignmentBytes / bytesPerPixel);
    
        parametersOut->FirstPixelOffset = offset / bytesPerPixel;
        parametersOut->PixelsPerRow =
            static_cast<unsigned int>((unpack.rowLength > 0) ? unpack.rowLength : destArea.width);
        parametersOut->RowStride    = roundUp(parametersOut->PixelsPerRow, alignmentPixels);
        parametersOut->RowsPerSlice = static_cast<unsigned int>(destArea.height);
        parametersOut->PositionOffset[0] =
            texelCenterX + (destArea.x / float(destSize.width)) * 2.0f - 1.0f;
        parametersOut->PositionOffset[1] =
            texelCenterY + ((destSize.height - destArea.y - 1) / float(destSize.height)) * 2.0f - 1.0f;
        parametersOut->PositionScale[0] = 2.0f / static_cast<float>(destSize.width);
        parametersOut->PositionScale[1] = -2.0f / static_cast<float>(destSize.height);
        parametersOut->FirstSlice       = destArea.z;
    }
    
    angle::Result PixelTransfer11::copyBufferToTexture(const gl::Context *context,
                                                       const gl::PixelUnpackState &unpack,
                                                       gl::Buffer *unpackBuffer,
                                                       unsigned int offset,
                                                       RenderTargetD3D *destRenderTarget,
                                                       GLenum destinationFormat,
                                                       GLenum sourcePixelsType,
                                                       const gl::Box &destArea)
    {
        ASSERT(unpackBuffer);
    
        ANGLE_TRY(loadResources(context));
    
        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);
    
        ASSERT(mRenderer->supportsFastCopyBufferToTexture(destinationFormat));
    
        const d3d11::PixelShader *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::GetUnsizedFormat(destinationFormat);
        const gl::InternalFormat &sourceglFormatInfo =
            gl::GetInternalFormatInfo(unsizedFormat, sourcePixelsType);
    
        const d3d11::Format &sourceFormatInfo = d3d11::Format::Get(
            sourceglFormatInfo.sizedInternalFormat, mRenderer->getRenderer11DeviceCaps());
        DXGI_FORMAT srvFormat = sourceFormatInfo.srvFormat;
        ASSERT(srvFormat != DXGI_FORMAT_UNKNOWN);
        Buffer11 *bufferStorage11                  = GetAs<Buffer11>(unpackBuffer->getImplementation());
        const d3d11::ShaderResourceView *bufferSRV = nullptr;
        ANGLE_TRY(bufferStorage11->getSRV(context, srvFormat, &bufferSRV));
        ASSERT(bufferSRV != nullptr);
    
        const d3d11::RenderTargetView &textureRTV =
            GetAs<RenderTarget11>(destRenderTarget)->getRenderTargetView();
        ASSERT(textureRTV.valid());
    
        CopyShaderParams shaderParams;
        setBufferToTextureCopyParams(destArea, destSize, sourceglFormatInfo.sizedInternalFormat, unpack,
                                     offset, &shaderParams);
    
        ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
    
        // Are we doing a 2D or 3D copy?
        const auto *geometryShader   = ((destSize.depth > 1) ? &mBufferToTextureGS : nullptr);
        StateManager11 *stateManager = mRenderer->getStateManager();
    
        stateManager->setDrawShaders(&mBufferToTextureVS, geometryShader, pixelShader);
        stateManager->setShaderResource(gl::ShaderType::Fragment, 0, bufferSRV);
        stateManager->setInputLayout(nullptr);
        stateManager->setPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
    
        stateManager->setSingleVertexBuffer(nullptr, 0, 0);
        stateManager->setSimpleBlendState(nullptr);
        stateManager->setDepthStencilState(&mCopyDepthStencilState, 0xFFFFFFFF);
        stateManager->setRasterizerState(&mCopyRasterizerState);
    
        stateManager->setRenderTarget(textureRTV.get(), nullptr);
    
        if (!StructEquals(mParamsData, shaderParams))
        {
            d3d11::SetBufferData(deviceContext, mParamsConstantBuffer.get(), shaderParams);
            mParamsData = shaderParams;
        }
    
        stateManager->setVertexConstantBuffer(0, &mParamsConstantBuffer);
    
        // Set the viewport
        stateManager->setSimpleViewport(destSize);
    
        UINT numPixels = (destArea.width * destArea.height * destArea.depth);
        deviceContext->Draw(numPixels, 0);
    
        return angle::Result::Continue;
    }
    
    angle::Result PixelTransfer11::buildShaderMap(const gl::Context *context)
    {
        d3d11::PixelShader bufferToTextureFloat;
        d3d11::PixelShader bufferToTextureInt;
        d3d11::PixelShader bufferToTextureUint;
    
        Context11 *context11 = GetImplAs<Context11>(context);
    
        ANGLE_TRY(mRenderer->allocateResource(context11, ShaderData(g_PS_BufferToTexture_4F),
                                              &bufferToTextureFloat));
        ANGLE_TRY(mRenderer->allocateResource(context11, ShaderData(g_PS_BufferToTexture_4I),
                                              &bufferToTextureInt));
        ANGLE_TRY(mRenderer->allocateResource(context11, ShaderData(g_PS_BufferToTexture_4UI),
                                              &bufferToTextureUint));
    
        bufferToTextureFloat.setDebugName("BufferToTexture RGBA ps");
        bufferToTextureInt.setDebugName("BufferToTexture RGBA-I ps");
        bufferToTextureUint.setDebugName("BufferToTexture RGBA-UI ps");
    
        mBufferToTexturePSMap[GL_FLOAT]        = std::move(bufferToTextureFloat);
        mBufferToTexturePSMap[GL_INT]          = std::move(bufferToTextureInt);
        mBufferToTexturePSMap[GL_UNSIGNED_INT] = std::move(bufferToTextureUint);
    
        return angle::Result::Continue;
    }
    
    const d3d11::PixelShader *PixelTransfer11::findBufferToTexturePS(GLenum internalFormat) const
    {
        GLenum componentType = gl::GetSizedInternalFormatInfo(internalFormat).componentType;
        if (componentType == GL_SIGNED_NORMALIZED || componentType == GL_UNSIGNED_NORMALIZED)
        {
            componentType = GL_FLOAT;
        }
    
        auto shaderMapIt = mBufferToTexturePSMap.find(componentType);
        return (shaderMapIt == mBufferToTexturePSMap.end() ? nullptr : &shaderMapIt->second);
    }
    
    }  // namespace rx