1 // 2 // Copyright (c) 2012 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 // RenderTarget11.cpp: Implements a DX11-specific wrapper for ID3D11View pointers 8 // retained by Renderbuffers. 9 10 #include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h" 11 #include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" 12 #include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" 13 #include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" 14 #include "libGLESv2/main.h" 15 16 namespace rx 17 { 18 19 static bool getTextureProperties(ID3D11Resource *resource, unsigned int *mipLevels, unsigned int *samples) 20 { 21 ID3D11Texture1D *texture1D = d3d11::DynamicCastComObject<ID3D11Texture1D>(resource); 22 if (texture1D) 23 { 24 D3D11_TEXTURE1D_DESC texDesc; 25 texture1D->GetDesc(&texDesc); 26 SafeRelease(texture1D); 27 28 *mipLevels = texDesc.MipLevels; 29 *samples = 0; 30 31 return true; 32 } 33 34 ID3D11Texture2D *texture2D = d3d11::DynamicCastComObject<ID3D11Texture2D>(resource); 35 if (texture2D) 36 { 37 D3D11_TEXTURE2D_DESC texDesc; 38 texture2D->GetDesc(&texDesc); 39 SafeRelease(texture2D); 40 41 *mipLevels = texDesc.MipLevels; 42 *samples = texDesc.SampleDesc.Count > 1 ? texDesc.SampleDesc.Count : 0; 43 44 return true; 45 } 46 47 ID3D11Texture3D *texture3D = d3d11::DynamicCastComObject<ID3D11Texture3D>(resource); 48 if (texture3D) 49 { 50 D3D11_TEXTURE3D_DESC texDesc; 51 texture3D->GetDesc(&texDesc); 52 SafeRelease(texture3D); 53 54 *mipLevels = texDesc.MipLevels; 55 *samples = 0; 56 57 return true; 58 } 59 60 return false; 61 } 62 63 static unsigned int getRTVSubresourceIndex(ID3D11Resource *resource, ID3D11RenderTargetView *view) 64 { 65 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; 66 view->GetDesc(&rtvDesc); 67 68 unsigned int mipSlice = 0; 69 unsigned int arraySlice = 0; 70 71 switch (rtvDesc.ViewDimension) 72 { 73 case D3D11_RTV_DIMENSION_TEXTURE1D: 74 mipSlice = rtvDesc.Texture1D.MipSlice; 75 arraySlice = 0; 76 break; 77 78 case D3D11_RTV_DIMENSION_TEXTURE1DARRAY: 79 mipSlice = rtvDesc.Texture1DArray.MipSlice; 80 arraySlice = rtvDesc.Texture1DArray.FirstArraySlice; 81 break; 82 83 case D3D11_RTV_DIMENSION_TEXTURE2D: 84 mipSlice = rtvDesc.Texture2D.MipSlice; 85 arraySlice = 0; 86 break; 87 88 case D3D11_RTV_DIMENSION_TEXTURE2DARRAY: 89 mipSlice = rtvDesc.Texture2DArray.MipSlice; 90 arraySlice = rtvDesc.Texture2DArray.FirstArraySlice; 91 break; 92 93 case D3D11_RTV_DIMENSION_TEXTURE2DMS: 94 mipSlice = 0; 95 arraySlice = 0; 96 break; 97 98 case D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY: 99 mipSlice = 0; 100 arraySlice = rtvDesc.Texture2DMSArray.FirstArraySlice; 101 break; 102 103 case D3D11_RTV_DIMENSION_TEXTURE3D: 104 mipSlice = rtvDesc.Texture3D.MipSlice; 105 arraySlice = 0; 106 break; 107 108 case D3D11_RTV_DIMENSION_UNKNOWN: 109 case D3D11_RTV_DIMENSION_BUFFER: 110 UNIMPLEMENTED(); 111 break; 112 113 default: 114 UNREACHABLE(); 115 break; 116 } 117 118 unsigned int mipLevels, samples; 119 getTextureProperties(resource, &mipLevels, &samples); 120 121 return D3D11CalcSubresource(mipSlice, arraySlice, mipLevels); 122 } 123 124 static unsigned int getDSVSubresourceIndex(ID3D11Resource *resource, ID3D11DepthStencilView *view) 125 { 126 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; 127 view->GetDesc(&dsvDesc); 128 129 unsigned int mipSlice = 0; 130 unsigned int arraySlice = 0; 131 132 switch (dsvDesc.ViewDimension) 133 { 134 case D3D11_DSV_DIMENSION_TEXTURE1D: 135 mipSlice = dsvDesc.Texture1D.MipSlice; 136 arraySlice = 0; 137 break; 138 139 case D3D11_DSV_DIMENSION_TEXTURE1DARRAY: 140 mipSlice = dsvDesc.Texture1DArray.MipSlice; 141 arraySlice = dsvDesc.Texture1DArray.FirstArraySlice; 142 break; 143 144 case D3D11_DSV_DIMENSION_TEXTURE2D: 145 mipSlice = dsvDesc.Texture2D.MipSlice; 146 arraySlice = 0; 147 break; 148 149 case D3D11_DSV_DIMENSION_TEXTURE2DARRAY: 150 mipSlice = dsvDesc.Texture2DArray.MipSlice; 151 arraySlice = dsvDesc.Texture2DArray.FirstArraySlice; 152 break; 153 154 case D3D11_DSV_DIMENSION_TEXTURE2DMS: 155 mipSlice = 0; 156 arraySlice = 0; 157 break; 158 159 case D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY: 160 mipSlice = 0; 161 arraySlice = dsvDesc.Texture2DMSArray.FirstArraySlice; 162 break; 163 164 case D3D11_DSV_DIMENSION_UNKNOWN: 165 UNIMPLEMENTED(); 166 break; 167 168 default: 169 UNREACHABLE(); 170 break; 171 } 172 173 unsigned int mipLevels, samples; 174 getTextureProperties(resource, &mipLevels, &samples); 175 176 return D3D11CalcSubresource(mipSlice, arraySlice, mipLevels); 177 } 178 179 RenderTarget11::RenderTarget11(Renderer *renderer, ID3D11RenderTargetView *rtv, ID3D11Resource *resource, 180 ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height, GLsizei depth) 181 { 182 mRenderer = Renderer11::makeRenderer11(renderer); 183 184 mTexture = resource; 185 if (mTexture) 186 { 187 mTexture->AddRef(); 188 } 189 190 mRenderTarget = rtv; 191 if (mRenderTarget) 192 { 193 mRenderTarget->AddRef(); 194 } 195 196 mDepthStencil = NULL; 197 198 mShaderResource = srv; 199 if (mShaderResource) 200 { 201 mShaderResource->AddRef(); 202 } 203 204 mSubresourceIndex = 0; 205 206 if (mRenderTarget && mTexture) 207 { 208 D3D11_RENDER_TARGET_VIEW_DESC desc; 209 mRenderTarget->GetDesc(&desc); 210 211 unsigned int mipLevels, samples; 212 getTextureProperties(mTexture, &mipLevels, &samples); 213 214 mSubresourceIndex = getRTVSubresourceIndex(mTexture, mRenderTarget); 215 mWidth = width; 216 mHeight = height; 217 mDepth = depth; 218 mSamples = samples; 219 220 const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(desc.Format); 221 mInternalFormat = dxgiFormatInfo.internalFormat; 222 mActualFormat = dxgiFormatInfo.internalFormat; 223 } 224 } 225 226 RenderTarget11::RenderTarget11(Renderer *renderer, ID3D11DepthStencilView *dsv, ID3D11Resource *resource, 227 ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height, GLsizei depth) 228 { 229 mRenderer = Renderer11::makeRenderer11(renderer); 230 231 mTexture = resource; 232 if (mTexture) 233 { 234 mTexture->AddRef(); 235 } 236 237 mRenderTarget = NULL; 238 239 mDepthStencil = dsv; 240 if (mDepthStencil) 241 { 242 mDepthStencil->AddRef(); 243 } 244 245 mShaderResource = srv; 246 if (mShaderResource) 247 { 248 mShaderResource->AddRef(); 249 } 250 251 mSubresourceIndex = 0; 252 253 if (mDepthStencil && mTexture) 254 { 255 D3D11_DEPTH_STENCIL_VIEW_DESC desc; 256 mDepthStencil->GetDesc(&desc); 257 258 unsigned int mipLevels, samples; 259 getTextureProperties(mTexture, &mipLevels, &samples); 260 261 mSubresourceIndex = getDSVSubresourceIndex(mTexture, mDepthStencil); 262 mWidth = width; 263 mHeight = height; 264 mDepth = depth; 265 mSamples = samples; 266 267 const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(desc.Format); 268 mInternalFormat = dxgiFormatInfo.internalFormat; 269 mActualFormat = dxgiFormatInfo.internalFormat; 270 } 271 } 272 273 RenderTarget11::RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height, GLenum internalFormat, GLsizei samples) 274 { 275 mRenderer = Renderer11::makeRenderer11(renderer); 276 mTexture = NULL; 277 mRenderTarget = NULL; 278 mDepthStencil = NULL; 279 mShaderResource = NULL; 280 281 const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalFormat); 282 const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(formatInfo.texFormat); 283 284 const gl::TextureCaps &textureCaps = mRenderer->getRendererTextureCaps().get(internalFormat); 285 GLuint supportedSamples = textureCaps.getNearestSamples(samples); 286 287 if (width > 0 && height > 0) 288 { 289 // Create texture resource 290 D3D11_TEXTURE2D_DESC desc; 291 desc.Width = width; 292 desc.Height = height; 293 desc.MipLevels = 1; 294 desc.ArraySize = 1; 295 desc.Format = formatInfo.texFormat; 296 desc.SampleDesc.Count = (supportedSamples == 0) ? 1 : supportedSamples; 297 desc.SampleDesc.Quality = 0; 298 desc.Usage = D3D11_USAGE_DEFAULT; 299 desc.CPUAccessFlags = 0; 300 desc.MiscFlags = 0; 301 302 // If a rendertarget or depthstencil format exists for this texture format, 303 // we'll flag it to allow binding that way. Shader resource views are a little 304 // more complicated. 305 bool bindRTV = false, bindDSV = false, bindSRV = false; 306 bindRTV = (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN); 307 bindDSV = (formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN); 308 if (formatInfo.srvFormat != DXGI_FORMAT_UNKNOWN) 309 { 310 // Multisample targets flagged for binding as depth stencil cannot also be 311 // flagged for binding as SRV, so make certain not to add the SRV flag for 312 // these targets. 313 bindSRV = !(formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN && desc.SampleDesc.Count > 1); 314 } 315 316 desc.BindFlags = (bindRTV ? D3D11_BIND_RENDER_TARGET : 0) | 317 (bindDSV ? D3D11_BIND_DEPTH_STENCIL : 0) | 318 (bindSRV ? D3D11_BIND_SHADER_RESOURCE : 0); 319 320 ID3D11Device *device = mRenderer->getDevice(); 321 ID3D11Texture2D *texture = NULL; 322 HRESULT result = device->CreateTexture2D(&desc, NULL, &texture); 323 mTexture = texture; 324 325 if (result == E_OUTOFMEMORY) 326 { 327 gl::error(GL_OUT_OF_MEMORY); 328 return; 329 } 330 ASSERT(SUCCEEDED(result)); 331 332 if (bindSRV) 333 { 334 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; 335 srvDesc.Format = formatInfo.srvFormat; 336 srvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_SRV_DIMENSION_TEXTURE2D : D3D11_SRV_DIMENSION_TEXTURE2DMS; 337 srvDesc.Texture2D.MostDetailedMip = 0; 338 srvDesc.Texture2D.MipLevels = 1; 339 result = device->CreateShaderResourceView(mTexture, &srvDesc, &mShaderResource); 340 341 if (result == E_OUTOFMEMORY) 342 { 343 SafeRelease(mTexture); 344 gl::error(GL_OUT_OF_MEMORY); 345 return; 346 } 347 ASSERT(SUCCEEDED(result)); 348 } 349 350 if (bindDSV) 351 { 352 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; 353 dsvDesc.Format = formatInfo.dsvFormat; 354 dsvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_DSV_DIMENSION_TEXTURE2D : D3D11_DSV_DIMENSION_TEXTURE2DMS; 355 dsvDesc.Texture2D.MipSlice = 0; 356 dsvDesc.Flags = 0; 357 result = device->CreateDepthStencilView(mTexture, &dsvDesc, &mDepthStencil); 358 359 if (result == E_OUTOFMEMORY) 360 { 361 SafeRelease(mTexture); 362 SafeRelease(mShaderResource); 363 gl::error(GL_OUT_OF_MEMORY); 364 return; 365 } 366 ASSERT(SUCCEEDED(result)); 367 } 368 369 if (bindRTV) 370 { 371 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; 372 rtvDesc.Format = formatInfo.rtvFormat; 373 rtvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_RTV_DIMENSION_TEXTURE2D : D3D11_RTV_DIMENSION_TEXTURE2DMS; 374 rtvDesc.Texture2D.MipSlice = 0; 375 result = device->CreateRenderTargetView(mTexture, &rtvDesc, &mRenderTarget); 376 377 if (result == E_OUTOFMEMORY) 378 { 379 SafeRelease(mTexture); 380 SafeRelease(mShaderResource); 381 SafeRelease(mDepthStencil); 382 gl::error(GL_OUT_OF_MEMORY); 383 return; 384 } 385 ASSERT(SUCCEEDED(result)); 386 387 if (formatInfo.dataInitializerFunction != NULL) 388 { 389 ID3D11DeviceContext *context = mRenderer->getDeviceContext(); 390 391 const float clearValues[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; 392 context->ClearRenderTargetView(mRenderTarget, clearValues); 393 } 394 } 395 } 396 397 398 mWidth = width; 399 mHeight = height; 400 mDepth = 1; 401 mInternalFormat = internalFormat; 402 mSamples = supportedSamples; 403 mActualFormat = dxgiFormatInfo.internalFormat; 404 mSubresourceIndex = D3D11CalcSubresource(0, 0, 1); 405 } 406 407 RenderTarget11::~RenderTarget11() 408 { 409 SafeRelease(mTexture); 410 SafeRelease(mRenderTarget); 411 SafeRelease(mDepthStencil); 412 SafeRelease(mShaderResource); 413 } 414 415 RenderTarget11 *RenderTarget11::makeRenderTarget11(RenderTarget *target) 416 { 417 ASSERT(HAS_DYNAMIC_TYPE(rx::RenderTarget11*, target)); 418 return static_cast<rx::RenderTarget11*>(target); 419 } 420 421 void RenderTarget11::invalidate(GLint x, GLint y, GLsizei width, GLsizei height) 422 { 423 // Currently a no-op 424 } 425 426 ID3D11Resource *RenderTarget11::getTexture() const 427 { 428 return mTexture; 429 } 430 431 ID3D11RenderTargetView *RenderTarget11::getRenderTargetView() const 432 { 433 return mRenderTarget; 434 } 435 436 ID3D11DepthStencilView *RenderTarget11::getDepthStencilView() const 437 { 438 return mDepthStencil; 439 } 440 441 ID3D11ShaderResourceView *RenderTarget11::getShaderResourceView() const 442 { 443 return mShaderResource; 444 } 445 446 unsigned int RenderTarget11::getSubresourceIndex() const 447 { 448 return mSubresourceIndex; 449 } 450 451 } 452