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.
7 // debug.cpp: Debugging utilities.
9 #include "common/debug.h"
10 #include "common/platform.h"
11 #include "common/angleutils.h"
20 #if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
21 // Wraps the D3D9/D3D11 debug annotation functions.
22 class DebugAnnotationWrapper
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;
33 #if defined(ANGLE_ENABLE_D3D9)
34 class D3D9DebugAnnotationWrapper : public DebugAnnotationWrapper
37 void beginEvent(const std::wstring &eventName)
39 D3DPERF_BeginEvent(0, eventName.c_str());
47 void setMarker(const std::wstring &markerName)
49 D3DPERF_SetMarker(0, markerName.c_str());
54 return !!D3DPERF_GetStatus();
57 #endif // ANGLE_ENABLE_D3D9
59 #if defined(ANGLE_ENABLE_D3D11)
60 class D3D11DebugAnnotationWrapper : public DebugAnnotationWrapper
64 D3D11DebugAnnotationWrapper()
65 : mInitialized(false),
67 mUserDefinedAnnotation(NULL)
69 // D3D11 devices can't be created during DllMain.
70 // We defer device creation until the object is actually used.
73 ~D3D11DebugAnnotationWrapper()
77 SafeRelease(mUserDefinedAnnotation);
78 FreeLibrary(mD3d11Module);
82 virtual void beginEvent(const std::wstring &eventName)
86 mUserDefinedAnnotation->BeginEvent(eventName.c_str());
89 virtual void endEvent()
93 mUserDefinedAnnotation->EndEvent();
96 virtual void setMarker(const std::wstring &markerName)
100 mUserDefinedAnnotation->SetMarker(markerName.c_str());
103 virtual bool getStatus()
105 // ID3DUserDefinedAnnotation::GetStatus doesn't work with the Graphics Diagnostics tools in Visual Studio 2013.
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);
118 // Otherwise, we have to return true here.
124 void initializeDevice()
128 #if !defined(ANGLE_ENABLE_WINDOWS_STORE)
129 mD3d11Module = LoadLibrary(TEXT("d3d11.dll"));
130 ASSERT(mD3d11Module);
132 PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice");
133 ASSERT(D3D11CreateDevice != NULL);
134 #endif // !ANGLE_ENABLE_WINDOWS_STORE
136 ID3D11Device* device = NULL;
137 ID3D11DeviceContext* context = NULL;
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));
145 hr = context->QueryInterface(__uuidof(mUserDefinedAnnotation), reinterpret_cast<void**>(&mUserDefinedAnnotation));
146 ASSERT(SUCCEEDED(hr) && mUserDefinedAnnotation != NULL);
149 SafeRelease(context);
156 HMODULE mD3d11Module;
157 ID3DUserDefinedAnnotation* mUserDefinedAnnotation;
159 #endif // ANGLE_ENABLE_D3D11
161 static DebugAnnotationWrapper* g_DebugAnnotationWrapper = NULL;
163 void InitializeDebugAnnotations()
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();
176 void UninitializeDebugAnnotations()
178 if (g_DebugAnnotationWrapper != NULL)
180 SafeDelete(g_DebugAnnotationWrapper);
184 #endif // ANGLE_ENABLE_DEBUG_ANNOTATIONS
186 enum DebugTraceOutputType
188 DebugTraceOutputTypeNone,
189 DebugTraceOutputTypeSetMarker,
190 DebugTraceOutputTypeBeginEvent
193 static void output(bool traceInDebugOnly, DebugTraceOutputType outputType, const char *format, va_list vararg)
195 #if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
196 static std::vector<char> buffer(512);
200 size_t len = FormatStringIntoVector(format, vararg, buffer);
201 std::wstring formattedWideMessage(buffer.begin(), buffer.begin() + len);
205 case DebugTraceOutputTypeNone:
207 case DebugTraceOutputTypeBeginEvent:
208 g_DebugAnnotationWrapper->beginEvent(formattedWideMessage);
210 case DebugTraceOutputTypeSetMarker:
211 g_DebugAnnotationWrapper->setMarker(formattedWideMessage);
215 #endif // ANGLE_ENABLE_DEBUG_ANNOTATIONS
217 #if defined(ANGLE_ENABLE_DEBUG_TRACE)
219 if (traceInDebugOnly)
224 std::string formattedMessage = FormatString(format, vararg);
226 static std::ofstream file(TRACE_OUTPUT_FILE, std::ofstream::app);
229 file.write(formattedMessage.c_str(), formattedMessage.length());
233 #if defined(ANGLE_ENABLE_DEBUG_TRACE_TO_DEBUGGER)
234 OutputDebugStringA(formattedMessage.c_str());
235 #endif // ANGLE_ENABLE_DEBUG_TRACE_TO_DEBUGGER
237 #endif // ANGLE_ENABLE_DEBUG_TRACE
240 void trace(bool traceInDebugOnly, const char *format, ...)
243 va_start(vararg, format);
244 #if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
245 output(traceInDebugOnly, DebugTraceOutputTypeSetMarker, format, vararg);
247 output(traceInDebugOnly, DebugTraceOutputTypeNone, format, vararg);
254 #if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
255 static bool active = g_DebugAnnotationWrapper->getStatus();
262 ScopedPerfEventHelper::ScopedPerfEventHelper(const char* format, ...)
264 #if !defined(ANGLE_ENABLE_DEBUG_TRACE)
269 #endif // !ANGLE_ENABLE_DEBUG_TRACE
271 va_start(vararg, format);
272 #if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
273 output(true, DebugTraceOutputTypeBeginEvent, format, vararg);
275 output(true, DebugTraceOutputTypeNone, format, vararg);
276 #endif // ANGLE_ENABLE_DEBUG_ANNOTATIONS
280 ScopedPerfEventHelper::~ScopedPerfEventHelper()
282 #if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
285 g_DebugAnnotationWrapper->endEvent();