|
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 } |