diff --git a/src/d3d9/d3d9_annotation.cpp b/src/d3d9/d3d9_annotation.cpp new file mode 100644 index 00000000..d460b0a5 --- /dev/null +++ b/src/d3d9/d3d9_annotation.cpp @@ -0,0 +1,95 @@ +#include "d3d9_annotation.h" + +namespace dxvk { + + //////////////////////////// + // D3D9GlobalAnnotationList + //////////////////////////// + + D3D9GlobalAnnotationList::D3D9GlobalAnnotationList() + : m_shouldAnnotate(false) + , m_eventDepth(0) + {} + + + D3D9GlobalAnnotationList::~D3D9GlobalAnnotationList() + {} + + + void D3D9GlobalAnnotationList::RegisterAnnotator(IDXVKUserDefinedAnnotation* annotation) { + auto lock = std::unique_lock(m_mutex); + m_shouldAnnotate = true; + m_annotations.push_back(annotation); + } + + + void D3D9GlobalAnnotationList::UnregisterAnnotator(IDXVKUserDefinedAnnotation* annotation) { + auto lock = std::unique_lock(m_mutex); + auto iter = std::find(m_annotations.begin(), m_annotations.end(), annotation); + if (iter != m_annotations.end()) + m_annotations.erase(iter); + } + + + INT D3D9GlobalAnnotationList::BeginEvent(D3DCOLOR color, LPCWSTR name) { + if (!m_shouldAnnotate) + return 0; + + auto lock = std::unique_lock(m_mutex); + for (auto* annotation : m_annotations) + annotation->BeginEvent(color, name); + + return m_eventDepth++; + } + + + INT D3D9GlobalAnnotationList::EndEvent() { + if (!m_shouldAnnotate) + return 0; + + auto lock = std::unique_lock(m_mutex); + for (auto* annotation : m_annotations) + annotation->EndEvent(); + + return m_eventDepth--; + } + + + void D3D9GlobalAnnotationList::SetMarker(D3DCOLOR color, LPCWSTR name) { + if (!m_shouldAnnotate) + return; + + auto lock = std::unique_lock(m_mutex); + for (auto* annotation : m_annotations) + annotation->SetMarker(color, name); + } + + + void D3D9GlobalAnnotationList::SetRegion(D3DCOLOR color, LPCWSTR name) { + // This, by the documentation, does nothing. + } + + + BOOL D3D9GlobalAnnotationList::QueryRepeatFrame() const { + // This, by the documentation, does nothing. + // It's meant to return TRUE if the profiler/debugger + // wants a frame to be repeated, but we never need that. + return FALSE; + } + + + void D3D9GlobalAnnotationList::SetOptions(DWORD options) { + // This is used to say that the app should + // not be debugged/profiled. + } + + + DWORD D3D9GlobalAnnotationList::GetStatus() const { + // This returns whether the app is being + // profiled / debugged. + // Some apps may rely on this to emit + // debug markers. + return m_shouldAnnotate ? 1 : 0; + } + +} diff --git a/src/d3d9/d3d9_annotation.h b/src/d3d9/d3d9_annotation.h new file mode 100644 index 00000000..32930766 --- /dev/null +++ b/src/d3d9/d3d9_annotation.h @@ -0,0 +1,55 @@ +#pragma once + +#include "d3d9_device.h" +#include "d3d9_include.h" +#include "../dxvk/dxvk_annotation.h" + +#include +#include +#include + +namespace dxvk { + + class D3D9GlobalAnnotationList { + + public: + + D3D9GlobalAnnotationList(); + ~D3D9GlobalAnnotationList(); + + void RegisterAnnotator(IDXVKUserDefinedAnnotation* annotation); + void UnregisterAnnotator(IDXVKUserDefinedAnnotation* annotation); + + INT BeginEvent(D3DCOLOR color, LPCWSTR name); + INT EndEvent(); + + void SetMarker(D3DCOLOR color, LPCWSTR name); + + void SetRegion(D3DCOLOR color, LPCWSTR name); + + BOOL QueryRepeatFrame() const; + + void SetOptions(DWORD options); + + DWORD GetStatus() const; + + static D3D9GlobalAnnotationList& Instance() { + return s_instance; + } + + private: + + static D3D9GlobalAnnotationList s_instance; + + std::atomic m_shouldAnnotate; + + std::mutex m_mutex; + std::vector m_annotations; + + // Provide our own event depth as we + // may have multiple annotators which could get out of sync. + int32_t m_eventDepth; + + }; + +} \ No newline at end of file diff --git a/src/d3d9/d3d9_device.cpp b/src/d3d9/d3d9_device.cpp index b76d7f62..bcd19015 100644 --- a/src/d3d9/d3d9_device.cpp +++ b/src/d3d9/d3d9_device.cpp @@ -1,5 +1,6 @@ #include "d3d9_device.h" +#include "d3d9_annotation.h" #include "d3d9_interface.h" #include "d3d9_swapchain.h" #include "d3d9_caps.h" diff --git a/src/d3d9/d3d9_main.cpp b/src/d3d9/d3d9_main.cpp index dfca9c1d..102a8a7f 100644 --- a/src/d3d9/d3d9_main.cpp +++ b/src/d3d9/d3d9_main.cpp @@ -3,11 +3,14 @@ #include "d3d9_interface.h" #include "d3d9_shader_validator.h" +#include "../d3d9/d3d9_annotation.h" + class D3DFE_PROCESSVERTICES; using PSGPERRORID = UINT; namespace dxvk { Logger Logger::s_instance("d3d9.log"); + D3D9GlobalAnnotationList D3D9GlobalAnnotationList::s_instance; HRESULT CreateD3D9( bool Extended, @@ -20,6 +23,7 @@ namespace dxvk { } } + extern "C" { DLLEXPORT IDirect3D9* __stdcall Direct3DCreate9(UINT nSDKVersion) { @@ -34,28 +38,31 @@ extern "C" { } DLLEXPORT int __stdcall D3DPERF_BeginEvent(D3DCOLOR col, LPCWSTR wszName) { - return 0; + return dxvk::D3D9GlobalAnnotationList::Instance().BeginEvent(col, wszName); } DLLEXPORT int __stdcall D3DPERF_EndEvent(void) { - return 0; + return dxvk::D3D9GlobalAnnotationList::Instance().EndEvent(); } DLLEXPORT void __stdcall D3DPERF_SetMarker(D3DCOLOR col, LPCWSTR wszName) { + dxvk::D3D9GlobalAnnotationList::Instance().SetMarker(col, wszName); } DLLEXPORT void __stdcall D3DPERF_SetRegion(D3DCOLOR col, LPCWSTR wszName) { + dxvk::D3D9GlobalAnnotationList::Instance().SetRegion(col, wszName); } DLLEXPORT BOOL __stdcall D3DPERF_QueryRepeatFrame(void) { - return FALSE; + return dxvk::D3D9GlobalAnnotationList::Instance().QueryRepeatFrame(); } DLLEXPORT void __stdcall D3DPERF_SetOptions(DWORD dwOptions) { + dxvk::D3D9GlobalAnnotationList::Instance().SetOptions(dwOptions); } DLLEXPORT DWORD __stdcall D3DPERF_GetStatus(void) { - return 0; + return dxvk::D3D9GlobalAnnotationList::Instance().GetStatus(); } diff --git a/src/d3d9/meson.build b/src/d3d9/meson.build index a53dc701..9750cd4c 100644 --- a/src/d3d9/meson.build +++ b/src/d3d9/meson.build @@ -38,7 +38,8 @@ d3d9_src = [ 'd3d9_names.cpp', 'd3d9_swvp_emu.cpp', 'd3d9_format_helpers.cpp', - 'd3d9_hud.cpp' + 'd3d9_hud.cpp', + 'd3d9_annotation.cpp', ] d3d9_dll = shared_library('d3d9'+dll_ext, d3d9_src, glsl_generator.process(d3d9_shaders), d3d9_res,