daniel@transgaming.com | 95a758f | 2012-07-12 15:17:06 +0000 | [diff] [blame] | 1 | // |
| 2 | // Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. |
| 3 | // Use of this source code is governed by a BSD-style license that can be |
| 4 | // found in the LICENSE file. |
| 5 | // |
| 6 | |
| 7 | // debug.cpp: Debugging utilities. |
| 8 | |
| 9 | #include "common/debug.h" |
Geoff Lang | 44fa759 | 2014-05-30 11:50:07 -0400 | [diff] [blame] | 10 | #include "common/platform.h" |
Geoff Lang | da5777c | 2014-07-11 09:52:58 -0400 | [diff] [blame] | 11 | #include "common/angleutils.h" |
Geoff Lang | 44fa759 | 2014-05-30 11:50:07 -0400 | [diff] [blame] | 12 | |
Geoff Lang | 8321779 | 2014-01-16 09:52:38 -0500 | [diff] [blame] | 13 | #include <stdarg.h> |
Geoff Lang | feee44b | 2014-03-05 11:34:31 -0500 | [diff] [blame] | 14 | #include <vector> |
| 15 | #include <fstream> |
| 16 | #include <cstdio> |
Geoff Lang | 6850947 | 2013-10-07 17:06:30 -0400 | [diff] [blame] | 17 | |
daniel@transgaming.com | 95a758f | 2012-07-12 15:17:06 +0000 | [diff] [blame] | 18 | namespace gl |
| 19 | { |
Austin Kinross | 570e83c | 2014-10-20 14:13:58 -0700 | [diff] [blame] | 20 | #if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) |
Austin Kinross | 922a9fb | 2014-10-21 14:26:33 -0700 | [diff] [blame^] | 21 | // Wraps the D3D9/D3D11 debug annotation functions. |
| 22 | class DebugAnnotationWrapper |
daniel@transgaming.com | 95a758f | 2012-07-12 15:17:06 +0000 | [diff] [blame] | 23 | { |
Austin Kinross | 922a9fb | 2014-10-21 14:26:33 -0700 | [diff] [blame^] | 24 | public: |
| 25 | DebugAnnotationWrapper() { }; |
| 26 | virtual ~DebugAnnotationWrapper() { }; |
| 27 | virtual void beginEvent(const std::wstring &eventName) = 0; |
| 28 | virtual void endEvent() = 0; |
| 29 | virtual void setMarker(const std::wstring &markerName) = 0; |
| 30 | virtual bool getStatus() = 0; |
| 31 | }; |
| 32 | |
| 33 | #if defined(ANGLE_ENABLE_D3D9) |
| 34 | class D3D9DebugAnnotationWrapper : public DebugAnnotationWrapper |
| 35 | { |
| 36 | public: |
| 37 | void beginEvent(const std::wstring &eventName) |
| 38 | { |
| 39 | D3DPERF_BeginEvent(0, eventName.c_str()); |
| 40 | } |
| 41 | |
| 42 | void endEvent() |
| 43 | { |
| 44 | D3DPERF_EndEvent(); |
| 45 | } |
| 46 | |
| 47 | void setMarker(const std::wstring &markerName) |
| 48 | { |
| 49 | D3DPERF_SetMarker(0, markerName.c_str()); |
| 50 | } |
| 51 | |
| 52 | bool getStatus() |
| 53 | { |
| 54 | return !!D3DPERF_GetStatus(); |
| 55 | } |
| 56 | }; |
| 57 | #endif // ANGLE_ENABLE_D3D9 |
| 58 | |
| 59 | #if defined(ANGLE_ENABLE_D3D11) |
| 60 | class D3D11DebugAnnotationWrapper : public DebugAnnotationWrapper |
| 61 | { |
| 62 | public: |
| 63 | |
| 64 | D3D11DebugAnnotationWrapper() |
| 65 | : mInitialized(false), |
| 66 | mD3d11Module(NULL), |
| 67 | mUserDefinedAnnotation(NULL) |
| 68 | { |
| 69 | // D3D11 devices can't be created during DllMain. |
| 70 | // We defer device creation until the object is actually used. |
| 71 | } |
| 72 | |
| 73 | ~D3D11DebugAnnotationWrapper() |
| 74 | { |
| 75 | if (mInitialized) |
| 76 | { |
| 77 | SafeRelease(mUserDefinedAnnotation); |
| 78 | FreeLibrary(mD3d11Module); |
| 79 | } |
| 80 | } |
| 81 | |
| 82 | virtual void beginEvent(const std::wstring &eventName) |
| 83 | { |
| 84 | initializeDevice(); |
| 85 | |
| 86 | mUserDefinedAnnotation->BeginEvent(eventName.c_str()); |
| 87 | } |
| 88 | |
| 89 | virtual void endEvent() |
| 90 | { |
| 91 | initializeDevice(); |
| 92 | |
| 93 | mUserDefinedAnnotation->EndEvent(); |
| 94 | } |
| 95 | |
| 96 | virtual void setMarker(const std::wstring &markerName) |
| 97 | { |
| 98 | initializeDevice(); |
| 99 | |
| 100 | mUserDefinedAnnotation->SetMarker(markerName.c_str()); |
| 101 | } |
| 102 | |
| 103 | virtual bool getStatus() |
| 104 | { |
| 105 | // ID3DUserDefinedAnnotation::GetStatus doesn't work with the Graphics Diagnostics tools in Visual Studio 2013. |
| 106 | |
| 107 | #if defined(_DEBUG) && defined(ANGLE_ENABLE_WINDOWS_STORE) |
| 108 | // In the Windows Store, we can use IDXGraphicsAnalysis. The call to GetDebugInterface1 only succeeds if the app is under capture. |
| 109 | // This should only be called in DEBUG mode. |
| 110 | // If an app links against DXGIGetDebugInterface1 in release mode then it will fail Windows Store ingestion checks. |
| 111 | IDXGraphicsAnalysis* graphicsAnalysis; |
| 112 | DXGIGetDebugInterface1(0, IID_PPV_ARGS(&graphicsAnalysis)); |
| 113 | bool underCapture = (graphicsAnalysis != NULL); |
| 114 | SafeRelease(graphicsAnalysis); |
| 115 | return underCapture; |
Geoff Lang | feee44b | 2014-03-05 11:34:31 -0500 | [diff] [blame] | 116 | #endif |
| 117 | |
Austin Kinross | 922a9fb | 2014-10-21 14:26:33 -0700 | [diff] [blame^] | 118 | // Otherwise, we have to return true here. |
| 119 | return true; |
| 120 | } |
| 121 | |
| 122 | protected: |
| 123 | |
| 124 | void initializeDevice() |
| 125 | { |
| 126 | if (!mInitialized) |
| 127 | { |
| 128 | #if !defined(ANGLE_ENABLE_WINDOWS_STORE) |
| 129 | mD3d11Module = LoadLibrary(TEXT("d3d11.dll")); |
| 130 | ASSERT(mD3d11Module); |
| 131 | |
| 132 | PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice"); |
| 133 | ASSERT(D3D11CreateDevice != NULL); |
| 134 | #endif // !ANGLE_ENABLE_WINDOWS_STORE |
| 135 | |
| 136 | ID3D11Device* device = NULL; |
| 137 | ID3D11DeviceContext* context = NULL; |
| 138 | |
| 139 | HRESULT hr = E_FAIL; |
| 140 | |
| 141 | // Create a D3D_DRIVER_TYPE_NULL device, which is much cheaper than other types of device. |
| 142 | hr = D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_NULL, NULL, 0, NULL, 0, D3D11_SDK_VERSION, &device, NULL, &context); |
| 143 | ASSERT(SUCCEEDED(hr)); |
| 144 | |
| 145 | hr = context->QueryInterface(__uuidof(mUserDefinedAnnotation), reinterpret_cast<void**>(&mUserDefinedAnnotation)); |
| 146 | ASSERT(SUCCEEDED(hr) && mUserDefinedAnnotation != NULL); |
| 147 | |
| 148 | SafeRelease(device); |
| 149 | SafeRelease(context); |
| 150 | |
| 151 | mInitialized = true; |
| 152 | } |
| 153 | } |
| 154 | |
| 155 | bool mInitialized; |
| 156 | HMODULE mD3d11Module; |
| 157 | ID3DUserDefinedAnnotation* mUserDefinedAnnotation; |
| 158 | }; |
| 159 | #endif // ANGLE_ENABLE_D3D11 |
| 160 | |
| 161 | static DebugAnnotationWrapper* g_DebugAnnotationWrapper = NULL; |
| 162 | |
| 163 | void InitializeDebugAnnotations() |
| 164 | { |
| 165 | #if defined(ANGLE_ENABLE_D3D9) |
| 166 | g_DebugAnnotationWrapper = new D3D9DebugAnnotationWrapper(); |
| 167 | #elif defined(ANGLE_ENABLE_D3D11) |
| 168 | // If the project uses D3D9 then we can use the D3D9 debug annotations, even with the D3D11 renderer. |
| 169 | // However, if D3D9 is unavailable (e.g. in Windows Store), then we use D3D11 debug annotations. |
| 170 | // The D3D11 debug annotations are methods on ID3DUserDefinedAnnotation, which is implemented by the DeviceContext. |
| 171 | // This doesn't have to be the same DeviceContext that the renderer uses, though. |
| 172 | g_DebugAnnotationWrapper = new D3D11DebugAnnotationWrapper(); |
| 173 | #endif |
| 174 | } |
| 175 | |
| 176 | void UninitializeDebugAnnotations() |
| 177 | { |
| 178 | if (g_DebugAnnotationWrapper != NULL) |
| 179 | { |
| 180 | SafeDelete(g_DebugAnnotationWrapper); |
| 181 | } |
| 182 | } |
| 183 | |
| 184 | #endif // ANGLE_ENABLE_DEBUG_ANNOTATIONS |
| 185 | |
| 186 | enum DebugTraceOutputType |
| 187 | { |
| 188 | DebugTraceOutputTypeNone, |
| 189 | DebugTraceOutputTypeSetMarker, |
| 190 | DebugTraceOutputTypeBeginEvent |
| 191 | }; |
| 192 | |
| 193 | static void output(bool traceInDebugOnly, DebugTraceOutputType outputType, const char *format, va_list vararg) |
| 194 | { |
Austin Kinross | 570e83c | 2014-10-20 14:13:58 -0700 | [diff] [blame] | 195 | #if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) |
Austin Kinross | 922a9fb | 2014-10-21 14:26:33 -0700 | [diff] [blame^] | 196 | static std::vector<char> buffer(512); |
| 197 | |
daniel@transgaming.com | 95a758f | 2012-07-12 15:17:06 +0000 | [diff] [blame] | 198 | if (perfActive()) |
| 199 | { |
Austin Kinross | 922a9fb | 2014-10-21 14:26:33 -0700 | [diff] [blame^] | 200 | size_t len = FormatStringIntoVector(format, vararg, buffer); |
| 201 | std::wstring formattedWideMessage(buffer.begin(), buffer.begin() + len); |
| 202 | |
| 203 | switch (outputType) |
daniel@transgaming.com | 95a758f | 2012-07-12 15:17:06 +0000 | [diff] [blame] | 204 | { |
Austin Kinross | 922a9fb | 2014-10-21 14:26:33 -0700 | [diff] [blame^] | 205 | case DebugTraceOutputTypeNone: |
| 206 | break; |
| 207 | case DebugTraceOutputTypeBeginEvent: |
| 208 | g_DebugAnnotationWrapper->beginEvent(formattedWideMessage); |
| 209 | break; |
| 210 | case DebugTraceOutputTypeSetMarker: |
| 211 | g_DebugAnnotationWrapper->setMarker(formattedWideMessage); |
| 212 | break; |
daniel@transgaming.com | 95a758f | 2012-07-12 15:17:06 +0000 | [diff] [blame] | 213 | } |
daniel@transgaming.com | 95a758f | 2012-07-12 15:17:06 +0000 | [diff] [blame] | 214 | } |
Austin Kinross | 570e83c | 2014-10-20 14:13:58 -0700 | [diff] [blame] | 215 | #endif // ANGLE_ENABLE_DEBUG_ANNOTATIONS |
daniel@transgaming.com | 95a758f | 2012-07-12 15:17:06 +0000 | [diff] [blame] | 216 | |
Austin Kinross | f0360c6 | 2014-10-20 14:26:13 -0700 | [diff] [blame] | 217 | #if defined(ANGLE_ENABLE_DEBUG_TRACE) |
daniel@transgaming.com | 95a758f | 2012-07-12 15:17:06 +0000 | [diff] [blame] | 218 | #if defined(NDEBUG) |
Austin Kinross | fe14d45 | 2014-10-20 14:36:18 -0700 | [diff] [blame] | 219 | if (traceInDebugOnly) |
daniel@transgaming.com | 95a758f | 2012-07-12 15:17:06 +0000 | [diff] [blame] | 220 | { |
| 221 | return; |
| 222 | } |
Geoff Lang | f571312 | 2013-10-07 17:06:30 -0400 | [diff] [blame] | 223 | #endif // NDEBUG |
Austin Kinross | 922a9fb | 2014-10-21 14:26:33 -0700 | [diff] [blame^] | 224 | std::string formattedMessage = FormatString(format, vararg); |
daniel@transgaming.com | 95a758f | 2012-07-12 15:17:06 +0000 | [diff] [blame] | 225 | |
Geoff Lang | feee44b | 2014-03-05 11:34:31 -0500 | [diff] [blame] | 226 | static std::ofstream file(TRACE_OUTPUT_FILE, std::ofstream::app); |
daniel@transgaming.com | 95a758f | 2012-07-12 15:17:06 +0000 | [diff] [blame] | 227 | if (file) |
| 228 | { |
Geoff Lang | da5777c | 2014-07-11 09:52:58 -0400 | [diff] [blame] | 229 | file.write(formattedMessage.c_str(), formattedMessage.length()); |
Geoff Lang | feee44b | 2014-03-05 11:34:31 -0500 | [diff] [blame] | 230 | file.flush(); |
daniel@transgaming.com | 95a758f | 2012-07-12 15:17:06 +0000 | [diff] [blame] | 231 | } |
Geoff Lang | feee44b | 2014-03-05 11:34:31 -0500 | [diff] [blame] | 232 | |
Austin Kinross | fe14d45 | 2014-10-20 14:36:18 -0700 | [diff] [blame] | 233 | #if defined(ANGLE_ENABLE_DEBUG_TRACE_TO_DEBUGGER) |
| 234 | OutputDebugStringA(formattedMessage.c_str()); |
| 235 | #endif // ANGLE_ENABLE_DEBUG_TRACE_TO_DEBUGGER |
| 236 | |
Austin Kinross | f0360c6 | 2014-10-20 14:26:13 -0700 | [diff] [blame] | 237 | #endif // ANGLE_ENABLE_DEBUG_TRACE |
daniel@transgaming.com | 95a758f | 2012-07-12 15:17:06 +0000 | [diff] [blame] | 238 | } |
| 239 | |
Austin Kinross | fe14d45 | 2014-10-20 14:36:18 -0700 | [diff] [blame] | 240 | void trace(bool traceInDebugOnly, const char *format, ...) |
daniel@transgaming.com | 95a758f | 2012-07-12 15:17:06 +0000 | [diff] [blame] | 241 | { |
| 242 | va_list vararg; |
| 243 | va_start(vararg, format); |
Austin Kinross | 570e83c | 2014-10-20 14:13:58 -0700 | [diff] [blame] | 244 | #if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) |
Austin Kinross | 922a9fb | 2014-10-21 14:26:33 -0700 | [diff] [blame^] | 245 | output(traceInDebugOnly, DebugTraceOutputTypeSetMarker, format, vararg); |
Geoff Lang | f571312 | 2013-10-07 17:06:30 -0400 | [diff] [blame] | 246 | #else |
Austin Kinross | 922a9fb | 2014-10-21 14:26:33 -0700 | [diff] [blame^] | 247 | output(traceInDebugOnly, DebugTraceOutputTypeNone, format, vararg); |
daniel@transgaming.com | 95a758f | 2012-07-12 15:17:06 +0000 | [diff] [blame] | 248 | #endif |
| 249 | va_end(vararg); |
| 250 | } |
| 251 | |
| 252 | bool perfActive() |
| 253 | { |
Austin Kinross | 570e83c | 2014-10-20 14:13:58 -0700 | [diff] [blame] | 254 | #if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) |
Austin Kinross | 922a9fb | 2014-10-21 14:26:33 -0700 | [diff] [blame^] | 255 | static bool active = g_DebugAnnotationWrapper->getStatus(); |
daniel@transgaming.com | 95a758f | 2012-07-12 15:17:06 +0000 | [diff] [blame] | 256 | return active; |
Geoff Lang | f571312 | 2013-10-07 17:06:30 -0400 | [diff] [blame] | 257 | #else |
| 258 | return false; |
daniel@transgaming.com | 95a758f | 2012-07-12 15:17:06 +0000 | [diff] [blame] | 259 | #endif |
| 260 | } |
| 261 | |
| 262 | ScopedPerfEventHelper::ScopedPerfEventHelper(const char* format, ...) |
| 263 | { |
Austin Kinross | f0360c6 | 2014-10-20 14:26:13 -0700 | [diff] [blame] | 264 | #if !defined(ANGLE_ENABLE_DEBUG_TRACE) |
daniel@transgaming.com | 5dc3b8b | 2012-11-28 19:43:49 +0000 | [diff] [blame] | 265 | if (!perfActive()) |
| 266 | { |
| 267 | return; |
| 268 | } |
Austin Kinross | f0360c6 | 2014-10-20 14:26:13 -0700 | [diff] [blame] | 269 | #endif // !ANGLE_ENABLE_DEBUG_TRACE |
daniel@transgaming.com | 95a758f | 2012-07-12 15:17:06 +0000 | [diff] [blame] | 270 | va_list vararg; |
| 271 | va_start(vararg, format); |
Austin Kinross | 570e83c | 2014-10-20 14:13:58 -0700 | [diff] [blame] | 272 | #if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) |
Austin Kinross | 922a9fb | 2014-10-21 14:26:33 -0700 | [diff] [blame^] | 273 | output(true, DebugTraceOutputTypeBeginEvent, format, vararg); |
Jamie Madill | b60fe31 | 2014-09-26 14:56:41 -0400 | [diff] [blame] | 274 | #else |
Austin Kinross | 922a9fb | 2014-10-21 14:26:33 -0700 | [diff] [blame^] | 275 | output(true, DebugTraceOutputTypeNone, format, vararg); |
Austin Kinross | 570e83c | 2014-10-20 14:13:58 -0700 | [diff] [blame] | 276 | #endif // ANGLE_ENABLE_DEBUG_ANNOTATIONS |
Jamie Madill | b60fe31 | 2014-09-26 14:56:41 -0400 | [diff] [blame] | 277 | va_end(vararg); |
daniel@transgaming.com | 95a758f | 2012-07-12 15:17:06 +0000 | [diff] [blame] | 278 | } |
| 279 | |
| 280 | ScopedPerfEventHelper::~ScopedPerfEventHelper() |
| 281 | { |
Austin Kinross | 570e83c | 2014-10-20 14:13:58 -0700 | [diff] [blame] | 282 | #if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) |
daniel@transgaming.com | 95a758f | 2012-07-12 15:17:06 +0000 | [diff] [blame] | 283 | if (perfActive()) |
| 284 | { |
Austin Kinross | 922a9fb | 2014-10-21 14:26:33 -0700 | [diff] [blame^] | 285 | g_DebugAnnotationWrapper->endEvent(); |
daniel@transgaming.com | 95a758f | 2012-07-12 15:17:06 +0000 | [diff] [blame] | 286 | } |
| 287 | #endif |
| 288 | } |
| 289 | } |