Home | History | Annotate | Download | only in d3d11
      1 #include "precompiled.h"
      2 //
      3 // Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
      4 // Use of this source code is governed by a BSD-style license that can be
      5 // found in the LICENSE file.
      6 //
      7 
      8 // PixelTransfer11.cpp:
      9 //   Implementation for buffer-to-texture and texture-to-buffer copies.
     10 //   Used to implement pixel transfers from unpack and to pack buffers.
     11 //
     12 
     13 #include "libGLESv2/renderer/d3d11/PixelTransfer11.h"
     14 #include "libGLESv2/formatutils.h"
     15 #include "libGLESv2/Texture.h"
     16 #include "libGLESv2/Buffer.h"
     17 #include "libGLESv2/renderer/d3d11/Renderer11.h"
     18 #include "libGLESv2/renderer/d3d11/renderer11_utils.h"
     19 #include "libGLESv2/renderer/d3d11/formatutils11.h"
     20 #include "libGLESv2/renderer/d3d11/BufferStorage11.h"
     21 #include "libGLESv2/renderer/d3d11/TextureStorage11.h"
     22 #include "libGLESv2/renderer/d3d11/RenderTarget11.h"
     23 #include "libGLESv2/Context.h"
     24 
     25 // Precompiled shaders
     26 #include "libGLESv2/renderer/d3d11/shaders/compiled/buffertotexture11_vs.h"
     27 #include "libGLESv2/renderer/d3d11/shaders/compiled/buffertotexture11_gs.h"
     28 #include "libGLESv2/renderer/d3d11/shaders/compiled/buffertotexture11_ps_4f.h"
     29 #include "libGLESv2/renderer/d3d11/shaders/compiled/buffertotexture11_ps_4i.h"
     30 #include "libGLESv2/renderer/d3d11/shaders/compiled/buffertotexture11_ps_4ui.h"
     31 
     32 namespace rx
     33 {
     34 
     35 PixelTransfer11::PixelTransfer11(Renderer11 *renderer)
     36     : mRenderer(renderer),
     37       mBufferToTextureVS(NULL),
     38       mBufferToTextureGS(NULL),
     39       mParamsConstantBuffer(NULL),
     40       mCopyRasterizerState(NULL),
     41       mCopyDepthStencilState(NULL)
     42 {
     43     HRESULT result = S_OK;
     44     ID3D11Device *device = mRenderer->getDevice();
     45 
     46     D3D11_RASTERIZER_DESC rasterDesc;
     47     rasterDesc.FillMode = D3D11_FILL_SOLID;
     48     rasterDesc.CullMode = D3D11_CULL_NONE;
     49     rasterDesc.FrontCounterClockwise = FALSE;
     50     rasterDesc.DepthBias = 0;
     51     rasterDesc.SlopeScaledDepthBias = 0.0f;
     52     rasterDesc.DepthBiasClamp = 0.0f;
     53     rasterDesc.DepthClipEnable = TRUE;
     54     rasterDesc.ScissorEnable = FALSE;
     55     rasterDesc.MultisampleEnable = FALSE;
     56     rasterDesc.AntialiasedLineEnable = FALSE;
     57 
     58     result = device->CreateRasterizerState(&rasterDesc, &mCopyRasterizerState);
     59     ASSERT(SUCCEEDED(result));
     60 
     61     D3D11_DEPTH_STENCIL_DESC depthStencilDesc;
     62     depthStencilDesc.DepthEnable = true;
     63     depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
     64     depthStencilDesc.DepthFunc = D3D11_COMPARISON_ALWAYS;
     65     depthStencilDesc.StencilEnable = FALSE;
     66     depthStencilDesc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK;
     67     depthStencilDesc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK;
     68     depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
     69     depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
     70     depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
     71     depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
     72     depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
     73     depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
     74     depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
     75     depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
     76 
     77     result = device->CreateDepthStencilState(&depthStencilDesc, &mCopyDepthStencilState);
     78     ASSERT(SUCCEEDED(result));
     79 
     80     D3D11_BUFFER_DESC constantBufferDesc = { 0 };
     81     constantBufferDesc.ByteWidth = rx::roundUp<UINT>(sizeof(CopyShaderParams), 32u);
     82     constantBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
     83     constantBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
     84     constantBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
     85     constantBufferDesc.MiscFlags = 0;
     86     constantBufferDesc.StructureByteStride = 0;
     87 
     88     result = device->CreateBuffer(&constantBufferDesc, NULL, &mParamsConstantBuffer);
     89     ASSERT(SUCCEEDED(result));
     90     d3d11::SetDebugName(mParamsConstantBuffer, "PixelTransfer11 constant buffer");
     91 
     92     // init shaders
     93     mBufferToTextureVS = d3d11::CompileVS(device, g_VS_BufferToTexture, "BufferToTexture VS");
     94     mBufferToTextureGS = d3d11::CompileGS(device, g_GS_BufferToTexture, "BufferToTexture GS");
     95 
     96     buildShaderMap();
     97 
     98     StructZero(&mParamsData);
     99 }
    100 
    101 PixelTransfer11::~PixelTransfer11()
    102 {
    103     for (auto shaderMapIt = mBufferToTexturePSMap.begin(); shaderMapIt != mBufferToTexturePSMap.end(); shaderMapIt++)
    104     {
    105         SafeRelease(shaderMapIt->second);
    106     }
    107 
    108     mBufferToTexturePSMap.clear();
    109 
    110     SafeRelease(mBufferToTextureVS);
    111     SafeRelease(mBufferToTextureGS);
    112     SafeRelease(mParamsConstantBuffer);
    113     SafeRelease(mCopyRasterizerState);
    114     SafeRelease(mCopyDepthStencilState);
    115 }
    116 
    117 void PixelTransfer11::setBufferToTextureCopyParams(const gl::Box &destArea, const gl::Extents &destSize, GLenum internalFormat,
    118                                                    const gl::PixelUnpackState &unpack, unsigned int offset, CopyShaderParams *parametersOut)
    119 {
    120     StructZero(parametersOut);
    121 
    122     float texelCenterX = 0.5f / static_cast<float>(destSize.width - 1);
    123     float texelCenterY = 0.5f / static_cast<float>(destSize.height - 1);
    124 
    125     unsigned int bytesPerPixel = gl::GetPixelBytes(internalFormat, 3);
    126     unsigned int alignmentBytes = static_cast<unsigned int>(unpack.alignment);
    127     unsigned int alignmentPixels = (alignmentBytes <= bytesPerPixel ? 1 : alignmentBytes / bytesPerPixel);
    128 
    129     parametersOut->FirstPixelOffset     = offset;
    130     parametersOut->PixelsPerRow         = static_cast<unsigned int>(destArea.width);
    131     parametersOut->RowStride            = roundUp(parametersOut->PixelsPerRow, alignmentPixels);
    132     parametersOut->RowsPerSlice         = static_cast<unsigned int>(destArea.height);
    133     parametersOut->PositionOffset[0]    = texelCenterX + (destArea.x / float(destSize.width)) * 2.0f - 1.0f;
    134     parametersOut->PositionOffset[1]    = texelCenterY + ((destSize.height - destArea.y - 1) / float(destSize.height)) * 2.0f - 1.0f;
    135     parametersOut->PositionScale[0]     = 2.0f / static_cast<float>(destSize.width);
    136     parametersOut->PositionScale[1]     = -2.0f / static_cast<float>(destSize.height);
    137 }
    138 
    139 bool PixelTransfer11::copyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget,
    140                                           GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea)
    141 {
    142     gl::Extents destSize = destRenderTarget->getExtents();
    143 
    144     if (destArea.x   < 0 || destArea.x   + destArea.width    > destSize.width    ||
    145         destArea.y   < 0 || destArea.y   + destArea.height   > destSize.height   ||
    146         destArea.z   < 0 || destArea.z   + destArea.depth    > destSize.depth    )
    147     {
    148         return false;
    149     }
    150 
    151     int clientVersion = mRenderer->getCurrentClientVersion();
    152     const gl::Buffer &sourceBuffer = *unpack.pixelBuffer.get();
    153 
    154     ASSERT(mRenderer->supportsFastCopyBufferToTexture(destinationFormat));
    155 
    156     ID3D11PixelShader *pixelShader = findBufferToTexturePS(destinationFormat);
    157     ASSERT(pixelShader);
    158 
    159     // The SRV must be in the proper read format, which may be different from the destination format
    160     // EG: for half float data, we can load full precision floats with implicit conversion
    161     GLenum unsizedFormat = gl::GetFormat(destinationFormat, clientVersion);
    162     GLenum sourceFormat = gl::GetSizedInternalFormat(unsizedFormat, sourcePixelsType, clientVersion);
    163 
    164     DXGI_FORMAT srvFormat = gl_d3d11::GetSRVFormat(sourceFormat, clientVersion);
    165     ASSERT(srvFormat != DXGI_FORMAT_UNKNOWN);
    166     BufferStorage11 *bufferStorage11 = BufferStorage11::makeBufferStorage11(sourceBuffer.getStorage());
    167     ID3D11ShaderResourceView *bufferSRV = bufferStorage11->getSRV(srvFormat);
    168     ASSERT(bufferSRV != NULL);
    169 
    170     ID3D11RenderTargetView *textureRTV = RenderTarget11::makeRenderTarget11(destRenderTarget)->getRenderTargetView();
    171     ASSERT(textureRTV != NULL);
    172 
    173     CopyShaderParams shaderParams;
    174     setBufferToTextureCopyParams(destArea, destSize, sourceFormat, unpack, offset, &shaderParams);
    175 
    176     ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
    177 
    178     ID3D11ShaderResourceView *nullSRV = NULL;
    179     ID3D11Buffer *nullBuffer = NULL;
    180     UINT zero = 0;
    181 
    182     // Are we doing a 2D or 3D copy?
    183     ID3D11GeometryShader *geometryShader = ((destSize.depth > 1) ? mBufferToTextureGS : NULL);
    184 
    185     deviceContext->VSSetShader(mBufferToTextureVS, NULL, 0);
    186     deviceContext->GSSetShader(geometryShader, NULL, 0);
    187     deviceContext->PSSetShader(pixelShader, NULL, 0);
    188     deviceContext->PSSetShaderResources(0, 1, &bufferSRV);
    189     deviceContext->IASetInputLayout(NULL);
    190     deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
    191 
    192     deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero);
    193     deviceContext->OMSetBlendState(NULL, NULL, 0xFFFFFFF);
    194     deviceContext->OMSetDepthStencilState(mCopyDepthStencilState, 0xFFFFFFFF);
    195     deviceContext->RSSetState(mCopyRasterizerState);
    196 
    197     mRenderer->setOneTimeRenderTarget(textureRTV);
    198 
    199     if (!StructEquals(mParamsData, shaderParams))
    200     {
    201         d3d11::SetBufferData(deviceContext, mParamsConstantBuffer, shaderParams);
    202         mParamsData = shaderParams;
    203     }
    204 
    205     deviceContext->VSSetConstantBuffers(0, 1, &mParamsConstantBuffer);
    206 
    207     // Set the viewport
    208     D3D11_VIEWPORT viewport;
    209     viewport.TopLeftX = 0;
    210     viewport.TopLeftY = 0;
    211     viewport.Width = destSize.width;
    212     viewport.Height = destSize.height;
    213     viewport.MinDepth = 0.0f;
    214     viewport.MaxDepth = 1.0f;
    215     deviceContext->RSSetViewports(1, &viewport);
    216 
    217     UINT numPixels = (destArea.width * destArea.height * destArea.depth);
    218     deviceContext->Draw(numPixels, 0);
    219 
    220     // Unbind textures and render targets and vertex buffer
    221     deviceContext->PSSetShaderResources(0, 1, &nullSRV);
    222     deviceContext->VSSetConstantBuffers(0, 1, &nullBuffer);
    223 
    224     mRenderer->markAllStateDirty();
    225 
    226     return true;
    227 }
    228 
    229 void PixelTransfer11::buildShaderMap()
    230 {
    231     ID3D11Device *device = mRenderer->getDevice();
    232 
    233     mBufferToTexturePSMap[GL_FLOAT]        = d3d11::CompilePS(device, g_PS_BufferToTexture_4F,  "BufferToTexture RGBA ps");
    234     mBufferToTexturePSMap[GL_INT]          = d3d11::CompilePS(device, g_PS_BufferToTexture_4I,  "BufferToTexture RGBA-I ps");
    235     mBufferToTexturePSMap[GL_UNSIGNED_INT] = d3d11::CompilePS(device, g_PS_BufferToTexture_4UI, "BufferToTexture RGBA-UI ps");
    236 }
    237 
    238 ID3D11PixelShader *PixelTransfer11::findBufferToTexturePS(GLenum internalFormat) const
    239 {
    240     int clientVersion = mRenderer->getCurrentClientVersion();
    241     GLenum componentType = gl::GetComponentType(internalFormat, clientVersion);
    242 
    243     if (componentType == GL_SIGNED_NORMALIZED || componentType == GL_UNSIGNED_NORMALIZED)
    244     {
    245         componentType = GL_FLOAT;
    246     }
    247 
    248     auto shaderMapIt = mBufferToTexturePSMap.find(componentType);
    249     return (shaderMapIt == mBufferToTexturePSMap.end() ? NULL : shaderMapIt->second);
    250 }
    251 
    252 }
    253