gfx/angle/src/libGLESv2/renderer/Renderer11.cpp

branch
TOR_BUG_3246
changeset 7
129ffea94266
equal deleted inserted replaced
-1:000000000000 0:3ab2fc7e3ece
1 #include "precompiled.h"
2 //
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.
6 //
7
8 // Renderer11.cpp: Implements a back-end specific class for the D3D11 renderer.
9
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/Renderer11.h"
17 #include "libGLESv2/renderer/RenderTarget11.h"
18 #include "libGLESv2/renderer/renderer11_utils.h"
19 #include "libGLESv2/renderer/ShaderExecutable11.h"
20 #include "libGLESv2/renderer/SwapChain11.h"
21 #include "libGLESv2/renderer/Image11.h"
22 #include "libGLESv2/renderer/VertexBuffer11.h"
23 #include "libGLESv2/renderer/IndexBuffer11.h"
24 #include "libGLESv2/renderer/BufferStorage11.h"
25 #include "libGLESv2/renderer/VertexDataManager.h"
26 #include "libGLESv2/renderer/IndexDataManager.h"
27 #include "libGLESv2/renderer/TextureStorage11.h"
28 #include "libGLESv2/renderer/Query11.h"
29 #include "libGLESv2/renderer/Fence11.h"
30
31 #include "libGLESv2/renderer/shaders/compiled/passthrough11vs.h"
32 #include "libGLESv2/renderer/shaders/compiled/passthroughrgba11ps.h"
33 #include "libGLESv2/renderer/shaders/compiled/passthroughrgb11ps.h"
34 #include "libGLESv2/renderer/shaders/compiled/passthroughlum11ps.h"
35 #include "libGLESv2/renderer/shaders/compiled/passthroughlumalpha11ps.h"
36
37 #include "libGLESv2/renderer/shaders/compiled/clear11vs.h"
38 #include "libGLESv2/renderer/shaders/compiled/clearsingle11ps.h"
39 #include "libGLESv2/renderer/shaders/compiled/clearmultiple11ps.h"
40
41 #include "libEGL/Display.h"
42
43 #ifdef _DEBUG
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
47 #endif
48
49 namespace rx
50 {
51 static const DXGI_FORMAT RenderTargetFormats[] =
52 {
53 DXGI_FORMAT_B8G8R8A8_UNORM,
54 DXGI_FORMAT_R8G8B8A8_UNORM
55 };
56
57 static const DXGI_FORMAT DepthStencilFormats[] =
58 {
59 DXGI_FORMAT_UNKNOWN,
60 DXGI_FORMAT_D24_UNORM_S8_UINT,
61 DXGI_FORMAT_D16_UNORM
62 };
63
64 enum
65 {
66 MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 = 16
67 };
68
69 Renderer11::Renderer11(egl::Display *display, HDC hDc) : Renderer(display), mDc(hDc)
70 {
71 mVertexDataManager = NULL;
72 mIndexDataManager = NULL;
73
74 mLineLoopIB = NULL;
75 mTriangleFanIB = NULL;
76
77 mCopyResourcesInitialized = false;
78 mCopyVB = NULL;
79 mCopySampler = NULL;
80 mCopyIL = NULL;
81 mCopyVS = NULL;
82 mCopyRGBAPS = NULL;
83 mCopyRGBPS = NULL;
84 mCopyLumPS = NULL;
85 mCopyLumAlphaPS = NULL;
86
87 mClearResourcesInitialized = false;
88 mClearVB = NULL;
89 mClearIL = NULL;
90 mClearVS = NULL;
91 mClearSinglePS = NULL;
92 mClearMultiplePS = NULL;
93 mClearScissorRS = NULL;
94 mClearNoScissorRS = NULL;
95
96 mSyncQuery = NULL;
97
98 mD3d11Module = NULL;
99 mDxgiModule = NULL;
100
101 mDeviceLost = false;
102
103 mMaxSupportedSamples = 0;
104
105 mDevice = NULL;
106 mDeviceContext = NULL;
107 mDxgiAdapter = NULL;
108 mDxgiFactory = NULL;
109
110 mDriverConstantBufferVS = NULL;
111 mDriverConstantBufferPS = NULL;
112
113 mBGRATextureSupport = false;
114
115 mIsGeometryShaderActive = false;
116 }
117
118 Renderer11::~Renderer11()
119 {
120 release();
121 }
122
123 Renderer11 *Renderer11::makeRenderer11(Renderer *renderer)
124 {
125 ASSERT(HAS_DYNAMIC_TYPE(rx::Renderer11*, renderer));
126 return static_cast<rx::Renderer11*>(renderer);
127 }
128
129 #ifndef __d3d11_1_h__
130 #define D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET ((D3D11_MESSAGE_ID)3146081)
131 #endif
132
133 EGLint Renderer11::initialize()
134 {
135 if (!initializeCompiler())
136 {
137 return EGL_NOT_INITIALIZED;
138 }
139
140 mDxgiModule = LoadLibrary(TEXT("dxgi.dll"));
141 mD3d11Module = LoadLibrary(TEXT("d3d11.dll"));
142
143 if (mD3d11Module == NULL || mDxgiModule == NULL)
144 {
145 ERR("Could not load D3D11 or DXGI library - aborting!\n");
146 return EGL_NOT_INITIALIZED;
147 }
148
149 // create the D3D11 device
150 ASSERT(mDevice == NULL);
151 PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice");
152
153 if (D3D11CreateDevice == NULL)
154 {
155 ERR("Could not retrieve D3D11CreateDevice address - aborting!\n");
156 return EGL_NOT_INITIALIZED;
157 }
158
159 D3D_FEATURE_LEVEL featureLevels[] =
160 {
161 D3D_FEATURE_LEVEL_11_0,
162 D3D_FEATURE_LEVEL_10_1,
163 D3D_FEATURE_LEVEL_10_0,
164 };
165
166 HRESULT result = S_OK;
167
168 #ifdef _DEBUG
169 result = D3D11CreateDevice(NULL,
170 D3D_DRIVER_TYPE_HARDWARE,
171 NULL,
172 D3D11_CREATE_DEVICE_DEBUG,
173 featureLevels,
174 ArraySize(featureLevels),
175 D3D11_SDK_VERSION,
176 &mDevice,
177 &mFeatureLevel,
178 &mDeviceContext);
179
180 if (!mDevice || FAILED(result))
181 {
182 ERR("Failed creating Debug D3D11 device - falling back to release runtime.\n");
183 }
184
185 if (!mDevice || FAILED(result))
186 #endif
187 {
188 result = D3D11CreateDevice(NULL,
189 D3D_DRIVER_TYPE_HARDWARE,
190 NULL,
191 0,
192 featureLevels,
193 ArraySize(featureLevels),
194 D3D11_SDK_VERSION,
195 &mDevice,
196 &mFeatureLevel,
197 &mDeviceContext);
198
199 if (!mDevice || FAILED(result))
200 {
201 ERR("Could not create D3D11 device - aborting!\n");
202 return EGL_NOT_INITIALIZED; // Cleanup done by destructor through glDestroyRenderer
203 }
204 }
205
206 IDXGIDevice *dxgiDevice = NULL;
207 result = mDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgiDevice);
208
209 if (FAILED(result))
210 {
211 ERR("Could not query DXGI device - aborting!\n");
212 return EGL_NOT_INITIALIZED;
213 }
214
215 result = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&mDxgiAdapter);
216
217 if (FAILED(result))
218 {
219 ERR("Could not retrieve DXGI adapter - aborting!\n");
220 return EGL_NOT_INITIALIZED;
221 }
222
223 dxgiDevice->Release();
224
225 mDxgiAdapter->GetDesc(&mAdapterDescription);
226 memset(mDescription, 0, sizeof(mDescription));
227 wcstombs(mDescription, mAdapterDescription.Description, sizeof(mDescription) - 1);
228
229 result = mDxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void**)&mDxgiFactory);
230
231 if (!mDxgiFactory || FAILED(result))
232 {
233 ERR("Could not create DXGI factory - aborting!\n");
234 return EGL_NOT_INITIALIZED;
235 }
236
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);
241
242 if (SUCCEEDED(result))
243 {
244 D3D11_MESSAGE_ID hideMessages[] =
245 {
246 D3D11_MESSAGE_ID_DEVICE_OMSETRENDERTARGETS_HAZARD,
247 D3D11_MESSAGE_ID_DEVICE_PSSETSHADERRESOURCES_HAZARD,
248 D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET
249 };
250
251 D3D11_INFO_QUEUE_FILTER filter = {0};
252 filter.DenyList.NumIDs = ArraySize(hideMessages);
253 filter.DenyList.pIDList = hideMessages;
254
255 infoQueue->AddStorageFilterEntries(&filter);
256
257 infoQueue->Release();
258 }
259 #endif
260
261 unsigned int maxSupportedSamples = 0;
262 unsigned int rtFormatCount = ArraySize(RenderTargetFormats);
263 unsigned int dsFormatCount = ArraySize(DepthStencilFormats);
264 for (unsigned int i = 0; i < rtFormatCount + dsFormatCount; ++i)
265 {
266 DXGI_FORMAT format = (i < rtFormatCount) ? RenderTargetFormats[i] : DepthStencilFormats[i - rtFormatCount];
267 if (format != DXGI_FORMAT_UNKNOWN)
268 {
269 UINT formatSupport;
270 result = mDevice->CheckFormatSupport(format, &formatSupport);
271 if (SUCCEEDED(result) && (formatSupport & D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET))
272 {
273 MultisampleSupportInfo supportInfo;
274
275 for (unsigned int j = 1; j <= D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; j++)
276 {
277 result = mDevice->CheckMultisampleQualityLevels(format, j, &supportInfo.qualityLevels[j - 1]);
278 if (SUCCEEDED(result) && supportInfo.qualityLevels[j - 1] > 0)
279 {
280 maxSupportedSamples = std::max(j, maxSupportedSamples);
281 }
282 else
283 {
284 supportInfo.qualityLevels[j - 1] = 0;
285 }
286 }
287
288 mMultisampleSupportMap.insert(std::make_pair(format, supportInfo));
289 }
290 }
291 }
292 mMaxSupportedSamples = maxSupportedSamples;
293
294 initializeDevice();
295
296 // BGRA texture support is optional in feature levels 10 and 10_1
297 UINT formatSupport;
298 result = mDevice->CheckFormatSupport(DXGI_FORMAT_B8G8R8A8_UNORM, &formatSupport);
299 if (FAILED(result))
300 {
301 ERR("Error checking BGRA format support: 0x%08X", result);
302 }
303 else
304 {
305 const int flags = (D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_RENDER_TARGET);
306 mBGRATextureSupport = (formatSupport & flags) == flags;
307 }
308
309 // Check floating point texture support
310 static const unsigned int requiredTextureFlags = D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_TEXTURECUBE;
311 static const unsigned int requiredRenderableFlags = D3D11_FORMAT_SUPPORT_RENDER_TARGET;
312 static const unsigned int requiredFilterFlags = D3D11_FORMAT_SUPPORT_SHADER_SAMPLE;
313
314 DXGI_FORMAT float16Formats[] =
315 {
316 DXGI_FORMAT_R16_FLOAT,
317 DXGI_FORMAT_R16G16_FLOAT,
318 DXGI_FORMAT_R16G16B16A16_FLOAT,
319 };
320
321 DXGI_FORMAT float32Formats[] =
322 {
323 DXGI_FORMAT_R32_FLOAT,
324 DXGI_FORMAT_R32G32_FLOAT,
325 DXGI_FORMAT_R32G32B32_FLOAT,
326 DXGI_FORMAT_R32G32B32A32_FLOAT,
327 };
328
329 mFloat16TextureSupport = true;
330 mFloat16FilterSupport = true;
331 mFloat16RenderSupport = true;
332 for (unsigned int i = 0; i < ArraySize(float16Formats); i++)
333 {
334 if (SUCCEEDED(mDevice->CheckFormatSupport(float16Formats[i], &formatSupport)))
335 {
336 mFloat16TextureSupport = mFloat16TextureSupport && (formatSupport & requiredTextureFlags) == requiredTextureFlags;
337 mFloat16FilterSupport = mFloat16FilterSupport && (formatSupport & requiredFilterFlags) == requiredFilterFlags;
338 mFloat16RenderSupport = mFloat16RenderSupport && (formatSupport & requiredRenderableFlags) == requiredRenderableFlags;
339 }
340 else
341 {
342 mFloat16TextureSupport = false;
343 mFloat16RenderSupport = false;
344 mFloat16FilterSupport = false;
345 }
346 }
347
348 mFloat32TextureSupport = true;
349 mFloat32FilterSupport = true;
350 mFloat32RenderSupport = true;
351 for (unsigned int i = 0; i < ArraySize(float32Formats); i++)
352 {
353 if (SUCCEEDED(mDevice->CheckFormatSupport(float32Formats[i], &formatSupport)))
354 {
355 mFloat32TextureSupport = mFloat32TextureSupport && (formatSupport & requiredTextureFlags) == requiredTextureFlags;
356 mFloat32FilterSupport = mFloat32FilterSupport && (formatSupport & requiredFilterFlags) == requiredFilterFlags;
357 mFloat32RenderSupport = mFloat32RenderSupport && (formatSupport & requiredRenderableFlags) == requiredRenderableFlags;
358 }
359 else
360 {
361 mFloat32TextureSupport = false;
362 mFloat32FilterSupport = false;
363 mFloat32RenderSupport = false;
364 }
365 }
366
367 // Check compressed texture support
368 const unsigned int requiredCompressedTextureFlags = D3D11_FORMAT_SUPPORT_TEXTURE2D;
369
370 if (SUCCEEDED(mDevice->CheckFormatSupport(DXGI_FORMAT_BC1_UNORM, &formatSupport)))
371 {
372 mDXT1TextureSupport = (formatSupport & requiredCompressedTextureFlags) == requiredCompressedTextureFlags;
373 }
374 else
375 {
376 mDXT1TextureSupport = false;
377 }
378
379 if (SUCCEEDED(mDevice->CheckFormatSupport(DXGI_FORMAT_BC3_UNORM, &formatSupport)))
380 {
381 mDXT3TextureSupport = (formatSupport & requiredCompressedTextureFlags) == requiredCompressedTextureFlags;
382 }
383 else
384 {
385 mDXT3TextureSupport = false;
386 }
387
388 if (SUCCEEDED(mDevice->CheckFormatSupport(DXGI_FORMAT_BC5_UNORM, &formatSupport)))
389 {
390 mDXT5TextureSupport = (formatSupport & requiredCompressedTextureFlags) == requiredCompressedTextureFlags;
391 }
392 else
393 {
394 mDXT5TextureSupport = false;
395 }
396
397 // Check depth texture support
398 DXGI_FORMAT depthTextureFormats[] =
399 {
400 DXGI_FORMAT_D16_UNORM,
401 DXGI_FORMAT_D24_UNORM_S8_UINT,
402 };
403
404 static const unsigned int requiredDepthTextureFlags = D3D11_FORMAT_SUPPORT_DEPTH_STENCIL |
405 D3D11_FORMAT_SUPPORT_TEXTURE2D;
406
407 mDepthTextureSupport = true;
408 for (unsigned int i = 0; i < ArraySize(depthTextureFormats); i++)
409 {
410 if (SUCCEEDED(mDevice->CheckFormatSupport(depthTextureFormats[i], &formatSupport)))
411 {
412 mDepthTextureSupport = mDepthTextureSupport && ((formatSupport & requiredDepthTextureFlags) == requiredDepthTextureFlags);
413 }
414 else
415 {
416 mDepthTextureSupport = false;
417 }
418 }
419
420 return EGL_SUCCESS;
421 }
422
423 // do any one-time device initialization
424 // NOTE: this is also needed after a device lost/reset
425 // to reset the scene status and ensure the default states are reset.
426 void Renderer11::initializeDevice()
427 {
428 mStateCache.initialize(mDevice);
429 mInputLayoutCache.initialize(mDevice, mDeviceContext);
430
431 ASSERT(!mVertexDataManager && !mIndexDataManager);
432 mVertexDataManager = new VertexDataManager(this);
433 mIndexDataManager = new IndexDataManager(this);
434
435 markAllStateDirty();
436 }
437
438 int Renderer11::generateConfigs(ConfigDesc **configDescList)
439 {
440 unsigned int numRenderFormats = ArraySize(RenderTargetFormats);
441 unsigned int numDepthFormats = ArraySize(DepthStencilFormats);
442 (*configDescList) = new ConfigDesc[numRenderFormats * numDepthFormats];
443 int numConfigs = 0;
444
445 for (unsigned int formatIndex = 0; formatIndex < numRenderFormats; formatIndex++)
446 {
447 for (unsigned int depthStencilIndex = 0; depthStencilIndex < numDepthFormats; depthStencilIndex++)
448 {
449 DXGI_FORMAT renderTargetFormat = RenderTargetFormats[formatIndex];
450
451 UINT formatSupport = 0;
452 HRESULT result = mDevice->CheckFormatSupport(renderTargetFormat, &formatSupport);
453
454 if (SUCCEEDED(result) && (formatSupport & D3D11_FORMAT_SUPPORT_RENDER_TARGET))
455 {
456 DXGI_FORMAT depthStencilFormat = DepthStencilFormats[depthStencilIndex];
457
458 bool depthStencilFormatOK = true;
459
460 if (depthStencilFormat != DXGI_FORMAT_UNKNOWN)
461 {
462 UINT formatSupport = 0;
463 result = mDevice->CheckFormatSupport(depthStencilFormat, &formatSupport);
464 depthStencilFormatOK = SUCCEEDED(result) && (formatSupport & D3D11_FORMAT_SUPPORT_DEPTH_STENCIL);
465 }
466
467 if (depthStencilFormatOK)
468 {
469 ConfigDesc newConfig;
470 newConfig.renderTargetFormat = d3d11_gl::ConvertBackBufferFormat(renderTargetFormat);
471 newConfig.depthStencilFormat = d3d11_gl::ConvertDepthStencilFormat(depthStencilFormat);
472 newConfig.multiSample = 0; // FIXME: enumerate multi-sampling
473 newConfig.fastConfig = true; // Assume all DX11 format conversions to be fast
474
475 (*configDescList)[numConfigs++] = newConfig;
476 }
477 }
478 }
479 }
480
481 return numConfigs;
482 }
483
484 void Renderer11::deleteConfigs(ConfigDesc *configDescList)
485 {
486 delete [] (configDescList);
487 }
488
489 void Renderer11::sync(bool block)
490 {
491 if (block)
492 {
493 HRESULT result;
494
495 if (!mSyncQuery)
496 {
497 D3D11_QUERY_DESC queryDesc;
498 queryDesc.Query = D3D11_QUERY_EVENT;
499 queryDesc.MiscFlags = 0;
500
501 result = mDevice->CreateQuery(&queryDesc, &mSyncQuery);
502 ASSERT(SUCCEEDED(result));
503 }
504
505 mDeviceContext->End(mSyncQuery);
506 mDeviceContext->Flush();
507
508 do
509 {
510 result = mDeviceContext->GetData(mSyncQuery, NULL, 0, D3D11_ASYNC_GETDATA_DONOTFLUSH);
511
512 // Keep polling, but allow other threads to do something useful first
513 Sleep(0);
514
515 if (testDeviceLost(true))
516 {
517 return;
518 }
519 }
520 while (result == S_FALSE);
521 }
522 else
523 {
524 mDeviceContext->Flush();
525 }
526 }
527
528 SwapChain *Renderer11::createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat)
529 {
530 return new rx::SwapChain11(this, window, shareHandle, backBufferFormat, depthBufferFormat);
531 }
532
533 void Renderer11::setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &samplerState)
534 {
535 if (type == gl::SAMPLER_PIXEL)
536 {
537 if (index < 0 || index >= gl::MAX_TEXTURE_IMAGE_UNITS)
538 {
539 ERR("Pixel shader sampler index %i is not valid.", index);
540 return;
541 }
542
543 if (mForceSetPixelSamplerStates[index] || memcmp(&samplerState, &mCurPixelSamplerStates[index], sizeof(gl::SamplerState)) != 0)
544 {
545 ID3D11SamplerState *dxSamplerState = mStateCache.getSamplerState(samplerState);
546
547 if (!dxSamplerState)
548 {
549 ERR("NULL sampler state returned by RenderStateCache::getSamplerState, setting the default"
550 "sampler state for pixel shaders at slot %i.", index);
551 }
552
553 mDeviceContext->PSSetSamplers(index, 1, &dxSamplerState);
554
555 mCurPixelSamplerStates[index] = samplerState;
556 }
557
558 mForceSetPixelSamplerStates[index] = false;
559 }
560 else if (type == gl::SAMPLER_VERTEX)
561 {
562 if (index < 0 || index >= (int)getMaxVertexTextureImageUnits())
563 {
564 ERR("Vertex shader sampler index %i is not valid.", index);
565 return;
566 }
567
568 if (mForceSetVertexSamplerStates[index] || memcmp(&samplerState, &mCurVertexSamplerStates[index], sizeof(gl::SamplerState)) != 0)
569 {
570 ID3D11SamplerState *dxSamplerState = mStateCache.getSamplerState(samplerState);
571
572 if (!dxSamplerState)
573 {
574 ERR("NULL sampler state returned by RenderStateCache::getSamplerState, setting the default"
575 "sampler state for vertex shaders at slot %i.", index);
576 }
577
578 mDeviceContext->VSSetSamplers(index, 1, &dxSamplerState);
579
580 mCurVertexSamplerStates[index] = samplerState;
581 }
582
583 mForceSetVertexSamplerStates[index] = false;
584 }
585 else UNREACHABLE();
586 }
587
588 void Renderer11::setTexture(gl::SamplerType type, int index, gl::Texture *texture)
589 {
590 ID3D11ShaderResourceView *textureSRV = NULL;
591 unsigned int serial = 0;
592 bool forceSetTexture = false;
593
594 if (texture)
595 {
596 TextureStorageInterface *texStorage = texture->getNativeTexture();
597 if (texStorage)
598 {
599 TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(texStorage->getStorageInstance());
600 textureSRV = storage11->getSRV();
601 }
602
603 // If we get NULL back from getSRV here, something went wrong in the texture class and we're unexpectedly
604 // missing the shader resource view
605 ASSERT(textureSRV != NULL);
606
607 serial = texture->getTextureSerial();
608 forceSetTexture = texture->hasDirtyImages();
609 }
610
611 if (type == gl::SAMPLER_PIXEL)
612 {
613 if (index < 0 || index >= gl::MAX_TEXTURE_IMAGE_UNITS)
614 {
615 ERR("Pixel shader sampler index %i is not valid.", index);
616 return;
617 }
618
619 if (forceSetTexture || mCurPixelTextureSerials[index] != serial)
620 {
621 mDeviceContext->PSSetShaderResources(index, 1, &textureSRV);
622 }
623
624 mCurPixelTextureSerials[index] = serial;
625 }
626 else if (type == gl::SAMPLER_VERTEX)
627 {
628 if (index < 0 || index >= (int)getMaxVertexTextureImageUnits())
629 {
630 ERR("Vertex shader sampler index %i is not valid.", index);
631 return;
632 }
633
634 if (forceSetTexture || mCurVertexTextureSerials[index] != serial)
635 {
636 mDeviceContext->VSSetShaderResources(index, 1, &textureSRV);
637 }
638
639 mCurVertexTextureSerials[index] = serial;
640 }
641 else UNREACHABLE();
642 }
643
644 void Renderer11::setRasterizerState(const gl::RasterizerState &rasterState)
645 {
646 if (mForceSetRasterState || memcmp(&rasterState, &mCurRasterState, sizeof(gl::RasterizerState)) != 0)
647 {
648 ID3D11RasterizerState *dxRasterState = mStateCache.getRasterizerState(rasterState, mScissorEnabled,
649 mCurDepthSize);
650 if (!dxRasterState)
651 {
652 ERR("NULL rasterizer state returned by RenderStateCache::getRasterizerState, setting the default"
653 "rasterizer state.");
654 }
655
656 mDeviceContext->RSSetState(dxRasterState);
657
658 mCurRasterState = rasterState;
659 }
660
661 mForceSetRasterState = false;
662 }
663
664 void Renderer11::setBlendState(const gl::BlendState &blendState, const gl::Color &blendColor,
665 unsigned int sampleMask)
666 {
667 if (mForceSetBlendState ||
668 memcmp(&blendState, &mCurBlendState, sizeof(gl::BlendState)) != 0 ||
669 memcmp(&blendColor, &mCurBlendColor, sizeof(gl::Color)) != 0 ||
670 sampleMask != mCurSampleMask)
671 {
672 ID3D11BlendState *dxBlendState = mStateCache.getBlendState(blendState);
673 if (!dxBlendState)
674 {
675 ERR("NULL blend state returned by RenderStateCache::getBlendState, setting the default "
676 "blend state.");
677 }
678
679 float blendColors[4] = {0.0f};
680 if (blendState.sourceBlendRGB != GL_CONSTANT_ALPHA && blendState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA &&
681 blendState.destBlendRGB != GL_CONSTANT_ALPHA && blendState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA)
682 {
683 blendColors[0] = blendColor.red;
684 blendColors[1] = blendColor.green;
685 blendColors[2] = blendColor.blue;
686 blendColors[3] = blendColor.alpha;
687 }
688 else
689 {
690 blendColors[0] = blendColor.alpha;
691 blendColors[1] = blendColor.alpha;
692 blendColors[2] = blendColor.alpha;
693 blendColors[3] = blendColor.alpha;
694 }
695
696 mDeviceContext->OMSetBlendState(dxBlendState, blendColors, sampleMask);
697
698 mCurBlendState = blendState;
699 mCurBlendColor = blendColor;
700 mCurSampleMask = sampleMask;
701 }
702
703 mForceSetBlendState = false;
704 }
705
706 void Renderer11::setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef,
707 int stencilBackRef, bool frontFaceCCW)
708 {
709 if (mForceSetDepthStencilState ||
710 memcmp(&depthStencilState, &mCurDepthStencilState, sizeof(gl::DepthStencilState)) != 0 ||
711 stencilRef != mCurStencilRef || stencilBackRef != mCurStencilBackRef)
712 {
713 if (depthStencilState.stencilWritemask != depthStencilState.stencilBackWritemask ||
714 stencilRef != stencilBackRef ||
715 depthStencilState.stencilMask != depthStencilState.stencilBackMask)
716 {
717 ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are "
718 "invalid under WebGL.");
719 return gl::error(GL_INVALID_OPERATION);
720 }
721
722 ID3D11DepthStencilState *dxDepthStencilState = mStateCache.getDepthStencilState(depthStencilState);
723 if (!dxDepthStencilState)
724 {
725 ERR("NULL depth stencil state returned by RenderStateCache::getDepthStencilState, "
726 "setting the default depth stencil state.");
727 }
728
729 mDeviceContext->OMSetDepthStencilState(dxDepthStencilState, static_cast<UINT>(stencilRef));
730
731 mCurDepthStencilState = depthStencilState;
732 mCurStencilRef = stencilRef;
733 mCurStencilBackRef = stencilBackRef;
734 }
735
736 mForceSetDepthStencilState = false;
737 }
738
739 void Renderer11::setScissorRectangle(const gl::Rectangle &scissor, bool enabled)
740 {
741 if (mForceSetScissor || memcmp(&scissor, &mCurScissor, sizeof(gl::Rectangle)) != 0 ||
742 enabled != mScissorEnabled)
743 {
744 if (enabled)
745 {
746 D3D11_RECT rect;
747 rect.left = std::max(0, scissor.x);
748 rect.top = std::max(0, scissor.y);
749 rect.right = scissor.x + std::max(0, scissor.width);
750 rect.bottom = scissor.y + std::max(0, scissor.height);
751
752 mDeviceContext->RSSetScissorRects(1, &rect);
753 }
754
755 if (enabled != mScissorEnabled)
756 {
757 mForceSetRasterState = true;
758 }
759
760 mCurScissor = scissor;
761 mScissorEnabled = enabled;
762 }
763
764 mForceSetScissor = false;
765 }
766
767 bool Renderer11::setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace,
768 bool ignoreViewport)
769 {
770 gl::Rectangle actualViewport = viewport;
771 float actualZNear = gl::clamp01(zNear);
772 float actualZFar = gl::clamp01(zFar);
773 if (ignoreViewport)
774 {
775 actualViewport.x = 0;
776 actualViewport.y = 0;
777 actualViewport.width = mRenderTargetDesc.width;
778 actualViewport.height = mRenderTargetDesc.height;
779 actualZNear = 0.0f;
780 actualZFar = 1.0f;
781 }
782
783 // Get D3D viewport bounds, which depends on the feature level
784 const Range& viewportBounds = getViewportBounds();
785
786 // Clamp width and height first to the gl maximum, then clamp further if we extend past the D3D maximum bounds
787 D3D11_VIEWPORT dxViewport;
788 dxViewport.TopLeftX = gl::clamp(actualViewport.x, viewportBounds.start, viewportBounds.end);
789 dxViewport.TopLeftY = gl::clamp(actualViewport.y, viewportBounds.start, viewportBounds.end);
790 dxViewport.Width = gl::clamp(actualViewport.width, 0, getMaxViewportDimension());
791 dxViewport.Height = gl::clamp(actualViewport.height, 0, getMaxViewportDimension());
792 dxViewport.Width = std::min((int)dxViewport.Width, viewportBounds.end - static_cast<int>(dxViewport.TopLeftX));
793 dxViewport.Height = std::min((int)dxViewport.Height, viewportBounds.end - static_cast<int>(dxViewport.TopLeftY));
794 dxViewport.MinDepth = actualZNear;
795 dxViewport.MaxDepth = actualZFar;
796
797 if (dxViewport.Width <= 0 || dxViewport.Height <= 0)
798 {
799 return false; // Nothing to render
800 }
801
802 bool viewportChanged = mForceSetViewport || memcmp(&actualViewport, &mCurViewport, sizeof(gl::Rectangle)) != 0 ||
803 actualZNear != mCurNear || actualZFar != mCurFar;
804
805 if (viewportChanged)
806 {
807 mDeviceContext->RSSetViewports(1, &dxViewport);
808
809 mCurViewport = actualViewport;
810 mCurNear = actualZNear;
811 mCurFar = actualZFar;
812
813 mPixelConstants.viewCoords[0] = actualViewport.width * 0.5f;
814 mPixelConstants.viewCoords[1] = actualViewport.height * 0.5f;
815 mPixelConstants.viewCoords[2] = actualViewport.x + (actualViewport.width * 0.5f);
816 mPixelConstants.viewCoords[3] = actualViewport.y + (actualViewport.height * 0.5f);
817
818 mPixelConstants.depthFront[0] = (actualZFar - actualZNear) * 0.5f;
819 mPixelConstants.depthFront[1] = (actualZNear + actualZFar) * 0.5f;
820
821 mVertexConstants.depthRange[0] = actualZNear;
822 mVertexConstants.depthRange[1] = actualZFar;
823 mVertexConstants.depthRange[2] = actualZFar - actualZNear;
824
825 mPixelConstants.depthRange[0] = actualZNear;
826 mPixelConstants.depthRange[1] = actualZFar;
827 mPixelConstants.depthRange[2] = actualZFar - actualZNear;
828 }
829
830 mForceSetViewport = false;
831 return true;
832 }
833
834 bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count)
835 {
836 D3D11_PRIMITIVE_TOPOLOGY primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
837
838 GLsizei minCount = 0;
839
840 switch (mode)
841 {
842 case GL_POINTS: primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST; minCount = 1; break;
843 case GL_LINES: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINELIST; minCount = 2; break;
844 case GL_LINE_LOOP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; minCount = 2; break;
845 case GL_LINE_STRIP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; minCount = 2; break;
846 case GL_TRIANGLES: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; minCount = 3; break;
847 case GL_TRIANGLE_STRIP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; minCount = 3; break;
848 // emulate fans via rewriting index buffer
849 case GL_TRIANGLE_FAN: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; minCount = 3; break;
850 default:
851 return gl::error(GL_INVALID_ENUM, false);
852 }
853
854 if (primitiveTopology != mCurrentPrimitiveTopology)
855 {
856 mDeviceContext->IASetPrimitiveTopology(primitiveTopology);
857 mCurrentPrimitiveTopology = primitiveTopology;
858 }
859
860 return count >= minCount;
861 }
862
863 bool Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer)
864 {
865 // Get the color render buffer and serial
866 // Also extract the render target dimensions and view
867 unsigned int renderTargetWidth = 0;
868 unsigned int renderTargetHeight = 0;
869 GLenum renderTargetFormat = 0;
870 unsigned int renderTargetSerials[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {0};
871 ID3D11RenderTargetView* framebufferRTVs[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {NULL};
872 bool missingColorRenderTarget = true;
873
874 for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
875 {
876 const GLenum drawBufferState = framebuffer->getDrawBufferState(colorAttachment);
877
878 if (framebuffer->getColorbufferType(colorAttachment) != GL_NONE && drawBufferState != GL_NONE)
879 {
880 // the draw buffer must be either "none", "back" for the default buffer or the same index as this color (in order)
881 ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + colorAttachment));
882
883 gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer(colorAttachment);
884
885 if (!colorbuffer)
886 {
887 ERR("render target pointer unexpectedly null.");
888 return false;
889 }
890
891 // check for zero-sized default framebuffer, which is a special case.
892 // in this case we do not wish to modify any state and just silently return false.
893 // this will not report any gl error but will cause the calling method to return.
894 if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0)
895 {
896 return false;
897 }
898
899 renderTargetSerials[colorAttachment] = colorbuffer->getSerial();
900
901 // Extract the render target dimensions and view
902 RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget());
903 if (!renderTarget)
904 {
905 ERR("render target pointer unexpectedly null.");
906 return false;
907 }
908
909 framebufferRTVs[colorAttachment] = renderTarget->getRenderTargetView();
910 if (!framebufferRTVs[colorAttachment])
911 {
912 ERR("render target view pointer unexpectedly null.");
913 return false;
914 }
915
916 if (missingColorRenderTarget)
917 {
918 renderTargetWidth = colorbuffer->getWidth();
919 renderTargetHeight = colorbuffer->getHeight();
920 renderTargetFormat = colorbuffer->getActualFormat();
921 missingColorRenderTarget = false;
922 }
923 }
924 }
925
926 // Get the depth stencil render buffer and serials
927 gl::Renderbuffer *depthStencil = NULL;
928 unsigned int depthbufferSerial = 0;
929 unsigned int stencilbufferSerial = 0;
930 if (framebuffer->getDepthbufferType() != GL_NONE)
931 {
932 depthStencil = framebuffer->getDepthbuffer();
933 if (!depthStencil)
934 {
935 ERR("Depth stencil pointer unexpectedly null.");
936 SafeRelease(framebufferRTVs);
937 return false;
938 }
939
940 depthbufferSerial = depthStencil->getSerial();
941 }
942 else if (framebuffer->getStencilbufferType() != GL_NONE)
943 {
944 depthStencil = framebuffer->getStencilbuffer();
945 if (!depthStencil)
946 {
947 ERR("Depth stencil pointer unexpectedly null.");
948 SafeRelease(framebufferRTVs);
949 return false;
950 }
951
952 stencilbufferSerial = depthStencil->getSerial();
953 }
954
955 // Extract the depth stencil sizes and view
956 unsigned int depthSize = 0;
957 unsigned int stencilSize = 0;
958 ID3D11DepthStencilView* framebufferDSV = NULL;
959 if (depthStencil)
960 {
961 RenderTarget11 *depthStencilRenderTarget = RenderTarget11::makeRenderTarget11(depthStencil->getDepthStencil());
962 if (!depthStencilRenderTarget)
963 {
964 ERR("render target pointer unexpectedly null.");
965 SafeRelease(framebufferRTVs);
966 return false;
967 }
968
969 framebufferDSV = depthStencilRenderTarget->getDepthStencilView();
970 if (!framebufferDSV)
971 {
972 ERR("depth stencil view pointer unexpectedly null.");
973 SafeRelease(framebufferRTVs);
974 return false;
975 }
976
977 // If there is no render buffer, the width, height and format values come from
978 // the depth stencil
979 if (missingColorRenderTarget)
980 {
981 renderTargetWidth = depthStencil->getWidth();
982 renderTargetHeight = depthStencil->getHeight();
983 renderTargetFormat = depthStencil->getActualFormat();
984 }
985
986 depthSize = depthStencil->getDepthSize();
987 stencilSize = depthStencil->getStencilSize();
988 }
989
990 // Apply the render target and depth stencil
991 if (!mRenderTargetDescInitialized || !mDepthStencilInitialized ||
992 memcmp(renderTargetSerials, mAppliedRenderTargetSerials, sizeof(renderTargetSerials)) != 0 ||
993 depthbufferSerial != mAppliedDepthbufferSerial ||
994 stencilbufferSerial != mAppliedStencilbufferSerial)
995 {
996 mDeviceContext->OMSetRenderTargets(getMaxRenderTargets(), framebufferRTVs, framebufferDSV);
997
998 mRenderTargetDesc.width = renderTargetWidth;
999 mRenderTargetDesc.height = renderTargetHeight;
1000 mRenderTargetDesc.format = renderTargetFormat;
1001 mForceSetViewport = true;
1002 mForceSetScissor = true;
1003
1004 if (!mDepthStencilInitialized || depthSize != mCurDepthSize)
1005 {
1006 mCurDepthSize = depthSize;
1007 mForceSetRasterState = true;
1008 }
1009
1010 mCurStencilSize = stencilSize;
1011
1012 for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++)
1013 {
1014 mAppliedRenderTargetSerials[rtIndex] = renderTargetSerials[rtIndex];
1015 }
1016 mAppliedDepthbufferSerial = depthbufferSerial;
1017 mAppliedStencilbufferSerial = stencilbufferSerial;
1018 mRenderTargetDescInitialized = true;
1019 mDepthStencilInitialized = true;
1020 }
1021
1022 return true;
1023 }
1024
1025 GLenum Renderer11::applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances)
1026 {
1027 TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS];
1028 GLenum err = mVertexDataManager->prepareVertexData(vertexAttributes, programBinary, first, count, attributes, instances);
1029 if (err != GL_NO_ERROR)
1030 {
1031 return err;
1032 }
1033
1034 return mInputLayoutCache.applyVertexBuffers(attributes, programBinary);
1035 }
1036
1037 GLenum Renderer11::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo)
1038 {
1039 GLenum err = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo);
1040
1041 if (err == GL_NO_ERROR)
1042 {
1043 if (indexInfo->storage)
1044 {
1045 if (indexInfo->serial != mAppliedStorageIBSerial || indexInfo->startOffset != mAppliedIBOffset)
1046 {
1047 BufferStorage11 *storage = BufferStorage11::makeBufferStorage11(indexInfo->storage);
1048 IndexBuffer11* indexBuffer = IndexBuffer11::makeIndexBuffer11(indexInfo->indexBuffer);
1049
1050 mDeviceContext->IASetIndexBuffer(storage->getBuffer(), indexBuffer->getIndexFormat(), indexInfo->startOffset);
1051
1052 mAppliedIBSerial = 0;
1053 mAppliedStorageIBSerial = storage->getSerial();
1054 mAppliedIBOffset = indexInfo->startOffset;
1055 }
1056 }
1057 else if (indexInfo->serial != mAppliedIBSerial || indexInfo->startOffset != mAppliedIBOffset)
1058 {
1059 IndexBuffer11* indexBuffer = IndexBuffer11::makeIndexBuffer11(indexInfo->indexBuffer);
1060
1061 mDeviceContext->IASetIndexBuffer(indexBuffer->getBuffer(), indexBuffer->getIndexFormat(), indexInfo->startOffset);
1062
1063 mAppliedIBSerial = indexInfo->serial;
1064 mAppliedStorageIBSerial = 0;
1065 mAppliedIBOffset = indexInfo->startOffset;
1066 }
1067 }
1068
1069 return err;
1070 }
1071
1072 void Renderer11::drawArrays(GLenum mode, GLsizei count, GLsizei instances)
1073 {
1074 if (mode == GL_LINE_LOOP)
1075 {
1076 drawLineLoop(count, GL_NONE, NULL, 0, NULL);
1077 }
1078 else if (mode == GL_TRIANGLE_FAN)
1079 {
1080 drawTriangleFan(count, GL_NONE, NULL, 0, NULL, instances);
1081 }
1082 else if (instances > 0)
1083 {
1084 mDeviceContext->DrawInstanced(count, instances, 0, 0);
1085 }
1086 else
1087 {
1088 mDeviceContext->Draw(count, 0);
1089 }
1090 }
1091
1092 void Renderer11::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances)
1093 {
1094 if (mode == GL_LINE_LOOP)
1095 {
1096 drawLineLoop(count, type, indices, indexInfo.minIndex, elementArrayBuffer);
1097 }
1098 else if (mode == GL_TRIANGLE_FAN)
1099 {
1100 drawTriangleFan(count, type, indices, indexInfo.minIndex, elementArrayBuffer, instances);
1101 }
1102 else if (instances > 0)
1103 {
1104 mDeviceContext->DrawIndexedInstanced(count, instances, 0, -static_cast<int>(indexInfo.minIndex), 0);
1105 }
1106 else
1107 {
1108 mDeviceContext->DrawIndexed(count, 0, -static_cast<int>(indexInfo.minIndex));
1109 }
1110 }
1111
1112 void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer)
1113 {
1114 // Get the raw indices for an indexed draw
1115 if (type != GL_NONE && elementArrayBuffer)
1116 {
1117 gl::Buffer *indexBuffer = elementArrayBuffer;
1118 BufferStorage *storage = indexBuffer->getStorage();
1119 intptr_t offset = reinterpret_cast<intptr_t>(indices);
1120 indices = static_cast<const GLubyte*>(storage->getData()) + offset;
1121 }
1122
1123 if (!mLineLoopIB)
1124 {
1125 mLineLoopIB = new StreamingIndexBufferInterface(this);
1126 if (!mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT))
1127 {
1128 delete mLineLoopIB;
1129 mLineLoopIB = NULL;
1130
1131 ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP.");
1132 return gl::error(GL_OUT_OF_MEMORY);
1133 }
1134 }
1135
1136 // Checked by Renderer11::applyPrimitiveType
1137 ASSERT(count >= 0);
1138
1139 if (static_cast<unsigned int>(count) + 1 > (std::numeric_limits<unsigned int>::max() / sizeof(unsigned int)))
1140 {
1141 ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required.");
1142 return gl::error(GL_OUT_OF_MEMORY);
1143 }
1144
1145 const unsigned int spaceNeeded = (static_cast<unsigned int>(count) + 1) * sizeof(unsigned int);
1146 if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT))
1147 {
1148 ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP.");
1149 return gl::error(GL_OUT_OF_MEMORY);
1150 }
1151
1152 void* mappedMemory = NULL;
1153 unsigned int offset;
1154 if (!mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset))
1155 {
1156 ERR("Could not map index buffer for GL_LINE_LOOP.");
1157 return gl::error(GL_OUT_OF_MEMORY);
1158 }
1159
1160 unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory);
1161 unsigned int indexBufferOffset = offset;
1162
1163 switch (type)
1164 {
1165 case GL_NONE: // Non-indexed draw
1166 for (int i = 0; i < count; i++)
1167 {
1168 data[i] = i;
1169 }
1170 data[count] = 0;
1171 break;
1172 case GL_UNSIGNED_BYTE:
1173 for (int i = 0; i < count; i++)
1174 {
1175 data[i] = static_cast<const GLubyte*>(indices)[i];
1176 }
1177 data[count] = static_cast<const GLubyte*>(indices)[0];
1178 break;
1179 case GL_UNSIGNED_SHORT:
1180 for (int i = 0; i < count; i++)
1181 {
1182 data[i] = static_cast<const GLushort*>(indices)[i];
1183 }
1184 data[count] = static_cast<const GLushort*>(indices)[0];
1185 break;
1186 case GL_UNSIGNED_INT:
1187 for (int i = 0; i < count; i++)
1188 {
1189 data[i] = static_cast<const GLuint*>(indices)[i];
1190 }
1191 data[count] = static_cast<const GLuint*>(indices)[0];
1192 break;
1193 default: UNREACHABLE();
1194 }
1195
1196 if (!mLineLoopIB->unmapBuffer())
1197 {
1198 ERR("Could not unmap index buffer for GL_LINE_LOOP.");
1199 return gl::error(GL_OUT_OF_MEMORY);
1200 }
1201
1202 if (mAppliedIBSerial != mLineLoopIB->getSerial() || mAppliedIBOffset != indexBufferOffset)
1203 {
1204 IndexBuffer11 *indexBuffer = IndexBuffer11::makeIndexBuffer11(mLineLoopIB->getIndexBuffer());
1205
1206 mDeviceContext->IASetIndexBuffer(indexBuffer->getBuffer(), indexBuffer->getIndexFormat(), indexBufferOffset);
1207 mAppliedIBSerial = mLineLoopIB->getSerial();
1208 mAppliedStorageIBSerial = 0;
1209 mAppliedIBOffset = indexBufferOffset;
1210 }
1211
1212 mDeviceContext->DrawIndexed(count + 1, 0, -minIndex);
1213 }
1214
1215 void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer, int instances)
1216 {
1217 // Get the raw indices for an indexed draw
1218 if (type != GL_NONE && elementArrayBuffer)
1219 {
1220 gl::Buffer *indexBuffer = elementArrayBuffer;
1221 BufferStorage *storage = indexBuffer->getStorage();
1222 intptr_t offset = reinterpret_cast<intptr_t>(indices);
1223 indices = static_cast<const GLubyte*>(storage->getData()) + offset;
1224 }
1225
1226 if (!mTriangleFanIB)
1227 {
1228 mTriangleFanIB = new StreamingIndexBufferInterface(this);
1229 if (!mTriangleFanIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT))
1230 {
1231 delete mTriangleFanIB;
1232 mTriangleFanIB = NULL;
1233
1234 ERR("Could not create a scratch index buffer for GL_TRIANGLE_FAN.");
1235 return gl::error(GL_OUT_OF_MEMORY);
1236 }
1237 }
1238
1239 // Checked by Renderer11::applyPrimitiveType
1240 ASSERT(count >= 3);
1241
1242 const unsigned int numTris = count - 2;
1243
1244 if (numTris > (std::numeric_limits<unsigned int>::max() / (sizeof(unsigned int) * 3)))
1245 {
1246 ERR("Could not create a scratch index buffer for GL_TRIANGLE_FAN, too many indices required.");
1247 return gl::error(GL_OUT_OF_MEMORY);
1248 }
1249
1250 const unsigned int spaceNeeded = (numTris * 3) * sizeof(unsigned int);
1251 if (!mTriangleFanIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT))
1252 {
1253 ERR("Could not reserve enough space in scratch index buffer for GL_TRIANGLE_FAN.");
1254 return gl::error(GL_OUT_OF_MEMORY);
1255 }
1256
1257 void* mappedMemory = NULL;
1258 unsigned int offset;
1259 if (!mTriangleFanIB->mapBuffer(spaceNeeded, &mappedMemory, &offset))
1260 {
1261 ERR("Could not map scratch index buffer for GL_TRIANGLE_FAN.");
1262 return gl::error(GL_OUT_OF_MEMORY);
1263 }
1264
1265 unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory);
1266 unsigned int indexBufferOffset = offset;
1267
1268 switch (type)
1269 {
1270 case GL_NONE: // Non-indexed draw
1271 for (unsigned int i = 0; i < numTris; i++)
1272 {
1273 data[i*3 + 0] = 0;
1274 data[i*3 + 1] = i + 1;
1275 data[i*3 + 2] = i + 2;
1276 }
1277 break;
1278 case GL_UNSIGNED_BYTE:
1279 for (unsigned int i = 0; i < numTris; i++)
1280 {
1281 data[i*3 + 0] = static_cast<const GLubyte*>(indices)[0];
1282 data[i*3 + 1] = static_cast<const GLubyte*>(indices)[i + 1];
1283 data[i*3 + 2] = static_cast<const GLubyte*>(indices)[i + 2];
1284 }
1285 break;
1286 case GL_UNSIGNED_SHORT:
1287 for (unsigned int i = 0; i < numTris; i++)
1288 {
1289 data[i*3 + 0] = static_cast<const GLushort*>(indices)[0];
1290 data[i*3 + 1] = static_cast<const GLushort*>(indices)[i + 1];
1291 data[i*3 + 2] = static_cast<const GLushort*>(indices)[i + 2];
1292 }
1293 break;
1294 case GL_UNSIGNED_INT:
1295 for (unsigned int i = 0; i < numTris; i++)
1296 {
1297 data[i*3 + 0] = static_cast<const GLuint*>(indices)[0];
1298 data[i*3 + 1] = static_cast<const GLuint*>(indices)[i + 1];
1299 data[i*3 + 2] = static_cast<const GLuint*>(indices)[i + 2];
1300 }
1301 break;
1302 default: UNREACHABLE();
1303 }
1304
1305 if (!mTriangleFanIB->unmapBuffer())
1306 {
1307 ERR("Could not unmap scratch index buffer for GL_TRIANGLE_FAN.");
1308 return gl::error(GL_OUT_OF_MEMORY);
1309 }
1310
1311 if (mAppliedIBSerial != mTriangleFanIB->getSerial() || mAppliedIBOffset != indexBufferOffset)
1312 {
1313 IndexBuffer11 *indexBuffer = IndexBuffer11::makeIndexBuffer11(mTriangleFanIB->getIndexBuffer());
1314
1315 mDeviceContext->IASetIndexBuffer(indexBuffer->getBuffer(), indexBuffer->getIndexFormat(), indexBufferOffset);
1316 mAppliedIBSerial = mTriangleFanIB->getSerial();
1317 mAppliedStorageIBSerial = 0;
1318 mAppliedIBOffset = indexBufferOffset;
1319 }
1320
1321 if (instances > 0)
1322 {
1323 mDeviceContext->DrawIndexedInstanced(numTris * 3, instances, 0, -minIndex, 0);
1324 }
1325 else
1326 {
1327 mDeviceContext->DrawIndexed(numTris * 3, 0, -minIndex);
1328 }
1329 }
1330
1331 void Renderer11::applyShaders(gl::ProgramBinary *programBinary)
1332 {
1333 unsigned int programBinarySerial = programBinary->getSerial();
1334 const bool updateProgramState = (programBinarySerial != mAppliedProgramBinarySerial);
1335
1336 if (updateProgramState)
1337 {
1338 ShaderExecutable *vertexExe = programBinary->getVertexExecutable();
1339 ShaderExecutable *pixelExe = programBinary->getPixelExecutable();
1340
1341 ID3D11VertexShader *vertexShader = NULL;
1342 if (vertexExe) vertexShader = ShaderExecutable11::makeShaderExecutable11(vertexExe)->getVertexShader();
1343
1344 ID3D11PixelShader *pixelShader = NULL;
1345 if (pixelExe) pixelShader = ShaderExecutable11::makeShaderExecutable11(pixelExe)->getPixelShader();
1346
1347 mDeviceContext->PSSetShader(pixelShader, NULL, 0);
1348 mDeviceContext->VSSetShader(vertexShader, NULL, 0);
1349
1350 programBinary->dirtyAllUniforms();
1351
1352 mAppliedProgramBinarySerial = programBinarySerial;
1353 }
1354
1355 // Only use the geometry shader currently for point sprite drawing
1356 const bool usesGeometryShader = (programBinary->usesGeometryShader() && mCurRasterState.pointDrawMode);
1357
1358 if (updateProgramState || usesGeometryShader != mIsGeometryShaderActive)
1359 {
1360 if (usesGeometryShader)
1361 {
1362 ShaderExecutable *geometryExe = programBinary->getGeometryExecutable();
1363 ID3D11GeometryShader *geometryShader = ShaderExecutable11::makeShaderExecutable11(geometryExe)->getGeometryShader();
1364 mDeviceContext->GSSetShader(geometryShader, NULL, 0);
1365 }
1366 else
1367 {
1368 mDeviceContext->GSSetShader(NULL, NULL, 0);
1369 }
1370
1371 mIsGeometryShaderActive = usesGeometryShader;
1372 }
1373 }
1374
1375 void Renderer11::applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray *uniformArray)
1376 {
1377 ShaderExecutable11 *vertexExecutable = ShaderExecutable11::makeShaderExecutable11(programBinary->getVertexExecutable());
1378 ShaderExecutable11 *pixelExecutable = ShaderExecutable11::makeShaderExecutable11(programBinary->getPixelExecutable());
1379
1380 unsigned int totalRegisterCountVS = 0;
1381 unsigned int totalRegisterCountPS = 0;
1382
1383 bool vertexUniformsDirty = false;
1384 bool pixelUniformsDirty = false;
1385
1386 for (gl::UniformArray::const_iterator uniform_iterator = uniformArray->begin(); uniform_iterator != uniformArray->end(); uniform_iterator++)
1387 {
1388 const gl::Uniform *uniform = *uniform_iterator;
1389
1390 if (uniform->vsRegisterIndex >= 0)
1391 {
1392 totalRegisterCountVS += uniform->registerCount;
1393 vertexUniformsDirty = vertexUniformsDirty || uniform->dirty;
1394 }
1395
1396 if (uniform->psRegisterIndex >= 0)
1397 {
1398 totalRegisterCountPS += uniform->registerCount;
1399 pixelUniformsDirty = pixelUniformsDirty || uniform->dirty;
1400 }
1401 }
1402
1403 ID3D11Buffer *vertexConstantBuffer = vertexExecutable->getConstantBuffer(mDevice, totalRegisterCountVS);
1404 ID3D11Buffer *pixelConstantBuffer = pixelExecutable->getConstantBuffer(mDevice, totalRegisterCountPS);
1405
1406 float (*mapVS)[4] = NULL;
1407 float (*mapPS)[4] = NULL;
1408
1409 if (totalRegisterCountVS > 0 && vertexUniformsDirty)
1410 {
1411 D3D11_MAPPED_SUBRESOURCE map = {0};
1412 HRESULT result = mDeviceContext->Map(vertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
1413 ASSERT(SUCCEEDED(result));
1414 mapVS = (float(*)[4])map.pData;
1415 }
1416
1417 if (totalRegisterCountPS > 0 && pixelUniformsDirty)
1418 {
1419 D3D11_MAPPED_SUBRESOURCE map = {0};
1420 HRESULT result = mDeviceContext->Map(pixelConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
1421 ASSERT(SUCCEEDED(result));
1422 mapPS = (float(*)[4])map.pData;
1423 }
1424
1425 for (gl::UniformArray::iterator uniform_iterator = uniformArray->begin(); uniform_iterator != uniformArray->end(); uniform_iterator++)
1426 {
1427 gl::Uniform *uniform = *uniform_iterator;
1428
1429 if (uniform->type != GL_SAMPLER_2D && uniform->type != GL_SAMPLER_CUBE)
1430 {
1431 if (uniform->vsRegisterIndex >= 0 && mapVS)
1432 {
1433 memcpy(mapVS + uniform->vsRegisterIndex, uniform->data, uniform->registerCount * sizeof(float[4]));
1434 }
1435
1436 if (uniform->psRegisterIndex >= 0 && mapPS)
1437 {
1438 memcpy(mapPS + uniform->psRegisterIndex, uniform->data, uniform->registerCount * sizeof(float[4]));
1439 }
1440 }
1441
1442 uniform->dirty = false;
1443 }
1444
1445 if (mapVS)
1446 {
1447 mDeviceContext->Unmap(vertexConstantBuffer, 0);
1448 }
1449
1450 if (mapPS)
1451 {
1452 mDeviceContext->Unmap(pixelConstantBuffer, 0);
1453 }
1454
1455 if (mCurrentVertexConstantBuffer != vertexConstantBuffer)
1456 {
1457 mDeviceContext->VSSetConstantBuffers(0, 1, &vertexConstantBuffer);
1458 mCurrentVertexConstantBuffer = vertexConstantBuffer;
1459 }
1460
1461 if (mCurrentPixelConstantBuffer != pixelConstantBuffer)
1462 {
1463 mDeviceContext->PSSetConstantBuffers(0, 1, &pixelConstantBuffer);
1464 mCurrentPixelConstantBuffer = pixelConstantBuffer;
1465 }
1466
1467 // Driver uniforms
1468 if (!mDriverConstantBufferVS)
1469 {
1470 D3D11_BUFFER_DESC constantBufferDescription = {0};
1471 constantBufferDescription.ByteWidth = sizeof(dx_VertexConstants);
1472 constantBufferDescription.Usage = D3D11_USAGE_DEFAULT;
1473 constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
1474 constantBufferDescription.CPUAccessFlags = 0;
1475 constantBufferDescription.MiscFlags = 0;
1476 constantBufferDescription.StructureByteStride = 0;
1477
1478 HRESULT result = mDevice->CreateBuffer(&constantBufferDescription, NULL, &mDriverConstantBufferVS);
1479 ASSERT(SUCCEEDED(result));
1480
1481 mDeviceContext->VSSetConstantBuffers(1, 1, &mDriverConstantBufferVS);
1482 }
1483
1484 if (!mDriverConstantBufferPS)
1485 {
1486 D3D11_BUFFER_DESC constantBufferDescription = {0};
1487 constantBufferDescription.ByteWidth = sizeof(dx_PixelConstants);
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;
1493
1494 HRESULT result = mDevice->CreateBuffer(&constantBufferDescription, NULL, &mDriverConstantBufferPS);
1495 ASSERT(SUCCEEDED(result));
1496
1497 mDeviceContext->PSSetConstantBuffers(1, 1, &mDriverConstantBufferPS);
1498 }
1499
1500 if (memcmp(&mVertexConstants, &mAppliedVertexConstants, sizeof(dx_VertexConstants)) != 0)
1501 {
1502 mDeviceContext->UpdateSubresource(mDriverConstantBufferVS, 0, NULL, &mVertexConstants, 16, 0);
1503 memcpy(&mAppliedVertexConstants, &mVertexConstants, sizeof(dx_VertexConstants));
1504 }
1505
1506 if (memcmp(&mPixelConstants, &mAppliedPixelConstants, sizeof(dx_PixelConstants)) != 0)
1507 {
1508 mDeviceContext->UpdateSubresource(mDriverConstantBufferPS, 0, NULL, &mPixelConstants, 16, 0);
1509 memcpy(&mAppliedPixelConstants, &mPixelConstants, sizeof(dx_PixelConstants));
1510 }
1511
1512 // needed for the point sprite geometry shader
1513 if (mCurrentGeometryConstantBuffer != mDriverConstantBufferPS)
1514 {
1515 mDeviceContext->GSSetConstantBuffers(0, 1, &mDriverConstantBufferPS);
1516 mCurrentGeometryConstantBuffer = mDriverConstantBufferPS;
1517 }
1518 }
1519
1520 void Renderer11::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer)
1521 {
1522 bool alphaUnmasked = (gl::GetAlphaSize(mRenderTargetDesc.format) == 0) || clearParams.colorMaskAlpha;
1523 bool needMaskedColorClear = (clearParams.mask & GL_COLOR_BUFFER_BIT) &&
1524 !(clearParams.colorMaskRed && clearParams.colorMaskGreen &&
1525 clearParams.colorMaskBlue && alphaUnmasked);
1526
1527 unsigned int stencilUnmasked = 0x0;
1528 if (frameBuffer->hasStencil())
1529 {
1530 unsigned int stencilSize = gl::GetStencilSize(frameBuffer->getStencilbuffer()->getActualFormat());
1531 stencilUnmasked = (0x1 << stencilSize) - 1;
1532 }
1533 bool needMaskedStencilClear = (clearParams.mask & GL_STENCIL_BUFFER_BIT) &&
1534 (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked;
1535
1536 bool needScissoredClear = mScissorEnabled && (mCurScissor.x > 0 || mCurScissor.y > 0 ||
1537 mCurScissor.x + mCurScissor.width < mRenderTargetDesc.width ||
1538 mCurScissor.y + mCurScissor.height < mRenderTargetDesc.height);
1539
1540 if (needMaskedColorClear || needMaskedStencilClear || needScissoredClear)
1541 {
1542 maskedClear(clearParams, frameBuffer->usingExtendedDrawBuffers());
1543 }
1544 else
1545 {
1546 if (clearParams.mask & GL_COLOR_BUFFER_BIT)
1547 {
1548 for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
1549 {
1550 if (frameBuffer->isEnabledColorAttachment(colorAttachment))
1551 {
1552 gl::Renderbuffer *renderbufferObject = frameBuffer->getColorbuffer(colorAttachment);
1553 if (renderbufferObject)
1554 {
1555 RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(renderbufferObject->getRenderTarget());
1556 if (!renderTarget)
1557 {
1558 ERR("render target pointer unexpectedly null.");
1559 return;
1560 }
1561
1562 ID3D11RenderTargetView *framebufferRTV = renderTarget->getRenderTargetView();
1563 if (!framebufferRTV)
1564 {
1565 ERR("render target view pointer unexpectedly null.");
1566 return;
1567 }
1568
1569 const float clearValues[4] = { clearParams.colorClearValue.red,
1570 clearParams.colorClearValue.green,
1571 clearParams.colorClearValue.blue,
1572 clearParams.colorClearValue.alpha };
1573 mDeviceContext->ClearRenderTargetView(framebufferRTV, clearValues);
1574 }
1575 }
1576 }
1577 }
1578 if (clearParams.mask & GL_DEPTH_BUFFER_BIT || clearParams.mask & GL_STENCIL_BUFFER_BIT)
1579 {
1580 gl::Renderbuffer *renderbufferObject = frameBuffer->getDepthOrStencilbuffer();
1581 if (renderbufferObject)
1582 {
1583 RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(renderbufferObject->getDepthStencil());
1584 if (!renderTarget)
1585 {
1586 ERR("render target pointer unexpectedly null.");
1587 return;
1588 }
1589
1590 ID3D11DepthStencilView *framebufferDSV = renderTarget->getDepthStencilView();
1591 if (!framebufferDSV)
1592 {
1593 ERR("depth stencil view pointer unexpectedly null.");
1594 return;
1595 }
1596
1597 UINT clearFlags = 0;
1598 if (clearParams.mask & GL_DEPTH_BUFFER_BIT)
1599 {
1600 clearFlags |= D3D11_CLEAR_DEPTH;
1601 }
1602 if (clearParams.mask & GL_STENCIL_BUFFER_BIT)
1603 {
1604 clearFlags |= D3D11_CLEAR_STENCIL;
1605 }
1606
1607 float depthClear = gl::clamp01(clearParams.depthClearValue);
1608 UINT8 stencilClear = clearParams.stencilClearValue & 0x000000FF;
1609
1610 mDeviceContext->ClearDepthStencilView(framebufferDSV, clearFlags, depthClear, stencilClear);
1611 }
1612 }
1613 }
1614 }
1615
1616 void Renderer11::maskedClear(const gl::ClearParameters &clearParams, bool usingExtendedDrawBuffers)
1617 {
1618 HRESULT result;
1619
1620 if (!mClearResourcesInitialized)
1621 {
1622 ASSERT(!mClearVB && !mClearVS && !mClearSinglePS && !mClearMultiplePS && !mClearScissorRS && !mClearNoScissorRS);
1623
1624 D3D11_BUFFER_DESC vbDesc;
1625 vbDesc.ByteWidth = sizeof(d3d11::PositionDepthColorVertex) * 4;
1626 vbDesc.Usage = D3D11_USAGE_DYNAMIC;
1627 vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
1628 vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
1629 vbDesc.MiscFlags = 0;
1630 vbDesc.StructureByteStride = 0;
1631
1632 result = mDevice->CreateBuffer(&vbDesc, NULL, &mClearVB);
1633 ASSERT(SUCCEEDED(result));
1634 d3d11::SetDebugName(mClearVB, "Renderer11 masked clear vertex buffer");
1635
1636 D3D11_INPUT_ELEMENT_DESC quadLayout[] =
1637 {
1638 { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
1639 { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
1640 };
1641
1642 result = mDevice->CreateInputLayout(quadLayout, 2, g_VS_Clear, sizeof(g_VS_Clear), &mClearIL);
1643 ASSERT(SUCCEEDED(result));
1644 d3d11::SetDebugName(mClearIL, "Renderer11 masked clear input layout");
1645
1646 result = mDevice->CreateVertexShader(g_VS_Clear, sizeof(g_VS_Clear), NULL, &mClearVS);
1647 ASSERT(SUCCEEDED(result));
1648 d3d11::SetDebugName(mClearVS, "Renderer11 masked clear vertex shader");
1649
1650 result = mDevice->CreatePixelShader(g_PS_ClearSingle, sizeof(g_PS_ClearSingle), NULL, &mClearSinglePS);
1651 ASSERT(SUCCEEDED(result));
1652 d3d11::SetDebugName(mClearSinglePS, "Renderer11 masked clear pixel shader (1 RT)");
1653
1654 result = mDevice->CreatePixelShader(g_PS_ClearMultiple, sizeof(g_PS_ClearMultiple), NULL, &mClearMultiplePS);
1655 ASSERT(SUCCEEDED(result));
1656 d3d11::SetDebugName(mClearMultiplePS, "Renderer11 masked clear pixel shader (MRT)");
1657
1658 D3D11_RASTERIZER_DESC rsScissorDesc;
1659 rsScissorDesc.FillMode = D3D11_FILL_SOLID;
1660 rsScissorDesc.CullMode = D3D11_CULL_NONE;
1661 rsScissorDesc.FrontCounterClockwise = FALSE;
1662 rsScissorDesc.DepthBias = 0;
1663 rsScissorDesc.DepthBiasClamp = 0.0f;
1664 rsScissorDesc.SlopeScaledDepthBias = 0.0f;
1665 rsScissorDesc.DepthClipEnable = FALSE;
1666 rsScissorDesc.ScissorEnable = TRUE;
1667 rsScissorDesc.MultisampleEnable = FALSE;
1668 rsScissorDesc.AntialiasedLineEnable = FALSE;
1669
1670 result = mDevice->CreateRasterizerState(&rsScissorDesc, &mClearScissorRS);
1671 ASSERT(SUCCEEDED(result));
1672 d3d11::SetDebugName(mClearScissorRS, "Renderer11 masked clear scissor rasterizer state");
1673
1674 D3D11_RASTERIZER_DESC rsNoScissorDesc;
1675 rsNoScissorDesc.FillMode = D3D11_FILL_SOLID;
1676 rsNoScissorDesc.CullMode = D3D11_CULL_NONE;
1677 rsNoScissorDesc.FrontCounterClockwise = FALSE;
1678 rsNoScissorDesc.DepthBias = 0;
1679 rsNoScissorDesc.DepthBiasClamp = 0.0f;
1680 rsNoScissorDesc.SlopeScaledDepthBias = 0.0f;
1681 rsNoScissorDesc.DepthClipEnable = FALSE;
1682 rsNoScissorDesc.ScissorEnable = FALSE;
1683 rsNoScissorDesc.MultisampleEnable = FALSE;
1684 rsNoScissorDesc.AntialiasedLineEnable = FALSE;
1685
1686 result = mDevice->CreateRasterizerState(&rsNoScissorDesc, &mClearNoScissorRS);
1687 ASSERT(SUCCEEDED(result));
1688 d3d11::SetDebugName(mClearNoScissorRS, "Renderer11 masked clear no scissor rasterizer state");
1689
1690 mClearResourcesInitialized = true;
1691 }
1692
1693 // Prepare the depth stencil state to write depth values if the depth should be cleared
1694 // and stencil values if the stencil should be cleared
1695 gl::DepthStencilState glDSState;
1696 glDSState.depthTest = (clearParams.mask & GL_DEPTH_BUFFER_BIT) != 0;
1697 glDSState.depthFunc = GL_ALWAYS;
1698 glDSState.depthMask = (clearParams.mask & GL_DEPTH_BUFFER_BIT) != 0;
1699 glDSState.stencilTest = (clearParams.mask & GL_STENCIL_BUFFER_BIT) != 0;
1700 glDSState.stencilFunc = GL_ALWAYS;
1701 glDSState.stencilMask = 0;
1702 glDSState.stencilFail = GL_REPLACE;
1703 glDSState.stencilPassDepthFail = GL_REPLACE;
1704 glDSState.stencilPassDepthPass = GL_REPLACE;
1705 glDSState.stencilWritemask = clearParams.stencilWriteMask;
1706 glDSState.stencilBackFunc = GL_ALWAYS;
1707 glDSState.stencilBackMask = 0;
1708 glDSState.stencilBackFail = GL_REPLACE;
1709 glDSState.stencilBackPassDepthFail = GL_REPLACE;
1710 glDSState.stencilBackPassDepthPass = GL_REPLACE;
1711 glDSState.stencilBackWritemask = clearParams.stencilWriteMask;
1712
1713 int stencilClear = clearParams.stencilClearValue & 0x000000FF;
1714
1715 ID3D11DepthStencilState *dsState = mStateCache.getDepthStencilState(glDSState);
1716
1717 // Prepare the blend state to use a write mask if the color buffer should be cleared
1718 gl::BlendState glBlendState;
1719 glBlendState.blend = false;
1720 glBlendState.sourceBlendRGB = GL_ONE;
1721 glBlendState.destBlendRGB = GL_ZERO;
1722 glBlendState.sourceBlendAlpha = GL_ONE;
1723 glBlendState.destBlendAlpha = GL_ZERO;
1724 glBlendState.blendEquationRGB = GL_FUNC_ADD;
1725 glBlendState.blendEquationAlpha = GL_FUNC_ADD;
1726 glBlendState.colorMaskRed = (clearParams.mask & GL_COLOR_BUFFER_BIT) ? clearParams.colorMaskRed : false;
1727 glBlendState.colorMaskGreen = (clearParams.mask & GL_COLOR_BUFFER_BIT) ? clearParams.colorMaskGreen : false;
1728 glBlendState.colorMaskBlue = (clearParams.mask & GL_COLOR_BUFFER_BIT) ? clearParams.colorMaskBlue : false;
1729 glBlendState.colorMaskAlpha = (clearParams.mask & GL_COLOR_BUFFER_BIT) ? clearParams.colorMaskAlpha : false;
1730 glBlendState.sampleAlphaToCoverage = false;
1731 glBlendState.dither = false;
1732
1733 static const float blendFactors[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
1734 static const UINT sampleMask = 0xFFFFFFFF;
1735
1736 ID3D11BlendState *blendState = mStateCache.getBlendState(glBlendState);
1737
1738 // Set the vertices
1739 D3D11_MAPPED_SUBRESOURCE mappedResource;
1740 result = mDeviceContext->Map(mClearVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
1741 if (FAILED(result))
1742 {
1743 ERR("Failed to map masked clear vertex buffer, HRESULT: 0x%X.", result);
1744 return;
1745 }
1746
1747 d3d11::PositionDepthColorVertex *vertices = reinterpret_cast<d3d11::PositionDepthColorVertex*>(mappedResource.pData);
1748
1749 float depthClear = gl::clamp01(clearParams.depthClearValue);
1750 d3d11::SetPositionDepthColorVertex(&vertices[0], -1.0f, 1.0f, depthClear, clearParams.colorClearValue);
1751 d3d11::SetPositionDepthColorVertex(&vertices[1], -1.0f, -1.0f, depthClear, clearParams.colorClearValue);
1752 d3d11::SetPositionDepthColorVertex(&vertices[2], 1.0f, 1.0f, depthClear, clearParams.colorClearValue);
1753 d3d11::SetPositionDepthColorVertex(&vertices[3], 1.0f, -1.0f, depthClear, clearParams.colorClearValue);
1754
1755 mDeviceContext->Unmap(mClearVB, 0);
1756
1757 // Apply state
1758 mDeviceContext->OMSetBlendState(blendState, blendFactors, sampleMask);
1759 mDeviceContext->OMSetDepthStencilState(dsState, stencilClear);
1760 mDeviceContext->RSSetState(mScissorEnabled ? mClearScissorRS : mClearNoScissorRS);
1761
1762 // Apply shaders
1763 ID3D11PixelShader *pixelShader = usingExtendedDrawBuffers ? mClearMultiplePS : mClearSinglePS;
1764
1765 mDeviceContext->IASetInputLayout(mClearIL);
1766 mDeviceContext->VSSetShader(mClearVS, NULL, 0);
1767 mDeviceContext->PSSetShader(pixelShader, NULL, 0);
1768 mDeviceContext->GSSetShader(NULL, NULL, 0);
1769
1770 // Apply vertex buffer
1771 static UINT stride = sizeof(d3d11::PositionDepthColorVertex);
1772 static UINT startIdx = 0;
1773 mDeviceContext->IASetVertexBuffers(0, 1, &mClearVB, &stride, &startIdx);
1774 mDeviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
1775
1776 // Draw the clear quad
1777 mDeviceContext->Draw(4, 0);
1778
1779 // Clean up
1780 markAllStateDirty();
1781 }
1782
1783 void Renderer11::markAllStateDirty()
1784 {
1785 for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++)
1786 {
1787 mAppliedRenderTargetSerials[rtIndex] = 0;
1788 }
1789 mAppliedDepthbufferSerial = 0;
1790 mAppliedStencilbufferSerial = 0;
1791 mDepthStencilInitialized = false;
1792 mRenderTargetDescInitialized = false;
1793
1794 for (int i = 0; i < gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; i++)
1795 {
1796 mForceSetVertexSamplerStates[i] = true;
1797 mCurVertexTextureSerials[i] = 0;
1798 }
1799 for (int i = 0; i < gl::MAX_TEXTURE_IMAGE_UNITS; i++)
1800 {
1801 mForceSetPixelSamplerStates[i] = true;
1802 mCurPixelTextureSerials[i] = 0;
1803 }
1804
1805 mForceSetBlendState = true;
1806 mForceSetRasterState = true;
1807 mForceSetDepthStencilState = true;
1808 mForceSetScissor = true;
1809 mForceSetViewport = true;
1810
1811 mAppliedIBSerial = 0;
1812 mAppliedStorageIBSerial = 0;
1813 mAppliedIBOffset = 0;
1814
1815 mAppliedProgramBinarySerial = 0;
1816 memset(&mAppliedVertexConstants, 0, sizeof(dx_VertexConstants));
1817 memset(&mAppliedPixelConstants, 0, sizeof(dx_PixelConstants));
1818
1819 mInputLayoutCache.markDirty();
1820
1821 mCurrentVertexConstantBuffer = NULL;
1822 mCurrentPixelConstantBuffer = NULL;
1823 mCurrentGeometryConstantBuffer = NULL;
1824
1825 mCurrentPrimitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
1826 }
1827
1828 void Renderer11::releaseDeviceResources()
1829 {
1830 mStateCache.clear();
1831 mInputLayoutCache.clear();
1832
1833 delete mVertexDataManager;
1834 mVertexDataManager = NULL;
1835
1836 delete mIndexDataManager;
1837 mIndexDataManager = NULL;
1838
1839 delete mLineLoopIB;
1840 mLineLoopIB = NULL;
1841
1842 delete mTriangleFanIB;
1843 mTriangleFanIB = NULL;
1844
1845 SafeRelease(mCopyVB);
1846 SafeRelease(mCopySampler);
1847 SafeRelease(mCopyIL);
1848 SafeRelease(mCopyIL);
1849 SafeRelease(mCopyVS);
1850 SafeRelease(mCopyRGBAPS);
1851 SafeRelease(mCopyRGBPS);
1852 SafeRelease(mCopyLumPS);
1853 SafeRelease(mCopyLumAlphaPS);
1854
1855 mCopyResourcesInitialized = false;
1856
1857 SafeRelease(mClearVB);
1858 SafeRelease(mClearIL);
1859 SafeRelease(mClearVS);
1860 SafeRelease(mClearSinglePS);
1861 SafeRelease(mClearMultiplePS);
1862 SafeRelease(mClearScissorRS);
1863 SafeRelease(mClearNoScissorRS);
1864
1865 mClearResourcesInitialized = false;
1866
1867 SafeRelease(mDriverConstantBufferVS);
1868 SafeRelease(mDriverConstantBufferPS);
1869 SafeRelease(mSyncQuery);
1870 }
1871
1872 void Renderer11::notifyDeviceLost()
1873 {
1874 mDeviceLost = true;
1875 mDisplay->notifyDeviceLost();
1876 }
1877
1878 bool Renderer11::isDeviceLost()
1879 {
1880 return mDeviceLost;
1881 }
1882
1883 // set notify to true to broadcast a message to all contexts of the device loss
1884 bool Renderer11::testDeviceLost(bool notify)
1885 {
1886 bool isLost = false;
1887
1888 // GetRemovedReason is used to test if the device is removed
1889 HRESULT result = mDevice->GetDeviceRemovedReason();
1890 isLost = d3d11::isDeviceLostError(result);
1891
1892 if (isLost)
1893 {
1894 // Log error if this is a new device lost event
1895 if (mDeviceLost == false)
1896 {
1897 ERR("The D3D11 device was removed: 0x%08X", result);
1898 }
1899
1900 // ensure we note the device loss --
1901 // we'll probably get this done again by notifyDeviceLost
1902 // but best to remember it!
1903 // Note that we don't want to clear the device loss status here
1904 // -- this needs to be done by resetDevice
1905 mDeviceLost = true;
1906 if (notify)
1907 {
1908 notifyDeviceLost();
1909 }
1910 }
1911
1912 return isLost;
1913 }
1914
1915 bool Renderer11::testDeviceResettable()
1916 {
1917 // determine if the device is resettable by creating a dummy device
1918 PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice");
1919
1920 if (D3D11CreateDevice == NULL)
1921 {
1922 return false;
1923 }
1924
1925 D3D_FEATURE_LEVEL featureLevels[] =
1926 {
1927 D3D_FEATURE_LEVEL_11_0,
1928 D3D_FEATURE_LEVEL_10_1,
1929 D3D_FEATURE_LEVEL_10_0,
1930 };
1931
1932 ID3D11Device* dummyDevice;
1933 D3D_FEATURE_LEVEL dummyFeatureLevel;
1934 ID3D11DeviceContext* dummyContext;
1935
1936 HRESULT result = D3D11CreateDevice(NULL,
1937 D3D_DRIVER_TYPE_HARDWARE,
1938 NULL,
1939 #if defined(_DEBUG)
1940 D3D11_CREATE_DEVICE_DEBUG,
1941 #else
1942 0,
1943 #endif
1944 featureLevels,
1945 ArraySize(featureLevels),
1946 D3D11_SDK_VERSION,
1947 &dummyDevice,
1948 &dummyFeatureLevel,
1949 &dummyContext);
1950
1951 if (!mDevice || FAILED(result))
1952 {
1953 return false;
1954 }
1955
1956 dummyContext->Release();
1957 dummyDevice->Release();
1958
1959 return true;
1960 }
1961
1962 void Renderer11::release()
1963 {
1964 releaseDeviceResources();
1965
1966 if (mDxgiFactory)
1967 {
1968 mDxgiFactory->Release();
1969 mDxgiFactory = NULL;
1970 }
1971
1972 if (mDxgiAdapter)
1973 {
1974 mDxgiAdapter->Release();
1975 mDxgiAdapter = NULL;
1976 }
1977
1978 if (mDeviceContext)
1979 {
1980 mDeviceContext->ClearState();
1981 mDeviceContext->Flush();
1982 mDeviceContext->Release();
1983 mDeviceContext = NULL;
1984 }
1985
1986 if (mDevice)
1987 {
1988 mDevice->Release();
1989 mDevice = NULL;
1990 }
1991
1992 if (mD3d11Module)
1993 {
1994 FreeLibrary(mD3d11Module);
1995 mD3d11Module = NULL;
1996 }
1997
1998 if (mDxgiModule)
1999 {
2000 FreeLibrary(mDxgiModule);
2001 mDxgiModule = NULL;
2002 }
2003 }
2004
2005 bool Renderer11::resetDevice()
2006 {
2007 // recreate everything
2008 release();
2009 EGLint result = initialize();
2010
2011 if (result != EGL_SUCCESS)
2012 {
2013 ERR("Could not reinitialize D3D11 device: %08X", result);
2014 return false;
2015 }
2016
2017 mDeviceLost = false;
2018
2019 return true;
2020 }
2021
2022 DWORD Renderer11::getAdapterVendor() const
2023 {
2024 return mAdapterDescription.VendorId;
2025 }
2026
2027 std::string Renderer11::getRendererDescription() const
2028 {
2029 std::ostringstream rendererString;
2030
2031 rendererString << mDescription;
2032 rendererString << " Direct3D11";
2033
2034 rendererString << " vs_" << getMajorShaderModel() << "_" << getMinorShaderModel();
2035 rendererString << " ps_" << getMajorShaderModel() << "_" << getMinorShaderModel();
2036
2037 return rendererString.str();
2038 }
2039
2040 GUID Renderer11::getAdapterIdentifier() const
2041 {
2042 // Use the adapter LUID as our adapter ID
2043 // This number is local to a machine is only guaranteed to be unique between restarts
2044 META_ASSERT(sizeof(LUID) <= sizeof(GUID));
2045 GUID adapterId = {0};
2046 memcpy(&adapterId, &mAdapterDescription.AdapterLuid, sizeof(LUID));
2047 return adapterId;
2048 }
2049
2050 bool Renderer11::getBGRATextureSupport() const
2051 {
2052 return mBGRATextureSupport;
2053 }
2054
2055 bool Renderer11::getDXT1TextureSupport()
2056 {
2057 return mDXT1TextureSupport;
2058 }
2059
2060 bool Renderer11::getDXT3TextureSupport()
2061 {
2062 return mDXT3TextureSupport;
2063 }
2064
2065 bool Renderer11::getDXT5TextureSupport()
2066 {
2067 return mDXT5TextureSupport;
2068 }
2069
2070 bool Renderer11::getDepthTextureSupport() const
2071 {
2072 return mDepthTextureSupport;
2073 }
2074
2075 bool Renderer11::getFloat32TextureSupport(bool *filtering, bool *renderable)
2076 {
2077 *renderable = mFloat32RenderSupport;
2078 *filtering = mFloat32FilterSupport;
2079 return mFloat32TextureSupport;
2080 }
2081
2082 bool Renderer11::getFloat16TextureSupport(bool *filtering, bool *renderable)
2083 {
2084 *renderable = mFloat16RenderSupport;
2085 *filtering = mFloat16FilterSupport;
2086 return mFloat16TextureSupport;
2087 }
2088
2089 bool Renderer11::getLuminanceTextureSupport()
2090 {
2091 return false;
2092 }
2093
2094 bool Renderer11::getLuminanceAlphaTextureSupport()
2095 {
2096 return false;
2097 }
2098
2099 bool Renderer11::getTextureFilterAnisotropySupport() const
2100 {
2101 return true;
2102 }
2103
2104 float Renderer11::getTextureMaxAnisotropy() const
2105 {
2106 switch (mFeatureLevel)
2107 {
2108 case D3D_FEATURE_LEVEL_11_0:
2109 return D3D11_MAX_MAXANISOTROPY;
2110 case D3D_FEATURE_LEVEL_10_1:
2111 case D3D_FEATURE_LEVEL_10_0:
2112 return D3D10_MAX_MAXANISOTROPY;
2113 default: UNREACHABLE();
2114 return 0;
2115 }
2116 }
2117
2118 bool Renderer11::getEventQuerySupport()
2119 {
2120 return true;
2121 }
2122
2123 Range Renderer11::getViewportBounds() const
2124 {
2125 switch (mFeatureLevel)
2126 {
2127 case D3D_FEATURE_LEVEL_11_0:
2128 return Range(D3D11_VIEWPORT_BOUNDS_MIN, D3D11_VIEWPORT_BOUNDS_MAX);
2129 case D3D_FEATURE_LEVEL_10_1:
2130 case D3D_FEATURE_LEVEL_10_0:
2131 return Range(D3D10_VIEWPORT_BOUNDS_MIN, D3D10_VIEWPORT_BOUNDS_MAX);
2132 default: UNREACHABLE();
2133 return Range(0, 0);
2134 }
2135 }
2136
2137 unsigned int Renderer11::getMaxVertexTextureImageUnits() const
2138 {
2139 META_ASSERT(MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 <= gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS);
2140 switch (mFeatureLevel)
2141 {
2142 case D3D_FEATURE_LEVEL_11_0:
2143 case D3D_FEATURE_LEVEL_10_1:
2144 case D3D_FEATURE_LEVEL_10_0:
2145 return MAX_TEXTURE_IMAGE_UNITS_VTF_SM4;
2146 default: UNREACHABLE();
2147 return 0;
2148 }
2149 }
2150
2151 unsigned int Renderer11::getMaxCombinedTextureImageUnits() const
2152 {
2153 return gl::MAX_TEXTURE_IMAGE_UNITS + getMaxVertexTextureImageUnits();
2154 }
2155
2156 unsigned int Renderer11::getReservedVertexUniformVectors() const
2157 {
2158 return 0; // Driver uniforms are stored in a separate constant buffer
2159 }
2160
2161 unsigned int Renderer11::getReservedFragmentUniformVectors() const
2162 {
2163 return 0; // Driver uniforms are stored in a separate constant buffer
2164 }
2165
2166 unsigned int Renderer11::getMaxVertexUniformVectors() const
2167 {
2168 META_ASSERT(MAX_VERTEX_UNIFORM_VECTORS_D3D11 <= D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT);
2169 ASSERT(mFeatureLevel >= D3D_FEATURE_LEVEL_10_0);
2170 return MAX_VERTEX_UNIFORM_VECTORS_D3D11;
2171 }
2172
2173 unsigned int Renderer11::getMaxFragmentUniformVectors() const
2174 {
2175 META_ASSERT(MAX_FRAGMENT_UNIFORM_VECTORS_D3D11 <= D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT);
2176 ASSERT(mFeatureLevel >= D3D_FEATURE_LEVEL_10_0);
2177 return MAX_FRAGMENT_UNIFORM_VECTORS_D3D11;
2178 }
2179
2180 unsigned int Renderer11::getMaxVaryingVectors() const
2181 {
2182 META_ASSERT(gl::IMPLEMENTATION_MAX_VARYING_VECTORS == D3D11_VS_OUTPUT_REGISTER_COUNT);
2183 switch (mFeatureLevel)
2184 {
2185 case D3D_FEATURE_LEVEL_11_0:
2186 return D3D11_VS_OUTPUT_REGISTER_COUNT;
2187 case D3D_FEATURE_LEVEL_10_1:
2188 case D3D_FEATURE_LEVEL_10_0:
2189 return D3D10_VS_OUTPUT_REGISTER_COUNT;
2190 default: UNREACHABLE();
2191 return 0;
2192 }
2193 }
2194
2195 bool Renderer11::getNonPower2TextureSupport() const
2196 {
2197 switch (mFeatureLevel)
2198 {
2199 case D3D_FEATURE_LEVEL_11_0:
2200 case D3D_FEATURE_LEVEL_10_1:
2201 case D3D_FEATURE_LEVEL_10_0:
2202 return true;
2203 default: UNREACHABLE();
2204 return false;
2205 }
2206 }
2207
2208 bool Renderer11::getOcclusionQuerySupport() const
2209 {
2210 switch (mFeatureLevel)
2211 {
2212 case D3D_FEATURE_LEVEL_11_0:
2213 case D3D_FEATURE_LEVEL_10_1:
2214 case D3D_FEATURE_LEVEL_10_0:
2215 return true;
2216 default: UNREACHABLE();
2217 return false;
2218 }
2219 }
2220
2221 bool Renderer11::getInstancingSupport() const
2222 {
2223 switch (mFeatureLevel)
2224 {
2225 case D3D_FEATURE_LEVEL_11_0:
2226 case D3D_FEATURE_LEVEL_10_1:
2227 case D3D_FEATURE_LEVEL_10_0:
2228 return true;
2229 default: UNREACHABLE();
2230 return false;
2231 }
2232 }
2233
2234 bool Renderer11::getShareHandleSupport() const
2235 {
2236 // We only currently support share handles with BGRA surfaces, because
2237 // chrome needs BGRA. Once chrome fixes this, we should always support them.
2238 // PIX doesn't seem to support using share handles, so disable them.
2239 return getBGRATextureSupport() && !gl::perfActive();
2240 }
2241
2242 bool Renderer11::getDerivativeInstructionSupport() const
2243 {
2244 switch (mFeatureLevel)
2245 {
2246 case D3D_FEATURE_LEVEL_11_0:
2247 case D3D_FEATURE_LEVEL_10_1:
2248 case D3D_FEATURE_LEVEL_10_0:
2249 return true;
2250 default: UNREACHABLE();
2251 return false;
2252 }
2253 }
2254
2255 bool Renderer11::getPostSubBufferSupport() const
2256 {
2257 // D3D11 does not support present with dirty rectangles until D3D11.1 and DXGI 1.2.
2258 return false;
2259 }
2260
2261 int Renderer11::getMajorShaderModel() const
2262 {
2263 switch (mFeatureLevel)
2264 {
2265 case D3D_FEATURE_LEVEL_11_0: return D3D11_SHADER_MAJOR_VERSION; // 5
2266 case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SHADER_MAJOR_VERSION; // 4
2267 case D3D_FEATURE_LEVEL_10_0: return D3D10_SHADER_MAJOR_VERSION; // 4
2268 default: UNREACHABLE(); return 0;
2269 }
2270 }
2271
2272 int Renderer11::getMinorShaderModel() const
2273 {
2274 switch (mFeatureLevel)
2275 {
2276 case D3D_FEATURE_LEVEL_11_0: return D3D11_SHADER_MINOR_VERSION; // 0
2277 case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SHADER_MINOR_VERSION; // 1
2278 case D3D_FEATURE_LEVEL_10_0: return D3D10_SHADER_MINOR_VERSION; // 0
2279 default: UNREACHABLE(); return 0;
2280 }
2281 }
2282
2283 float Renderer11::getMaxPointSize() const
2284 {
2285 // choose a reasonable maximum. we enforce this in the shader.
2286 // (nb: on a Radeon 2600xt, DX9 reports a 256 max point size)
2287 return 1024.0f;
2288 }
2289
2290 int Renderer11::getMaxViewportDimension() const
2291 {
2292 // Maximum viewport size must be at least as large as the largest render buffer (or larger).
2293 // In our case return the maximum texture size, which is the maximum render buffer size.
2294 META_ASSERT(D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION * 2 - 1 <= D3D11_VIEWPORT_BOUNDS_MAX);
2295 META_ASSERT(D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION * 2 - 1 <= D3D10_VIEWPORT_BOUNDS_MAX);
2296
2297 switch (mFeatureLevel)
2298 {
2299 case D3D_FEATURE_LEVEL_11_0:
2300 return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 16384
2301 case D3D_FEATURE_LEVEL_10_1:
2302 case D3D_FEATURE_LEVEL_10_0:
2303 return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 8192
2304 default: UNREACHABLE();
2305 return 0;
2306 }
2307 }
2308
2309 int Renderer11::getMaxTextureWidth() const
2310 {
2311 switch (mFeatureLevel)
2312 {
2313 case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 16384
2314 case D3D_FEATURE_LEVEL_10_1:
2315 case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 8192
2316 default: UNREACHABLE(); return 0;
2317 }
2318 }
2319
2320 int Renderer11::getMaxTextureHeight() const
2321 {
2322 switch (mFeatureLevel)
2323 {
2324 case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 16384
2325 case D3D_FEATURE_LEVEL_10_1:
2326 case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 8192
2327 default: UNREACHABLE(); return 0;
2328 }
2329 }
2330
2331 bool Renderer11::get32BitIndexSupport() const
2332 {
2333 switch (mFeatureLevel)
2334 {
2335 case D3D_FEATURE_LEVEL_11_0:
2336 case D3D_FEATURE_LEVEL_10_1:
2337 case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP >= 32; // true
2338 default: UNREACHABLE(); return false;
2339 }
2340 }
2341
2342 int Renderer11::getMinSwapInterval() const
2343 {
2344 return 0;
2345 }
2346
2347 int Renderer11::getMaxSwapInterval() const
2348 {
2349 return 4;
2350 }
2351
2352 int Renderer11::getMaxSupportedSamples() const
2353 {
2354 return mMaxSupportedSamples;
2355 }
2356
2357 int Renderer11::getNearestSupportedSamples(DXGI_FORMAT format, unsigned int requested) const
2358 {
2359 if (requested == 0)
2360 {
2361 return 0;
2362 }
2363
2364 MultisampleSupportMap::const_iterator iter = mMultisampleSupportMap.find(format);
2365 if (iter != mMultisampleSupportMap.end())
2366 {
2367 const MultisampleSupportInfo& info = iter->second;
2368 for (unsigned int i = requested - 1; i < D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; i++)
2369 {
2370 if (info.qualityLevels[i] > 0)
2371 {
2372 return i + 1;
2373 }
2374 }
2375 }
2376
2377 return -1;
2378 }
2379
2380 unsigned int Renderer11::getMaxRenderTargets() const
2381 {
2382 META_ASSERT(D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT <= gl::IMPLEMENTATION_MAX_DRAW_BUFFERS);
2383 META_ASSERT(D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT <= gl::IMPLEMENTATION_MAX_DRAW_BUFFERS);
2384
2385 switch (mFeatureLevel)
2386 {
2387 case D3D_FEATURE_LEVEL_11_0:
2388 return D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; // 8
2389 case D3D_FEATURE_LEVEL_10_1:
2390 case D3D_FEATURE_LEVEL_10_0:
2391 return D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT; // 8
2392 default:
2393 UNREACHABLE();
2394 return 1;
2395 }
2396 }
2397
2398 bool Renderer11::copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source)
2399 {
2400 if (source && dest)
2401 {
2402 TextureStorage11_2D *source11 = TextureStorage11_2D::makeTextureStorage11_2D(source->getStorageInstance());
2403 TextureStorage11_2D *dest11 = TextureStorage11_2D::makeTextureStorage11_2D(dest->getStorageInstance());
2404
2405 mDeviceContext->CopyResource(dest11->getBaseTexture(), source11->getBaseTexture());
2406 return true;
2407 }
2408
2409 return false;
2410 }
2411
2412 bool Renderer11::copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source)
2413 {
2414 if (source && dest)
2415 {
2416 TextureStorage11_Cube *source11 = TextureStorage11_Cube::makeTextureStorage11_Cube(source->getStorageInstance());
2417 TextureStorage11_Cube *dest11 = TextureStorage11_Cube::makeTextureStorage11_Cube(dest->getStorageInstance());
2418
2419 mDeviceContext->CopyResource(dest11->getBaseTexture(), source11->getBaseTexture());
2420 return true;
2421 }
2422
2423 return false;
2424 }
2425
2426 bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
2427 GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level)
2428 {
2429 gl::Renderbuffer *colorbuffer = framebuffer->getReadColorbuffer();
2430 if (!colorbuffer)
2431 {
2432 ERR("Failed to retrieve the color buffer from the frame buffer.");
2433 return gl::error(GL_OUT_OF_MEMORY, false);
2434 }
2435
2436 RenderTarget11 *sourceRenderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget());
2437 if (!sourceRenderTarget)
2438 {
2439 ERR("Failed to retrieve the render target from the frame buffer.");
2440 return gl::error(GL_OUT_OF_MEMORY, false);
2441 }
2442
2443 ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView();
2444 if (!source)
2445 {
2446 ERR("Failed to retrieve the render target view from the render target.");
2447 return gl::error(GL_OUT_OF_MEMORY, false);
2448 }
2449
2450 TextureStorage11_2D *storage11 = TextureStorage11_2D::makeTextureStorage11_2D(storage->getStorageInstance());
2451 if (!storage11)
2452 {
2453 ERR("Failed to retrieve the texture storage from the destination.");
2454 return gl::error(GL_OUT_OF_MEMORY, false);
2455 }
2456
2457 RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTarget(level));
2458 if (!destRenderTarget)
2459 {
2460 ERR("Failed to retrieve the render target from the destination storage.");
2461 return gl::error(GL_OUT_OF_MEMORY, false);
2462 }
2463
2464 ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView();
2465 if (!dest)
2466 {
2467 ERR("Failed to retrieve the render target view from the destination render target.");
2468 return gl::error(GL_OUT_OF_MEMORY, false);
2469 }
2470
2471 gl::Rectangle destRect;
2472 destRect.x = xoffset;
2473 destRect.y = yoffset;
2474 destRect.width = sourceRect.width;
2475 destRect.height = sourceRect.height;
2476
2477 bool ret = copyTexture(source, sourceRect, sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(),
2478 dest, destRect, destRenderTarget->getWidth(), destRenderTarget->getHeight(), destFormat);
2479
2480 return ret;
2481 }
2482
2483 bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
2484 GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level)
2485 {
2486 gl::Renderbuffer *colorbuffer = framebuffer->getReadColorbuffer();
2487 if (!colorbuffer)
2488 {
2489 ERR("Failed to retrieve the color buffer from the frame buffer.");
2490 return gl::error(GL_OUT_OF_MEMORY, false);
2491 }
2492
2493 RenderTarget11 *sourceRenderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget());
2494 if (!sourceRenderTarget)
2495 {
2496 ERR("Failed to retrieve the render target from the frame buffer.");
2497 return gl::error(GL_OUT_OF_MEMORY, false);
2498 }
2499
2500 ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView();
2501 if (!source)
2502 {
2503 ERR("Failed to retrieve the render target view from the render target.");
2504 return gl::error(GL_OUT_OF_MEMORY, false);
2505 }
2506
2507 TextureStorage11_Cube *storage11 = TextureStorage11_Cube::makeTextureStorage11_Cube(storage->getStorageInstance());
2508 if (!storage11)
2509 {
2510 ERR("Failed to retrieve the texture storage from the destination.");
2511 return gl::error(GL_OUT_OF_MEMORY, false);
2512 }
2513
2514 RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTarget(target, level));
2515 if (!destRenderTarget)
2516 {
2517 ERR("Failed to retrieve the render target from the destination storage.");
2518 return gl::error(GL_OUT_OF_MEMORY, false);
2519 }
2520
2521 ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView();
2522 if (!dest)
2523 {
2524 ERR("Failed to retrieve the render target view from the destination render target.");
2525 return gl::error(GL_OUT_OF_MEMORY, false);
2526 }
2527
2528 gl::Rectangle destRect;
2529 destRect.x = xoffset;
2530 destRect.y = yoffset;
2531 destRect.width = sourceRect.width;
2532 destRect.height = sourceRect.height;
2533
2534 bool ret = copyTexture(source, sourceRect, sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(),
2535 dest, destRect, destRenderTarget->getWidth(), destRenderTarget->getHeight(), destFormat);
2536
2537 return ret;
2538 }
2539
2540 bool Renderer11::copyTexture(ID3D11ShaderResourceView *source, const gl::Rectangle &sourceArea, unsigned int sourceWidth, unsigned int sourceHeight,
2541 ID3D11RenderTargetView *dest, const gl::Rectangle &destArea, unsigned int destWidth, unsigned int destHeight, GLenum destFormat)
2542 {
2543 HRESULT result;
2544
2545 if (!mCopyResourcesInitialized)
2546 {
2547 ASSERT(!mCopyVB && !mCopySampler && !mCopyIL && !mCopyVS && !mCopyRGBAPS && !mCopyRGBPS && !mCopyLumPS && !mCopyLumAlphaPS);
2548
2549 D3D11_BUFFER_DESC vbDesc;
2550 vbDesc.ByteWidth = sizeof(d3d11::PositionTexCoordVertex) * 4;
2551 vbDesc.Usage = D3D11_USAGE_DYNAMIC;
2552 vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
2553 vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
2554 vbDesc.MiscFlags = 0;
2555 vbDesc.StructureByteStride = 0;
2556
2557 result = mDevice->CreateBuffer(&vbDesc, NULL, &mCopyVB);
2558 ASSERT(SUCCEEDED(result));
2559 d3d11::SetDebugName(mCopyVB, "Renderer11 copy texture vertex buffer");
2560
2561 D3D11_SAMPLER_DESC samplerDesc;
2562 samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
2563 samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
2564 samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
2565 samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
2566 samplerDesc.MipLODBias = 0.0f;
2567 samplerDesc.MaxAnisotropy = 0;
2568 samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
2569 samplerDesc.BorderColor[0] = 0.0f;
2570 samplerDesc.BorderColor[1] = 0.0f;
2571 samplerDesc.BorderColor[2] = 0.0f;
2572 samplerDesc.BorderColor[3] = 0.0f;
2573 samplerDesc.MinLOD = 0.0f;
2574 samplerDesc.MaxLOD = 0.0f;
2575
2576 result = mDevice->CreateSamplerState(&samplerDesc, &mCopySampler);
2577 ASSERT(SUCCEEDED(result));
2578 d3d11::SetDebugName(mCopySampler, "Renderer11 copy sampler");
2579
2580 D3D11_INPUT_ELEMENT_DESC quadLayout[] =
2581 {
2582 { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
2583 { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 },
2584 };
2585
2586 result = mDevice->CreateInputLayout(quadLayout, 2, g_VS_Passthrough, sizeof(g_VS_Passthrough), &mCopyIL);
2587 ASSERT(SUCCEEDED(result));
2588 d3d11::SetDebugName(mCopyIL, "Renderer11 copy texture input layout");
2589
2590 result = mDevice->CreateVertexShader(g_VS_Passthrough, sizeof(g_VS_Passthrough), NULL, &mCopyVS);
2591 ASSERT(SUCCEEDED(result));
2592 d3d11::SetDebugName(mCopyVS, "Renderer11 copy texture vertex shader");
2593
2594 result = mDevice->CreatePixelShader(g_PS_PassthroughRGBA, sizeof(g_PS_PassthroughRGBA), NULL, &mCopyRGBAPS);
2595 ASSERT(SUCCEEDED(result));
2596 d3d11::SetDebugName(mCopyRGBAPS, "Renderer11 copy texture RGBA pixel shader");
2597
2598 result = mDevice->CreatePixelShader(g_PS_PassthroughRGB, sizeof(g_PS_PassthroughRGB), NULL, &mCopyRGBPS);
2599 ASSERT(SUCCEEDED(result));
2600 d3d11::SetDebugName(mCopyRGBPS, "Renderer11 copy texture RGB pixel shader");
2601
2602 result = mDevice->CreatePixelShader(g_PS_PassthroughLum, sizeof(g_PS_PassthroughLum), NULL, &mCopyLumPS);
2603 ASSERT(SUCCEEDED(result));
2604 d3d11::SetDebugName(mCopyLumPS, "Renderer11 copy texture luminance pixel shader");
2605
2606 result = mDevice->CreatePixelShader(g_PS_PassthroughLumAlpha, sizeof(g_PS_PassthroughLumAlpha), NULL, &mCopyLumAlphaPS);
2607 ASSERT(SUCCEEDED(result));
2608 d3d11::SetDebugName(mCopyLumAlphaPS, "Renderer11 copy texture luminance alpha pixel shader");
2609
2610 mCopyResourcesInitialized = true;
2611 }
2612
2613 // Verify the source and destination area sizes
2614 if (sourceArea.x < 0 || sourceArea.x + sourceArea.width > static_cast<int>(sourceWidth) ||
2615 sourceArea.y < 0 || sourceArea.y + sourceArea.height > static_cast<int>(sourceHeight) ||
2616 destArea.x < 0 || destArea.x + destArea.width > static_cast<int>(destWidth) ||
2617 destArea.y < 0 || destArea.y + destArea.height > static_cast<int>(destHeight))
2618 {
2619 return gl::error(GL_INVALID_VALUE, false);
2620 }
2621
2622 // Set vertices
2623 D3D11_MAPPED_SUBRESOURCE mappedResource;
2624 result = mDeviceContext->Map(mCopyVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
2625 if (FAILED(result))
2626 {
2627 ERR("Failed to map vertex buffer for texture copy, HRESULT: 0x%X.", result);
2628 return gl::error(GL_OUT_OF_MEMORY, false);
2629 }
2630
2631 d3d11::PositionTexCoordVertex *vertices = static_cast<d3d11::PositionTexCoordVertex*>(mappedResource.pData);
2632
2633 // Create a quad in homogeneous coordinates
2634 float x1 = (destArea.x / float(destWidth)) * 2.0f - 1.0f;
2635 float y1 = ((destHeight - destArea.y - destArea.height) / float(destHeight)) * 2.0f - 1.0f;
2636 float x2 = ((destArea.x + destArea.width) / float(destWidth)) * 2.0f - 1.0f;
2637 float y2 = ((destHeight - destArea.y) / float(destHeight)) * 2.0f - 1.0f;
2638
2639 float u1 = sourceArea.x / float(sourceWidth);
2640 float v1 = sourceArea.y / float(sourceHeight);
2641 float u2 = (sourceArea.x + sourceArea.width) / float(sourceWidth);
2642 float v2 = (sourceArea.y + sourceArea.height) / float(sourceHeight);
2643
2644 d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v2);
2645 d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v1);
2646 d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v2);
2647 d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v1);
2648
2649 mDeviceContext->Unmap(mCopyVB, 0);
2650
2651 static UINT stride = sizeof(d3d11::PositionTexCoordVertex);
2652 static UINT startIdx = 0;
2653 mDeviceContext->IASetVertexBuffers(0, 1, &mCopyVB, &stride, &startIdx);
2654
2655 // Apply state
2656 mDeviceContext->OMSetBlendState(NULL, NULL, 0xFFFFFFF);
2657 mDeviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF);
2658 mDeviceContext->RSSetState(NULL);
2659
2660 // Apply shaders
2661 mDeviceContext->IASetInputLayout(mCopyIL);
2662 mDeviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
2663 mDeviceContext->VSSetShader(mCopyVS, NULL, 0);
2664
2665 ID3D11PixelShader *ps = NULL;
2666 switch(destFormat)
2667 {
2668 case GL_RGBA: ps = mCopyRGBAPS; break;
2669 case GL_RGB: ps = mCopyRGBPS; break;
2670 case GL_ALPHA: ps = mCopyRGBAPS; break;
2671 case GL_BGRA_EXT: ps = mCopyRGBAPS; break;
2672 case GL_LUMINANCE: ps = mCopyLumPS; break;
2673 case GL_LUMINANCE_ALPHA: ps = mCopyLumAlphaPS; break;
2674 default: UNREACHABLE(); ps = NULL; break;
2675 }
2676
2677 mDeviceContext->PSSetShader(ps, NULL, 0);
2678 mDeviceContext->GSSetShader(NULL, NULL, 0);
2679
2680 // Unset the currently bound shader resource to avoid conflicts
2681 static ID3D11ShaderResourceView *const nullSRV = NULL;
2682 mDeviceContext->PSSetShaderResources(0, 1, &nullSRV);
2683
2684 // Apply render target
2685 setOneTimeRenderTarget(dest);
2686
2687 // Set the viewport
2688 D3D11_VIEWPORT viewport;
2689 viewport.TopLeftX = 0;
2690 viewport.TopLeftY = 0;
2691 viewport.Width = destWidth;
2692 viewport.Height = destHeight;
2693 viewport.MinDepth = 0.0f;
2694 viewport.MaxDepth = 1.0f;
2695 mDeviceContext->RSSetViewports(1, &viewport);
2696
2697 // Apply textures
2698 mDeviceContext->PSSetShaderResources(0, 1, &source);
2699 mDeviceContext->PSSetSamplers(0, 1, &mCopySampler);
2700
2701 // Draw the quad
2702 mDeviceContext->Draw(4, 0);
2703
2704 // Unbind textures and render targets and vertex buffer
2705 mDeviceContext->PSSetShaderResources(0, 1, &nullSRV);
2706
2707 unapplyRenderTargets();
2708
2709 UINT zero = 0;
2710 ID3D11Buffer *const nullBuffer = NULL;
2711 mDeviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero);
2712
2713 markAllStateDirty();
2714
2715 return true;
2716 }
2717
2718 void Renderer11::unapplyRenderTargets()
2719 {
2720 setOneTimeRenderTarget(NULL);
2721 }
2722
2723 void Renderer11::setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView)
2724 {
2725 ID3D11RenderTargetView *rtvArray[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {NULL};
2726
2727 rtvArray[0] = renderTargetView;
2728
2729 mDeviceContext->OMSetRenderTargets(getMaxRenderTargets(), rtvArray, NULL);
2730
2731 // Do not preserve the serial for this one-time-use render target
2732 for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++)
2733 {
2734 mAppliedRenderTargetSerials[rtIndex] = 0;
2735 }
2736 }
2737
2738 RenderTarget *Renderer11::createRenderTarget(SwapChain *swapChain, bool depth)
2739 {
2740 SwapChain11 *swapChain11 = SwapChain11::makeSwapChain11(swapChain);
2741 RenderTarget11 *renderTarget = NULL;
2742
2743 if (depth)
2744 {
2745 // Note: depth stencil may be NULL for 0 sized surfaces
2746 renderTarget = new RenderTarget11(this, swapChain11->getDepthStencil(),
2747 swapChain11->getDepthStencilTexture(), NULL,
2748 swapChain11->getWidth(), swapChain11->getHeight());
2749 }
2750 else
2751 {
2752 // Note: render target may be NULL for 0 sized surfaces
2753 renderTarget = new RenderTarget11(this, swapChain11->getRenderTarget(),
2754 swapChain11->getOffscreenTexture(),
2755 swapChain11->getRenderTargetShaderResource(),
2756 swapChain11->getWidth(), swapChain11->getHeight());
2757 }
2758 return renderTarget;
2759 }
2760
2761 RenderTarget *Renderer11::createRenderTarget(int width, int height, GLenum format, GLsizei samples, bool depth)
2762 {
2763 RenderTarget11 *renderTarget = new RenderTarget11(this, width, height, format, samples, depth);
2764 return renderTarget;
2765 }
2766
2767 ShaderExecutable *Renderer11::loadExecutable(const void *function, size_t length, rx::ShaderType type)
2768 {
2769 ShaderExecutable11 *executable = NULL;
2770
2771 switch (type)
2772 {
2773 case rx::SHADER_VERTEX:
2774 {
2775 ID3D11VertexShader *vshader = NULL;
2776 HRESULT result = mDevice->CreateVertexShader(function, length, NULL, &vshader);
2777 ASSERT(SUCCEEDED(result));
2778
2779 if (vshader)
2780 {
2781 executable = new ShaderExecutable11(function, length, vshader);
2782 }
2783 }
2784 break;
2785 case rx::SHADER_PIXEL:
2786 {
2787 ID3D11PixelShader *pshader = NULL;
2788 HRESULT result = mDevice->CreatePixelShader(function, length, NULL, &pshader);
2789 ASSERT(SUCCEEDED(result));
2790
2791 if (pshader)
2792 {
2793 executable = new ShaderExecutable11(function, length, pshader);
2794 }
2795 }
2796 break;
2797 case rx::SHADER_GEOMETRY:
2798 {
2799 ID3D11GeometryShader *gshader = NULL;
2800 HRESULT result = mDevice->CreateGeometryShader(function, length, NULL, &gshader);
2801 ASSERT(SUCCEEDED(result));
2802
2803 if (gshader)
2804 {
2805 executable = new ShaderExecutable11(function, length, gshader);
2806 }
2807 }
2808 break;
2809 default:
2810 UNREACHABLE();
2811 break;
2812 }
2813
2814 return executable;
2815 }
2816
2817 ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type)
2818 {
2819 const char *profile = NULL;
2820
2821 switch (type)
2822 {
2823 case rx::SHADER_VERTEX:
2824 profile = "vs_4_0";
2825 break;
2826 case rx::SHADER_PIXEL:
2827 profile = "ps_4_0";
2828 break;
2829 case rx::SHADER_GEOMETRY:
2830 profile = "gs_4_0";
2831 break;
2832 default:
2833 UNREACHABLE();
2834 return NULL;
2835 }
2836
2837 ID3DBlob *binary = (ID3DBlob*)compileToBinary(infoLog, shaderHLSL, profile, D3DCOMPILE_OPTIMIZATION_LEVEL0, false);
2838 if (!binary)
2839 return NULL;
2840
2841 ShaderExecutable *executable = loadExecutable((DWORD *)binary->GetBufferPointer(), binary->GetBufferSize(), type);
2842 binary->Release();
2843
2844 return executable;
2845 }
2846
2847 VertexBuffer *Renderer11::createVertexBuffer()
2848 {
2849 return new VertexBuffer11(this);
2850 }
2851
2852 IndexBuffer *Renderer11::createIndexBuffer()
2853 {
2854 return new IndexBuffer11(this);
2855 }
2856
2857 BufferStorage *Renderer11::createBufferStorage()
2858 {
2859 return new BufferStorage11(this);
2860 }
2861
2862 QueryImpl *Renderer11::createQuery(GLenum type)
2863 {
2864 return new Query11(this, type);
2865 }
2866
2867 FenceImpl *Renderer11::createFence()
2868 {
2869 return new Fence11(this);
2870 }
2871
2872 bool Renderer11::getRenderTargetResource(gl::Renderbuffer *colorbuffer, unsigned int *subresourceIndex, ID3D11Texture2D **resource)
2873 {
2874 ASSERT(colorbuffer != NULL);
2875
2876 RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget());
2877 if (renderTarget)
2878 {
2879 *subresourceIndex = renderTarget->getSubresourceIndex();
2880
2881 ID3D11RenderTargetView *colorBufferRTV = renderTarget->getRenderTargetView();
2882 if (colorBufferRTV)
2883 {
2884 ID3D11Resource *textureResource = NULL;
2885 colorBufferRTV->GetResource(&textureResource);
2886
2887 if (textureResource)
2888 {
2889 HRESULT result = textureResource->QueryInterface(IID_ID3D11Texture2D, (void**)resource);
2890 textureResource->Release();
2891
2892 if (SUCCEEDED(result))
2893 {
2894 return true;
2895 }
2896 else
2897 {
2898 ERR("Failed to extract the ID3D11Texture2D from the render target resource, "
2899 "HRESULT: 0x%X.", result);
2900 }
2901 }
2902 }
2903 }
2904
2905 return false;
2906 }
2907
2908 bool Renderer11::blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect,
2909 bool blitRenderTarget, bool blitDepthStencil)
2910 {
2911 if (blitRenderTarget)
2912 {
2913 gl::Renderbuffer *readBuffer = readTarget->getReadColorbuffer();
2914
2915 if (!readBuffer)
2916 {
2917 ERR("Failed to retrieve the read buffer from the read framebuffer.");
2918 return gl::error(GL_OUT_OF_MEMORY, false);
2919 }
2920
2921 RenderTarget *readRenderTarget = readBuffer->getRenderTarget();
2922
2923 for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
2924 {
2925 if (drawTarget->isEnabledColorAttachment(colorAttachment))
2926 {
2927 gl::Renderbuffer *drawBuffer = drawTarget->getColorbuffer(colorAttachment);
2928
2929 if (!drawBuffer)
2930 {
2931 ERR("Failed to retrieve the draw buffer from the draw framebuffer.");
2932 return gl::error(GL_OUT_OF_MEMORY, false);
2933 }
2934
2935 RenderTarget *drawRenderTarget = drawBuffer->getRenderTarget();
2936
2937 if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, false))
2938 {
2939 return false;
2940 }
2941 }
2942 }
2943 }
2944
2945 if (blitDepthStencil)
2946 {
2947 gl::Renderbuffer *readBuffer = readTarget->getDepthOrStencilbuffer();
2948 gl::Renderbuffer *drawBuffer = drawTarget->getDepthOrStencilbuffer();
2949
2950 if (!readBuffer)
2951 {
2952 ERR("Failed to retrieve the read depth-stencil buffer from the read framebuffer.");
2953 return gl::error(GL_OUT_OF_MEMORY, false);
2954 }
2955
2956 if (!drawBuffer)
2957 {
2958 ERR("Failed to retrieve the draw depth-stencil buffer from the draw framebuffer.");
2959 return gl::error(GL_OUT_OF_MEMORY, false);
2960 }
2961
2962 RenderTarget *readRenderTarget = readBuffer->getDepthStencil();
2963 RenderTarget *drawRenderTarget = drawBuffer->getDepthStencil();
2964
2965 if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, true))
2966 {
2967 return false;
2968 }
2969 }
2970
2971 return true;
2972 }
2973
2974 void Renderer11::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type,
2975 GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels)
2976 {
2977 ID3D11Texture2D *colorBufferTexture = NULL;
2978 unsigned int subresourceIndex = 0;
2979
2980 gl::Renderbuffer *colorbuffer = framebuffer->getReadColorbuffer();
2981
2982 if (colorbuffer && getRenderTargetResource(colorbuffer, &subresourceIndex, &colorBufferTexture))
2983 {
2984 gl::Rectangle area;
2985 area.x = x;
2986 area.y = y;
2987 area.width = width;
2988 area.height = height;
2989
2990 readTextureData(colorBufferTexture, subresourceIndex, area, format, type, outputPitch,
2991 packReverseRowOrder, packAlignment, pixels);
2992
2993 colorBufferTexture->Release();
2994 colorBufferTexture = NULL;
2995 }
2996 }
2997
2998 Image *Renderer11::createImage()
2999 {
3000 return new Image11();
3001 }
3002
3003 void Renderer11::generateMipmap(Image *dest, Image *src)
3004 {
3005 Image11 *dest11 = Image11::makeImage11(dest);
3006 Image11 *src11 = Image11::makeImage11(src);
3007 Image11::generateMipmap(dest11, src11);
3008 }
3009
3010 TextureStorage *Renderer11::createTextureStorage2D(SwapChain *swapChain)
3011 {
3012 SwapChain11 *swapChain11 = SwapChain11::makeSwapChain11(swapChain);
3013 return new TextureStorage11_2D(this, swapChain11);
3014 }
3015
3016 TextureStorage *Renderer11::createTextureStorage2D(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height)
3017 {
3018 return new TextureStorage11_2D(this, levels, internalformat, usage, forceRenderable, width, height);
3019 }
3020
3021 TextureStorage *Renderer11::createTextureStorageCube(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size)
3022 {
3023 return new TextureStorage11_Cube(this, levels, internalformat, usage, forceRenderable, size);
3024 }
3025
3026 static inline unsigned int getFastPixelCopySize(DXGI_FORMAT sourceFormat, GLenum destFormat, GLenum destType)
3027 {
3028 if (sourceFormat == DXGI_FORMAT_A8_UNORM &&
3029 destFormat == GL_ALPHA &&
3030 destType == GL_UNSIGNED_BYTE)
3031 {
3032 return 1;
3033 }
3034 else if (sourceFormat == DXGI_FORMAT_R8G8B8A8_UNORM &&
3035 destFormat == GL_RGBA &&
3036 destType == GL_UNSIGNED_BYTE)
3037 {
3038 return 4;
3039 }
3040 else if (sourceFormat == DXGI_FORMAT_B8G8R8A8_UNORM &&
3041 destFormat == GL_BGRA_EXT &&
3042 destType == GL_UNSIGNED_BYTE)
3043 {
3044 return 4;
3045 }
3046 else if (sourceFormat == DXGI_FORMAT_R16G16B16A16_FLOAT &&
3047 destFormat == GL_RGBA &&
3048 destType == GL_HALF_FLOAT_OES)
3049 {
3050 return 8;
3051 }
3052 else if (sourceFormat == DXGI_FORMAT_R32G32B32_FLOAT &&
3053 destFormat == GL_RGB &&
3054 destType == GL_FLOAT)
3055 {
3056 return 12;
3057 }
3058 else if (sourceFormat == DXGI_FORMAT_R32G32B32A32_FLOAT &&
3059 destFormat == GL_RGBA &&
3060 destType == GL_FLOAT)
3061 {
3062 return 16;
3063 }
3064 else
3065 {
3066 return 0;
3067 }
3068 }
3069
3070 static inline void readPixelColor(const unsigned char *data, DXGI_FORMAT format, unsigned int x,
3071 unsigned int y, int inputPitch, gl::Color *outColor)
3072 {
3073 switch (format)
3074 {
3075 case DXGI_FORMAT_R8G8B8A8_UNORM:
3076 {
3077 unsigned int rgba = *reinterpret_cast<const unsigned int*>(data + 4 * x + y * inputPitch);
3078 outColor->red = (rgba & 0x000000FF) * (1.0f / 0x000000FF);
3079 outColor->green = (rgba & 0x0000FF00) * (1.0f / 0x0000FF00);
3080 outColor->blue = (rgba & 0x00FF0000) * (1.0f / 0x00FF0000);
3081 outColor->alpha = (rgba & 0xFF000000) * (1.0f / 0xFF000000);
3082 }
3083 break;
3084
3085 case DXGI_FORMAT_A8_UNORM:
3086 {
3087 outColor->red = 0.0f;
3088 outColor->green = 0.0f;
3089 outColor->blue = 0.0f;
3090 outColor->alpha = *(data + x + y * inputPitch) / 255.0f;
3091 }
3092 break;
3093
3094 case DXGI_FORMAT_R32G32B32A32_FLOAT:
3095 {
3096 outColor->red = *(reinterpret_cast<const float*>(data + 16 * x + y * inputPitch) + 0);
3097 outColor->green = *(reinterpret_cast<const float*>(data + 16 * x + y * inputPitch) + 1);
3098 outColor->blue = *(reinterpret_cast<const float*>(data + 16 * x + y * inputPitch) + 2);
3099 outColor->alpha = *(reinterpret_cast<const float*>(data + 16 * x + y * inputPitch) + 3);
3100 }
3101 break;
3102
3103 case DXGI_FORMAT_R32G32B32_FLOAT:
3104 {
3105 outColor->red = *(reinterpret_cast<const float*>(data + 12 * x + y * inputPitch) + 0);
3106 outColor->green = *(reinterpret_cast<const float*>(data + 12 * x + y * inputPitch) + 1);
3107 outColor->blue = *(reinterpret_cast<const float*>(data + 12 * x + y * inputPitch) + 2);
3108 outColor->alpha = 1.0f;
3109 }
3110 break;
3111
3112 case DXGI_FORMAT_R16G16B16A16_FLOAT:
3113 {
3114 outColor->red = gl::float16ToFloat32(*(reinterpret_cast<const unsigned short*>(data + 8 * x + y * inputPitch) + 0));
3115 outColor->green = gl::float16ToFloat32(*(reinterpret_cast<const unsigned short*>(data + 8 * x + y * inputPitch) + 1));
3116 outColor->blue = gl::float16ToFloat32(*(reinterpret_cast<const unsigned short*>(data + 8 * x + y * inputPitch) + 2));
3117 outColor->alpha = gl::float16ToFloat32(*(reinterpret_cast<const unsigned short*>(data + 8 * x + y * inputPitch) + 3));
3118 }
3119 break;
3120
3121 case DXGI_FORMAT_B8G8R8A8_UNORM:
3122 {
3123 unsigned int bgra = *reinterpret_cast<const unsigned int*>(data + 4 * x + y * inputPitch);
3124 outColor->red = (bgra & 0x00FF0000) * (1.0f / 0x00FF0000);
3125 outColor->blue = (bgra & 0x000000FF) * (1.0f / 0x000000FF);
3126 outColor->green = (bgra & 0x0000FF00) * (1.0f / 0x0000FF00);
3127 outColor->alpha = (bgra & 0xFF000000) * (1.0f / 0xFF000000);
3128 }
3129 break;
3130
3131 case DXGI_FORMAT_R8_UNORM:
3132 {
3133 outColor->red = *(data + x + y * inputPitch) / 255.0f;
3134 outColor->green = 0.0f;
3135 outColor->blue = 0.0f;
3136 outColor->alpha = 1.0f;
3137 }
3138 break;
3139
3140 case DXGI_FORMAT_R8G8_UNORM:
3141 {
3142 unsigned short rg = *reinterpret_cast<const unsigned short*>(data + 2 * x + y * inputPitch);
3143
3144 outColor->red = (rg & 0xFF00) * (1.0f / 0xFF00);
3145 outColor->green = (rg & 0x00FF) * (1.0f / 0x00FF);
3146 outColor->blue = 0.0f;
3147 outColor->alpha = 1.0f;
3148 }
3149 break;
3150
3151 case DXGI_FORMAT_R16_FLOAT:
3152 {
3153 outColor->red = gl::float16ToFloat32(*reinterpret_cast<const unsigned short*>(data + 2 * x + y * inputPitch));
3154 outColor->green = 0.0f;
3155 outColor->blue = 0.0f;
3156 outColor->alpha = 1.0f;
3157 }
3158 break;
3159
3160 case DXGI_FORMAT_R16G16_FLOAT:
3161 {
3162 outColor->red = gl::float16ToFloat32(*(reinterpret_cast<const unsigned short*>(data + 4 * x + y * inputPitch) + 0));
3163 outColor->green = gl::float16ToFloat32(*(reinterpret_cast<const unsigned short*>(data + 4 * x + y * inputPitch) + 1));
3164 outColor->blue = 0.0f;
3165 outColor->alpha = 1.0f;
3166 }
3167 break;
3168
3169 default:
3170 ERR("ReadPixelColor not implemented for DXGI format %u.", format);
3171 UNIMPLEMENTED();
3172 break;
3173 }
3174 }
3175
3176 static inline void writePixelColor(const gl::Color &color, GLenum format, GLenum type, unsigned int x,
3177 unsigned int y, int outputPitch, void *outData)
3178 {
3179 unsigned char* byteData = reinterpret_cast<unsigned char*>(outData);
3180 unsigned short* shortData = reinterpret_cast<unsigned short*>(outData);
3181
3182 switch (format)
3183 {
3184 case GL_RGBA:
3185 switch (type)
3186 {
3187 case GL_UNSIGNED_BYTE:
3188 byteData[4 * x + y * outputPitch + 0] = static_cast<unsigned char>(255 * color.red + 0.5f);
3189 byteData[4 * x + y * outputPitch + 1] = static_cast<unsigned char>(255 * color.green + 0.5f);
3190 byteData[4 * x + y * outputPitch + 2] = static_cast<unsigned char>(255 * color.blue + 0.5f);
3191 byteData[4 * x + y * outputPitch + 3] = static_cast<unsigned char>(255 * color.alpha + 0.5f);
3192 break;
3193
3194 default:
3195 ERR("WritePixelColor not implemented for format GL_RGBA and type 0x%X.", type);
3196 UNIMPLEMENTED();
3197 break;
3198 }
3199 break;
3200
3201 case GL_BGRA_EXT:
3202 switch (type)
3203 {
3204 case GL_UNSIGNED_BYTE:
3205 byteData[4 * x + y * outputPitch + 0] = static_cast<unsigned char>(255 * color.blue + 0.5f);
3206 byteData[4 * x + y * outputPitch + 1] = static_cast<unsigned char>(255 * color.green + 0.5f);
3207 byteData[4 * x + y * outputPitch + 2] = static_cast<unsigned char>(255 * color.red + 0.5f);
3208 byteData[4 * x + y * outputPitch + 3] = static_cast<unsigned char>(255 * color.alpha + 0.5f);
3209 break;
3210
3211 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
3212 // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section
3213 // this type is packed as follows:
3214 // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
3215 // --------------------------------------------------------------------------------
3216 // | 4th | 3rd | 2nd | 1st component |
3217 // --------------------------------------------------------------------------------
3218 // in the case of BGRA_EXT, B is the first component, G the second, and so forth.
3219 shortData[x + y * outputPitch / sizeof(unsigned short)] =
3220 (static_cast<unsigned short>(15 * color.alpha + 0.5f) << 12) |
3221 (static_cast<unsigned short>(15 * color.red + 0.5f) << 8) |
3222 (static_cast<unsigned short>(15 * color.green + 0.5f) << 4) |
3223 (static_cast<unsigned short>(15 * color.blue + 0.5f) << 0);
3224 break;
3225
3226 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
3227 // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section
3228 // this type is packed as follows:
3229 // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
3230 // --------------------------------------------------------------------------------
3231 // | 4th | 3rd | 2nd | 1st component |
3232 // --------------------------------------------------------------------------------
3233 // in the case of BGRA_EXT, B is the first component, G the second, and so forth.
3234 shortData[x + y * outputPitch / sizeof(unsigned short)] =
3235 (static_cast<unsigned short>( color.alpha + 0.5f) << 15) |
3236 (static_cast<unsigned short>(31 * color.red + 0.5f) << 10) |
3237 (static_cast<unsigned short>(31 * color.green + 0.5f) << 5) |
3238 (static_cast<unsigned short>(31 * color.blue + 0.5f) << 0);
3239 break;
3240
3241 default:
3242 ERR("WritePixelColor not implemented for format GL_BGRA_EXT and type 0x%X.", type);
3243 UNIMPLEMENTED();
3244 break;
3245 }
3246 break;
3247
3248 case GL_RGB:
3249 switch (type)
3250 {
3251 case GL_UNSIGNED_SHORT_5_6_5:
3252 shortData[x + y * outputPitch / sizeof(unsigned short)] =
3253 (static_cast<unsigned short>(31 * color.blue + 0.5f) << 0) |
3254 (static_cast<unsigned short>(63 * color.green + 0.5f) << 5) |
3255 (static_cast<unsigned short>(31 * color.red + 0.5f) << 11);
3256 break;
3257
3258 case GL_UNSIGNED_BYTE:
3259 byteData[3 * x + y * outputPitch + 0] = static_cast<unsigned char>(255 * color.red + 0.5f);
3260 byteData[3 * x + y * outputPitch + 1] = static_cast<unsigned char>(255 * color.green + 0.5f);
3261 byteData[3 * x + y * outputPitch + 2] = static_cast<unsigned char>(255 * color.blue + 0.5f);
3262 break;
3263
3264 default:
3265 ERR("WritePixelColor not implemented for format GL_RGB and type 0x%X.", type);
3266 UNIMPLEMENTED();
3267 break;
3268 }
3269 break;
3270
3271 default:
3272 ERR("WritePixelColor not implemented for format 0x%X.", format);
3273 UNIMPLEMENTED();
3274 break;
3275 }
3276 }
3277
3278 void Renderer11::readTextureData(ID3D11Texture2D *texture, unsigned int subResource, const gl::Rectangle &area,
3279 GLenum format, GLenum type, GLsizei outputPitch, bool packReverseRowOrder,
3280 GLint packAlignment, void *pixels)
3281 {
3282 D3D11_TEXTURE2D_DESC textureDesc;
3283 texture->GetDesc(&textureDesc);
3284
3285 D3D11_TEXTURE2D_DESC stagingDesc;
3286 stagingDesc.Width = area.width;
3287 stagingDesc.Height = area.height;
3288 stagingDesc.MipLevels = 1;
3289 stagingDesc.ArraySize = 1;
3290 stagingDesc.Format = textureDesc.Format;
3291 stagingDesc.SampleDesc.Count = 1;
3292 stagingDesc.SampleDesc.Quality = 0;
3293 stagingDesc.Usage = D3D11_USAGE_STAGING;
3294 stagingDesc.BindFlags = 0;
3295 stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
3296 stagingDesc.MiscFlags = 0;
3297
3298 ID3D11Texture2D* stagingTex = NULL;
3299 HRESULT result = mDevice->CreateTexture2D(&stagingDesc, NULL, &stagingTex);
3300 if (FAILED(result))
3301 {
3302 ERR("Failed to create staging texture for readPixels, HRESULT: 0x%X.", result);
3303 return;
3304 }
3305
3306 ID3D11Texture2D* srcTex = NULL;
3307 if (textureDesc.SampleDesc.Count > 1)
3308 {
3309 D3D11_TEXTURE2D_DESC resolveDesc;
3310 resolveDesc.Width = textureDesc.Width;
3311 resolveDesc.Height = textureDesc.Height;
3312 resolveDesc.MipLevels = 1;
3313 resolveDesc.ArraySize = 1;
3314 resolveDesc.Format = textureDesc.Format;
3315 resolveDesc.SampleDesc.Count = 1;
3316 resolveDesc.SampleDesc.Quality = 0;
3317 resolveDesc.Usage = D3D11_USAGE_DEFAULT;
3318 resolveDesc.BindFlags = 0;
3319 resolveDesc.CPUAccessFlags = 0;
3320 resolveDesc.MiscFlags = 0;
3321
3322 result = mDevice->CreateTexture2D(&resolveDesc, NULL, &srcTex);
3323 if (FAILED(result))
3324 {
3325 ERR("Failed to create resolve texture for readPixels, HRESULT: 0x%X.", result);
3326 stagingTex->Release();
3327 return;
3328 }
3329
3330 mDeviceContext->ResolveSubresource(srcTex, 0, texture, subResource, textureDesc.Format);
3331 subResource = 0;
3332 }
3333 else
3334 {
3335 srcTex = texture;
3336 srcTex->AddRef();
3337 }
3338
3339 D3D11_BOX srcBox;
3340 srcBox.left = area.x;
3341 srcBox.right = area.x + area.width;
3342 srcBox.top = area.y;
3343 srcBox.bottom = area.y + area.height;
3344 srcBox.front = 0;
3345 srcBox.back = 1;
3346
3347 mDeviceContext->CopySubresourceRegion(stagingTex, 0, 0, 0, 0, srcTex, subResource, &srcBox);
3348
3349 srcTex->Release();
3350 srcTex = NULL;
3351
3352 D3D11_MAPPED_SUBRESOURCE mapping;
3353 mDeviceContext->Map(stagingTex, 0, D3D11_MAP_READ, 0, &mapping);
3354
3355 unsigned char *source;
3356 int inputPitch;
3357 if (packReverseRowOrder)
3358 {
3359 source = static_cast<unsigned char*>(mapping.pData) + mapping.RowPitch * (area.height - 1);
3360 inputPitch = -static_cast<int>(mapping.RowPitch);
3361 }
3362 else
3363 {
3364 source = static_cast<unsigned char*>(mapping.pData);
3365 inputPitch = static_cast<int>(mapping.RowPitch);
3366 }
3367
3368 unsigned int fastPixelSize = getFastPixelCopySize(textureDesc.Format, format, type);
3369 if (fastPixelSize != 0)
3370 {
3371 unsigned char *dest = static_cast<unsigned char*>(pixels);
3372 for (int j = 0; j < area.height; j++)
3373 {
3374 memcpy(dest + j * outputPitch, source + j * inputPitch, area.width * fastPixelSize);
3375 }
3376 }
3377 else if (textureDesc.Format == DXGI_FORMAT_B8G8R8A8_UNORM &&
3378 format == GL_RGBA &&
3379 type == GL_UNSIGNED_BYTE)
3380 {
3381 // Fast path for swapping red with blue
3382 unsigned char *dest = static_cast<unsigned char*>(pixels);
3383
3384 for (int j = 0; j < area.height; j++)
3385 {
3386 for (int i = 0; i < area.width; i++)
3387 {
3388 unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch);
3389 *(unsigned int*)(dest + 4 * i + j * outputPitch) =
3390 (argb & 0xFF00FF00) | // Keep alpha and green
3391 (argb & 0x00FF0000) >> 16 | // Move red to blue
3392 (argb & 0x000000FF) << 16; // Move blue to red
3393 }
3394 }
3395 }
3396 else
3397 {
3398 gl::Color pixelColor;
3399 for (int j = 0; j < area.height; j++)
3400 {
3401 for (int i = 0; i < area.width; i++)
3402 {
3403 readPixelColor(source, textureDesc.Format, i, j, inputPitch, &pixelColor);
3404 writePixelColor(pixelColor, format, type, i, j, outputPitch, pixels);
3405 }
3406 }
3407 }
3408
3409 mDeviceContext->Unmap(stagingTex, 0);
3410
3411 stagingTex->Release();
3412 stagingTex = NULL;
3413 }
3414
3415 bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget,
3416 RenderTarget *drawRenderTarget, bool wholeBufferCopy)
3417 {
3418 ASSERT(readRect.width == drawRect.width && readRect.height == drawRect.height);
3419
3420 RenderTarget11 *drawRenderTarget11 = RenderTarget11::makeRenderTarget11(drawRenderTarget);
3421 if (!drawRenderTarget)
3422 {
3423 ERR("Failed to retrieve the draw render target from the draw framebuffer.");
3424 return gl::error(GL_OUT_OF_MEMORY, false);
3425 }
3426
3427 ID3D11Texture2D *drawTexture = drawRenderTarget11->getTexture();
3428 unsigned int drawSubresource = drawRenderTarget11->getSubresourceIndex();
3429
3430 RenderTarget11 *readRenderTarget11 = RenderTarget11::makeRenderTarget11(readRenderTarget);
3431 if (!readRenderTarget)
3432 {
3433 ERR("Failed to retrieve the read render target from the read framebuffer.");
3434 return gl::error(GL_OUT_OF_MEMORY, false);
3435 }
3436
3437 ID3D11Texture2D *readTexture = NULL;
3438 unsigned int readSubresource = 0;
3439 if (readRenderTarget->getSamples() > 0)
3440 {
3441 readTexture = resolveMultisampledTexture(readRenderTarget11->getTexture(), readRenderTarget11->getSubresourceIndex());
3442 readSubresource = 0;
3443 }
3444 else
3445 {
3446 readTexture = readRenderTarget11->getTexture();
3447 readTexture->AddRef();
3448 readSubresource = readRenderTarget11->getSubresourceIndex();
3449 }
3450
3451 if (!readTexture)
3452 {
3453 ERR("Failed to retrieve the read render target view from the read render target.");
3454 return gl::error(GL_OUT_OF_MEMORY, false);
3455 }
3456
3457 D3D11_BOX readBox;
3458 readBox.left = readRect.x;
3459 readBox.right = readRect.x + readRect.width;
3460 readBox.top = readRect.y;
3461 readBox.bottom = readRect.y + readRect.height;
3462 readBox.front = 0;
3463 readBox.back = 1;
3464
3465 // D3D11 needs depth-stencil CopySubresourceRegions to have a NULL pSrcBox
3466 // We also require complete framebuffer copies for depth-stencil blit.
3467 D3D11_BOX *pSrcBox = wholeBufferCopy ? NULL : &readBox;
3468
3469 mDeviceContext->CopySubresourceRegion(drawTexture, drawSubresource, drawRect.x, drawRect.y, 0,
3470 readTexture, readSubresource, pSrcBox);
3471
3472 SafeRelease(readTexture);
3473
3474 return true;
3475 }
3476
3477 ID3D11Texture2D *Renderer11::resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource)
3478 {
3479 D3D11_TEXTURE2D_DESC textureDesc;
3480 source->GetDesc(&textureDesc);
3481
3482 if (textureDesc.SampleDesc.Count > 1)
3483 {
3484 D3D11_TEXTURE2D_DESC resolveDesc;
3485 resolveDesc.Width = textureDesc.Width;
3486 resolveDesc.Height = textureDesc.Height;
3487 resolveDesc.MipLevels = 1;
3488 resolveDesc.ArraySize = 1;
3489 resolveDesc.Format = textureDesc.Format;
3490 resolveDesc.SampleDesc.Count = 1;
3491 resolveDesc.SampleDesc.Quality = 0;
3492 resolveDesc.Usage = textureDesc.Usage;
3493 resolveDesc.BindFlags = textureDesc.BindFlags;
3494 resolveDesc.CPUAccessFlags = 0;
3495 resolveDesc.MiscFlags = 0;
3496
3497 ID3D11Texture2D *resolveTexture = NULL;
3498 HRESULT result = mDevice->CreateTexture2D(&resolveDesc, NULL, &resolveTexture);
3499 if (FAILED(result))
3500 {
3501 ERR("Failed to create a multisample resolve texture, HRESULT: 0x%X.", result);
3502 return NULL;
3503 }
3504
3505 mDeviceContext->ResolveSubresource(resolveTexture, 0, source, subresource, textureDesc.Format);
3506 return resolveTexture;
3507 }
3508 else
3509 {
3510 source->AddRef();
3511 return source;
3512 }
3513 }
3514
3515 bool Renderer11::getLUID(LUID *adapterLuid) const
3516 {
3517 adapterLuid->HighPart = 0;
3518 adapterLuid->LowPart = 0;
3519
3520 if (!mDxgiAdapter)
3521 {
3522 return false;
3523 }
3524
3525 DXGI_ADAPTER_DESC adapterDesc;
3526 if (FAILED(mDxgiAdapter->GetDesc(&adapterDesc)))
3527 {
3528 return false;
3529 }
3530
3531 *adapterLuid = adapterDesc.AdapterLuid;
3532 return true;
3533 }
3534
3535 }

mercurial