1 #include "precompiled.h"
3 // Copyright (c) 2012-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.
8 // Renderer11.cpp: Implements a back-end specific class for the D3D11 renderer.
10 #include "libGLESv2/main.h"
11 #include "libGLESv2/utilities.h"
12 #include "libGLESv2/Buffer.h"
13 #include "libGLESv2/ProgramBinary.h"
14 #include "libGLESv2/Framebuffer.h"
15 #include "libGLESv2/Renderbuffer.h"
16 #include "libGLESv2/renderer/d3d11/Renderer11.h"
17 #include "libGLESv2/renderer/d3d11/RenderTarget11.h"
18 #include "libGLESv2/renderer/d3d11/renderer11_utils.h"
19 #include "libGLESv2/renderer/d3d11/ShaderExecutable11.h"
20 #include "libGLESv2/renderer/d3d11/SwapChain11.h"
21 #include "libGLESv2/renderer/d3d11/Image11.h"
22 #include "libGLESv2/renderer/d3d11/VertexBuffer11.h"
23 #include "libGLESv2/renderer/d3d11/IndexBuffer11.h"
24 #include "libGLESv2/renderer/d3d11/BufferStorage11.h"
25 #include "libGLESv2/renderer/VertexDataManager.h"
26 #include "libGLESv2/renderer/IndexDataManager.h"
27 #include "libGLESv2/renderer/d3d11/TextureStorage11.h"
28 #include "libGLESv2/renderer/d3d11/Query11.h"
29 #include "libGLESv2/renderer/d3d11/Fence11.h"
31 #include "libGLESv2/renderer/d3d11/shaders/compiled/passthrough11vs.h"
32 #include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgba11ps.h"
33 #include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgb11ps.h"
34 #include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughlum11ps.h"
35 #include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughlumalpha11ps.h"
37 #include "libGLESv2/renderer/d3d11/shaders/compiled/clear11vs.h"
38 #include "libGLESv2/renderer/d3d11/shaders/compiled/clearsingle11ps.h"
39 #include "libGLESv2/renderer/d3d11/shaders/compiled/clearmultiple11ps.h"
41 #include "libEGL/Display.h"
44 // this flag enables suppressing some spurious warnings that pop up in certain WebGL samples
45 // and conformance tests. to enable all warnings, remove this define.
46 #define ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS 1
51 static const DXGI_FORMAT RenderTargetFormats[] =
53 DXGI_FORMAT_B8G8R8A8_UNORM,
54 DXGI_FORMAT_R8G8B8A8_UNORM
57 static const DXGI_FORMAT DepthStencilFormats[] =
60 DXGI_FORMAT_D24_UNORM_S8_UINT,
66 MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 = 16
69 Renderer11::Renderer11(egl::Display *display, HDC hDc) : Renderer(display), mDc(hDc)
71 mVertexDataManager = NULL;
72 mIndexDataManager = NULL;
75 mTriangleFanIB = NULL;
77 mCopyResourcesInitialized = false;
85 mCopyLumAlphaPS = NULL;
87 mClearResourcesInitialized = false;
91 mClearSinglePS = NULL;
92 mClearMultiplePS = NULL;
93 mClearScissorRS = NULL;
94 mClearNoScissorRS = NULL;
103 mMaxSupportedSamples = 0;
106 mDeviceContext = NULL;
110 mDriverConstantBufferVS = NULL;
111 mDriverConstantBufferPS = NULL;
113 mBGRATextureSupport = false;
115 mIsGeometryShaderActive = false;
118 Renderer11::~Renderer11()
123 Renderer11 *Renderer11::makeRenderer11(Renderer *renderer)
125 ASSERT(HAS_DYNAMIC_TYPE(rx::Renderer11*, renderer));
126 return static_cast<rx::Renderer11*>(renderer);
129 #ifndef __d3d11_1_h__
130 #define D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET ((D3D11_MESSAGE_ID)3146081)
133 EGLint Renderer11::initialize()
135 if (!initializeCompiler())
137 return EGL_NOT_INITIALIZED;
140 mDxgiModule = LoadLibrary(TEXT("dxgi.dll"));
141 mD3d11Module = LoadLibrary(TEXT("d3d11.dll"));
143 if (mD3d11Module == NULL || mDxgiModule == NULL)
145 ERR("Could not load D3D11 or DXGI library - aborting!\n");
146 return EGL_NOT_INITIALIZED;
149 // create the D3D11 device
150 ASSERT(mDevice == NULL);
151 PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice");
153 if (D3D11CreateDevice == NULL)
155 ERR("Could not retrieve D3D11CreateDevice address - aborting!\n");
156 return EGL_NOT_INITIALIZED;
159 D3D_FEATURE_LEVEL featureLevels[] =
161 D3D_FEATURE_LEVEL_11_0,
162 D3D_FEATURE_LEVEL_10_1,
163 D3D_FEATURE_LEVEL_10_0,
166 HRESULT result = S_OK;
169 result = D3D11CreateDevice(NULL,
170 D3D_DRIVER_TYPE_HARDWARE,
172 D3D11_CREATE_DEVICE_DEBUG,
174 ArraySize(featureLevels),
180 if (!mDevice || FAILED(result))
182 ERR("Failed creating Debug D3D11 device - falling back to release runtime.\n");
185 if (!mDevice || FAILED(result))
188 result = D3D11CreateDevice(NULL,
189 D3D_DRIVER_TYPE_HARDWARE,
193 ArraySize(featureLevels),
199 if (!mDevice || FAILED(result))
201 ERR("Could not create D3D11 device - aborting!\n");
202 return EGL_NOT_INITIALIZED; // Cleanup done by destructor through glDestroyRenderer
206 IDXGIDevice *dxgiDevice = NULL;
207 result = mDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgiDevice);
211 ERR("Could not query DXGI device - aborting!\n");
212 return EGL_NOT_INITIALIZED;
215 result = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&mDxgiAdapter);
219 ERR("Could not retrieve DXGI adapter - aborting!\n");
220 return EGL_NOT_INITIALIZED;
223 dxgiDevice->Release();
225 mDxgiAdapter->GetDesc(&mAdapterDescription);
226 memset(mDescription, 0, sizeof(mDescription));
227 wcstombs(mDescription, mAdapterDescription.Description, sizeof(mDescription) - 1);
229 result = mDxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void**)&mDxgiFactory);
231 if (!mDxgiFactory || FAILED(result))
233 ERR("Could not create DXGI factory - aborting!\n");
234 return EGL_NOT_INITIALIZED;
237 // Disable some spurious D3D11 debug warnings to prevent them from flooding the output log
238 #if defined(ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS) && defined(_DEBUG)
239 ID3D11InfoQueue *infoQueue;
240 result = mDevice->QueryInterface(__uuidof(ID3D11InfoQueue), (void **)&infoQueue);
242 if (SUCCEEDED(result))
244 D3D11_MESSAGE_ID hideMessages[] =
246 D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET
249 D3D11_INFO_QUEUE_FILTER filter = {0};
250 filter.DenyList.NumIDs = ArraySize(hideMessages);
251 filter.DenyList.pIDList = hideMessages;
253 infoQueue->AddStorageFilterEntries(&filter);
255 infoQueue->Release();
259 unsigned int maxSupportedSamples = 0;
260 unsigned int rtFormatCount = ArraySize(RenderTargetFormats);
261 unsigned int dsFormatCount = ArraySize(DepthStencilFormats);
262 for (unsigned int i = 0; i < rtFormatCount + dsFormatCount; ++i)
264 DXGI_FORMAT format = (i < rtFormatCount) ? RenderTargetFormats[i] : DepthStencilFormats[i - rtFormatCount];
265 if (format != DXGI_FORMAT_UNKNOWN)
268 result = mDevice->CheckFormatSupport(format, &formatSupport);
269 if (SUCCEEDED(result) && (formatSupport & D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET))
271 MultisampleSupportInfo supportInfo;
273 for (unsigned int j = 1; j <= D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; j++)
275 result = mDevice->CheckMultisampleQualityLevels(format, j, &supportInfo.qualityLevels[j - 1]);
276 if (SUCCEEDED(result) && supportInfo.qualityLevels[j - 1] > 0)
278 maxSupportedSamples = std::max(j, maxSupportedSamples);
282 supportInfo.qualityLevels[j - 1] = 0;
286 mMultisampleSupportMap.insert(std::make_pair(format, supportInfo));
290 mMaxSupportedSamples = maxSupportedSamples;
294 // BGRA texture support is optional in feature levels 10 and 10_1
296 result = mDevice->CheckFormatSupport(DXGI_FORMAT_B8G8R8A8_UNORM, &formatSupport);
299 ERR("Error checking BGRA format support: 0x%08X", result);
303 const int flags = (D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_RENDER_TARGET);
304 mBGRATextureSupport = (formatSupport & flags) == flags;
307 // Check floating point texture support
308 static const unsigned int requiredTextureFlags = D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_TEXTURECUBE;
309 static const unsigned int requiredRenderableFlags = D3D11_FORMAT_SUPPORT_RENDER_TARGET;
310 static const unsigned int requiredFilterFlags = D3D11_FORMAT_SUPPORT_SHADER_SAMPLE;
312 DXGI_FORMAT float16Formats[] =
314 DXGI_FORMAT_R16_FLOAT,
315 DXGI_FORMAT_R16G16_FLOAT,
316 DXGI_FORMAT_R16G16B16A16_FLOAT,
319 DXGI_FORMAT float32Formats[] =
321 DXGI_FORMAT_R32_FLOAT,
322 DXGI_FORMAT_R32G32_FLOAT,
323 DXGI_FORMAT_R32G32B32A32_FLOAT,
326 mFloat16TextureSupport = true;
327 mFloat16FilterSupport = true;
328 mFloat16RenderSupport = true;
329 for (unsigned int i = 0; i < ArraySize(float16Formats); i++)
331 if (SUCCEEDED(mDevice->CheckFormatSupport(float16Formats[i], &formatSupport)))
333 mFloat16TextureSupport = mFloat16TextureSupport && (formatSupport & requiredTextureFlags) == requiredTextureFlags;
334 mFloat16FilterSupport = mFloat16FilterSupport && (formatSupport & requiredFilterFlags) == requiredFilterFlags;
335 mFloat16RenderSupport = mFloat16RenderSupport && (formatSupport & requiredRenderableFlags) == requiredRenderableFlags;
339 mFloat16TextureSupport = false;
340 mFloat16RenderSupport = false;
341 mFloat16FilterSupport = false;
345 mFloat32TextureSupport = true;
346 mFloat32FilterSupport = true;
347 mFloat32RenderSupport = true;
348 for (unsigned int i = 0; i < ArraySize(float32Formats); i++)
350 if (SUCCEEDED(mDevice->CheckFormatSupport(float32Formats[i], &formatSupport)))
352 mFloat32TextureSupport = mFloat32TextureSupport && (formatSupport & requiredTextureFlags) == requiredTextureFlags;
353 mFloat32FilterSupport = mFloat32FilterSupport && (formatSupport & requiredFilterFlags) == requiredFilterFlags;
354 mFloat32RenderSupport = mFloat32RenderSupport && (formatSupport & requiredRenderableFlags) == requiredRenderableFlags;
358 mFloat32TextureSupport = false;
359 mFloat32FilterSupport = false;
360 mFloat32RenderSupport = false;
364 // Check compressed texture support
365 const unsigned int requiredCompressedTextureFlags = D3D11_FORMAT_SUPPORT_TEXTURE2D;
367 if (SUCCEEDED(mDevice->CheckFormatSupport(DXGI_FORMAT_BC1_UNORM, &formatSupport)))
369 mDXT1TextureSupport = (formatSupport & requiredCompressedTextureFlags) == requiredCompressedTextureFlags;
373 mDXT1TextureSupport = false;
376 if (SUCCEEDED(mDevice->CheckFormatSupport(DXGI_FORMAT_BC3_UNORM, &formatSupport)))
378 mDXT3TextureSupport = (formatSupport & requiredCompressedTextureFlags) == requiredCompressedTextureFlags;
382 mDXT3TextureSupport = false;
385 if (SUCCEEDED(mDevice->CheckFormatSupport(DXGI_FORMAT_BC5_UNORM, &formatSupport)))
387 mDXT5TextureSupport = (formatSupport & requiredCompressedTextureFlags) == requiredCompressedTextureFlags;
391 mDXT5TextureSupport = false;
394 // Check depth texture support
395 DXGI_FORMAT depthTextureFormats[] =
397 DXGI_FORMAT_D16_UNORM,
398 DXGI_FORMAT_D24_UNORM_S8_UINT,
401 static const unsigned int requiredDepthTextureFlags = D3D11_FORMAT_SUPPORT_DEPTH_STENCIL |
402 D3D11_FORMAT_SUPPORT_TEXTURE2D;
404 mDepthTextureSupport = true;
405 for (unsigned int i = 0; i < ArraySize(depthTextureFormats); i++)
407 if (SUCCEEDED(mDevice->CheckFormatSupport(depthTextureFormats[i], &formatSupport)))
409 mDepthTextureSupport = mDepthTextureSupport && ((formatSupport & requiredDepthTextureFlags) == requiredDepthTextureFlags);
413 mDepthTextureSupport = false;
420 // do any one-time device initialization
421 // NOTE: this is also needed after a device lost/reset
422 // to reset the scene status and ensure the default states are reset.
423 void Renderer11::initializeDevice()
425 mStateCache.initialize(mDevice);
426 mInputLayoutCache.initialize(mDevice, mDeviceContext);
428 ASSERT(!mVertexDataManager && !mIndexDataManager);
429 mVertexDataManager = new VertexDataManager(this);
430 mIndexDataManager = new IndexDataManager(this);
435 int Renderer11::generateConfigs(ConfigDesc **configDescList)
437 unsigned int numRenderFormats = ArraySize(RenderTargetFormats);
438 unsigned int numDepthFormats = ArraySize(DepthStencilFormats);
439 (*configDescList) = new ConfigDesc[numRenderFormats * numDepthFormats];
442 for (unsigned int formatIndex = 0; formatIndex < numRenderFormats; formatIndex++)
444 for (unsigned int depthStencilIndex = 0; depthStencilIndex < numDepthFormats; depthStencilIndex++)
446 DXGI_FORMAT renderTargetFormat = RenderTargetFormats[formatIndex];
448 UINT formatSupport = 0;
449 HRESULT result = mDevice->CheckFormatSupport(renderTargetFormat, &formatSupport);
451 if (SUCCEEDED(result) && (formatSupport & D3D11_FORMAT_SUPPORT_RENDER_TARGET))
453 DXGI_FORMAT depthStencilFormat = DepthStencilFormats[depthStencilIndex];
455 bool depthStencilFormatOK = true;
457 if (depthStencilFormat != DXGI_FORMAT_UNKNOWN)
459 UINT formatSupport = 0;
460 result = mDevice->CheckFormatSupport(depthStencilFormat, &formatSupport);
461 depthStencilFormatOK = SUCCEEDED(result) && (formatSupport & D3D11_FORMAT_SUPPORT_DEPTH_STENCIL);
464 if (depthStencilFormatOK)
466 ConfigDesc newConfig;
467 newConfig.renderTargetFormat = d3d11_gl::ConvertBackBufferFormat(renderTargetFormat);
468 newConfig.depthStencilFormat = d3d11_gl::ConvertDepthStencilFormat(depthStencilFormat);
469 newConfig.multiSample = 0; // FIXME: enumerate multi-sampling
470 newConfig.fastConfig = true; // Assume all DX11 format conversions to be fast
472 (*configDescList)[numConfigs++] = newConfig;
481 void Renderer11::deleteConfigs(ConfigDesc *configDescList)
483 delete [] (configDescList);
486 void Renderer11::sync(bool block)
494 D3D11_QUERY_DESC queryDesc;
495 queryDesc.Query = D3D11_QUERY_EVENT;
496 queryDesc.MiscFlags = 0;
498 result = mDevice->CreateQuery(&queryDesc, &mSyncQuery);
499 ASSERT(SUCCEEDED(result));
502 mDeviceContext->End(mSyncQuery);
503 mDeviceContext->Flush();
507 result = mDeviceContext->GetData(mSyncQuery, NULL, 0, D3D11_ASYNC_GETDATA_DONOTFLUSH);
509 // Keep polling, but allow other threads to do something useful first
512 if (testDeviceLost(true))
517 while (result == S_FALSE);
521 mDeviceContext->Flush();
525 SwapChain *Renderer11::createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat)
527 return new rx::SwapChain11(this, window, shareHandle, backBufferFormat, depthBufferFormat);
530 void Renderer11::setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &samplerState)
532 if (type == gl::SAMPLER_PIXEL)
534 if (index < 0 || index >= gl::MAX_TEXTURE_IMAGE_UNITS)
536 ERR("Pixel shader sampler index %i is not valid.", index);
540 if (mForceSetPixelSamplerStates[index] || memcmp(&samplerState, &mCurPixelSamplerStates[index], sizeof(gl::SamplerState)) != 0)
542 ID3D11SamplerState *dxSamplerState = mStateCache.getSamplerState(samplerState);
546 ERR("NULL sampler state returned by RenderStateCache::getSamplerState, setting the default"
547 "sampler state for pixel shaders at slot %i.", index);
550 mDeviceContext->PSSetSamplers(index, 1, &dxSamplerState);
552 mCurPixelSamplerStates[index] = samplerState;
555 mForceSetPixelSamplerStates[index] = false;
557 else if (type == gl::SAMPLER_VERTEX)
559 if (index < 0 || index >= (int)getMaxVertexTextureImageUnits())
561 ERR("Vertex shader sampler index %i is not valid.", index);
565 if (mForceSetVertexSamplerStates[index] || memcmp(&samplerState, &mCurVertexSamplerStates[index], sizeof(gl::SamplerState)) != 0)
567 ID3D11SamplerState *dxSamplerState = mStateCache.getSamplerState(samplerState);
571 ERR("NULL sampler state returned by RenderStateCache::getSamplerState, setting the default"
572 "sampler state for vertex shaders at slot %i.", index);
575 mDeviceContext->VSSetSamplers(index, 1, &dxSamplerState);
577 mCurVertexSamplerStates[index] = samplerState;
580 mForceSetVertexSamplerStates[index] = false;
585 void Renderer11::setTexture(gl::SamplerType type, int index, gl::Texture *texture)
587 ID3D11ShaderResourceView *textureSRV = NULL;
588 unsigned int serial = 0;
589 bool forceSetTexture = false;
593 TextureStorageInterface *texStorage = texture->getNativeTexture();
596 TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(texStorage->getStorageInstance());
597 textureSRV = storage11->getSRV();
600 // If we get NULL back from getSRV here, something went wrong in the texture class and we're unexpectedly
601 // missing the shader resource view
602 ASSERT(textureSRV != NULL);
604 serial = texture->getTextureSerial();
605 forceSetTexture = texture->hasDirtyImages();
608 if (type == gl::SAMPLER_PIXEL)
610 if (index < 0 || index >= gl::MAX_TEXTURE_IMAGE_UNITS)
612 ERR("Pixel shader sampler index %i is not valid.", index);
616 if (forceSetTexture || mCurPixelTextureSerials[index] != serial)
618 mDeviceContext->PSSetShaderResources(index, 1, &textureSRV);
621 mCurPixelTextureSerials[index] = serial;
623 else if (type == gl::SAMPLER_VERTEX)
625 if (index < 0 || index >= (int)getMaxVertexTextureImageUnits())
627 ERR("Vertex shader sampler index %i is not valid.", index);
631 if (forceSetTexture || mCurVertexTextureSerials[index] != serial)
633 mDeviceContext->VSSetShaderResources(index, 1, &textureSRV);
636 mCurVertexTextureSerials[index] = serial;
641 void Renderer11::setRasterizerState(const gl::RasterizerState &rasterState)
643 if (mForceSetRasterState || memcmp(&rasterState, &mCurRasterState, sizeof(gl::RasterizerState)) != 0)
645 ID3D11RasterizerState *dxRasterState = mStateCache.getRasterizerState(rasterState, mScissorEnabled,
649 ERR("NULL rasterizer state returned by RenderStateCache::getRasterizerState, setting the default"
650 "rasterizer state.");
653 mDeviceContext->RSSetState(dxRasterState);
655 mCurRasterState = rasterState;
658 mForceSetRasterState = false;
661 void Renderer11::setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::Color &blendColor,
662 unsigned int sampleMask)
664 if (mForceSetBlendState ||
665 memcmp(&blendState, &mCurBlendState, sizeof(gl::BlendState)) != 0 ||
666 memcmp(&blendColor, &mCurBlendColor, sizeof(gl::Color)) != 0 ||
667 sampleMask != mCurSampleMask)
669 ID3D11BlendState *dxBlendState = mStateCache.getBlendState(framebuffer, blendState);
672 ERR("NULL blend state returned by RenderStateCache::getBlendState, setting the default "
676 float blendColors[4] = {0.0f};
677 if (blendState.sourceBlendRGB != GL_CONSTANT_ALPHA && blendState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA &&
678 blendState.destBlendRGB != GL_CONSTANT_ALPHA && blendState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA)
680 blendColors[0] = blendColor.red;
681 blendColors[1] = blendColor.green;
682 blendColors[2] = blendColor.blue;
683 blendColors[3] = blendColor.alpha;
687 blendColors[0] = blendColor.alpha;
688 blendColors[1] = blendColor.alpha;
689 blendColors[2] = blendColor.alpha;
690 blendColors[3] = blendColor.alpha;
693 mDeviceContext->OMSetBlendState(dxBlendState, blendColors, sampleMask);
695 mCurBlendState = blendState;
696 mCurBlendColor = blendColor;
697 mCurSampleMask = sampleMask;
700 mForceSetBlendState = false;
703 void Renderer11::setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef,
704 int stencilBackRef, bool frontFaceCCW)
706 if (mForceSetDepthStencilState ||
707 memcmp(&depthStencilState, &mCurDepthStencilState, sizeof(gl::DepthStencilState)) != 0 ||
708 stencilRef != mCurStencilRef || stencilBackRef != mCurStencilBackRef)
710 if (depthStencilState.stencilWritemask != depthStencilState.stencilBackWritemask ||
711 stencilRef != stencilBackRef ||
712 depthStencilState.stencilMask != depthStencilState.stencilBackMask)
714 ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are "
715 "invalid under WebGL.");
716 return gl::error(GL_INVALID_OPERATION);
719 ID3D11DepthStencilState *dxDepthStencilState = mStateCache.getDepthStencilState(depthStencilState);
720 if (!dxDepthStencilState)
722 ERR("NULL depth stencil state returned by RenderStateCache::getDepthStencilState, "
723 "setting the default depth stencil state.");
726 mDeviceContext->OMSetDepthStencilState(dxDepthStencilState, static_cast<UINT>(stencilRef));
728 mCurDepthStencilState = depthStencilState;
729 mCurStencilRef = stencilRef;
730 mCurStencilBackRef = stencilBackRef;
733 mForceSetDepthStencilState = false;
736 void Renderer11::setScissorRectangle(const gl::Rectangle &scissor, bool enabled)
738 if (mForceSetScissor || memcmp(&scissor, &mCurScissor, sizeof(gl::Rectangle)) != 0 ||
739 enabled != mScissorEnabled)
744 rect.left = std::max(0, scissor.x);
745 rect.top = std::max(0, scissor.y);
746 rect.right = scissor.x + std::max(0, scissor.width);
747 rect.bottom = scissor.y + std::max(0, scissor.height);
749 mDeviceContext->RSSetScissorRects(1, &rect);
752 if (enabled != mScissorEnabled)
754 mForceSetRasterState = true;
757 mCurScissor = scissor;
758 mScissorEnabled = enabled;
761 mForceSetScissor = false;
764 bool Renderer11::setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace,
767 gl::Rectangle actualViewport = viewport;
768 float actualZNear = gl::clamp01(zNear);
769 float actualZFar = gl::clamp01(zFar);
772 actualViewport.x = 0;
773 actualViewport.y = 0;
774 actualViewport.width = mRenderTargetDesc.width;
775 actualViewport.height = mRenderTargetDesc.height;
780 // Get D3D viewport bounds, which depends on the feature level
781 const Range& viewportBounds = getViewportBounds();
783 // Clamp width and height first to the gl maximum, then clamp further if we extend past the D3D maximum bounds
784 D3D11_VIEWPORT dxViewport;
785 dxViewport.TopLeftX = gl::clamp(actualViewport.x, viewportBounds.start, viewportBounds.end);
786 dxViewport.TopLeftY = gl::clamp(actualViewport.y, viewportBounds.start, viewportBounds.end);
787 dxViewport.Width = gl::clamp(actualViewport.width, 0, getMaxViewportDimension());
788 dxViewport.Height = gl::clamp(actualViewport.height, 0, getMaxViewportDimension());
789 dxViewport.Width = std::min((int)dxViewport.Width, viewportBounds.end - static_cast<int>(dxViewport.TopLeftX));
790 dxViewport.Height = std::min((int)dxViewport.Height, viewportBounds.end - static_cast<int>(dxViewport.TopLeftY));
791 dxViewport.MinDepth = actualZNear;
792 dxViewport.MaxDepth = actualZFar;
794 if (dxViewport.Width <= 0 || dxViewport.Height <= 0)
796 return false; // Nothing to render
799 bool viewportChanged = mForceSetViewport || memcmp(&actualViewport, &mCurViewport, sizeof(gl::Rectangle)) != 0 ||
800 actualZNear != mCurNear || actualZFar != mCurFar;
804 mDeviceContext->RSSetViewports(1, &dxViewport);
806 mCurViewport = actualViewport;
807 mCurNear = actualZNear;
808 mCurFar = actualZFar;
810 mPixelConstants.viewCoords[0] = actualViewport.width * 0.5f;
811 mPixelConstants.viewCoords[1] = actualViewport.height * 0.5f;
812 mPixelConstants.viewCoords[2] = actualViewport.x + (actualViewport.width * 0.5f);
813 mPixelConstants.viewCoords[3] = actualViewport.y + (actualViewport.height * 0.5f);
815 mPixelConstants.depthFront[0] = (actualZFar - actualZNear) * 0.5f;
816 mPixelConstants.depthFront[1] = (actualZNear + actualZFar) * 0.5f;
818 mVertexConstants.depthRange[0] = actualZNear;
819 mVertexConstants.depthRange[1] = actualZFar;
820 mVertexConstants.depthRange[2] = actualZFar - actualZNear;
822 mPixelConstants.depthRange[0] = actualZNear;
823 mPixelConstants.depthRange[1] = actualZFar;
824 mPixelConstants.depthRange[2] = actualZFar - actualZNear;
827 mForceSetViewport = false;
831 bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count)
833 D3D11_PRIMITIVE_TOPOLOGY primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
835 GLsizei minCount = 0;
839 case GL_POINTS: primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST; minCount = 1; break;
840 case GL_LINES: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINELIST; minCount = 2; break;
841 case GL_LINE_LOOP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; minCount = 2; break;
842 case GL_LINE_STRIP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; minCount = 2; break;
843 case GL_TRIANGLES: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; minCount = 3; break;
844 case GL_TRIANGLE_STRIP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; minCount = 3; break;
845 // emulate fans via rewriting index buffer
846 case GL_TRIANGLE_FAN: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; minCount = 3; break;
848 return gl::error(GL_INVALID_ENUM, false);
851 if (primitiveTopology != mCurrentPrimitiveTopology)
853 mDeviceContext->IASetPrimitiveTopology(primitiveTopology);
854 mCurrentPrimitiveTopology = primitiveTopology;
857 return count >= minCount;
860 bool Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer)
862 // Get the color render buffer and serial
863 // Also extract the render target dimensions and view
864 unsigned int renderTargetWidth = 0;
865 unsigned int renderTargetHeight = 0;
866 GLenum renderTargetFormat = 0;
867 unsigned int renderTargetSerials[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {0};
868 ID3D11RenderTargetView* framebufferRTVs[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {NULL};
869 bool missingColorRenderTarget = true;
871 for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
873 const GLenum drawBufferState = framebuffer->getDrawBufferState(colorAttachment);
875 if (framebuffer->getColorbufferType(colorAttachment) != GL_NONE && drawBufferState != GL_NONE)
877 // the draw buffer must be either "none", "back" for the default buffer or the same index as this color (in order)
878 ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + colorAttachment));
880 gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer(colorAttachment);
884 ERR("render target pointer unexpectedly null.");
888 // check for zero-sized default framebuffer, which is a special case.
889 // in this case we do not wish to modify any state and just silently return false.
890 // this will not report any gl error but will cause the calling method to return.
891 if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0)
896 renderTargetSerials[colorAttachment] = colorbuffer->getSerial();
898 // Extract the render target dimensions and view
899 RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget());
902 ERR("render target pointer unexpectedly null.");
906 framebufferRTVs[colorAttachment] = renderTarget->getRenderTargetView();
907 if (!framebufferRTVs[colorAttachment])
909 ERR("render target view pointer unexpectedly null.");
913 if (missingColorRenderTarget)
915 renderTargetWidth = colorbuffer->getWidth();
916 renderTargetHeight = colorbuffer->getHeight();
917 renderTargetFormat = colorbuffer->getActualFormat();
918 missingColorRenderTarget = false;
922 // Workaround for Debug SETSHADERRESOURCES_HAZARD D3D11 warnings
923 for (unsigned int vertexSerialIndex = 0; vertexSerialIndex < gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; vertexSerialIndex++)
925 if (colorbuffer->getTextureSerial() != 0 && mCurVertexTextureSerials[vertexSerialIndex] == colorbuffer->getTextureSerial())
927 setTexture(gl::SAMPLER_VERTEX, vertexSerialIndex, NULL);
931 for (unsigned int pixelSerialIndex = 0; pixelSerialIndex < gl::MAX_TEXTURE_IMAGE_UNITS; pixelSerialIndex++)
933 if (colorbuffer->getTextureSerial() != 0 && mCurPixelTextureSerials[pixelSerialIndex] == colorbuffer->getTextureSerial())
935 setTexture(gl::SAMPLER_PIXEL, pixelSerialIndex, NULL);
942 // Get the depth stencil render buffer and serials
943 gl::Renderbuffer *depthStencil = NULL;
944 unsigned int depthbufferSerial = 0;
945 unsigned int stencilbufferSerial = 0;
946 if (framebuffer->getDepthbufferType() != GL_NONE)
948 depthStencil = framebuffer->getDepthbuffer();
951 ERR("Depth stencil pointer unexpectedly null.");
952 SafeRelease(framebufferRTVs);
956 depthbufferSerial = depthStencil->getSerial();
958 else if (framebuffer->getStencilbufferType() != GL_NONE)
960 depthStencil = framebuffer->getStencilbuffer();
963 ERR("Depth stencil pointer unexpectedly null.");
964 SafeRelease(framebufferRTVs);
968 stencilbufferSerial = depthStencil->getSerial();
971 // Extract the depth stencil sizes and view
972 unsigned int depthSize = 0;
973 unsigned int stencilSize = 0;
974 ID3D11DepthStencilView* framebufferDSV = NULL;
977 RenderTarget11 *depthStencilRenderTarget = RenderTarget11::makeRenderTarget11(depthStencil->getDepthStencil());
978 if (!depthStencilRenderTarget)
980 ERR("render target pointer unexpectedly null.");
981 SafeRelease(framebufferRTVs);
985 framebufferDSV = depthStencilRenderTarget->getDepthStencilView();
988 ERR("depth stencil view pointer unexpectedly null.");
989 SafeRelease(framebufferRTVs);
993 // If there is no render buffer, the width, height and format values come from
995 if (missingColorRenderTarget)
997 renderTargetWidth = depthStencil->getWidth();
998 renderTargetHeight = depthStencil->getHeight();
999 renderTargetFormat = depthStencil->getActualFormat();
1002 depthSize = depthStencil->getDepthSize();
1003 stencilSize = depthStencil->getStencilSize();
1006 // Apply the render target and depth stencil
1007 if (!mRenderTargetDescInitialized || !mDepthStencilInitialized ||
1008 memcmp(renderTargetSerials, mAppliedRenderTargetSerials, sizeof(renderTargetSerials)) != 0 ||
1009 depthbufferSerial != mAppliedDepthbufferSerial ||
1010 stencilbufferSerial != mAppliedStencilbufferSerial)
1012 mDeviceContext->OMSetRenderTargets(getMaxRenderTargets(), framebufferRTVs, framebufferDSV);
1014 mRenderTargetDesc.width = renderTargetWidth;
1015 mRenderTargetDesc.height = renderTargetHeight;
1016 mRenderTargetDesc.format = renderTargetFormat;
1017 mForceSetViewport = true;
1018 mForceSetScissor = true;
1020 if (!mDepthStencilInitialized || depthSize != mCurDepthSize)
1022 mCurDepthSize = depthSize;
1023 mForceSetRasterState = true;
1026 mCurStencilSize = stencilSize;
1028 for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++)
1030 mAppliedRenderTargetSerials[rtIndex] = renderTargetSerials[rtIndex];
1032 mAppliedDepthbufferSerial = depthbufferSerial;
1033 mAppliedStencilbufferSerial = stencilbufferSerial;
1034 mRenderTargetDescInitialized = true;
1035 mDepthStencilInitialized = true;
1041 GLenum Renderer11::applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances)
1043 TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS];
1044 GLenum err = mVertexDataManager->prepareVertexData(vertexAttributes, programBinary, first, count, attributes, instances);
1045 if (err != GL_NO_ERROR)
1050 return mInputLayoutCache.applyVertexBuffers(attributes, programBinary);
1053 GLenum Renderer11::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo)
1055 GLenum err = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo);
1057 if (err == GL_NO_ERROR)
1059 if (indexInfo->storage)
1061 if (indexInfo->serial != mAppliedStorageIBSerial || indexInfo->startOffset != mAppliedIBOffset)
1063 BufferStorage11 *storage = BufferStorage11::makeBufferStorage11(indexInfo->storage);
1064 IndexBuffer11* indexBuffer = IndexBuffer11::makeIndexBuffer11(indexInfo->indexBuffer);
1066 mDeviceContext->IASetIndexBuffer(storage->getBuffer(BUFFER_USAGE_INDEX), indexBuffer->getIndexFormat(), indexInfo->startOffset);
1068 mAppliedIBSerial = 0;
1069 mAppliedStorageIBSerial = storage->getSerial();
1070 mAppliedIBOffset = indexInfo->startOffset;
1073 else if (indexInfo->serial != mAppliedIBSerial || indexInfo->startOffset != mAppliedIBOffset)
1075 IndexBuffer11* indexBuffer = IndexBuffer11::makeIndexBuffer11(indexInfo->indexBuffer);
1077 mDeviceContext->IASetIndexBuffer(indexBuffer->getBuffer(), indexBuffer->getIndexFormat(), indexInfo->startOffset);
1079 mAppliedIBSerial = indexInfo->serial;
1080 mAppliedStorageIBSerial = 0;
1081 mAppliedIBOffset = indexInfo->startOffset;
1088 void Renderer11::drawArrays(GLenum mode, GLsizei count, GLsizei instances)
1090 if (mode == GL_LINE_LOOP)
1092 drawLineLoop(count, GL_NONE, NULL, 0, NULL);
1094 else if (mode == GL_TRIANGLE_FAN)
1096 drawTriangleFan(count, GL_NONE, NULL, 0, NULL, instances);
1098 else if (instances > 0)
1100 mDeviceContext->DrawInstanced(count, instances, 0, 0);
1104 mDeviceContext->Draw(count, 0);
1108 void Renderer11::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances)
1110 if (mode == GL_LINE_LOOP)
1112 drawLineLoop(count, type, indices, indexInfo.minIndex, elementArrayBuffer);
1114 else if (mode == GL_TRIANGLE_FAN)
1116 drawTriangleFan(count, type, indices, indexInfo.minIndex, elementArrayBuffer, instances);
1118 else if (instances > 0)
1120 mDeviceContext->DrawIndexedInstanced(count, instances, 0, -static_cast<int>(indexInfo.minIndex), 0);
1124 mDeviceContext->DrawIndexed(count, 0, -static_cast<int>(indexInfo.minIndex));
1128 void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer)
1130 // Get the raw indices for an indexed draw
1131 if (type != GL_NONE && elementArrayBuffer)
1133 gl::Buffer *indexBuffer = elementArrayBuffer;
1134 BufferStorage *storage = indexBuffer->getStorage();
1135 intptr_t offset = reinterpret_cast<intptr_t>(indices);
1136 indices = static_cast<const GLubyte*>(storage->getData()) + offset;
1141 mLineLoopIB = new StreamingIndexBufferInterface(this);
1142 if (!mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT))
1147 ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP.");
1148 return gl::error(GL_OUT_OF_MEMORY);
1152 // Checked by Renderer11::applyPrimitiveType
1155 if (static_cast<unsigned int>(count) + 1 > (std::numeric_limits<unsigned int>::max() / sizeof(unsigned int)))
1157 ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required.");
1158 return gl::error(GL_OUT_OF_MEMORY);
1161 const unsigned int spaceNeeded = (static_cast<unsigned int>(count) + 1) * sizeof(unsigned int);
1162 if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT))
1164 ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP.");
1165 return gl::error(GL_OUT_OF_MEMORY);
1168 void* mappedMemory = NULL;
1169 unsigned int offset;
1170 if (!mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset))
1172 ERR("Could not map index buffer for GL_LINE_LOOP.");
1173 return gl::error(GL_OUT_OF_MEMORY);
1176 unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory);
1177 unsigned int indexBufferOffset = offset;
1181 case GL_NONE: // Non-indexed draw
1182 for (int i = 0; i < count; i++)
1188 case GL_UNSIGNED_BYTE:
1189 for (int i = 0; i < count; i++)
1191 data[i] = static_cast<const GLubyte*>(indices)[i];
1193 data[count] = static_cast<const GLubyte*>(indices)[0];
1195 case GL_UNSIGNED_SHORT:
1196 for (int i = 0; i < count; i++)
1198 data[i] = static_cast<const GLushort*>(indices)[i];
1200 data[count] = static_cast<const GLushort*>(indices)[0];
1202 case GL_UNSIGNED_INT:
1203 for (int i = 0; i < count; i++)
1205 data[i] = static_cast<const GLuint*>(indices)[i];
1207 data[count] = static_cast<const GLuint*>(indices)[0];
1209 default: UNREACHABLE();
1212 if (!mLineLoopIB->unmapBuffer())
1214 ERR("Could not unmap index buffer for GL_LINE_LOOP.");
1215 return gl::error(GL_OUT_OF_MEMORY);
1218 if (mAppliedIBSerial != mLineLoopIB->getSerial() || mAppliedIBOffset != indexBufferOffset)
1220 IndexBuffer11 *indexBuffer = IndexBuffer11::makeIndexBuffer11(mLineLoopIB->getIndexBuffer());
1222 mDeviceContext->IASetIndexBuffer(indexBuffer->getBuffer(), indexBuffer->getIndexFormat(), indexBufferOffset);
1223 mAppliedIBSerial = mLineLoopIB->getSerial();
1224 mAppliedStorageIBSerial = 0;
1225 mAppliedIBOffset = indexBufferOffset;
1228 mDeviceContext->DrawIndexed(count + 1, 0, -minIndex);
1231 void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer, int instances)
1233 // Get the raw indices for an indexed draw
1234 if (type != GL_NONE && elementArrayBuffer)
1236 gl::Buffer *indexBuffer = elementArrayBuffer;
1237 BufferStorage *storage = indexBuffer->getStorage();
1238 intptr_t offset = reinterpret_cast<intptr_t>(indices);
1239 indices = static_cast<const GLubyte*>(storage->getData()) + offset;
1242 if (!mTriangleFanIB)
1244 mTriangleFanIB = new StreamingIndexBufferInterface(this);
1245 if (!mTriangleFanIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT))
1247 delete mTriangleFanIB;
1248 mTriangleFanIB = NULL;
1250 ERR("Could not create a scratch index buffer for GL_TRIANGLE_FAN.");
1251 return gl::error(GL_OUT_OF_MEMORY);
1255 // Checked by Renderer11::applyPrimitiveType
1258 const unsigned int numTris = count - 2;
1260 if (numTris > (std::numeric_limits<unsigned int>::max() / (sizeof(unsigned int) * 3)))
1262 ERR("Could not create a scratch index buffer for GL_TRIANGLE_FAN, too many indices required.");
1263 return gl::error(GL_OUT_OF_MEMORY);
1266 const unsigned int spaceNeeded = (numTris * 3) * sizeof(unsigned int);
1267 if (!mTriangleFanIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT))
1269 ERR("Could not reserve enough space in scratch index buffer for GL_TRIANGLE_FAN.");
1270 return gl::error(GL_OUT_OF_MEMORY);
1273 void* mappedMemory = NULL;
1274 unsigned int offset;
1275 if (!mTriangleFanIB->mapBuffer(spaceNeeded, &mappedMemory, &offset))
1277 ERR("Could not map scratch index buffer for GL_TRIANGLE_FAN.");
1278 return gl::error(GL_OUT_OF_MEMORY);
1281 unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory);
1282 unsigned int indexBufferOffset = offset;
1286 case GL_NONE: // Non-indexed draw
1287 for (unsigned int i = 0; i < numTris; i++)
1290 data[i*3 + 1] = i + 1;
1291 data[i*3 + 2] = i + 2;
1294 case GL_UNSIGNED_BYTE:
1295 for (unsigned int i = 0; i < numTris; i++)
1297 data[i*3 + 0] = static_cast<const GLubyte*>(indices)[0];
1298 data[i*3 + 1] = static_cast<const GLubyte*>(indices)[i + 1];
1299 data[i*3 + 2] = static_cast<const GLubyte*>(indices)[i + 2];
1302 case GL_UNSIGNED_SHORT:
1303 for (unsigned int i = 0; i < numTris; i++)
1305 data[i*3 + 0] = static_cast<const GLushort*>(indices)[0];
1306 data[i*3 + 1] = static_cast<const GLushort*>(indices)[i + 1];
1307 data[i*3 + 2] = static_cast<const GLushort*>(indices)[i + 2];
1310 case GL_UNSIGNED_INT:
1311 for (unsigned int i = 0; i < numTris; i++)
1313 data[i*3 + 0] = static_cast<const GLuint*>(indices)[0];
1314 data[i*3 + 1] = static_cast<const GLuint*>(indices)[i + 1];
1315 data[i*3 + 2] = static_cast<const GLuint*>(indices)[i + 2];
1318 default: UNREACHABLE();
1321 if (!mTriangleFanIB->unmapBuffer())
1323 ERR("Could not unmap scratch index buffer for GL_TRIANGLE_FAN.");
1324 return gl::error(GL_OUT_OF_MEMORY);
1327 if (mAppliedIBSerial != mTriangleFanIB->getSerial() || mAppliedIBOffset != indexBufferOffset)
1329 IndexBuffer11 *indexBuffer = IndexBuffer11::makeIndexBuffer11(mTriangleFanIB->getIndexBuffer());
1331 mDeviceContext->IASetIndexBuffer(indexBuffer->getBuffer(), indexBuffer->getIndexFormat(), indexBufferOffset);
1332 mAppliedIBSerial = mTriangleFanIB->getSerial();
1333 mAppliedStorageIBSerial = 0;
1334 mAppliedIBOffset = indexBufferOffset;
1339 mDeviceContext->DrawIndexedInstanced(numTris * 3, instances, 0, -minIndex, 0);
1343 mDeviceContext->DrawIndexed(numTris * 3, 0, -minIndex);
1347 void Renderer11::applyShaders(gl::ProgramBinary *programBinary)
1349 unsigned int programBinarySerial = programBinary->getSerial();
1350 const bool updateProgramState = (programBinarySerial != mAppliedProgramBinarySerial);
1352 if (updateProgramState)
1354 ShaderExecutable *vertexExe = programBinary->getVertexExecutable();
1355 ShaderExecutable *pixelExe = programBinary->getPixelExecutable();
1357 ID3D11VertexShader *vertexShader = NULL;
1358 if (vertexExe) vertexShader = ShaderExecutable11::makeShaderExecutable11(vertexExe)->getVertexShader();
1360 ID3D11PixelShader *pixelShader = NULL;
1361 if (pixelExe) pixelShader = ShaderExecutable11::makeShaderExecutable11(pixelExe)->getPixelShader();
1363 mDeviceContext->PSSetShader(pixelShader, NULL, 0);
1364 mDeviceContext->VSSetShader(vertexShader, NULL, 0);
1366 programBinary->dirtyAllUniforms();
1368 mAppliedProgramBinarySerial = programBinarySerial;
1371 // Only use the geometry shader currently for point sprite drawing
1372 const bool usesGeometryShader = (programBinary->usesGeometryShader() && mCurRasterState.pointDrawMode);
1374 if (updateProgramState || usesGeometryShader != mIsGeometryShaderActive)
1376 if (usesGeometryShader)
1378 ShaderExecutable *geometryExe = programBinary->getGeometryExecutable();
1379 ID3D11GeometryShader *geometryShader = ShaderExecutable11::makeShaderExecutable11(geometryExe)->getGeometryShader();
1380 mDeviceContext->GSSetShader(geometryShader, NULL, 0);
1384 mDeviceContext->GSSetShader(NULL, NULL, 0);
1387 mIsGeometryShaderActive = usesGeometryShader;
1391 void Renderer11::applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray *uniformArray)
1393 ShaderExecutable11 *vertexExecutable = ShaderExecutable11::makeShaderExecutable11(programBinary->getVertexExecutable());
1394 ShaderExecutable11 *pixelExecutable = ShaderExecutable11::makeShaderExecutable11(programBinary->getPixelExecutable());
1396 unsigned int totalRegisterCountVS = 0;
1397 unsigned int totalRegisterCountPS = 0;
1399 bool vertexUniformsDirty = false;
1400 bool pixelUniformsDirty = false;
1402 for (gl::UniformArray::const_iterator uniform_iterator = uniformArray->begin(); uniform_iterator != uniformArray->end(); uniform_iterator++)
1404 const gl::Uniform *uniform = *uniform_iterator;
1406 if (uniform->vsRegisterIndex >= 0)
1408 totalRegisterCountVS += uniform->registerCount;
1409 vertexUniformsDirty = vertexUniformsDirty || uniform->dirty;
1412 if (uniform->psRegisterIndex >= 0)
1414 totalRegisterCountPS += uniform->registerCount;
1415 pixelUniformsDirty = pixelUniformsDirty || uniform->dirty;
1419 ID3D11Buffer *vertexConstantBuffer = vertexExecutable->getConstantBuffer(mDevice, totalRegisterCountVS);
1420 ID3D11Buffer *pixelConstantBuffer = pixelExecutable->getConstantBuffer(mDevice, totalRegisterCountPS);
1422 float (*mapVS)[4] = NULL;
1423 float (*mapPS)[4] = NULL;
1425 if (totalRegisterCountVS > 0 && vertexUniformsDirty)
1427 D3D11_MAPPED_SUBRESOURCE map = {0};
1428 HRESULT result = mDeviceContext->Map(vertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
1429 ASSERT(SUCCEEDED(result));
1430 mapVS = (float(*)[4])map.pData;
1433 if (totalRegisterCountPS > 0 && pixelUniformsDirty)
1435 D3D11_MAPPED_SUBRESOURCE map = {0};
1436 HRESULT result = mDeviceContext->Map(pixelConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
1437 ASSERT(SUCCEEDED(result));
1438 mapPS = (float(*)[4])map.pData;
1441 for (gl::UniformArray::iterator uniform_iterator = uniformArray->begin(); uniform_iterator != uniformArray->end(); uniform_iterator++)
1443 gl::Uniform *uniform = *uniform_iterator;
1445 if (uniform->type != GL_SAMPLER_2D && uniform->type != GL_SAMPLER_CUBE)
1447 if (uniform->vsRegisterIndex >= 0 && mapVS)
1449 memcpy(mapVS + uniform->vsRegisterIndex, uniform->data, uniform->registerCount * sizeof(float[4]));
1452 if (uniform->psRegisterIndex >= 0 && mapPS)
1454 memcpy(mapPS + uniform->psRegisterIndex, uniform->data, uniform->registerCount * sizeof(float[4]));
1458 uniform->dirty = false;
1463 mDeviceContext->Unmap(vertexConstantBuffer, 0);
1468 mDeviceContext->Unmap(pixelConstantBuffer, 0);
1471 if (mCurrentVertexConstantBuffer != vertexConstantBuffer)
1473 mDeviceContext->VSSetConstantBuffers(0, 1, &vertexConstantBuffer);
1474 mCurrentVertexConstantBuffer = vertexConstantBuffer;
1477 if (mCurrentPixelConstantBuffer != pixelConstantBuffer)
1479 mDeviceContext->PSSetConstantBuffers(0, 1, &pixelConstantBuffer);
1480 mCurrentPixelConstantBuffer = pixelConstantBuffer;
1484 if (!mDriverConstantBufferVS)
1486 D3D11_BUFFER_DESC constantBufferDescription = {0};
1487 constantBufferDescription.ByteWidth = sizeof(dx_VertexConstants);
1488 constantBufferDescription.Usage = D3D11_USAGE_DEFAULT;
1489 constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
1490 constantBufferDescription.CPUAccessFlags = 0;
1491 constantBufferDescription.MiscFlags = 0;
1492 constantBufferDescription.StructureByteStride = 0;
1494 HRESULT result = mDevice->CreateBuffer(&constantBufferDescription, NULL, &mDriverConstantBufferVS);
1495 ASSERT(SUCCEEDED(result));
1497 mDeviceContext->VSSetConstantBuffers(1, 1, &mDriverConstantBufferVS);
1500 if (!mDriverConstantBufferPS)
1502 D3D11_BUFFER_DESC constantBufferDescription = {0};
1503 constantBufferDescription.ByteWidth = sizeof(dx_PixelConstants);
1504 constantBufferDescription.Usage = D3D11_USAGE_DEFAULT;
1505 constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
1506 constantBufferDescription.CPUAccessFlags = 0;
1507 constantBufferDescription.MiscFlags = 0;
1508 constantBufferDescription.StructureByteStride = 0;
1510 HRESULT result = mDevice->CreateBuffer(&constantBufferDescription, NULL, &mDriverConstantBufferPS);
1511 ASSERT(SUCCEEDED(result));
1513 mDeviceContext->PSSetConstantBuffers(1, 1, &mDriverConstantBufferPS);
1516 if (memcmp(&mVertexConstants, &mAppliedVertexConstants, sizeof(dx_VertexConstants)) != 0)
1518 mDeviceContext->UpdateSubresource(mDriverConstantBufferVS, 0, NULL, &mVertexConstants, 16, 0);
1519 memcpy(&mAppliedVertexConstants, &mVertexConstants, sizeof(dx_VertexConstants));
1522 if (memcmp(&mPixelConstants, &mAppliedPixelConstants, sizeof(dx_PixelConstants)) != 0)
1524 mDeviceContext->UpdateSubresource(mDriverConstantBufferPS, 0, NULL, &mPixelConstants, 16, 0);
1525 memcpy(&mAppliedPixelConstants, &mPixelConstants, sizeof(dx_PixelConstants));
1528 // needed for the point sprite geometry shader
1529 if (mCurrentGeometryConstantBuffer != mDriverConstantBufferPS)
1531 mDeviceContext->GSSetConstantBuffers(0, 1, &mDriverConstantBufferPS);
1532 mCurrentGeometryConstantBuffer = mDriverConstantBufferPS;
1536 void Renderer11::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer)
1538 gl::Renderbuffer *firstRenderbuffer = frameBuffer->getFirstColorbuffer();
1539 GLenum internalFormat = firstRenderbuffer ? firstRenderbuffer->getInternalFormat() : GL_NONE;
1541 bool needMaskedColorClear = (clearParams.mask & GL_COLOR_BUFFER_BIT) &&
1542 ((!clearParams.colorMaskRed && gl::GetRedSize(internalFormat) > 0) ||
1543 (!clearParams.colorMaskGreen && gl::GetGreenSize(internalFormat) > 0) ||
1544 (!clearParams.colorMaskBlue && gl::GetBlueSize(internalFormat) > 0) ||
1545 (!clearParams.colorMaskAlpha && gl::GetAlphaSize(internalFormat) > 0));
1547 unsigned int stencilUnmasked = 0x0;
1548 if (frameBuffer->hasStencil())
1550 unsigned int stencilSize = gl::GetStencilSize(frameBuffer->getStencilbuffer()->getActualFormat());
1551 stencilUnmasked = (0x1 << stencilSize) - 1;
1553 bool needMaskedStencilClear = (clearParams.mask & GL_STENCIL_BUFFER_BIT) &&
1554 (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked;
1556 bool needScissoredClear = mScissorEnabled && (mCurScissor.x > 0 || mCurScissor.y > 0 ||
1557 mCurScissor.x + mCurScissor.width < mRenderTargetDesc.width ||
1558 mCurScissor.y + mCurScissor.height < mRenderTargetDesc.height);
1560 if (needMaskedColorClear || needMaskedStencilClear || needScissoredClear)
1562 maskedClear(clearParams, frameBuffer);
1566 if (clearParams.mask & GL_COLOR_BUFFER_BIT)
1568 for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
1570 if (frameBuffer->isEnabledColorAttachment(colorAttachment))
1572 gl::Renderbuffer *renderbufferObject = frameBuffer->getColorbuffer(colorAttachment);
1573 if (renderbufferObject)
1575 RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(renderbufferObject->getRenderTarget());
1578 ERR("render target pointer unexpectedly null.");
1582 ID3D11RenderTargetView *framebufferRTV = renderTarget->getRenderTargetView();
1583 if (!framebufferRTV)
1585 ERR("render target view pointer unexpectedly null.");
1589 GLenum format = renderbufferObject->getInternalFormat();
1591 const float clearValues[4] = { (gl::GetRedSize(format) > 0) ? clearParams.colorClearValue.red : 0.0f,
1592 (gl::GetGreenSize(format) > 0) ? clearParams.colorClearValue.green : 0.0f,
1593 (gl::GetBlueSize(format) > 0) ? clearParams.colorClearValue.blue : 0.0f,
1594 (gl::GetAlphaSize(format) > 0) ? clearParams.colorClearValue.alpha : 1.0f };
1595 mDeviceContext->ClearRenderTargetView(framebufferRTV, clearValues);
1600 if (clearParams.mask & GL_DEPTH_BUFFER_BIT || clearParams.mask & GL_STENCIL_BUFFER_BIT)
1602 gl::Renderbuffer *renderbufferObject = frameBuffer->getDepthOrStencilbuffer();
1603 if (renderbufferObject)
1605 RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(renderbufferObject->getDepthStencil());
1608 ERR("render target pointer unexpectedly null.");
1612 ID3D11DepthStencilView *framebufferDSV = renderTarget->getDepthStencilView();
1613 if (!framebufferDSV)
1615 ERR("depth stencil view pointer unexpectedly null.");
1619 UINT clearFlags = 0;
1620 if (clearParams.mask & GL_DEPTH_BUFFER_BIT)
1622 clearFlags |= D3D11_CLEAR_DEPTH;
1624 if (clearParams.mask & GL_STENCIL_BUFFER_BIT)
1626 clearFlags |= D3D11_CLEAR_STENCIL;
1629 float depthClear = gl::clamp01(clearParams.depthClearValue);
1630 UINT8 stencilClear = clearParams.stencilClearValue & 0x000000FF;
1632 mDeviceContext->ClearDepthStencilView(framebufferDSV, clearFlags, depthClear, stencilClear);
1638 void Renderer11::maskedClear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer)
1642 if (!mClearResourcesInitialized)
1644 ASSERT(!mClearVB && !mClearVS && !mClearSinglePS && !mClearMultiplePS && !mClearScissorRS && !mClearNoScissorRS);
1646 D3D11_BUFFER_DESC vbDesc;
1647 vbDesc.ByteWidth = sizeof(d3d11::PositionDepthColorVertex) * 4;
1648 vbDesc.Usage = D3D11_USAGE_DYNAMIC;
1649 vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
1650 vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
1651 vbDesc.MiscFlags = 0;
1652 vbDesc.StructureByteStride = 0;
1654 result = mDevice->CreateBuffer(&vbDesc, NULL, &mClearVB);
1655 ASSERT(SUCCEEDED(result));
1656 d3d11::SetDebugName(mClearVB, "Renderer11 masked clear vertex buffer");
1658 D3D11_INPUT_ELEMENT_DESC quadLayout[] =
1660 { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
1661 { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
1664 result = mDevice->CreateInputLayout(quadLayout, 2, g_VS_Clear, sizeof(g_VS_Clear), &mClearIL);
1665 ASSERT(SUCCEEDED(result));
1666 d3d11::SetDebugName(mClearIL, "Renderer11 masked clear input layout");
1668 result = mDevice->CreateVertexShader(g_VS_Clear, sizeof(g_VS_Clear), NULL, &mClearVS);
1669 ASSERT(SUCCEEDED(result));
1670 d3d11::SetDebugName(mClearVS, "Renderer11 masked clear vertex shader");
1672 result = mDevice->CreatePixelShader(g_PS_ClearSingle, sizeof(g_PS_ClearSingle), NULL, &mClearSinglePS);
1673 ASSERT(SUCCEEDED(result));
1674 d3d11::SetDebugName(mClearSinglePS, "Renderer11 masked clear pixel shader (1 RT)");
1676 result = mDevice->CreatePixelShader(g_PS_ClearMultiple, sizeof(g_PS_ClearMultiple), NULL, &mClearMultiplePS);
1677 ASSERT(SUCCEEDED(result));
1678 d3d11::SetDebugName(mClearMultiplePS, "Renderer11 masked clear pixel shader (MRT)");
1680 D3D11_RASTERIZER_DESC rsScissorDesc;
1681 rsScissorDesc.FillMode = D3D11_FILL_SOLID;
1682 rsScissorDesc.CullMode = D3D11_CULL_NONE;
1683 rsScissorDesc.FrontCounterClockwise = FALSE;
1684 rsScissorDesc.DepthBias = 0;
1685 rsScissorDesc.DepthBiasClamp = 0.0f;
1686 rsScissorDesc.SlopeScaledDepthBias = 0.0f;
1687 rsScissorDesc.DepthClipEnable = FALSE;
1688 rsScissorDesc.ScissorEnable = TRUE;
1689 rsScissorDesc.MultisampleEnable = FALSE;
1690 rsScissorDesc.AntialiasedLineEnable = FALSE;
1692 result = mDevice->CreateRasterizerState(&rsScissorDesc, &mClearScissorRS);
1693 ASSERT(SUCCEEDED(result));
1694 d3d11::SetDebugName(mClearScissorRS, "Renderer11 masked clear scissor rasterizer state");
1696 D3D11_RASTERIZER_DESC rsNoScissorDesc;
1697 rsNoScissorDesc.FillMode = D3D11_FILL_SOLID;
1698 rsNoScissorDesc.CullMode = D3D11_CULL_NONE;
1699 rsNoScissorDesc.FrontCounterClockwise = FALSE;
1700 rsNoScissorDesc.DepthBias = 0;
1701 rsNoScissorDesc.DepthBiasClamp = 0.0f;
1702 rsNoScissorDesc.SlopeScaledDepthBias = 0.0f;
1703 rsNoScissorDesc.DepthClipEnable = FALSE;
1704 rsNoScissorDesc.ScissorEnable = FALSE;
1705 rsNoScissorDesc.MultisampleEnable = FALSE;
1706 rsNoScissorDesc.AntialiasedLineEnable = FALSE;
1708 result = mDevice->CreateRasterizerState(&rsNoScissorDesc, &mClearNoScissorRS);
1709 ASSERT(SUCCEEDED(result));
1710 d3d11::SetDebugName(mClearNoScissorRS, "Renderer11 masked clear no scissor rasterizer state");
1712 mClearResourcesInitialized = true;
1715 // Prepare the depth stencil state to write depth values if the depth should be cleared
1716 // and stencil values if the stencil should be cleared
1717 gl::DepthStencilState glDSState;
1718 glDSState.depthTest = (clearParams.mask & GL_DEPTH_BUFFER_BIT) != 0;
1719 glDSState.depthFunc = GL_ALWAYS;
1720 glDSState.depthMask = (clearParams.mask & GL_DEPTH_BUFFER_BIT) != 0;
1721 glDSState.stencilTest = (clearParams.mask & GL_STENCIL_BUFFER_BIT) != 0;
1722 glDSState.stencilFunc = GL_ALWAYS;
1723 glDSState.stencilMask = 0;
1724 glDSState.stencilFail = GL_REPLACE;
1725 glDSState.stencilPassDepthFail = GL_REPLACE;
1726 glDSState.stencilPassDepthPass = GL_REPLACE;
1727 glDSState.stencilWritemask = clearParams.stencilWriteMask;
1728 glDSState.stencilBackFunc = GL_ALWAYS;
1729 glDSState.stencilBackMask = 0;
1730 glDSState.stencilBackFail = GL_REPLACE;
1731 glDSState.stencilBackPassDepthFail = GL_REPLACE;
1732 glDSState.stencilBackPassDepthPass = GL_REPLACE;
1733 glDSState.stencilBackWritemask = clearParams.stencilWriteMask;
1735 int stencilClear = clearParams.stencilClearValue & 0x000000FF;
1737 ID3D11DepthStencilState *dsState = mStateCache.getDepthStencilState(glDSState);
1739 // Prepare the blend state to use a write mask if the color buffer should be cleared
1740 gl::BlendState glBlendState;
1741 glBlendState.blend = false;
1742 glBlendState.sourceBlendRGB = GL_ONE;
1743 glBlendState.destBlendRGB = GL_ZERO;
1744 glBlendState.sourceBlendAlpha = GL_ONE;
1745 glBlendState.destBlendAlpha = GL_ZERO;
1746 glBlendState.blendEquationRGB = GL_FUNC_ADD;
1747 glBlendState.blendEquationAlpha = GL_FUNC_ADD;
1748 glBlendState.colorMaskRed = (clearParams.mask & GL_COLOR_BUFFER_BIT) ? clearParams.colorMaskRed : false;
1749 glBlendState.colorMaskGreen = (clearParams.mask & GL_COLOR_BUFFER_BIT) ? clearParams.colorMaskGreen : false;
1750 glBlendState.colorMaskBlue = (clearParams.mask & GL_COLOR_BUFFER_BIT) ? clearParams.colorMaskBlue : false;
1751 glBlendState.colorMaskAlpha = (clearParams.mask & GL_COLOR_BUFFER_BIT) ? clearParams.colorMaskAlpha : false;
1752 glBlendState.sampleAlphaToCoverage = false;
1753 glBlendState.dither = false;
1755 static const float blendFactors[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
1756 static const UINT sampleMask = 0xFFFFFFFF;
1758 ID3D11BlendState *blendState = mStateCache.getBlendState(frameBuffer, glBlendState);
1761 D3D11_MAPPED_SUBRESOURCE mappedResource;
1762 result = mDeviceContext->Map(mClearVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
1765 ERR("Failed to map masked clear vertex buffer, HRESULT: 0x%X.", result);
1769 d3d11::PositionDepthColorVertex *vertices = reinterpret_cast<d3d11::PositionDepthColorVertex*>(mappedResource.pData);
1771 float depthClear = gl::clamp01(clearParams.depthClearValue);
1772 d3d11::SetPositionDepthColorVertex(&vertices[0], -1.0f, 1.0f, depthClear, clearParams.colorClearValue);
1773 d3d11::SetPositionDepthColorVertex(&vertices[1], -1.0f, -1.0f, depthClear, clearParams.colorClearValue);
1774 d3d11::SetPositionDepthColorVertex(&vertices[2], 1.0f, 1.0f, depthClear, clearParams.colorClearValue);
1775 d3d11::SetPositionDepthColorVertex(&vertices[3], 1.0f, -1.0f, depthClear, clearParams.colorClearValue);
1777 mDeviceContext->Unmap(mClearVB, 0);
1780 mDeviceContext->OMSetBlendState(blendState, blendFactors, sampleMask);
1781 mDeviceContext->OMSetDepthStencilState(dsState, stencilClear);
1782 mDeviceContext->RSSetState(mScissorEnabled ? mClearScissorRS : mClearNoScissorRS);
1785 ID3D11PixelShader *pixelShader = frameBuffer->usingExtendedDrawBuffers() ? mClearMultiplePS : mClearSinglePS;
1787 mDeviceContext->IASetInputLayout(mClearIL);
1788 mDeviceContext->VSSetShader(mClearVS, NULL, 0);
1789 mDeviceContext->PSSetShader(pixelShader, NULL, 0);
1790 mDeviceContext->GSSetShader(NULL, NULL, 0);
1792 // Apply vertex buffer
1793 static UINT stride = sizeof(d3d11::PositionDepthColorVertex);
1794 static UINT startIdx = 0;
1795 mDeviceContext->IASetVertexBuffers(0, 1, &mClearVB, &stride, &startIdx);
1796 mDeviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
1798 // Draw the clear quad
1799 mDeviceContext->Draw(4, 0);
1802 markAllStateDirty();
1805 void Renderer11::markAllStateDirty()
1807 for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++)
1809 mAppliedRenderTargetSerials[rtIndex] = 0;
1811 mAppliedDepthbufferSerial = 0;
1812 mAppliedStencilbufferSerial = 0;
1813 mDepthStencilInitialized = false;
1814 mRenderTargetDescInitialized = false;
1816 for (int i = 0; i < gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; i++)
1818 mForceSetVertexSamplerStates[i] = true;
1819 mCurVertexTextureSerials[i] = 0;
1821 for (int i = 0; i < gl::MAX_TEXTURE_IMAGE_UNITS; i++)
1823 mForceSetPixelSamplerStates[i] = true;
1824 mCurPixelTextureSerials[i] = 0;
1827 mForceSetBlendState = true;
1828 mForceSetRasterState = true;
1829 mForceSetDepthStencilState = true;
1830 mForceSetScissor = true;
1831 mForceSetViewport = true;
1833 mAppliedIBSerial = 0;
1834 mAppliedStorageIBSerial = 0;
1835 mAppliedIBOffset = 0;
1837 mAppliedProgramBinarySerial = 0;
1838 memset(&mAppliedVertexConstants, 0, sizeof(dx_VertexConstants));
1839 memset(&mAppliedPixelConstants, 0, sizeof(dx_PixelConstants));
1841 mInputLayoutCache.markDirty();
1843 mCurrentVertexConstantBuffer = NULL;
1844 mCurrentPixelConstantBuffer = NULL;
1845 mCurrentGeometryConstantBuffer = NULL;
1847 mCurrentPrimitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
1850 void Renderer11::releaseDeviceResources()
1852 mStateCache.clear();
1853 mInputLayoutCache.clear();
1855 delete mVertexDataManager;
1856 mVertexDataManager = NULL;
1858 delete mIndexDataManager;
1859 mIndexDataManager = NULL;
1864 delete mTriangleFanIB;
1865 mTriangleFanIB = NULL;
1867 SafeRelease(mCopyVB);
1868 SafeRelease(mCopySampler);
1869 SafeRelease(mCopyIL);
1870 SafeRelease(mCopyIL);
1871 SafeRelease(mCopyVS);
1872 SafeRelease(mCopyRGBAPS);
1873 SafeRelease(mCopyRGBPS);
1874 SafeRelease(mCopyLumPS);
1875 SafeRelease(mCopyLumAlphaPS);
1877 mCopyResourcesInitialized = false;
1879 SafeRelease(mClearVB);
1880 SafeRelease(mClearIL);
1881 SafeRelease(mClearVS);
1882 SafeRelease(mClearSinglePS);
1883 SafeRelease(mClearMultiplePS);
1884 SafeRelease(mClearScissorRS);
1885 SafeRelease(mClearNoScissorRS);
1887 mClearResourcesInitialized = false;
1889 SafeRelease(mDriverConstantBufferVS);
1890 SafeRelease(mDriverConstantBufferPS);
1891 SafeRelease(mSyncQuery);
1894 void Renderer11::notifyDeviceLost()
1897 mDisplay->notifyDeviceLost();
1900 bool Renderer11::isDeviceLost()
1905 // set notify to true to broadcast a message to all contexts of the device loss
1906 bool Renderer11::testDeviceLost(bool notify)
1908 bool isLost = false;
1910 // GetRemovedReason is used to test if the device is removed
1911 HRESULT result = mDevice->GetDeviceRemovedReason();
1912 isLost = d3d11::isDeviceLostError(result);
1916 // Log error if this is a new device lost event
1917 if (mDeviceLost == false)
1919 ERR("The D3D11 device was removed: 0x%08X", result);
1922 // ensure we note the device loss --
1923 // we'll probably get this done again by notifyDeviceLost
1924 // but best to remember it!
1925 // Note that we don't want to clear the device loss status here
1926 // -- this needs to be done by resetDevice
1937 bool Renderer11::testDeviceResettable()
1939 // determine if the device is resettable by creating a dummy device
1940 PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice");
1942 if (D3D11CreateDevice == NULL)
1947 D3D_FEATURE_LEVEL featureLevels[] =
1949 D3D_FEATURE_LEVEL_11_0,
1950 D3D_FEATURE_LEVEL_10_1,
1951 D3D_FEATURE_LEVEL_10_0,
1954 ID3D11Device* dummyDevice;
1955 D3D_FEATURE_LEVEL dummyFeatureLevel;
1956 ID3D11DeviceContext* dummyContext;
1958 HRESULT result = D3D11CreateDevice(NULL,
1959 D3D_DRIVER_TYPE_HARDWARE,
1962 D3D11_CREATE_DEVICE_DEBUG,
1967 ArraySize(featureLevels),
1973 if (!mDevice || FAILED(result))
1978 dummyContext->Release();
1979 dummyDevice->Release();
1984 void Renderer11::release()
1986 releaseDeviceResources();
1990 mDxgiFactory->Release();
1991 mDxgiFactory = NULL;
1996 mDxgiAdapter->Release();
1997 mDxgiAdapter = NULL;
2002 mDeviceContext->ClearState();
2003 mDeviceContext->Flush();
2004 mDeviceContext->Release();
2005 mDeviceContext = NULL;
2016 FreeLibrary(mD3d11Module);
2017 mD3d11Module = NULL;
2022 FreeLibrary(mDxgiModule);
2027 bool Renderer11::resetDevice()
2029 // recreate everything
2031 EGLint result = initialize();
2033 if (result != EGL_SUCCESS)
2035 ERR("Could not reinitialize D3D11 device: %08X", result);
2039 mDeviceLost = false;
2044 DWORD Renderer11::getAdapterVendor() const
2046 return mAdapterDescription.VendorId;
2049 std::string Renderer11::getRendererDescription() const
2051 std::ostringstream rendererString;
2053 rendererString << mDescription;
2054 rendererString << " Direct3D11";
2056 rendererString << " vs_" << getMajorShaderModel() << "_" << getMinorShaderModel();
2057 rendererString << " ps_" << getMajorShaderModel() << "_" << getMinorShaderModel();
2059 return rendererString.str();
2062 GUID Renderer11::getAdapterIdentifier() const
2064 // Use the adapter LUID as our adapter ID
2065 // This number is local to a machine is only guaranteed to be unique between restarts
2066 META_ASSERT(sizeof(LUID) <= sizeof(GUID));
2067 GUID adapterId = {0};
2068 memcpy(&adapterId, &mAdapterDescription.AdapterLuid, sizeof(LUID));
2072 bool Renderer11::getBGRATextureSupport() const
2074 return mBGRATextureSupport;
2077 bool Renderer11::getDXT1TextureSupport()
2079 return mDXT1TextureSupport;
2082 bool Renderer11::getDXT3TextureSupport()
2084 return mDXT3TextureSupport;
2087 bool Renderer11::getDXT5TextureSupport()
2089 return mDXT5TextureSupport;
2092 bool Renderer11::getDepthTextureSupport() const
2094 return mDepthTextureSupport;
2097 bool Renderer11::getFloat32TextureSupport(bool *filtering, bool *renderable)
2099 *renderable = mFloat32RenderSupport;
2100 *filtering = mFloat32FilterSupport;
2101 return mFloat32TextureSupport;
2104 bool Renderer11::getFloat16TextureSupport(bool *filtering, bool *renderable)
2106 *renderable = mFloat16RenderSupport;
2107 *filtering = mFloat16FilterSupport;
2108 return mFloat16TextureSupport;
2111 bool Renderer11::getLuminanceTextureSupport()
2116 bool Renderer11::getLuminanceAlphaTextureSupport()
2121 bool Renderer11::getTextureFilterAnisotropySupport() const
2126 float Renderer11::getTextureMaxAnisotropy() const
2128 switch (mFeatureLevel)
2130 case D3D_FEATURE_LEVEL_11_0:
2131 return D3D11_MAX_MAXANISOTROPY;
2132 case D3D_FEATURE_LEVEL_10_1:
2133 case D3D_FEATURE_LEVEL_10_0:
2134 return D3D10_MAX_MAXANISOTROPY;
2135 default: UNREACHABLE();
2140 bool Renderer11::getEventQuerySupport()
2145 Range Renderer11::getViewportBounds() const
2147 switch (mFeatureLevel)
2149 case D3D_FEATURE_LEVEL_11_0:
2150 return Range(D3D11_VIEWPORT_BOUNDS_MIN, D3D11_VIEWPORT_BOUNDS_MAX);
2151 case D3D_FEATURE_LEVEL_10_1:
2152 case D3D_FEATURE_LEVEL_10_0:
2153 return Range(D3D10_VIEWPORT_BOUNDS_MIN, D3D10_VIEWPORT_BOUNDS_MAX);
2154 default: UNREACHABLE();
2159 unsigned int Renderer11::getMaxVertexTextureImageUnits() const
2161 META_ASSERT(MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 <= gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS);
2162 switch (mFeatureLevel)
2164 case D3D_FEATURE_LEVEL_11_0:
2165 case D3D_FEATURE_LEVEL_10_1:
2166 case D3D_FEATURE_LEVEL_10_0:
2167 return MAX_TEXTURE_IMAGE_UNITS_VTF_SM4;
2168 default: UNREACHABLE();
2173 unsigned int Renderer11::getMaxCombinedTextureImageUnits() const
2175 return gl::MAX_TEXTURE_IMAGE_UNITS + getMaxVertexTextureImageUnits();
2178 unsigned int Renderer11::getReservedVertexUniformVectors() const
2180 return 0; // Driver uniforms are stored in a separate constant buffer
2183 unsigned int Renderer11::getReservedFragmentUniformVectors() const
2185 return 0; // Driver uniforms are stored in a separate constant buffer
2188 unsigned int Renderer11::getMaxVertexUniformVectors() const
2190 META_ASSERT(MAX_VERTEX_UNIFORM_VECTORS_D3D11 <= D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT);
2191 ASSERT(mFeatureLevel >= D3D_FEATURE_LEVEL_10_0);
2192 return MAX_VERTEX_UNIFORM_VECTORS_D3D11;
2195 unsigned int Renderer11::getMaxFragmentUniformVectors() const
2197 META_ASSERT(MAX_FRAGMENT_UNIFORM_VECTORS_D3D11 <= D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT);
2198 ASSERT(mFeatureLevel >= D3D_FEATURE_LEVEL_10_0);
2199 return MAX_FRAGMENT_UNIFORM_VECTORS_D3D11;
2202 unsigned int Renderer11::getMaxVaryingVectors() const
2204 META_ASSERT(gl::IMPLEMENTATION_MAX_VARYING_VECTORS == D3D11_VS_OUTPUT_REGISTER_COUNT);
2205 switch (mFeatureLevel)
2207 case D3D_FEATURE_LEVEL_11_0:
2208 return D3D11_VS_OUTPUT_REGISTER_COUNT;
2209 case D3D_FEATURE_LEVEL_10_1:
2210 case D3D_FEATURE_LEVEL_10_0:
2211 return D3D10_VS_OUTPUT_REGISTER_COUNT;
2212 default: UNREACHABLE();
2217 bool Renderer11::getNonPower2TextureSupport() const
2219 switch (mFeatureLevel)
2221 case D3D_FEATURE_LEVEL_11_0:
2222 case D3D_FEATURE_LEVEL_10_1:
2223 case D3D_FEATURE_LEVEL_10_0:
2225 default: UNREACHABLE();
2230 bool Renderer11::getOcclusionQuerySupport() const
2232 switch (mFeatureLevel)
2234 case D3D_FEATURE_LEVEL_11_0:
2235 case D3D_FEATURE_LEVEL_10_1:
2236 case D3D_FEATURE_LEVEL_10_0:
2238 default: UNREACHABLE();
2243 bool Renderer11::getInstancingSupport() const
2245 switch (mFeatureLevel)
2247 case D3D_FEATURE_LEVEL_11_0:
2248 case D3D_FEATURE_LEVEL_10_1:
2249 case D3D_FEATURE_LEVEL_10_0:
2251 default: UNREACHABLE();
2256 bool Renderer11::getShareHandleSupport() const
2258 // We only currently support share handles with BGRA surfaces, because
2259 // chrome needs BGRA. Once chrome fixes this, we should always support them.
2260 // PIX doesn't seem to support using share handles, so disable them.
2261 return getBGRATextureSupport() && !gl::perfActive();
2264 bool Renderer11::getDerivativeInstructionSupport() const
2266 switch (mFeatureLevel)
2268 case D3D_FEATURE_LEVEL_11_0:
2269 case D3D_FEATURE_LEVEL_10_1:
2270 case D3D_FEATURE_LEVEL_10_0:
2272 default: UNREACHABLE();
2277 bool Renderer11::getPostSubBufferSupport() const
2279 // D3D11 does not support present with dirty rectangles until D3D11.1 and DXGI 1.2.
2283 int Renderer11::getMajorShaderModel() const
2285 switch (mFeatureLevel)
2287 case D3D_FEATURE_LEVEL_11_0: return D3D11_SHADER_MAJOR_VERSION; // 5
2288 case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SHADER_MAJOR_VERSION; // 4
2289 case D3D_FEATURE_LEVEL_10_0: return D3D10_SHADER_MAJOR_VERSION; // 4
2290 default: UNREACHABLE(); return 0;
2294 int Renderer11::getMinorShaderModel() const
2296 switch (mFeatureLevel)
2298 case D3D_FEATURE_LEVEL_11_0: return D3D11_SHADER_MINOR_VERSION; // 0
2299 case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SHADER_MINOR_VERSION; // 1
2300 case D3D_FEATURE_LEVEL_10_0: return D3D10_SHADER_MINOR_VERSION; // 0
2301 default: UNREACHABLE(); return 0;
2305 float Renderer11::getMaxPointSize() const
2307 // choose a reasonable maximum. we enforce this in the shader.
2308 // (nb: on a Radeon 2600xt, DX9 reports a 256 max point size)
2312 int Renderer11::getMaxViewportDimension() const
2314 // Maximum viewport size must be at least as large as the largest render buffer (or larger).
2315 // In our case return the maximum texture size, which is the maximum render buffer size.
2316 META_ASSERT(D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION * 2 - 1 <= D3D11_VIEWPORT_BOUNDS_MAX);
2317 META_ASSERT(D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION * 2 - 1 <= D3D10_VIEWPORT_BOUNDS_MAX);
2319 switch (mFeatureLevel)
2321 case D3D_FEATURE_LEVEL_11_0:
2322 return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 16384
2323 case D3D_FEATURE_LEVEL_10_1:
2324 case D3D_FEATURE_LEVEL_10_0:
2325 return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 8192
2326 default: UNREACHABLE();
2331 int Renderer11::getMaxTextureWidth() const
2333 switch (mFeatureLevel)
2335 case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 16384
2336 case D3D_FEATURE_LEVEL_10_1:
2337 case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 8192
2338 default: UNREACHABLE(); return 0;
2342 int Renderer11::getMaxTextureHeight() const
2344 switch (mFeatureLevel)
2346 case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 16384
2347 case D3D_FEATURE_LEVEL_10_1:
2348 case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 8192
2349 default: UNREACHABLE(); return 0;
2353 bool Renderer11::get32BitIndexSupport() const
2355 switch (mFeatureLevel)
2357 case D3D_FEATURE_LEVEL_11_0:
2358 case D3D_FEATURE_LEVEL_10_1:
2359 case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP >= 32; // true
2360 default: UNREACHABLE(); return false;
2364 int Renderer11::getMinSwapInterval() const
2369 int Renderer11::getMaxSwapInterval() const
2374 int Renderer11::getMaxSupportedSamples() const
2376 return mMaxSupportedSamples;
2379 int Renderer11::getNearestSupportedSamples(DXGI_FORMAT format, unsigned int requested) const
2386 MultisampleSupportMap::const_iterator iter = mMultisampleSupportMap.find(format);
2387 if (iter != mMultisampleSupportMap.end())
2389 const MultisampleSupportInfo& info = iter->second;
2390 for (unsigned int i = requested - 1; i < D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; i++)
2392 if (info.qualityLevels[i] > 0)
2402 unsigned int Renderer11::getMaxRenderTargets() const
2404 META_ASSERT(D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT <= gl::IMPLEMENTATION_MAX_DRAW_BUFFERS);
2405 META_ASSERT(D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT <= gl::IMPLEMENTATION_MAX_DRAW_BUFFERS);
2407 switch (mFeatureLevel)
2409 case D3D_FEATURE_LEVEL_11_0:
2410 return D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; // 8
2411 case D3D_FEATURE_LEVEL_10_1:
2412 case D3D_FEATURE_LEVEL_10_0:
2413 // Feature level 10.0 and 10.1 cards perform very poorly when the pixel shader
2414 // outputs to multiple RTs that are not bound.
2415 // TODO: Remove pixel shader outputs for render targets that are not bound.
2423 bool Renderer11::copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source)
2427 TextureStorage11_2D *source11 = TextureStorage11_2D::makeTextureStorage11_2D(source->getStorageInstance());
2428 TextureStorage11_2D *dest11 = TextureStorage11_2D::makeTextureStorage11_2D(dest->getStorageInstance());
2430 mDeviceContext->CopyResource(dest11->getBaseTexture(), source11->getBaseTexture());
2437 bool Renderer11::copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source)
2441 TextureStorage11_Cube *source11 = TextureStorage11_Cube::makeTextureStorage11_Cube(source->getStorageInstance());
2442 TextureStorage11_Cube *dest11 = TextureStorage11_Cube::makeTextureStorage11_Cube(dest->getStorageInstance());
2444 mDeviceContext->CopyResource(dest11->getBaseTexture(), source11->getBaseTexture());
2451 bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
2452 GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level)
2454 gl::Renderbuffer *colorbuffer = framebuffer->getReadColorbuffer();
2457 ERR("Failed to retrieve the color buffer from the frame buffer.");
2458 return gl::error(GL_OUT_OF_MEMORY, false);
2461 RenderTarget11 *sourceRenderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget());
2462 if (!sourceRenderTarget)
2464 ERR("Failed to retrieve the render target from the frame buffer.");
2465 return gl::error(GL_OUT_OF_MEMORY, false);
2468 ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView();
2471 ERR("Failed to retrieve the render target view from the render target.");
2472 return gl::error(GL_OUT_OF_MEMORY, false);
2475 TextureStorage11_2D *storage11 = TextureStorage11_2D::makeTextureStorage11_2D(storage->getStorageInstance());
2478 ERR("Failed to retrieve the texture storage from the destination.");
2479 return gl::error(GL_OUT_OF_MEMORY, false);
2482 RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTarget(level));
2483 if (!destRenderTarget)
2485 ERR("Failed to retrieve the render target from the destination storage.");
2486 return gl::error(GL_OUT_OF_MEMORY, false);
2489 ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView();
2492 ERR("Failed to retrieve the render target view from the destination render target.");
2493 return gl::error(GL_OUT_OF_MEMORY, false);
2496 gl::Rectangle destRect;
2497 destRect.x = xoffset;
2498 destRect.y = yoffset;
2499 destRect.width = sourceRect.width;
2500 destRect.height = sourceRect.height;
2502 bool ret = copyTexture(source, sourceRect, sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(),
2503 dest, destRect, destRenderTarget->getWidth(), destRenderTarget->getHeight(), destFormat);
2508 bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
2509 GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level)
2511 gl::Renderbuffer *colorbuffer = framebuffer->getReadColorbuffer();
2514 ERR("Failed to retrieve the color buffer from the frame buffer.");
2515 return gl::error(GL_OUT_OF_MEMORY, false);
2518 RenderTarget11 *sourceRenderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget());
2519 if (!sourceRenderTarget)
2521 ERR("Failed to retrieve the render target from the frame buffer.");
2522 return gl::error(GL_OUT_OF_MEMORY, false);
2525 ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView();
2528 ERR("Failed to retrieve the render target view from the render target.");
2529 return gl::error(GL_OUT_OF_MEMORY, false);
2532 TextureStorage11_Cube *storage11 = TextureStorage11_Cube::makeTextureStorage11_Cube(storage->getStorageInstance());
2535 ERR("Failed to retrieve the texture storage from the destination.");
2536 return gl::error(GL_OUT_OF_MEMORY, false);
2539 RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTarget(target, level));
2540 if (!destRenderTarget)
2542 ERR("Failed to retrieve the render target from the destination storage.");
2543 return gl::error(GL_OUT_OF_MEMORY, false);
2546 ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView();
2549 ERR("Failed to retrieve the render target view from the destination render target.");
2550 return gl::error(GL_OUT_OF_MEMORY, false);
2553 gl::Rectangle destRect;
2554 destRect.x = xoffset;
2555 destRect.y = yoffset;
2556 destRect.width = sourceRect.width;
2557 destRect.height = sourceRect.height;
2559 bool ret = copyTexture(source, sourceRect, sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(),
2560 dest, destRect, destRenderTarget->getWidth(), destRenderTarget->getHeight(), destFormat);
2565 bool Renderer11::copyTexture(ID3D11ShaderResourceView *source, const gl::Rectangle &sourceArea, unsigned int sourceWidth, unsigned int sourceHeight,
2566 ID3D11RenderTargetView *dest, const gl::Rectangle &destArea, unsigned int destWidth, unsigned int destHeight, GLenum destFormat)
2570 if (!mCopyResourcesInitialized)
2572 ASSERT(!mCopyVB && !mCopySampler && !mCopyIL && !mCopyVS && !mCopyRGBAPS && !mCopyRGBPS && !mCopyLumPS && !mCopyLumAlphaPS);
2574 D3D11_BUFFER_DESC vbDesc;
2575 vbDesc.ByteWidth = sizeof(d3d11::PositionTexCoordVertex) * 4;
2576 vbDesc.Usage = D3D11_USAGE_DYNAMIC;
2577 vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
2578 vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
2579 vbDesc.MiscFlags = 0;
2580 vbDesc.StructureByteStride = 0;
2582 result = mDevice->CreateBuffer(&vbDesc, NULL, &mCopyVB);
2583 ASSERT(SUCCEEDED(result));
2584 d3d11::SetDebugName(mCopyVB, "Renderer11 copy texture vertex buffer");
2586 D3D11_SAMPLER_DESC samplerDesc;
2587 samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
2588 samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
2589 samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
2590 samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
2591 samplerDesc.MipLODBias = 0.0f;
2592 samplerDesc.MaxAnisotropy = 0;
2593 samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
2594 samplerDesc.BorderColor[0] = 0.0f;
2595 samplerDesc.BorderColor[1] = 0.0f;
2596 samplerDesc.BorderColor[2] = 0.0f;
2597 samplerDesc.BorderColor[3] = 0.0f;
2598 samplerDesc.MinLOD = 0.0f;
2599 samplerDesc.MaxLOD = 0.0f;
2601 result = mDevice->CreateSamplerState(&samplerDesc, &mCopySampler);
2602 ASSERT(SUCCEEDED(result));
2603 d3d11::SetDebugName(mCopySampler, "Renderer11 copy sampler");
2605 D3D11_INPUT_ELEMENT_DESC quadLayout[] =
2607 { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
2608 { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 },
2611 result = mDevice->CreateInputLayout(quadLayout, 2, g_VS_Passthrough, sizeof(g_VS_Passthrough), &mCopyIL);
2612 ASSERT(SUCCEEDED(result));
2613 d3d11::SetDebugName(mCopyIL, "Renderer11 copy texture input layout");
2615 result = mDevice->CreateVertexShader(g_VS_Passthrough, sizeof(g_VS_Passthrough), NULL, &mCopyVS);
2616 ASSERT(SUCCEEDED(result));
2617 d3d11::SetDebugName(mCopyVS, "Renderer11 copy texture vertex shader");
2619 result = mDevice->CreatePixelShader(g_PS_PassthroughRGBA, sizeof(g_PS_PassthroughRGBA), NULL, &mCopyRGBAPS);
2620 ASSERT(SUCCEEDED(result));
2621 d3d11::SetDebugName(mCopyRGBAPS, "Renderer11 copy texture RGBA pixel shader");
2623 result = mDevice->CreatePixelShader(g_PS_PassthroughRGB, sizeof(g_PS_PassthroughRGB), NULL, &mCopyRGBPS);
2624 ASSERT(SUCCEEDED(result));
2625 d3d11::SetDebugName(mCopyRGBPS, "Renderer11 copy texture RGB pixel shader");
2627 result = mDevice->CreatePixelShader(g_PS_PassthroughLum, sizeof(g_PS_PassthroughLum), NULL, &mCopyLumPS);
2628 ASSERT(SUCCEEDED(result));
2629 d3d11::SetDebugName(mCopyLumPS, "Renderer11 copy texture luminance pixel shader");
2631 result = mDevice->CreatePixelShader(g_PS_PassthroughLumAlpha, sizeof(g_PS_PassthroughLumAlpha), NULL, &mCopyLumAlphaPS);
2632 ASSERT(SUCCEEDED(result));
2633 d3d11::SetDebugName(mCopyLumAlphaPS, "Renderer11 copy texture luminance alpha pixel shader");
2635 mCopyResourcesInitialized = true;
2638 // Verify the source and destination area sizes
2639 if (sourceArea.x < 0 || sourceArea.x + sourceArea.width > static_cast<int>(sourceWidth) ||
2640 sourceArea.y < 0 || sourceArea.y + sourceArea.height > static_cast<int>(sourceHeight) ||
2641 destArea.x < 0 || destArea.x + destArea.width > static_cast<int>(destWidth) ||
2642 destArea.y < 0 || destArea.y + destArea.height > static_cast<int>(destHeight))
2644 return gl::error(GL_INVALID_VALUE, false);
2648 D3D11_MAPPED_SUBRESOURCE mappedResource;
2649 result = mDeviceContext->Map(mCopyVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
2652 ERR("Failed to map vertex buffer for texture copy, HRESULT: 0x%X.", result);
2653 return gl::error(GL_OUT_OF_MEMORY, false);
2656 d3d11::PositionTexCoordVertex *vertices = static_cast<d3d11::PositionTexCoordVertex*>(mappedResource.pData);
2658 // Create a quad in homogeneous coordinates
2659 float x1 = (destArea.x / float(destWidth)) * 2.0f - 1.0f;
2660 float y1 = ((destHeight - destArea.y - destArea.height) / float(destHeight)) * 2.0f - 1.0f;
2661 float x2 = ((destArea.x + destArea.width) / float(destWidth)) * 2.0f - 1.0f;
2662 float y2 = ((destHeight - destArea.y) / float(destHeight)) * 2.0f - 1.0f;
2664 float u1 = sourceArea.x / float(sourceWidth);
2665 float v1 = sourceArea.y / float(sourceHeight);
2666 float u2 = (sourceArea.x + sourceArea.width) / float(sourceWidth);
2667 float v2 = (sourceArea.y + sourceArea.height) / float(sourceHeight);
2669 d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v2);
2670 d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v1);
2671 d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v2);
2672 d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v1);
2674 mDeviceContext->Unmap(mCopyVB, 0);
2676 static UINT stride = sizeof(d3d11::PositionTexCoordVertex);
2677 static UINT startIdx = 0;
2678 mDeviceContext->IASetVertexBuffers(0, 1, &mCopyVB, &stride, &startIdx);
2681 mDeviceContext->OMSetBlendState(NULL, NULL, 0xFFFFFFF);
2682 mDeviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF);
2683 mDeviceContext->RSSetState(NULL);
2686 mDeviceContext->IASetInputLayout(mCopyIL);
2687 mDeviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
2688 mDeviceContext->VSSetShader(mCopyVS, NULL, 0);
2690 ID3D11PixelShader *ps = NULL;
2693 case GL_RGBA: ps = mCopyRGBAPS; break;
2694 case GL_RGB: ps = mCopyRGBPS; break;
2695 case GL_ALPHA: ps = mCopyRGBAPS; break;
2696 case GL_BGRA_EXT: ps = mCopyRGBAPS; break;
2697 case GL_LUMINANCE: ps = mCopyLumPS; break;
2698 case GL_LUMINANCE_ALPHA: ps = mCopyLumAlphaPS; break;
2699 default: UNREACHABLE(); ps = NULL; break;
2702 mDeviceContext->PSSetShader(ps, NULL, 0);
2703 mDeviceContext->GSSetShader(NULL, NULL, 0);
2705 // Unset the currently bound shader resource to avoid conflicts
2706 static ID3D11ShaderResourceView *const nullSRV = NULL;
2707 mDeviceContext->PSSetShaderResources(0, 1, &nullSRV);
2709 // Apply render target
2710 setOneTimeRenderTarget(dest);
2713 D3D11_VIEWPORT viewport;
2714 viewport.TopLeftX = 0;
2715 viewport.TopLeftY = 0;
2716 viewport.Width = destWidth;
2717 viewport.Height = destHeight;
2718 viewport.MinDepth = 0.0f;
2719 viewport.MaxDepth = 1.0f;
2720 mDeviceContext->RSSetViewports(1, &viewport);
2723 mDeviceContext->PSSetShaderResources(0, 1, &source);
2724 mDeviceContext->PSSetSamplers(0, 1, &mCopySampler);
2727 mDeviceContext->Draw(4, 0);
2729 // Unbind textures and render targets and vertex buffer
2730 mDeviceContext->PSSetShaderResources(0, 1, &nullSRV);
2732 unapplyRenderTargets();
2735 ID3D11Buffer *const nullBuffer = NULL;
2736 mDeviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero);
2738 markAllStateDirty();
2743 void Renderer11::unapplyRenderTargets()
2745 setOneTimeRenderTarget(NULL);
2748 void Renderer11::setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView)
2750 ID3D11RenderTargetView *rtvArray[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {NULL};
2752 rtvArray[0] = renderTargetView;
2754 mDeviceContext->OMSetRenderTargets(getMaxRenderTargets(), rtvArray, NULL);
2756 // Do not preserve the serial for this one-time-use render target
2757 for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++)
2759 mAppliedRenderTargetSerials[rtIndex] = 0;
2763 RenderTarget *Renderer11::createRenderTarget(SwapChain *swapChain, bool depth)
2765 SwapChain11 *swapChain11 = SwapChain11::makeSwapChain11(swapChain);
2766 RenderTarget11 *renderTarget = NULL;
2770 // Note: depth stencil may be NULL for 0 sized surfaces
2771 renderTarget = new RenderTarget11(this, swapChain11->getDepthStencil(),
2772 swapChain11->getDepthStencilTexture(), NULL,
2773 swapChain11->getWidth(), swapChain11->getHeight());
2777 // Note: render target may be NULL for 0 sized surfaces
2778 renderTarget = new RenderTarget11(this, swapChain11->getRenderTarget(),
2779 swapChain11->getOffscreenTexture(),
2780 swapChain11->getRenderTargetShaderResource(),
2781 swapChain11->getWidth(), swapChain11->getHeight());
2783 return renderTarget;
2786 RenderTarget *Renderer11::createRenderTarget(int width, int height, GLenum format, GLsizei samples, bool depth)
2788 RenderTarget11 *renderTarget = new RenderTarget11(this, width, height, format, samples, depth);
2789 return renderTarget;
2792 ShaderExecutable *Renderer11::loadExecutable(const void *function, size_t length, rx::ShaderType type)
2794 ShaderExecutable11 *executable = NULL;
2798 case rx::SHADER_VERTEX:
2800 ID3D11VertexShader *vshader = NULL;
2801 HRESULT result = mDevice->CreateVertexShader(function, length, NULL, &vshader);
2802 ASSERT(SUCCEEDED(result));
2806 executable = new ShaderExecutable11(function, length, vshader);
2810 case rx::SHADER_PIXEL:
2812 ID3D11PixelShader *pshader = NULL;
2813 HRESULT result = mDevice->CreatePixelShader(function, length, NULL, &pshader);
2814 ASSERT(SUCCEEDED(result));
2818 executable = new ShaderExecutable11(function, length, pshader);
2822 case rx::SHADER_GEOMETRY:
2824 ID3D11GeometryShader *gshader = NULL;
2825 HRESULT result = mDevice->CreateGeometryShader(function, length, NULL, &gshader);
2826 ASSERT(SUCCEEDED(result));
2830 executable = new ShaderExecutable11(function, length, gshader);
2842 ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, D3DWorkaroundType workaround)
2844 const char *profile = NULL;
2848 case rx::SHADER_VERTEX:
2851 case rx::SHADER_PIXEL:
2854 case rx::SHADER_GEOMETRY:
2862 ID3DBlob *binary = (ID3DBlob*)compileToBinary(infoLog, shaderHLSL, profile, D3DCOMPILE_OPTIMIZATION_LEVEL0, false);
2866 ShaderExecutable *executable = loadExecutable((DWORD *)binary->GetBufferPointer(), binary->GetBufferSize(), type);
2872 VertexBuffer *Renderer11::createVertexBuffer()
2874 return new VertexBuffer11(this);
2877 IndexBuffer *Renderer11::createIndexBuffer()
2879 return new IndexBuffer11(this);
2882 BufferStorage *Renderer11::createBufferStorage()
2884 return new BufferStorage11(this);
2887 QueryImpl *Renderer11::createQuery(GLenum type)
2889 return new Query11(this, type);
2892 FenceImpl *Renderer11::createFence()
2894 return new Fence11(this);
2897 bool Renderer11::getRenderTargetResource(gl::Renderbuffer *colorbuffer, unsigned int *subresourceIndex, ID3D11Texture2D **resource)
2899 ASSERT(colorbuffer != NULL);
2901 RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget());
2904 *subresourceIndex = renderTarget->getSubresourceIndex();
2906 ID3D11RenderTargetView *colorBufferRTV = renderTarget->getRenderTargetView();
2909 ID3D11Resource *textureResource = NULL;
2910 colorBufferRTV->GetResource(&textureResource);
2912 if (textureResource)
2914 HRESULT result = textureResource->QueryInterface(IID_ID3D11Texture2D, (void**)resource);
2915 textureResource->Release();
2917 if (SUCCEEDED(result))
2923 ERR("Failed to extract the ID3D11Texture2D from the render target resource, "
2924 "HRESULT: 0x%X.", result);
2933 bool Renderer11::blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect,
2934 bool blitRenderTarget, bool blitDepthStencil)
2936 if (blitRenderTarget)
2938 gl::Renderbuffer *readBuffer = readTarget->getReadColorbuffer();
2942 ERR("Failed to retrieve the read buffer from the read framebuffer.");
2943 return gl::error(GL_OUT_OF_MEMORY, false);
2946 RenderTarget *readRenderTarget = readBuffer->getRenderTarget();
2948 for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
2950 if (drawTarget->isEnabledColorAttachment(colorAttachment))
2952 gl::Renderbuffer *drawBuffer = drawTarget->getColorbuffer(colorAttachment);
2956 ERR("Failed to retrieve the draw buffer from the draw framebuffer.");
2957 return gl::error(GL_OUT_OF_MEMORY, false);
2960 RenderTarget *drawRenderTarget = drawBuffer->getRenderTarget();
2962 if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, false))
2970 if (blitDepthStencil)
2972 gl::Renderbuffer *readBuffer = readTarget->getDepthOrStencilbuffer();
2973 gl::Renderbuffer *drawBuffer = drawTarget->getDepthOrStencilbuffer();
2977 ERR("Failed to retrieve the read depth-stencil buffer from the read framebuffer.");
2978 return gl::error(GL_OUT_OF_MEMORY, false);
2983 ERR("Failed to retrieve the draw depth-stencil buffer from the draw framebuffer.");
2984 return gl::error(GL_OUT_OF_MEMORY, false);
2987 RenderTarget *readRenderTarget = readBuffer->getDepthStencil();
2988 RenderTarget *drawRenderTarget = drawBuffer->getDepthStencil();
2990 if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, true))
2999 void Renderer11::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type,
3000 GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels)
3002 ID3D11Texture2D *colorBufferTexture = NULL;
3003 unsigned int subresourceIndex = 0;
3005 gl::Renderbuffer *colorbuffer = framebuffer->getReadColorbuffer();
3007 if (colorbuffer && getRenderTargetResource(colorbuffer, &subresourceIndex, &colorBufferTexture))
3013 area.height = height;
3015 readTextureData(colorBufferTexture, subresourceIndex, area, colorbuffer->getActualFormat(), format, type, outputPitch,
3016 packReverseRowOrder, packAlignment, pixels);
3018 colorBufferTexture->Release();
3019 colorBufferTexture = NULL;
3023 Image *Renderer11::createImage()
3025 return new Image11();
3028 void Renderer11::generateMipmap(Image *dest, Image *src)
3030 Image11 *dest11 = Image11::makeImage11(dest);
3031 Image11 *src11 = Image11::makeImage11(src);
3032 Image11::generateMipmap(dest11, src11);
3035 TextureStorage *Renderer11::createTextureStorage2D(SwapChain *swapChain)
3037 SwapChain11 *swapChain11 = SwapChain11::makeSwapChain11(swapChain);
3038 return new TextureStorage11_2D(this, swapChain11);
3041 TextureStorage *Renderer11::createTextureStorage2D(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height)
3043 return new TextureStorage11_2D(this, levels, internalformat, usage, forceRenderable, width, height);
3046 TextureStorage *Renderer11::createTextureStorageCube(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size)
3048 return new TextureStorage11_Cube(this, levels, internalformat, usage, forceRenderable, size);
3051 static inline unsigned int getFastPixelCopySize(DXGI_FORMAT sourceFormat, GLenum sourceGLFormat, GLenum destFormat, GLenum destType)
3053 if (sourceFormat == DXGI_FORMAT_A8_UNORM &&
3054 destFormat == GL_ALPHA &&
3055 destType == GL_UNSIGNED_BYTE)
3059 else if (sourceFormat == DXGI_FORMAT_R8G8B8A8_UNORM &&
3060 sourceGLFormat == GL_RGBA8_OES &&
3061 destFormat == GL_RGBA &&
3062 destType == GL_UNSIGNED_BYTE)
3066 else if (sourceFormat == DXGI_FORMAT_B8G8R8A8_UNORM &&
3067 destFormat == GL_BGRA_EXT &&
3068 destType == GL_UNSIGNED_BYTE)
3072 else if (sourceFormat == DXGI_FORMAT_R16G16B16A16_FLOAT &&
3073 sourceGLFormat == GL_RGBA16F_EXT &&
3074 destFormat == GL_RGBA &&
3075 destType == GL_HALF_FLOAT_OES)
3079 else if (sourceFormat == DXGI_FORMAT_R32G32B32_FLOAT &&
3080 destFormat == GL_RGB &&
3081 destType == GL_FLOAT)
3085 else if (sourceFormat == DXGI_FORMAT_R32G32B32A32_FLOAT &&
3086 sourceGLFormat == GL_RGBA32F_EXT &&
3087 destFormat == GL_RGBA &&
3088 destType == GL_FLOAT)
3098 static inline void readPixelColor(const unsigned char *data, DXGI_FORMAT format, GLenum glFormat, unsigned int x,
3099 unsigned int y, int inputPitch, gl::Color *outColor)
3103 case DXGI_FORMAT_R8G8B8A8_UNORM:
3105 unsigned int rgba = *reinterpret_cast<const unsigned int*>(data + 4 * x + y * inputPitch);
3106 outColor->red = (rgba & 0x000000FF) * (1.0f / 0x000000FF);
3107 outColor->green = (rgba & 0x0000FF00) * (1.0f / 0x0000FF00);
3108 outColor->blue = (rgba & 0x00FF0000) * (1.0f / 0x00FF0000);
3110 if (gl::GetAlphaSize(glFormat) > 0)
3112 outColor->alpha = (rgba & 0xFF000000) * (1.0f / 0xFF000000);
3116 outColor->alpha = 1.0f;
3121 case DXGI_FORMAT_A8_UNORM:
3123 outColor->red = 0.0f;
3124 outColor->green = 0.0f;
3125 outColor->blue = 0.0f;
3126 outColor->alpha = *(data + x + y * inputPitch) / 255.0f;
3130 case DXGI_FORMAT_R32G32B32A32_FLOAT:
3132 outColor->red = *(reinterpret_cast<const float*>(data + 16 * x + y * inputPitch) + 0);
3133 outColor->green = *(reinterpret_cast<const float*>(data + 16 * x + y * inputPitch) + 1);
3134 outColor->blue = *(reinterpret_cast<const float*>(data + 16 * x + y * inputPitch) + 2);
3136 if (gl::GetAlphaSize(glFormat) > 0)
3138 outColor->alpha = *(reinterpret_cast<const float*>(data + 16 * x + y * inputPitch) + 3);
3142 outColor->alpha = 1.0f;
3147 case DXGI_FORMAT_R32G32B32_FLOAT:
3149 outColor->red = *(reinterpret_cast<const float*>(data + 12 * x + y * inputPitch) + 0);
3150 outColor->green = *(reinterpret_cast<const float*>(data + 12 * x + y * inputPitch) + 1);
3151 outColor->blue = *(reinterpret_cast<const float*>(data + 12 * x + y * inputPitch) + 2);
3152 outColor->alpha = 1.0f;
3156 case DXGI_FORMAT_R16G16B16A16_FLOAT:
3158 outColor->red = gl::float16ToFloat32(*(reinterpret_cast<const unsigned short*>(data + 8 * x + y * inputPitch) + 0));
3159 outColor->green = gl::float16ToFloat32(*(reinterpret_cast<const unsigned short*>(data + 8 * x + y * inputPitch) + 1));
3160 outColor->blue = gl::float16ToFloat32(*(reinterpret_cast<const unsigned short*>(data + 8 * x + y * inputPitch) + 2));
3162 if (gl::GetAlphaSize(glFormat) > 0)
3164 outColor->alpha = gl::float16ToFloat32(*(reinterpret_cast<const unsigned short*>(data + 8 * x + y * inputPitch) + 3));
3168 outColor->alpha = 1.0f;
3173 case DXGI_FORMAT_B8G8R8A8_UNORM:
3175 unsigned int bgra = *reinterpret_cast<const unsigned int*>(data + 4 * x + y * inputPitch);
3176 outColor->red = (bgra & 0x00FF0000) * (1.0f / 0x00FF0000);
3177 outColor->blue = (bgra & 0x000000FF) * (1.0f / 0x000000FF);
3178 outColor->green = (bgra & 0x0000FF00) * (1.0f / 0x0000FF00);
3179 outColor->alpha = (bgra & 0xFF000000) * (1.0f / 0xFF000000);
3183 case DXGI_FORMAT_R8_UNORM:
3185 outColor->red = *(data + x + y * inputPitch) / 255.0f;
3186 outColor->green = 0.0f;
3187 outColor->blue = 0.0f;
3188 outColor->alpha = 1.0f;
3192 case DXGI_FORMAT_R8G8_UNORM:
3194 unsigned short rg = *reinterpret_cast<const unsigned short*>(data + 2 * x + y * inputPitch);
3196 outColor->red = (rg & 0xFF00) * (1.0f / 0xFF00);
3197 outColor->green = (rg & 0x00FF) * (1.0f / 0x00FF);
3198 outColor->blue = 0.0f;
3199 outColor->alpha = 1.0f;
3203 case DXGI_FORMAT_R16_FLOAT:
3205 outColor->red = gl::float16ToFloat32(*reinterpret_cast<const unsigned short*>(data + 2 * x + y * inputPitch));
3206 outColor->green = 0.0f;
3207 outColor->blue = 0.0f;
3208 outColor->alpha = 1.0f;
3212 case DXGI_FORMAT_R16G16_FLOAT:
3214 outColor->red = gl::float16ToFloat32(*(reinterpret_cast<const unsigned short*>(data + 4 * x + y * inputPitch) + 0));
3215 outColor->green = gl::float16ToFloat32(*(reinterpret_cast<const unsigned short*>(data + 4 * x + y * inputPitch) + 1));
3216 outColor->blue = 0.0f;
3217 outColor->alpha = 1.0f;
3222 ERR("ReadPixelColor not implemented for DXGI format %u.", format);
3228 static inline void writePixelColor(const gl::Color &color, GLenum format, GLenum type, unsigned int x,
3229 unsigned int y, int outputPitch, void *outData)
3231 unsigned char* byteData = reinterpret_cast<unsigned char*>(outData);
3232 unsigned short* shortData = reinterpret_cast<unsigned short*>(outData);
3239 case GL_UNSIGNED_BYTE:
3240 byteData[4 * x + y * outputPitch + 0] = static_cast<unsigned char>(255 * color.red + 0.5f);
3241 byteData[4 * x + y * outputPitch + 1] = static_cast<unsigned char>(255 * color.green + 0.5f);
3242 byteData[4 * x + y * outputPitch + 2] = static_cast<unsigned char>(255 * color.blue + 0.5f);
3243 byteData[4 * x + y * outputPitch + 3] = static_cast<unsigned char>(255 * color.alpha + 0.5f);
3247 ERR("WritePixelColor not implemented for format GL_RGBA and type 0x%X.", type);
3256 case GL_UNSIGNED_BYTE:
3257 byteData[4 * x + y * outputPitch + 0] = static_cast<unsigned char>(255 * color.blue + 0.5f);
3258 byteData[4 * x + y * outputPitch + 1] = static_cast<unsigned char>(255 * color.green + 0.5f);
3259 byteData[4 * x + y * outputPitch + 2] = static_cast<unsigned char>(255 * color.red + 0.5f);
3260 byteData[4 * x + y * outputPitch + 3] = static_cast<unsigned char>(255 * color.alpha + 0.5f);
3263 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
3264 // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section
3265 // this type is packed as follows:
3266 // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
3267 // --------------------------------------------------------------------------------
3268 // | 4th | 3rd | 2nd | 1st component |
3269 // --------------------------------------------------------------------------------
3270 // in the case of BGRA_EXT, B is the first component, G the second, and so forth.
3271 shortData[x + y * outputPitch / sizeof(unsigned short)] =
3272 (static_cast<unsigned short>(15 * color.alpha + 0.5f) << 12) |
3273 (static_cast<unsigned short>(15 * color.red + 0.5f) << 8) |
3274 (static_cast<unsigned short>(15 * color.green + 0.5f) << 4) |
3275 (static_cast<unsigned short>(15 * color.blue + 0.5f) << 0);
3278 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
3279 // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section
3280 // this type is packed as follows:
3281 // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
3282 // --------------------------------------------------------------------------------
3283 // | 4th | 3rd | 2nd | 1st component |
3284 // --------------------------------------------------------------------------------
3285 // in the case of BGRA_EXT, B is the first component, G the second, and so forth.
3286 shortData[x + y * outputPitch / sizeof(unsigned short)] =
3287 (static_cast<unsigned short>( color.alpha + 0.5f) << 15) |
3288 (static_cast<unsigned short>(31 * color.red + 0.5f) << 10) |
3289 (static_cast<unsigned short>(31 * color.green + 0.5f) << 5) |
3290 (static_cast<unsigned short>(31 * color.blue + 0.5f) << 0);
3294 ERR("WritePixelColor not implemented for format GL_BGRA_EXT and type 0x%X.", type);
3303 case GL_UNSIGNED_SHORT_5_6_5:
3304 shortData[x + y * outputPitch / sizeof(unsigned short)] =
3305 (static_cast<unsigned short>(31 * color.blue + 0.5f) << 0) |
3306 (static_cast<unsigned short>(63 * color.green + 0.5f) << 5) |
3307 (static_cast<unsigned short>(31 * color.red + 0.5f) << 11);
3310 case GL_UNSIGNED_BYTE:
3311 byteData[3 * x + y * outputPitch + 0] = static_cast<unsigned char>(255 * color.red + 0.5f);
3312 byteData[3 * x + y * outputPitch + 1] = static_cast<unsigned char>(255 * color.green + 0.5f);
3313 byteData[3 * x + y * outputPitch + 2] = static_cast<unsigned char>(255 * color.blue + 0.5f);
3317 ERR("WritePixelColor not implemented for format GL_RGB and type 0x%X.", type);
3324 ERR("WritePixelColor not implemented for format 0x%X.", format);
3330 void Renderer11::readTextureData(ID3D11Texture2D *texture, unsigned int subResource, const gl::Rectangle &area,
3331 GLenum sourceFormat, GLenum format, GLenum type, GLsizei outputPitch, bool packReverseRowOrder,
3332 GLint packAlignment, void *pixels)
3334 D3D11_TEXTURE2D_DESC textureDesc;
3335 texture->GetDesc(&textureDesc);
3337 D3D11_TEXTURE2D_DESC stagingDesc;
3338 stagingDesc.Width = area.width;
3339 stagingDesc.Height = area.height;
3340 stagingDesc.MipLevels = 1;
3341 stagingDesc.ArraySize = 1;
3342 stagingDesc.Format = textureDesc.Format;
3343 stagingDesc.SampleDesc.Count = 1;
3344 stagingDesc.SampleDesc.Quality = 0;
3345 stagingDesc.Usage = D3D11_USAGE_STAGING;
3346 stagingDesc.BindFlags = 0;
3347 stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
3348 stagingDesc.MiscFlags = 0;
3350 ID3D11Texture2D* stagingTex = NULL;
3351 HRESULT result = mDevice->CreateTexture2D(&stagingDesc, NULL, &stagingTex);
3354 ERR("Failed to create staging texture for readPixels, HRESULT: 0x%X.", result);
3358 ID3D11Texture2D* srcTex = NULL;
3359 if (textureDesc.SampleDesc.Count > 1)
3361 D3D11_TEXTURE2D_DESC resolveDesc;
3362 resolveDesc.Width = textureDesc.Width;
3363 resolveDesc.Height = textureDesc.Height;
3364 resolveDesc.MipLevels = 1;
3365 resolveDesc.ArraySize = 1;
3366 resolveDesc.Format = textureDesc.Format;
3367 resolveDesc.SampleDesc.Count = 1;
3368 resolveDesc.SampleDesc.Quality = 0;
3369 resolveDesc.Usage = D3D11_USAGE_DEFAULT;
3370 resolveDesc.BindFlags = 0;
3371 resolveDesc.CPUAccessFlags = 0;
3372 resolveDesc.MiscFlags = 0;
3374 result = mDevice->CreateTexture2D(&resolveDesc, NULL, &srcTex);
3377 ERR("Failed to create resolve texture for readPixels, HRESULT: 0x%X.", result);
3378 stagingTex->Release();
3382 mDeviceContext->ResolveSubresource(srcTex, 0, texture, subResource, textureDesc.Format);
3392 srcBox.left = area.x;
3393 srcBox.right = area.x + area.width;
3394 srcBox.top = area.y;
3395 srcBox.bottom = area.y + area.height;
3399 mDeviceContext->CopySubresourceRegion(stagingTex, 0, 0, 0, 0, srcTex, subResource, &srcBox);
3404 D3D11_MAPPED_SUBRESOURCE mapping;
3405 mDeviceContext->Map(stagingTex, 0, D3D11_MAP_READ, 0, &mapping);
3407 unsigned char *source;
3409 if (packReverseRowOrder)
3411 source = static_cast<unsigned char*>(mapping.pData) + mapping.RowPitch * (area.height - 1);
3412 inputPitch = -static_cast<int>(mapping.RowPitch);
3416 source = static_cast<unsigned char*>(mapping.pData);
3417 inputPitch = static_cast<int>(mapping.RowPitch);
3420 unsigned int fastPixelSize = getFastPixelCopySize(textureDesc.Format, sourceFormat, format, type);
3421 if (fastPixelSize != 0)
3423 unsigned char *dest = static_cast<unsigned char*>(pixels);
3424 for (int j = 0; j < area.height; j++)
3426 memcpy(dest + j * outputPitch, source + j * inputPitch, area.width * fastPixelSize);
3429 else if (textureDesc.Format == DXGI_FORMAT_B8G8R8A8_UNORM &&
3430 format == GL_RGBA &&
3431 type == GL_UNSIGNED_BYTE)
3433 // Fast path for swapping red with blue
3434 unsigned char *dest = static_cast<unsigned char*>(pixels);
3436 for (int j = 0; j < area.height; j++)
3438 for (int i = 0; i < area.width; i++)
3440 unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch);
3441 *(unsigned int*)(dest + 4 * i + j * outputPitch) =
3442 (argb & 0xFF00FF00) | // Keep alpha and green
3443 (argb & 0x00FF0000) >> 16 | // Move red to blue
3444 (argb & 0x000000FF) << 16; // Move blue to red
3450 gl::Color pixelColor;
3451 for (int j = 0; j < area.height; j++)
3453 for (int i = 0; i < area.width; i++)
3455 readPixelColor(source, textureDesc.Format, sourceFormat, i, j, inputPitch, &pixelColor);
3456 writePixelColor(pixelColor, format, type, i, j, outputPitch, pixels);
3461 mDeviceContext->Unmap(stagingTex, 0);
3463 stagingTex->Release();
3467 bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget,
3468 RenderTarget *drawRenderTarget, bool wholeBufferCopy)
3470 ASSERT(readRect.width == drawRect.width && readRect.height == drawRect.height);
3472 RenderTarget11 *drawRenderTarget11 = RenderTarget11::makeRenderTarget11(drawRenderTarget);
3473 if (!drawRenderTarget)
3475 ERR("Failed to retrieve the draw render target from the draw framebuffer.");
3476 return gl::error(GL_OUT_OF_MEMORY, false);
3479 ID3D11Texture2D *drawTexture = drawRenderTarget11->getTexture();
3480 unsigned int drawSubresource = drawRenderTarget11->getSubresourceIndex();
3482 RenderTarget11 *readRenderTarget11 = RenderTarget11::makeRenderTarget11(readRenderTarget);
3483 if (!readRenderTarget)
3485 ERR("Failed to retrieve the read render target from the read framebuffer.");
3486 return gl::error(GL_OUT_OF_MEMORY, false);
3489 ID3D11Texture2D *readTexture = NULL;
3490 unsigned int readSubresource = 0;
3491 if (readRenderTarget->getSamples() > 0)
3493 readTexture = resolveMultisampledTexture(readRenderTarget11->getTexture(), readRenderTarget11->getSubresourceIndex());
3494 readSubresource = 0;
3498 readTexture = readRenderTarget11->getTexture();
3499 readTexture->AddRef();
3500 readSubresource = readRenderTarget11->getSubresourceIndex();
3505 ERR("Failed to retrieve the read render target view from the read render target.");
3506 return gl::error(GL_OUT_OF_MEMORY, false);
3510 readBox.left = readRect.x;
3511 readBox.right = readRect.x + readRect.width;
3512 readBox.top = readRect.y;
3513 readBox.bottom = readRect.y + readRect.height;
3517 // D3D11 needs depth-stencil CopySubresourceRegions to have a NULL pSrcBox
3518 // We also require complete framebuffer copies for depth-stencil blit.
3519 D3D11_BOX *pSrcBox = wholeBufferCopy ? NULL : &readBox;
3521 mDeviceContext->CopySubresourceRegion(drawTexture, drawSubresource, drawRect.x, drawRect.y, 0,
3522 readTexture, readSubresource, pSrcBox);
3524 SafeRelease(readTexture);
3529 ID3D11Texture2D *Renderer11::resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource)
3531 D3D11_TEXTURE2D_DESC textureDesc;
3532 source->GetDesc(&textureDesc);
3534 if (textureDesc.SampleDesc.Count > 1)
3536 D3D11_TEXTURE2D_DESC resolveDesc;
3537 resolveDesc.Width = textureDesc.Width;
3538 resolveDesc.Height = textureDesc.Height;
3539 resolveDesc.MipLevels = 1;
3540 resolveDesc.ArraySize = 1;
3541 resolveDesc.Format = textureDesc.Format;
3542 resolveDesc.SampleDesc.Count = 1;
3543 resolveDesc.SampleDesc.Quality = 0;
3544 resolveDesc.Usage = textureDesc.Usage;
3545 resolveDesc.BindFlags = textureDesc.BindFlags;
3546 resolveDesc.CPUAccessFlags = 0;
3547 resolveDesc.MiscFlags = 0;
3549 ID3D11Texture2D *resolveTexture = NULL;
3550 HRESULT result = mDevice->CreateTexture2D(&resolveDesc, NULL, &resolveTexture);
3553 ERR("Failed to create a multisample resolve texture, HRESULT: 0x%X.", result);
3557 mDeviceContext->ResolveSubresource(resolveTexture, 0, source, subresource, textureDesc.Format);
3558 return resolveTexture;
3567 bool Renderer11::getLUID(LUID *adapterLuid) const
3569 adapterLuid->HighPart = 0;
3570 adapterLuid->LowPart = 0;
3577 DXGI_ADAPTER_DESC adapterDesc;
3578 if (FAILED(mDxgiAdapter->GetDesc(&adapterDesc)))
3583 *adapterLuid = adapterDesc.AdapterLuid;