Edit

kc3-lang/angle/src/common/debug.cpp

Branch :

  • Show log

    Commit

  • Author : Cooper Partin
    Date : 2015-01-08 09:15:35
    Hash : 7318b7cb
    Message : Fixed failed compilation for WinRT to use OutputDebugStringA for non wide strings. Change-Id: If012660d4b895399fe5e3226dea25a8c7f78c8ac Reviewed-on: https://chromium-review.googlesource.com/239504 Reviewed-by: Geoff Lang <geofflang@chromium.org> Tested-by: Cooper Partin <coopp@microsoft.com> Reviewed-by: Jamie Madill <jmadill@chromium.org>

  • src/common/debug.cpp
  • //
    // Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
    // Use of this source code is governed by a BSD-style license that can be
    // found in the LICENSE file.
    //
    
    // debug.cpp: Debugging utilities.
    
    #include "common/debug.h"
    #include "common/platform.h"
    #include "common/angleutils.h"
    
    #include <stdarg.h>
    #include <vector>
    #include <fstream>
    #include <cstdio>
    
    namespace gl
    {
    // Wraps the D3D9/D3D11 debug annotation functions.
    class DebugAnnotationWrapper
    {
      public:
        DebugAnnotationWrapper() { };
        virtual ~DebugAnnotationWrapper() { };
        virtual void beginEvent(const std::wstring &eventName) = 0;
        virtual void endEvent() = 0;
        virtual void setMarker(const std::wstring &markerName) = 0;
        virtual bool getStatus() = 0;
    };
    
    #if defined(ANGLE_ENABLE_D3D9)
    class D3D9DebugAnnotationWrapper : public DebugAnnotationWrapper
    {
      public:
        void beginEvent(const std::wstring &eventName)
        {
            D3DPERF_BeginEvent(0, eventName.c_str());
        }
    
        void endEvent()
        {
            D3DPERF_EndEvent();
        }
    
        void setMarker(const std::wstring &markerName)
        {
            D3DPERF_SetMarker(0, markerName.c_str());
        }
    
        bool getStatus()
        {
            return !!D3DPERF_GetStatus();
        }
    };
    #endif // ANGLE_ENABLE_D3D9
    
    #if defined(ANGLE_ENABLE_D3D11)
    class D3D11DebugAnnotationWrapper : public DebugAnnotationWrapper
    {
      public:
    
        D3D11DebugAnnotationWrapper()
          : mInitialized(false),
            mD3d11Module(NULL),
            mUserDefinedAnnotation(NULL)
        {
            // D3D11 devices can't be created during DllMain.
            // We defer device creation until the object is actually used.
        }
    
        ~D3D11DebugAnnotationWrapper()
        {
            if (mInitialized)
            {
                SafeRelease(mUserDefinedAnnotation);
                FreeLibrary(mD3d11Module);
            }
        }
    
        virtual void beginEvent(const std::wstring &eventName)
        {
            initializeDevice();
    
            mUserDefinedAnnotation->BeginEvent(eventName.c_str());
        }
    
        virtual void endEvent()
        {
            initializeDevice();
    
            mUserDefinedAnnotation->EndEvent();
        }
    
        virtual void setMarker(const std::wstring &markerName)
        {
            initializeDevice();
    
            mUserDefinedAnnotation->SetMarker(markerName.c_str());
        }
    
        virtual bool getStatus()
        {
            // ID3DUserDefinedAnnotation::GetStatus doesn't work with the Graphics Diagnostics tools in Visual Studio 2013.
    
    #if defined(_DEBUG) && defined(ANGLE_ENABLE_WINDOWS_STORE)
            // In the Windows Store, we can use IDXGraphicsAnalysis. The call to GetDebugInterface1 only succeeds if the app is under capture.
            // This should only be called in DEBUG mode.
            // If an app links against DXGIGetDebugInterface1 in release mode then it will fail Windows Store ingestion checks.
            IDXGraphicsAnalysis* graphicsAnalysis;
            DXGIGetDebugInterface1(0, IID_PPV_ARGS(&graphicsAnalysis));
            bool underCapture = (graphicsAnalysis != NULL);
            SafeRelease(graphicsAnalysis);
            return underCapture;
    #endif
    
            // Otherwise, we have to return true here.
            return true;
        }
    
      protected:
    
        void initializeDevice()
        {
            if (!mInitialized)
            {
    #if !defined(ANGLE_ENABLE_WINDOWS_STORE)
                mD3d11Module = LoadLibrary(TEXT("d3d11.dll"));
                ASSERT(mD3d11Module);
    
                PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice");
                ASSERT(D3D11CreateDevice != NULL);
    #endif // !ANGLE_ENABLE_WINDOWS_STORE
    
                ID3D11Device* device = NULL;
                ID3D11DeviceContext* context = NULL;
    
                HRESULT hr = E_FAIL;
    
                // Create a D3D_DRIVER_TYPE_NULL device, which is much cheaper than other types of device.
                hr =  D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_NULL, NULL, 0, NULL, 0, D3D11_SDK_VERSION, &device, NULL, &context);
                ASSERT(SUCCEEDED(hr));
    
                hr = context->QueryInterface(__uuidof(mUserDefinedAnnotation), reinterpret_cast<void**>(&mUserDefinedAnnotation));
                ASSERT(SUCCEEDED(hr) && mUserDefinedAnnotation != NULL);
    
                SafeRelease(device);
                SafeRelease(context);
    
                mInitialized = true;
            }
        }
    
        bool mInitialized;
        HMODULE mD3d11Module;
        ID3DUserDefinedAnnotation* mUserDefinedAnnotation;
    };
    #endif // ANGLE_ENABLE_D3D11
    
    static DebugAnnotationWrapper *GetDebugAnnotationWrapper()
    {
    #if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
    #   if defined(ANGLE_ENABLE_D3D9)
        static D3D9DebugAnnotationWrapper wrapper;
    #   elif defined(ANGLE_ENABLE_D3D11)
        // If the project uses D3D9 then we can use the D3D9 debug annotations, even with the D3D11 renderer.
        // However, if D3D9 is unavailable (e.g. in Windows Store), then we use D3D11 debug annotations.
        // The D3D11 debug annotations are methods on ID3DUserDefinedAnnotation, which is implemented by the DeviceContext.
        // This doesn't have to be the same DeviceContext that the renderer uses, though.
        static D3D11DebugAnnotationWrapper wrapper;
    #   endif
        return &wrapper;
    #else
        return nullptr;
    #endif
    }
    
    enum DebugTraceOutputType
    {
       DebugTraceOutputTypeNone,
       DebugTraceOutputTypeSetMarker,
       DebugTraceOutputTypeBeginEvent
    };
    
    static void output(bool traceInDebugOnly, MessageType messageType, DebugTraceOutputType outputType,
                       const char *format, va_list vararg)
    {
        if (perfActive())
        {
            static std::vector<char> buffer(512);
            size_t len = FormatStringIntoVector(format, vararg, buffer);
            std::wstring formattedWideMessage(buffer.begin(), buffer.begin() + len);
    
            DebugAnnotationWrapper *annotationWrapper = GetDebugAnnotationWrapper();
            switch (outputType)
            {
              case DebugTraceOutputTypeNone:
                break;
              case DebugTraceOutputTypeBeginEvent:
                annotationWrapper->beginEvent(formattedWideMessage);
                break;
              case DebugTraceOutputTypeSetMarker:
                annotationWrapper->setMarker(formattedWideMessage);
                break;
            }
        }
    
        std::string formattedMessage;
        UNUSED_TRACE_VARIABLE(formattedMessage);
    
    #if !defined(NDEBUG) && defined(_MSC_VER)
        if (messageType == MESSAGE_ERR)
        {
            if (formattedMessage.empty())
            {
                formattedMessage = FormatString(format, vararg);
            }
            OutputDebugStringA(formattedMessage.c_str());
        }
    #endif
    
    #if defined(ANGLE_ENABLE_DEBUG_TRACE)
    #if defined(NDEBUG)
        if (traceInDebugOnly)
        {
            return;
        }
    #endif // NDEBUG
        if (formattedMessage.empty())
        {
            formattedMessage = FormatString(format, vararg);
        }
    
        static std::ofstream file(TRACE_OUTPUT_FILE, std::ofstream::app);
        if (file)
        {
            file.write(formattedMessage.c_str(), formattedMessage.length());
            file.flush();
        }
    
    #if defined(ANGLE_ENABLE_DEBUG_TRACE_TO_DEBUGGER)
        OutputDebugStringA(formattedMessage.c_str());
    #endif // ANGLE_ENABLE_DEBUG_TRACE_TO_DEBUGGER
    
    #endif // ANGLE_ENABLE_DEBUG_TRACE
    }
    
    void trace(bool traceInDebugOnly, MessageType messageType, const char *format, ...)
    {
        va_list vararg;
        va_start(vararg, format);
    #if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
        output(traceInDebugOnly, messageType, DebugTraceOutputTypeSetMarker, format, vararg);
    #else
        output(traceInDebugOnly, messageType, DebugTraceOutputTypeNone, format, vararg);
    #endif
        va_end(vararg);
    }
    
    bool perfActive()
    {
    #if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
        static bool active = GetDebugAnnotationWrapper()->getStatus();
        return active;
    #else
        return false;
    #endif
    }
    
    ScopedPerfEventHelper::ScopedPerfEventHelper(const char* format, ...)
    {
    #if !defined(ANGLE_ENABLE_DEBUG_TRACE)
        if (!perfActive())
        {
            return;
        }
    #endif // !ANGLE_ENABLE_DEBUG_TRACE
        va_list vararg;
        va_start(vararg, format);
    #if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
        output(true, MESSAGE_EVENT, DebugTraceOutputTypeBeginEvent, format, vararg);
    #else
        output(true, MESSAGE_EVENT, DebugTraceOutputTypeNone, format, vararg);
    #endif // ANGLE_ENABLE_DEBUG_ANNOTATIONS
        va_end(vararg);
    }
    
    ScopedPerfEventHelper::~ScopedPerfEventHelper()
    {
    #if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
        if (perfActive())
        {
            GetDebugAnnotationWrapper()->endEvent();
        }
    #endif
    }
    }