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