Skip to content

Commit aa3ef8b

Browse files
committed
[dxvk] Re-add workaround for failed device creation with NVX extensions
Apparently Planetside 2 needs this. Obviously this means no DLSS for affected users.
1 parent 8ee0104 commit aa3ef8b

4 files changed

Lines changed: 47 additions & 21 deletions

File tree

src/dxvk/dxvk_adapter.cpp

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -161,26 +161,41 @@ namespace dxvk {
161161

162162

163163
Rc<DxvkDevice> DxvkAdapter::createDevice() {
164+
Rc<DxvkDevice> device = createDevice(false);
165+
166+
if (!device)
167+
device = createDevice(true);
168+
169+
if (!device)
170+
throw DxvkError("Failed to initialize DXVK device.");
171+
172+
return device;
173+
}
174+
175+
176+
Rc<DxvkDevice> DxvkAdapter::createDevice(bool safeMode) {
164177
auto vk = m_instance->vki();
165178

179+
DxvkDeviceCapabilities caps(*m_instance, m_handle, nullptr, safeMode);
180+
166181
Logger::info("Creating device:");
167-
m_capabilities.logDeviceInfo();
182+
caps.logDeviceInfo();
168183

169184
// Get device features to enable
170185
size_t featureBlobSize = 0u;
171-
m_capabilities.queryDeviceFeatures(&featureBlobSize, nullptr);
186+
caps.queryDeviceFeatures(&featureBlobSize, nullptr);
172187

173188
std::vector<char> featureBlob(featureBlobSize);
174-
m_capabilities.queryDeviceFeatures(&featureBlobSize, featureBlob.data());
189+
caps.queryDeviceFeatures(&featureBlobSize, featureBlob.data());
175190

176191
auto features = reinterpret_cast<const VkPhysicalDeviceFeatures2*>(featureBlob.data());
177192

178193
// Get extension list and add extra extensions
179194
uint32_t extensionCount = 0u;
180-
m_capabilities.queryDeviceExtensions(&extensionCount, nullptr);
195+
caps.queryDeviceExtensions(&extensionCount, nullptr);
181196

182197
std::vector<VkExtensionProperties> extensions(extensionCount);
183-
m_capabilities.queryDeviceExtensions(&extensionCount, extensions.data());
198+
caps.queryDeviceExtensions(&extensionCount, extensions.data());
184199

185200
for (const auto& extra : m_extraExtensions) {
186201
bool found = false;
@@ -202,13 +217,13 @@ namespace dxvk {
202217
extensionNames.push_back(ext.extensionName);
203218

204219
// Query queue infos
205-
DxvkDeviceQueueMapping queueMapping = m_capabilities.getQueueMapping();
220+
DxvkDeviceQueueMapping queueMapping = caps.getQueueMapping();
206221

207222
uint32_t queueCount = { };
208-
m_capabilities.queryDeviceQueues(&queueCount, nullptr);
223+
caps.queryDeviceQueues(&queueCount, nullptr);
209224

210225
std::vector<VkDeviceQueueCreateInfo> queues(queueCount, { VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO });
211-
m_capabilities.queryDeviceQueues(&queueCount, queues.data());
226+
caps.queryDeviceQueues(&queueCount, queues.data());
212227

213228
uint32_t priorityCount = 0u;
214229

@@ -224,7 +239,7 @@ namespace dxvk {
224239
priorityIndex += q.queueCount;
225240
}
226241

227-
m_capabilities.queryDeviceQueues(&queueCount, queues.data());
242+
caps.queryDeviceQueues(&queueCount, queues.data());
228243

229244
// Create the actual Vulkan device
230245
VkDeviceCreateInfo deviceInfo = { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO };
@@ -238,8 +253,11 @@ namespace dxvk {
238253
VkDevice device = VK_NULL_HANDLE;
239254
VkResult vr = vk->vkCreateDevice(m_handle, &deviceInfo, nullptr, &device);
240255

241-
if (vr)
242-
throw DxvkError(str::format("Failed to create Vulkan device: ", vr));
256+
if (vr) {
257+
Logger::err(str::format("Failed to create Vulkan device: ", vr,
258+
safeMode ? "" : ", retrying 'safe mode'."));
259+
return nullptr;
260+
}
243261

244262
Rc<vk::DeviceFn> vkd = new vk::DeviceFn(vk, true, device);
245263

@@ -248,7 +266,7 @@ namespace dxvk {
248266
deviceQueues.transfer = getDeviceQueue(vkd, queueMapping.transfer);
249267
deviceQueues.sparse = getDeviceQueue(vkd, queueMapping.sparse);
250268

251-
return new DxvkDevice(m_instance, this, vkd, m_capabilities.getFeatures(), deviceQueues, DxvkQueueCallback());
269+
return new DxvkDevice(m_instance, this, vkd, caps.getFeatures(), deviceQueues, DxvkQueueCallback());
252270
}
253271

254272

src/dxvk/dxvk_adapter.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,8 @@ namespace dxvk {
322322

323323
std::array<DxvkAdapterMemoryStats, VK_MAX_MEMORY_HEAPS> m_memoryStats = { };
324324

325+
Rc<DxvkDevice> createDevice(bool safeMode);
326+
325327
};
326328

327329
}

src/dxvk/dxvk_device_info.cpp

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,8 @@ namespace dxvk {
8888
DxvkDeviceCapabilities::DxvkDeviceCapabilities(
8989
const DxvkInstance& instance,
9090
VkPhysicalDevice adapter,
91-
const VkDeviceCreateInfo* deviceInfo) {
91+
const VkDeviceCreateInfo* deviceInfo,
92+
bool safeMode) {
9293
// Can't query anything on a Vulkan 1.0 device
9394
auto vk = instance.vki();
9495
vk->vkGetPhysicalDeviceProperties(adapter, &m_properties.core.properties);
@@ -102,7 +103,7 @@ namespace dxvk {
102103
initQueueProperties(instance, adapter, deviceInfo);
103104
initMemoryProperties(instance, adapter);
104105

105-
disableUnusedFeatures(instance);
106+
disableUnusedFeatures(instance, safeMode);
106107

107108
enableFeaturesAndExtensions();
108109
enableQueues();
@@ -456,7 +457,8 @@ namespace dxvk {
456457

457458

458459
void DxvkDeviceCapabilities::disableUnusedFeatures(
459-
const DxvkInstance& instance) {
460+
const DxvkInstance& instance,
461+
bool safeMode) {
460462
if (m_featuresSupported.extDescriptorHeap.descriptorHeap) {
461463
// Only enable descriptor heaps on drivers that are either known to work,
462464
// or are maintained well enough that any issues are likely to get fixed
@@ -502,14 +504,16 @@ namespace dxvk {
502504
if (!instance.options().enableUnifiedImageLayout)
503505
m_featuresSupported.khrUnifiedImageLayouts.unifiedImageLayouts = VK_FALSE;
504506

505-
if (env::is32BitHostPlatform()) {
506-
// CUDA interop is unnecessary on 32-bit, no games use it
507+
if (env::is32BitHostPlatform() || safeMode) {
508+
// CUDA interop is unnecessary on 32-bit, no games use it. These extensions
509+
// can also cause device creation errors for unknown reasons.
507510
m_featuresSupported.nvxBinaryImport = VK_FALSE;
508511
m_featuresSupported.nvxImageViewHandle = VK_FALSE;
512+
}
509513

510-
// Reflex is broken on 32-bit
514+
// Reflex is broken on 32-bit
515+
if (env::is32BitHostPlatform())
511516
m_featuresSupported.nvLowLatency2 = VK_FALSE;
512-
}
513517

514518
// EXT_multi_draw is broken on proprietary qcom on some devices
515519
if (m_properties.vk12.driverID == VK_DRIVER_ID_QUALCOMM_PROPRIETARY)

src/dxvk/dxvk_device_info.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,8 @@ namespace dxvk {
207207
DxvkDeviceCapabilities(
208208
const DxvkInstance& instance,
209209
VkPhysicalDevice adapter,
210-
const VkDeviceCreateInfo* deviceInfo);
210+
const VkDeviceCreateInfo* deviceInfo,
211+
bool safeMode = false);
211212

212213
DxvkDeviceCapabilities(const DxvkDeviceCapabilities&) = delete;
213214

@@ -370,7 +371,8 @@ namespace dxvk {
370371
VkPhysicalDevice adapter);
371372

372373
void disableUnusedFeatures(
373-
const DxvkInstance& instance);
374+
const DxvkInstance& instance,
375+
bool safeMode);
374376

375377
void enableFeaturesAndExtensions();
376378

0 commit comments

Comments
 (0)