[D3D12] ID3D12Device creation
This commit is contained in:
parent
e9083dbc2f
commit
03682e81d1
|
@ -0,0 +1,18 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* Xenia : Xbox 360 Emulator Research Project *
|
||||||
|
******************************************************************************
|
||||||
|
* Copyright 2018 Ben Vanik. All rights reserved. *
|
||||||
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef XENIA_UI_D3D12_D3D12_API_H_
|
||||||
|
#define XENIA_UI_D3D12_D3D12_API_H_
|
||||||
|
|
||||||
|
#include <dxgi1_4.h>
|
||||||
|
#include <d3d12.h>
|
||||||
|
|
||||||
|
#define XELOGD3D XELOGI
|
||||||
|
|
||||||
|
#endif // XENIA_UI_D3D12_D3D12_API_H_
|
|
@ -0,0 +1,165 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* Xenia : Xbox 360 Emulator Research Project *
|
||||||
|
******************************************************************************
|
||||||
|
* Copyright 2018 Ben Vanik. All rights reserved. *
|
||||||
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "xenia/ui/d3d12/d3d12_provider.h"
|
||||||
|
|
||||||
|
#include <gflags/gflags.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include "xenia/base/logging.h"
|
||||||
|
|
||||||
|
DEFINE_bool(d3d12_debug, false, "Enable Direct3D 12 and DXGI debug layer.");
|
||||||
|
DEFINE_int32(d3d12_adapter_index, -1, "Index of the DXGI adapter to use. "
|
||||||
|
"-1 for any physical adapter, -2 for WARP software rendering.");
|
||||||
|
|
||||||
|
namespace xe {
|
||||||
|
namespace ui {
|
||||||
|
namespace d3d12 {
|
||||||
|
|
||||||
|
std::unique_ptr<D3D12Provider> D3D12Provider::Create(Window* main_window) {
|
||||||
|
std::unique_ptr<D3D12Provider> provider(new D3D12Provider(main_window));
|
||||||
|
if (!provider->Initialize()) {
|
||||||
|
xe::FatalError(
|
||||||
|
"Unable to initialize Direct3D 12 graphics subsystem.\n"
|
||||||
|
"\n"
|
||||||
|
"Ensure that you have the latest drivers for your GPU and it supports "
|
||||||
|
"Direct3D 12 feature level 11_0 and typed UAV loads.\n"
|
||||||
|
"\n"
|
||||||
|
"See http://xenia.jp/faq/ for more information and a list of supported "
|
||||||
|
"GPUs.");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return provider;
|
||||||
|
}
|
||||||
|
|
||||||
|
D3D12Provider::D3D12Provider(Window* main_window)
|
||||||
|
: GraphicsProvider(main_window) {}
|
||||||
|
|
||||||
|
D3D12Provider::~D3D12Provider() {
|
||||||
|
if (direct_queue_ != nullptr) {
|
||||||
|
direct_queue_->Release();
|
||||||
|
}
|
||||||
|
if (device_ != nullptr) {
|
||||||
|
device_->Release();
|
||||||
|
}
|
||||||
|
if (dxgi_factory_ != nullptr) {
|
||||||
|
dxgi_factory_->Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool D3D12Provider::Initialize() {
|
||||||
|
// Enable the debug layer.
|
||||||
|
bool debug = FLAGS_d3d12_debug;
|
||||||
|
if (debug) {
|
||||||
|
ID3D12Debug* debug_interface;
|
||||||
|
if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debug_interface)))) {
|
||||||
|
debug_interface->EnableDebugLayer();
|
||||||
|
debug_interface->Release();
|
||||||
|
} else {
|
||||||
|
XELOGW("Failed to enable the Direct3D 12 debug layer");
|
||||||
|
debug = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the DXGI factory.
|
||||||
|
IDXGIFactory2* dxgi_factory;
|
||||||
|
if (FAILED(CreateDXGIFactory2(debug ? DXGI_CREATE_FACTORY_DEBUG : 0,
|
||||||
|
IID_PPV_ARGS(&dxgi_factory)))) {
|
||||||
|
XELOGE("Failed to create a DXGI factory");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Choose the adapter and create a device with required features.
|
||||||
|
// TODO(Triang3l): Log adapter info (contains a wide string).
|
||||||
|
uint32_t adapter_index = 0;
|
||||||
|
IDXGIAdapter1* adapter = nullptr;
|
||||||
|
ID3D12Device* device = nullptr;
|
||||||
|
while (dxgi_factory->EnumAdapters1(adapter_index, &adapter) == S_OK) {
|
||||||
|
DXGI_ADAPTER_DESC1 adapter_desc;
|
||||||
|
if (SUCCEEDED(adapter->GetDesc1(&adapter_desc))) {
|
||||||
|
if (SUCCEEDED(D3D12CreateDevice(adapter, D3D_FEATURE_LEVEL_11_0,
|
||||||
|
IID_PPV_ARGS(&device)))) {
|
||||||
|
if (IsDeviceSupported(device)) {
|
||||||
|
if (FLAGS_d3d12_adapter_index >= 0) {
|
||||||
|
if (adapter_index == FLAGS_d3d12_adapter_index) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (FLAGS_d3d12_adapter_index == -2) {
|
||||||
|
if (adapter_desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!(adapter_desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
device->Release();
|
||||||
|
device = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
adapter->Release();
|
||||||
|
adapter = nullptr;
|
||||||
|
++adapter_index;
|
||||||
|
}
|
||||||
|
if (adapter != nullptr) {
|
||||||
|
adapter->Release();
|
||||||
|
}
|
||||||
|
if (device == nullptr) {
|
||||||
|
XELOGE("Failed to get an adapter supporting Direct3D feature level 11_0 "
|
||||||
|
"and typed UAV loads, or failed to create a Direct3D 12 device.");
|
||||||
|
dxgi_factory->Release();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the command queue for graphics.
|
||||||
|
D3D12_COMMAND_QUEUE_DESC queue_desc;
|
||||||
|
queue_desc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
|
||||||
|
queue_desc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL;
|
||||||
|
queue_desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
|
||||||
|
queue_desc.NodeMask = 0;
|
||||||
|
ID3D12CommandQueue* direct_queue;
|
||||||
|
if (FAILED(device->CreateCommandQueue(&queue_desc,
|
||||||
|
IID_PPV_ARGS(&direct_queue)))) {
|
||||||
|
XELOGE("Failed to create a direct command queue");
|
||||||
|
device->Release();
|
||||||
|
dxgi_factory->Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
dxgi_factory_ = dxgi_factory;
|
||||||
|
device_ = device;
|
||||||
|
direct_queue_ = direct_queue;
|
||||||
|
|
||||||
|
// Get descriptor sizes for each type.
|
||||||
|
descriptor_size_view_ = device->GetDescriptorHandleIncrementSize(
|
||||||
|
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
|
||||||
|
descriptor_size_sampler_ = device->GetDescriptorHandleIncrementSize(
|
||||||
|
D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
|
||||||
|
descriptor_size_rtv_ =
|
||||||
|
device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
|
||||||
|
descriptor_size_dsv_ =
|
||||||
|
device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_DSV);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool D3D12Provider::IsDeviceSupported(ID3D12Device* device) {
|
||||||
|
D3D12_FEATURE_DATA_D3D12_OPTIONS options;
|
||||||
|
if (FAILED(device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS, &options,
|
||||||
|
sizeof(options)))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Typed UAV loads required for vertex fetch and post-resolve tiling.
|
||||||
|
return !!options.TypedUAVLoadAdditionalFormats;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace d3d12
|
||||||
|
} // namespace ui
|
||||||
|
} // namespace xe
|
|
@ -0,0 +1,59 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* Xenia : Xbox 360 Emulator Research Project *
|
||||||
|
******************************************************************************
|
||||||
|
* Copyright 2018 Ben Vanik. All rights reserved. *
|
||||||
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef XENIA_UI_D3D12_D3D12_PROVIDER_H_
|
||||||
|
#define XENIA_UI_D3D12_D3D12_PROVIDER_H_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "xenia/ui/d3d12/d3d12_api.h"
|
||||||
|
#include "xenia/ui/graphics_provider.h"
|
||||||
|
|
||||||
|
namespace xe {
|
||||||
|
namespace ui {
|
||||||
|
namespace d3d12 {
|
||||||
|
|
||||||
|
class D3D12Provider : public GraphicsProvider {
|
||||||
|
public:
|
||||||
|
~D3D12Provider() override;
|
||||||
|
|
||||||
|
static std::unique_ptr<D3D12Provider> Create(Window* main_window);
|
||||||
|
|
||||||
|
IDXGIFactory2* get_dxgi_factory() const { return dxgi_factory_; }
|
||||||
|
ID3D12Device* get_device() const { return device_; }
|
||||||
|
ID3D12CommandQueue* get_direct_queue() const { return direct_queue_; }
|
||||||
|
|
||||||
|
uint32_t get_descriptor_size_view() const { return descriptor_size_view_; }
|
||||||
|
uint32_t get_descriptor_size_sampler() const {
|
||||||
|
return descriptor_size_sampler_;
|
||||||
|
}
|
||||||
|
uint32_t get_descriptor_size_rtv() const { return descriptor_size_rtv_; }
|
||||||
|
uint32_t get_descriptor_size_dsv() const { return descriptor_size_dsv_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
explicit D3D12Provider(Window* main_window);
|
||||||
|
|
||||||
|
bool Initialize();
|
||||||
|
static bool IsDeviceSupported(ID3D12Device* device);
|
||||||
|
|
||||||
|
IDXGIFactory2* dxgi_factory_ = nullptr;
|
||||||
|
ID3D12Device* device_ = nullptr;
|
||||||
|
ID3D12CommandQueue* direct_queue_ = nullptr;
|
||||||
|
|
||||||
|
uint32_t descriptor_size_view_;
|
||||||
|
uint32_t descriptor_size_sampler_;
|
||||||
|
uint32_t descriptor_size_rtv_;
|
||||||
|
uint32_t descriptor_size_dsv_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace d3d12
|
||||||
|
} // namespace ui
|
||||||
|
} // namespace xe
|
||||||
|
|
||||||
|
#endif // XENIA_UI_D3D12_D3D12_PROVIDER_H_
|
Loading…
Reference in New Issue