blob: f093b81ebe354de9f4c3982d1358ff1c7b48b449 [file] [log] [blame]
shannon.woods@transgaming.combdf2d802013-02-28 23:16:20 +00001#include "precompiled.h"
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00002//
daniel@transgaming.com54de24f2013-01-11 04:07:59 +00003// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved.
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00004// 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
daniel@transgaming.com5503fd02012-11-28 19:38:57 +000010#include "libGLESv2/main.h"
shannonwoods@chromium.orga2ecfcc2013-05-30 00:11:59 +000011#include "common/utilities.h"
daniel@transgaming.com18adad02012-11-28 21:04:03 +000012#include "libGLESv2/Buffer.h"
daniel@transgaming.com53670042012-11-28 20:55:51 +000013#include "libGLESv2/ProgramBinary.h"
daniel@transgaming.com80fc3322012-11-28 21:02:13 +000014#include "libGLESv2/Framebuffer.h"
shannon.woods@transgaming.com486d9e92013-02-28 23:15:41 +000015#include "libGLESv2/RenderBuffer.h"
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +000016#include "libGLESv2/renderer/Renderer11.h"
daniel@transgaming.comb6b27bc2012-11-28 20:54:30 +000017#include "libGLESv2/renderer/RenderTarget11.h"
daniel@transgaming.com65e65372012-11-28 19:33:50 +000018#include "libGLESv2/renderer/renderer11_utils.h"
shannonwoods@chromium.org755012f2013-05-30 00:09:32 +000019#include "libGLESv2/renderer/formatutils11.h"
daniel@transgaming.coma2f9fbe2012-11-28 21:03:40 +000020#include "libGLESv2/renderer/ShaderExecutable11.h"
daniel@transgaming.coma60160b2012-11-28 19:41:15 +000021#include "libGLESv2/renderer/SwapChain11.h"
daniel@transgaming.coma8aac672012-12-20 21:08:00 +000022#include "libGLESv2/renderer/Image11.h"
daniel@transgaming.com2c4d0702012-12-20 21:08:51 +000023#include "libGLESv2/renderer/VertexBuffer11.h"
daniel@transgaming.com11c2af52012-12-20 21:10:01 +000024#include "libGLESv2/renderer/IndexBuffer11.h"
shannon.woods@transgaming.com4e52b632013-02-28 23:08:01 +000025#include "libGLESv2/renderer/BufferStorage11.h"
daniel@transgaming.comc5431eb2012-12-20 21:10:15 +000026#include "libGLESv2/renderer/VertexDataManager.h"
27#include "libGLESv2/renderer/IndexDataManager.h"
daniel@transgaming.comb1c208f2013-01-11 04:06:49 +000028#include "libGLESv2/renderer/TextureStorage11.h"
shannon.woods@transgaming.com8b7606a2013-02-28 23:03:47 +000029#include "libGLESv2/renderer/Query11.h"
shannon.woods@transgaming.combe58aa02013-02-28 23:03:55 +000030#include "libGLESv2/renderer/Fence11.h"
Geoff Langb86b9792013-06-04 16:32:05 -040031#include "libGLESv2/renderer/Blit11.h"
shannonwoods@chromium.org7b61d5c2013-05-30 00:04:12 +000032
shannon.woods@transgaming.com34f507c2013-01-25 21:52:15 +000033#include "libGLESv2/renderer/shaders/compiled/clear11vs.h"
shannonwoods@chromium.org98949842013-05-30 00:01:51 +000034#include "libGLESv2/renderer/shaders/compiled/clearsingle11ps.h"
35#include "libGLESv2/renderer/shaders/compiled/clearmultiple11ps.h"
shannon.woods@transgaming.com34f507c2013-01-25 21:52:15 +000036
shannon.woods@transgaming.com486d9e92013-02-28 23:15:41 +000037#include "libEGL/Display.h"
38
shannon.woods@transgaming.com236be772013-02-28 23:18:15 +000039#ifdef _DEBUG
40// this flag enables suppressing some spurious warnings that pop up in certain WebGL samples
41// and conformance tests. to enable all warnings, remove this define.
42#define ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS 1
43#endif
44
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +000045namespace rx
46{
daniel@transgaming.com65e65372012-11-28 19:33:50 +000047static const DXGI_FORMAT RenderTargetFormats[] =
48 {
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +000049 DXGI_FORMAT_B8G8R8A8_UNORM,
daniel@transgaming.com65e65372012-11-28 19:33:50 +000050 DXGI_FORMAT_R8G8B8A8_UNORM
51 };
52
53static const DXGI_FORMAT DepthStencilFormats[] =
54 {
shannon.woods@transgaming.comeec5c632013-02-28 23:04:21 +000055 DXGI_FORMAT_UNKNOWN,
56 DXGI_FORMAT_D24_UNORM_S8_UINT,
57 DXGI_FORMAT_D16_UNORM
daniel@transgaming.com65e65372012-11-28 19:33:50 +000058 };
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +000059
shannon.woods@transgaming.com233fe952013-01-25 21:51:57 +000060enum
61{
62 MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 = 16
63};
64
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +000065Renderer11::Renderer11(egl::Display *display, HDC hDc) : Renderer(display), mDc(hDc)
66{
daniel@transgaming.comc5431eb2012-12-20 21:10:15 +000067 mVertexDataManager = NULL;
68 mIndexDataManager = NULL;
69
daniel@transgaming.comc5114302012-12-20 21:11:36 +000070 mLineLoopIB = NULL;
daniel@transgaming.com4fd1f982013-01-11 04:12:58 +000071 mTriangleFanIB = NULL;
daniel@transgaming.comc5114302012-12-20 21:11:36 +000072
Geoff Langb86b9792013-06-04 16:32:05 -040073 mBlit = NULL;
shannon.woods@transgaming.com9d971ff2013-01-25 21:50:53 +000074
shannon.woods@transgaming.com34f507c2013-01-25 21:52:15 +000075 mClearResourcesInitialized = false;
76 mClearVB = NULL;
77 mClearIL = NULL;
78 mClearVS = NULL;
shannonwoods@chromium.org98949842013-05-30 00:01:51 +000079 mClearSinglePS = NULL;
80 mClearMultiplePS = NULL;
shannon.woods@transgaming.com34f507c2013-01-25 21:52:15 +000081 mClearScissorRS = NULL;
82 mClearNoScissorRS = NULL;
83
daniel@transgaming.combdf787f2013-02-01 03:20:36 +000084 mSyncQuery = NULL;
85
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +000086 mD3d11Module = NULL;
87 mDxgiModule = NULL;
88
daniel@transgaming.comb9bb2792012-11-28 19:36:49 +000089 mDeviceLost = false;
90
shannon.woods@transgaming.comdf2fd572013-02-28 23:05:40 +000091 mMaxSupportedSamples = 0;
92
daniel@transgaming.com25072f62012-11-28 19:31:32 +000093 mDevice = NULL;
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +000094 mDeviceContext = NULL;
daniel@transgaming.com65e65372012-11-28 19:33:50 +000095 mDxgiAdapter = NULL;
96 mDxgiFactory = NULL;
shannon.woods@transgaming.com5fb979d2013-01-25 21:53:04 +000097
98 mDriverConstantBufferVS = NULL;
99 mDriverConstantBufferPS = NULL;
shannon.woods@transgaming.combec04bf2013-01-25 21:53:52 +0000100
101 mBGRATextureSupport = false;
shannon.woods@transgaming.comdd2524c2013-02-28 23:04:33 +0000102
103 mIsGeometryShaderActive = false;
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000104}
105
106Renderer11::~Renderer11()
107{
shannon.woods@transgaming.comddd6c802013-02-28 23:05:14 +0000108 release();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000109}
110
daniel@transgaming.comb64ed282012-11-28 20:54:02 +0000111Renderer11 *Renderer11::makeRenderer11(Renderer *renderer)
112{
apatrick@chromium.org8b400b12013-01-30 21:53:40 +0000113 ASSERT(HAS_DYNAMIC_TYPE(rx::Renderer11*, renderer));
daniel@transgaming.comb64ed282012-11-28 20:54:02 +0000114 return static_cast<rx::Renderer11*>(renderer);
115}
116
shannon.woods%transgaming.com@gtempaccount.comf9686c22013-04-13 03:33:45 +0000117#ifndef __d3d11_1_h__
118#define D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET ((D3D11_MESSAGE_ID)3146081)
119#endif
120
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000121EGLint Renderer11::initialize()
122{
daniel@transgaming.com25e16af2012-11-28 21:05:57 +0000123 if (!initializeCompiler())
124 {
125 return EGL_NOT_INITIALIZED;
126 }
127
daniel@transgaming.comc1e26342012-11-28 19:31:16 +0000128 mDxgiModule = LoadLibrary(TEXT("dxgi.dll"));
129 mD3d11Module = LoadLibrary(TEXT("d3d11.dll"));
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000130
131 if (mD3d11Module == NULL || mDxgiModule == NULL)
132 {
daniel@transgaming.comc1e26342012-11-28 19:31:16 +0000133 ERR("Could not load D3D11 or DXGI library - aborting!\n");
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000134 return EGL_NOT_INITIALIZED;
135 }
136
shannon.woods@transgaming.comddd6c802013-02-28 23:05:14 +0000137 // create the D3D11 device
138 ASSERT(mDevice == NULL);
daniel@transgaming.comc1e26342012-11-28 19:31:16 +0000139 PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice");
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000140
daniel@transgaming.comc1e26342012-11-28 19:31:16 +0000141 if (D3D11CreateDevice == NULL)
142 {
143 ERR("Could not retrieve D3D11CreateDevice address - aborting!\n");
144 return EGL_NOT_INITIALIZED;
145 }
shannon.woods@transgaming.comdf2fd572013-02-28 23:05:40 +0000146
shannon.woods@transgaming.comd438fd42013-02-28 23:17:45 +0000147 D3D_FEATURE_LEVEL featureLevels[] =
daniel@transgaming.com25072f62012-11-28 19:31:32 +0000148 {
149 D3D_FEATURE_LEVEL_11_0,
150 D3D_FEATURE_LEVEL_10_1,
151 D3D_FEATURE_LEVEL_10_0,
152 };
shannon.woods@transgaming.comdf2fd572013-02-28 23:05:40 +0000153
shannonwoods@chromium.orgc3419c12013-05-30 00:02:01 +0000154 HRESULT result = S_OK;
155
156#ifdef _DEBUG
157 result = D3D11CreateDevice(NULL,
158 D3D_DRIVER_TYPE_HARDWARE,
159 NULL,
160 D3D11_CREATE_DEVICE_DEBUG,
161 featureLevels,
162 ArraySize(featureLevels),
163 D3D11_SDK_VERSION,
164 &mDevice,
165 &mFeatureLevel,
166 &mDeviceContext);
shannon.woods@transgaming.comdf2fd572013-02-28 23:05:40 +0000167
daniel@transgaming.com25072f62012-11-28 19:31:32 +0000168 if (!mDevice || FAILED(result))
daniel@transgaming.comc1e26342012-11-28 19:31:16 +0000169 {
shannonwoods@chromium.orgc3419c12013-05-30 00:02:01 +0000170 ERR("Failed creating Debug D3D11 device - falling back to release runtime.\n");
171 }
172
173 if (!mDevice || FAILED(result))
174#endif
175 {
176 result = D3D11CreateDevice(NULL,
177 D3D_DRIVER_TYPE_HARDWARE,
178 NULL,
179 0,
180 featureLevels,
181 ArraySize(featureLevels),
182 D3D11_SDK_VERSION,
183 &mDevice,
184 &mFeatureLevel,
185 &mDeviceContext);
186
187 if (!mDevice || FAILED(result))
188 {
189 ERR("Could not create D3D11 device - aborting!\n");
190 return EGL_NOT_INITIALIZED; // Cleanup done by destructor through glDestroyRenderer
191 }
daniel@transgaming.comc1e26342012-11-28 19:31:16 +0000192 }
daniel@transgaming.com65e65372012-11-28 19:33:50 +0000193
194 IDXGIDevice *dxgiDevice = NULL;
195 result = mDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgiDevice);
196
197 if (FAILED(result))
198 {
199 ERR("Could not query DXGI device - aborting!\n");
200 return EGL_NOT_INITIALIZED;
201 }
202
203 result = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&mDxgiAdapter);
204
205 if (FAILED(result))
206 {
207 ERR("Could not retrieve DXGI adapter - aborting!\n");
208 return EGL_NOT_INITIALIZED;
209 }
210
211 dxgiDevice->Release();
212
daniel@transgaming.com1f811f52012-11-28 20:57:39 +0000213 mDxgiAdapter->GetDesc(&mAdapterDescription);
214 memset(mDescription, 0, sizeof(mDescription));
215 wcstombs(mDescription, mAdapterDescription.Description, sizeof(mDescription) - 1);
216
daniel@transgaming.com65e65372012-11-28 19:33:50 +0000217 result = mDxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void**)&mDxgiFactory);
218
219 if (!mDxgiFactory || FAILED(result))
220 {
221 ERR("Could not create DXGI factory - aborting!\n");
222 return EGL_NOT_INITIALIZED;
223 }
224
shannon.woods@transgaming.com236be772013-02-28 23:18:15 +0000225 // Disable some spurious D3D11 debug warnings to prevent them from flooding the output log
226#if defined(ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS) && defined(_DEBUG)
227 ID3D11InfoQueue *infoQueue;
228 result = mDevice->QueryInterface(__uuidof(ID3D11InfoQueue), (void **)&infoQueue);
229
230 if (SUCCEEDED(result))
231 {
232 D3D11_MESSAGE_ID hideMessages[] =
233 {
234 D3D11_MESSAGE_ID_DEVICE_OMSETRENDERTARGETS_HAZARD,
shannon.woods%transgaming.com@gtempaccount.comf9686c22013-04-13 03:33:45 +0000235 D3D11_MESSAGE_ID_DEVICE_PSSETSHADERRESOURCES_HAZARD,
236 D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET
shannon.woods@transgaming.com236be772013-02-28 23:18:15 +0000237 };
238
239 D3D11_INFO_QUEUE_FILTER filter = {0};
240 filter.DenyList.NumIDs = ArraySize(hideMessages);
241 filter.DenyList.pIDList = hideMessages;
242
243 infoQueue->AddStorageFilterEntries(&filter);
244
245 infoQueue->Release();
246 }
247#endif
248
Geoff Lang61e49a52013-05-29 10:22:58 -0400249 mMaxSupportedSamples = 0;
250
251 const d3d11::DXGIFormatSet &dxgiFormats = d3d11::GetAllUsedDXGIFormats();
252 for (d3d11::DXGIFormatSet::const_iterator i = dxgiFormats.begin(); i != dxgiFormats.end(); ++i)
shannon.woods@transgaming.comdf2fd572013-02-28 23:05:40 +0000253 {
Geoff Lang61e49a52013-05-29 10:22:58 -0400254 MultisampleSupportInfo support = getMultisampleSupportInfo(*i);
255 mMultisampleSupportMap.insert(std::make_pair(*i, support));
256 mMaxSupportedSamples = std::max(mMaxSupportedSamples, support.maxSupportedSamples);
shannon.woods@transgaming.comdf2fd572013-02-28 23:05:40 +0000257 }
shannon.woods@transgaming.comdf2fd572013-02-28 23:05:40 +0000258
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000259 initializeDevice();
260
shannon.woods@transgaming.combec04bf2013-01-25 21:53:52 +0000261 // BGRA texture support is optional in feature levels 10 and 10_1
262 UINT formatSupport;
263 result = mDevice->CheckFormatSupport(DXGI_FORMAT_B8G8R8A8_UNORM, &formatSupport);
264 if (FAILED(result))
265 {
266 ERR("Error checking BGRA format support: 0x%08X", result);
267 }
268 else
269 {
270 const int flags = (D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_RENDER_TARGET);
271 mBGRATextureSupport = (formatSupport & flags) == flags;
272 }
273
shannon.woods@transgaming.com9cdced62013-02-28 23:07:31 +0000274 // Check floating point texture support
275 static const unsigned int requiredTextureFlags = D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_TEXTURECUBE;
276 static const unsigned int requiredRenderableFlags = D3D11_FORMAT_SUPPORT_RENDER_TARGET;
277 static const unsigned int requiredFilterFlags = D3D11_FORMAT_SUPPORT_SHADER_SAMPLE;
278
279 DXGI_FORMAT float16Formats[] =
280 {
281 DXGI_FORMAT_R16_FLOAT,
282 DXGI_FORMAT_R16G16_FLOAT,
283 DXGI_FORMAT_R16G16B16A16_FLOAT,
284 };
285
286 DXGI_FORMAT float32Formats[] =
287 {
288 DXGI_FORMAT_R32_FLOAT,
289 DXGI_FORMAT_R32G32_FLOAT,
290 DXGI_FORMAT_R32G32B32_FLOAT,
291 DXGI_FORMAT_R32G32B32A32_FLOAT,
292 };
293
294 mFloat16TextureSupport = true;
295 mFloat16FilterSupport = true;
296 mFloat16RenderSupport = true;
297 for (unsigned int i = 0; i < ArraySize(float16Formats); i++)
298 {
299 if (SUCCEEDED(mDevice->CheckFormatSupport(float16Formats[i], &formatSupport)))
300 {
301 mFloat16TextureSupport = mFloat16TextureSupport && (formatSupport & requiredTextureFlags) == requiredTextureFlags;
302 mFloat16FilterSupport = mFloat16FilterSupport && (formatSupport & requiredFilterFlags) == requiredFilterFlags;
303 mFloat16RenderSupport = mFloat16RenderSupport && (formatSupport & requiredRenderableFlags) == requiredRenderableFlags;
304 }
305 else
306 {
307 mFloat16TextureSupport = false;
308 mFloat16RenderSupport = false;
309 mFloat16FilterSupport = false;
310 }
311 }
312
313 mFloat32TextureSupport = true;
314 mFloat32FilterSupport = true;
315 mFloat32RenderSupport = true;
316 for (unsigned int i = 0; i < ArraySize(float32Formats); i++)
317 {
318 if (SUCCEEDED(mDevice->CheckFormatSupport(float32Formats[i], &formatSupport)))
319 {
320 mFloat32TextureSupport = mFloat32TextureSupport && (formatSupport & requiredTextureFlags) == requiredTextureFlags;
321 mFloat32FilterSupport = mFloat32FilterSupport && (formatSupport & requiredFilterFlags) == requiredFilterFlags;
322 mFloat32RenderSupport = mFloat32RenderSupport && (formatSupport & requiredRenderableFlags) == requiredRenderableFlags;
323 }
324 else
325 {
326 mFloat32TextureSupport = false;
327 mFloat32FilterSupport = false;
328 mFloat32RenderSupport = false;
329 }
330 }
331
shannon.woods@transgaming.com09f326b2013-02-28 23:13:34 +0000332 // Check compressed texture support
333 const unsigned int requiredCompressedTextureFlags = D3D11_FORMAT_SUPPORT_TEXTURE2D;
334
335 if (SUCCEEDED(mDevice->CheckFormatSupport(DXGI_FORMAT_BC1_UNORM, &formatSupport)))
336 {
337 mDXT1TextureSupport = (formatSupport & requiredCompressedTextureFlags) == requiredCompressedTextureFlags;
338 }
339 else
340 {
341 mDXT1TextureSupport = false;
342 }
343
344 if (SUCCEEDED(mDevice->CheckFormatSupport(DXGI_FORMAT_BC3_UNORM, &formatSupport)))
345 {
346 mDXT3TextureSupport = (formatSupport & requiredCompressedTextureFlags) == requiredCompressedTextureFlags;
347 }
348 else
349 {
350 mDXT3TextureSupport = false;
351 }
352
353 if (SUCCEEDED(mDevice->CheckFormatSupport(DXGI_FORMAT_BC5_UNORM, &formatSupport)))
354 {
355 mDXT5TextureSupport = (formatSupport & requiredCompressedTextureFlags) == requiredCompressedTextureFlags;
356 }
357 else
358 {
359 mDXT5TextureSupport = false;
360 }
361
shannon.woods@transgaming.comcf103f32013-02-28 23:18:45 +0000362 // Check depth texture support
363 DXGI_FORMAT depthTextureFormats[] =
364 {
365 DXGI_FORMAT_D16_UNORM,
366 DXGI_FORMAT_D24_UNORM_S8_UINT,
367 };
368
369 static const unsigned int requiredDepthTextureFlags = D3D11_FORMAT_SUPPORT_DEPTH_STENCIL |
370 D3D11_FORMAT_SUPPORT_TEXTURE2D;
371
372 mDepthTextureSupport = true;
373 for (unsigned int i = 0; i < ArraySize(depthTextureFormats); i++)
374 {
375 if (SUCCEEDED(mDevice->CheckFormatSupport(depthTextureFormats[i], &formatSupport)))
376 {
377 mDepthTextureSupport = mDepthTextureSupport && ((formatSupport & requiredDepthTextureFlags) == requiredDepthTextureFlags);
378 }
379 else
380 {
381 mDepthTextureSupport = false;
382 }
383 }
384
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000385 return EGL_SUCCESS;
386}
387
388// do any one-time device initialization
389// NOTE: this is also needed after a device lost/reset
390// to reset the scene status and ensure the default states are reset.
391void Renderer11::initializeDevice()
392{
daniel@transgaming.comf8ba1092012-11-28 19:37:53 +0000393 mStateCache.initialize(mDevice);
daniel@transgaming.comc5431eb2012-12-20 21:10:15 +0000394 mInputLayoutCache.initialize(mDevice, mDeviceContext);
395
396 ASSERT(!mVertexDataManager && !mIndexDataManager);
397 mVertexDataManager = new VertexDataManager(this);
398 mIndexDataManager = new IndexDataManager(this);
daniel@transgaming.comf8ba1092012-11-28 19:37:53 +0000399
Geoff Langb86b9792013-06-04 16:32:05 -0400400 ASSERT(!mBlit);
401 mBlit = new Blit11(this);
402
daniel@transgaming.comc43a6052012-11-28 19:41:51 +0000403 markAllStateDirty();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000404}
405
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000406int Renderer11::generateConfigs(ConfigDesc **configDescList)
407{
shannon.woods@transgaming.comd438fd42013-02-28 23:17:45 +0000408 unsigned int numRenderFormats = ArraySize(RenderTargetFormats);
409 unsigned int numDepthFormats = ArraySize(DepthStencilFormats);
daniel@transgaming.com65e65372012-11-28 19:33:50 +0000410 (*configDescList) = new ConfigDesc[numRenderFormats * numDepthFormats];
411 int numConfigs = 0;
412
daniel@transgaming.come3e826d2012-11-28 19:42:35 +0000413 for (unsigned int formatIndex = 0; formatIndex < numRenderFormats; formatIndex++)
daniel@transgaming.com65e65372012-11-28 19:33:50 +0000414 {
daniel@transgaming.come3e826d2012-11-28 19:42:35 +0000415 for (unsigned int depthStencilIndex = 0; depthStencilIndex < numDepthFormats; depthStencilIndex++)
daniel@transgaming.com65e65372012-11-28 19:33:50 +0000416 {
417 DXGI_FORMAT renderTargetFormat = RenderTargetFormats[formatIndex];
418
419 UINT formatSupport = 0;
420 HRESULT result = mDevice->CheckFormatSupport(renderTargetFormat, &formatSupport);
shannon.woods@transgaming.comdf2fd572013-02-28 23:05:40 +0000421
daniel@transgaming.com65e65372012-11-28 19:33:50 +0000422 if (SUCCEEDED(result) && (formatSupport & D3D11_FORMAT_SUPPORT_RENDER_TARGET))
423 {
424 DXGI_FORMAT depthStencilFormat = DepthStencilFormats[depthStencilIndex];
425
shannon.woods@transgaming.comeec5c632013-02-28 23:04:21 +0000426 bool depthStencilFormatOK = true;
daniel@transgaming.com65e65372012-11-28 19:33:50 +0000427
shannon.woods@transgaming.comeec5c632013-02-28 23:04:21 +0000428 if (depthStencilFormat != DXGI_FORMAT_UNKNOWN)
429 {
430 UINT formatSupport = 0;
431 result = mDevice->CheckFormatSupport(depthStencilFormat, &formatSupport);
432 depthStencilFormatOK = SUCCEEDED(result) && (formatSupport & D3D11_FORMAT_SUPPORT_DEPTH_STENCIL);
433 }
434
435 if (depthStencilFormatOK)
daniel@transgaming.com65e65372012-11-28 19:33:50 +0000436 {
437 ConfigDesc newConfig;
shannonwoods@chromium.org755012f2013-05-30 00:09:32 +0000438 newConfig.renderTargetFormat = d3d11_gl::GetInternalFormat(renderTargetFormat);
439 newConfig.depthStencilFormat = d3d11_gl::GetInternalFormat(depthStencilFormat);
daniel@transgaming.com65e65372012-11-28 19:33:50 +0000440 newConfig.multiSample = 0; // FIXME: enumerate multi-sampling
441 newConfig.fastConfig = true; // Assume all DX11 format conversions to be fast
shannon.woods%transgaming.com@gtempaccount.comdcf33d52013-04-13 03:33:11 +0000442 newConfig.es3Capable = true;
daniel@transgaming.com65e65372012-11-28 19:33:50 +0000443
444 (*configDescList)[numConfigs++] = newConfig;
445 }
446 }
447 }
448 }
449
450 return numConfigs;
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000451}
452
453void Renderer11::deleteConfigs(ConfigDesc *configDescList)
454{
455 delete [] (configDescList);
456}
457
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000458void Renderer11::sync(bool block)
459{
daniel@transgaming.combdf787f2013-02-01 03:20:36 +0000460 if (block)
461 {
462 HRESULT result;
463
464 if (!mSyncQuery)
465 {
466 D3D11_QUERY_DESC queryDesc;
467 queryDesc.Query = D3D11_QUERY_EVENT;
468 queryDesc.MiscFlags = 0;
469
470 result = mDevice->CreateQuery(&queryDesc, &mSyncQuery);
471 ASSERT(SUCCEEDED(result));
472 }
473
474 mDeviceContext->End(mSyncQuery);
475 mDeviceContext->Flush();
476
477 do
478 {
479 result = mDeviceContext->GetData(mSyncQuery, NULL, 0, D3D11_ASYNC_GETDATA_DONOTFLUSH);
480
481 // Keep polling, but allow other threads to do something useful first
482 Sleep(0);
483
484 if (testDeviceLost(true))
485 {
486 return;
487 }
488 }
489 while (result == S_FALSE);
490 }
491 else
492 {
493 mDeviceContext->Flush();
494 }
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000495}
496
daniel@transgaming.comb9bb2792012-11-28 19:36:49 +0000497SwapChain *Renderer11::createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat)
498{
daniel@transgaming.coma60160b2012-11-28 19:41:15 +0000499 return new rx::SwapChain11(this, window, shareHandle, backBufferFormat, depthBufferFormat);
daniel@transgaming.comb9bb2792012-11-28 19:36:49 +0000500}
501
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000502void Renderer11::setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &samplerState)
503{
daniel@transgaming.com54de24f2013-01-11 04:07:59 +0000504 if (type == gl::SAMPLER_PIXEL)
505 {
506 if (index < 0 || index >= gl::MAX_TEXTURE_IMAGE_UNITS)
507 {
508 ERR("Pixel shader sampler index %i is not valid.", index);
509 return;
510 }
511
512 if (mForceSetPixelSamplerStates[index] || memcmp(&samplerState, &mCurPixelSamplerStates[index], sizeof(gl::SamplerState)) != 0)
513 {
514 ID3D11SamplerState *dxSamplerState = mStateCache.getSamplerState(samplerState);
515
516 if (!dxSamplerState)
517 {
518 ERR("NULL sampler state returned by RenderStateCache::getSamplerState, setting the default"
519 "sampler state for pixel shaders at slot %i.", index);
520 }
521
522 mDeviceContext->PSSetSamplers(index, 1, &dxSamplerState);
523
daniel@transgaming.com54de24f2013-01-11 04:07:59 +0000524 mCurPixelSamplerStates[index] = samplerState;
525 }
526
527 mForceSetPixelSamplerStates[index] = false;
528 }
529 else if (type == gl::SAMPLER_VERTEX)
530 {
shannon.woods@transgaming.com233fe952013-01-25 21:51:57 +0000531 if (index < 0 || index >= (int)getMaxVertexTextureImageUnits())
daniel@transgaming.com54de24f2013-01-11 04:07:59 +0000532 {
533 ERR("Vertex shader sampler index %i is not valid.", index);
534 return;
535 }
536
537 if (mForceSetVertexSamplerStates[index] || memcmp(&samplerState, &mCurVertexSamplerStates[index], sizeof(gl::SamplerState)) != 0)
538 {
539 ID3D11SamplerState *dxSamplerState = mStateCache.getSamplerState(samplerState);
540
541 if (!dxSamplerState)
542 {
543 ERR("NULL sampler state returned by RenderStateCache::getSamplerState, setting the default"
544 "sampler state for vertex shaders at slot %i.", index);
545 }
546
547 mDeviceContext->VSSetSamplers(index, 1, &dxSamplerState);
548
daniel@transgaming.com54de24f2013-01-11 04:07:59 +0000549 mCurVertexSamplerStates[index] = samplerState;
550 }
551
552 mForceSetVertexSamplerStates[index] = false;
553 }
554 else UNREACHABLE();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000555}
556
557void Renderer11::setTexture(gl::SamplerType type, int index, gl::Texture *texture)
558{
daniel@transgaming.com0785fad2013-01-11 04:08:10 +0000559 ID3D11ShaderResourceView *textureSRV = NULL;
daniel@transgaming.come33c8bf2013-01-11 04:11:33 +0000560 unsigned int serial = 0;
561 bool forceSetTexture = false;
daniel@transgaming.com0785fad2013-01-11 04:08:10 +0000562
563 if (texture)
564 {
565 TextureStorageInterface *texStorage = texture->getNativeTexture();
566 if (texStorage)
567 {
568 TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(texStorage->getStorageInstance());
569 textureSRV = storage11->getSRV();
570 }
571
572 // If we get NULL back from getSRV here, something went wrong in the texture class and we're unexpectedly
573 // missing the shader resource view
574 ASSERT(textureSRV != NULL);
daniel@transgaming.come33c8bf2013-01-11 04:11:33 +0000575
576 serial = texture->getTextureSerial();
577 forceSetTexture = texture->hasDirtyImages();
daniel@transgaming.com0785fad2013-01-11 04:08:10 +0000578 }
579
580 if (type == gl::SAMPLER_PIXEL)
581 {
582 if (index < 0 || index >= gl::MAX_TEXTURE_IMAGE_UNITS)
583 {
584 ERR("Pixel shader sampler index %i is not valid.", index);
585 return;
586 }
587
daniel@transgaming.come33c8bf2013-01-11 04:11:33 +0000588 if (forceSetTexture || mCurPixelTextureSerials[index] != serial)
589 {
590 mDeviceContext->PSSetShaderResources(index, 1, &textureSRV);
591 }
592
593 mCurPixelTextureSerials[index] = serial;
daniel@transgaming.com0785fad2013-01-11 04:08:10 +0000594 }
595 else if (type == gl::SAMPLER_VERTEX)
596 {
shannon.woods@transgaming.com233fe952013-01-25 21:51:57 +0000597 if (index < 0 || index >= (int)getMaxVertexTextureImageUnits())
daniel@transgaming.com0785fad2013-01-11 04:08:10 +0000598 {
599 ERR("Vertex shader sampler index %i is not valid.", index);
600 return;
601 }
602
daniel@transgaming.come33c8bf2013-01-11 04:11:33 +0000603 if (forceSetTexture || mCurVertexTextureSerials[index] != serial)
604 {
605 mDeviceContext->VSSetShaderResources(index, 1, &textureSRV);
606 }
607
608 mCurVertexTextureSerials[index] = serial;
daniel@transgaming.com0785fad2013-01-11 04:08:10 +0000609 }
610 else UNREACHABLE();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +0000611}
612
shannonwoods@chromium.org1bddfb92013-05-30 00:11:29 +0000613bool Renderer11::setUniformBuffers(const gl::Buffer *vertexUniformBuffers[], const gl::Buffer *fragmentUniformBuffers[])
614{
615 // convert buffers to ID3D11Buffer*
616 ID3D11Buffer *vertexConstantBuffers[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS] = { NULL };
617 ID3D11Buffer *pixelConstantBuffers[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS] = { NULL };
618
619 for (unsigned int uniformBufferIndex = 0; uniformBufferIndex < gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS; uniformBufferIndex++)
620 {
621 const gl::Buffer *uniformBuffer = vertexUniformBuffers[uniformBufferIndex];
622 if (uniformBuffer)
623 {
624 BufferStorage11 *bufferStorage = BufferStorage11::makeBufferStorage11(uniformBuffer->getStorage());
625 ID3D11Buffer *constantBuffer = bufferStorage->getBuffer(GL_UNIFORM_BUFFER);
626
627 if (!constantBuffer)
628 {
629 return false;
630 }
631
632 vertexConstantBuffers[uniformBufferIndex] = constantBuffer;
633 }
634 }
635
636 for (unsigned int uniformBufferIndex = 0; uniformBufferIndex < gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS; uniformBufferIndex++)
637 {
638 const gl::Buffer *uniformBuffer = fragmentUniformBuffers[uniformBufferIndex];
639 if (uniformBuffer)
640 {
641 BufferStorage11 *bufferStorage = BufferStorage11::makeBufferStorage11(uniformBuffer->getStorage());
642 ID3D11Buffer *constantBuffer = bufferStorage->getBuffer(GL_UNIFORM_BUFFER);
643
644 if (!constantBuffer)
645 {
646 return false;
647 }
648
649 pixelConstantBuffers[uniformBufferIndex] = constantBuffer;
650 }
651 }
652
653 mDeviceContext->VSSetConstantBuffers(getReservedVertexUniformBuffers(), getMaxVertexShaderUniformBuffers(), vertexConstantBuffers);
654 mDeviceContext->PSSetConstantBuffers(getReservedFragmentUniformBuffers(), getMaxFragmentShaderUniformBuffers(), pixelConstantBuffers);
655
656 return true;
657}
658
daniel@transgaming.com237bc7e2012-11-28 21:01:06 +0000659void Renderer11::setRasterizerState(const gl::RasterizerState &rasterState)
daniel@transgaming.com493d4f82012-11-28 19:35:45 +0000660{
daniel@transgaming.com237bc7e2012-11-28 21:01:06 +0000661 if (mForceSetRasterState || memcmp(&rasterState, &mCurRasterState, sizeof(gl::RasterizerState)) != 0)
daniel@transgaming.comdcf1e672012-11-28 19:38:19 +0000662 {
daniel@transgaming.comd55e8c12012-11-28 21:07:02 +0000663 ID3D11RasterizerState *dxRasterState = mStateCache.getRasterizerState(rasterState, mScissorEnabled,
664 mCurDepthSize);
daniel@transgaming.comdcf1e672012-11-28 19:38:19 +0000665 if (!dxRasterState)
666 {
daniel@transgaming.com0f9b3202013-01-11 04:08:05 +0000667 ERR("NULL rasterizer state returned by RenderStateCache::getRasterizerState, setting the default"
daniel@transgaming.comdcf1e672012-11-28 19:38:19 +0000668 "rasterizer state.");
669 }
670
671 mDeviceContext->RSSetState(dxRasterState);
672
daniel@transgaming.comdcf1e672012-11-28 19:38:19 +0000673 mCurRasterState = rasterState;
daniel@transgaming.comdcf1e672012-11-28 19:38:19 +0000674 }
675
676 mForceSetRasterState = false;
daniel@transgaming.com493d4f82012-11-28 19:35:45 +0000677}
678
Geoff Lang2a64ee42013-05-31 11:22:40 -0400679void Renderer11::setBlendState(const gl::BlendState &blendState, const gl::ColorF &blendColor,
daniel@transgaming.com493d4f82012-11-28 19:35:45 +0000680 unsigned int sampleMask)
681{
daniel@transgaming.comf8ba1092012-11-28 19:37:53 +0000682 if (mForceSetBlendState ||
683 memcmp(&blendState, &mCurBlendState, sizeof(gl::BlendState)) != 0 ||
Geoff Lang2a64ee42013-05-31 11:22:40 -0400684 memcmp(&blendColor, &mCurBlendColor, sizeof(gl::ColorF)) != 0 ||
daniel@transgaming.comf8ba1092012-11-28 19:37:53 +0000685 sampleMask != mCurSampleMask)
686 {
687 ID3D11BlendState *dxBlendState = mStateCache.getBlendState(blendState);
688 if (!dxBlendState)
689 {
690 ERR("NULL blend state returned by RenderStateCache::getBlendState, setting the default "
691 "blend state.");
692 }
693
shannonwoods@chromium.org568c82e2013-05-30 00:13:15 +0000694 float blendColors[4] = {0.0f};
695 if (blendState.sourceBlendRGB != GL_CONSTANT_ALPHA && blendState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA &&
696 blendState.destBlendRGB != GL_CONSTANT_ALPHA && blendState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA)
697 {
698 blendColors[0] = blendColor.red;
699 blendColors[1] = blendColor.green;
700 blendColors[2] = blendColor.blue;
701 blendColors[3] = blendColor.alpha;
702 }
703 else
704 {
705 blendColors[0] = blendColor.alpha;
706 blendColors[1] = blendColor.alpha;
707 blendColors[2] = blendColor.alpha;
708 blendColors[3] = blendColor.alpha;
709 }
710
daniel@transgaming.comf8ba1092012-11-28 19:37:53 +0000711 mDeviceContext->OMSetBlendState(dxBlendState, blendColors, sampleMask);
712
daniel@transgaming.comf8ba1092012-11-28 19:37:53 +0000713 mCurBlendState = blendState;
714 mCurBlendColor = blendColor;
715 mCurSampleMask = sampleMask;
716 }
717
718 mForceSetBlendState = false;
daniel@transgaming.com493d4f82012-11-28 19:35:45 +0000719}
720
daniel@transgaming.com08c331d2012-11-28 19:38:39 +0000721void Renderer11::setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef,
daniel@transgaming.com3a0ef482012-11-28 21:01:20 +0000722 int stencilBackRef, bool frontFaceCCW)
daniel@transgaming.com493d4f82012-11-28 19:35:45 +0000723{
daniel@transgaming.com5503fd02012-11-28 19:38:57 +0000724 if (mForceSetDepthStencilState ||
725 memcmp(&depthStencilState, &mCurDepthStencilState, sizeof(gl::DepthStencilState)) != 0 ||
726 stencilRef != mCurStencilRef || stencilBackRef != mCurStencilBackRef)
727 {
728 if (depthStencilState.stencilWritemask != depthStencilState.stencilBackWritemask ||
729 stencilRef != stencilBackRef ||
730 depthStencilState.stencilMask != depthStencilState.stencilBackMask)
731 {
732 ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are "
733 "invalid under WebGL.");
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000734 return gl::error(GL_INVALID_OPERATION);
daniel@transgaming.com5503fd02012-11-28 19:38:57 +0000735 }
736
737 ID3D11DepthStencilState *dxDepthStencilState = mStateCache.getDepthStencilState(depthStencilState);
738 if (!dxDepthStencilState)
739 {
740 ERR("NULL depth stencil state returned by RenderStateCache::getDepthStencilState, "
741 "setting the default depth stencil state.");
742 }
743
744 mDeviceContext->OMSetDepthStencilState(dxDepthStencilState, static_cast<UINT>(stencilRef));
745
daniel@transgaming.com5503fd02012-11-28 19:38:57 +0000746 mCurDepthStencilState = depthStencilState;
747 mCurStencilRef = stencilRef;
748 mCurStencilBackRef = stencilBackRef;
749 }
750
751 mForceSetDepthStencilState = false;
daniel@transgaming.com493d4f82012-11-28 19:35:45 +0000752}
753
daniel@transgaming.comd55e8c12012-11-28 21:07:02 +0000754void Renderer11::setScissorRectangle(const gl::Rectangle &scissor, bool enabled)
daniel@transgaming.com493d4f82012-11-28 19:35:45 +0000755{
daniel@transgaming.comd55e8c12012-11-28 21:07:02 +0000756 if (mForceSetScissor || memcmp(&scissor, &mCurScissor, sizeof(gl::Rectangle)) != 0 ||
757 enabled != mScissorEnabled)
daniel@transgaming.comdcf1e672012-11-28 19:38:19 +0000758 {
daniel@transgaming.comd55e8c12012-11-28 21:07:02 +0000759 if (enabled)
760 {
761 D3D11_RECT rect;
shannon.woods@transgaming.com8ce2f8f2013-02-28 23:07:10 +0000762 rect.left = std::max(0, scissor.x);
763 rect.top = std::max(0, scissor.y);
764 rect.right = scissor.x + std::max(0, scissor.width);
765 rect.bottom = scissor.y + std::max(0, scissor.height);
daniel@transgaming.comdcf1e672012-11-28 19:38:19 +0000766
daniel@transgaming.comd55e8c12012-11-28 21:07:02 +0000767 mDeviceContext->RSSetScissorRects(1, &rect);
768 }
769
770 if (enabled != mScissorEnabled)
771 {
772 mForceSetRasterState = true;
773 }
daniel@transgaming.comdcf1e672012-11-28 19:38:19 +0000774
775 mCurScissor = scissor;
daniel@transgaming.comd55e8c12012-11-28 21:07:02 +0000776 mScissorEnabled = enabled;
daniel@transgaming.comdcf1e672012-11-28 19:38:19 +0000777 }
778
779 mForceSetScissor = false;
daniel@transgaming.com493d4f82012-11-28 19:35:45 +0000780}
781
daniel@transgaming.com12985182012-12-20 20:56:31 +0000782bool Renderer11::setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace,
shannon.woods@transgaming.com0b236e22013-01-25 21:57:07 +0000783 bool ignoreViewport)
daniel@transgaming.com83e80ee2012-11-28 19:40:53 +0000784{
daniel@transgaming.com4c4ce232012-11-28 21:01:40 +0000785 gl::Rectangle actualViewport = viewport;
786 float actualZNear = gl::clamp01(zNear);
787 float actualZFar = gl::clamp01(zFar);
788 if (ignoreViewport)
789 {
790 actualViewport.x = 0;
791 actualViewport.y = 0;
792 actualViewport.width = mRenderTargetDesc.width;
793 actualViewport.height = mRenderTargetDesc.height;
794 actualZNear = 0.0f;
795 actualZFar = 1.0f;
796 }
daniel@transgaming.com53670042012-11-28 20:55:51 +0000797
shannon.woods@transgaming.com8ce2f8f2013-02-28 23:07:10 +0000798 // Get D3D viewport bounds, which depends on the feature level
799 const Range& viewportBounds = getViewportBounds();
800
801 // Clamp width and height first to the gl maximum, then clamp further if we extend past the D3D maximum bounds
daniel@transgaming.com53670042012-11-28 20:55:51 +0000802 D3D11_VIEWPORT dxViewport;
shannon.woods@transgaming.com8ce2f8f2013-02-28 23:07:10 +0000803 dxViewport.TopLeftX = gl::clamp(actualViewport.x, viewportBounds.start, viewportBounds.end);
804 dxViewport.TopLeftY = gl::clamp(actualViewport.y, viewportBounds.start, viewportBounds.end);
805 dxViewport.Width = gl::clamp(actualViewport.width, 0, getMaxViewportDimension());
806 dxViewport.Height = gl::clamp(actualViewport.height, 0, getMaxViewportDimension());
807 dxViewport.Width = std::min((int)dxViewport.Width, viewportBounds.end - static_cast<int>(dxViewport.TopLeftX));
808 dxViewport.Height = std::min((int)dxViewport.Height, viewportBounds.end - static_cast<int>(dxViewport.TopLeftY));
daniel@transgaming.com4c4ce232012-11-28 21:01:40 +0000809 dxViewport.MinDepth = actualZNear;
810 dxViewport.MaxDepth = actualZFar;
daniel@transgaming.com53670042012-11-28 20:55:51 +0000811
812 if (dxViewport.Width <= 0 || dxViewport.Height <= 0)
813 {
814 return false; // Nothing to render
815 }
816
daniel@transgaming.comed36abd2013-01-11 21:15:58 +0000817 bool viewportChanged = mForceSetViewport || memcmp(&actualViewport, &mCurViewport, sizeof(gl::Rectangle)) != 0 ||
818 actualZNear != mCurNear || actualZFar != mCurFar;
daniel@transgaming.com4c4ce232012-11-28 21:01:40 +0000819
daniel@transgaming.com53670042012-11-28 20:55:51 +0000820 if (viewportChanged)
821 {
822 mDeviceContext->RSSetViewports(1, &dxViewport);
823
daniel@transgaming.com4c4ce232012-11-28 21:01:40 +0000824 mCurViewport = actualViewport;
825 mCurNear = actualZNear;
826 mCurFar = actualZFar;
daniel@transgaming.com53670042012-11-28 20:55:51 +0000827
shannon.woods@transgaming.coma14ecf32013-02-28 23:09:42 +0000828 mPixelConstants.viewCoords[0] = actualViewport.width * 0.5f;
829 mPixelConstants.viewCoords[1] = actualViewport.height * 0.5f;
830 mPixelConstants.viewCoords[2] = actualViewport.x + (actualViewport.width * 0.5f);
831 mPixelConstants.viewCoords[3] = actualViewport.y + (actualViewport.height * 0.5f);
daniel@transgaming.com53670042012-11-28 20:55:51 +0000832
shannon.woods@transgaming.com5fb979d2013-01-25 21:53:04 +0000833 mPixelConstants.depthFront[0] = (actualZFar - actualZNear) * 0.5f;
834 mPixelConstants.depthFront[1] = (actualZNear + actualZFar) * 0.5f;
daniel@transgaming.com53670042012-11-28 20:55:51 +0000835
shannon.woods@transgaming.com5fb979d2013-01-25 21:53:04 +0000836 mVertexConstants.depthRange[0] = actualZNear;
837 mVertexConstants.depthRange[1] = actualZFar;
838 mVertexConstants.depthRange[2] = actualZFar - actualZNear;
daniel@transgaming.comed36abd2013-01-11 21:15:58 +0000839
shannon.woods@transgaming.com5fb979d2013-01-25 21:53:04 +0000840 mPixelConstants.depthRange[0] = actualZNear;
841 mPixelConstants.depthRange[1] = actualZFar;
842 mPixelConstants.depthRange[2] = actualZFar - actualZNear;
daniel@transgaming.com53670042012-11-28 20:55:51 +0000843 }
844
845 mForceSetViewport = false;
daniel@transgaming.com83e80ee2012-11-28 19:40:53 +0000846 return true;
847}
848
daniel@transgaming.com91207b72012-11-28 20:56:43 +0000849bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count)
850{
daniel@transgaming.comc52be632012-11-28 21:04:28 +0000851 D3D11_PRIMITIVE_TOPOLOGY primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
daniel@transgaming.com91207b72012-11-28 20:56:43 +0000852
daniel@transgaming.com0b03b062012-11-28 21:03:49 +0000853 switch (mode)
854 {
daniel@transgaming.comc52be632012-11-28 21:04:28 +0000855 case GL_POINTS: primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST; break;
856 case GL_LINES: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINELIST; break;
daniel@transgaming.com1ef09672013-01-11 04:10:37 +0000857 case GL_LINE_LOOP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; break;
daniel@transgaming.comc52be632012-11-28 21:04:28 +0000858 case GL_LINE_STRIP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; break;
859 case GL_TRIANGLES: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; break;
860 case GL_TRIANGLE_STRIP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; break;
daniel@transgaming.com4fd1f982013-01-11 04:12:58 +0000861 // emulate fans via rewriting index buffer
862 case GL_TRIANGLE_FAN: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; break;
daniel@transgaming.com0b03b062012-11-28 21:03:49 +0000863 default:
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000864 return gl::error(GL_INVALID_ENUM, false);
daniel@transgaming.com0b03b062012-11-28 21:03:49 +0000865 }
866
daniel@transgaming.comc52be632012-11-28 21:04:28 +0000867 mDeviceContext->IASetPrimitiveTopology(primitiveTopology);
daniel@transgaming.com0b03b062012-11-28 21:03:49 +0000868
869 return count > 0;
daniel@transgaming.com91207b72012-11-28 20:56:43 +0000870}
871
872bool Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer)
daniel@transgaming.com493d4f82012-11-28 19:35:45 +0000873{
daniel@transgaming.com80fc3322012-11-28 21:02:13 +0000874 // Get the color render buffer and serial
shannon.woods%transgaming.com@gtempaccount.comf4fe7102013-04-13 03:30:26 +0000875 // Also extract the render target dimensions and view
876 unsigned int renderTargetWidth = 0;
877 unsigned int renderTargetHeight = 0;
878 GLenum renderTargetFormat = 0;
879 unsigned int renderTargetSerials[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {0};
880 ID3D11RenderTargetView* framebufferRTVs[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {NULL};
881 bool missingColorRenderTarget = true;
882
883 for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
daniel@transgaming.com80fc3322012-11-28 21:02:13 +0000884 {
shannon.woods%transgaming.com@gtempaccount.com4059a382013-04-13 03:31:16 +0000885 const GLenum drawBufferState = framebuffer->getDrawBufferState(colorAttachment);
886
887 if (framebuffer->getColorbufferType(colorAttachment) != GL_NONE && drawBufferState != GL_NONE)
daniel@transgaming.com80fc3322012-11-28 21:02:13 +0000888 {
shannon.woods%transgaming.com@gtempaccount.com4059a382013-04-13 03:31:16 +0000889 // the draw buffer must be either "none", "back" for the default buffer or the same index as this color (in order)
890 ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + colorAttachment));
891
shannon.woods%transgaming.com@gtempaccount.comf4fe7102013-04-13 03:30:26 +0000892 gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer(colorAttachment);
daniel@transgaming.com80fc3322012-11-28 21:02:13 +0000893
shannon.woods%transgaming.com@gtempaccount.comf4fe7102013-04-13 03:30:26 +0000894 if (!colorbuffer)
895 {
896 ERR("render target pointer unexpectedly null.");
897 return false;
898 }
shannon.woods@transgaming.com3e3da582013-02-28 23:09:03 +0000899
shannon.woods%transgaming.com@gtempaccount.comf4fe7102013-04-13 03:30:26 +0000900 // check for zero-sized default framebuffer, which is a special case.
901 // in this case we do not wish to modify any state and just silently return false.
902 // this will not report any gl error but will cause the calling method to return.
903 if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0)
904 {
905 return false;
906 }
907
908 renderTargetSerials[colorAttachment] = colorbuffer->getSerial();
909
910 // Extract the render target dimensions and view
911 RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget());
912 if (!renderTarget)
913 {
914 ERR("render target pointer unexpectedly null.");
915 return false;
916 }
917
918 framebufferRTVs[colorAttachment] = renderTarget->getRenderTargetView();
919 if (!framebufferRTVs[colorAttachment])
920 {
921 ERR("render target view pointer unexpectedly null.");
922 return false;
923 }
924
925 if (missingColorRenderTarget)
926 {
927 renderTargetWidth = colorbuffer->getWidth();
928 renderTargetHeight = colorbuffer->getHeight();
929 renderTargetFormat = colorbuffer->getActualFormat();
930 missingColorRenderTarget = false;
931 }
932 }
daniel@transgaming.com80fc3322012-11-28 21:02:13 +0000933 }
934
935 // Get the depth stencil render buffer and serials
936 gl::Renderbuffer *depthStencil = NULL;
937 unsigned int depthbufferSerial = 0;
938 unsigned int stencilbufferSerial = 0;
939 if (framebuffer->getDepthbufferType() != GL_NONE)
940 {
941 depthStencil = framebuffer->getDepthbuffer();
942 if (!depthStencil)
943 {
944 ERR("Depth stencil pointer unexpectedly null.");
shannon.woods%transgaming.com@gtempaccount.comf4fe7102013-04-13 03:30:26 +0000945 SafeRelease(framebufferRTVs);
daniel@transgaming.com80fc3322012-11-28 21:02:13 +0000946 return false;
947 }
948
949 depthbufferSerial = depthStencil->getSerial();
950 }
951 else if (framebuffer->getStencilbufferType() != GL_NONE)
952 {
953 depthStencil = framebuffer->getStencilbuffer();
954 if (!depthStencil)
955 {
956 ERR("Depth stencil pointer unexpectedly null.");
shannon.woods%transgaming.com@gtempaccount.comf4fe7102013-04-13 03:30:26 +0000957 SafeRelease(framebufferRTVs);
daniel@transgaming.com80fc3322012-11-28 21:02:13 +0000958 return false;
959 }
960
961 stencilbufferSerial = depthStencil->getSerial();
962 }
963
daniel@transgaming.com80fc3322012-11-28 21:02:13 +0000964 // Extract the depth stencil sizes and view
965 unsigned int depthSize = 0;
966 unsigned int stencilSize = 0;
967 ID3D11DepthStencilView* framebufferDSV = NULL;
968 if (depthStencil)
969 {
970 RenderTarget11 *depthStencilRenderTarget = RenderTarget11::makeRenderTarget11(depthStencil->getDepthStencil());
971 if (!depthStencilRenderTarget)
972 {
973 ERR("render target pointer unexpectedly null.");
shannon.woods%transgaming.com@gtempaccount.comf4fe7102013-04-13 03:30:26 +0000974 SafeRelease(framebufferRTVs);
daniel@transgaming.com80fc3322012-11-28 21:02:13 +0000975 return false;
976 }
977
978 framebufferDSV = depthStencilRenderTarget->getDepthStencilView();
979 if (!framebufferDSV)
980 {
981 ERR("depth stencil view pointer unexpectedly null.");
shannon.woods%transgaming.com@gtempaccount.comf4fe7102013-04-13 03:30:26 +0000982 SafeRelease(framebufferRTVs);
daniel@transgaming.com80fc3322012-11-28 21:02:13 +0000983 return false;
984 }
985
986 // If there is no render buffer, the width, height and format values come from
987 // the depth stencil
shannon.woods%transgaming.com@gtempaccount.comf4fe7102013-04-13 03:30:26 +0000988 if (missingColorRenderTarget)
daniel@transgaming.com80fc3322012-11-28 21:02:13 +0000989 {
990 renderTargetWidth = depthStencil->getWidth();
991 renderTargetHeight = depthStencil->getHeight();
992 renderTargetFormat = depthStencil->getActualFormat();
993 }
994
995 depthSize = depthStencil->getDepthSize();
996 stencilSize = depthStencil->getStencilSize();
997 }
998
999 // Apply the render target and depth stencil
1000 if (!mRenderTargetDescInitialized || !mDepthStencilInitialized ||
shannon.woods%transgaming.com@gtempaccount.comf4fe7102013-04-13 03:30:26 +00001001 memcmp(renderTargetSerials, mAppliedRenderTargetSerials, sizeof(renderTargetSerials)) != 0 ||
daniel@transgaming.com80fc3322012-11-28 21:02:13 +00001002 depthbufferSerial != mAppliedDepthbufferSerial ||
1003 stencilbufferSerial != mAppliedStencilbufferSerial)
1004 {
shannon.woods%transgaming.com@gtempaccount.comf4fe7102013-04-13 03:30:26 +00001005 mDeviceContext->OMSetRenderTargets(getMaxRenderTargets(), framebufferRTVs, framebufferDSV);
daniel@transgaming.com80fc3322012-11-28 21:02:13 +00001006
1007 mRenderTargetDesc.width = renderTargetWidth;
1008 mRenderTargetDesc.height = renderTargetHeight;
1009 mRenderTargetDesc.format = renderTargetFormat;
shannon.woods@transgaming.com8ce2f8f2013-02-28 23:07:10 +00001010 mForceSetViewport = true;
1011 mForceSetScissor = true;
daniel@transgaming.com80fc3322012-11-28 21:02:13 +00001012
1013 if (!mDepthStencilInitialized || depthSize != mCurDepthSize)
1014 {
1015 mCurDepthSize = depthSize;
1016 mForceSetRasterState = true;
1017 }
1018
1019 mCurStencilSize = stencilSize;
1020
shannon.woods%transgaming.com@gtempaccount.comf4fe7102013-04-13 03:30:26 +00001021 for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++)
1022 {
1023 mAppliedRenderTargetSerials[rtIndex] = renderTargetSerials[rtIndex];
1024 }
daniel@transgaming.com80fc3322012-11-28 21:02:13 +00001025 mAppliedDepthbufferSerial = depthbufferSerial;
1026 mAppliedStencilbufferSerial = stencilbufferSerial;
1027 mRenderTargetDescInitialized = true;
1028 mDepthStencilInitialized = true;
1029 }
1030
shannon.woods%transgaming.com@gtempaccount.comf4fe7102013-04-13 03:30:26 +00001031 SafeRelease(framebufferRTVs);
1032 SafeRelease(framebufferDSV);
daniel@transgaming.comae39ee22012-11-28 19:42:02 +00001033
1034 return true;
daniel@transgaming.com493d4f82012-11-28 19:35:45 +00001035}
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001036
daniel@transgaming.com91207b72012-11-28 20:56:43 +00001037GLenum Renderer11::applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances)
daniel@transgaming.comdef9f0f2012-11-28 20:53:20 +00001038{
daniel@transgaming.comc5431eb2012-12-20 21:10:15 +00001039 TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS];
1040 GLenum err = mVertexDataManager->prepareVertexData(vertexAttributes, programBinary, first, count, attributes, instances);
1041 if (err != GL_NO_ERROR)
daniel@transgaming.comda495a12012-11-28 21:03:56 +00001042 {
daniel@transgaming.comc5431eb2012-12-20 21:10:15 +00001043 return err;
1044 }
daniel@transgaming.comda495a12012-11-28 21:03:56 +00001045
daniel@transgaming.comc5431eb2012-12-20 21:10:15 +00001046 return mInputLayoutCache.applyVertexBuffers(attributes, programBinary);
daniel@transgaming.comdef9f0f2012-11-28 20:53:20 +00001047}
1048
daniel@transgaming.com31240482012-11-28 21:06:41 +00001049GLenum Renderer11::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo)
daniel@transgaming.com91207b72012-11-28 20:56:43 +00001050{
daniel@transgaming.comc5431eb2012-12-20 21:10:15 +00001051 GLenum err = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo);
daniel@transgaming.com91207b72012-11-28 20:56:43 +00001052
daniel@transgaming.comc5431eb2012-12-20 21:10:15 +00001053 if (err == GL_NO_ERROR)
1054 {
shannon.woods@transgaming.coma1229a32013-02-28 23:08:40 +00001055 if (indexInfo->storage)
1056 {
1057 if (indexInfo->serial != mAppliedStorageIBSerial || indexInfo->startOffset != mAppliedIBOffset)
1058 {
1059 BufferStorage11 *storage = BufferStorage11::makeBufferStorage11(indexInfo->storage);
1060 IndexBuffer11* indexBuffer = IndexBuffer11::makeIndexBuffer11(indexInfo->indexBuffer);
1061
shannonwoods@chromium.org675526e2013-05-30 00:04:49 +00001062 mDeviceContext->IASetIndexBuffer(storage->getBuffer(GL_ELEMENT_ARRAY_BUFFER), indexBuffer->getIndexFormat(), indexInfo->startOffset);
shannon.woods@transgaming.coma1229a32013-02-28 23:08:40 +00001063
1064 mAppliedIBSerial = 0;
1065 mAppliedStorageIBSerial = storage->getSerial();
1066 mAppliedIBOffset = indexInfo->startOffset;
1067 }
1068 }
1069 else if (indexInfo->serial != mAppliedIBSerial || indexInfo->startOffset != mAppliedIBOffset)
daniel@transgaming.comc5431eb2012-12-20 21:10:15 +00001070 {
1071 IndexBuffer11* indexBuffer = IndexBuffer11::makeIndexBuffer11(indexInfo->indexBuffer);
1072
daniel@transgaming.com22ada2c2013-01-11 04:07:12 +00001073 mDeviceContext->IASetIndexBuffer(indexBuffer->getBuffer(), indexBuffer->getIndexFormat(), indexInfo->startOffset);
shannon.woods@transgaming.coma1229a32013-02-28 23:08:40 +00001074
daniel@transgaming.comc5431eb2012-12-20 21:10:15 +00001075 mAppliedIBSerial = indexInfo->serial;
shannon.woods@transgaming.coma1229a32013-02-28 23:08:40 +00001076 mAppliedStorageIBSerial = 0;
daniel@transgaming.com7fbf4862013-01-11 04:09:22 +00001077 mAppliedIBOffset = indexInfo->startOffset;
daniel@transgaming.comc5431eb2012-12-20 21:10:15 +00001078 }
1079 }
1080
1081 return err;
daniel@transgaming.com91207b72012-11-28 20:56:43 +00001082}
1083
1084void Renderer11::drawArrays(GLenum mode, GLsizei count, GLsizei instances)
1085{
daniel@transgaming.com1ef09672013-01-11 04:10:37 +00001086 if (mode == GL_LINE_LOOP)
1087 {
1088 drawLineLoop(count, GL_NONE, NULL, 0, NULL);
1089 }
daniel@transgaming.com4fd1f982013-01-11 04:12:58 +00001090 else if (mode == GL_TRIANGLE_FAN)
1091 {
shannon.woods@transgaming.com00032cb2013-01-25 21:56:30 +00001092 drawTriangleFan(count, GL_NONE, NULL, 0, NULL, instances);
daniel@transgaming.com4fd1f982013-01-11 04:12:58 +00001093 }
daniel@transgaming.com1ef09672013-01-11 04:10:37 +00001094 else if (instances > 0)
1095 {
shannon.woods@transgaming.com00032cb2013-01-25 21:56:30 +00001096 mDeviceContext->DrawInstanced(count, instances, 0, 0);
daniel@transgaming.com1ef09672013-01-11 04:10:37 +00001097 }
1098 else
1099 {
1100 mDeviceContext->Draw(count, 0);
1101 }
daniel@transgaming.com91207b72012-11-28 20:56:43 +00001102}
1103
shannon.woods@transgaming.com00032cb2013-01-25 21:56:30 +00001104void Renderer11::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances)
daniel@transgaming.com91207b72012-11-28 20:56:43 +00001105{
daniel@transgaming.comc5114302012-12-20 21:11:36 +00001106 if (mode == GL_LINE_LOOP)
1107 {
1108 drawLineLoop(count, type, indices, indexInfo.minIndex, elementArrayBuffer);
1109 }
daniel@transgaming.com4fd1f982013-01-11 04:12:58 +00001110 else if (mode == GL_TRIANGLE_FAN)
1111 {
shannon.woods@transgaming.com00032cb2013-01-25 21:56:30 +00001112 drawTriangleFan(count, type, indices, indexInfo.minIndex, elementArrayBuffer, instances);
1113 }
1114 else if (instances > 0)
1115 {
1116 mDeviceContext->DrawIndexedInstanced(count, instances, 0, -static_cast<int>(indexInfo.minIndex), 0);
daniel@transgaming.com4fd1f982013-01-11 04:12:58 +00001117 }
daniel@transgaming.comc5114302012-12-20 21:11:36 +00001118 else
1119 {
daniel@transgaming.com9f7ede62013-01-11 04:07:06 +00001120 mDeviceContext->DrawIndexed(count, 0, -static_cast<int>(indexInfo.minIndex));
daniel@transgaming.comc5114302012-12-20 21:11:36 +00001121 }
1122}
1123
1124void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer)
1125{
1126 // Get the raw indices for an indexed draw
1127 if (type != GL_NONE && elementArrayBuffer)
1128 {
1129 gl::Buffer *indexBuffer = elementArrayBuffer;
shannon.woods@transgaming.com76655412013-02-28 23:08:09 +00001130 BufferStorage *storage = indexBuffer->getStorage();
daniel@transgaming.comc5114302012-12-20 21:11:36 +00001131 intptr_t offset = reinterpret_cast<intptr_t>(indices);
shannon.woods@transgaming.com76655412013-02-28 23:08:09 +00001132 indices = static_cast<const GLubyte*>(storage->getData()) + offset;
daniel@transgaming.comc5114302012-12-20 21:11:36 +00001133 }
1134
1135 if (!mLineLoopIB)
1136 {
1137 mLineLoopIB = new StreamingIndexBufferInterface(this);
1138 if (!mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT))
1139 {
1140 delete mLineLoopIB;
1141 mLineLoopIB = NULL;
1142
1143 ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP.");
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +00001144 return gl::error(GL_OUT_OF_MEMORY);
daniel@transgaming.comc5114302012-12-20 21:11:36 +00001145 }
1146 }
1147
1148 const int spaceNeeded = (count + 1) * sizeof(unsigned int);
1149 if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT))
1150 {
1151 ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP.");
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +00001152 return gl::error(GL_OUT_OF_MEMORY);
daniel@transgaming.comc5114302012-12-20 21:11:36 +00001153 }
1154
1155 void* mappedMemory = NULL;
1156 int offset = mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory);
1157 if (offset == -1 || mappedMemory == NULL)
1158 {
1159 ERR("Could not map index buffer for GL_LINE_LOOP.");
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +00001160 return gl::error(GL_OUT_OF_MEMORY);
daniel@transgaming.comc5114302012-12-20 21:11:36 +00001161 }
1162
daniel@transgaming.comc5114302012-12-20 21:11:36 +00001163 unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory);
daniel@transgaming.com7fbf4862013-01-11 04:09:22 +00001164 unsigned int indexBufferOffset = static_cast<unsigned int>(offset);
daniel@transgaming.comc5114302012-12-20 21:11:36 +00001165
1166 switch (type)
1167 {
1168 case GL_NONE: // Non-indexed draw
1169 for (int i = 0; i < count; i++)
1170 {
1171 data[i] = i;
1172 }
1173 data[count] = 0;
1174 break;
1175 case GL_UNSIGNED_BYTE:
1176 for (int i = 0; i < count; i++)
1177 {
1178 data[i] = static_cast<const GLubyte*>(indices)[i];
1179 }
1180 data[count] = static_cast<const GLubyte*>(indices)[0];
1181 break;
1182 case GL_UNSIGNED_SHORT:
1183 for (int i = 0; i < count; i++)
1184 {
1185 data[i] = static_cast<const GLushort*>(indices)[i];
1186 }
1187 data[count] = static_cast<const GLushort*>(indices)[0];
1188 break;
1189 case GL_UNSIGNED_INT:
1190 for (int i = 0; i < count; i++)
1191 {
1192 data[i] = static_cast<const GLuint*>(indices)[i];
1193 }
1194 data[count] = static_cast<const GLuint*>(indices)[0];
1195 break;
1196 default: UNREACHABLE();
1197 }
1198
1199 if (!mLineLoopIB->unmapBuffer())
1200 {
1201 ERR("Could not unmap index buffer for GL_LINE_LOOP.");
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +00001202 return gl::error(GL_OUT_OF_MEMORY);
daniel@transgaming.comc5114302012-12-20 21:11:36 +00001203 }
1204
daniel@transgaming.com7fbf4862013-01-11 04:09:22 +00001205 if (mAppliedIBSerial != mLineLoopIB->getSerial() || mAppliedIBOffset != indexBufferOffset)
daniel@transgaming.comc5114302012-12-20 21:11:36 +00001206 {
1207 IndexBuffer11 *indexBuffer = IndexBuffer11::makeIndexBuffer11(mLineLoopIB->getIndexBuffer());
1208
daniel@transgaming.com7fbf4862013-01-11 04:09:22 +00001209 mDeviceContext->IASetIndexBuffer(indexBuffer->getBuffer(), indexBuffer->getIndexFormat(), indexBufferOffset);
daniel@transgaming.comc5114302012-12-20 21:11:36 +00001210 mAppliedIBSerial = mLineLoopIB->getSerial();
shannon.woods@transgaming.coma1229a32013-02-28 23:08:40 +00001211 mAppliedStorageIBSerial = 0;
daniel@transgaming.com7fbf4862013-01-11 04:09:22 +00001212 mAppliedIBOffset = indexBufferOffset;
daniel@transgaming.comc5114302012-12-20 21:11:36 +00001213 }
1214
daniel@transgaming.com1ef09672013-01-11 04:10:37 +00001215 mDeviceContext->DrawIndexed(count + 1, 0, -minIndex);
daniel@transgaming.com91207b72012-11-28 20:56:43 +00001216}
1217
shannon.woods@transgaming.com00032cb2013-01-25 21:56:30 +00001218void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer, int instances)
daniel@transgaming.com4fd1f982013-01-11 04:12:58 +00001219{
1220 // Get the raw indices for an indexed draw
1221 if (type != GL_NONE && elementArrayBuffer)
1222 {
1223 gl::Buffer *indexBuffer = elementArrayBuffer;
shannon.woods@transgaming.com76655412013-02-28 23:08:09 +00001224 BufferStorage *storage = indexBuffer->getStorage();
daniel@transgaming.com4fd1f982013-01-11 04:12:58 +00001225 intptr_t offset = reinterpret_cast<intptr_t>(indices);
shannon.woods@transgaming.com76655412013-02-28 23:08:09 +00001226 indices = static_cast<const GLubyte*>(storage->getData()) + offset;
daniel@transgaming.com4fd1f982013-01-11 04:12:58 +00001227 }
1228
1229 if (!mTriangleFanIB)
1230 {
1231 mTriangleFanIB = new StreamingIndexBufferInterface(this);
1232 if (!mTriangleFanIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT))
1233 {
1234 delete mTriangleFanIB;
1235 mTriangleFanIB = NULL;
1236
1237 ERR("Could not create a scratch index buffer for GL_TRIANGLE_FAN.");
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +00001238 return gl::error(GL_OUT_OF_MEMORY);
daniel@transgaming.com4fd1f982013-01-11 04:12:58 +00001239 }
1240 }
1241
1242 const int numTris = count - 2;
1243 const int spaceNeeded = (numTris * 3) * sizeof(unsigned int);
1244 if (!mTriangleFanIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT))
1245 {
1246 ERR("Could not reserve enough space in scratch index buffer for GL_TRIANGLE_FAN.");
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +00001247 return gl::error(GL_OUT_OF_MEMORY);
daniel@transgaming.com4fd1f982013-01-11 04:12:58 +00001248 }
1249
1250 void* mappedMemory = NULL;
1251 int offset = mTriangleFanIB->mapBuffer(spaceNeeded, &mappedMemory);
1252 if (offset == -1 || mappedMemory == NULL)
1253 {
1254 ERR("Could not map scratch index buffer for GL_TRIANGLE_FAN.");
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +00001255 return gl::error(GL_OUT_OF_MEMORY);
daniel@transgaming.com4fd1f982013-01-11 04:12:58 +00001256 }
1257
1258 unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory);
1259 unsigned int indexBufferOffset = static_cast<unsigned int>(offset);
1260
1261 switch (type)
1262 {
1263 case GL_NONE: // Non-indexed draw
1264 for (int i = 0; i < numTris; i++)
1265 {
1266 data[i*3 + 0] = 0;
1267 data[i*3 + 1] = i + 1;
1268 data[i*3 + 2] = i + 2;
1269 }
1270 break;
1271 case GL_UNSIGNED_BYTE:
1272 for (int i = 0; i < numTris; i++)
1273 {
1274 data[i*3 + 0] = static_cast<const GLubyte*>(indices)[0];
1275 data[i*3 + 1] = static_cast<const GLubyte*>(indices)[i + 1];
1276 data[i*3 + 2] = static_cast<const GLubyte*>(indices)[i + 2];
1277 }
1278 break;
1279 case GL_UNSIGNED_SHORT:
1280 for (int i = 0; i < numTris; i++)
1281 {
1282 data[i*3 + 0] = static_cast<const GLushort*>(indices)[0];
1283 data[i*3 + 1] = static_cast<const GLushort*>(indices)[i + 1];
1284 data[i*3 + 2] = static_cast<const GLushort*>(indices)[i + 2];
1285 }
1286 break;
1287 case GL_UNSIGNED_INT:
1288 for (int i = 0; i < numTris; i++)
1289 {
1290 data[i*3 + 0] = static_cast<const GLuint*>(indices)[0];
1291 data[i*3 + 1] = static_cast<const GLuint*>(indices)[i + 1];
1292 data[i*3 + 2] = static_cast<const GLuint*>(indices)[i + 2];
1293 }
1294 break;
1295 default: UNREACHABLE();
1296 }
1297
1298 if (!mTriangleFanIB->unmapBuffer())
1299 {
1300 ERR("Could not unmap scratch index buffer for GL_TRIANGLE_FAN.");
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +00001301 return gl::error(GL_OUT_OF_MEMORY);
daniel@transgaming.com4fd1f982013-01-11 04:12:58 +00001302 }
1303
1304 if (mAppliedIBSerial != mTriangleFanIB->getSerial() || mAppliedIBOffset != indexBufferOffset)
1305 {
1306 IndexBuffer11 *indexBuffer = IndexBuffer11::makeIndexBuffer11(mTriangleFanIB->getIndexBuffer());
1307
1308 mDeviceContext->IASetIndexBuffer(indexBuffer->getBuffer(), indexBuffer->getIndexFormat(), indexBufferOffset);
1309 mAppliedIBSerial = mTriangleFanIB->getSerial();
shannon.woods@transgaming.coma1229a32013-02-28 23:08:40 +00001310 mAppliedStorageIBSerial = 0;
daniel@transgaming.com4fd1f982013-01-11 04:12:58 +00001311 mAppliedIBOffset = indexBufferOffset;
1312 }
1313
shannon.woods@transgaming.com00032cb2013-01-25 21:56:30 +00001314 if (instances > 0)
1315 {
1316 mDeviceContext->DrawIndexedInstanced(numTris * 3, instances, 0, -minIndex, 0);
1317 }
1318 else
1319 {
1320 mDeviceContext->DrawIndexed(numTris * 3, 0, -minIndex);
1321 }
daniel@transgaming.com4fd1f982013-01-11 04:12:58 +00001322}
1323
daniel@transgaming.com5fbf1772012-11-28 20:54:43 +00001324void Renderer11::applyShaders(gl::ProgramBinary *programBinary)
1325{
daniel@transgaming.come4991412012-12-20 20:55:34 +00001326 unsigned int programBinarySerial = programBinary->getSerial();
shannon.woods@transgaming.com43ccf3f2013-02-28 23:07:19 +00001327 const bool updateProgramState = (programBinarySerial != mAppliedProgramBinarySerial);
1328
1329 if (updateProgramState)
daniel@transgaming.come4991412012-12-20 20:55:34 +00001330 {
1331 ShaderExecutable *vertexExe = programBinary->getVertexExecutable();
1332 ShaderExecutable *pixelExe = programBinary->getPixelExecutable();
daniel@transgaming.comd4b2db22012-11-28 21:05:15 +00001333
daniel@transgaming.come4991412012-12-20 20:55:34 +00001334 ID3D11VertexShader *vertexShader = NULL;
1335 if (vertexExe) vertexShader = ShaderExecutable11::makeShaderExecutable11(vertexExe)->getVertexShader();
daniel@transgaming.comd4b2db22012-11-28 21:05:15 +00001336
daniel@transgaming.come4991412012-12-20 20:55:34 +00001337 ID3D11PixelShader *pixelShader = NULL;
1338 if (pixelExe) pixelShader = ShaderExecutable11::makeShaderExecutable11(pixelExe)->getPixelShader();
daniel@transgaming.comd4b2db22012-11-28 21:05:15 +00001339
daniel@transgaming.come4991412012-12-20 20:55:34 +00001340 mDeviceContext->PSSetShader(pixelShader, NULL, 0);
1341 mDeviceContext->VSSetShader(vertexShader, NULL, 0);
shannon.woods@transgaming.com3e773bb2013-01-25 21:55:47 +00001342
shannon.woods@transgaming.comdd2524c2013-02-28 23:04:33 +00001343 programBinary->dirtyAllUniforms();
1344
1345 mAppliedProgramBinarySerial = programBinarySerial;
1346 }
1347
1348 // Only use the geometry shader currently for point sprite drawing
shannon.woods@transgaming.com43ccf3f2013-02-28 23:07:19 +00001349 const bool usesGeometryShader = (programBinary->usesGeometryShader() && mCurRasterState.pointDrawMode);
shannon.woods@transgaming.comdd2524c2013-02-28 23:04:33 +00001350
shannon.woods@transgaming.com43ccf3f2013-02-28 23:07:19 +00001351 if (updateProgramState || usesGeometryShader != mIsGeometryShaderActive)
shannon.woods@transgaming.comdd2524c2013-02-28 23:04:33 +00001352 {
1353 if (usesGeometryShader)
shannon.woods@transgaming.com3e773bb2013-01-25 21:55:47 +00001354 {
shannon.woods@transgaming.comdd2524c2013-02-28 23:04:33 +00001355 ShaderExecutable *geometryExe = programBinary->getGeometryExecutable();
1356 ID3D11GeometryShader *geometryShader = ShaderExecutable11::makeShaderExecutable11(geometryExe)->getGeometryShader();
shannon.woods@transgaming.com3e773bb2013-01-25 21:55:47 +00001357 mDeviceContext->GSSetShader(geometryShader, NULL, 0);
1358 }
1359 else
1360 {
1361 mDeviceContext->GSSetShader(NULL, NULL, 0);
1362 }
1363
shannon.woods@transgaming.comdd2524c2013-02-28 23:04:33 +00001364 mIsGeometryShaderActive = usesGeometryShader;
daniel@transgaming.come4991412012-12-20 20:55:34 +00001365 }
daniel@transgaming.com5fbf1772012-11-28 20:54:43 +00001366}
1367
shannon.woods@transgaming.com21ba6472013-01-25 21:53:32 +00001368void Renderer11::applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray *uniformArray)
daniel@transgaming.comab1c1462012-12-20 21:08:30 +00001369{
shannon.woods@transgaming.com5929ef22013-01-25 21:53:24 +00001370 ShaderExecutable11 *vertexExecutable = ShaderExecutable11::makeShaderExecutable11(programBinary->getVertexExecutable());
1371 ShaderExecutable11 *pixelExecutable = ShaderExecutable11::makeShaderExecutable11(programBinary->getPixelExecutable());
daniel@transgaming.com873f28a2012-12-20 21:12:42 +00001372
shannon.woods@transgaming.com5929ef22013-01-25 21:53:24 +00001373 unsigned int totalRegisterCountVS = 0;
1374 unsigned int totalRegisterCountPS = 0;
daniel@transgaming.com873f28a2012-12-20 21:12:42 +00001375
shannon.woods@transgaming.com21ba6472013-01-25 21:53:32 +00001376 bool vertexUniformsDirty = false;
1377 bool pixelUniformsDirty = false;
1378
shannon.woods@transgaming.com5929ef22013-01-25 21:53:24 +00001379 for (gl::UniformArray::const_iterator uniform_iterator = uniformArray->begin(); uniform_iterator != uniformArray->end(); uniform_iterator++)
1380 {
1381 const gl::Uniform *uniform = *uniform_iterator;
shannon.woods@transgaming.com46a5b872013-01-25 21:52:57 +00001382
shannonwoods@chromium.org38676dc2013-05-30 00:06:52 +00001383 if (uniform->isReferencedByVertexShader())
shannon.woods@transgaming.com5929ef22013-01-25 21:53:24 +00001384 {
1385 totalRegisterCountVS += uniform->registerCount;
shannon.woods@transgaming.com21ba6472013-01-25 21:53:32 +00001386 vertexUniformsDirty = vertexUniformsDirty || uniform->dirty;
shannon.woods@transgaming.com5929ef22013-01-25 21:53:24 +00001387 }
daniel@transgaming.com873f28a2012-12-20 21:12:42 +00001388
shannonwoods@chromium.org38676dc2013-05-30 00:06:52 +00001389 if (uniform->isReferencedByFragmentShader())
shannon.woods@transgaming.com5929ef22013-01-25 21:53:24 +00001390 {
1391 totalRegisterCountPS += uniform->registerCount;
shannon.woods@transgaming.com21ba6472013-01-25 21:53:32 +00001392 pixelUniformsDirty = pixelUniformsDirty || uniform->dirty;
shannon.woods@transgaming.com5929ef22013-01-25 21:53:24 +00001393 }
1394 }
daniel@transgaming.com873f28a2012-12-20 21:12:42 +00001395
shannon.woods@transgaming.com5929ef22013-01-25 21:53:24 +00001396 ID3D11Buffer *vertexConstantBuffer = vertexExecutable->getConstantBuffer(mDevice, totalRegisterCountVS);
1397 ID3D11Buffer *pixelConstantBuffer = pixelExecutable->getConstantBuffer(mDevice, totalRegisterCountPS);
1398
shannon.woods@transgaming.com09bf2a72013-02-28 23:12:54 +00001399 float (*mapVS)[4] = NULL;
1400 float (*mapPS)[4] = NULL;
1401
1402 if (totalRegisterCountVS > 0 && vertexUniformsDirty)
1403 {
1404 D3D11_MAPPED_SUBRESOURCE map = {0};
1405 HRESULT result = mDeviceContext->Map(vertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
1406 ASSERT(SUCCEEDED(result));
1407 mapVS = (float(*)[4])map.pData;
1408 }
1409
1410 if (totalRegisterCountPS > 0 && pixelUniformsDirty)
1411 {
1412 D3D11_MAPPED_SUBRESOURCE map = {0};
1413 HRESULT result = mDeviceContext->Map(pixelConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
1414 ASSERT(SUCCEEDED(result));
1415 mapPS = (float(*)[4])map.pData;
1416 }
daniel@transgaming.com873f28a2012-12-20 21:12:42 +00001417
shannon.woods@transgaming.com21ba6472013-01-25 21:53:32 +00001418 for (gl::UniformArray::iterator uniform_iterator = uniformArray->begin(); uniform_iterator != uniformArray->end(); uniform_iterator++)
daniel@transgaming.comab1c1462012-12-20 21:08:30 +00001419 {
shannon.woods@transgaming.com21ba6472013-01-25 21:53:32 +00001420 gl::Uniform *uniform = *uniform_iterator;
daniel@transgaming.com873f28a2012-12-20 21:12:42 +00001421
shannon.woods@transgaming.com13979a62013-02-28 23:10:18 +00001422 if (uniform->type != GL_SAMPLER_2D && uniform->type != GL_SAMPLER_CUBE)
daniel@transgaming.com873f28a2012-12-20 21:12:42 +00001423 {
shannonwoods@chromium.org38676dc2013-05-30 00:06:52 +00001424 if (uniform->isReferencedByVertexShader() && mapVS)
daniel@transgaming.com873f28a2012-12-20 21:12:42 +00001425 {
shannon.woods@transgaming.com13979a62013-02-28 23:10:18 +00001426 memcpy(mapVS + uniform->vsRegisterIndex, uniform->data, uniform->registerCount * sizeof(float[4]));
daniel@transgaming.com873f28a2012-12-20 21:12:42 +00001427 }
shannon.woods@transgaming.com13979a62013-02-28 23:10:18 +00001428
shannonwoods@chromium.org38676dc2013-05-30 00:06:52 +00001429 if (uniform->isReferencedByFragmentShader() && mapPS)
daniel@transgaming.com873f28a2012-12-20 21:12:42 +00001430 {
shannon.woods@transgaming.com13979a62013-02-28 23:10:18 +00001431 memcpy(mapPS + uniform->psRegisterIndex, uniform->data, uniform->registerCount * sizeof(float[4]));
daniel@transgaming.come76b64b2013-01-11 04:10:08 +00001432 }
daniel@transgaming.com873f28a2012-12-20 21:12:42 +00001433 }
shannon.woods@transgaming.com21ba6472013-01-25 21:53:32 +00001434
1435 uniform->dirty = false;
daniel@transgaming.comab1c1462012-12-20 21:08:30 +00001436 }
daniel@transgaming.com873f28a2012-12-20 21:12:42 +00001437
shannon.woods@transgaming.com09bf2a72013-02-28 23:12:54 +00001438 if (mapVS)
shannon.woods@transgaming.com5929ef22013-01-25 21:53:24 +00001439 {
shannon.woods@transgaming.com09bf2a72013-02-28 23:12:54 +00001440 mDeviceContext->Unmap(vertexConstantBuffer, 0);
shannon.woods@transgaming.com5929ef22013-01-25 21:53:24 +00001441 }
1442
shannon.woods@transgaming.com09bf2a72013-02-28 23:12:54 +00001443 if (mapPS)
shannon.woods@transgaming.com5929ef22013-01-25 21:53:24 +00001444 {
shannon.woods@transgaming.com09bf2a72013-02-28 23:12:54 +00001445 mDeviceContext->Unmap(pixelConstantBuffer, 0);
shannon.woods@transgaming.com5929ef22013-01-25 21:53:24 +00001446 }
shannon.woods@transgaming.com5fb979d2013-01-25 21:53:04 +00001447
shannon.woods@transgaming.com5929ef22013-01-25 21:53:24 +00001448 mDeviceContext->VSSetConstantBuffers(0, 1, &vertexConstantBuffer);
1449 mDeviceContext->PSSetConstantBuffers(0, 1, &pixelConstantBuffer);
shannon.woods@transgaming.com3e773bb2013-01-25 21:55:47 +00001450
daniel@transgaming.coma390e1e2013-01-11 04:09:39 +00001451 // Driver uniforms
shannon.woods@transgaming.com5fb979d2013-01-25 21:53:04 +00001452 if (!mDriverConstantBufferVS)
1453 {
1454 D3D11_BUFFER_DESC constantBufferDescription = {0};
1455 constantBufferDescription.ByteWidth = sizeof(dx_VertexConstants);
1456 constantBufferDescription.Usage = D3D11_USAGE_DEFAULT;
1457 constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
1458 constantBufferDescription.CPUAccessFlags = 0;
1459 constantBufferDescription.MiscFlags = 0;
1460 constantBufferDescription.StructureByteStride = 0;
daniel@transgaming.coma390e1e2013-01-11 04:09:39 +00001461
shannon.woods@transgaming.com5929ef22013-01-25 21:53:24 +00001462 HRESULT result = mDevice->CreateBuffer(&constantBufferDescription, NULL, &mDriverConstantBufferVS);
shannon.woods@transgaming.com5fb979d2013-01-25 21:53:04 +00001463 ASSERT(SUCCEEDED(result));
daniel@transgaming.com873f28a2012-12-20 21:12:42 +00001464
shannon.woods@transgaming.com5fb979d2013-01-25 21:53:04 +00001465 mDeviceContext->VSSetConstantBuffers(1, 1, &mDriverConstantBufferVS);
1466 }
shannon.woods@transgaming.com46a5b872013-01-25 21:52:57 +00001467
shannon.woods@transgaming.com5fb979d2013-01-25 21:53:04 +00001468 if (!mDriverConstantBufferPS)
1469 {
1470 D3D11_BUFFER_DESC constantBufferDescription = {0};
1471 constantBufferDescription.ByteWidth = sizeof(dx_PixelConstants);
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;
shannon.woods@transgaming.com46a5b872013-01-25 21:52:57 +00001477
shannon.woods@transgaming.com5929ef22013-01-25 21:53:24 +00001478 HRESULT result = mDevice->CreateBuffer(&constantBufferDescription, NULL, &mDriverConstantBufferPS);
shannon.woods@transgaming.com5fb979d2013-01-25 21:53:04 +00001479 ASSERT(SUCCEEDED(result));
shannon.woods@transgaming.com46a5b872013-01-25 21:52:57 +00001480
shannon.woods@transgaming.com5fb979d2013-01-25 21:53:04 +00001481 mDeviceContext->PSSetConstantBuffers(1, 1, &mDriverConstantBufferPS);
1482 }
shannon.woods@transgaming.com46a5b872013-01-25 21:52:57 +00001483
shannon.woods@transgaming.com5fb979d2013-01-25 21:53:04 +00001484 if (memcmp(&mVertexConstants, &mAppliedVertexConstants, sizeof(dx_VertexConstants)) != 0)
1485 {
1486 mDeviceContext->UpdateSubresource(mDriverConstantBufferVS, 0, NULL, &mVertexConstants, 16, 0);
1487 memcpy(&mAppliedVertexConstants, &mVertexConstants, sizeof(dx_VertexConstants));
1488 }
shannon.woods@transgaming.com46a5b872013-01-25 21:52:57 +00001489
shannon.woods@transgaming.com5fb979d2013-01-25 21:53:04 +00001490 if (memcmp(&mPixelConstants, &mAppliedPixelConstants, sizeof(dx_PixelConstants)) != 0)
1491 {
1492 mDeviceContext->UpdateSubresource(mDriverConstantBufferPS, 0, NULL, &mPixelConstants, 16, 0);
1493 memcpy(&mAppliedPixelConstants, &mPixelConstants, sizeof(dx_PixelConstants));
1494 }
shannon.woods@transgaming.com3e773bb2013-01-25 21:55:47 +00001495
1496 // needed for the point sprite geometry shader
1497 mDeviceContext->GSSetConstantBuffers(0, 1, &mDriverConstantBufferPS);
daniel@transgaming.comab1c1462012-12-20 21:08:30 +00001498}
1499
daniel@transgaming.com084a2572012-11-28 20:55:17 +00001500void Renderer11::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer)
daniel@transgaming.comd084c622012-11-28 19:36:05 +00001501{
shannonwoods@chromium.org755012f2013-05-30 00:09:32 +00001502 bool alphaUnmasked = gl::GetAlphaBits(mRenderTargetDesc.format, getCurrentClientVersion()) == 0 ||
1503 clearParams.colorMaskAlpha;
shannon.woods@transgaming.com81c5ef92013-01-25 21:52:08 +00001504 bool needMaskedColorClear = (clearParams.mask & GL_COLOR_BUFFER_BIT) &&
1505 !(clearParams.colorMaskRed && clearParams.colorMaskGreen &&
1506 clearParams.colorMaskBlue && alphaUnmasked);
daniel@transgaming.com54e67542012-11-28 21:02:31 +00001507
shannon.woods@transgaming.com81c5ef92013-01-25 21:52:08 +00001508 unsigned int stencilUnmasked = 0x0;
1509 if (frameBuffer->hasStencil())
1510 {
shannonwoods@chromium.org755012f2013-05-30 00:09:32 +00001511 unsigned int stencilSize = gl::GetStencilBits(frameBuffer->getStencilbuffer()->getActualFormat(),
1512 getCurrentClientVersion());
shannon.woods@transgaming.com81c5ef92013-01-25 21:52:08 +00001513 stencilUnmasked = (0x1 << stencilSize) - 1;
1514 }
1515 bool needMaskedStencilClear = (clearParams.mask & GL_STENCIL_BUFFER_BIT) &&
1516 (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked;
daniel@transgaming.com54e67542012-11-28 21:02:31 +00001517
shannon.woods@transgaming.com81c5ef92013-01-25 21:52:08 +00001518 bool needScissoredClear = mScissorEnabled && (mCurScissor.x > 0 || mCurScissor.y > 0 ||
1519 mCurScissor.x + mCurScissor.width < mRenderTargetDesc.width ||
1520 mCurScissor.y + mCurScissor.height < mRenderTargetDesc.height);
daniel@transgaming.com54e67542012-11-28 21:02:31 +00001521
shannon.woods@transgaming.com81c5ef92013-01-25 21:52:08 +00001522 if (needMaskedColorClear || needMaskedStencilClear || needScissoredClear)
1523 {
shannonwoods@chromium.org98949842013-05-30 00:01:51 +00001524 maskedClear(clearParams, frameBuffer->usingExtendedDrawBuffers());
shannon.woods@transgaming.com81c5ef92013-01-25 21:52:08 +00001525 }
1526 else
1527 {
1528 if (clearParams.mask & GL_COLOR_BUFFER_BIT)
1529 {
shannon.woods%transgaming.com@gtempaccount.comdae24092013-04-13 03:31:31 +00001530 for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
shannon.woods@transgaming.com81c5ef92013-01-25 21:52:08 +00001531 {
shannon.woods%transgaming.com@gtempaccount.comdae24092013-04-13 03:31:31 +00001532 if (frameBuffer->isEnabledColorAttachment(colorAttachment))
1533 {
1534 gl::Renderbuffer *renderbufferObject = frameBuffer->getColorbuffer(colorAttachment);
1535 if (renderbufferObject)
1536 {
1537 RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(renderbufferObject->getRenderTarget());
1538 if (!renderTarget)
1539 {
1540 ERR("render target pointer unexpectedly null.");
1541 return;
1542 }
daniel@transgaming.com54e67542012-11-28 21:02:31 +00001543
shannon.woods%transgaming.com@gtempaccount.comdae24092013-04-13 03:31:31 +00001544 ID3D11RenderTargetView *framebufferRTV = renderTarget->getRenderTargetView();
1545 if (!framebufferRTV)
1546 {
1547 ERR("render target view pointer unexpectedly null.");
1548 return;
1549 }
shannon.woods@transgaming.com81c5ef92013-01-25 21:52:08 +00001550
shannon.woods%transgaming.com@gtempaccount.comdae24092013-04-13 03:31:31 +00001551 const float clearValues[4] = { clearParams.colorClearValue.red,
1552 clearParams.colorClearValue.green,
1553 clearParams.colorClearValue.blue,
1554 clearParams.colorClearValue.alpha };
1555 mDeviceContext->ClearRenderTargetView(framebufferRTV, clearValues);
daniel@transgaming.com54e67542012-11-28 21:02:31 +00001556
shannon.woods%transgaming.com@gtempaccount.comdae24092013-04-13 03:31:31 +00001557 framebufferRTV->Release();
1558 }
1559 }
1560 }
daniel@transgaming.com54e67542012-11-28 21:02:31 +00001561 }
shannon.woods@transgaming.com81c5ef92013-01-25 21:52:08 +00001562 if (clearParams.mask & GL_DEPTH_BUFFER_BIT || clearParams.mask & GL_STENCIL_BUFFER_BIT)
daniel@transgaming.com54e67542012-11-28 21:02:31 +00001563 {
shannon.woods@transgaming.com81c5ef92013-01-25 21:52:08 +00001564 gl::Renderbuffer *renderbufferObject = frameBuffer->getDepthOrStencilbuffer();
1565 if (renderbufferObject)
daniel@transgaming.com54e67542012-11-28 21:02:31 +00001566 {
shannon.woods@transgaming.com81c5ef92013-01-25 21:52:08 +00001567 RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(renderbufferObject->getDepthStencil());
1568 if (!renderTarget)
1569 {
1570 ERR("render target pointer unexpectedly null.");
1571 return;
1572 }
daniel@transgaming.com54e67542012-11-28 21:02:31 +00001573
shannon.woods@transgaming.com81c5ef92013-01-25 21:52:08 +00001574 ID3D11DepthStencilView *framebufferDSV = renderTarget->getDepthStencilView();
1575 if (!framebufferDSV)
1576 {
1577 ERR("depth stencil view pointer unexpectedly null.");
1578 return;
1579 }
daniel@transgaming.com54e67542012-11-28 21:02:31 +00001580
daniel@transgaming.com54e67542012-11-28 21:02:31 +00001581 UINT clearFlags = 0;
1582 if (clearParams.mask & GL_DEPTH_BUFFER_BIT)
1583 {
1584 clearFlags |= D3D11_CLEAR_DEPTH;
1585 }
1586 if (clearParams.mask & GL_STENCIL_BUFFER_BIT)
1587 {
1588 clearFlags |= D3D11_CLEAR_STENCIL;
1589 }
1590
shannon.woods@transgaming.combe211b32013-02-28 23:17:16 +00001591 float depthClear = gl::clamp01(clearParams.depthClearValue);
daniel@transgaming.com54e67542012-11-28 21:02:31 +00001592 UINT8 stencilClear = clearParams.stencilClearValue & 0x000000FF;
1593
1594 mDeviceContext->ClearDepthStencilView(framebufferDSV, clearFlags, depthClear, stencilClear);
daniel@transgaming.com54e67542012-11-28 21:02:31 +00001595
shannon.woods@transgaming.com81c5ef92013-01-25 21:52:08 +00001596 framebufferDSV->Release();
1597 }
daniel@transgaming.com54e67542012-11-28 21:02:31 +00001598 }
1599 }
daniel@transgaming.comd084c622012-11-28 19:36:05 +00001600}
1601
shannonwoods@chromium.org98949842013-05-30 00:01:51 +00001602void Renderer11::maskedClear(const gl::ClearParameters &clearParams, bool usingExtendedDrawBuffers)
shannon.woods@transgaming.com34f507c2013-01-25 21:52:15 +00001603{
1604 HRESULT result;
1605
1606 if (!mClearResourcesInitialized)
1607 {
shannonwoods@chromium.org98949842013-05-30 00:01:51 +00001608 ASSERT(!mClearVB && !mClearVS && !mClearSinglePS && !mClearMultiplePS && !mClearScissorRS && !mClearNoScissorRS);
shannon.woods@transgaming.com34f507c2013-01-25 21:52:15 +00001609
1610 D3D11_BUFFER_DESC vbDesc;
1611 vbDesc.ByteWidth = sizeof(d3d11::PositionDepthColorVertex) * 4;
1612 vbDesc.Usage = D3D11_USAGE_DYNAMIC;
1613 vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
1614 vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
1615 vbDesc.MiscFlags = 0;
1616 vbDesc.StructureByteStride = 0;
1617
1618 result = mDevice->CreateBuffer(&vbDesc, NULL, &mClearVB);
1619 ASSERT(SUCCEEDED(result));
1620 d3d11::SetDebugName(mClearVB, "Renderer11 masked clear vertex buffer");
1621
1622 D3D11_INPUT_ELEMENT_DESC quadLayout[] =
1623 {
1624 { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
1625 { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
1626 };
1627
1628 result = mDevice->CreateInputLayout(quadLayout, 2, g_VS_Clear, sizeof(g_VS_Clear), &mClearIL);
1629 ASSERT(SUCCEEDED(result));
1630 d3d11::SetDebugName(mClearIL, "Renderer11 masked clear input layout");
1631
1632 result = mDevice->CreateVertexShader(g_VS_Clear, sizeof(g_VS_Clear), NULL, &mClearVS);
1633 ASSERT(SUCCEEDED(result));
1634 d3d11::SetDebugName(mClearVS, "Renderer11 masked clear vertex shader");
1635
shannonwoods@chromium.org98949842013-05-30 00:01:51 +00001636 result = mDevice->CreatePixelShader(g_PS_ClearSingle, sizeof(g_PS_ClearSingle), NULL, &mClearSinglePS);
shannon.woods@transgaming.com34f507c2013-01-25 21:52:15 +00001637 ASSERT(SUCCEEDED(result));
shannonwoods@chromium.org98949842013-05-30 00:01:51 +00001638 d3d11::SetDebugName(mClearSinglePS, "Renderer11 masked clear pixel shader (1 RT)");
1639
1640 result = mDevice->CreatePixelShader(g_PS_ClearMultiple, sizeof(g_PS_ClearMultiple), NULL, &mClearMultiplePS);
1641 ASSERT(SUCCEEDED(result));
1642 d3d11::SetDebugName(mClearMultiplePS, "Renderer11 masked clear pixel shader (MRT)");
shannon.woods@transgaming.com34f507c2013-01-25 21:52:15 +00001643
1644 D3D11_RASTERIZER_DESC rsScissorDesc;
1645 rsScissorDesc.FillMode = D3D11_FILL_SOLID;
1646 rsScissorDesc.CullMode = D3D11_CULL_NONE;
1647 rsScissorDesc.FrontCounterClockwise = FALSE;
1648 rsScissorDesc.DepthBias = 0;
1649 rsScissorDesc.DepthBiasClamp = 0.0f;
1650 rsScissorDesc.SlopeScaledDepthBias = 0.0f;
1651 rsScissorDesc.DepthClipEnable = FALSE;
1652 rsScissorDesc.ScissorEnable = TRUE;
1653 rsScissorDesc.MultisampleEnable = FALSE;
1654 rsScissorDesc.AntialiasedLineEnable = FALSE;
1655
1656 result = mDevice->CreateRasterizerState(&rsScissorDesc, &mClearScissorRS);
1657 ASSERT(SUCCEEDED(result));
1658 d3d11::SetDebugName(mClearScissorRS, "Renderer11 masked clear scissor rasterizer state");
1659
1660 D3D11_RASTERIZER_DESC rsNoScissorDesc;
1661 rsNoScissorDesc.FillMode = D3D11_FILL_SOLID;
1662 rsNoScissorDesc.CullMode = D3D11_CULL_NONE;
1663 rsNoScissorDesc.FrontCounterClockwise = FALSE;
1664 rsNoScissorDesc.DepthBias = 0;
1665 rsNoScissorDesc.DepthBiasClamp = 0.0f;
1666 rsNoScissorDesc.SlopeScaledDepthBias = 0.0f;
1667 rsNoScissorDesc.DepthClipEnable = FALSE;
1668 rsNoScissorDesc.ScissorEnable = FALSE;
1669 rsNoScissorDesc.MultisampleEnable = FALSE;
1670 rsNoScissorDesc.AntialiasedLineEnable = FALSE;
1671
1672 result = mDevice->CreateRasterizerState(&rsNoScissorDesc, &mClearNoScissorRS);
1673 ASSERT(SUCCEEDED(result));
1674 d3d11::SetDebugName(mClearNoScissorRS, "Renderer11 masked clear no scissor rasterizer state");
1675
1676 mClearResourcesInitialized = true;
1677 }
1678
1679 // Prepare the depth stencil state to write depth values if the depth should be cleared
1680 // and stencil values if the stencil should be cleared
1681 gl::DepthStencilState glDSState;
1682 glDSState.depthTest = (clearParams.mask & GL_DEPTH_BUFFER_BIT) != 0;
1683 glDSState.depthFunc = GL_ALWAYS;
1684 glDSState.depthMask = (clearParams.mask & GL_DEPTH_BUFFER_BIT) != 0;
1685 glDSState.stencilTest = (clearParams.mask & GL_STENCIL_BUFFER_BIT) != 0;
1686 glDSState.stencilFunc = GL_ALWAYS;
1687 glDSState.stencilMask = 0;
1688 glDSState.stencilFail = GL_REPLACE;
1689 glDSState.stencilPassDepthFail = GL_REPLACE;
1690 glDSState.stencilPassDepthPass = GL_REPLACE;
1691 glDSState.stencilWritemask = clearParams.stencilWriteMask;
1692 glDSState.stencilBackFunc = GL_ALWAYS;
1693 glDSState.stencilBackMask = 0;
1694 glDSState.stencilBackFail = GL_REPLACE;
1695 glDSState.stencilBackPassDepthFail = GL_REPLACE;
1696 glDSState.stencilBackPassDepthPass = GL_REPLACE;
1697 glDSState.stencilBackWritemask = clearParams.stencilWriteMask;
1698
1699 int stencilClear = clearParams.stencilClearValue & 0x000000FF;
1700
1701 ID3D11DepthStencilState *dsState = mStateCache.getDepthStencilState(glDSState);
1702
1703 // Prepare the blend state to use a write mask if the color buffer should be cleared
1704 gl::BlendState glBlendState;
1705 glBlendState.blend = false;
1706 glBlendState.sourceBlendRGB = GL_ONE;
1707 glBlendState.destBlendRGB = GL_ZERO;
1708 glBlendState.sourceBlendAlpha = GL_ONE;
1709 glBlendState.destBlendAlpha = GL_ZERO;
1710 glBlendState.blendEquationRGB = GL_FUNC_ADD;
1711 glBlendState.blendEquationAlpha = GL_FUNC_ADD;
1712 glBlendState.colorMaskRed = (clearParams.mask & GL_COLOR_BUFFER_BIT) ? clearParams.colorMaskRed : false;
1713 glBlendState.colorMaskGreen = (clearParams.mask & GL_COLOR_BUFFER_BIT) ? clearParams.colorMaskGreen : false;
1714 glBlendState.colorMaskBlue = (clearParams.mask & GL_COLOR_BUFFER_BIT) ? clearParams.colorMaskBlue : false;
shannon.woods@transgaming.com50ea9932013-02-28 23:13:40 +00001715 glBlendState.colorMaskAlpha = (clearParams.mask & GL_COLOR_BUFFER_BIT) ? clearParams.colorMaskAlpha : false;
shannon.woods@transgaming.com34f507c2013-01-25 21:52:15 +00001716 glBlendState.sampleAlphaToCoverage = false;
1717 glBlendState.dither = false;
1718
1719 static const float blendFactors[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
1720 static const UINT sampleMask = 0xFFFFFFFF;
1721
1722 ID3D11BlendState *blendState = mStateCache.getBlendState(glBlendState);
1723
1724 // Set the vertices
1725 D3D11_MAPPED_SUBRESOURCE mappedResource;
1726 result = mDeviceContext->Map(mClearVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
1727 if (FAILED(result))
1728 {
1729 ERR("Failed to map masked clear vertex buffer, HRESULT: 0x%X.", result);
1730 return;
1731 }
1732
1733 d3d11::PositionDepthColorVertex *vertices = reinterpret_cast<d3d11::PositionDepthColorVertex*>(mappedResource.pData);
1734
1735 float depthClear = gl::clamp01(clearParams.depthClearValue);
1736 d3d11::SetPositionDepthColorVertex(&vertices[0], -1.0f, 1.0f, depthClear, clearParams.colorClearValue);
1737 d3d11::SetPositionDepthColorVertex(&vertices[1], -1.0f, -1.0f, depthClear, clearParams.colorClearValue);
1738 d3d11::SetPositionDepthColorVertex(&vertices[2], 1.0f, 1.0f, depthClear, clearParams.colorClearValue);
1739 d3d11::SetPositionDepthColorVertex(&vertices[3], 1.0f, -1.0f, depthClear, clearParams.colorClearValue);
1740
1741 mDeviceContext->Unmap(mClearVB, 0);
1742
1743 // Apply state
1744 mDeviceContext->OMSetBlendState(blendState, blendFactors, sampleMask);
1745 mDeviceContext->OMSetDepthStencilState(dsState, stencilClear);
1746 mDeviceContext->RSSetState(mScissorEnabled ? mClearScissorRS : mClearNoScissorRS);
1747
1748 // Apply shaders
shannonwoods@chromium.org98949842013-05-30 00:01:51 +00001749 ID3D11PixelShader *pixelShader = usingExtendedDrawBuffers ? mClearMultiplePS : mClearSinglePS;
1750
shannon.woods@transgaming.com34f507c2013-01-25 21:52:15 +00001751 mDeviceContext->IASetInputLayout(mClearIL);
1752 mDeviceContext->VSSetShader(mClearVS, NULL, 0);
shannonwoods@chromium.org98949842013-05-30 00:01:51 +00001753 mDeviceContext->PSSetShader(pixelShader, NULL, 0);
shannon.woods@transgaming.com2c53e472013-02-28 23:13:56 +00001754 mDeviceContext->GSSetShader(NULL, NULL, 0);
shannon.woods@transgaming.com34f507c2013-01-25 21:52:15 +00001755
1756 // Apply vertex buffer
1757 static UINT stride = sizeof(d3d11::PositionDepthColorVertex);
1758 static UINT startIdx = 0;
1759 mDeviceContext->IASetVertexBuffers(0, 1, &mClearVB, &stride, &startIdx);
1760 mDeviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
1761
1762 // Draw the clear quad
1763 mDeviceContext->Draw(4, 0);
1764
1765 // Clean up
1766 markAllStateDirty();
1767}
1768
daniel@transgaming.comc43a6052012-11-28 19:41:51 +00001769void Renderer11::markAllStateDirty()
1770{
shannon.woods%transgaming.com@gtempaccount.comf4fe7102013-04-13 03:30:26 +00001771 for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++)
1772 {
1773 mAppliedRenderTargetSerials[rtIndex] = 0;
1774 }
daniel@transgaming.com9a067372012-12-20 20:55:24 +00001775 mAppliedDepthbufferSerial = 0;
1776 mAppliedStencilbufferSerial = 0;
daniel@transgaming.com7b6b83e2012-11-28 21:00:30 +00001777 mDepthStencilInitialized = false;
1778 mRenderTargetDescInitialized = false;
1779
shannon.woods@transgaming.com233fe952013-01-25 21:51:57 +00001780 for (int i = 0; i < gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; i++)
daniel@transgaming.com54de24f2013-01-11 04:07:59 +00001781 {
1782 mForceSetVertexSamplerStates[i] = true;
daniel@transgaming.come33c8bf2013-01-11 04:11:33 +00001783 mCurVertexTextureSerials[i] = 0;
daniel@transgaming.com54de24f2013-01-11 04:07:59 +00001784 }
1785 for (int i = 0; i < gl::MAX_TEXTURE_IMAGE_UNITS; i++)
1786 {
1787 mForceSetPixelSamplerStates[i] = true;
daniel@transgaming.come33c8bf2013-01-11 04:11:33 +00001788 mCurPixelTextureSerials[i] = 0;
daniel@transgaming.com54de24f2013-01-11 04:07:59 +00001789 }
1790
daniel@transgaming.comc43a6052012-11-28 19:41:51 +00001791 mForceSetBlendState = true;
1792 mForceSetRasterState = true;
1793 mForceSetDepthStencilState = true;
1794 mForceSetScissor = true;
daniel@transgaming.com53670042012-11-28 20:55:51 +00001795 mForceSetViewport = true;
daniel@transgaming.come4991412012-12-20 20:55:34 +00001796
daniel@transgaming.comc5431eb2012-12-20 21:10:15 +00001797 mAppliedIBSerial = 0;
shannon.woods@transgaming.coma1229a32013-02-28 23:08:40 +00001798 mAppliedStorageIBSerial = 0;
daniel@transgaming.com7fbf4862013-01-11 04:09:22 +00001799 mAppliedIBOffset = 0;
1800
daniel@transgaming.come4991412012-12-20 20:55:34 +00001801 mAppliedProgramBinarySerial = 0;
shannon.woods@transgaming.com5fb979d2013-01-25 21:53:04 +00001802 memset(&mAppliedVertexConstants, 0, sizeof(dx_VertexConstants));
1803 memset(&mAppliedPixelConstants, 0, sizeof(dx_PixelConstants));
daniel@transgaming.comc43a6052012-11-28 19:41:51 +00001804}
1805
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001806void Renderer11::releaseDeviceResources()
1807{
daniel@transgaming.comf8ba1092012-11-28 19:37:53 +00001808 mStateCache.clear();
daniel@transgaming.comc5431eb2012-12-20 21:10:15 +00001809 mInputLayoutCache.clear();
1810
1811 delete mVertexDataManager;
1812 mVertexDataManager = NULL;
1813
1814 delete mIndexDataManager;
1815 mIndexDataManager = NULL;
daniel@transgaming.comc5114302012-12-20 21:11:36 +00001816
1817 delete mLineLoopIB;
1818 mLineLoopIB = NULL;
daniel@transgaming.com4fd1f982013-01-11 04:12:58 +00001819
1820 delete mTriangleFanIB;
1821 mTriangleFanIB = NULL;
shannon.woods@transgaming.com9d971ff2013-01-25 21:50:53 +00001822
Geoff Langb86b9792013-06-04 16:32:05 -04001823 delete mBlit;
1824 mBlit = NULL;
shannon.woods@transgaming.com34f507c2013-01-25 21:52:15 +00001825
shannonwoods@chromium.org894b3242013-05-30 00:01:44 +00001826 SafeRelease(mClearVB);
1827 SafeRelease(mClearIL);
1828 SafeRelease(mClearVS);
shannonwoods@chromium.org98949842013-05-30 00:01:51 +00001829 SafeRelease(mClearSinglePS);
1830 SafeRelease(mClearMultiplePS);
shannonwoods@chromium.org894b3242013-05-30 00:01:44 +00001831 SafeRelease(mClearScissorRS);
1832 SafeRelease(mClearNoScissorRS);
shannon.woods@transgaming.com34f507c2013-01-25 21:52:15 +00001833
1834 mClearResourcesInitialized = false;
shannon.woods@transgaming.com5fb979d2013-01-25 21:53:04 +00001835
shannonwoods@chromium.org894b3242013-05-30 00:01:44 +00001836 SafeRelease(mDriverConstantBufferVS);
1837 SafeRelease(mDriverConstantBufferPS);
1838 SafeRelease(mSyncQuery);
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001839}
1840
shannon.woods@transgaming.comeb049e22013-02-28 23:04:49 +00001841void Renderer11::notifyDeviceLost()
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001842{
1843 mDeviceLost = true;
shannon.woods@transgaming.comeb049e22013-02-28 23:04:49 +00001844 mDisplay->notifyDeviceLost();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001845}
1846
1847bool Renderer11::isDeviceLost()
1848{
1849 return mDeviceLost;
1850}
1851
1852// set notify to true to broadcast a message to all contexts of the device loss
1853bool Renderer11::testDeviceLost(bool notify)
1854{
1855 bool isLost = false;
1856
shannon.woods@transgaming.comddd6c802013-02-28 23:05:14 +00001857 // GetRemovedReason is used to test if the device is removed
1858 HRESULT result = mDevice->GetDeviceRemovedReason();
1859 isLost = d3d11::isDeviceLostError(result);
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001860
1861 if (isLost)
1862 {
shannon.woods@transgaming.comddd6c802013-02-28 23:05:14 +00001863 // Log error if this is a new device lost event
1864 if (mDeviceLost == false)
1865 {
1866 ERR("The D3D11 device was removed: 0x%08X", result);
1867 }
1868
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001869 // ensure we note the device loss --
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +00001870 // we'll probably get this done again by notifyDeviceLost
1871 // but best to remember it!
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001872 // Note that we don't want to clear the device loss status here
1873 // -- this needs to be done by resetDevice
1874 mDeviceLost = true;
1875 if (notify)
1876 {
shannon.woods@transgaming.comeb049e22013-02-28 23:04:49 +00001877 notifyDeviceLost();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001878 }
1879 }
1880
1881 return isLost;
1882}
1883
1884bool Renderer11::testDeviceResettable()
1885{
shannon.woods@transgaming.comddd6c802013-02-28 23:05:14 +00001886 // determine if the device is resettable by creating a dummy device
1887 PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice");
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001888
shannon.woods@transgaming.comddd6c802013-02-28 23:05:14 +00001889 if (D3D11CreateDevice == NULL)
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001890 {
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001891 return false;
1892 }
shannon.woods@transgaming.comddd6c802013-02-28 23:05:14 +00001893
shannon.woods@transgaming.comd438fd42013-02-28 23:17:45 +00001894 D3D_FEATURE_LEVEL featureLevels[] =
shannon.woods@transgaming.comddd6c802013-02-28 23:05:14 +00001895 {
1896 D3D_FEATURE_LEVEL_11_0,
1897 D3D_FEATURE_LEVEL_10_1,
1898 D3D_FEATURE_LEVEL_10_0,
1899 };
1900
1901 ID3D11Device* dummyDevice;
1902 D3D_FEATURE_LEVEL dummyFeatureLevel;
1903 ID3D11DeviceContext* dummyContext;
1904
1905 HRESULT result = D3D11CreateDevice(NULL,
1906 D3D_DRIVER_TYPE_HARDWARE,
1907 NULL,
1908 #if defined(_DEBUG)
1909 D3D11_CREATE_DEVICE_DEBUG,
1910 #else
1911 0,
1912 #endif
shannon.woods@transgaming.comd438fd42013-02-28 23:17:45 +00001913 featureLevels,
1914 ArraySize(featureLevels),
shannon.woods@transgaming.comddd6c802013-02-28 23:05:14 +00001915 D3D11_SDK_VERSION,
1916 &dummyDevice,
1917 &dummyFeatureLevel,
1918 &dummyContext);
1919
1920 if (!mDevice || FAILED(result))
1921 {
1922 return false;
1923 }
1924
1925 dummyContext->Release();
1926 dummyDevice->Release();
1927
1928 return true;
1929}
1930
1931void Renderer11::release()
1932{
1933 releaseDeviceResources();
1934
1935 if (mDxgiFactory)
1936 {
1937 mDxgiFactory->Release();
1938 mDxgiFactory = NULL;
1939 }
1940
1941 if (mDxgiAdapter)
1942 {
1943 mDxgiAdapter->Release();
1944 mDxgiAdapter = NULL;
1945 }
1946
1947 if (mDeviceContext)
1948 {
1949 mDeviceContext->ClearState();
1950 mDeviceContext->Flush();
1951 mDeviceContext->Release();
1952 mDeviceContext = NULL;
1953 }
1954
1955 if (mDevice)
1956 {
1957 mDevice->Release();
1958 mDevice = NULL;
1959 }
1960
1961 if (mD3d11Module)
1962 {
1963 FreeLibrary(mD3d11Module);
1964 mD3d11Module = NULL;
1965 }
1966
1967 if (mDxgiModule)
1968 {
1969 FreeLibrary(mDxgiModule);
1970 mDxgiModule = NULL;
1971 }
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001972}
1973
1974bool Renderer11::resetDevice()
1975{
shannon.woods@transgaming.comddd6c802013-02-28 23:05:14 +00001976 // recreate everything
1977 release();
1978 EGLint result = initialize();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001979
shannon.woods@transgaming.comddd6c802013-02-28 23:05:14 +00001980 if (result != EGL_SUCCESS)
1981 {
1982 ERR("Could not reinitialize D3D11 device: %08X", result);
1983 return false;
1984 }
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001985
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001986 mDeviceLost = false;
1987
1988 return true;
1989}
1990
1991DWORD Renderer11::getAdapterVendor() const
1992{
daniel@transgaming.com1f811f52012-11-28 20:57:39 +00001993 return mAdapterDescription.VendorId;
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001994}
1995
daniel@transgaming.comca1ac1f2013-01-11 04:13:05 +00001996std::string Renderer11::getRendererDescription() const
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00001997{
daniel@transgaming.comca1ac1f2013-01-11 04:13:05 +00001998 std::ostringstream rendererString;
1999
2000 rendererString << mDescription;
2001 rendererString << " Direct3D11";
2002
2003 rendererString << " vs_" << getMajorShaderModel() << "_" << getMinorShaderModel();
2004 rendererString << " ps_" << getMajorShaderModel() << "_" << getMinorShaderModel();
2005
2006 return rendererString.str();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00002007}
2008
2009GUID Renderer11::getAdapterIdentifier() const
2010{
shannon.woods@transgaming.com43db7952013-02-28 23:04:28 +00002011 // Use the adapter LUID as our adapter ID
2012 // This number is local to a machine is only guaranteed to be unique between restarts
2013 META_ASSERT(sizeof(LUID) <= sizeof(GUID));
2014 GUID adapterId = {0};
2015 memcpy(&adapterId, &mAdapterDescription.AdapterLuid, sizeof(LUID));
2016 return adapterId;
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00002017}
2018
shannon.woods@transgaming.combec04bf2013-01-25 21:53:52 +00002019bool Renderer11::getBGRATextureSupport() const
2020{
2021 return mBGRATextureSupport;
2022}
2023
shannonwoods@chromium.org89200d92013-05-30 00:07:50 +00002024bool Renderer11::getDXT1TextureSupport() const
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00002025{
shannon.woods@transgaming.com09f326b2013-02-28 23:13:34 +00002026 return mDXT1TextureSupport;
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00002027}
2028
shannonwoods@chromium.org89200d92013-05-30 00:07:50 +00002029bool Renderer11::getDXT3TextureSupport() const
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00002030{
shannon.woods@transgaming.com09f326b2013-02-28 23:13:34 +00002031 return mDXT3TextureSupport;
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00002032}
2033
shannonwoods@chromium.org89200d92013-05-30 00:07:50 +00002034bool Renderer11::getDXT5TextureSupport() const
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00002035{
shannon.woods@transgaming.com09f326b2013-02-28 23:13:34 +00002036 return mDXT5TextureSupport;
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00002037}
2038
2039bool Renderer11::getDepthTextureSupport() const
2040{
shannon.woods@transgaming.comcf103f32013-02-28 23:18:45 +00002041 return mDepthTextureSupport;
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00002042}
2043
shannonwoods@chromium.org89200d92013-05-30 00:07:50 +00002044bool Renderer11::getFloat32TextureSupport() const
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00002045{
shannon.woods@transgaming.com9cdced62013-02-28 23:07:31 +00002046 return mFloat32TextureSupport;
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00002047}
2048
shannonwoods@chromium.org89200d92013-05-30 00:07:50 +00002049bool Renderer11::getFloat32TextureFilteringSupport() const
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00002050{
shannonwoods@chromium.org89200d92013-05-30 00:07:50 +00002051 return mFloat32FilterSupport;
2052}
2053
2054bool Renderer11::getFloat32TextureRenderingSupport() const
2055{
2056 return mFloat32RenderSupport;
2057}
2058
2059bool Renderer11::getFloat16TextureSupport() const
2060{
shannon.woods@transgaming.com9cdced62013-02-28 23:07:31 +00002061 return mFloat16TextureSupport;
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00002062}
2063
shannonwoods@chromium.org89200d92013-05-30 00:07:50 +00002064bool Renderer11::getFloat16TextureFilteringSupport() const
2065{
2066 return mFloat16FilterSupport;
2067}
2068
2069bool Renderer11::getFloat16TextureRenderingSupport() const
2070{
2071 return mFloat16RenderSupport;
2072}
2073
Geoff Langd42cf4e2013-06-05 16:09:17 -04002074bool Renderer11::getRGB565TextureSupport() const
2075{
2076 return false;
2077}
2078
shannonwoods@chromium.org89200d92013-05-30 00:07:50 +00002079bool Renderer11::getLuminanceTextureSupport() const
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00002080{
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00002081 return false;
2082}
2083
shannonwoods@chromium.org89200d92013-05-30 00:07:50 +00002084bool Renderer11::getLuminanceAlphaTextureSupport() const
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00002085{
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00002086 return false;
2087}
2088
2089bool Renderer11::getTextureFilterAnisotropySupport() const
2090{
shannon.woods@transgaming.com1abd7972013-02-28 23:06:58 +00002091 return true;
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00002092}
2093
2094float Renderer11::getTextureMaxAnisotropy() const
2095{
shannon.woods@transgaming.com1abd7972013-02-28 23:06:58 +00002096 switch (mFeatureLevel)
2097 {
2098 case D3D_FEATURE_LEVEL_11_0:
2099 return D3D11_MAX_MAXANISOTROPY;
2100 case D3D_FEATURE_LEVEL_10_1:
2101 case D3D_FEATURE_LEVEL_10_0:
2102 return D3D10_MAX_MAXANISOTROPY;
2103 default: UNREACHABLE();
2104 return 0;
2105 }
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00002106}
2107
shannonwoods@chromium.org89200d92013-05-30 00:07:50 +00002108bool Renderer11::getEventQuerySupport() const
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00002109{
shannon.woods@transgaming.combe58aa02013-02-28 23:03:55 +00002110 return true;
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00002111}
2112
shannon.woods@transgaming.com8ce2f8f2013-02-28 23:07:10 +00002113Range Renderer11::getViewportBounds() const
2114{
2115 switch (mFeatureLevel)
2116 {
2117 case D3D_FEATURE_LEVEL_11_0:
2118 return Range(D3D11_VIEWPORT_BOUNDS_MIN, D3D11_VIEWPORT_BOUNDS_MAX);
2119 case D3D_FEATURE_LEVEL_10_1:
2120 case D3D_FEATURE_LEVEL_10_0:
2121 return Range(D3D10_VIEWPORT_BOUNDS_MIN, D3D10_VIEWPORT_BOUNDS_MAX);
2122 default: UNREACHABLE();
2123 return Range(0, 0);
2124 }
2125}
2126
shannon.woods@transgaming.com233fe952013-01-25 21:51:57 +00002127unsigned int Renderer11::getMaxVertexTextureImageUnits() const
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00002128{
shannon.woods@transgaming.com233fe952013-01-25 21:51:57 +00002129 META_ASSERT(MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 <= gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS);
2130 switch (mFeatureLevel)
2131 {
2132 case D3D_FEATURE_LEVEL_11_0:
2133 case D3D_FEATURE_LEVEL_10_1:
2134 case D3D_FEATURE_LEVEL_10_0:
2135 return MAX_TEXTURE_IMAGE_UNITS_VTF_SM4;
2136 default: UNREACHABLE();
2137 return 0;
2138 }
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00002139}
2140
shannon.woods@transgaming.com76cd88c2013-01-25 21:54:36 +00002141unsigned int Renderer11::getMaxCombinedTextureImageUnits() const
2142{
2143 return gl::MAX_TEXTURE_IMAGE_UNITS + getMaxVertexTextureImageUnits();
2144}
2145
shannon.woods@transgaming.comd8136cb2013-02-28 23:14:44 +00002146unsigned int Renderer11::getReservedVertexUniformVectors() const
2147{
2148 return 0; // Driver uniforms are stored in a separate constant buffer
2149}
2150
2151unsigned int Renderer11::getReservedFragmentUniformVectors() const
2152{
2153 return 0; // Driver uniforms are stored in a separate constant buffer
2154}
2155
2156unsigned int Renderer11::getMaxVertexUniformVectors() const
shannon.woods@transgaming.com254317d2013-01-25 21:54:09 +00002157{
shannon.woods@transgaming.com4e482042013-01-25 21:54:18 +00002158 META_ASSERT(MAX_VERTEX_UNIFORM_VECTORS_D3D11 <= D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT);
2159 ASSERT(mFeatureLevel >= D3D_FEATURE_LEVEL_10_0);
2160 return MAX_VERTEX_UNIFORM_VECTORS_D3D11;
shannon.woods@transgaming.com254317d2013-01-25 21:54:09 +00002161}
2162
shannon.woods@transgaming.comd8136cb2013-02-28 23:14:44 +00002163unsigned int Renderer11::getMaxFragmentUniformVectors() const
shannon.woods@transgaming.com254317d2013-01-25 21:54:09 +00002164{
shannon.woods@transgaming.com4e482042013-01-25 21:54:18 +00002165 META_ASSERT(MAX_FRAGMENT_UNIFORM_VECTORS_D3D11 <= D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT);
2166 ASSERT(mFeatureLevel >= D3D_FEATURE_LEVEL_10_0);
2167 return MAX_FRAGMENT_UNIFORM_VECTORS_D3D11;
shannon.woods@transgaming.com254317d2013-01-25 21:54:09 +00002168}
2169
shannon.woods@transgaming.comd8136cb2013-02-28 23:14:44 +00002170unsigned int Renderer11::getMaxVaryingVectors() const
shannon.woods@transgaming.com28d268e2013-01-25 21:54:26 +00002171{
2172 META_ASSERT(gl::IMPLEMENTATION_MAX_VARYING_VECTORS == D3D11_VS_OUTPUT_REGISTER_COUNT);
shannonwoods@chromium.org74b86cf2013-05-30 00:02:58 +00002173 META_ASSERT(D3D11_VS_OUTPUT_REGISTER_COUNT <= D3D11_PS_INPUT_REGISTER_COUNT);
2174 META_ASSERT(D3D10_VS_OUTPUT_REGISTER_COUNT <= D3D10_PS_INPUT_REGISTER_COUNT);
shannon.woods@transgaming.com28d268e2013-01-25 21:54:26 +00002175 switch (mFeatureLevel)
2176 {
2177 case D3D_FEATURE_LEVEL_11_0:
2178 return D3D11_VS_OUTPUT_REGISTER_COUNT;
2179 case D3D_FEATURE_LEVEL_10_1:
2180 case D3D_FEATURE_LEVEL_10_0:
2181 return D3D10_VS_OUTPUT_REGISTER_COUNT;
2182 default: UNREACHABLE();
2183 return 0;
2184 }
2185}
2186
shannon.woods%transgaming.com@gtempaccount.com3f72ce32013-04-13 03:36:43 +00002187unsigned int Renderer11::getMaxVertexShaderUniformBuffers() const
2188{
shannon.woods%transgaming.com@gtempaccount.com34089352013-04-13 03:36:57 +00002189 META_ASSERT(gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS >= D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT &&
2190 gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS >= D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT);
2191
shannon.woods%transgaming.com@gtempaccount.com3f72ce32013-04-13 03:36:43 +00002192 switch (mFeatureLevel)
2193 {
2194 case D3D_FEATURE_LEVEL_11_0:
shannonwoods@chromium.org2b544222013-05-30 00:11:12 +00002195 return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - getReservedVertexUniformBuffers();
shannon.woods%transgaming.com@gtempaccount.com3f72ce32013-04-13 03:36:43 +00002196 case D3D_FEATURE_LEVEL_10_1:
2197 case D3D_FEATURE_LEVEL_10_0:
shannonwoods@chromium.org2b544222013-05-30 00:11:12 +00002198 return D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - getReservedVertexUniformBuffers();
shannon.woods%transgaming.com@gtempaccount.com3f72ce32013-04-13 03:36:43 +00002199 default: UNREACHABLE();
2200 return 0;
2201 }
2202}
2203
2204unsigned int Renderer11::getMaxFragmentShaderUniformBuffers() const
2205{
shannon.woods%transgaming.com@gtempaccount.com34089352013-04-13 03:36:57 +00002206 META_ASSERT(gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS >= D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT &&
2207 gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS >= D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT);
2208
shannon.woods%transgaming.com@gtempaccount.com3f72ce32013-04-13 03:36:43 +00002209 switch (mFeatureLevel)
2210 {
2211 case D3D_FEATURE_LEVEL_11_0:
shannonwoods@chromium.org2b544222013-05-30 00:11:12 +00002212 return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - getReservedFragmentUniformBuffers();
shannon.woods%transgaming.com@gtempaccount.com3f72ce32013-04-13 03:36:43 +00002213 case D3D_FEATURE_LEVEL_10_1:
2214 case D3D_FEATURE_LEVEL_10_0:
shannonwoods@chromium.org2b544222013-05-30 00:11:12 +00002215 return D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - getReservedFragmentUniformBuffers();
shannon.woods%transgaming.com@gtempaccount.com3f72ce32013-04-13 03:36:43 +00002216 default: UNREACHABLE();
2217 return 0;
2218 }
2219}
2220
shannonwoods@chromium.org2b544222013-05-30 00:11:12 +00002221unsigned int Renderer11::getReservedVertexUniformBuffers() const
2222{
2223 // we reserve one buffer for the application uniforms, and one for driver uniforms
2224 return 2;
2225}
2226
2227unsigned int Renderer11::getReservedFragmentUniformBuffers() const
2228{
2229 // we reserve one buffer for the application uniforms, and one for driver uniforms
2230 return 2;
2231}
2232
shannon.woods%transgaming.com@gtempaccount.com3f72ce32013-04-13 03:36:43 +00002233unsigned int Renderer11::getMaxTransformFeedbackBuffers() const
2234{
shannon.woods%transgaming.com@gtempaccount.com34089352013-04-13 03:36:57 +00002235 META_ASSERT(gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS >= D3D11_SO_BUFFER_SLOT_COUNT &&
2236 gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS >= D3D10_SO_BUFFER_SLOT_COUNT);
2237
shannon.woods%transgaming.com@gtempaccount.com3f72ce32013-04-13 03:36:43 +00002238 switch (mFeatureLevel)
2239 {
2240 case D3D_FEATURE_LEVEL_11_0:
2241 return D3D11_SO_BUFFER_SLOT_COUNT;
2242 case D3D_FEATURE_LEVEL_10_1:
2243 case D3D_FEATURE_LEVEL_10_0:
2244 return D3D10_SO_BUFFER_SLOT_COUNT;
2245 default: UNREACHABLE();
2246 return 0;
2247 }
2248}
2249
shannonwoods@chromium.org33e798f2013-05-30 00:05:05 +00002250unsigned int Renderer11::getMaxUniformBufferSize() const
2251{
2252 // Each component is a 4-element vector of 4-byte units (floats)
2253 const unsigned int bytesPerComponent = 4 * sizeof(float);
2254
2255 switch (mFeatureLevel)
2256 {
2257 case D3D_FEATURE_LEVEL_11_0:
2258 return D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * bytesPerComponent;
2259 case D3D_FEATURE_LEVEL_10_1:
2260 case D3D_FEATURE_LEVEL_10_0:
2261 return D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * bytesPerComponent;
2262 default: UNREACHABLE();
2263 return 0;
2264 }
2265}
2266
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00002267bool Renderer11::getNonPower2TextureSupport() const
2268{
shannon.woods@transgaming.com03951cf2013-01-25 21:57:01 +00002269 switch (mFeatureLevel)
2270 {
2271 case D3D_FEATURE_LEVEL_11_0:
2272 case D3D_FEATURE_LEVEL_10_1:
2273 case D3D_FEATURE_LEVEL_10_0:
2274 return true;
2275 default: UNREACHABLE();
2276 return false;
2277 }
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00002278}
2279
2280bool Renderer11::getOcclusionQuerySupport() const
2281{
shannon.woods@transgaming.com8b7606a2013-02-28 23:03:47 +00002282 switch (mFeatureLevel)
2283 {
2284 case D3D_FEATURE_LEVEL_11_0:
2285 case D3D_FEATURE_LEVEL_10_1:
2286 case D3D_FEATURE_LEVEL_10_0:
2287 return true;
2288 default: UNREACHABLE();
2289 return false;
2290 }
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00002291}
2292
2293bool Renderer11::getInstancingSupport() const
2294{
daniel@transgaming.comfe324642013-02-01 03:20:11 +00002295 switch (mFeatureLevel)
2296 {
2297 case D3D_FEATURE_LEVEL_11_0:
2298 case D3D_FEATURE_LEVEL_10_1:
2299 case D3D_FEATURE_LEVEL_10_0:
2300 return true;
2301 default: UNREACHABLE();
2302 return false;
2303 }
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00002304}
2305
2306bool Renderer11::getShareHandleSupport() const
2307{
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +00002308 // We only currently support share handles with BGRA surfaces, because
2309 // chrome needs BGRA. Once chrome fixes this, we should always support them.
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00002310 // PIX doesn't seem to support using share handles, so disable them.
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +00002311 return getBGRATextureSupport() && !gl::perfActive();
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00002312}
2313
daniel@transgaming.com7629bb62013-01-11 04:12:28 +00002314bool Renderer11::getDerivativeInstructionSupport() const
2315{
shannon.woods@transgaming.com09fd9452013-02-28 23:02:28 +00002316 switch (mFeatureLevel)
2317 {
2318 case D3D_FEATURE_LEVEL_11_0:
2319 case D3D_FEATURE_LEVEL_10_1:
2320 case D3D_FEATURE_LEVEL_10_0:
2321 return true;
2322 default: UNREACHABLE();
2323 return false;
2324 }
daniel@transgaming.com7629bb62013-01-11 04:12:28 +00002325}
2326
shannon.woods@transgaming.com8d2f0862013-02-28 23:09:19 +00002327bool Renderer11::getPostSubBufferSupport() const
2328{
2329 // D3D11 does not support present with dirty rectangles until D3D11.1 and DXGI 1.2.
2330 return false;
2331}
2332
daniel@transgaming.com9549bea2012-11-28 20:57:23 +00002333int Renderer11::getMajorShaderModel() const
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00002334{
daniel@transgaming.com9549bea2012-11-28 20:57:23 +00002335 switch (mFeatureLevel)
2336 {
2337 case D3D_FEATURE_LEVEL_11_0: return D3D11_SHADER_MAJOR_VERSION; // 5
daniel@transgaming.comca1ac1f2013-01-11 04:13:05 +00002338 case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SHADER_MAJOR_VERSION; // 4
daniel@transgaming.com9549bea2012-11-28 20:57:23 +00002339 case D3D_FEATURE_LEVEL_10_0: return D3D10_SHADER_MAJOR_VERSION; // 4
2340 default: UNREACHABLE(); return 0;
2341 }
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00002342}
2343
daniel@transgaming.comca1ac1f2013-01-11 04:13:05 +00002344int Renderer11::getMinorShaderModel() const
2345{
2346 switch (mFeatureLevel)
2347 {
2348 case D3D_FEATURE_LEVEL_11_0: return D3D11_SHADER_MINOR_VERSION; // 0
2349 case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SHADER_MINOR_VERSION; // 1
2350 case D3D_FEATURE_LEVEL_10_0: return D3D10_SHADER_MINOR_VERSION; // 0
2351 default: UNREACHABLE(); return 0;
2352 }
2353}
2354
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00002355float Renderer11::getMaxPointSize() const
2356{
shannon.woods@transgaming.com3e773bb2013-01-25 21:55:47 +00002357 // choose a reasonable maximum. we enforce this in the shader.
2358 // (nb: on a Radeon 2600xt, DX9 reports a 256 max point size)
2359 return 1024.0f;
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00002360}
2361
shannon.woods@transgaming.com8ce2f8f2013-02-28 23:07:10 +00002362int Renderer11::getMaxViewportDimension() const
2363{
shannon.woods@transgaming.comfd86c2c2013-02-28 23:13:07 +00002364 // Maximum viewport size must be at least as large as the largest render buffer (or larger).
2365 // In our case return the maximum texture size, which is the maximum render buffer size.
2366 META_ASSERT(D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION * 2 - 1 <= D3D11_VIEWPORT_BOUNDS_MAX);
2367 META_ASSERT(D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION * 2 - 1 <= D3D10_VIEWPORT_BOUNDS_MAX);
2368
shannon.woods@transgaming.com8ce2f8f2013-02-28 23:07:10 +00002369 switch (mFeatureLevel)
2370 {
2371 case D3D_FEATURE_LEVEL_11_0:
shannon.woods@transgaming.comfd86c2c2013-02-28 23:13:07 +00002372 return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 16384
shannon.woods@transgaming.com8ce2f8f2013-02-28 23:07:10 +00002373 case D3D_FEATURE_LEVEL_10_1:
2374 case D3D_FEATURE_LEVEL_10_0:
shannon.woods@transgaming.comfd86c2c2013-02-28 23:13:07 +00002375 return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 8192
shannon.woods@transgaming.com8ce2f8f2013-02-28 23:07:10 +00002376 default: UNREACHABLE();
2377 return 0;
2378 }
2379}
2380
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00002381int Renderer11::getMaxTextureWidth() const
2382{
daniel@transgaming.com25072f62012-11-28 19:31:32 +00002383 switch (mFeatureLevel)
2384 {
2385 case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 16384
2386 case D3D_FEATURE_LEVEL_10_1:
2387 case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 8192
2388 default: UNREACHABLE(); return 0;
2389 }
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00002390}
2391
2392int Renderer11::getMaxTextureHeight() const
2393{
daniel@transgaming.com25072f62012-11-28 19:31:32 +00002394 switch (mFeatureLevel)
2395 {
2396 case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 16384
2397 case D3D_FEATURE_LEVEL_10_1:
2398 case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 8192
2399 default: UNREACHABLE(); return 0;
2400 }
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00002401}
2402
shannon.woods%transgaming.com@gtempaccount.comc1fdf6b2013-04-13 03:44:41 +00002403int Renderer11::getMaxTextureDepth() const
2404{
2405 switch (mFeatureLevel)
2406 {
2407 case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION; // 2048
2408 case D3D_FEATURE_LEVEL_10_1:
2409 case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE3D_U_V_OR_W_DIMENSION; // 2048
2410 default: UNREACHABLE(); return 0;
2411 }
2412}
2413
shannon.woods%transgaming.com@gtempaccount.coma98a8112013-04-13 03:45:57 +00002414int Renderer11::getMaxTextureArrayLayers() const
2415{
2416 switch (mFeatureLevel)
2417 {
2418 case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION; // 2048
2419 case D3D_FEATURE_LEVEL_10_1:
2420 case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION; // 512
2421 default: UNREACHABLE(); return 0;
2422 }
2423}
2424
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00002425bool Renderer11::get32BitIndexSupport() const
2426{
daniel@transgaming.com25072f62012-11-28 19:31:32 +00002427 switch (mFeatureLevel)
2428 {
2429 case D3D_FEATURE_LEVEL_11_0:
2430 case D3D_FEATURE_LEVEL_10_1:
2431 case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP >= 32; // true
2432 default: UNREACHABLE(); return false;
2433 }
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00002434}
2435
2436int Renderer11::getMinSwapInterval() const
2437{
daniel@transgaming.com8c7b1a92012-11-28 19:34:06 +00002438 return 0;
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00002439}
2440
2441int Renderer11::getMaxSwapInterval() const
2442{
daniel@transgaming.com8c7b1a92012-11-28 19:34:06 +00002443 return 4;
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00002444}
2445
2446int Renderer11::getMaxSupportedSamples() const
2447{
shannon.woods@transgaming.comdf2fd572013-02-28 23:05:40 +00002448 return mMaxSupportedSamples;
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00002449}
2450
Geoff Lang0e120e32013-05-29 10:23:55 -04002451GLsizei Renderer11::getMaxSupportedFormatSamples(GLint internalFormat) const
2452{
2453 DXGI_FORMAT format = gl_d3d11::GetTexFormat(internalFormat, getCurrentClientVersion());
2454 MultisampleSupportMap::const_iterator iter = mMultisampleSupportMap.find(format);
2455 return (iter != mMultisampleSupportMap.end()) ? iter->second.maxSupportedSamples : 0;
2456}
2457
shannon.woods@transgaming.com88fbd0f2013-02-28 23:05:46 +00002458int Renderer11::getNearestSupportedSamples(DXGI_FORMAT format, unsigned int requested) const
2459{
2460 if (requested == 0)
2461 {
2462 return 0;
2463 }
2464
2465 MultisampleSupportMap::const_iterator iter = mMultisampleSupportMap.find(format);
2466 if (iter != mMultisampleSupportMap.end())
2467 {
2468 const MultisampleSupportInfo& info = iter->second;
2469 for (unsigned int i = requested - 1; i < D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; i++)
2470 {
2471 if (info.qualityLevels[i] > 0)
2472 {
2473 return i + 1;
2474 }
2475 }
2476 }
2477
2478 return -1;
2479}
2480
shannon.woods%transgaming.com@gtempaccount.comb290ac12013-04-13 03:28:15 +00002481unsigned int Renderer11::getMaxRenderTargets() const
2482{
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00002483 META_ASSERT(D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT <= gl::IMPLEMENTATION_MAX_DRAW_BUFFERS);
2484 META_ASSERT(D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT <= gl::IMPLEMENTATION_MAX_DRAW_BUFFERS);
2485
shannon.woods%transgaming.com@gtempaccount.comb290ac12013-04-13 03:28:15 +00002486 switch (mFeatureLevel)
2487 {
2488 case D3D_FEATURE_LEVEL_11_0:
2489 return D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; // 8
2490 case D3D_FEATURE_LEVEL_10_1:
2491 case D3D_FEATURE_LEVEL_10_0:
2492 return D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT; // 8
2493 default:
2494 UNREACHABLE();
2495 return 1;
2496 }
2497}
2498
daniel@transgaming.com87705f82012-12-20 21:10:45 +00002499bool Renderer11::copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source)
daniel@transgaming.comad6aee72012-11-28 19:33:42 +00002500{
daniel@transgaming.comb1c208f2013-01-11 04:06:49 +00002501 if (source && dest)
2502 {
2503 TextureStorage11_2D *source11 = TextureStorage11_2D::makeTextureStorage11_2D(source->getStorageInstance());
2504 TextureStorage11_2D *dest11 = TextureStorage11_2D::makeTextureStorage11_2D(dest->getStorageInstance());
2505
daniel@transgaming.come9cf5e72013-01-11 04:06:55 +00002506 mDeviceContext->CopyResource(dest11->getBaseTexture(), source11->getBaseTexture());
daniel@transgaming.comb1c208f2013-01-11 04:06:49 +00002507 return true;
2508 }
2509
daniel@transgaming.comad6aee72012-11-28 19:33:42 +00002510 return false;
2511}
2512
daniel@transgaming.com87705f82012-12-20 21:10:45 +00002513bool Renderer11::copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source)
daniel@transgaming.comad6aee72012-11-28 19:33:42 +00002514{
daniel@transgaming.comb1c208f2013-01-11 04:06:49 +00002515 if (source && dest)
2516 {
daniel@transgaming.come9cf5e72013-01-11 04:06:55 +00002517 TextureStorage11_Cube *source11 = TextureStorage11_Cube::makeTextureStorage11_Cube(source->getStorageInstance());
2518 TextureStorage11_Cube *dest11 = TextureStorage11_Cube::makeTextureStorage11_Cube(dest->getStorageInstance());
daniel@transgaming.comb1c208f2013-01-11 04:06:49 +00002519
daniel@transgaming.come9cf5e72013-01-11 04:06:55 +00002520 mDeviceContext->CopyResource(dest11->getBaseTexture(), source11->getBaseTexture());
daniel@transgaming.comb1c208f2013-01-11 04:06:49 +00002521 return true;
2522 }
2523
daniel@transgaming.comad6aee72012-11-28 19:33:42 +00002524 return false;
2525}
2526
shannon.woods%transgaming.com@gtempaccount.com414e82a2013-04-13 03:44:05 +00002527bool Renderer11::copyToRenderTarget(TextureStorageInterface3D *dest, TextureStorageInterface3D *source)
2528{
2529 if (source && dest)
2530 {
2531 TextureStorage11_3D *source11 = TextureStorage11_3D::makeTextureStorage11_3D(source->getStorageInstance());
2532 TextureStorage11_3D *dest11 = TextureStorage11_3D::makeTextureStorage11_3D(dest->getStorageInstance());
2533
2534 mDeviceContext->CopyResource(dest11->getBaseTexture(), source11->getBaseTexture());
2535 return true;
2536 }
2537
2538 return false;
2539}
2540
shannon.woods%transgaming.com@gtempaccount.com6c86bd52013-04-13 03:45:45 +00002541bool Renderer11::copyToRenderTarget(TextureStorageInterface2DArray *dest, TextureStorageInterface2DArray *source)
2542{
2543 if (source && dest)
2544 {
2545 TextureStorage11_2DArray *source11 = TextureStorage11_2DArray::makeTextureStorage11_2DArray(source->getStorageInstance());
2546 TextureStorage11_2DArray *dest11 = TextureStorage11_2DArray::makeTextureStorage11_2DArray(dest->getStorageInstance());
2547
2548 mDeviceContext->CopyResource(dest11->getBaseTexture(), source11->getBaseTexture());
2549 return true;
2550 }
2551
2552 return false;
2553}
2554
shannon.woods@transgaming.com664916b2013-01-25 21:50:32 +00002555bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
daniel@transgaming.com87705f82012-12-20 21:10:45 +00002556 GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level)
daniel@transgaming.com38380882012-11-28 19:36:39 +00002557{
shannon.woods%transgaming.com@gtempaccount.com89ae1132013-04-13 03:28:43 +00002558 gl::Renderbuffer *colorbuffer = framebuffer->getReadColorbuffer();
shannon.woods@transgaming.com9d971ff2013-01-25 21:50:53 +00002559 if (!colorbuffer)
2560 {
2561 ERR("Failed to retrieve the color buffer from the frame buffer.");
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +00002562 return gl::error(GL_OUT_OF_MEMORY, false);
shannon.woods@transgaming.com9d971ff2013-01-25 21:50:53 +00002563 }
2564
2565 RenderTarget11 *sourceRenderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget());
2566 if (!sourceRenderTarget)
2567 {
2568 ERR("Failed to retrieve the render target from the frame buffer.");
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +00002569 return gl::error(GL_OUT_OF_MEMORY, false);
shannon.woods@transgaming.com9d971ff2013-01-25 21:50:53 +00002570 }
2571
2572 ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView();
2573 if (!source)
2574 {
2575 ERR("Failed to retrieve the render target view from the render target.");
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +00002576 return gl::error(GL_OUT_OF_MEMORY, false);
shannon.woods@transgaming.com9d971ff2013-01-25 21:50:53 +00002577 }
2578
2579 TextureStorage11_2D *storage11 = TextureStorage11_2D::makeTextureStorage11_2D(storage->getStorageInstance());
2580 if (!storage11)
2581 {
2582 source->Release();
2583 ERR("Failed to retrieve the texture storage from the destination.");
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +00002584 return gl::error(GL_OUT_OF_MEMORY, false);
shannon.woods@transgaming.com9d971ff2013-01-25 21:50:53 +00002585 }
2586
2587 RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTarget(level));
2588 if (!destRenderTarget)
2589 {
2590 source->Release();
2591 ERR("Failed to retrieve the render target from the destination storage.");
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +00002592 return gl::error(GL_OUT_OF_MEMORY, false);
shannon.woods@transgaming.com9d971ff2013-01-25 21:50:53 +00002593 }
2594
2595 ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView();
2596 if (!dest)
2597 {
2598 source->Release();
2599 ERR("Failed to retrieve the render target view from the destination render target.");
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +00002600 return gl::error(GL_OUT_OF_MEMORY, false);
shannon.woods@transgaming.com9d971ff2013-01-25 21:50:53 +00002601 }
2602
Geoff Langb86b9792013-06-04 16:32:05 -04002603 gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1);
2604 gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1);
shannon.woods@transgaming.com9d971ff2013-01-25 21:50:53 +00002605
Geoff Langb86b9792013-06-04 16:32:05 -04002606 gl::Box destArea(xoffset, yoffset, 0, sourceRect.width, sourceRect.height, 1);
2607 gl::Extents destSize(destRenderTarget->getWidth(), destRenderTarget->getHeight(), 1);
shannonwoods@chromium.org7b61d5c2013-05-30 00:04:12 +00002608
Geoff Langb86b9792013-06-04 16:32:05 -04002609 // Use nearest filtering because source and destination are the same size for the direct
2610 // copy
2611 bool ret = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize,
2612 destFormat, GL_NEAREST);
shannon.woods@transgaming.com9d971ff2013-01-25 21:50:53 +00002613
2614 source->Release();
2615 dest->Release();
2616
2617 return ret;
daniel@transgaming.com38380882012-11-28 19:36:39 +00002618}
2619
shannon.woods@transgaming.com664916b2013-01-25 21:50:32 +00002620bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
daniel@transgaming.com87705f82012-12-20 21:10:45 +00002621 GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level)
daniel@transgaming.com38380882012-11-28 19:36:39 +00002622{
shannon.woods%transgaming.com@gtempaccount.com89ae1132013-04-13 03:28:43 +00002623 gl::Renderbuffer *colorbuffer = framebuffer->getReadColorbuffer();
shannon.woods@transgaming.com9d971ff2013-01-25 21:50:53 +00002624 if (!colorbuffer)
2625 {
2626 ERR("Failed to retrieve the color buffer from the frame buffer.");
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +00002627 return gl::error(GL_OUT_OF_MEMORY, false);
shannon.woods@transgaming.com9d971ff2013-01-25 21:50:53 +00002628 }
2629
2630 RenderTarget11 *sourceRenderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget());
2631 if (!sourceRenderTarget)
2632 {
2633 ERR("Failed to retrieve the render target from the frame buffer.");
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +00002634 return gl::error(GL_OUT_OF_MEMORY, false);
shannon.woods@transgaming.com9d971ff2013-01-25 21:50:53 +00002635 }
2636
2637 ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView();
2638 if (!source)
2639 {
2640 ERR("Failed to retrieve the render target view from the render target.");
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +00002641 return gl::error(GL_OUT_OF_MEMORY, false);
shannon.woods@transgaming.com9d971ff2013-01-25 21:50:53 +00002642 }
2643
2644 TextureStorage11_Cube *storage11 = TextureStorage11_Cube::makeTextureStorage11_Cube(storage->getStorageInstance());
2645 if (!storage11)
2646 {
2647 source->Release();
2648 ERR("Failed to retrieve the texture storage from the destination.");
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +00002649 return gl::error(GL_OUT_OF_MEMORY, false);
shannon.woods@transgaming.com9d971ff2013-01-25 21:50:53 +00002650 }
2651
Nicolas Capensb13f8662013-06-04 13:30:19 -04002652 RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTargetFace(target, level));
shannon.woods@transgaming.com9d971ff2013-01-25 21:50:53 +00002653 if (!destRenderTarget)
2654 {
2655 source->Release();
2656 ERR("Failed to retrieve the render target from the destination storage.");
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +00002657 return gl::error(GL_OUT_OF_MEMORY, false);
shannon.woods@transgaming.com9d971ff2013-01-25 21:50:53 +00002658 }
2659
2660 ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView();
2661 if (!dest)
2662 {
2663 source->Release();
2664 ERR("Failed to retrieve the render target view from the destination render target.");
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +00002665 return gl::error(GL_OUT_OF_MEMORY, false);
shannon.woods@transgaming.com9d971ff2013-01-25 21:50:53 +00002666 }
2667
Geoff Langb86b9792013-06-04 16:32:05 -04002668 gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1);
2669 gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1);
shannon.woods@transgaming.com9d971ff2013-01-25 21:50:53 +00002670
Geoff Langb86b9792013-06-04 16:32:05 -04002671 gl::Box destArea(xoffset, yoffset, 0, sourceRect.width, sourceRect.height, 1);
2672 gl::Extents destSize(destRenderTarget->getWidth(), destRenderTarget->getHeight(), 1);
shannonwoods@chromium.org7b61d5c2013-05-30 00:04:12 +00002673
Geoff Langb86b9792013-06-04 16:32:05 -04002674 // Use nearest filtering because source and destination are the same size for the direct
2675 // copy
2676 bool ret = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize,
2677 destFormat, GL_NEAREST);
shannon.woods@transgaming.com9d971ff2013-01-25 21:50:53 +00002678
2679 source->Release();
2680 dest->Release();
2681
2682 return ret;
2683}
2684
shannon.woods%transgaming.com@gtempaccount.com414e82a2013-04-13 03:44:05 +00002685bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
2686 GLint xoffset, GLint yoffset, GLint zOffset, TextureStorageInterface3D *storage, GLint level)
2687{
2688 gl::Renderbuffer *colorbuffer = framebuffer->getReadColorbuffer();
2689 if (!colorbuffer)
2690 {
2691 ERR("Failed to retrieve the color buffer from the frame buffer.");
2692 return gl::error(GL_OUT_OF_MEMORY, false);
2693 }
2694
2695 RenderTarget11 *sourceRenderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget());
2696 if (!sourceRenderTarget)
2697 {
2698 ERR("Failed to retrieve the render target from the frame buffer.");
2699 return gl::error(GL_OUT_OF_MEMORY, false);
2700 }
2701
2702 ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView();
2703 if (!source)
2704 {
2705 ERR("Failed to retrieve the render target view from the render target.");
2706 return gl::error(GL_OUT_OF_MEMORY, false);
2707 }
2708
2709 TextureStorage11_3D *storage11 = TextureStorage11_3D::makeTextureStorage11_3D(storage->getStorageInstance());
2710 if (!storage11)
2711 {
2712 source->Release();
2713 ERR("Failed to retrieve the texture storage from the destination.");
2714 return gl::error(GL_OUT_OF_MEMORY, false);
2715 }
2716
2717 RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTargetLayer(level, zOffset));
2718 if (!destRenderTarget)
2719 {
2720 source->Release();
2721 ERR("Failed to retrieve the render target from the destination storage.");
2722 return gl::error(GL_OUT_OF_MEMORY, false);
2723 }
2724
2725 ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView();
2726 if (!dest)
2727 {
2728 source->Release();
2729 ERR("Failed to retrieve the render target view from the destination render target.");
2730 return gl::error(GL_OUT_OF_MEMORY, false);
2731 }
2732
Geoff Langb86b9792013-06-04 16:32:05 -04002733 gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1);
2734 gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1);
shannon.woods%transgaming.com@gtempaccount.com414e82a2013-04-13 03:44:05 +00002735
Geoff Langb86b9792013-06-04 16:32:05 -04002736 gl::Box destArea(xoffset, yoffset, 0, sourceRect.width, sourceRect.height, 1);
2737 gl::Extents destSize(destRenderTarget->getWidth(), destRenderTarget->getHeight(), 1);
shannonwoods@chromium.org7b61d5c2013-05-30 00:04:12 +00002738
Geoff Langb86b9792013-06-04 16:32:05 -04002739 // Use nearest filtering because source and destination are the same size for the direct
2740 // copy
2741 bool ret = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize,
2742 destFormat, GL_NEAREST);
shannon.woods%transgaming.com@gtempaccount.com414e82a2013-04-13 03:44:05 +00002743
2744 source->Release();
2745 dest->Release();
2746
2747 return ret;
2748}
2749
shannon.woods%transgaming.com@gtempaccount.com6c86bd52013-04-13 03:45:45 +00002750bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
2751 GLint xoffset, GLint yoffset, GLint zOffset, TextureStorageInterface2DArray *storage, GLint level)
2752{
2753 gl::Renderbuffer *colorbuffer = framebuffer->getReadColorbuffer();
2754 if (!colorbuffer)
2755 {
2756 ERR("Failed to retrieve the color buffer from the frame buffer.");
2757 return gl::error(GL_OUT_OF_MEMORY, false);
2758 }
2759
2760 RenderTarget11 *sourceRenderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget());
2761 if (!sourceRenderTarget)
2762 {
2763 ERR("Failed to retrieve the render target from the frame buffer.");
2764 return gl::error(GL_OUT_OF_MEMORY, false);
2765 }
2766
2767 ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView();
2768 if (!source)
2769 {
2770 ERR("Failed to retrieve the render target view from the render target.");
2771 return gl::error(GL_OUT_OF_MEMORY, false);
2772 }
2773
2774 TextureStorage11_2DArray *storage11 = TextureStorage11_2DArray::makeTextureStorage11_2DArray(storage->getStorageInstance());
2775 if (!storage11)
2776 {
2777 source->Release();
2778 ERR("Failed to retrieve the texture storage from the destination.");
2779 return gl::error(GL_OUT_OF_MEMORY, false);
2780 }
2781
2782 RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTargetLayer(level, zOffset));
2783 if (!destRenderTarget)
2784 {
2785 source->Release();
2786 ERR("Failed to retrieve the render target from the destination storage.");
2787 return gl::error(GL_OUT_OF_MEMORY, false);
2788 }
2789
2790 ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView();
2791 if (!dest)
2792 {
2793 source->Release();
2794 ERR("Failed to retrieve the render target view from the destination render target.");
2795 return gl::error(GL_OUT_OF_MEMORY, false);
2796 }
2797
Geoff Langb86b9792013-06-04 16:32:05 -04002798 gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1);
2799 gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1);
shannon.woods%transgaming.com@gtempaccount.com6c86bd52013-04-13 03:45:45 +00002800
Geoff Langb86b9792013-06-04 16:32:05 -04002801 gl::Box destArea(xoffset, yoffset, 0, sourceRect.width, sourceRect.height, 1);
2802 gl::Extents destSize(destRenderTarget->getWidth(), destRenderTarget->getHeight(), 1);
shannonwoods@chromium.org7b61d5c2013-05-30 00:04:12 +00002803
Geoff Langb86b9792013-06-04 16:32:05 -04002804 // Use nearest filtering because source and destination are the same size for the direct
2805 // copy
2806 bool ret = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize,
2807 destFormat, GL_NEAREST);
shannon.woods%transgaming.com@gtempaccount.com6c86bd52013-04-13 03:45:45 +00002808
2809 source->Release();
2810 dest->Release();
2811
2812 return ret;
2813}
2814
shannon.woods%transgaming.com@gtempaccount.comba2744f2013-04-13 03:33:38 +00002815void Renderer11::unapplyRenderTargets()
2816{
2817 setOneTimeRenderTarget(NULL);
2818}
2819
2820void Renderer11::setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView)
2821{
2822 ID3D11RenderTargetView *rtvArray[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {NULL};
2823
2824 rtvArray[0] = renderTargetView;
2825
2826 mDeviceContext->OMSetRenderTargets(getMaxRenderTargets(), rtvArray, NULL);
2827
2828 // Do not preserve the serial for this one-time-use render target
2829 for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++)
2830 {
2831 mAppliedRenderTargetSerials[rtIndex] = 0;
2832 }
2833}
2834
daniel@transgaming.comf2423652012-11-28 20:53:50 +00002835RenderTarget *Renderer11::createRenderTarget(SwapChain *swapChain, bool depth)
2836{
shannon.woods@transgaming.com183408d2013-01-25 21:50:07 +00002837 SwapChain11 *swapChain11 = SwapChain11::makeSwapChain11(swapChain);
daniel@transgaming.comb6b27bc2012-11-28 20:54:30 +00002838 RenderTarget11 *renderTarget = NULL;
shannon.woods@transgaming.com8c6d9df2013-02-28 23:08:57 +00002839
daniel@transgaming.comb6b27bc2012-11-28 20:54:30 +00002840 if (depth)
2841 {
shannon.woods@transgaming.com8c6d9df2013-02-28 23:08:57 +00002842 // Note: depth stencil may be NULL for 0 sized surfaces
shannon.woods@transgaming.com7e232852013-02-28 23:06:15 +00002843 renderTarget = new RenderTarget11(this, swapChain11->getDepthStencil(),
2844 swapChain11->getDepthStencilTexture(), NULL,
shannonwoods@chromium.org7faf3ec2013-05-30 00:03:45 +00002845 swapChain11->getWidth(), swapChain11->getHeight(), 1);
daniel@transgaming.comb6b27bc2012-11-28 20:54:30 +00002846 }
2847 else
2848 {
shannon.woods@transgaming.com8c6d9df2013-02-28 23:08:57 +00002849 // Note: render target may be NULL for 0 sized surfaces
shannon.woods@transgaming.com183408d2013-01-25 21:50:07 +00002850 renderTarget = new RenderTarget11(this, swapChain11->getRenderTarget(),
shannon.woods@transgaming.com7e232852013-02-28 23:06:15 +00002851 swapChain11->getOffscreenTexture(),
shannon.woods@transgaming.com183408d2013-01-25 21:50:07 +00002852 swapChain11->getRenderTargetShaderResource(),
shannonwoods@chromium.org7faf3ec2013-05-30 00:03:45 +00002853 swapChain11->getWidth(), swapChain11->getHeight(), 1);
daniel@transgaming.comb6b27bc2012-11-28 20:54:30 +00002854 }
2855 return renderTarget;
daniel@transgaming.comf2423652012-11-28 20:53:50 +00002856}
2857
2858RenderTarget *Renderer11::createRenderTarget(int width, int height, GLenum format, GLsizei samples, bool depth)
2859{
daniel@transgaming.comc9a501d2013-01-11 04:08:46 +00002860 RenderTarget11 *renderTarget = new RenderTarget11(this, width, height, format, samples, depth);
2861 return renderTarget;
daniel@transgaming.comf2423652012-11-28 20:53:50 +00002862}
2863
shannon.woods@transgaming.com69ff7762013-01-25 21:55:24 +00002864ShaderExecutable *Renderer11::loadExecutable(const void *function, size_t length, rx::ShaderType type)
daniel@transgaming.com55318902012-11-28 20:58:58 +00002865{
daniel@transgaming.coma2f9fbe2012-11-28 21:03:40 +00002866 ShaderExecutable11 *executable = NULL;
2867
2868 switch (type)
2869 {
shannon.woods@transgaming.com69ff7762013-01-25 21:55:24 +00002870 case rx::SHADER_VERTEX:
daniel@transgaming.coma2f9fbe2012-11-28 21:03:40 +00002871 {
2872 ID3D11VertexShader *vshader = NULL;
2873 HRESULT result = mDevice->CreateVertexShader(function, length, NULL, &vshader);
2874 ASSERT(SUCCEEDED(result));
2875
2876 if (vshader)
2877 {
daniel@transgaming.com7b18d0c2012-11-28 21:04:10 +00002878 executable = new ShaderExecutable11(function, length, vshader);
daniel@transgaming.coma2f9fbe2012-11-28 21:03:40 +00002879 }
2880 }
2881 break;
shannon.woods@transgaming.com69ff7762013-01-25 21:55:24 +00002882 case rx::SHADER_PIXEL:
daniel@transgaming.coma2f9fbe2012-11-28 21:03:40 +00002883 {
2884 ID3D11PixelShader *pshader = NULL;
2885 HRESULT result = mDevice->CreatePixelShader(function, length, NULL, &pshader);
2886 ASSERT(SUCCEEDED(result));
2887
2888 if (pshader)
2889 {
daniel@transgaming.com7b18d0c2012-11-28 21:04:10 +00002890 executable = new ShaderExecutable11(function, length, pshader);
daniel@transgaming.coma2f9fbe2012-11-28 21:03:40 +00002891 }
2892 }
2893 break;
shannon.woods@transgaming.com3e773bb2013-01-25 21:55:47 +00002894 case rx::SHADER_GEOMETRY:
2895 {
2896 ID3D11GeometryShader *gshader = NULL;
2897 HRESULT result = mDevice->CreateGeometryShader(function, length, NULL, &gshader);
2898 ASSERT(SUCCEEDED(result));
2899
2900 if (gshader)
2901 {
2902 executable = new ShaderExecutable11(function, length, gshader);
2903 }
2904 }
2905 break;
daniel@transgaming.coma2f9fbe2012-11-28 21:03:40 +00002906 default:
2907 UNREACHABLE();
2908 break;
2909 }
2910
2911 return executable;
daniel@transgaming.com55318902012-11-28 20:58:58 +00002912}
2913
shannon.woods@transgaming.com69ff7762013-01-25 21:55:24 +00002914ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type)
daniel@transgaming.coma9c71422012-11-28 20:58:45 +00002915{
daniel@transgaming.com071ee6a2012-11-28 21:03:21 +00002916 const char *profile = NULL;
2917
2918 switch (type)
2919 {
shannon.woods@transgaming.com69ff7762013-01-25 21:55:24 +00002920 case rx::SHADER_VERTEX:
daniel@transgaming.com071ee6a2012-11-28 21:03:21 +00002921 profile = "vs_4_0";
2922 break;
shannon.woods@transgaming.com69ff7762013-01-25 21:55:24 +00002923 case rx::SHADER_PIXEL:
daniel@transgaming.com071ee6a2012-11-28 21:03:21 +00002924 profile = "ps_4_0";
2925 break;
shannon.woods@transgaming.com3e773bb2013-01-25 21:55:47 +00002926 case rx::SHADER_GEOMETRY:
2927 profile = "gs_4_0";
2928 break;
daniel@transgaming.com071ee6a2012-11-28 21:03:21 +00002929 default:
2930 UNREACHABLE();
2931 return NULL;
2932 }
2933
shannon.woods@transgaming.comd3d42082013-02-28 23:14:31 +00002934 ID3DBlob *binary = (ID3DBlob*)compileToBinary(infoLog, shaderHLSL, profile, D3DCOMPILE_OPTIMIZATION_LEVEL0, false);
daniel@transgaming.com071ee6a2012-11-28 21:03:21 +00002935 if (!binary)
2936 return NULL;
2937
daniel@transgaming.com2275f912012-12-20 21:13:22 +00002938 ShaderExecutable *executable = loadExecutable((DWORD *)binary->GetBufferPointer(), binary->GetBufferSize(), type);
daniel@transgaming.com071ee6a2012-11-28 21:03:21 +00002939 binary->Release();
2940
2941 return executable;
2942}
2943
daniel@transgaming.com3f255b42012-12-20 21:07:35 +00002944VertexBuffer *Renderer11::createVertexBuffer()
2945{
daniel@transgaming.com2c4d0702012-12-20 21:08:51 +00002946 return new VertexBuffer11(this);
daniel@transgaming.com3f255b42012-12-20 21:07:35 +00002947}
2948
daniel@transgaming.com0b6d7742012-12-20 21:09:47 +00002949IndexBuffer *Renderer11::createIndexBuffer()
2950{
daniel@transgaming.com11c2af52012-12-20 21:10:01 +00002951 return new IndexBuffer11(this);
shannon.woods@transgaming.comcfe787e2013-02-28 23:03:35 +00002952}
2953
shannon.woods@transgaming.com4e52b632013-02-28 23:08:01 +00002954BufferStorage *Renderer11::createBufferStorage()
2955{
2956 return new BufferStorage11(this);
2957}
2958
shannon.woods@transgaming.comcfe787e2013-02-28 23:03:35 +00002959QueryImpl *Renderer11::createQuery(GLenum type)
2960{
shannon.woods@transgaming.com8b7606a2013-02-28 23:03:47 +00002961 return new Query11(this, type);
shannon.woods@transgaming.comcfe787e2013-02-28 23:03:35 +00002962}
2963
2964FenceImpl *Renderer11::createFence()
2965{
shannon.woods@transgaming.combe58aa02013-02-28 23:03:55 +00002966 return new Fence11(this);
daniel@transgaming.com0b6d7742012-12-20 21:09:47 +00002967}
2968
shannon.woods%transgaming.com@gtempaccount.com00e3f0c2013-04-13 03:31:02 +00002969bool Renderer11::getRenderTargetResource(gl::Renderbuffer *colorbuffer, unsigned int *subresourceIndex, ID3D11Texture2D **resource)
shannon.woods@transgaming.comfdeacb82013-01-25 21:52:34 +00002970{
shannon.woods%transgaming.com@gtempaccount.com00e3f0c2013-04-13 03:31:02 +00002971 ASSERT(colorbuffer != NULL);
2972
2973 RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget());
2974 if (renderTarget)
shannon.woods@transgaming.comfdeacb82013-01-25 21:52:34 +00002975 {
shannon.woods%transgaming.com@gtempaccount.com00e3f0c2013-04-13 03:31:02 +00002976 *subresourceIndex = renderTarget->getSubresourceIndex();
2977
2978 ID3D11RenderTargetView *colorBufferRTV = renderTarget->getRenderTargetView();
2979 if (colorBufferRTV)
shannon.woods@transgaming.comfdeacb82013-01-25 21:52:34 +00002980 {
shannon.woods%transgaming.com@gtempaccount.com00e3f0c2013-04-13 03:31:02 +00002981 ID3D11Resource *textureResource = NULL;
2982 colorBufferRTV->GetResource(&textureResource);
2983 colorBufferRTV->Release();
shannon.woods@transgaming.comfdeacb82013-01-25 21:52:34 +00002984
shannon.woods%transgaming.com@gtempaccount.com00e3f0c2013-04-13 03:31:02 +00002985 if (textureResource)
shannon.woods@transgaming.comfdeacb82013-01-25 21:52:34 +00002986 {
shannon.woods%transgaming.com@gtempaccount.com00e3f0c2013-04-13 03:31:02 +00002987 HRESULT result = textureResource->QueryInterface(IID_ID3D11Texture2D, (void**)resource);
2988 textureResource->Release();
shannon.woods@transgaming.comfdeacb82013-01-25 21:52:34 +00002989
shannon.woods%transgaming.com@gtempaccount.com00e3f0c2013-04-13 03:31:02 +00002990 if (SUCCEEDED(result))
shannon.woods@transgaming.comfdeacb82013-01-25 21:52:34 +00002991 {
shannon.woods%transgaming.com@gtempaccount.com00e3f0c2013-04-13 03:31:02 +00002992 return true;
2993 }
2994 else
2995 {
2996 ERR("Failed to extract the ID3D11Texture2D from the render target resource, "
2997 "HRESULT: 0x%X.", result);
shannon.woods@transgaming.comfdeacb82013-01-25 21:52:34 +00002998 }
2999 }
3000 }
3001 }
3002
3003 return false;
3004}
3005
shannon.woods@transgaming.comea4a0c62013-02-28 23:06:29 +00003006bool Renderer11::blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect,
daniel@transgaming.com6c872172012-11-28 19:39:33 +00003007 bool blitRenderTarget, bool blitDepthStencil)
3008{
shannon.woods%transgaming.com@gtempaccount.com1d64b622013-04-13 03:33:53 +00003009 if (blitRenderTarget)
shannon.woods@transgaming.com1e1deda2013-02-28 23:06:23 +00003010 {
shannon.woods%transgaming.com@gtempaccount.com1d64b622013-04-13 03:33:53 +00003011 gl::Renderbuffer *readBuffer = readTarget->getReadColorbuffer();
shannon.woods%transgaming.com@gtempaccount.com1d64b622013-04-13 03:33:53 +00003012
3013 if (!readBuffer)
3014 {
3015 ERR("Failed to retrieve the read buffer from the read framebuffer.");
3016 return gl::error(GL_OUT_OF_MEMORY, false);
3017 }
3018
shannon.woods%transgaming.com@gtempaccount.com1d64b622013-04-13 03:33:53 +00003019 RenderTarget *readRenderTarget = readBuffer->getRenderTarget();
shannon.woods%transgaming.com@gtempaccount.com1d64b622013-04-13 03:33:53 +00003020
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +00003021 for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
shannon.woods%transgaming.com@gtempaccount.com1d64b622013-04-13 03:33:53 +00003022 {
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +00003023 if (drawTarget->isEnabledColorAttachment(colorAttachment))
3024 {
3025 gl::Renderbuffer *drawBuffer = drawTarget->getColorbuffer(colorAttachment);
3026
3027 if (!drawBuffer)
3028 {
3029 ERR("Failed to retrieve the draw buffer from the draw framebuffer.");
3030 return gl::error(GL_OUT_OF_MEMORY, false);
3031 }
3032
3033 RenderTarget *drawRenderTarget = drawBuffer->getRenderTarget();
3034
shannon.woods%transgaming.com@gtempaccount.com86df5a42013-04-13 03:34:07 +00003035 if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, false))
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +00003036 {
3037 return false;
3038 }
3039 }
shannon.woods%transgaming.com@gtempaccount.com1d64b622013-04-13 03:33:53 +00003040 }
shannon.woods@transgaming.com1e1deda2013-02-28 23:06:23 +00003041 }
3042
shannon.woods%transgaming.com@gtempaccount.com1d64b622013-04-13 03:33:53 +00003043 if (blitDepthStencil)
shannon.woods@transgaming.com1e1deda2013-02-28 23:06:23 +00003044 {
shannon.woods%transgaming.com@gtempaccount.com1d64b622013-04-13 03:33:53 +00003045 gl::Renderbuffer *readBuffer = readTarget->getDepthOrStencilbuffer();
3046 gl::Renderbuffer *drawBuffer = drawTarget->getDepthOrStencilbuffer();
3047
3048 if (!readBuffer)
3049 {
3050 ERR("Failed to retrieve the read depth-stencil buffer from the read framebuffer.");
3051 return gl::error(GL_OUT_OF_MEMORY, false);
3052 }
3053
3054 if (!drawBuffer)
3055 {
3056 ERR("Failed to retrieve the draw depth-stencil buffer from the draw framebuffer.");
3057 return gl::error(GL_OUT_OF_MEMORY, false);
3058 }
3059
3060 RenderTarget *readRenderTarget = readBuffer->getDepthStencil();
3061 RenderTarget *drawRenderTarget = drawBuffer->getDepthStencil();
3062
shannon.woods%transgaming.com@gtempaccount.com86df5a42013-04-13 03:34:07 +00003063 if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, true))
shannon.woods%transgaming.com@gtempaccount.com1d64b622013-04-13 03:33:53 +00003064 {
3065 return false;
3066 }
shannon.woods@transgaming.com1e1deda2013-02-28 23:06:23 +00003067 }
3068
3069 return true;
daniel@transgaming.com6c872172012-11-28 19:39:33 +00003070}
3071
3072void Renderer11::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type,
3073 GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels)
3074{
daniel@transgaming.comee42a0a2013-01-11 04:09:15 +00003075 ID3D11Texture2D *colorBufferTexture = NULL;
daniel@transgaming.com2eb7ab72013-01-11 04:10:21 +00003076 unsigned int subresourceIndex = 0;
daniel@transgaming.comee42a0a2013-01-11 04:09:15 +00003077
shannon.woods%transgaming.com@gtempaccount.com00e3f0c2013-04-13 03:31:02 +00003078 gl::Renderbuffer *colorbuffer = framebuffer->getReadColorbuffer();
3079
3080 if (colorbuffer && getRenderTargetResource(colorbuffer, &subresourceIndex, &colorBufferTexture))
daniel@transgaming.comee42a0a2013-01-11 04:09:15 +00003081 {
3082 gl::Rectangle area;
3083 area.x = x;
3084 area.y = y;
3085 area.width = width;
3086 area.height = height;
3087
daniel@transgaming.com2eb7ab72013-01-11 04:10:21 +00003088 readTextureData(colorBufferTexture, subresourceIndex, area, format, type, outputPitch,
3089 packReverseRowOrder, packAlignment, pixels);
daniel@transgaming.comee42a0a2013-01-11 04:09:15 +00003090
3091 colorBufferTexture->Release();
3092 colorBufferTexture = NULL;
3093 }
daniel@transgaming.com6c872172012-11-28 19:39:33 +00003094}
3095
daniel@transgaming.com244e1832012-12-20 20:52:35 +00003096Image *Renderer11::createImage()
3097{
daniel@transgaming.coma8aac672012-12-20 21:08:00 +00003098 return new Image11();
daniel@transgaming.com244e1832012-12-20 20:52:35 +00003099}
3100
daniel@transgaming.comf721fdb2012-12-20 20:53:11 +00003101void Renderer11::generateMipmap(Image *dest, Image *src)
3102{
shannon.woods@transgaming.com2b132f42013-01-25 21:52:47 +00003103 Image11 *dest11 = Image11::makeImage11(dest);
3104 Image11 *src11 = Image11::makeImage11(src);
3105 Image11::generateMipmap(dest11, src11);
daniel@transgaming.comf721fdb2012-12-20 20:53:11 +00003106}
3107
daniel@transgaming.com413d2712012-12-20 21:11:04 +00003108TextureStorage *Renderer11::createTextureStorage2D(SwapChain *swapChain)
3109{
daniel@transgaming.com36670db2013-01-11 04:08:22 +00003110 SwapChain11 *swapChain11 = SwapChain11::makeSwapChain11(swapChain);
3111 return new TextureStorage11_2D(this, swapChain11);
daniel@transgaming.com413d2712012-12-20 21:11:04 +00003112}
3113
3114TextureStorage *Renderer11::createTextureStorage2D(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height)
3115{
daniel@transgaming.com36670db2013-01-11 04:08:22 +00003116 return new TextureStorage11_2D(this, levels, internalformat, usage, forceRenderable, width, height);
daniel@transgaming.com413d2712012-12-20 21:11:04 +00003117}
3118
3119TextureStorage *Renderer11::createTextureStorageCube(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size)
3120{
daniel@transgaming.com36670db2013-01-11 04:08:22 +00003121 return new TextureStorage11_Cube(this, levels, internalformat, usage, forceRenderable, size);
daniel@transgaming.com413d2712012-12-20 21:11:04 +00003122}
3123
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +00003124TextureStorage *Renderer11::createTextureStorage3D(int levels, GLenum internalformat, GLenum usage, GLsizei width, GLsizei height, GLsizei depth)
3125{
3126 return new TextureStorage11_3D(this, levels, internalformat, usage, width, height, depth);
3127}
3128
shannon.woods%transgaming.com@gtempaccount.com6c86bd52013-04-13 03:45:45 +00003129TextureStorage *Renderer11::createTextureStorage2DArray(int levels, GLenum internalformat, GLenum usage, GLsizei width, GLsizei height, GLsizei depth)
3130{
3131 return new TextureStorage11_2DArray(this, levels, internalformat, usage, width, height, depth);
3132}
3133
daniel@transgaming.comee42a0a2013-01-11 04:09:15 +00003134void Renderer11::readTextureData(ID3D11Texture2D *texture, unsigned int subResource, const gl::Rectangle &area,
3135 GLenum format, GLenum type, GLsizei outputPitch, bool packReverseRowOrder,
3136 GLint packAlignment, void *pixels)
3137{
3138 D3D11_TEXTURE2D_DESC textureDesc;
3139 texture->GetDesc(&textureDesc);
3140
3141 D3D11_TEXTURE2D_DESC stagingDesc;
3142 stagingDesc.Width = area.width;
3143 stagingDesc.Height = area.height;
3144 stagingDesc.MipLevels = 1;
3145 stagingDesc.ArraySize = 1;
3146 stagingDesc.Format = textureDesc.Format;
3147 stagingDesc.SampleDesc.Count = 1;
3148 stagingDesc.SampleDesc.Quality = 0;
3149 stagingDesc.Usage = D3D11_USAGE_STAGING;
3150 stagingDesc.BindFlags = 0;
3151 stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
3152 stagingDesc.MiscFlags = 0;
3153
3154 ID3D11Texture2D* stagingTex = NULL;
3155 HRESULT result = mDevice->CreateTexture2D(&stagingDesc, NULL, &stagingTex);
3156 if (FAILED(result))
3157 {
3158 ERR("Failed to create staging texture for readPixels, HRESULT: 0x%X.", result);
3159 return;
3160 }
3161
3162 ID3D11Texture2D* srcTex = NULL;
3163 if (textureDesc.SampleDesc.Count > 1)
3164 {
3165 D3D11_TEXTURE2D_DESC resolveDesc;
3166 resolveDesc.Width = textureDesc.Width;
3167 resolveDesc.Height = textureDesc.Height;
3168 resolveDesc.MipLevels = 1;
3169 resolveDesc.ArraySize = 1;
3170 resolveDesc.Format = textureDesc.Format;
3171 resolveDesc.SampleDesc.Count = 1;
3172 resolveDesc.SampleDesc.Quality = 0;
3173 resolveDesc.Usage = D3D11_USAGE_DEFAULT;
3174 resolveDesc.BindFlags = 0;
3175 resolveDesc.CPUAccessFlags = 0;
3176 resolveDesc.MiscFlags = 0;
3177
3178 result = mDevice->CreateTexture2D(&resolveDesc, NULL, &srcTex);
3179 if (FAILED(result))
3180 {
3181 ERR("Failed to create resolve texture for readPixels, HRESULT: 0x%X.", result);
3182 stagingTex->Release();
3183 return;
3184 }
3185
3186 mDeviceContext->ResolveSubresource(srcTex, 0, texture, subResource, textureDesc.Format);
3187 subResource = 0;
3188 }
3189 else
3190 {
3191 srcTex = texture;
3192 srcTex->AddRef();
3193 }
3194
3195 D3D11_BOX srcBox;
3196 srcBox.left = area.x;
3197 srcBox.right = area.x + area.width;
3198 srcBox.top = area.y;
3199 srcBox.bottom = area.y + area.height;
3200 srcBox.front = 0;
3201 srcBox.back = 1;
3202
3203 mDeviceContext->CopySubresourceRegion(stagingTex, 0, 0, 0, 0, srcTex, subResource, &srcBox);
3204
3205 srcTex->Release();
3206 srcTex = NULL;
3207
3208 D3D11_MAPPED_SUBRESOURCE mapping;
3209 mDeviceContext->Map(stagingTex, 0, D3D11_MAP_READ, 0, &mapping);
3210
3211 unsigned char *source;
3212 int inputPitch;
3213 if (packReverseRowOrder)
3214 {
3215 source = static_cast<unsigned char*>(mapping.pData) + mapping.RowPitch * (area.height - 1);
3216 inputPitch = -static_cast<int>(mapping.RowPitch);
3217 }
3218 else
3219 {
3220 source = static_cast<unsigned char*>(mapping.pData);
3221 inputPitch = static_cast<int>(mapping.RowPitch);
3222 }
3223
Geoff Lang697ad3e2013-06-04 10:11:28 -04003224 GLuint clientVersion = getCurrentClientVersion();
shannon.woods%transgaming.com@gtempaccount.com676dc8f2013-04-13 03:35:13 +00003225
Geoff Lang697ad3e2013-06-04 10:11:28 -04003226 GLint sourceInternalFormat = d3d11_gl::GetInternalFormat(textureDesc.Format);
3227 GLenum sourceFormat = gl::GetFormat(sourceInternalFormat, clientVersion);
3228 GLenum sourceType = gl::GetType(sourceInternalFormat, clientVersion);
3229
3230 GLuint sourcePixelSize = gl::GetPixelBytes(sourceInternalFormat, clientVersion);
3231
3232 if (sourceFormat == format && sourceType == type)
3233 {
3234 // Direct copy possible
3235 unsigned char *dest = static_cast<unsigned char*>(pixels);
3236 for (int y = 0; y < area.height; y++)
shannon.woods%transgaming.com@gtempaccount.com676dc8f2013-04-13 03:35:13 +00003237 {
Geoff Lang697ad3e2013-06-04 10:11:28 -04003238 memcpy(dest + y * outputPitch, source + y * inputPitch, area.width * sourcePixelSize);
shannon.woods%transgaming.com@gtempaccount.com676dc8f2013-04-13 03:35:13 +00003239 }
3240 }
daniel@transgaming.comee42a0a2013-01-11 04:09:15 +00003241 else
3242 {
Geoff Lang697ad3e2013-06-04 10:11:28 -04003243 GLint destInternalFormat = gl::GetSizedInternalFormat(format, type, clientVersion);
3244 GLuint destPixelSize = gl::GetPixelBytes(destInternalFormat, clientVersion);
3245
3246 ColorCopyFunction fastCopyFunc = d3d11::GetFastCopyFunction(textureDesc.Format, format, type, getCurrentClientVersion());
3247 if (fastCopyFunc)
daniel@transgaming.comee42a0a2013-01-11 04:09:15 +00003248 {
Geoff Lang697ad3e2013-06-04 10:11:28 -04003249 // Fast copy is possible through some special function
3250 for (int y = 0; y < area.height; y++)
daniel@transgaming.comee42a0a2013-01-11 04:09:15 +00003251 {
Geoff Lang697ad3e2013-06-04 10:11:28 -04003252 for (int x = 0; x < area.width; x++)
3253 {
3254 void *dest = static_cast<unsigned char*>(pixels) + y * outputPitch + x * destPixelSize;
3255 void *src = static_cast<unsigned char*>(source) + y * inputPitch + x * sourcePixelSize;
3256
3257 fastCopyFunc(src, dest);
3258 }
3259 }
3260 }
3261 else
3262 {
3263 ColorReadFunction readFunc = d3d11::GetColorReadFunction(textureDesc.Format);
3264 ColorWriteFunction writeFunc = gl::GetColorWriteFunction(format, type, clientVersion);
3265
3266 unsigned char temp[16]; // Maximum size of any Color<T> type used.
3267 META_ASSERT(sizeof(temp) >= sizeof(gl::ColorF) &&
3268 sizeof(temp) >= sizeof(gl::ColorUI) &&
3269 sizeof(temp) >= sizeof(gl::ColorI));
3270
3271 for (int y = 0; y < area.height; y++)
3272 {
3273 for (int x = 0; x < area.width; x++)
3274 {
3275 void *dest = static_cast<unsigned char*>(pixels) + y * outputPitch + x * destPixelSize;
3276 void *src = static_cast<unsigned char*>(source) + y * inputPitch + x * sourcePixelSize;
3277
3278 // readFunc and writeFunc will be using the same type of color, CopyTexImage
3279 // will not allow the copy otherwise.
3280 readFunc(src, temp);
3281 writeFunc(temp, dest);
3282 }
daniel@transgaming.comee42a0a2013-01-11 04:09:15 +00003283 }
3284 }
3285 }
3286
3287 mDeviceContext->Unmap(stagingTex, 0);
3288
3289 stagingTex->Release();
3290 stagingTex = NULL;
3291}
3292
shannon.woods%transgaming.com@gtempaccount.com86df5a42013-04-13 03:34:07 +00003293bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget,
3294 RenderTarget *drawRenderTarget, bool wholeBufferCopy)
shannon.woods@transgaming.com1e1deda2013-02-28 23:06:23 +00003295{
3296 ASSERT(readRect.width == drawRect.width && readRect.height == drawRect.height);
3297
shannon.woods%transgaming.com@gtempaccount.com1d64b622013-04-13 03:33:53 +00003298 RenderTarget11 *readRenderTarget11 = RenderTarget11::makeRenderTarget11(readRenderTarget);
3299 if (!readRenderTarget)
shannon.woods@transgaming.com1e1deda2013-02-28 23:06:23 +00003300 {
shannon.woods%transgaming.com@gtempaccount.com1d64b622013-04-13 03:33:53 +00003301 ERR("Failed to retrieve the read render target from the read framebuffer.");
shannon.woods@transgaming.comea4a0c62013-02-28 23:06:29 +00003302 return gl::error(GL_OUT_OF_MEMORY, false);
shannon.woods@transgaming.com1e1deda2013-02-28 23:06:23 +00003303 }
3304
shannon.woods%transgaming.com@gtempaccount.com27ac40e2013-04-13 03:43:17 +00003305 ID3D11Resource *readTexture = NULL;
shannon.woods%transgaming.com@gtempaccount.com1d64b622013-04-13 03:33:53 +00003306 unsigned int readSubresource = 0;
3307 if (readRenderTarget->getSamples() > 0)
shannon.woods@transgaming.com1e1deda2013-02-28 23:06:23 +00003308 {
shannon.woods%transgaming.com@gtempaccount.com27ac40e2013-04-13 03:43:17 +00003309 ID3D11Resource *unresolvedResource = readRenderTarget11->getTexture();
3310 ID3D11Texture2D *unresolvedTexture = d3d11::DynamicCastComObject<ID3D11Texture2D>(unresolvedResource);
3311 unresolvedResource->Release();
shannon.woods@transgaming.com1e1deda2013-02-28 23:06:23 +00003312
shannon.woods%transgaming.com@gtempaccount.com27ac40e2013-04-13 03:43:17 +00003313 if (unresolvedTexture)
3314 {
3315 readTexture = resolveMultisampledTexture(unresolvedTexture, readRenderTarget11->getSubresourceIndex());
3316 readSubresource = 0;
shannon.woods@transgaming.com1e1deda2013-02-28 23:06:23 +00003317
shannon.woods%transgaming.com@gtempaccount.com27ac40e2013-04-13 03:43:17 +00003318 unresolvedTexture->Release();
3319 }
shannon.woods@transgaming.com1e1deda2013-02-28 23:06:23 +00003320 }
3321 else
3322 {
shannon.woods%transgaming.com@gtempaccount.com1d64b622013-04-13 03:33:53 +00003323 readTexture = readRenderTarget11->getTexture();
3324 readSubresource = readRenderTarget11->getSubresourceIndex();
shannon.woods@transgaming.com1e1deda2013-02-28 23:06:23 +00003325 }
3326
shannon.woods%transgaming.com@gtempaccount.com1d64b622013-04-13 03:33:53 +00003327 if (!readTexture)
shannon.woods@transgaming.com1e1deda2013-02-28 23:06:23 +00003328 {
shannon.woods%transgaming.com@gtempaccount.com1d64b622013-04-13 03:33:53 +00003329 ERR("Failed to retrieve the read render target view from the read render target.");
shannon.woods@transgaming.comea4a0c62013-02-28 23:06:29 +00003330 return gl::error(GL_OUT_OF_MEMORY, false);
shannon.woods@transgaming.com1e1deda2013-02-28 23:06:23 +00003331 }
3332
shannon.woods%transgaming.com@gtempaccount.com1d64b622013-04-13 03:33:53 +00003333 RenderTarget11 *drawRenderTarget11 = RenderTarget11::makeRenderTarget11(drawRenderTarget);
shannon.woods@transgaming.com1e1deda2013-02-28 23:06:23 +00003334 if (!drawRenderTarget)
3335 {
shannon.woods%transgaming.com@gtempaccount.com1d64b622013-04-13 03:33:53 +00003336 readTexture->Release();
3337 ERR("Failed to retrieve the draw render target from the draw framebuffer.");
shannon.woods@transgaming.comea4a0c62013-02-28 23:06:29 +00003338 return gl::error(GL_OUT_OF_MEMORY, false);
shannon.woods@transgaming.com1e1deda2013-02-28 23:06:23 +00003339 }
3340
shannon.woods%transgaming.com@gtempaccount.com27ac40e2013-04-13 03:43:17 +00003341 ID3D11Resource *drawTexture = drawRenderTarget11->getTexture();
shannon.woods%transgaming.com@gtempaccount.com1d64b622013-04-13 03:33:53 +00003342 unsigned int drawSubresource = drawRenderTarget11->getSubresourceIndex();
shannon.woods@transgaming.com1e1deda2013-02-28 23:06:23 +00003343
shannon.woods%transgaming.com@gtempaccount.com1d64b622013-04-13 03:33:53 +00003344 D3D11_BOX readBox;
3345 readBox.left = readRect.x;
3346 readBox.right = readRect.x + readRect.width;
3347 readBox.top = readRect.y;
3348 readBox.bottom = readRect.y + readRect.height;
3349 readBox.front = 0;
3350 readBox.back = 1;
shannon.woods@transgaming.com1e1deda2013-02-28 23:06:23 +00003351
shannon.woods%transgaming.com@gtempaccount.com86df5a42013-04-13 03:34:07 +00003352 // D3D11 needs depth-stencil CopySubresourceRegions to have a NULL pSrcBox
3353 // We also require complete framebuffer copies for depth-stencil blit.
3354 D3D11_BOX *pSrcBox = wholeBufferCopy ? NULL : &readBox;
3355
shannon.woods%transgaming.com@gtempaccount.com1d64b622013-04-13 03:33:53 +00003356 mDeviceContext->CopySubresourceRegion(drawTexture, drawSubresource, drawRect.x, drawRect.y, 0,
shannon.woods%transgaming.com@gtempaccount.com86df5a42013-04-13 03:34:07 +00003357 readTexture, readSubresource, pSrcBox);
shannon.woods@transgaming.com1e1deda2013-02-28 23:06:23 +00003358
shannon.woods%transgaming.com@gtempaccount.com1d64b622013-04-13 03:33:53 +00003359 readTexture->Release();
3360 drawTexture->Release();
shannon.woods@transgaming.com1e1deda2013-02-28 23:06:23 +00003361
3362 return true;
3363}
3364
shannon.woods@transgaming.comd67f9ce2013-02-28 23:06:09 +00003365ID3D11Texture2D *Renderer11::resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource)
3366{
3367 D3D11_TEXTURE2D_DESC textureDesc;
3368 source->GetDesc(&textureDesc);
3369
3370 if (textureDesc.SampleDesc.Count > 1)
3371 {
3372 D3D11_TEXTURE2D_DESC resolveDesc;
3373 resolveDesc.Width = textureDesc.Width;
3374 resolveDesc.Height = textureDesc.Height;
3375 resolveDesc.MipLevels = 1;
3376 resolveDesc.ArraySize = 1;
3377 resolveDesc.Format = textureDesc.Format;
3378 resolveDesc.SampleDesc.Count = 1;
3379 resolveDesc.SampleDesc.Quality = 0;
3380 resolveDesc.Usage = textureDesc.Usage;
3381 resolveDesc.BindFlags = textureDesc.BindFlags;
3382 resolveDesc.CPUAccessFlags = 0;
3383 resolveDesc.MiscFlags = 0;
3384
3385 ID3D11Texture2D *resolveTexture = NULL;
3386 HRESULT result = mDevice->CreateTexture2D(&resolveDesc, NULL, &resolveTexture);
3387 if (FAILED(result))
3388 {
3389 ERR("Failed to create a multisample resolve texture, HRESULT: 0x%X.", result);
3390 return NULL;
3391 }
3392
3393 mDeviceContext->ResolveSubresource(resolveTexture, 0, source, subresource, textureDesc.Format);
3394 return resolveTexture;
3395 }
3396 else
3397 {
3398 source->AddRef();
3399 return source;
3400 }
3401}
3402
shannonwoods@chromium.org6e4f2a62013-05-30 00:15:19 +00003403bool Renderer11::getLUID(LUID *adapterLuid) const
3404{
3405 adapterLuid->HighPart = 0;
3406 adapterLuid->LowPart = 0;
3407
3408 if (!mDxgiAdapter)
3409 {
3410 return false;
3411 }
3412
3413 DXGI_ADAPTER_DESC adapterDesc;
3414 if (FAILED(mDxgiAdapter->GetDesc(&adapterDesc)))
3415 {
3416 return false;
3417 }
3418
3419 *adapterLuid = adapterDesc.AdapterLuid;
3420 return true;
3421}
3422
Geoff Lang61e49a52013-05-29 10:22:58 -04003423Renderer11::MultisampleSupportInfo Renderer11::getMultisampleSupportInfo(DXGI_FORMAT format)
3424{
3425 MultisampleSupportInfo supportInfo = { 0 };
3426
3427 UINT formatSupport;
3428 HRESULT result;
3429
3430 result = mDevice->CheckFormatSupport(format, &formatSupport);
3431 if (SUCCEEDED(result) && (formatSupport & D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET))
3432 {
3433 for (unsigned int i = 1; i <= D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; i++)
3434 {
3435 result = mDevice->CheckMultisampleQualityLevels(format, i, &supportInfo.qualityLevels[i - 1]);
3436 if (SUCCEEDED(result) && supportInfo.qualityLevels[i - 1] > 0)
3437 {
3438 supportInfo.maxSupportedSamples = std::max(supportInfo.maxSupportedSamples, i);
3439 }
3440 else
3441 {
3442 supportInfo.qualityLevels[i - 1] = 0;
3443 }
3444 }
3445 }
3446
3447 return supportInfo;
3448}
3449
shannon.woods@transgaming.com9d971ff2013-01-25 21:50:53 +00003450}