[UI/D3D12] Small refactoring, allow BeginSwap to return false if no surface
This commit is contained in:
parent
acb1fc059f
commit
dfbe36a8aa
|
@ -9,9 +9,6 @@
|
||||||
|
|
||||||
#include "xenia/ui/d3d12/d3d12_context.h"
|
#include "xenia/ui/d3d12/d3d12_context.h"
|
||||||
|
|
||||||
#include <cstdlib>
|
|
||||||
|
|
||||||
#include "xenia/base/cvar.h"
|
|
||||||
#include "xenia/base/logging.h"
|
#include "xenia/base/logging.h"
|
||||||
#include "xenia/base/math.h"
|
#include "xenia/base/math.h"
|
||||||
#include "xenia/ui/d3d12/d3d12_immediate_drawer.h"
|
#include "xenia/ui/d3d12/d3d12_immediate_drawer.h"
|
||||||
|
@ -19,9 +16,6 @@
|
||||||
#include "xenia/ui/d3d12/d3d12_util.h"
|
#include "xenia/ui/d3d12/d3d12_util.h"
|
||||||
#include "xenia/ui/window.h"
|
#include "xenia/ui/window.h"
|
||||||
|
|
||||||
DEFINE_bool(d3d12_random_clear_color, false,
|
|
||||||
"Randomize presentation back buffer clear color.", "D3D12");
|
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace ui {
|
namespace ui {
|
||||||
namespace d3d12 {
|
namespace d3d12 {
|
||||||
|
@ -32,14 +26,17 @@ D3D12Context::D3D12Context(D3D12Provider* provider, Window* target_window)
|
||||||
D3D12Context::~D3D12Context() { Shutdown(); }
|
D3D12Context::~D3D12Context() { Shutdown(); }
|
||||||
|
|
||||||
bool D3D12Context::Initialize() {
|
bool D3D12Context::Initialize() {
|
||||||
|
context_lost_ = false;
|
||||||
|
|
||||||
|
if (!target_window_) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
auto& provider = GetD3D12Provider();
|
auto& provider = GetD3D12Provider();
|
||||||
auto dxgi_factory = provider.GetDXGIFactory();
|
auto dxgi_factory = provider.GetDXGIFactory();
|
||||||
auto device = provider.GetDevice();
|
auto device = provider.GetDevice();
|
||||||
auto direct_queue = provider.GetDirectQueue();
|
auto direct_queue = provider.GetDirectQueue();
|
||||||
|
|
||||||
context_lost_ = false;
|
|
||||||
|
|
||||||
if (target_window_) {
|
|
||||||
swap_fence_current_value_ = 1;
|
swap_fence_current_value_ = 1;
|
||||||
swap_fence_completed_value_ = 0;
|
swap_fence_completed_value_ = 0;
|
||||||
swap_fence_completion_event_ = CreateEvent(nullptr, false, false, nullptr);
|
swap_fence_completion_event_ = CreateEvent(nullptr, false, false, nullptr);
|
||||||
|
@ -75,7 +72,7 @@ bool D3D12Context::Initialize() {
|
||||||
IDXGISwapChain1* swap_chain_1;
|
IDXGISwapChain1* swap_chain_1;
|
||||||
if (FAILED(dxgi_factory->CreateSwapChainForHwnd(
|
if (FAILED(dxgi_factory->CreateSwapChainForHwnd(
|
||||||
provider.GetDirectQueue(),
|
provider.GetDirectQueue(),
|
||||||
static_cast<HWND>(target_window_->native_handle()),
|
reinterpret_cast<HWND>(target_window_->native_handle()),
|
||||||
&swap_chain_desc, nullptr, nullptr, &swap_chain_1))) {
|
&swap_chain_desc, nullptr, nullptr, &swap_chain_1))) {
|
||||||
XELOGE("Failed to create a DXGI swap chain");
|
XELOGE("Failed to create a DXGI swap chain");
|
||||||
Shutdown();
|
Shutdown();
|
||||||
|
@ -136,7 +133,6 @@ bool D3D12Context::Initialize() {
|
||||||
Shutdown();
|
Shutdown();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -223,9 +219,11 @@ ImmediateDrawer* D3D12Context::immediate_drawer() {
|
||||||
return immediate_drawer_.get();
|
return immediate_drawer_.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
void D3D12Context::BeginSwap() {
|
bool D3D12Context::WasLost() { return context_lost_; }
|
||||||
|
|
||||||
|
bool D3D12Context::BeginSwap() {
|
||||||
if (!target_window_ || context_lost_) {
|
if (!target_window_ || context_lost_) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resize the swap chain if the window is resized.
|
// Resize the swap chain if the window is resized.
|
||||||
|
@ -252,13 +250,13 @@ void D3D12Context::BeginSwap() {
|
||||||
kSwapChainBufferCount, target_window_width, target_window_height,
|
kSwapChainBufferCount, target_window_width, target_window_height,
|
||||||
kSwapChainFormat, 0))) {
|
kSwapChainFormat, 0))) {
|
||||||
context_lost_ = true;
|
context_lost_ = true;
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
swap_chain_width_ = target_window_width;
|
swap_chain_width_ = target_window_width;
|
||||||
swap_chain_height_ = target_window_height;
|
swap_chain_height_ = target_window_height;
|
||||||
if (!InitializeSwapChainBuffers()) {
|
if (!InitializeSwapChainBuffers()) {
|
||||||
context_lost_ = true;
|
context_lost_ = true;
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,18 +293,11 @@ void D3D12Context::BeginSwap() {
|
||||||
D3D12_CPU_DESCRIPTOR_HANDLE back_buffer_rtv = GetSwapChainBackBufferRTV();
|
D3D12_CPU_DESCRIPTOR_HANDLE back_buffer_rtv = GetSwapChainBackBufferRTV();
|
||||||
swap_command_list_->OMSetRenderTargets(1, &back_buffer_rtv, TRUE, nullptr);
|
swap_command_list_->OMSetRenderTargets(1, &back_buffer_rtv, TRUE, nullptr);
|
||||||
float clear_color[4];
|
float clear_color[4];
|
||||||
if (cvars::d3d12_random_clear_color) {
|
GetClearColor(clear_color);
|
||||||
clear_color[0] = rand() / float(RAND_MAX); // NOLINT(runtime/threadsafe_fn)
|
|
||||||
clear_color[1] = 1.0f;
|
|
||||||
clear_color[2] = 0.0f;
|
|
||||||
} else {
|
|
||||||
clear_color[0] = 0.0f;
|
|
||||||
clear_color[1] = 0.0f;
|
|
||||||
clear_color[2] = 0.0f;
|
|
||||||
}
|
|
||||||
clear_color[3] = 1.0f;
|
|
||||||
swap_command_list_->ClearRenderTargetView(back_buffer_rtv, clear_color, 0,
|
swap_command_list_->ClearRenderTargetView(back_buffer_rtv, clear_color, 0,
|
||||||
nullptr);
|
nullptr);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void D3D12Context::EndSwap() {
|
void D3D12Context::EndSwap() {
|
||||||
|
|
|
@ -28,9 +28,9 @@ class D3D12Context : public GraphicsContext {
|
||||||
|
|
||||||
ImmediateDrawer* immediate_drawer() override;
|
ImmediateDrawer* immediate_drawer() override;
|
||||||
|
|
||||||
bool WasLost() override { return context_lost_; }
|
bool WasLost() override;
|
||||||
|
|
||||||
void BeginSwap() override;
|
bool BeginSwap() override;
|
||||||
void EndSwap() override;
|
void EndSwap() override;
|
||||||
|
|
||||||
std::unique_ptr<RawImage> Capture() override;
|
std::unique_ptr<RawImage> Capture() override;
|
||||||
|
@ -69,11 +69,10 @@ class D3D12Context : public GraphicsContext {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class D3D12Provider;
|
friend class D3D12Provider;
|
||||||
|
|
||||||
explicit D3D12Context(D3D12Provider* provider, Window* target_window);
|
explicit D3D12Context(D3D12Provider* provider, Window* target_window);
|
||||||
|
bool Initialize();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool Initialize();
|
|
||||||
bool InitializeSwapChainBuffers();
|
bool InitializeSwapChainBuffers();
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
|
|
||||||
|
|
|
@ -383,6 +383,14 @@ bool D3D12Provider::Initialize() {
|
||||||
device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_DSV);
|
device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_DSV);
|
||||||
|
|
||||||
// Check if optional features are supported.
|
// Check if optional features are supported.
|
||||||
|
// D3D12_HEAP_FLAG_CREATE_NOT_ZEROED requires Windows 10 2004 (indicated by
|
||||||
|
// the availability of ID3D12Device8 or D3D12_FEATURE_D3D12_OPTIONS7).
|
||||||
|
heap_flag_create_not_zeroed_ = D3D12_HEAP_FLAG_NONE;
|
||||||
|
D3D12_FEATURE_DATA_D3D12_OPTIONS7 options7;
|
||||||
|
if (SUCCEEDED(device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS7,
|
||||||
|
&options7, sizeof(options7)))) {
|
||||||
|
heap_flag_create_not_zeroed_ = D3D12_HEAP_FLAG_CREATE_NOT_ZEROED;
|
||||||
|
}
|
||||||
rasterizer_ordered_views_supported_ = false;
|
rasterizer_ordered_views_supported_ = false;
|
||||||
resource_binding_tier_ = D3D12_RESOURCE_BINDING_TIER_1;
|
resource_binding_tier_ = D3D12_RESOURCE_BINDING_TIER_1;
|
||||||
tiled_resources_tier_ = D3D12_TILED_RESOURCES_TIER_NOT_SUPPORTED;
|
tiled_resources_tier_ = D3D12_TILED_RESOURCES_TIER_NOT_SUPPORTED;
|
||||||
|
@ -409,14 +417,6 @@ bool D3D12Provider::Initialize() {
|
||||||
virtual_address_bits_per_resource_ =
|
virtual_address_bits_per_resource_ =
|
||||||
virtual_address_support.MaxGPUVirtualAddressBitsPerResource;
|
virtual_address_support.MaxGPUVirtualAddressBitsPerResource;
|
||||||
}
|
}
|
||||||
// D3D12_HEAP_FLAG_CREATE_NOT_ZEROED requires Windows 10 2004 (indicated by
|
|
||||||
// the availability of ID3D12Device8 or D3D12_FEATURE_D3D12_OPTIONS7).
|
|
||||||
heap_flag_create_not_zeroed_ = D3D12_HEAP_FLAG_NONE;
|
|
||||||
D3D12_FEATURE_DATA_D3D12_OPTIONS7 options7;
|
|
||||||
if (SUCCEEDED(device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS7,
|
|
||||||
&options7, sizeof(options7)))) {
|
|
||||||
heap_flag_create_not_zeroed_ = D3D12_HEAP_FLAG_CREATE_NOT_ZEROED;
|
|
||||||
}
|
|
||||||
XELOGD3D(
|
XELOGD3D(
|
||||||
"Direct3D 12 device and OS features:\n"
|
"Direct3D 12 device and OS features:\n"
|
||||||
"* Max GPU virtual address bits per resource: {}\n"
|
"* Max GPU virtual address bits per resource: {}\n"
|
||||||
|
|
|
@ -68,6 +68,9 @@ class D3D12Provider : public GraphicsProvider {
|
||||||
uint32_t GetAdapterVendorID() const { return adapter_vendor_id_; }
|
uint32_t GetAdapterVendorID() const { return adapter_vendor_id_; }
|
||||||
|
|
||||||
// Device features.
|
// Device features.
|
||||||
|
D3D12_HEAP_FLAGS GetHeapFlagCreateNotZeroed() const {
|
||||||
|
return heap_flag_create_not_zeroed_;
|
||||||
|
}
|
||||||
D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER
|
D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER
|
||||||
GetProgrammableSamplePositionsTier() const {
|
GetProgrammableSamplePositionsTier() const {
|
||||||
return programmable_sample_positions_tier_;
|
return programmable_sample_positions_tier_;
|
||||||
|
@ -84,9 +87,6 @@ class D3D12Provider : public GraphicsProvider {
|
||||||
uint32_t GetVirtualAddressBitsPerResource() const {
|
uint32_t GetVirtualAddressBitsPerResource() const {
|
||||||
return virtual_address_bits_per_resource_;
|
return virtual_address_bits_per_resource_;
|
||||||
}
|
}
|
||||||
D3D12_HEAP_FLAGS GetHeapFlagCreateNotZeroed() const {
|
|
||||||
return heap_flag_create_not_zeroed_;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Proxies for Direct3D 12 functions since they are loaded dynamically.
|
// Proxies for Direct3D 12 functions since they are loaded dynamically.
|
||||||
inline HRESULT SerializeRootSignature(const D3D12_ROOT_SIGNATURE_DESC* desc,
|
inline HRESULT SerializeRootSignature(const D3D12_ROOT_SIGNATURE_DESC* desc,
|
||||||
|
@ -162,12 +162,12 @@ class D3D12Provider : public GraphicsProvider {
|
||||||
|
|
||||||
uint32_t adapter_vendor_id_;
|
uint32_t adapter_vendor_id_;
|
||||||
|
|
||||||
|
D3D12_HEAP_FLAGS heap_flag_create_not_zeroed_;
|
||||||
D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER programmable_sample_positions_tier_;
|
D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER programmable_sample_positions_tier_;
|
||||||
bool rasterizer_ordered_views_supported_;
|
bool rasterizer_ordered_views_supported_;
|
||||||
D3D12_RESOURCE_BINDING_TIER resource_binding_tier_;
|
D3D12_RESOURCE_BINDING_TIER resource_binding_tier_;
|
||||||
D3D12_TILED_RESOURCES_TIER tiled_resources_tier_;
|
D3D12_TILED_RESOURCES_TIER tiled_resources_tier_;
|
||||||
uint32_t virtual_address_bits_per_resource_;
|
uint32_t virtual_address_bits_per_resource_;
|
||||||
D3D12_HEAP_FLAGS heap_flag_create_not_zeroed_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace d3d12
|
} // namespace d3d12
|
||||||
|
|
|
@ -9,8 +9,13 @@
|
||||||
|
|
||||||
#include "xenia/ui/graphics_context.h"
|
#include "xenia/ui/graphics_context.h"
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
#include "xenia/base/cvar.h"
|
||||||
#include "xenia/ui/graphics_provider.h"
|
#include "xenia/ui/graphics_provider.h"
|
||||||
|
|
||||||
|
DEFINE_bool(random_clear_color, false, "Randomize window clear color.", "UI");
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace ui {
|
namespace ui {
|
||||||
|
|
||||||
|
@ -26,5 +31,18 @@ bool GraphicsContext::MakeCurrent() { return true; }
|
||||||
|
|
||||||
void GraphicsContext::ClearCurrent() {}
|
void GraphicsContext::ClearCurrent() {}
|
||||||
|
|
||||||
|
void GraphicsContext::GetClearColor(float* rgba) {
|
||||||
|
if (cvars::random_clear_color) {
|
||||||
|
rgba[0] = rand() / float(RAND_MAX); // NOLINT(runtime/threadsafe_fn)
|
||||||
|
rgba[1] = 1.0f;
|
||||||
|
rgba[2] = 0.0f;
|
||||||
|
} else {
|
||||||
|
rgba[0] = 0.0f;
|
||||||
|
rgba[1] = 0.0f;
|
||||||
|
rgba[2] = 0.0f;
|
||||||
|
}
|
||||||
|
rgba[3] = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ui
|
} // namespace ui
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
|
@ -51,7 +51,8 @@ class GraphicsContext {
|
||||||
// This context must be made current in order for this call to work properly.
|
// This context must be made current in order for this call to work properly.
|
||||||
virtual bool WasLost() = 0;
|
virtual bool WasLost() = 0;
|
||||||
|
|
||||||
virtual void BeginSwap() = 0;
|
// Returns true if able to draw now (the target surface is available).
|
||||||
|
virtual bool BeginSwap() = 0;
|
||||||
virtual void EndSwap() = 0;
|
virtual void EndSwap() = 0;
|
||||||
|
|
||||||
virtual std::unique_ptr<RawImage> Capture() = 0;
|
virtual std::unique_ptr<RawImage> Capture() = 0;
|
||||||
|
@ -59,6 +60,8 @@ class GraphicsContext {
|
||||||
protected:
|
protected:
|
||||||
explicit GraphicsContext(GraphicsProvider* provider, Window* target_window);
|
explicit GraphicsContext(GraphicsProvider* provider, Window* target_window);
|
||||||
|
|
||||||
|
static void GetClearColor(float* rgba);
|
||||||
|
|
||||||
GraphicsProvider* provider_ = nullptr;
|
GraphicsProvider* provider_ = nullptr;
|
||||||
Window* target_window_ = nullptr;
|
Window* target_window_ = nullptr;
|
||||||
};
|
};
|
||||||
|
|
|
@ -141,7 +141,7 @@ bool VulkanContext::MakeCurrent() {
|
||||||
|
|
||||||
void VulkanContext::ClearCurrent() {}
|
void VulkanContext::ClearCurrent() {}
|
||||||
|
|
||||||
void VulkanContext::BeginSwap() {
|
bool VulkanContext::BeginSwap() {
|
||||||
SCOPE_profile_cpu_f("gpu");
|
SCOPE_profile_cpu_f("gpu");
|
||||||
auto provider = static_cast<VulkanProvider*>(provider_);
|
auto provider = static_cast<VulkanProvider*>(provider_);
|
||||||
auto device = provider->device();
|
auto device = provider->device();
|
||||||
|
@ -170,6 +170,8 @@ void VulkanContext::BeginSwap() {
|
||||||
// TODO(benvanik): use a fence instead? May not be possible with target image.
|
// TODO(benvanik): use a fence instead? May not be possible with target image.
|
||||||
std::lock_guard<std::mutex> queue_lock(device->primary_queue_mutex());
|
std::lock_guard<std::mutex> queue_lock(device->primary_queue_mutex());
|
||||||
status = vkQueueWaitIdle(device->primary_queue());
|
status = vkQueueWaitIdle(device->primary_queue());
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanContext::EndSwap() {
|
void VulkanContext::EndSwap() {
|
||||||
|
|
|
@ -40,7 +40,7 @@ class VulkanContext : public GraphicsContext {
|
||||||
|
|
||||||
bool WasLost() override { return context_lost_; }
|
bool WasLost() override { return context_lost_; }
|
||||||
|
|
||||||
void BeginSwap() override;
|
bool BeginSwap() override;
|
||||||
void EndSwap() override;
|
void EndSwap() override;
|
||||||
|
|
||||||
std::unique_ptr<RawImage> Capture() override;
|
std::unique_ptr<RawImage> Capture() override;
|
||||||
|
|
|
@ -200,11 +200,15 @@ void Window::OnPaint(UIEvent* e) {
|
||||||
io.DisplaySize = ImVec2(static_cast<float>(scaled_width()),
|
io.DisplaySize = ImVec2(static_cast<float>(scaled_width()),
|
||||||
static_cast<float>(scaled_height()));
|
static_cast<float>(scaled_height()));
|
||||||
|
|
||||||
context_->BeginSwap();
|
bool can_swap = context_->BeginSwap();
|
||||||
if (context_->WasLost()) {
|
if (context_->WasLost()) {
|
||||||
on_context_lost(e);
|
on_context_lost(e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (!can_swap) {
|
||||||
|
// Surface not available.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ImGui::NewFrame();
|
ImGui::NewFrame();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue