Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions include/fast/backends/gfx_dxgi.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,7 @@ class GfxWindowBackendDXGI final : public GfxWindowBackend {
// These need to be public to be accessible in the window callback
void CreateSwapChain(IUnknown* mDevice, std::function<void()>&& before_destroy_fn);
void CreateFactoryAndDevice(bool debug, int d3d_version, class GfxRenderingAPIDX11* self,
bool (*createFunc)(class GfxRenderingAPIDX11* self, IDXGIAdapter1* adapter,
bool test_only));
bool (*createFunc)(class GfxRenderingAPIDX11* self, bool SoftwareRenderer));
void OnKeydown(WPARAM wParam, LPARAM lParam);
void OnKeyup(WPARAM wParam, LPARAM lParam);
void OnMouseButtonDown(int btn);
Expand Down
94 changes: 82 additions & 12 deletions src/fast/backends/gfx_direct3d11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,26 +97,96 @@ void GfxRenderingAPIDX11::CreateDepthStencilObjects(uint32_t width, uint32_t hei
ThrowIfFailed(mDevice->CreateShaderResourceView(texture.Get(), &srv_desc, srv));
}
}
static bool CreateDeviceFunc(class GfxRenderingAPIDX11* self, IDXGIAdapter1* adapter, bool test_only) {
static bool CreateDeviceFunc(class GfxRenderingAPIDX11* self, bool SoftwareRenderer) {
#if DEBUG_D3D
UINT device_creation_flags = D3D11_CREATE_DEVICE_DEBUG;
#else
UINT device_creation_flags = 0;
#endif
D3D_FEATURE_LEVEL FeatureLevels[] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0 };
bool CreationFailed = false;
const char HardwareText[320] = "\nUsing software renderer. Performance issues are to be expected.\n\n"
"Please check your preferred GPU in Windows graphics or GPU driver settings and "
"make sure you have the correct GPU drivers installed.\n\n"
"You can also try to change the graphic backend of the port in its config file.\n"
"Window->Backend->Id\n"
"0 = DX11, 1 = OpenGL";
const char SoftwareText[33] = "\nUsing software renderer failed.";

if (SoftwareRenderer) {
SPDLOG_INFO("Using software renderer.");
}

HRESULT res = self->mDX11CreateDevice(
NULL, SoftwareRenderer ? D3D_DRIVER_TYPE_WARP : D3D_DRIVER_TYPE_HARDWARE, nullptr, device_creation_flags, NULL,
NULL, D3D11_SDK_VERSION, self->mDevice.GetAddressOf(), &self->mFeatureLevel, self->mContext.GetAddressOf());

// Get and log name of adapter
IDXGIDevice* DXGIDevice = nullptr;
IDXGIAdapter* Adapter = nullptr;
DXGI_ADAPTER_DESC adapterDesc;
std::wstring adapterName;
char adapterNameCStr[128] = "";
char error_message[512];
HRESULT res2;

res2 = self->mDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&DXGIDevice);
if (SUCCEEDED(res2)) {
res2 = DXGIDevice->GetAdapter(&Adapter);
if (SUCCEEDED(res2)) {
res2 = Adapter->GetDesc(&adapterDesc);
if (SUCCEEDED(res2)) {
adapterName = adapterDesc.Description;
wcstombs(adapterNameCStr, adapterName.c_str(), 128);
}
Adapter->Release();
}
DXGIDevice->Release();
}
SPDLOG_INFO("Using D3D adapter: {0}", adapterNameCStr);

if (FAILED(res)) {
CreationFailed = true;
SPDLOG_WARN("Failed to create a D3D device. HRESULT: 0x{0:08x}", res);
sprintf(error_message, "Failed to create a D3D device on %s\nHRESULT: 0x%08X%s", adapterNameCStr, res,
SoftwareRenderer ? SoftwareText : HardwareText);
}

HRESULT res = self->mDX11CreateDevice(adapter,
D3D_DRIVER_TYPE_UNKNOWN, // since we use a specific adapter
nullptr, device_creation_flags, FeatureLevels, ARRAYSIZE(FeatureLevels),
D3D11_SDK_VERSION, test_only ? nullptr : self->mDevice.GetAddressOf(),
&self->mFeatureLevel, test_only ? nullptr : self->mContext.GetAddressOf());
else if (self->mFeatureLevel < D3D_FEATURE_LEVEL_10_0) {
CreationFailed = true;
SPDLOG_WARN("D3D adapter doesn't support D3D feature level 10_0 or greater.");
sprintf(error_message, "%s doesn't support D3D feature level 10_0 or greater.%s", adapterNameCStr,
SoftwareRenderer ? SoftwareText : HardwareText);
}

