PixelTransfer11.cpp (12251B)
1 // 2 // Copyright 2013 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 7 // PixelTransfer11.cpp: 8 // Implementation for buffer-to-texture and texture-to-buffer copies. 9 // Used to implement pixel transfers from unpack and to pack buffers. 10 // 11 12 #include "libANGLE/renderer/d3d/d3d11/PixelTransfer11.h" 13 14 #include "libANGLE/Buffer.h" 15 #include "libANGLE/Context.h" 16 #include "libANGLE/Texture.h" 17 #include "libANGLE/formatutils.h" 18 #include "libANGLE/renderer/d3d/d3d11/Buffer11.h" 19 #include "libANGLE/renderer/d3d/d3d11/Context11.h" 20 #include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" 21 #include "libANGLE/renderer/d3d/d3d11/Renderer11.h" 22 #include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h" 23 #include "libANGLE/renderer/d3d/d3d11/formatutils11.h" 24 #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" 25 #include "libANGLE/renderer/d3d/d3d11/texture_format_table.h" 26 #include "libANGLE/renderer/serial_utils.h" 27 28 // Precompiled shaders 29 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_gs.h" 30 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4f.h" 31 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4i.h" 32 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4ui.h" 33 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_vs.h" 34 35 namespace rx 36 { 37 38 PixelTransfer11::PixelTransfer11(Renderer11 *renderer) 39 : mRenderer(renderer), 40 mResourcesLoaded(false), 41 mBufferToTextureVS(), 42 mBufferToTextureGS(), 43 mParamsConstantBuffer(), 44 mCopyRasterizerState(), 45 mCopyDepthStencilState() 46 {} 47 48 PixelTransfer11::~PixelTransfer11() {} 49 50 angle::Result PixelTransfer11::loadResources(const gl::Context *context) 51 { 52 if (mResourcesLoaded) 53 { 54 return angle::Result::Continue; 55 } 56 57 D3D11_RASTERIZER_DESC rasterDesc; 58 rasterDesc.FillMode = D3D11_FILL_SOLID; 59 rasterDesc.CullMode = D3D11_CULL_NONE; 60 rasterDesc.FrontCounterClockwise = FALSE; 61 rasterDesc.DepthBias = 0; 62 rasterDesc.SlopeScaledDepthBias = 0.0f; 63 rasterDesc.DepthBiasClamp = 0.0f; 64 rasterDesc.DepthClipEnable = TRUE; 65 rasterDesc.ScissorEnable = FALSE; 66 rasterDesc.MultisampleEnable = FALSE; 67 rasterDesc.AntialiasedLineEnable = FALSE; 68 69 Context11 *context11 = GetImplAs<Context11>(context); 70 71 ANGLE_TRY(mRenderer->allocateResource(context11, rasterDesc, &mCopyRasterizerState)); 72 73 D3D11_DEPTH_STENCIL_DESC depthStencilDesc; 74 depthStencilDesc.DepthEnable = true; 75 depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; 76 depthStencilDesc.DepthFunc = D3D11_COMPARISON_ALWAYS; 77 depthStencilDesc.StencilEnable = FALSE; 78 depthStencilDesc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK; 79 depthStencilDesc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK; 80 depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; 81 depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; 82 depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; 83 depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; 84 depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; 85 depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; 86 depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; 87 depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; 88 89 ANGLE_TRY(mRenderer->allocateResource(context11, depthStencilDesc, &mCopyDepthStencilState)); 90 91 D3D11_BUFFER_DESC constantBufferDesc = {}; 92 constantBufferDesc.ByteWidth = roundUpPow2<UINT>(sizeof(CopyShaderParams), 32u); 93 constantBufferDesc.Usage = D3D11_USAGE_DYNAMIC; 94 constantBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; 95 constantBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; 96 constantBufferDesc.MiscFlags = 0; 97 constantBufferDesc.StructureByteStride = 0; 98 99 ANGLE_TRY(mRenderer->allocateResource(context11, constantBufferDesc, &mParamsConstantBuffer)); 100 mParamsConstantBuffer.setInternalName("PixelTransfer11ConstantBuffer"); 101 102 // init shaders 103 ANGLE_TRY(mRenderer->allocateResource(context11, ShaderData(g_VS_BufferToTexture), 104 &mBufferToTextureVS)); 105 mBufferToTextureVS.setInternalName("BufferToTextureVS"); 106 107 ANGLE_TRY(mRenderer->allocateResource(context11, ShaderData(g_GS_BufferToTexture), 108 &mBufferToTextureGS)); 109 mBufferToTextureGS.setInternalName("BufferToTextureGS"); 110 111 ANGLE_TRY(buildShaderMap(context)); 112 113 StructZero(&mParamsData); 114 115 mResourcesLoaded = true; 116 117 return angle::Result::Continue; 118 } 119 120 void PixelTransfer11::setBufferToTextureCopyParams(const gl::Box &destArea, 121 const gl::Extents &destSize, 122 GLenum internalFormat, 123 const gl::PixelUnpackState &unpack, 124 unsigned int offset, 125 CopyShaderParams *parametersOut) 126 { 127 StructZero(parametersOut); 128 129 float texelCenterX = 0.5f / static_cast<float>(destSize.width); 130 float texelCenterY = 0.5f / static_cast<float>(destSize.height); 131 132 unsigned int bytesPerPixel = gl::GetSizedInternalFormatInfo(internalFormat).pixelBytes; 133 unsigned int alignmentBytes = static_cast<unsigned int>(unpack.alignment); 134 unsigned int alignmentPixels = 135 (alignmentBytes <= bytesPerPixel ? 1 : alignmentBytes / bytesPerPixel); 136 137 parametersOut->FirstPixelOffset = offset / bytesPerPixel; 138 parametersOut->PixelsPerRow = 139 static_cast<unsigned int>((unpack.rowLength > 0) ? unpack.rowLength : destArea.width); 140 parametersOut->RowStride = roundUp(parametersOut->PixelsPerRow, alignmentPixels); 141 parametersOut->RowsPerSlice = static_cast<unsigned int>(destArea.height); 142 parametersOut->PositionOffset[0] = 143 texelCenterX + (destArea.x / float(destSize.width)) * 2.0f - 1.0f; 144 parametersOut->PositionOffset[1] = 145 texelCenterY + ((destSize.height - destArea.y - 1) / float(destSize.height)) * 2.0f - 1.0f; 146 parametersOut->PositionScale[0] = 2.0f / static_cast<float>(destSize.width); 147 parametersOut->PositionScale[1] = -2.0f / static_cast<float>(destSize.height); 148 parametersOut->FirstSlice = destArea.z; 149 } 150 151 angle::Result PixelTransfer11::copyBufferToTexture(const gl::Context *context, 152 const gl::PixelUnpackState &unpack, 153 gl::Buffer *unpackBuffer, 154 unsigned int offset, 155 RenderTargetD3D *destRenderTarget, 156 GLenum destinationFormat, 157 GLenum sourcePixelsType, 158 const gl::Box &destArea) 159 { 160 ASSERT(unpackBuffer); 161 162 ANGLE_TRY(loadResources(context)); 163 164 gl::Extents destSize = destRenderTarget->getExtents(); 165 166 ASSERT(destArea.x >= 0 && destArea.x + destArea.width <= destSize.width && destArea.y >= 0 && 167 destArea.y + destArea.height <= destSize.height && destArea.z >= 0 && 168 destArea.z + destArea.depth <= destSize.depth); 169 170 ASSERT(mRenderer->supportsFastCopyBufferToTexture(destinationFormat)); 171 172 const d3d11::PixelShader *pixelShader = findBufferToTexturePS(destinationFormat); 173 ASSERT(pixelShader); 174 175 // The SRV must be in the proper read format, which may be different from the destination format 176 // EG: for half float data, we can load full precision floats with implicit conversion 177 GLenum unsizedFormat = gl::GetUnsizedFormat(destinationFormat); 178 const gl::InternalFormat &sourceglFormatInfo = 179 gl::GetInternalFormatInfo(unsizedFormat, sourcePixelsType); 180 181 const d3d11::Format &sourceFormatInfo = d3d11::Format::Get( 182 sourceglFormatInfo.sizedInternalFormat, mRenderer->getRenderer11DeviceCaps()); 183 DXGI_FORMAT srvFormat = sourceFormatInfo.srvFormat; 184 ASSERT(srvFormat != DXGI_FORMAT_UNKNOWN); 185 Buffer11 *bufferStorage11 = GetAs<Buffer11>(unpackBuffer->getImplementation()); 186 const d3d11::ShaderResourceView *bufferSRV = nullptr; 187 ANGLE_TRY(bufferStorage11->getSRV(context, srvFormat, &bufferSRV)); 188 ASSERT(bufferSRV != nullptr); 189 190 const d3d11::RenderTargetView &textureRTV = 191 GetAs<RenderTarget11>(destRenderTarget)->getRenderTargetView(); 192 ASSERT(textureRTV.valid()); 193 194 CopyShaderParams shaderParams; 195 setBufferToTextureCopyParams(destArea, destSize, sourceglFormatInfo.sizedInternalFormat, unpack, 196 offset, &shaderParams); 197 198 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); 199 200 // Are we doing a 2D or 3D copy? 201 const auto *geometryShader = ((destSize.depth > 1) ? &mBufferToTextureGS : nullptr); 202 StateManager11 *stateManager = mRenderer->getStateManager(); 203 204 stateManager->setDrawShaders(&mBufferToTextureVS, geometryShader, pixelShader); 205 stateManager->setShaderResource(gl::ShaderType::Fragment, 0, bufferSRV); 206 stateManager->setInputLayout(nullptr); 207 stateManager->setPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); 208 209 stateManager->setSingleVertexBuffer(nullptr, 0, 0); 210 stateManager->setSimpleBlendState(nullptr); 211 stateManager->setDepthStencilState(&mCopyDepthStencilState, 0xFFFFFFFF); 212 stateManager->setRasterizerState(&mCopyRasterizerState); 213 214 stateManager->setRenderTarget(textureRTV.get(), nullptr); 215 216 if (!StructEquals(mParamsData, shaderParams)) 217 { 218 d3d11::SetBufferData(deviceContext, mParamsConstantBuffer.get(), shaderParams); 219 mParamsData = shaderParams; 220 } 221 222 stateManager->setVertexConstantBuffer(0, &mParamsConstantBuffer); 223 224 // Set the viewport 225 stateManager->setSimpleViewport(destSize); 226 227 UINT numPixels = (shaderParams.PixelsPerRow * destArea.height * destArea.depth); 228 deviceContext->Draw(numPixels, 0); 229 230 return angle::Result::Continue; 231 } 232 233 angle::Result PixelTransfer11::buildShaderMap(const gl::Context *context) 234 { 235 d3d11::PixelShader bufferToTextureFloat; 236 d3d11::PixelShader bufferToTextureInt; 237 d3d11::PixelShader bufferToTextureUint; 238 239 Context11 *context11 = GetImplAs<Context11>(context); 240 241 ANGLE_TRY(mRenderer->allocateResource(context11, ShaderData(g_PS_BufferToTexture_4F), 242 &bufferToTextureFloat)); 243 ANGLE_TRY(mRenderer->allocateResource(context11, ShaderData(g_PS_BufferToTexture_4I), 244 &bufferToTextureInt)); 245 ANGLE_TRY(mRenderer->allocateResource(context11, ShaderData(g_PS_BufferToTexture_4UI), 246 &bufferToTextureUint)); 247 248 bufferToTextureFloat.setInternalName("BufferToTextureRGBA.ps"); 249 bufferToTextureInt.setInternalName("BufferToTextureRGBA-I.ps"); 250 bufferToTextureUint.setInternalName("BufferToTextureRGBA-UI.ps"); 251 252 mBufferToTexturePSMap[GL_FLOAT] = std::move(bufferToTextureFloat); 253 mBufferToTexturePSMap[GL_INT] = std::move(bufferToTextureInt); 254 mBufferToTexturePSMap[GL_UNSIGNED_INT] = std::move(bufferToTextureUint); 255 256 return angle::Result::Continue; 257 } 258 259 const d3d11::PixelShader *PixelTransfer11::findBufferToTexturePS(GLenum internalFormat) const 260 { 261 GLenum componentType = gl::GetSizedInternalFormatInfo(internalFormat).componentType; 262 if (componentType == GL_SIGNED_NORMALIZED || componentType == GL_UNSIGNED_NORMALIZED) 263 { 264 componentType = GL_FLOAT; 265 } 266 267 auto shaderMapIt = mBufferToTexturePSMap.find(componentType); 268 return (shaderMapIt == mBufferToTexturePSMap.end() ? nullptr : &shaderMapIt->second); 269 } 270 271 } // namespace rx