diff --git a/src/xenia/gpu/d3d12/d3d12_command_processor.cc b/src/xenia/gpu/d3d12/d3d12_command_processor.cc index 31b77ef39..8016701e8 100644 --- a/src/xenia/gpu/d3d12/d3d12_command_processor.cc +++ b/src/xenia/gpu/d3d12/d3d12_command_processor.cc @@ -47,6 +47,15 @@ void D3D12CommandProcessor::ClearCaches() { cache_clear_requested_ = true; } +void D3D12CommandProcessor::RequestFrameTrace(const std::wstring& root_path) { + // Capture with PIX if attached. + if (GetD3D12Context()->GetD3D12Provider()->GetGraphicsAnalysis() != nullptr) { + pix_capture_requested_.store(true, std::memory_order_relaxed); + return; + } + CommandProcessor::RequestFrameTrace(root_path); +} + ID3D12GraphicsCommandList* D3D12CommandProcessor::GetCurrentCommandList() const { assert_true(current_queue_frame_ != UINT_MAX); @@ -752,6 +761,9 @@ bool D3D12CommandProcessor::SetupContext() { swap_texture_, &swap_srv_desc, swap_texture_srv_descriptor_heap_->GetCPUDescriptorHandleForHeapStart()); + pix_capture_requested_.store(false, std::memory_order_relaxed); + pix_capturing_ = false; + return true; } @@ -1273,6 +1285,7 @@ bool D3D12CommandProcessor::BeginFrame() { #endif // FINE_GRAINED_DRAW_SCOPES auto context = GetD3D12Context(); + auto provider = context->GetD3D12Provider(); context->BeginSwap(); current_queue_frame_ = context->GetCurrentQueueFrame(); @@ -1323,6 +1336,14 @@ bool D3D12CommandProcessor::BeginFrame() { samplers_written_pixel_ = false; primitive_topology_ = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED; + pix_capturing_ = + pix_capture_requested_.exchange(false, std::memory_order_relaxed); + if (pix_capturing_) { + IDXGraphicsAnalysis* graphics_analysis = provider->GetGraphicsAnalysis(); + if (graphics_analysis != nullptr) { + graphics_analysis->BeginCapture(); + } + } command_lists_[current_queue_frame_]->BeginRecording(); constant_buffer_pool_->BeginFrame(); @@ -1360,6 +1381,15 @@ bool D3D12CommandProcessor::EndFrame() { SubmitBarriers(); command_lists_[current_queue_frame_]->Execute(); + if (pix_capturing_) { + IDXGraphicsAnalysis* graphics_analysis = + GetD3D12Context()->GetD3D12Provider()->GetGraphicsAnalysis(); + if (graphics_analysis != nullptr) { + graphics_analysis->EndCapture(); + } + pix_capturing_ = false; + } + sampler_heap_pool_->EndFrame(); view_heap_pool_->EndFrame(); constant_buffer_pool_->EndFrame(); diff --git a/src/xenia/gpu/d3d12/d3d12_command_processor.h b/src/xenia/gpu/d3d12/d3d12_command_processor.h index 18163b370..cf53ddeb6 100644 --- a/src/xenia/gpu/d3d12/d3d12_command_processor.h +++ b/src/xenia/gpu/d3d12/d3d12_command_processor.h @@ -10,6 +10,7 @@ #ifndef XENIA_GPU_D3D12_D3D12_COMMAND_PROCESSOR_H_ #define XENIA_GPU_D3D12_D3D12_COMMAND_PROCESSOR_H_ +#include #include #include #include @@ -40,6 +41,8 @@ class D3D12CommandProcessor : public CommandProcessor { void ClearCaches() override; + void RequestFrameTrace(const std::wstring& root_path) override; + // Needed by everything that owns transient objects. xe::ui::d3d12::D3D12Context* GetD3D12Context() const { return static_cast(context_.get()); @@ -252,6 +255,9 @@ class D3D12CommandProcessor : public CommandProcessor { uint32_t current_queue_frame_ = UINT32_MAX; + std::atomic pix_capture_requested_ = false; + bool pix_capturing_; + // The current fixed-function drawing state. D3D12_VIEWPORT ff_viewport_; D3D12_RECT ff_scissor_; diff --git a/src/xenia/gpu/d3d12/shared_memory.cc b/src/xenia/gpu/d3d12/shared_memory.cc index bfacf5ea1..89da91fdb 100644 --- a/src/xenia/gpu/d3d12/shared_memory.cc +++ b/src/xenia/gpu/d3d12/shared_memory.cc @@ -47,7 +47,8 @@ SharedMemory::~SharedMemory() { Shutdown(); } bool SharedMemory::Initialize() { auto context = command_processor_->GetD3D12Context(); - auto device = context->GetD3D12Provider()->GetDevice(); + auto provider = context->GetD3D12Provider(); + auto device = provider->GetDevice(); D3D12_RESOURCE_DESC buffer_desc; ui::d3d12::util::FillBufferResourceDesc( @@ -65,6 +66,13 @@ bool SharedMemory::Initialize() { "Direct3D 12 tiled resources are not used for shared memory " "emulation - video memory usage may increase significantly " "because a full 512 MB buffer will be created!"); + if (provider->GetGraphicsAnalysis() != nullptr) { + // As of October 8th, 2018, PIX doesn't support tiled buffers. + // FIXME(Triang3l): Re-enable tiled resources with PIX once fixed. + XELOGGPU( + "This is caused by PIX being attached, which doesn't support tiled " + "resources yet."); + } if (FAILED(device->CreateCommittedResource( &ui::d3d12::util::kHeapPropertiesDefault, D3D12_HEAP_FLAG_NONE, &buffer_desc, buffer_state_, nullptr, IID_PPV_ARGS(&buffer_)))) { @@ -370,7 +378,10 @@ bool SharedMemory::AreTiledResourcesUsed() const { return false; } auto provider = command_processor_->GetD3D12Context()->GetD3D12Provider(); - return provider->GetTiledResourcesTier() >= 1; + // As of October 8th, 2018, PIX doesn't support tiled buffers. + // FIXME(Triang3l): Re-enable tiled resources with PIX once fixed. + return provider->GetTiledResourcesTier() >= 1 && + provider->GetGraphicsAnalysis() == nullptr; } void SharedMemory::MakeRangeValid(uint32_t valid_page_first, diff --git a/src/xenia/ui/d3d12/d3d12_api.h b/src/xenia/ui/d3d12/d3d12_api.h index b3528a3f9..45eb02e07 100644 --- a/src/xenia/ui/d3d12/d3d12_api.h +++ b/src/xenia/ui/d3d12/d3d12_api.h @@ -13,6 +13,7 @@ // This must be included before D3D and DXGI for things like NOMINMAX. #include "xenia/base/platform_win.h" +#include #include #include #include diff --git a/src/xenia/ui/d3d12/d3d12_provider.cc b/src/xenia/ui/d3d12/d3d12_provider.cc index 4fd7093de..7bf7259ad 100644 --- a/src/xenia/ui/d3d12/d3d12_provider.cc +++ b/src/xenia/ui/d3d12/d3d12_provider.cc @@ -43,6 +43,9 @@ D3D12Provider::D3D12Provider(Window* main_window) : GraphicsProvider(main_window) {} D3D12Provider::~D3D12Provider() { + if (graphics_analysis_ != nullptr) { + graphics_analysis_->Release(); + } if (direct_queue_ != nullptr) { direct_queue_->Release(); } @@ -167,6 +170,10 @@ bool D3D12Provider::Initialize() { "sample positions tier %u", tiled_resources_tier_, programmable_sample_positions_tier_); + // Get the graphics analysis interface, will silently fail if PIX not + // attached. + DXGIGetDebugInterface1(0, IID_PPV_ARGS(&graphics_analysis_)); + return true; } diff --git a/src/xenia/ui/d3d12/d3d12_provider.h b/src/xenia/ui/d3d12/d3d12_provider.h index d113c015a..99244d9dd 100644 --- a/src/xenia/ui/d3d12/d3d12_provider.h +++ b/src/xenia/ui/d3d12/d3d12_provider.h @@ -30,6 +30,10 @@ class D3D12Provider : public GraphicsProvider { std::unique_ptr CreateOffscreenContext() override; IDXGIFactory2* GetDXGIFactory() const { return dxgi_factory_; } + // nullptr if PIX not attached. + IDXGraphicsAnalysis* GetGraphicsAnalysis() const { + return graphics_analysis_; + } ID3D12Device* GetDevice() const { return device_; } ID3D12CommandQueue* GetDirectQueue() const { return direct_queue_; } @@ -69,6 +73,7 @@ class D3D12Provider : public GraphicsProvider { bool Initialize(); IDXGIFactory2* dxgi_factory_ = nullptr; + IDXGraphicsAnalysis* graphics_analysis_ = nullptr; ID3D12Device* device_ = nullptr; ID3D12CommandQueue* direct_queue_ = nullptr;