else if (self->mFeatureLevel < D3D_FEATURE_LEVEL_10_1) {
SPDLOG_WARN("D3D adapter doesn't support D3D feature level 10_1 or greater. MSAA setting will be ignored.");

if (test_only) {
return SUCCEEDED(res);
} else {
ThrowIfFailed(res, self->mWindowBackend->GetWindowHandle(), "Failed to create D3D11 device.");
return true;
// Check for Compute Shader support
if (self->mDevice != NULL) {
D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS features;
self->mDevice->CheckFeatureSupport(D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS, &features,
sizeof(D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS));
if (features.ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x == false) {
CreationFailed = true;
SPDLOG_WARN("D3D adapter doesn't support compute shaders.");
sprintf(error_message, "%s doesn't support compute shaders.%s", adapterNameCStr,
SoftwareRenderer ? SoftwareText : HardwareText);
}
}
}

if (CreationFailed) {
if (self->mContext) {
self->mContext->Release();
}
if (self->mDevice) {
self->mDevice->Release();
}
MessageBoxA(self->mWindowBackend->GetWindowHandle(), error_message, "Warning", MB_OK | MB_ICONWARNING);
return false;
}
return true;
};

void GfxRenderingAPIDX11::Init() {
Expand Down Expand Up @@ -752,7 +822,7 @@ void GfxRenderingAPIDX11::UpdateFramebufferParameters(int fb_id, uint32_t width,

width = ((width) > (1U) ? (width) : (1U));
height = ((height) > (1U) ? (height) : (1U));
// We can't use MSAA the way we are using it on Feature Level 10.0 Hardware, so disable it altogether.
// We can't use MSAA the way we are using it on feature level 10_0 hardware, so disable it altogether.
msaa_level = mFeatureLevel < D3D_FEATURE_LEVEL_10_1 ? 1 : msaa_level;
while (msaa_level > 1 && mMsaaNumQualityLevels[msaa_level - 1] == 0) {
--msaa_level;
Expand Down
21 changes: 8 additions & 13 deletions src/fast/backends/gfx_dxgi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -976,7 +976,7 @@ void GfxWindowBackendDXGI::SetMaxFrameLatency(int latency) {

void GfxWindowBackendDXGI::CreateFactoryAndDevice(bool debug, int d3d_version, class GfxRenderingAPIDX11* self,
bool (*createFunc)(class GfxRenderingAPIDX11* self,
IDXGIAdapter1* adapter, bool test_only)) {
bool SoftwareRenderer)) {
if (CreateDXGIFactory2 != nullptr) {
ThrowIfFailed(CreateDXGIFactory2(debug ? DXGI_CREATE_FACTORY_DEBUG : 0, __uuidof(IDXGIFactory2), &mFactory));
} else {
Expand All @@ -996,19 +996,14 @@ void GfxWindowBackendDXGI::CreateFactoryAndDevice(bool debug, int d3d_version, c

mTearingSupport = SUCCEEDED(hr) && allowTearing;
}

ComPtr<IDXGIAdapter1> adapter;
for (UINT i = 0; mFactory->EnumAdapters1(i, &adapter) != DXGI_ERROR_NOT_FOUND; i++) {
DXGI_ADAPTER_DESC1 desc;
adapter->GetDesc1(&desc);
if (desc.Flags & 2 /*DXGI_ADAPTER_FLAG_SOFTWARE*/) { // declaration missing in mingw headers
continue;
}
if (createFunc(self, adapter.Get(), true)) {
break;
}
// Try preferred hardware adapter and then try software adapter (WARP), if that fails.
// Maybe we can try a different renderer (like OpenGL) here first before software?
if (!createFunc(self, false) && !createFunc(self, true)) {
SPDLOG_CRITICAL("Creating D3D renderer failed. Exiting");
MessageBoxA(self->mWindowBackend->GetWindowHandle(), "Creating D3D renderer failed. Exiting", "Error",
MB_OK | MB_ICONERROR);
throw;
}
createFunc(self, adapter.Get(), false);
}

void GfxWindowBackendDXGI::CreateSwapChain(IUnknown* mDevice, std::function<void()>&& before_destroy_fn) {
Expand Down
Loading