mirror of https://github.com/doitsujin/dxvk
Compare commits
66 Commits
5a5fe29a45
...
f57f084bda
Author | SHA1 | Date |
---|---|---|
Rémi Bernon | f57f084bda | |
Philip Rebohle | 462165da19 | |
Philip Rebohle | 3f27a0ee58 | |
Katharine Chui | aac3396671 | |
Katharine Chui | 92a43ebf65 | |
Blisto91 | 8ba5256dc7 | |
Philip Rebohle | 2b70ba8f77 | |
Philip Rebohle | 9c66c4bf1d | |
Philip Rebohle | 00872e9e4f | |
Philip Rebohle | 35157357dd | |
Philip Rebohle | 617ebf4e05 | |
Philip Rebohle | c2489d5a45 | |
Philip Rebohle | 6ef98c613f | |
Philip Rebohle | 7441137a33 | |
WinterSnowfall | 571948cfc0 | |
Martino Fontana | 133f0794bc | |
Philip Rebohle | 44695f9311 | |
Casey Bowman | 49e9ea5f5a | |
Blisto91 | 198bd3a4b8 | |
Philip Rebohle | f06c646315 | |
Philip Rebohle | 855b2746b6 | |
Blisto91 | 28c7c09bf5 | |
Philip Rebohle | 2742486540 | |
Philip Rebohle | 037d0fa1ad | |
Philip Rebohle | cbf51a7a25 | |
Philip Rebohle | 70e34dc31c | |
Philip Rebohle | c5aeb0f87a | |
Philip Rebohle | a163082770 | |
Blisto91 | 2e1a19c7fd | |
Joshua Ashton | 0beb18ef73 | |
Joshua Ashton | ef4428ab8c | |
Philip Rebohle | 1085ba713e | |
Philip Rebohle | e857b09432 | |
Kaitlyn | 538f1d13d4 | |
Kaitlyn | 783c9d4591 | |
Kaitlyn | 1a685b1c67 | |
Robin Kertels | 8b8be7c2bf | |
Billy Laws | 0776d764a4 | |
Robin Kertels | 15ddadc4de | |
Philip Rebohle | 69a52b3da0 | |
Philip Rebohle | 707ad6f328 | |
Philip Rebohle | 3a6992ea97 | |
Robin Kertels | 72c86b8229 | |
Robin Kertels | 85215b10d6 | |
Philip Rebohle | fd3fbf6607 | |
Minelelol | 0a699fddb6 | |
Blisto91 | afec5cce88 | |
Ethan Lee | 4b0e3111d1 | |
Philip Rebohle | 0414bbe2d5 | |
Robin Kertels | 20490b678f | |
Blisto91 | 428c98bc63 | |
Robin Kertels | a0e39e94fa | |
Robin Kertels | eaa732d0b3 | |
Robin Kertels | 49b18f03fe | |
Philip Rebohle | c9cea93b7b | |
Philip Rebohle | 69d74a46a0 | |
Philip Rebohle | 94098aa97d | |
Philip Rebohle | c677ba9b3e | |
Philip Rebohle | 77c7396ee1 | |
Philip Rebohle | f07e5f9eaa | |
Philip Rebohle | d5c3011f54 | |
Blisto91 | 6b3b934471 | |
Philip Rebohle | 9004c132ed | |
Philip Rebohle | 24d4c9c938 | |
Philip Rebohle | 5ded7d67f0 | |
Philip Rebohle | 234f3ea071 |
34
dxvk.conf
34
dxvk.conf
|
@ -62,7 +62,7 @@
|
||||||
|
|
||||||
|
|
||||||
# Report Nvidia GPUs as AMD GPUs. Unless NVAPI support is explicitly
|
# Report Nvidia GPUs as AMD GPUs. Unless NVAPI support is explicitly
|
||||||
# enabled through proton, this is done by default in order to work
|
# enabled through Proton, this is done by default in order to work
|
||||||
# around crashes or low performance with Nvidia-speciic code paths
|
# around crashes or low performance with Nvidia-speciic code paths
|
||||||
# in games, especially Unreal Engine.
|
# in games, especially Unreal Engine.
|
||||||
#
|
#
|
||||||
|
@ -71,6 +71,13 @@
|
||||||
# dxgi.hideNvidiaGpu = Auto
|
# dxgi.hideNvidiaGpu = Auto
|
||||||
|
|
||||||
|
|
||||||
|
# Report Nvidia GPUs running on NVK as AMD GPUs.
|
||||||
|
#
|
||||||
|
# Supported values: Auto, True, False
|
||||||
|
|
||||||
|
# dxgi.hideNvkGpu = Auto
|
||||||
|
|
||||||
|
|
||||||
# Report AMD GPUs as Nvidia GPUs. This is only done for games that are
|
# Report AMD GPUs as Nvidia GPUs. This is only done for games that are
|
||||||
# known to have issues with AMDAGS or other AMD-specific code paths.
|
# known to have issues with AMDAGS or other AMD-specific code paths.
|
||||||
#
|
#
|
||||||
|
@ -90,6 +97,7 @@
|
||||||
# Override maximum amount of device memory and shared system memory
|
# Override maximum amount of device memory and shared system memory
|
||||||
# reported to the application. This may fix texture streaming issues
|
# reported to the application. This may fix texture streaming issues
|
||||||
# in games that do not support cards with large amounts of VRAM.
|
# in games that do not support cards with large amounts of VRAM.
|
||||||
|
# This is not a hard cap and applications can choose to ignore it.
|
||||||
#
|
#
|
||||||
# Supported values: Any number in Megabytes.
|
# Supported values: Any number in Megabytes.
|
||||||
|
|
||||||
|
@ -292,6 +300,18 @@
|
||||||
# d3d11.enableContextLock = False
|
# d3d11.enableContextLock = False
|
||||||
|
|
||||||
|
|
||||||
|
# Exposes or hides support for driver command lists
|
||||||
|
#
|
||||||
|
# Some games use the feature flag to decide whether to use deferred
|
||||||
|
# contexts or not. We enable this by default, but in some situations
|
||||||
|
# this can lead to issues if games detect an AMD GPU where command
|
||||||
|
# lists are not natively supported on Windows.
|
||||||
|
#
|
||||||
|
# Supported values: True, False
|
||||||
|
|
||||||
|
# d3d11.exposeDriverCommandLists = True
|
||||||
|
|
||||||
|
|
||||||
# Sets number of pipeline compiler threads.
|
# Sets number of pipeline compiler threads.
|
||||||
#
|
#
|
||||||
# If the graphics pipeline library feature is enabled, the given
|
# If the graphics pipeline library feature is enabled, the given
|
||||||
|
@ -624,18 +644,6 @@
|
||||||
|
|
||||||
# d3d9.textureMemory = 100
|
# d3d9.textureMemory = 100
|
||||||
|
|
||||||
# Always enumerate all monitors on each dxgi output
|
|
||||||
#
|
|
||||||
# Used to avoid performance degradation in some games
|
|
||||||
# (will be deprecated once QueryDisplayConfig optimization
|
|
||||||
# is in Proton Wine).
|
|
||||||
#
|
|
||||||
# Supported values:
|
|
||||||
# - True/False
|
|
||||||
|
|
||||||
# dxgi.useMonitorFallback = False
|
|
||||||
|
|
||||||
|
|
||||||
# Hide integrated graphics from applications
|
# Hide integrated graphics from applications
|
||||||
#
|
#
|
||||||
# Only has an effect when dedicated GPUs are present on the system. It is
|
# Only has an effect when dedicated GPUs are present on the system. It is
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 0bcc624926a25a2a273d07877fd25a6ff5ba1cfb
|
Subproject commit 8b246ff75c6615ba4532fe4fde20f1be090c3764
|
|
@ -1 +1 @@
|
||||||
Subproject commit 85c2334e92e215cce34e8e0ed8b2dce4700f4a50
|
Subproject commit 46dc0f6e514f5730784bb2cac2a7c731636839e8
|
21
meson.build
21
meson.build
|
@ -1,7 +1,8 @@
|
||||||
project('dxvk', ['c', 'cpp'], version : 'v2.3', meson_version : '>= 0.49', default_options : [ 'cpp_std=c++17', 'warning_level=2' ])
|
project('dxvk', ['c', 'cpp'], version : 'v2.3.1', meson_version : '>= 0.58', default_options : [ 'cpp_std=c++17', 'warning_level=2' ])
|
||||||
|
|
||||||
cpu_family = target_machine.cpu_family()
|
cpu_family = target_machine.cpu_family()
|
||||||
platform = target_machine.system()
|
platform = target_machine.system()
|
||||||
|
fs = import('fs')
|
||||||
|
|
||||||
cpp = meson.get_compiler('cpp')
|
cpp = meson.get_compiler('cpp')
|
||||||
cc = meson.get_compiler('c')
|
cc = meson.get_compiler('c')
|
||||||
|
@ -33,11 +34,17 @@ if get_option('build_id')
|
||||||
]
|
]
|
||||||
endif
|
endif
|
||||||
|
|
||||||
dxvk_include_dirs = [
|
dxvk_include_dirs = ['./include']
|
||||||
'./include',
|
if fs.is_dir('./include/vulkan/include')
|
||||||
'./include/vulkan/include',
|
dxvk_include_dirs += ['./include/vulkan/include']
|
||||||
'./include/spirv/include'
|
elif not cpp.check_header('vulkan/vulkan.h')
|
||||||
]
|
error('Missing Vulkan-Headers')
|
||||||
|
endif
|
||||||
|
if fs.is_dir('./include/spirv/include')
|
||||||
|
dxvk_include_dirs += ['./include/spirv/include']
|
||||||
|
elif not cpp.check_header('spirv/unified1/spirv.hpp')
|
||||||
|
error('Missing SPIRV-Headers')
|
||||||
|
endif
|
||||||
|
|
||||||
dep_displayinfo = dependency(
|
dep_displayinfo = dependency(
|
||||||
'libdisplay-info',
|
'libdisplay-info',
|
||||||
|
@ -153,7 +160,7 @@ def_spec_ext = '.def'
|
||||||
glsl_compiler = find_program('glslang', 'glslangValidator')
|
glsl_compiler = find_program('glslang', 'glslangValidator')
|
||||||
glsl_args = [
|
glsl_args = [
|
||||||
'--quiet',
|
'--quiet',
|
||||||
'--target-env', 'vulkan1.2',
|
'--target-env', 'vulkan1.3',
|
||||||
'--vn', '@BASENAME@',
|
'--vn', '@BASENAME@',
|
||||||
'--depfile', '@DEPFILE@',
|
'--depfile', '@DEPFILE@',
|
||||||
'@INPUT@',
|
'@INPUT@',
|
||||||
|
|
|
@ -928,6 +928,34 @@ namespace dxvk {
|
||||||
const void* pSrcData,
|
const void* pSrcData,
|
||||||
UINT SrcRowPitch,
|
UINT SrcRowPitch,
|
||||||
UINT SrcDepthPitch) {
|
UINT SrcDepthPitch) {
|
||||||
|
if (IsDeferred && unlikely(pDstBox != nullptr) && unlikely(!m_parent->GetOptions()->exposeDriverCommandLists)) {
|
||||||
|
// If called from a deferred context and native command list support is not
|
||||||
|
// exposed, we need to apply the destination box to the source pointer. This
|
||||||
|
// only applies to UpdateSubresource, not to UpdateSubresource1. See MSDN:
|
||||||
|
// https://msdn.microsoft.com/en-us/library/windows/desktop/ff476486(v=vs.85).aspx)
|
||||||
|
size_t srcOffset = pDstBox->left;
|
||||||
|
|
||||||
|
// For textures, the offset logic needs to take the format into account.
|
||||||
|
// Ignore that multi-planar images exist, this is hairy enough already.
|
||||||
|
D3D11CommonTexture* dstTexture = GetCommonTexture(pDstResource);
|
||||||
|
|
||||||
|
if (dstTexture) {
|
||||||
|
auto dstFormat = dstTexture->GetPackedFormat();
|
||||||
|
auto dstFormatInfo = lookupFormatInfo(dstFormat);
|
||||||
|
|
||||||
|
size_t blockSize = dstFormatInfo->elementSize;
|
||||||
|
|
||||||
|
VkOffset3D offset;
|
||||||
|
offset.x = pDstBox->left / dstFormatInfo->blockSize.width;
|
||||||
|
offset.y = pDstBox->top / dstFormatInfo->blockSize.height;
|
||||||
|
offset.z = pDstBox->front / dstFormatInfo->blockSize.depth;
|
||||||
|
|
||||||
|
srcOffset = offset.x * blockSize + offset.y * SrcRowPitch + offset.z * SrcDepthPitch;
|
||||||
|
}
|
||||||
|
|
||||||
|
pSrcData = reinterpret_cast<const char*>(pSrcData) + srcOffset;
|
||||||
|
}
|
||||||
|
|
||||||
UpdateResource(pDstResource, DstSubresource, pDstBox,
|
UpdateResource(pDstResource, DstSubresource, pDstBox,
|
||||||
pSrcData, SrcRowPitch, SrcDepthPitch, 0);
|
pSrcData, SrcRowPitch, SrcDepthPitch, 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,10 +45,10 @@ namespace dxvk {
|
||||||
m_dxvkDevice (pContainer->GetDXVKDevice()),
|
m_dxvkDevice (pContainer->GetDXVKDevice()),
|
||||||
m_dxvkAdapter (m_dxvkDevice->adapter()),
|
m_dxvkAdapter (m_dxvkDevice->adapter()),
|
||||||
m_d3d11Formats (m_dxvkDevice),
|
m_d3d11Formats (m_dxvkDevice),
|
||||||
m_d3d11Options (m_dxvkDevice->instance()->config(), m_dxvkDevice),
|
m_d3d11Options (m_dxvkDevice->instance()->config()),
|
||||||
m_dxbcOptions (m_dxvkDevice, m_d3d11Options),
|
m_dxbcOptions (m_dxvkDevice, m_d3d11Options),
|
||||||
m_maxFeatureLevel (GetMaxFeatureLevel(m_dxvkDevice->instance(), m_dxvkDevice->adapter())),
|
m_maxFeatureLevel (GetMaxFeatureLevel(m_dxvkDevice->instance(), m_dxvkDevice->adapter())),
|
||||||
m_deviceFeatures (m_dxvkDevice->instance(), m_dxvkDevice->adapter(), m_featureLevel) {
|
m_deviceFeatures (m_dxvkDevice->instance(), m_dxvkDevice->adapter(), m_d3d11Options, m_featureLevel) {
|
||||||
m_initializer = new D3D11Initializer(this);
|
m_initializer = new D3D11Initializer(this);
|
||||||
m_context = new D3D11ImmediateContext(this, m_dxvkDevice);
|
m_context = new D3D11ImmediateContext(this, m_dxvkDevice);
|
||||||
m_d3d10Device = new D3D10Device(this, m_context.ptr());
|
m_d3d10Device = new D3D10Device(this, m_context.ptr());
|
||||||
|
@ -1348,7 +1348,7 @@ namespace dxvk {
|
||||||
m_deviceFeatures = D3D11DeviceFeatures(
|
m_deviceFeatures = D3D11DeviceFeatures(
|
||||||
m_dxvkDevice->instance(),
|
m_dxvkDevice->instance(),
|
||||||
m_dxvkDevice->adapter(),
|
m_dxvkDevice->adapter(),
|
||||||
m_featureLevel);
|
m_d3d11Options, m_featureLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pChosenFeatureLevel)
|
if (pChosenFeatureLevel)
|
||||||
|
@ -3411,8 +3411,9 @@ namespace dxvk {
|
||||||
|
|
||||||
|
|
||||||
HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::EnqueueSetEvent(HANDLE hEvent) {
|
HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::EnqueueSetEvent(HANDLE hEvent) {
|
||||||
Logger::err("D3D11DXGIDevice::EnqueueSetEvent: Not implemented");
|
auto immediateContext = m_d3d11Device.GetContext();
|
||||||
return DXGI_ERROR_UNSUPPORTED;
|
immediateContext->Flush1(D3D11_CONTEXT_TYPE_ALL, hEvent);
|
||||||
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ namespace dxvk {
|
||||||
D3D11DeviceFeatures::D3D11DeviceFeatures(
|
D3D11DeviceFeatures::D3D11DeviceFeatures(
|
||||||
const Rc<DxvkInstance>& Instance,
|
const Rc<DxvkInstance>& Instance,
|
||||||
const Rc<DxvkAdapter>& Adapter,
|
const Rc<DxvkAdapter>& Adapter,
|
||||||
|
const D3D11Options& Options,
|
||||||
D3D_FEATURE_LEVEL FeatureLevel)
|
D3D_FEATURE_LEVEL FeatureLevel)
|
||||||
: m_features (Adapter->features()),
|
: m_features (Adapter->features()),
|
||||||
m_properties (Adapter->devicePropertiesExt()) {
|
m_properties (Adapter->devicePropertiesExt()) {
|
||||||
|
@ -118,11 +119,11 @@ namespace dxvk {
|
||||||
m_shaderMinPrecision.PixelShaderMinPrecision = 0;
|
m_shaderMinPrecision.PixelShaderMinPrecision = 0;
|
||||||
m_shaderMinPrecision.AllOtherShaderStagesMinPrecision = 0;
|
m_shaderMinPrecision.AllOtherShaderStagesMinPrecision = 0;
|
||||||
|
|
||||||
// Report native support for command lists here so that we do not actually have
|
// Report native support for command lists by default. Deferred context
|
||||||
// to re-implement the UpdateSubresource bug from the D3D11 runtime, see MSDN:
|
// usage can be beneficial for us as ExecuteCommandList has low overhead,
|
||||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/ff476486(v=vs.85).aspx)
|
// and we avoid having to deal with known UpdateSubresource bugs this way.
|
||||||
m_threading.DriverConcurrentCreates = TRUE;
|
m_threading.DriverConcurrentCreates = TRUE;
|
||||||
m_threading.DriverCommandLists = TRUE;
|
m_threading.DriverCommandLists = Options.exposeDriverCommandLists;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -182,7 +183,8 @@ namespace dxvk {
|
||||||
D3D_FEATURE_LEVEL D3D11DeviceFeatures::GetMaxFeatureLevel(
|
D3D_FEATURE_LEVEL D3D11DeviceFeatures::GetMaxFeatureLevel(
|
||||||
const Rc<DxvkInstance>& Instance,
|
const Rc<DxvkInstance>& Instance,
|
||||||
const Rc<DxvkAdapter>& Adapter) {
|
const Rc<DxvkAdapter>& Adapter) {
|
||||||
D3D11DeviceFeatures features(Instance, Adapter, D3D_FEATURE_LEVEL_12_1);
|
D3D11Options options(Instance->config());
|
||||||
|
D3D11DeviceFeatures features(Instance, Adapter, options, D3D_FEATURE_LEVEL_12_1);
|
||||||
return features.GetMaxFeatureLevel();
|
return features.GetMaxFeatureLevel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "d3d11_include.h"
|
#include "d3d11_include.h"
|
||||||
|
#include "d3d11_options.h"
|
||||||
|
|
||||||
#include "../dxvk/dxvk_adapter.h"
|
#include "../dxvk/dxvk_adapter.h"
|
||||||
#include "../dxvk/dxvk_instance.h"
|
#include "../dxvk/dxvk_instance.h"
|
||||||
|
@ -21,6 +22,7 @@ namespace dxvk {
|
||||||
D3D11DeviceFeatures(
|
D3D11DeviceFeatures(
|
||||||
const Rc<DxvkInstance>& Instance,
|
const Rc<DxvkInstance>& Instance,
|
||||||
const Rc<DxvkAdapter>& Adapter,
|
const Rc<DxvkAdapter>& Adapter,
|
||||||
|
const D3D11Options& Options,
|
||||||
D3D_FEATURE_LEVEL FeatureLevel);
|
D3D_FEATURE_LEVEL FeatureLevel);
|
||||||
|
|
||||||
~D3D11DeviceFeatures();
|
~D3D11DeviceFeatures();
|
||||||
|
|
|
@ -12,7 +12,7 @@ namespace dxvk {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
D3D11Options::D3D11Options(const Config& config, const Rc<DxvkDevice>& device) {
|
D3D11Options::D3D11Options(const Config& config) {
|
||||||
this->dcSingleUseMode = config.getOption<bool>("d3d11.dcSingleUseMode", true);
|
this->dcSingleUseMode = config.getOption<bool>("d3d11.dcSingleUseMode", true);
|
||||||
this->zeroInitWorkgroupMemory = config.getOption<bool>("d3d11.zeroInitWorkgroupMemory", false);
|
this->zeroInitWorkgroupMemory = config.getOption<bool>("d3d11.zeroInitWorkgroupMemory", false);
|
||||||
this->forceVolatileTgsmAccess = config.getOption<bool>("d3d11.forceVolatileTgsmAccess", false);
|
this->forceVolatileTgsmAccess = config.getOption<bool>("d3d11.forceVolatileTgsmAccess", false);
|
||||||
|
@ -31,6 +31,7 @@ namespace dxvk {
|
||||||
this->numBackBuffers = config.getOption<int32_t>("dxgi.numBackBuffers", 0);
|
this->numBackBuffers = config.getOption<int32_t>("dxgi.numBackBuffers", 0);
|
||||||
this->maxFrameLatency = config.getOption<int32_t>("dxgi.maxFrameLatency", 0);
|
this->maxFrameLatency = config.getOption<int32_t>("dxgi.maxFrameLatency", 0);
|
||||||
this->maxFrameRate = config.getOption<int32_t>("dxgi.maxFrameRate", 0);
|
this->maxFrameRate = config.getOption<int32_t>("dxgi.maxFrameRate", 0);
|
||||||
|
this->exposeDriverCommandLists = config.getOption<bool>("d3d11.exposeDriverCommandLists", true);
|
||||||
|
|
||||||
// Clamp LOD bias so that people don't abuse this in unintended ways
|
// Clamp LOD bias so that people don't abuse this in unintended ways
|
||||||
this->samplerLodBias = dxvk::fclamp(this->samplerLodBias, -2.0f, 1.0f);
|
this->samplerLodBias = dxvk::fclamp(this->samplerLodBias, -2.0f, 1.0f);
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
namespace dxvk {
|
namespace dxvk {
|
||||||
|
|
||||||
struct D3D11Options {
|
struct D3D11Options {
|
||||||
D3D11Options(const Config& config, const Rc<DxvkDevice>& device);
|
D3D11Options(const Config& config);
|
||||||
|
|
||||||
/// Enables speed hack for mapping on deferred contexts
|
/// Enables speed hack for mapping on deferred contexts
|
||||||
///
|
///
|
||||||
|
@ -113,6 +113,11 @@ namespace dxvk {
|
||||||
/// race conditions.
|
/// race conditions.
|
||||||
bool enableContextLock;
|
bool enableContextLock;
|
||||||
|
|
||||||
|
/// Whether to expose the driver command list feature. Enabled by
|
||||||
|
/// default and generally beneficial, but some games may assume that
|
||||||
|
/// this is not supported when running on an AMD GPU.
|
||||||
|
bool exposeDriverCommandLists;
|
||||||
|
|
||||||
/// Shader dump path
|
/// Shader dump path
|
||||||
std::string shaderDumpPath;
|
std::string shaderDumpPath;
|
||||||
};
|
};
|
||||||
|
|
|
@ -58,9 +58,6 @@ namespace dxvk {
|
||||||
"\n MiscFlags: ", m_desc.MiscFlags,
|
"\n MiscFlags: ", m_desc.MiscFlags,
|
||||||
"\n FeatureLevel: ", pDevice->GetFeatureLevel()));
|
"\n FeatureLevel: ", pDevice->GetFeatureLevel()));
|
||||||
|
|
||||||
if (m_desc.MiscFlags & D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX)
|
|
||||||
Logger::warn("D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX: not supported.");
|
|
||||||
|
|
||||||
imageInfo.shared = true;
|
imageInfo.shared = true;
|
||||||
imageInfo.sharing.mode = hSharedHandle == INVALID_HANDLE_VALUE ? DxvkSharedHandleMode::Export : DxvkSharedHandleMode::Import;
|
imageInfo.sharing.mode = hSharedHandle == INVALID_HANDLE_VALUE ? DxvkSharedHandleMode::Export : DxvkSharedHandleMode::Import;
|
||||||
imageInfo.sharing.type = (m_desc.MiscFlags & D3D11_RESOURCE_MISC_SHARED_NTHANDLE)
|
imageInfo.sharing.type = (m_desc.MiscFlags & D3D11_RESOURCE_MISC_SHARED_NTHANDLE)
|
||||||
|
@ -214,9 +211,12 @@ namespace dxvk {
|
||||||
// For some formats, we need to enable sampled and/or
|
// For some formats, we need to enable sampled and/or
|
||||||
// render target capabilities if available, but these
|
// render target capabilities if available, but these
|
||||||
// should in no way affect the default image layout
|
// should in no way affect the default image layout
|
||||||
imageInfo.usage |= EnableMetaCopyUsage(imageInfo.format, imageInfo.tiling);
|
|
||||||
imageInfo.usage |= EnableMetaPackUsage(imageInfo.format, m_desc.CPUAccessFlags);
|
imageInfo.usage |= EnableMetaPackUsage(imageInfo.format, m_desc.CPUAccessFlags);
|
||||||
|
imageInfo.usage |= EnableMetaCopyUsage(imageInfo.format, imageInfo.tiling);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < imageInfo.viewFormatCount; i++)
|
||||||
|
imageInfo.usage |= EnableMetaCopyUsage(imageInfo.viewFormats[i], imageInfo.tiling);
|
||||||
|
|
||||||
// Check if we can actually create the image
|
// Check if we can actually create the image
|
||||||
if (!CheckImageSupport(&imageInfo, imageInfo.tiling)) {
|
if (!CheckImageSupport(&imageInfo, imageInfo.tiling)) {
|
||||||
throw DxvkError(str::format(
|
throw DxvkError(str::format(
|
||||||
|
|
|
@ -298,7 +298,7 @@ namespace dxvk {
|
||||||
D3D11_BUFFER_DESC bufferDesc;
|
D3D11_BUFFER_DESC bufferDesc;
|
||||||
static_cast<D3D11Buffer*>(pResource)->GetDesc(&bufferDesc);
|
static_cast<D3D11Buffer*>(pResource)->GetDesc(&bufferDesc);
|
||||||
|
|
||||||
if (bufferDesc.MiscFlags == D3D11_RESOURCE_MISC_BUFFER_STRUCTURED) {
|
if (bufferDesc.MiscFlags & D3D11_RESOURCE_MISC_BUFFER_STRUCTURED) {
|
||||||
pDesc->Format = DXGI_FORMAT_UNKNOWN;
|
pDesc->Format = DXGI_FORMAT_UNKNOWN;
|
||||||
pDesc->ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
|
pDesc->ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
|
||||||
pDesc->Buffer.FirstElement = 0;
|
pDesc->Buffer.FirstElement = 0;
|
||||||
|
|
|
@ -214,7 +214,7 @@ namespace dxvk {
|
||||||
D3D11_BUFFER_DESC bufferDesc;
|
D3D11_BUFFER_DESC bufferDesc;
|
||||||
static_cast<D3D11Buffer*>(pResource)->GetDesc(&bufferDesc);
|
static_cast<D3D11Buffer*>(pResource)->GetDesc(&bufferDesc);
|
||||||
|
|
||||||
if (bufferDesc.MiscFlags == D3D11_RESOURCE_MISC_BUFFER_STRUCTURED) {
|
if (bufferDesc.MiscFlags & D3D11_RESOURCE_MISC_BUFFER_STRUCTURED) {
|
||||||
pDesc->Format = DXGI_FORMAT_UNKNOWN;
|
pDesc->Format = DXGI_FORMAT_UNKNOWN;
|
||||||
pDesc->ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
|
pDesc->ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
|
||||||
pDesc->Buffer.FirstElement = 0;
|
pDesc->Buffer.FirstElement = 0;
|
||||||
|
|
|
@ -481,6 +481,14 @@ namespace dxvk {
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Unbind all buffers that were still bound to the backend to avoid leaks.
|
||||||
|
EmitCs([](DxvkContext* ctx) {
|
||||||
|
ctx->bindIndexBuffer(DxvkBufferSlice(), VK_INDEX_TYPE_UINT32);
|
||||||
|
for (uint32_t i = 0; i < caps::MaxStreams; i++) {
|
||||||
|
ctx->bindVertexBuffer(i, DxvkBufferSlice(), 0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
Flush();
|
Flush();
|
||||||
SynchronizeCsThread(DxvkCsThread::SynchronizeAll);
|
SynchronizeCsThread(DxvkCsThread::SynchronizeAll);
|
||||||
|
|
||||||
|
@ -1085,7 +1093,12 @@ namespace dxvk {
|
||||||
if (unlikely(iSwapChain != 0))
|
if (unlikely(iSwapChain != 0))
|
||||||
return D3DERR_INVALIDCALL;
|
return D3DERR_INVALIDCALL;
|
||||||
|
|
||||||
return m_implicitSwapchain->GetFrontBufferData(pDestSurface);
|
D3D9DeviceLock lock = LockDevice();
|
||||||
|
|
||||||
|
// In windowed mode, GetFrontBufferData takes a screenshot of the entire screen.
|
||||||
|
// We use the last used swapchain as a workaround.
|
||||||
|
// Total War: Medieval 2 relies on this.
|
||||||
|
return m_mostRecentlyUsedSwapchain->GetFrontBufferData(pDestSurface);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1603,6 +1616,23 @@ namespace dxvk {
|
||||||
|
|
||||||
m_flags.clr(D3D9DeviceFlag::InScene);
|
m_flags.clr(D3D9DeviceFlag::InScene);
|
||||||
|
|
||||||
|
// D3D9 resets the internally bound vertex buffers and index buffer in EndScene if they were unbound in the meantime.
|
||||||
|
// We have to ignore unbinding those buffers because of Operation Flashpoint Red River,
|
||||||
|
// so we should also clear the bindings here, to avoid leaks.
|
||||||
|
if (m_state.indices == nullptr) {
|
||||||
|
EmitCs([](DxvkContext* ctx) {
|
||||||
|
ctx->bindIndexBuffer(DxvkBufferSlice(), VK_INDEX_TYPE_UINT32);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < caps::MaxStreams; i++) {
|
||||||
|
if (m_state.vertexBuffers[i].vertexBuffer == nullptr) {
|
||||||
|
EmitCs([cIndex = i](DxvkContext* ctx) {
|
||||||
|
ctx->bindVertexBuffer(cIndex, DxvkBufferSlice(), 0);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return D3D_OK;
|
return D3D_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5223,7 +5253,7 @@ namespace dxvk {
|
||||||
auto* vbo = GetCommonBuffer(m_state.vertexBuffers[i].vertexBuffer);
|
auto* vbo = GetCommonBuffer(m_state.vertexBuffers[i].vertexBuffer);
|
||||||
|
|
||||||
const uint32_t vertexStride = m_state.vertexDecl->GetSize(i);
|
const uint32_t vertexStride = m_state.vertexDecl->GetSize(i);
|
||||||
uint32_t offset = (BaseVertexIndex + FirstVertexIndex) * vertexStride;
|
uint32_t offset = (BaseVertexIndex + FirstVertexIndex) * vertexStride + m_state.vertexBuffers[i].offset;
|
||||||
|
|
||||||
uint8_t* data = reinterpret_cast<uint8_t*>(upSlice.mapPtr) + vboUPBufferOffsets[i];
|
uint8_t* data = reinterpret_cast<uint8_t*>(upSlice.mapPtr) + vboUPBufferOffsets[i];
|
||||||
uint8_t* src = reinterpret_cast<uint8_t*>(vbo->GetMappedSlice().mapPtr) + offset;
|
uint8_t* src = reinterpret_cast<uint8_t*>(vbo->GetMappedSlice().mapPtr) + offset;
|
||||||
|
@ -5325,7 +5355,7 @@ namespace dxvk {
|
||||||
|
|
||||||
// Round to nearest
|
// Round to nearest
|
||||||
_controlfp(_RC_NEAR, _MCW_RC);
|
_controlfp(_RC_NEAR, _MCW_RC);
|
||||||
#elif (defined(__GNUC__) || defined(__MINGW32__)) && (defined(__i386__) || defined(__x86_64__) || defined(__ia64))
|
#elif (defined(__GNUC__) || defined(__MINGW32__)) && (defined(__i386__) || (defined(__x86_64__) && !defined(__arm64ec__)) || defined(__ia64))
|
||||||
// For GCC/MinGW we can use inline asm to set it.
|
// For GCC/MinGW we can use inline asm to set it.
|
||||||
// This only works for x86 and x64 processors however.
|
// This only works for x86 and x64 processors however.
|
||||||
|
|
||||||
|
@ -5642,10 +5672,13 @@ namespace dxvk {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <bool Synchronize9On12>
|
||||||
void D3D9DeviceEx::Flush() {
|
void D3D9DeviceEx::ExecuteFlush() {
|
||||||
D3D9DeviceLock lock = LockDevice();
|
D3D9DeviceLock lock = LockDevice();
|
||||||
|
|
||||||
|
if constexpr (Synchronize9On12)
|
||||||
|
m_submitStatus.result = VK_NOT_READY;
|
||||||
|
|
||||||
m_initializer->Flush();
|
m_initializer->Flush();
|
||||||
m_converter->Flush();
|
m_converter->Flush();
|
||||||
|
|
||||||
|
@ -5657,16 +5690,32 @@ namespace dxvk {
|
||||||
|
|
||||||
EmitCs<false>([
|
EmitCs<false>([
|
||||||
cSubmissionFence = m_submissionFence,
|
cSubmissionFence = m_submissionFence,
|
||||||
cSubmissionId = submissionId
|
cSubmissionId = submissionId,
|
||||||
|
cSubmissionStatus = Synchronize9On12 ? &m_submitStatus : nullptr
|
||||||
] (DxvkContext* ctx) {
|
] (DxvkContext* ctx) {
|
||||||
ctx->signal(cSubmissionFence, cSubmissionId);
|
ctx->signal(cSubmissionFence, cSubmissionId);
|
||||||
ctx->flushCommandList(nullptr);
|
ctx->flushCommandList(cSubmissionStatus);
|
||||||
});
|
});
|
||||||
|
|
||||||
FlushCsChunk();
|
FlushCsChunk();
|
||||||
|
|
||||||
m_flushSeqNum = m_csSeqNum;
|
m_flushSeqNum = m_csSeqNum;
|
||||||
m_flushTracker.notifyFlush(m_flushSeqNum, submissionId);
|
m_flushTracker.notifyFlush(m_flushSeqNum, submissionId);
|
||||||
|
|
||||||
|
// If necessary, block calling thread until the
|
||||||
|
// Vulkan queue submission is performed.
|
||||||
|
if constexpr (Synchronize9On12)
|
||||||
|
m_dxvkDevice->waitForSubmission(&m_submitStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void D3D9DeviceEx::Flush() {
|
||||||
|
ExecuteFlush<false>();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void D3D9DeviceEx::FlushAndSync9On12() {
|
||||||
|
ExecuteFlush<true>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -7819,8 +7868,10 @@ namespace dxvk {
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
m_implicitSwapchain = new D3D9SwapChainEx(this, pPresentationParameters, pFullscreenDisplayMode);
|
m_implicitSwapchain = new D3D9SwapChainEx(this, pPresentationParameters, pFullscreenDisplayMode);
|
||||||
|
m_mostRecentlyUsedSwapchain = m_implicitSwapchain.ptr();
|
||||||
|
}
|
||||||
|
|
||||||
if (pPresentationParameters->EnableAutoDepthStencil) {
|
if (pPresentationParameters->EnableAutoDepthStencil) {
|
||||||
D3D9_COMMON_TEXTURE_DESC desc;
|
D3D9_COMMON_TEXTURE_DESC desc;
|
||||||
|
|
|
@ -793,6 +793,7 @@ namespace dxvk {
|
||||||
void SynchronizeCsThread(uint64_t SequenceNumber);
|
void SynchronizeCsThread(uint64_t SequenceNumber);
|
||||||
|
|
||||||
void Flush();
|
void Flush();
|
||||||
|
void FlushAndSync9On12();
|
||||||
|
|
||||||
void EndFrame();
|
void EndFrame();
|
||||||
|
|
||||||
|
@ -1059,6 +1060,9 @@ namespace dxvk {
|
||||||
return std::exchange(m_deviceHasBeenReset, false);
|
return std::exchange(m_deviceHasBeenReset, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <bool Synchronize9On12>
|
||||||
|
void ExecuteFlush();
|
||||||
|
|
||||||
void DetermineConstantLayouts(bool canSWVP);
|
void DetermineConstantLayouts(bool canSWVP);
|
||||||
|
|
||||||
D3D9BufferSlice AllocUPBuffer(VkDeviceSize size);
|
D3D9BufferSlice AllocUPBuffer(VkDeviceSize size);
|
||||||
|
@ -1241,6 +1245,34 @@ namespace dxvk {
|
||||||
|
|
||||||
uint64_t GetCurrentSequenceNumber();
|
uint64_t GetCurrentSequenceNumber();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the swapchain that was used the most recently for presenting
|
||||||
|
* Has to be externally synchronized.
|
||||||
|
*
|
||||||
|
* @return D3D9SwapChainEx* Swapchain
|
||||||
|
*/
|
||||||
|
D3D9SwapChainEx* GetMostRecentlyUsedSwapchain() {
|
||||||
|
return m_mostRecentlyUsedSwapchain;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the swapchain that was used the most recently for presenting
|
||||||
|
* Has to be externally synchronized.
|
||||||
|
*
|
||||||
|
* @param swapchain Swapchain
|
||||||
|
*/
|
||||||
|
void SetMostRecentlyUsedSwapchain(D3D9SwapChainEx* swapchain) {
|
||||||
|
m_mostRecentlyUsedSwapchain = swapchain;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reset the most recently swapchain back to the implicit one
|
||||||
|
* Has to be externally synchronized.
|
||||||
|
*/
|
||||||
|
void ResetMostRecentlyUsedSwapchain() {
|
||||||
|
m_mostRecentlyUsedSwapchain = m_implicitSwapchain.ptr();
|
||||||
|
}
|
||||||
|
|
||||||
Com<D3D9InterfaceEx> m_parent;
|
Com<D3D9InterfaceEx> m_parent;
|
||||||
D3DDEVTYPE m_deviceType;
|
D3DDEVTYPE m_deviceType;
|
||||||
HWND m_window;
|
HWND m_window;
|
||||||
|
@ -1393,6 +1425,8 @@ namespace dxvk {
|
||||||
|
|
||||||
Rc<sync::Fence> m_submissionFence;
|
Rc<sync::Fence> m_submissionFence;
|
||||||
uint64_t m_submissionId = 0ull;
|
uint64_t m_submissionId = 0ull;
|
||||||
|
DxvkSubmitStatus m_submitStatus;
|
||||||
|
|
||||||
uint64_t m_flushSeqNum = 0ull;
|
uint64_t m_flushSeqNum = 0ull;
|
||||||
GpuFlushTracker m_flushTracker;
|
GpuFlushTracker m_flushTracker;
|
||||||
|
|
||||||
|
@ -1403,6 +1437,8 @@ namespace dxvk {
|
||||||
HWND m_fullscreenWindow = NULL;
|
HWND m_fullscreenWindow = NULL;
|
||||||
std::atomic<uint32_t> m_losableResourceCounter = { 0 };
|
std::atomic<uint32_t> m_losableResourceCounter = { 0 };
|
||||||
|
|
||||||
|
D3D9SwapChainEx* m_mostRecentlyUsedSwapchain = nullptr;
|
||||||
|
|
||||||
#ifdef D3D9_ALLOW_UNMAPPING
|
#ifdef D3D9_ALLOW_UNMAPPING
|
||||||
lru_list<D3D9CommonTexture*> m_mappedTextures;
|
lru_list<D3D9CommonTexture*> m_mappedTextures;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -30,8 +30,11 @@ namespace dxvk {
|
||||||
return E_NOINTERFACE;
|
return E_NOINTERFACE;
|
||||||
}
|
}
|
||||||
HRESULT STDMETHODCALLTYPE D3D9On12::ReturnUnderlyingResource(IDirect3DResource9* resource, UINT num_sync, UINT64* signal_values, ID3D12Fence** fences) {
|
HRESULT STDMETHODCALLTYPE D3D9On12::ReturnUnderlyingResource(IDirect3DResource9* resource, UINT num_sync, UINT64* signal_values, ID3D12Fence** fences) {
|
||||||
Logger::err("D3D9On12::GetD3D12Device: ReturnUnderlyingResource: Stub");
|
if (num_sync)
|
||||||
return E_NOINTERFACE;
|
Logger::err("D3D9On12::GetD3D12Device: ReturnUnderlyingResource: Stub");
|
||||||
|
|
||||||
|
m_device->FlushAndSync9On12();
|
||||||
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,11 +41,6 @@ namespace dxvk {
|
||||||
case D3DQUERYTYPE_TIMESTAMPFREQ:
|
case D3DQUERYTYPE_TIMESTAMPFREQ:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case D3DQUERYTYPE_VERTEXSTATS:
|
|
||||||
m_query[0] = dxvkDevice->createGpuQuery(
|
|
||||||
VK_QUERY_TYPE_PIPELINE_STATISTICS, 0, 0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw DxvkError(str::format("D3D9Query: Unsupported query type ", m_queryType));
|
throw DxvkError(str::format("D3D9Query: Unsupported query type ", m_queryType));
|
||||||
}
|
}
|
||||||
|
@ -246,11 +241,6 @@ namespace dxvk {
|
||||||
m_dataCache.TimestampFreq = GetTimestampQueryFrequency();
|
m_dataCache.TimestampFreq = GetTimestampQueryFrequency();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case D3DQUERYTYPE_VERTEXSTATS:
|
|
||||||
m_dataCache.VertexStats.NumRenderedTriangles = queryData[0].statistic.iaPrimitives;
|
|
||||||
m_dataCache.VertexStats.NumExtraClippingTriangles = queryData[0].statistic.clipPrimitives;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -276,7 +266,6 @@ namespace dxvk {
|
||||||
void D3D9Query::Begin(DxvkContext* ctx) {
|
void D3D9Query::Begin(DxvkContext* ctx) {
|
||||||
switch (m_queryType) {
|
switch (m_queryType) {
|
||||||
case D3DQUERYTYPE_OCCLUSION:
|
case D3DQUERYTYPE_OCCLUSION:
|
||||||
case D3DQUERYTYPE_VERTEXSTATS:
|
|
||||||
ctx->beginQuery(m_query[0]);
|
ctx->beginQuery(m_query[0]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -296,7 +285,6 @@ namespace dxvk {
|
||||||
ctx->writeTimestamp(m_query[0]);
|
ctx->writeTimestamp(m_query[0]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case D3DQUERYTYPE_VERTEXSTATS:
|
|
||||||
case D3DQUERYTYPE_OCCLUSION:
|
case D3DQUERYTYPE_OCCLUSION:
|
||||||
ctx->endQuery(m_query[0]);
|
ctx->endQuery(m_query[0]);
|
||||||
break;
|
break;
|
||||||
|
@ -314,7 +302,6 @@ namespace dxvk {
|
||||||
|
|
||||||
bool D3D9Query::QueryBeginnable(D3DQUERYTYPE QueryType) {
|
bool D3D9Query::QueryBeginnable(D3DQUERYTYPE QueryType) {
|
||||||
return QueryType == D3DQUERYTYPE_OCCLUSION
|
return QueryType == D3DQUERYTYPE_OCCLUSION
|
||||||
|| QueryType == D3DQUERYTYPE_VERTEXSTATS
|
|
||||||
|| QueryType == D3DQUERYTYPE_TIMESTAMPDISJOINT;
|
|| QueryType == D3DQUERYTYPE_TIMESTAMPDISJOINT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -338,7 +325,6 @@ namespace dxvk {
|
||||||
case D3DQUERYTYPE_TIMESTAMP:
|
case D3DQUERYTYPE_TIMESTAMP:
|
||||||
case D3DQUERYTYPE_TIMESTAMPDISJOINT:
|
case D3DQUERYTYPE_TIMESTAMPDISJOINT:
|
||||||
case D3DQUERYTYPE_TIMESTAMPFREQ:
|
case D3DQUERYTYPE_TIMESTAMPFREQ:
|
||||||
case D3DQUERYTYPE_VERTEXSTATS:
|
|
||||||
return D3D_OK;
|
return D3D_OK;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -65,6 +65,16 @@ namespace dxvk {
|
||||||
if (this_thread::isInModuleDetachment())
|
if (this_thread::isInModuleDetachment())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
{
|
||||||
|
// Locking here and in Device::GetFrontBufferData
|
||||||
|
// ensures that other threads don't accidentally access a stale pointer.
|
||||||
|
D3D9DeviceLock lock = m_parent->LockDevice();
|
||||||
|
|
||||||
|
if (m_parent->GetMostRecentlyUsedSwapchain() == this) {
|
||||||
|
m_parent->ResetMostRecentlyUsedSwapchain();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DestroyBackBuffers();
|
DestroyBackBuffers();
|
||||||
|
|
||||||
ResetWindowProc(m_window);
|
ResetWindowProc(m_window);
|
||||||
|
@ -112,6 +122,8 @@ namespace dxvk {
|
||||||
DWORD dwFlags) {
|
DWORD dwFlags) {
|
||||||
D3D9DeviceLock lock = m_parent->LockDevice();
|
D3D9DeviceLock lock = m_parent->LockDevice();
|
||||||
|
|
||||||
|
m_parent->SetMostRecentlyUsedSwapchain(this);
|
||||||
|
|
||||||
if (unlikely(m_parent->IsDeviceLost()))
|
if (unlikely(m_parent->IsDeviceLost()))
|
||||||
return D3DERR_DEVICELOST;
|
return D3DERR_DEVICELOST;
|
||||||
|
|
||||||
|
@ -382,6 +394,20 @@ namespace dxvk {
|
||||||
blitInfo.srcOffsets[0] = VkOffset3D{ 0, 0, 0 };
|
blitInfo.srcOffsets[0] = VkOffset3D{ 0, 0, 0 };
|
||||||
blitInfo.srcOffsets[1] = VkOffset3D{ int32_t(srcExtent.width), int32_t(srcExtent.height), 1 };
|
blitInfo.srcOffsets[1] = VkOffset3D{ int32_t(srcExtent.width), int32_t(srcExtent.height), 1 };
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
if (m_presentParams.Windowed) {
|
||||||
|
// In windowed mode, GetFrontBufferData takes a screenshot of the entire screen.
|
||||||
|
// So place the copy of the front buffer at the position of the window.
|
||||||
|
POINT point = { 0, 0 };
|
||||||
|
if (ClientToScreen(m_window, &point) != 0) {
|
||||||
|
blitInfo.dstOffsets[0].x = point.x;
|
||||||
|
blitInfo.dstOffsets[0].y = point.y;
|
||||||
|
blitInfo.dstOffsets[1].x += point.x;
|
||||||
|
blitInfo.dstOffsets[1].y += point.y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
m_parent->EmitCs([
|
m_parent->EmitCs([
|
||||||
cDstImage = blittedSrc,
|
cDstImage = blittedSrc,
|
||||||
cDstMap = dstTexInfo->GetMapping().Swizzle,
|
cDstMap = dstTexInfo->GetMapping().Swizzle,
|
||||||
|
|
|
@ -87,9 +87,9 @@ namespace dxvk {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint32_t i = 0; i < ins.dstCount; i++) {
|
for (uint32_t i = 0; i < ins.dstCount; i++) {
|
||||||
if (ins.dst[0].type == DxbcOperandType::IndexableTemp) {
|
if (ins.dst[i].type == DxbcOperandType::IndexableTemp) {
|
||||||
uint32_t index = ins.dst[0].idx[0].offset;
|
uint32_t index = ins.dst[i].idx[0].offset;
|
||||||
m_analysis->xRegMasks[index] |= ins.dst[0].mask;
|
m_analysis->xRegMasks[index] |= ins.dst[i].mask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,11 @@ namespace dxvk {
|
||||||
entry.systemValue = static_cast<DxbcSystemValue>(reader.readu32());
|
entry.systemValue = static_cast<DxbcSystemValue>(reader.readu32());
|
||||||
entry.componentType = componentTypes.at(reader.readu32());
|
entry.componentType = componentTypes.at(reader.readu32());
|
||||||
entry.registerId = reader.readu32();
|
entry.registerId = reader.readu32();
|
||||||
entry.componentMask = bit::extract(reader.readu32(), 0, 3);
|
|
||||||
|
uint32_t mask = reader.readu32();
|
||||||
|
|
||||||
|
entry.componentMask = bit::extract(mask, 0, 3);
|
||||||
|
entry.componentUsed = bit::extract(mask, 8, 11);
|
||||||
|
|
||||||
if (hasPrecision)
|
if (hasPrecision)
|
||||||
reader.readu32();
|
reader.readu32();
|
||||||
|
|
|
@ -20,6 +20,7 @@ namespace dxvk {
|
||||||
uint32_t semanticIndex;
|
uint32_t semanticIndex;
|
||||||
uint32_t registerId;
|
uint32_t registerId;
|
||||||
DxbcRegMask componentMask;
|
DxbcRegMask componentMask;
|
||||||
|
DxbcRegMask componentUsed;
|
||||||
DxbcScalarType componentType;
|
DxbcScalarType componentType;
|
||||||
DxbcSystemValue systemValue;
|
DxbcSystemValue systemValue;
|
||||||
uint32_t streamId;
|
uint32_t streamId;
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -512,6 +512,7 @@ namespace dxvk {
|
||||||
// Entry point description - we'll need to declare
|
// Entry point description - we'll need to declare
|
||||||
// the function ID and all input/output variables.
|
// the function ID and all input/output variables.
|
||||||
uint32_t m_entryPointId = 0;
|
uint32_t m_entryPointId = 0;
|
||||||
|
bool m_hasRawAccessChains = false;
|
||||||
|
|
||||||
////////////////////////////////////////////
|
////////////////////////////////////////////
|
||||||
// Inter-stage shader interface slots. Also
|
// Inter-stage shader interface slots. Also
|
||||||
|
@ -944,19 +945,6 @@ namespace dxvk {
|
||||||
const DxbcRegister& operand,
|
const DxbcRegister& operand,
|
||||||
const DxbcRegister& address);
|
const DxbcRegister& address);
|
||||||
|
|
||||||
///////////////////////////////
|
|
||||||
// Resource load/store methods
|
|
||||||
DxbcRegisterValue emitRawBufferLoad(
|
|
||||||
const DxbcRegister& operand,
|
|
||||||
DxbcRegisterValue elementIndex,
|
|
||||||
DxbcRegMask writeMask,
|
|
||||||
uint32_t& sparseFeedbackId);
|
|
||||||
|
|
||||||
void emitRawBufferStore(
|
|
||||||
const DxbcRegister& operand,
|
|
||||||
DxbcRegisterValue elementIndex,
|
|
||||||
DxbcRegisterValue value);
|
|
||||||
|
|
||||||
//////////////////////////
|
//////////////////////////
|
||||||
// Resource query methods
|
// Resource query methods
|
||||||
DxbcRegisterValue emitQueryBufferSize(
|
DxbcRegisterValue emitQueryBufferSize(
|
||||||
|
@ -1233,6 +1221,9 @@ namespace dxvk {
|
||||||
uint32_t getUavCoherence(
|
uint32_t getUavCoherence(
|
||||||
uint32_t registerId,
|
uint32_t registerId,
|
||||||
DxbcUavFlags flags);
|
DxbcUavFlags flags);
|
||||||
|
|
||||||
|
bool ignoreInputSystemValue(
|
||||||
|
DxbcSystemValue sv) const;
|
||||||
|
|
||||||
///////////////////////////
|
///////////////////////////
|
||||||
// Type definition methods
|
// Type definition methods
|
||||||
|
|
|
@ -149,6 +149,10 @@ namespace dxvk {
|
||||||
: m_mask((x ? 0x1 : 0) | (y ? 0x2 : 0)
|
: m_mask((x ? 0x1 : 0) | (y ? 0x2 : 0)
|
||||||
| (z ? 0x4 : 0) | (w ? 0x8 : 0)) { }
|
| (z ? 0x4 : 0) | (w ? 0x8 : 0)) { }
|
||||||
|
|
||||||
|
uint32_t raw() const {
|
||||||
|
return m_mask;
|
||||||
|
}
|
||||||
|
|
||||||
bool operator [] (uint32_t id) const {
|
bool operator [] (uint32_t id) const {
|
||||||
return (m_mask >> id) & 1;
|
return (m_mask >> id) & 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,9 +17,6 @@ namespace dxvk {
|
||||||
|
|
||||||
useDepthClipWorkaround
|
useDepthClipWorkaround
|
||||||
= !devFeatures.extDepthClipEnable.depthClipEnable;
|
= !devFeatures.extDepthClipEnable.depthClipEnable;
|
||||||
useSubgroupOpsForAtomicCounters
|
|
||||||
= (devInfo.vk11.subgroupSupportedStages & VK_SHADER_STAGE_COMPUTE_BIT)
|
|
||||||
&& (devInfo.vk11.subgroupSupportedOperations & VK_SUBGROUP_FEATURE_BALLOT_BIT);
|
|
||||||
|
|
||||||
VkFormatFeatureFlags2 r32Features
|
VkFormatFeatureFlags2 r32Features
|
||||||
= device->getFormatFeatures(VK_FORMAT_R32_SFLOAT).optimal
|
= device->getFormatFeatures(VK_FORMAT_R32_SFLOAT).optimal
|
||||||
|
@ -27,6 +24,7 @@ namespace dxvk {
|
||||||
& device->getFormatFeatures(VK_FORMAT_R32_SINT).optimal;
|
& device->getFormatFeatures(VK_FORMAT_R32_SINT).optimal;
|
||||||
|
|
||||||
supportsTypedUavLoadR32 = (r32Features & VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT);
|
supportsTypedUavLoadR32 = (r32Features & VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT);
|
||||||
|
supportsRawAccessChains = device->features().nvRawAccessChains.shaderRawAccessChains;
|
||||||
|
|
||||||
switch (device->config().useRawSsbo) {
|
switch (device->config().useRawSsbo) {
|
||||||
case Tristate::Auto: minSsboAlignment = devInfo.core.properties.limits.minStorageBufferOffsetAlignment; break;
|
case Tristate::Auto: minSsboAlignment = devInfo.core.properties.limits.minStorageBufferOffsetAlignment; break;
|
||||||
|
|
|
@ -27,9 +27,8 @@ namespace dxvk {
|
||||||
/// on typed UAV loads are required
|
/// on typed UAV loads are required
|
||||||
bool supportsTypedUavLoadR32 = false;
|
bool supportsTypedUavLoadR32 = false;
|
||||||
|
|
||||||
/// Use subgroup operations to reduce the number of
|
/// Determines whether raw access chains are supported
|
||||||
/// atomic operations for append/consume buffers.
|
bool supportsRawAccessChains = false;
|
||||||
bool useSubgroupOpsForAtomicCounters = false;
|
|
||||||
|
|
||||||
/// Clear thread-group shared memory to zero
|
/// Clear thread-group shared memory to zero
|
||||||
bool zeroInitWorkgroupMemory = false;
|
bool zeroInitWorkgroupMemory = false;
|
||||||
|
|
|
@ -272,7 +272,8 @@ namespace dxvk {
|
||||||
auto deviceProp = m_adapter->deviceProperties();
|
auto deviceProp = m_adapter->deviceProperties();
|
||||||
auto memoryProp = m_adapter->memoryProperties();
|
auto memoryProp = m_adapter->memoryProperties();
|
||||||
auto vk11 = m_adapter->devicePropertiesExt().vk11;
|
auto vk11 = m_adapter->devicePropertiesExt().vk11;
|
||||||
|
auto vk12 = m_adapter->devicePropertiesExt().vk12;
|
||||||
|
|
||||||
// Custom Vendor / Device ID
|
// Custom Vendor / Device ID
|
||||||
if (options->customVendorId >= 0)
|
if (options->customVendorId >= 0)
|
||||||
deviceProp.vendorID = options->customVendorId;
|
deviceProp.vendorID = options->customVendorId;
|
||||||
|
@ -298,7 +299,10 @@ namespace dxvk {
|
||||||
fallbackDevice = 0x2487;
|
fallbackDevice = 0x2487;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hideGpu = (deviceProp.vendorID == uint16_t(DxvkGpuVendor::Nvidia) && options->hideNvidiaGpu)
|
bool hideNvidiaGpu = vk12.driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY
|
||||||
|
? options->hideNvidiaGpu : options->hideNvkGpu;
|
||||||
|
|
||||||
|
bool hideGpu = (deviceProp.vendorID == uint16_t(DxvkGpuVendor::Nvidia) && hideNvidiaGpu)
|
||||||
|| (deviceProp.vendorID == uint16_t(DxvkGpuVendor::Amd) && options->hideAmdGpu)
|
|| (deviceProp.vendorID == uint16_t(DxvkGpuVendor::Amd) && options->hideAmdGpu)
|
||||||
|| (deviceProp.vendorID == uint16_t(DxvkGpuVendor::Intel) && options->hideIntelGpu);
|
|| (deviceProp.vendorID == uint16_t(DxvkGpuVendor::Intel) && options->hideIntelGpu);
|
||||||
|
|
||||||
|
|
|
@ -124,13 +124,10 @@ namespace dxvk {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// If any monitors are left on the list, enable the
|
// If any monitors are left on the list, enable the
|
||||||
// fallback to always enumerate all monitors.
|
// fallback to always enumerate all monitors.
|
||||||
if ((m_monitorFallback = !monitors.empty()))
|
if ((m_monitorFallback = !monitors.empty()))
|
||||||
Logger::warn("DXGI: Found monitors not associated with any adapter, using fallback");
|
Logger::warn("DXGI: Found monitors not associated with any adapter, using fallback");
|
||||||
else
|
|
||||||
m_monitorFallback = m_options.useMonitorFallback;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -233,7 +230,7 @@ namespace dxvk {
|
||||||
descFs.Windowed = pDesc->Windowed;
|
descFs.Windowed = pDesc->Windowed;
|
||||||
|
|
||||||
IDXGISwapChain1* swapChain = nullptr;
|
IDXGISwapChain1* swapChain = nullptr;
|
||||||
HRESULT hr = CreateSwapChainForHwnd(
|
HRESULT hr = CreateSwapChainForHwndBase(
|
||||||
pDevice, pDesc->OutputWindow,
|
pDevice, pDesc->OutputWindow,
|
||||||
&desc, &descFs, nullptr,
|
&desc, &descFs, nullptr,
|
||||||
&swapChain);
|
&swapChain);
|
||||||
|
@ -247,6 +244,19 @@ namespace dxvk {
|
||||||
IUnknown* pDevice,
|
IUnknown* pDevice,
|
||||||
HWND hWnd,
|
HWND hWnd,
|
||||||
const DXGI_SWAP_CHAIN_DESC1* pDesc,
|
const DXGI_SWAP_CHAIN_DESC1* pDesc,
|
||||||
|
const DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pFullscreenDesc,
|
||||||
|
IDXGIOutput* pRestrictToOutput,
|
||||||
|
IDXGISwapChain1** ppSwapChain) {
|
||||||
|
return CreateSwapChainForHwndBase(
|
||||||
|
pDevice, hWnd,
|
||||||
|
pDesc, pFullscreenDesc, pRestrictToOutput,
|
||||||
|
ppSwapChain);
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE DxgiFactory::CreateSwapChainForHwndBase(
|
||||||
|
IUnknown* pDevice,
|
||||||
|
HWND hWnd,
|
||||||
|
const DXGI_SWAP_CHAIN_DESC1* pDesc,
|
||||||
const DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pFullscreenDesc,
|
const DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pFullscreenDesc,
|
||||||
IDXGIOutput* pRestrictToOutput,
|
IDXGIOutput* pRestrictToOutput,
|
||||||
IDXGISwapChain1** ppSwapChain) {
|
IDXGISwapChain1** ppSwapChain) {
|
||||||
|
|
|
@ -200,6 +200,14 @@ namespace dxvk {
|
||||||
UINT m_flags;
|
UINT m_flags;
|
||||||
BOOL m_monitorFallback;
|
BOOL m_monitorFallback;
|
||||||
|
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE CreateSwapChainForHwndBase(
|
||||||
|
IUnknown* pDevice,
|
||||||
|
HWND hWnd,
|
||||||
|
const DXGI_SWAP_CHAIN_DESC1* pDesc,
|
||||||
|
const DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pFullscreenDesc,
|
||||||
|
IDXGIOutput* pRestrictToOutput,
|
||||||
|
IDXGISwapChain1** ppSwapChain);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,21 @@ namespace dxvk {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* First generation XeSS causes crash on proton for Intel due to missing
|
||||||
|
* Intel interface. Avoid crash by pretending to be non-Intel if the
|
||||||
|
* libxess.dll module is loaded by an application.
|
||||||
|
*/
|
||||||
|
static bool isXessUsed() {
|
||||||
|
#ifdef _WIN32
|
||||||
|
if (GetModuleHandleA("libxess") != nullptr ||
|
||||||
|
GetModuleHandleA("libxess_dx11") != nullptr)
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static bool isNvapiEnabled() {
|
static bool isNvapiEnabled() {
|
||||||
return env::getEnvVar("DXVK_ENABLE_NVAPI") == "1";
|
return env::getEnvVar("DXVK_ENABLE_NVAPI") == "1";
|
||||||
|
@ -82,15 +97,12 @@ namespace dxvk {
|
||||||
|
|
||||||
// Expose Nvidia GPUs properly if NvAPI is enabled in environment
|
// Expose Nvidia GPUs properly if NvAPI is enabled in environment
|
||||||
this->hideNvidiaGpu = !isNvapiEnabled();
|
this->hideNvidiaGpu = !isNvapiEnabled();
|
||||||
|
applyTristate(this->hideNvidiaGpu, config.getOption<Tristate>("dxgi.hideNvidiaGpu", Tristate::Auto));
|
||||||
|
|
||||||
Tristate hideNvidiaGpuOption = config.getOption<Tristate>("dxgi.hideNvidiaGpu", Tristate::Auto);
|
// Treat NVK adapters the same as Nvidia cards on the proprietary by
|
||||||
|
// default, but provide an override in case something isn't working.
|
||||||
if (hideNvidiaGpuOption == Tristate::Auto && !config.getOption<bool>("dxgi.nvapiHack", true)) {
|
this->hideNvkGpu = this->hideNvidiaGpu;
|
||||||
Logger::warn("dxgi.nvapiHack is deprecated, please set dxgi.hideNvidiaGpu instead.");
|
applyTristate(this->hideNvkGpu, config.getOption<Tristate>("dxgi.hideNvkGpu", Tristate::Auto));
|
||||||
hideNvidiaGpuOption = Tristate::False;
|
|
||||||
}
|
|
||||||
|
|
||||||
applyTristate(this->hideNvidiaGpu, hideNvidiaGpuOption);
|
|
||||||
|
|
||||||
// Expose AMD and Intel GPU by default, unless a config override is active.
|
// Expose AMD and Intel GPU by default, unless a config override is active.
|
||||||
// Implement as a tristate so that we have the option to introduce similar
|
// Implement as a tristate so that we have the option to introduce similar
|
||||||
|
@ -98,15 +110,17 @@ namespace dxvk {
|
||||||
this->hideAmdGpu = config.getOption<Tristate>("dxgi.hideAmdGpu", Tristate::Auto) == Tristate::True;
|
this->hideAmdGpu = config.getOption<Tristate>("dxgi.hideAmdGpu", Tristate::Auto) == Tristate::True;
|
||||||
this->hideIntelGpu = config.getOption<Tristate>("dxgi.hideIntelGpu", Tristate::Auto) == Tristate::True;
|
this->hideIntelGpu = config.getOption<Tristate>("dxgi.hideIntelGpu", Tristate::Auto) == Tristate::True;
|
||||||
|
|
||||||
|
/* Force vendor ID to non-Intel ID when XeSS is in use */
|
||||||
|
if (isXessUsed()) {
|
||||||
|
Logger::info(str::format("Detected XeSS usage, hiding Intel GPU Vendor"));
|
||||||
|
this->hideIntelGpu = true;
|
||||||
|
}
|
||||||
|
|
||||||
this->enableHDR = config.getOption<bool>("dxgi.enableHDR", env::getEnvVar("DXVK_HDR") == "1");
|
this->enableHDR = config.getOption<bool>("dxgi.enableHDR", env::getEnvVar("DXVK_HDR") == "1");
|
||||||
if (this->enableHDR && isHDRDisallowed()) {
|
if (this->enableHDR && isHDRDisallowed()) {
|
||||||
Logger::info("HDR was configured to be enabled, but has been force disabled as a UE4 DX11 game was detected.");
|
Logger::info("HDR was configured to be enabled, but has been force disabled as a UE4 DX11 game was detected.");
|
||||||
this->enableHDR = false;
|
this->enableHDR = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->useMonitorFallback = config.getOption<bool>("dxgi.useMonitorFallback", env::getEnvVar("DXVK_MONITOR_FALLBACK") == "1");
|
|
||||||
if (this->useMonitorFallback)
|
|
||||||
Logger::info("Enabled useMonitorFallback option");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,9 +33,13 @@ namespace dxvk {
|
||||||
/// Emulate UMA
|
/// Emulate UMA
|
||||||
bool emulateUMA;
|
bool emulateUMA;
|
||||||
|
|
||||||
/// Reports Nvidia GPUs as a different vendor (usually AMD)
|
/// Reports Nvidia GPUs running on the proprietary driver as a different
|
||||||
|
/// vendor (usually AMD). Proton will generally disable this option.
|
||||||
bool hideNvidiaGpu;
|
bool hideNvidiaGpu;
|
||||||
|
|
||||||
|
/// Reports Nvidia GPUs running on NVK as a different vendor (usually AMD)
|
||||||
|
bool hideNvkGpu;
|
||||||
|
|
||||||
/// Reports AMD GPUs as a different vendor (usually Nvidia)
|
/// Reports AMD GPUs as a different vendor (usually Nvidia)
|
||||||
bool hideAmdGpu;
|
bool hideAmdGpu;
|
||||||
|
|
||||||
|
@ -45,9 +49,6 @@ namespace dxvk {
|
||||||
/// Enable HDR
|
/// Enable HDR
|
||||||
bool enableHDR;
|
bool enableHDR;
|
||||||
|
|
||||||
/// Use monitor fallback to enumerating all monitors per output
|
|
||||||
bool useMonitorFallback;
|
|
||||||
|
|
||||||
/// Sync interval. Overrides the value
|
/// Sync interval. Overrides the value
|
||||||
/// passed to IDXGISwapChain::Present.
|
/// passed to IDXGISwapChain::Present.
|
||||||
int32_t syncInterval;
|
int32_t syncInterval;
|
||||||
|
|
|
@ -32,6 +32,9 @@ namespace dxvk {
|
||||||
// Apply initial window mode and fullscreen state
|
// Apply initial window mode and fullscreen state
|
||||||
if (!m_descFs.Windowed && FAILED(EnterFullscreenMode(nullptr)))
|
if (!m_descFs.Windowed && FAILED(EnterFullscreenMode(nullptr)))
|
||||||
throw DxvkError("DXGI: Failed to set initial fullscreen state");
|
throw DxvkError("DXGI: Failed to set initial fullscreen state");
|
||||||
|
|
||||||
|
// Ensure that RGBA16 swap chains are scRGB if supported
|
||||||
|
UpdateColorSpace(m_desc.Format, m_colorSpace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -300,15 +303,22 @@ namespace dxvk {
|
||||||
|
|
||||||
|
|
||||||
HRESULT STDMETHODCALLTYPE DxgiSwapChain::Present(UINT SyncInterval, UINT Flags) {
|
HRESULT STDMETHODCALLTYPE DxgiSwapChain::Present(UINT SyncInterval, UINT Flags) {
|
||||||
return Present1(SyncInterval, Flags, nullptr);
|
return PresentBase(SyncInterval, Flags, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
HRESULT STDMETHODCALLTYPE DxgiSwapChain::Present1(
|
HRESULT STDMETHODCALLTYPE DxgiSwapChain::Present1(
|
||||||
UINT SyncInterval,
|
UINT SyncInterval,
|
||||||
UINT PresentFlags,
|
UINT PresentFlags,
|
||||||
const DXGI_PRESENT_PARAMETERS* pPresentParameters) {
|
const DXGI_PRESENT_PARAMETERS* pPresentParameters) {
|
||||||
|
|
||||||
|
return PresentBase(SyncInterval, PresentFlags, pPresentParameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE DxgiSwapChain::PresentBase(
|
||||||
|
UINT SyncInterval,
|
||||||
|
UINT PresentFlags,
|
||||||
|
const DXGI_PRESENT_PARAMETERS* pPresentParameters) {
|
||||||
|
|
||||||
if (SyncInterval > 4)
|
if (SyncInterval > 4)
|
||||||
return DXGI_ERROR_INVALID_CALL;
|
return DXGI_ERROR_INVALID_CALL;
|
||||||
|
|
||||||
|
@ -398,7 +408,13 @@ namespace dxvk {
|
||||||
if (Format != DXGI_FORMAT_UNKNOWN)
|
if (Format != DXGI_FORMAT_UNKNOWN)
|
||||||
m_desc.Format = Format;
|
m_desc.Format = Format;
|
||||||
|
|
||||||
return m_presenter->ChangeProperties(&m_desc, pCreationNodeMask, ppPresentQueue);
|
HRESULT hr = m_presenter->ChangeProperties(&m_desc, pCreationNodeMask, ppPresentQueue);
|
||||||
|
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
UpdateColorSpace(m_desc.Format, m_colorSpace);
|
||||||
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -572,36 +588,31 @@ namespace dxvk {
|
||||||
if (!pColorSpaceSupport)
|
if (!pColorSpaceSupport)
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
// Don't expose any color spaces other than standard
|
std::lock_guard<dxvk::mutex> lock(m_lockBuffer);
|
||||||
// sRGB if the enableHDR option is not set.
|
|
||||||
//
|
if (ValidateColorSpaceSupport(m_desc.Format, ColorSpace))
|
||||||
// If we ever have a use for the non-SRGB non-HDR colorspaces
|
*pColorSpaceSupport = DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT;
|
||||||
// some day, we may want to revisit this.
|
else
|
||||||
if (ColorSpace != DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709
|
*pColorSpaceSupport = 0;
|
||||||
&& !m_factory->GetOptions()->enableHDR) {
|
|
||||||
*pColorSpaceSupport = 0;
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
UINT support = m_presenter->CheckColorSpaceSupport(ColorSpace);
|
|
||||||
*pColorSpaceSupport = support;
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
HRESULT STDMETHODCALLTYPE DxgiSwapChain::SetColorSpace1(DXGI_COLOR_SPACE_TYPE ColorSpace) {
|
HRESULT STDMETHODCALLTYPE DxgiSwapChain::SetColorSpace1(DXGI_COLOR_SPACE_TYPE ColorSpace) {
|
||||||
UINT support = m_presenter->CheckColorSpaceSupport(ColorSpace);
|
std::lock_guard<dxvk::mutex> lock(m_lockBuffer);
|
||||||
|
|
||||||
if (!support)
|
if (!ValidateColorSpaceSupport(m_desc.Format, ColorSpace))
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
std::lock_guard<dxvk::mutex> lock(m_lockBuffer);
|
// Write back color space if setting it up succeeded. This way, we preserve
|
||||||
HRESULT hr = m_presenter->SetColorSpace(ColorSpace);
|
// the current color space even if the swap chain temporarily switches to a
|
||||||
if (SUCCEEDED(hr)) {
|
// back buffer format which does not support it.
|
||||||
// If this was a colorspace other than our current one,
|
HRESULT hr = UpdateColorSpace(m_desc.Format, ColorSpace);
|
||||||
// punt us into that one on the DXGI output.
|
|
||||||
m_monitorInfo->PuntColorSpace(ColorSpace);
|
if (SUCCEEDED(hr))
|
||||||
}
|
m_colorSpace = ColorSpace;
|
||||||
|
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -869,6 +880,7 @@ namespace dxvk {
|
||||||
m_monitorInfo->ReleaseMonitorData();
|
m_monitorInfo->ReleaseMonitorData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxgiSwapChain::UpdateGlobalHDRState() {
|
void DxgiSwapChain::UpdateGlobalHDRState() {
|
||||||
// Update the global HDR state if called from the legacy NVAPI
|
// Update the global HDR state if called from the legacy NVAPI
|
||||||
// interfaces, etc.
|
// interfaces, etc.
|
||||||
|
@ -893,4 +905,51 @@ namespace dxvk {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool DxgiSwapChain::ValidateColorSpaceSupport(
|
||||||
|
DXGI_FORMAT Format,
|
||||||
|
DXGI_COLOR_SPACE_TYPE ColorSpace) {
|
||||||
|
// RGBA16 swap chains are treated as scRGB even on SDR displays,
|
||||||
|
// and regular sRGB is not exposed when this format is used.
|
||||||
|
if (Format == DXGI_FORMAT_R16G16B16A16_FLOAT)
|
||||||
|
return ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709;
|
||||||
|
|
||||||
|
// For everything else, we will always expose plain sRGB
|
||||||
|
if (ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Only expose HDR10 color space if HDR option is enabled
|
||||||
|
if (ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020)
|
||||||
|
return m_factory->GetOptions()->enableHDR && m_presenter->CheckColorSpaceSupport(ColorSpace);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
HRESULT DxgiSwapChain::UpdateColorSpace(
|
||||||
|
DXGI_FORMAT Format,
|
||||||
|
DXGI_COLOR_SPACE_TYPE ColorSpace) {
|
||||||
|
// Don't do anything if the explicitly sepected color space
|
||||||
|
// is compatible with the back buffer format already
|
||||||
|
if (!ValidateColorSpaceSupport(Format, ColorSpace)) {
|
||||||
|
ColorSpace = Format == DXGI_FORMAT_R16G16B16A16_FLOAT
|
||||||
|
? DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709
|
||||||
|
: DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure that we pick a supported color space. This is relevant for
|
||||||
|
// mapping scRGB to sRGB on SDR setups, matching Windows behaviour.
|
||||||
|
if (!m_presenter->CheckColorSpaceSupport(ColorSpace))
|
||||||
|
ColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709;
|
||||||
|
|
||||||
|
HRESULT hr = m_presenter->SetColorSpace(ColorSpace);
|
||||||
|
|
||||||
|
// If this was a colorspace other than our current one,
|
||||||
|
// punt us into that one on the DXGI output.
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
m_monitorInfo->PuntColorSpace(ColorSpace);
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -193,6 +193,8 @@ namespace dxvk {
|
||||||
bool m_frameStatisticsDisjoint = true;
|
bool m_frameStatisticsDisjoint = true;
|
||||||
wsi::DxvkWindowState m_windowState;
|
wsi::DxvkWindowState m_windowState;
|
||||||
|
|
||||||
|
DXGI_COLOR_SPACE_TYPE m_colorSpace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709;
|
||||||
|
|
||||||
uint32_t m_globalHDRStateSerial = 0;
|
uint32_t m_globalHDRStateSerial = 0;
|
||||||
|
|
||||||
HRESULT EnterFullscreenMode(
|
HRESULT EnterFullscreenMode(
|
||||||
|
@ -223,6 +225,18 @@ namespace dxvk {
|
||||||
|
|
||||||
void UpdateGlobalHDRState();
|
void UpdateGlobalHDRState();
|
||||||
|
|
||||||
|
bool ValidateColorSpaceSupport(
|
||||||
|
DXGI_FORMAT Format,
|
||||||
|
DXGI_COLOR_SPACE_TYPE ColorSpace);
|
||||||
|
|
||||||
|
HRESULT UpdateColorSpace(
|
||||||
|
DXGI_FORMAT Format,
|
||||||
|
DXGI_COLOR_SPACE_TYPE ColorSpace);
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE PresentBase(
|
||||||
|
UINT SyncInterval,
|
||||||
|
UINT PresentFlags,
|
||||||
|
const DXGI_PRESENT_PARAMETERS* pPresentParameters);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -346,6 +346,11 @@ namespace dxvk {
|
||||||
enabledFeatures.vk13.synchronization2 = VK_TRUE;
|
enabledFeatures.vk13.synchronization2 = VK_TRUE;
|
||||||
enabledFeatures.vk13.dynamicRendering = VK_TRUE;
|
enabledFeatures.vk13.dynamicRendering = VK_TRUE;
|
||||||
|
|
||||||
|
// Maintenance4 may cause performance problems on amdvlk in some cases
|
||||||
|
if (m_deviceInfo.vk12.driverID != VK_DRIVER_ID_AMD_OPEN_SOURCE
|
||||||
|
&& m_deviceInfo.vk12.driverID != VK_DRIVER_ID_AMD_PROPRIETARY)
|
||||||
|
enabledFeatures.vk13.maintenance4 = VK_TRUE;
|
||||||
|
|
||||||
// We expose depth clip rather than depth clamp to client APIs
|
// We expose depth clip rather than depth clamp to client APIs
|
||||||
enabledFeatures.extDepthClipEnable.depthClipEnable =
|
enabledFeatures.extDepthClipEnable.depthClipEnable =
|
||||||
m_deviceFeatures.extDepthClipEnable.depthClipEnable;
|
m_deviceFeatures.extDepthClipEnable.depthClipEnable;
|
||||||
|
@ -415,6 +420,10 @@ namespace dxvk {
|
||||||
enabledFeatures.khrPresentWait.presentWait = VK_FALSE;
|
enabledFeatures.khrPresentWait.presentWait = VK_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Enable raw access chains for shader backends
|
||||||
|
enabledFeatures.nvRawAccessChains.shaderRawAccessChains =
|
||||||
|
m_deviceFeatures.nvRawAccessChains.shaderRawAccessChains;
|
||||||
|
|
||||||
// Create pNext chain for additional device features
|
// Create pNext chain for additional device features
|
||||||
initFeatureChain(enabledFeatures, devExtensions, instance->extensions());
|
initFeatureChain(enabledFeatures, devExtensions, instance->extensions());
|
||||||
|
|
||||||
|
@ -606,6 +615,10 @@ namespace dxvk {
|
||||||
enabledFeatures.khrPresentWait = *reinterpret_cast<const VkPhysicalDevicePresentWaitFeaturesKHR*>(f);
|
enabledFeatures.khrPresentWait = *reinterpret_cast<const VkPhysicalDevicePresentWaitFeaturesKHR*>(f);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAW_ACCESS_CHAINS_FEATURES_NV:
|
||||||
|
enabledFeatures.nvRawAccessChains = *reinterpret_cast<const VkPhysicalDeviceRawAccessChainsFeaturesNV*>(f);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// Ignore any unknown feature structs
|
// Ignore any unknown feature structs
|
||||||
break;
|
break;
|
||||||
|
@ -927,6 +940,11 @@ namespace dxvk {
|
||||||
m_deviceFeatures.khrPresentWait.pNext = std::exchange(m_deviceFeatures.core.pNext, &m_deviceFeatures.khrPresentWait);
|
m_deviceFeatures.khrPresentWait.pNext = std::exchange(m_deviceFeatures.core.pNext, &m_deviceFeatures.khrPresentWait);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_deviceExtensions.supports(VK_NV_RAW_ACCESS_CHAINS_EXTENSION_NAME)) {
|
||||||
|
m_deviceFeatures.nvRawAccessChains.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAW_ACCESS_CHAINS_FEATURES_NV;
|
||||||
|
m_deviceFeatures.nvRawAccessChains.pNext = std::exchange(m_deviceFeatures.core.pNext, &m_deviceFeatures.nvRawAccessChains);
|
||||||
|
}
|
||||||
|
|
||||||
if (m_deviceExtensions.supports(VK_NVX_BINARY_IMPORT_EXTENSION_NAME))
|
if (m_deviceExtensions.supports(VK_NVX_BINARY_IMPORT_EXTENSION_NAME))
|
||||||
m_deviceFeatures.nvxBinaryImport = VK_TRUE;
|
m_deviceFeatures.nvxBinaryImport = VK_TRUE;
|
||||||
|
|
||||||
|
@ -994,6 +1012,7 @@ namespace dxvk {
|
||||||
&devExtensions.khrPresentWait,
|
&devExtensions.khrPresentWait,
|
||||||
&devExtensions.khrSwapchain,
|
&devExtensions.khrSwapchain,
|
||||||
&devExtensions.khrWin32KeyedMutex,
|
&devExtensions.khrWin32KeyedMutex,
|
||||||
|
&devExtensions.nvRawAccessChains,
|
||||||
&devExtensions.nvxBinaryImport,
|
&devExtensions.nvxBinaryImport,
|
||||||
&devExtensions.nvxImageViewHandle,
|
&devExtensions.nvxImageViewHandle,
|
||||||
}};
|
}};
|
||||||
|
@ -1133,6 +1152,11 @@ namespace dxvk {
|
||||||
enabledFeatures.khrPresentWait.pNext = std::exchange(enabledFeatures.core.pNext, &enabledFeatures.khrPresentWait);
|
enabledFeatures.khrPresentWait.pNext = std::exchange(enabledFeatures.core.pNext, &enabledFeatures.khrPresentWait);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (devExtensions.nvRawAccessChains) {
|
||||||
|
enabledFeatures.nvRawAccessChains.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAW_ACCESS_CHAINS_FEATURES_NV;
|
||||||
|
enabledFeatures.nvRawAccessChains.pNext = std::exchange(enabledFeatures.core.pNext, &enabledFeatures.nvRawAccessChains);
|
||||||
|
}
|
||||||
|
|
||||||
if (devExtensions.nvxBinaryImport)
|
if (devExtensions.nvxBinaryImport)
|
||||||
enabledFeatures.nvxBinaryImport = VK_TRUE;
|
enabledFeatures.nvxBinaryImport = VK_TRUE;
|
||||||
|
|
||||||
|
@ -1279,6 +1303,8 @@ namespace dxvk {
|
||||||
"\n presentId : ", features.khrPresentId.presentId ? "1" : "0",
|
"\n presentId : ", features.khrPresentId.presentId ? "1" : "0",
|
||||||
"\n", VK_KHR_PRESENT_WAIT_EXTENSION_NAME,
|
"\n", VK_KHR_PRESENT_WAIT_EXTENSION_NAME,
|
||||||
"\n presentWait : ", features.khrPresentWait.presentWait ? "1" : "0",
|
"\n presentWait : ", features.khrPresentWait.presentWait ? "1" : "0",
|
||||||
|
"\n", VK_NV_RAW_ACCESS_CHAINS_EXTENSION_NAME,
|
||||||
|
"\n shaderRawAccessChains : ", features.nvRawAccessChains.shaderRawAccessChains ? "1" : "0",
|
||||||
"\n", VK_NVX_BINARY_IMPORT_EXTENSION_NAME,
|
"\n", VK_NVX_BINARY_IMPORT_EXTENSION_NAME,
|
||||||
"\n extension supported : ", features.nvxBinaryImport ? "1" : "0",
|
"\n extension supported : ", features.nvxBinaryImport ? "1" : "0",
|
||||||
"\n", VK_NVX_IMAGE_VIEW_HANDLE_EXTENSION_NAME,
|
"\n", VK_NVX_IMAGE_VIEW_HANDLE_EXTENSION_NAME,
|
||||||
|
|
|
@ -1997,7 +1997,7 @@ namespace dxvk {
|
||||||
depthOp.loadOpS = VK_ATTACHMENT_LOAD_OP_LOAD;
|
depthOp.loadOpS = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||||
depthOp.loadLayout = imageView->imageInfo().layout;
|
depthOp.loadLayout = imageView->imageInfo().layout;
|
||||||
depthOp.storeLayout = imageView->imageInfo().layout;
|
depthOp.storeLayout = imageView->imageInfo().layout;
|
||||||
|
|
||||||
if (clearAspects & VK_IMAGE_ASPECT_COLOR_BIT)
|
if (clearAspects & VK_IMAGE_ASPECT_COLOR_BIT)
|
||||||
colorOp.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
colorOp.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
||||||
else if (discardAspects & VK_IMAGE_ASPECT_COLOR_BIT)
|
else if (discardAspects & VK_IMAGE_ASPECT_COLOR_BIT)
|
||||||
|
@ -2010,7 +2010,7 @@ namespace dxvk {
|
||||||
|
|
||||||
if (clearAspects & VK_IMAGE_ASPECT_STENCIL_BIT)
|
if (clearAspects & VK_IMAGE_ASPECT_STENCIL_BIT)
|
||||||
depthOp.loadOpS = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
depthOp.loadOpS = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
||||||
else if (discardAspects & VK_IMAGE_ASPECT_DEPTH_BIT)
|
else if (discardAspects & VK_IMAGE_ASPECT_STENCIL_BIT)
|
||||||
depthOp.loadOpS = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
depthOp.loadOpS = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||||
|
|
||||||
if (attachmentIndex >= 0 && !m_state.om.framebufferInfo.isWritable(attachmentIndex, clearAspects | discardAspects)) {
|
if (attachmentIndex >= 0 && !m_state.om.framebufferInfo.isWritable(attachmentIndex, clearAspects | discardAspects)) {
|
||||||
|
@ -2041,6 +2041,8 @@ namespace dxvk {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attachmentIndex < 0) {
|
if (attachmentIndex < 0) {
|
||||||
|
bool hasViewFormatMismatch = imageView->info().format != imageView->imageInfo().format;
|
||||||
|
|
||||||
if (m_execBarriers.isImageDirty(imageView->image(), imageView->imageSubresources(), DxvkAccess::Write))
|
if (m_execBarriers.isImageDirty(imageView->image(), imageView->imageSubresources(), DxvkAccess::Write))
|
||||||
m_execBarriers.recordCommands(m_cmd);
|
m_execBarriers.recordCommands(m_cmd);
|
||||||
|
|
||||||
|
@ -2075,6 +2077,11 @@ namespace dxvk {
|
||||||
|
|
||||||
attachmentInfo.loadOp = colorOp.loadOp;
|
attachmentInfo.loadOp = colorOp.loadOp;
|
||||||
|
|
||||||
|
// We can't use LOAD_OP_CLEAR if the view format does not match the
|
||||||
|
// underlying image format, so just discard here and use clear later.
|
||||||
|
if (hasViewFormatMismatch && attachmentInfo.loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR)
|
||||||
|
attachmentInfo.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||||
|
|
||||||
renderingInfo.colorAttachmentCount = 1;
|
renderingInfo.colorAttachmentCount = 1;
|
||||||
renderingInfo.pColorAttachments = &attachmentInfo;
|
renderingInfo.pColorAttachments = &attachmentInfo;
|
||||||
|
|
||||||
|
@ -2110,6 +2117,20 @@ namespace dxvk {
|
||||||
}
|
}
|
||||||
|
|
||||||
m_cmd->cmdBeginRendering(&renderingInfo);
|
m_cmd->cmdBeginRendering(&renderingInfo);
|
||||||
|
|
||||||
|
if (hasViewFormatMismatch) {
|
||||||
|
VkClearAttachment clearInfo = { };
|
||||||
|
clearInfo.aspectMask = imageView->info().aspect;
|
||||||
|
clearInfo.clearValue = clearValue;
|
||||||
|
|
||||||
|
VkClearRect clearRect = { };
|
||||||
|
clearRect.rect.extent.width = extent.width;
|
||||||
|
clearRect.rect.extent.height = extent.height;
|
||||||
|
clearRect.layerCount = imageView->info().numLayers;
|
||||||
|
|
||||||
|
m_cmd->cmdClearAttachments(1, &clearInfo, 1, &clearRect);
|
||||||
|
}
|
||||||
|
|
||||||
m_cmd->cmdEndRendering();
|
m_cmd->cmdEndRendering();
|
||||||
|
|
||||||
m_execBarriers.accessImage(
|
m_execBarriers.accessImage(
|
||||||
|
@ -3563,69 +3584,90 @@ namespace dxvk {
|
||||||
VkImageSubresourceLayers srcSubresource,
|
VkImageSubresourceLayers srcSubresource,
|
||||||
VkOffset3D srcOffset,
|
VkOffset3D srcOffset,
|
||||||
VkExtent3D extent) {
|
VkExtent3D extent) {
|
||||||
VkFormat viewFormat = m_common->metaCopy().getCopyDestinationFormat(
|
DxvkMetaCopyFormats viewFormats = m_common->metaCopy().getFormats(
|
||||||
dstSubresource.aspectMask,
|
dstImage->info().format, dstSubresource.aspectMask,
|
||||||
srcSubresource.aspectMask,
|
srcImage->info().format, srcSubresource.aspectMask);
|
||||||
srcImage->info().format);
|
|
||||||
|
|
||||||
if (!viewFormat) {
|
|
||||||
Logger::err("DxvkContext: copyImageFb: Unsupported format");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Usually we should be able to draw directly to the destination image,
|
// Usually we should be able to draw directly to the destination image,
|
||||||
// but in some cases this might not be possible, e.g. if when copying
|
// but in some cases this might not be possible, e.g. if when copying
|
||||||
// from something like D32_SFLOAT to RGBA8_UNORM. In those situations,
|
// from something like D32_SFLOAT to RGBA8_UNORM. In those situations,
|
||||||
// create a temporary image to draw to, and then copy to the actual
|
// create a temporary image to draw to, and then copy to the actual
|
||||||
// destination image using a regular Vulkan transfer function.
|
// destination image using a regular Vulkan transfer function.
|
||||||
bool useDirectCopy = (dstImage->info().usage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT))
|
bool dstIsCompatible = (dstImage->info().usage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT))
|
||||||
&& (dstImage->isViewCompatible(viewFormat));
|
&& (dstImage->isViewCompatible(viewFormats.dstFormat));
|
||||||
|
bool srcIsCompatible = (srcImage->info().usage & (VK_IMAGE_USAGE_SAMPLED_BIT))
|
||||||
|
&& (srcImage->isViewCompatible(viewFormats.srcFormat));
|
||||||
|
|
||||||
if (useDirectCopy) {
|
if (dstIsCompatible && srcIsCompatible) {
|
||||||
this->copyImageFbDirect(
|
this->copyImageFbDirect(
|
||||||
dstImage, dstSubresource, dstOffset, viewFormat,
|
dstImage, dstSubresource, dstOffset, viewFormats.dstFormat,
|
||||||
srcImage, srcSubresource, srcOffset, extent);
|
srcImage, srcSubresource, srcOffset, viewFormats.srcFormat, extent);
|
||||||
} else {
|
} else if (dstIsCompatible || srcIsCompatible) {
|
||||||
DxvkImageCreateInfo imageInfo = dstImage->info();
|
DxvkImageCreateInfo imageInfo = dstImage->info();
|
||||||
imageInfo.format = viewFormat;
|
|
||||||
imageInfo.flags = 0;
|
imageInfo.flags = 0;
|
||||||
imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
|
||||||
imageInfo.extent = extent;
|
imageInfo.extent = extent;
|
||||||
imageInfo.numLayers = dstSubresource.layerCount;
|
|
||||||
imageInfo.mipLevels = 1;
|
imageInfo.mipLevels = 1;
|
||||||
imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||||
imageInfo.layout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
|
||||||
imageInfo.stages = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
|
||||||
imageInfo.access = VK_ACCESS_TRANSFER_READ_BIT;
|
|
||||||
imageInfo.viewFormatCount = 0;
|
imageInfo.viewFormatCount = 0;
|
||||||
|
|
||||||
if (dstImage->formatInfo()->aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) {
|
if (!dstIsCompatible) {
|
||||||
imageInfo.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
imageInfo.format = viewFormats.dstFormat;
|
||||||
imageInfo.stages |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
imageInfo.numLayers = dstSubresource.layerCount;
|
||||||
imageInfo.access |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
||||||
} else {
|
imageInfo.layout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
||||||
imageInfo.usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
imageInfo.stages = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||||
imageInfo.stages |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
|
imageInfo.access = VK_ACCESS_TRANSFER_READ_BIT;
|
||||||
| VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
|
|
||||||
imageInfo.access |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
if (dstImage->formatInfo()->aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) {
|
||||||
|
imageInfo.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||||
|
imageInfo.stages |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||||
|
imageInfo.access |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||||
|
} else {
|
||||||
|
imageInfo.usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
||||||
|
imageInfo.stages |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
|
||||||
|
| VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
|
||||||
|
imageInfo.access |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
||||||
|
}
|
||||||
|
} else /* if (!srcIsCompatible) */ {
|
||||||
|
imageInfo.format = viewFormats.srcFormat;
|
||||||
|
imageInfo.numLayers = srcSubresource.layerCount;
|
||||||
|
imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||||
|
imageInfo.layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||||
|
imageInfo.stages = VK_PIPELINE_STAGE_TRANSFER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
||||||
|
imageInfo.access = VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
Rc<DxvkImage> tmpImage = m_device->createImage(imageInfo,
|
Rc<DxvkImage> tmpImage = m_device->createImage(imageInfo, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
|
||||||
|
|
||||||
VkImageSubresourceLayers tmpSubresource = dstSubresource;
|
VkImageSubresourceLayers tmpSubresource = { };
|
||||||
|
tmpSubresource.aspectMask = tmpImage->formatInfo()->aspectMask;
|
||||||
tmpSubresource.mipLevel = 0;
|
tmpSubresource.mipLevel = 0;
|
||||||
tmpSubresource.baseArrayLayer = 0;
|
tmpSubresource.baseArrayLayer = 0;
|
||||||
|
tmpSubresource.layerCount = imageInfo.numLayers;
|
||||||
|
|
||||||
VkOffset3D tmpOffset = { 0, 0, 0 };
|
VkOffset3D tmpOffset = { 0, 0, 0 };
|
||||||
|
|
||||||
this->copyImageFbDirect(
|
if (!dstIsCompatible) {
|
||||||
tmpImage, tmpSubresource, tmpOffset, viewFormat,
|
this->copyImageFbDirect(
|
||||||
srcImage, srcSubresource, srcOffset, extent);
|
tmpImage, tmpSubresource, tmpOffset, viewFormats.dstFormat,
|
||||||
|
srcImage, srcSubresource, srcOffset, viewFormats.srcFormat, extent);
|
||||||
|
|
||||||
this->copyImageHw(
|
this->copyImageHw(
|
||||||
dstImage, dstSubresource, dstOffset,
|
dstImage, dstSubresource, dstOffset,
|
||||||
tmpImage, tmpSubresource, tmpOffset, extent);
|
tmpImage, tmpSubresource, tmpOffset, extent);
|
||||||
|
} else /* if (!srcIsCompatible) */ {
|
||||||
|
this->copyImageHw(
|
||||||
|
tmpImage, tmpSubresource, tmpOffset,
|
||||||
|
srcImage, srcSubresource, srcOffset, extent);
|
||||||
|
|
||||||
|
this->copyImageFbDirect(
|
||||||
|
dstImage, dstSubresource, dstOffset, viewFormats.dstFormat,
|
||||||
|
tmpImage, tmpSubresource, tmpOffset, viewFormats.srcFormat, extent);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Logger::err(str::format("DxvkContext: copyImageFb: Unsupported operation:\n"
|
||||||
|
" srcFormat = ", srcImage->info().format, " (aspect ", srcSubresource.aspectMask, ")\n",
|
||||||
|
" dstFormat = ", dstImage->info().format, " (aspect ", dstSubresource.aspectMask, ")"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3638,6 +3680,7 @@ namespace dxvk {
|
||||||
const Rc<DxvkImage>& srcImage,
|
const Rc<DxvkImage>& srcImage,
|
||||||
VkImageSubresourceLayers srcSubresource,
|
VkImageSubresourceLayers srcSubresource,
|
||||||
VkOffset3D srcOffset,
|
VkOffset3D srcOffset,
|
||||||
|
VkFormat srcFormat,
|
||||||
VkExtent3D extent) {
|
VkExtent3D extent) {
|
||||||
this->invalidateState();
|
this->invalidateState();
|
||||||
|
|
||||||
|
@ -3701,8 +3744,6 @@ namespace dxvk {
|
||||||
m_execAcquires.recordCommands(m_cmd);
|
m_execAcquires.recordCommands(m_cmd);
|
||||||
|
|
||||||
// Create source and destination image views
|
// Create source and destination image views
|
||||||
VkFormat srcFormat = srcImage->info().format;
|
|
||||||
|
|
||||||
Rc<DxvkMetaCopyViews> views = new DxvkMetaCopyViews(m_device->vkd(),
|
Rc<DxvkMetaCopyViews> views = new DxvkMetaCopyViews(m_device->vkd(),
|
||||||
dstImage, dstSubresource, dstFormat,
|
dstImage, dstSubresource, dstFormat,
|
||||||
srcImage, srcSubresource, srcFormat);
|
srcImage, srcSubresource, srcFormat);
|
||||||
|
@ -4721,8 +4762,10 @@ namespace dxvk {
|
||||||
this->renderPassEmitPostBarriers(framebufferInfo, ops);
|
this->renderPassEmitPostBarriers(framebufferInfo, ops);
|
||||||
|
|
||||||
uint32_t colorInfoCount = 0;
|
uint32_t colorInfoCount = 0;
|
||||||
|
uint32_t lateClearCount = 0;
|
||||||
|
|
||||||
std::array<VkRenderingAttachmentInfo, MaxNumRenderTargets> colorInfos;
|
std::array<VkRenderingAttachmentInfo, MaxNumRenderTargets> colorInfos;
|
||||||
|
std::array<VkClearAttachment, MaxNumRenderTargets> lateClears;
|
||||||
|
|
||||||
for (uint32_t i = 0; i < MaxNumRenderTargets; i++) {
|
for (uint32_t i = 0; i < MaxNumRenderTargets; i++) {
|
||||||
const auto& colorTarget = framebufferInfo.getColorTarget(i);
|
const auto& colorTarget = framebufferInfo.getColorTarget(i);
|
||||||
|
@ -4734,9 +4777,21 @@ namespace dxvk {
|
||||||
colorInfos[i].loadOp = ops.colorOps[i].loadOp;
|
colorInfos[i].loadOp = ops.colorOps[i].loadOp;
|
||||||
colorInfos[i].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
colorInfos[i].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||||
|
|
||||||
if (ops.colorOps[i].loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR)
|
if (ops.colorOps[i].loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR) {
|
||||||
colorInfos[i].clearValue.color = ops.colorOps[i].clearValue;
|
colorInfos[i].clearValue.color = ops.colorOps[i].clearValue;
|
||||||
|
|
||||||
|
// We can't use LOAD_OP_CLEAR if the view format does not match the
|
||||||
|
// underlying image format, so just discard here and use clear later.
|
||||||
|
if (colorTarget.view->info().format != colorTarget.view->imageInfo().format) {
|
||||||
|
colorInfos[i].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||||
|
|
||||||
|
auto& clear = lateClears[lateClearCount++];
|
||||||
|
clear.colorAttachment = i;
|
||||||
|
clear.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
|
clear.clearValue.color = ops.colorOps[i].clearValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
colorInfoCount = i + 1;
|
colorInfoCount = i + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4784,6 +4839,15 @@ namespace dxvk {
|
||||||
|
|
||||||
m_cmd->cmdBeginRendering(&renderingInfo);
|
m_cmd->cmdBeginRendering(&renderingInfo);
|
||||||
|
|
||||||
|
if (lateClearCount) {
|
||||||
|
VkClearRect clearRect = { };
|
||||||
|
clearRect.rect.extent.width = fbSize.width;
|
||||||
|
clearRect.rect.extent.height = fbSize.height;
|
||||||
|
clearRect.layerCount = fbSize.layers;
|
||||||
|
|
||||||
|
m_cmd->cmdClearAttachments(lateClearCount, lateClears.data(), 1, &clearRect);
|
||||||
|
}
|
||||||
|
|
||||||
for (uint32_t i = 0; i < framebufferInfo.numAttachments(); i++) {
|
for (uint32_t i = 0; i < framebufferInfo.numAttachments(); i++) {
|
||||||
m_cmd->trackResource<DxvkAccess::None> (framebufferInfo.getAttachment(i).view);
|
m_cmd->trackResource<DxvkAccess::None> (framebufferInfo.getAttachment(i).view);
|
||||||
m_cmd->trackResource<DxvkAccess::Write>(framebufferInfo.getAttachment(i).view->image());
|
m_cmd->trackResource<DxvkAccess::Write>(framebufferInfo.getAttachment(i).view->image());
|
||||||
|
@ -5594,11 +5658,13 @@ namespace dxvk {
|
||||||
auto bufferInfo = m_state.vi.indexBuffer.getDescriptor();
|
auto bufferInfo = m_state.vi.indexBuffer.getDescriptor();
|
||||||
|
|
||||||
if (m_features.test(DxvkContextFeature::IndexBufferRobustness)) {
|
if (m_features.test(DxvkContextFeature::IndexBufferRobustness)) {
|
||||||
|
VkDeviceSize align = m_state.vi.indexType == VK_INDEX_TYPE_UINT16 ? 2 : 4;
|
||||||
|
VkDeviceSize range = bufferInfo.buffer.range & ~(align - 1);
|
||||||
|
|
||||||
m_cmd->cmdBindIndexBuffer2(
|
m_cmd->cmdBindIndexBuffer2(
|
||||||
bufferInfo.buffer.buffer,
|
bufferInfo.buffer.buffer,
|
||||||
bufferInfo.buffer.offset,
|
bufferInfo.buffer.offset,
|
||||||
bufferInfo.buffer.range,
|
range, m_state.vi.indexType);
|
||||||
m_state.vi.indexType);
|
|
||||||
} else {
|
} else {
|
||||||
m_cmd->cmdBindIndexBuffer(
|
m_cmd->cmdBindIndexBuffer(
|
||||||
bufferInfo.buffer.buffer,
|
bufferInfo.buffer.buffer,
|
||||||
|
|
|
@ -1506,6 +1506,7 @@ namespace dxvk {
|
||||||
const Rc<DxvkImage>& srcImage,
|
const Rc<DxvkImage>& srcImage,
|
||||||
VkImageSubresourceLayers srcSubresource,
|
VkImageSubresourceLayers srcSubresource,
|
||||||
VkOffset3D srcOffset,
|
VkOffset3D srcOffset,
|
||||||
|
VkFormat srcFormat,
|
||||||
VkExtent3D extent);
|
VkExtent3D extent);
|
||||||
|
|
||||||
bool copyImageClear(
|
bool copyImageClear(
|
||||||
|
|
|
@ -72,7 +72,7 @@ namespace dxvk {
|
||||||
// memory bloat. This may be necessary for off-screen
|
// memory bloat. This may be necessary for off-screen
|
||||||
// rendering applications, or in situations where games
|
// rendering applications, or in situations where games
|
||||||
// pre-render a lot of images without presenting in between.
|
// pre-render a lot of images without presenting in between.
|
||||||
return m_descriptorPools.size() >= 8;
|
return m_descriptorPools.size() > MaxDesiredPoolCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -100,29 +100,25 @@ namespace dxvk {
|
||||||
|
|
||||||
|
|
||||||
void DxvkDescriptorPool::reset() {
|
void DxvkDescriptorPool::reset() {
|
||||||
// As a heuristic to save memory, check how many descriptors
|
// As a heuristic to save memory, check how many descriptor
|
||||||
// have actively been used in the past couple of submissions.
|
// sets were actually being used in past submissions.
|
||||||
bool isLowUsageFrame = false;
|
|
||||||
|
|
||||||
size_t poolCount = m_descriptorPools.size();
|
size_t poolCount = m_descriptorPools.size();
|
||||||
|
bool needsReset = poolCount > MaxDesiredPoolCount;
|
||||||
|
|
||||||
if (poolCount > 1 || m_setsAllocated > m_manager->getMaxSetCount() / 2) {
|
if (poolCount > 1 || m_setsAllocated > m_manager->getMaxSetCount() / 2) {
|
||||||
double factor = std::max(11.0 / 3.0 - double(poolCount) / 3.0, 1.0);
|
double factor = std::max(11.0 / 3.0 - double(poolCount) / 3.0, 1.0);
|
||||||
isLowUsageFrame = double(m_setsUsed) * factor < double(m_setsAllocated);
|
needsReset = double(m_setsUsed) * factor < double(m_setsAllocated);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_lowUsageFrames = isLowUsageFrame
|
|
||||||
? m_lowUsageFrames + 1
|
|
||||||
: 0;
|
|
||||||
m_setsUsed = 0;
|
m_setsUsed = 0;
|
||||||
|
|
||||||
if (m_lowUsageFrames < 16) {
|
if (!needsReset) {
|
||||||
for (auto& entry : m_setLists)
|
for (auto& entry : m_setLists)
|
||||||
entry.second.reset();
|
entry.second.reset();
|
||||||
} else {
|
} else {
|
||||||
// If most sets are no longer being used, reset and destroy
|
// If most sets are no longer needed, reset and destroy
|
||||||
// descriptor pools and reset all lookup tables in order to
|
// descriptor pools and reset all lookup tables in order
|
||||||
// accomodate more descriptors of different layouts.
|
// to accomodate more descriptors of different layouts.
|
||||||
for (auto pool : m_descriptorPools)
|
for (auto pool : m_descriptorPools)
|
||||||
m_manager->recycleVulkanDescriptorPool(pool);
|
m_manager->recycleVulkanDescriptorPool(pool);
|
||||||
|
|
||||||
|
@ -131,7 +127,6 @@ namespace dxvk {
|
||||||
m_setMaps.clear();
|
m_setMaps.clear();
|
||||||
|
|
||||||
m_setsAllocated = 0;
|
m_setsAllocated = 0;
|
||||||
m_lowUsageFrames = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_cachedEntry = { nullptr, nullptr };
|
m_cachedEntry = { nullptr, nullptr };
|
||||||
|
|
|
@ -80,7 +80,7 @@ namespace dxvk {
|
||||||
* to be updated.
|
* to be updated.
|
||||||
*/
|
*/
|
||||||
class DxvkDescriptorPool : public RcObject {
|
class DxvkDescriptorPool : public RcObject {
|
||||||
|
constexpr static uint32_t MaxDesiredPoolCount = 2;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
DxvkDescriptorPool(
|
DxvkDescriptorPool(
|
||||||
|
@ -155,8 +155,6 @@ namespace dxvk {
|
||||||
|
|
||||||
uint32_t m_prevSetsAllocated = 0;
|
uint32_t m_prevSetsAllocated = 0;
|
||||||
|
|
||||||
uint32_t m_lowUsageFrames = 0;
|
|
||||||
|
|
||||||
DxvkDescriptorSetMap* getSetMapCached(
|
DxvkDescriptorSetMap* getSetMapCached(
|
||||||
const DxvkBindingLayoutObjects* layout);
|
const DxvkBindingLayoutObjects* layout);
|
||||||
|
|
||||||
|
|
|
@ -68,6 +68,7 @@ namespace dxvk {
|
||||||
VkPhysicalDeviceMaintenance5FeaturesKHR khrMaintenance5;
|
VkPhysicalDeviceMaintenance5FeaturesKHR khrMaintenance5;
|
||||||
VkPhysicalDevicePresentIdFeaturesKHR khrPresentId;
|
VkPhysicalDevicePresentIdFeaturesKHR khrPresentId;
|
||||||
VkPhysicalDevicePresentWaitFeaturesKHR khrPresentWait;
|
VkPhysicalDevicePresentWaitFeaturesKHR khrPresentWait;
|
||||||
|
VkPhysicalDeviceRawAccessChainsFeaturesNV nvRawAccessChains;
|
||||||
VkBool32 nvxBinaryImport;
|
VkBool32 nvxBinaryImport;
|
||||||
VkBool32 nvxImageViewHandle;
|
VkBool32 nvxImageViewHandle;
|
||||||
VkBool32 khrWin32KeyedMutex;
|
VkBool32 khrWin32KeyedMutex;
|
||||||
|
|
|
@ -325,6 +325,7 @@ namespace dxvk {
|
||||||
DxvkExt khrPresentWait = { VK_KHR_PRESENT_WAIT_EXTENSION_NAME, DxvkExtMode::Optional };
|
DxvkExt khrPresentWait = { VK_KHR_PRESENT_WAIT_EXTENSION_NAME, DxvkExtMode::Optional };
|
||||||
DxvkExt khrSwapchain = { VK_KHR_SWAPCHAIN_EXTENSION_NAME, DxvkExtMode::Required };
|
DxvkExt khrSwapchain = { VK_KHR_SWAPCHAIN_EXTENSION_NAME, DxvkExtMode::Required };
|
||||||
DxvkExt khrWin32KeyedMutex = { VK_KHR_WIN32_KEYED_MUTEX_EXTENSION_NAME, DxvkExtMode::Optional };
|
DxvkExt khrWin32KeyedMutex = { VK_KHR_WIN32_KEYED_MUTEX_EXTENSION_NAME, DxvkExtMode::Optional };
|
||||||
|
DxvkExt nvRawAccessChains = { VK_NV_RAW_ACCESS_CHAINS_EXTENSION_NAME, DxvkExtMode::Optional };
|
||||||
DxvkExt nvxBinaryImport = { VK_NVX_BINARY_IMPORT_EXTENSION_NAME, DxvkExtMode::Disabled };
|
DxvkExt nvxBinaryImport = { VK_NVX_BINARY_IMPORT_EXTENSION_NAME, DxvkExtMode::Disabled };
|
||||||
DxvkExt nvxImageViewHandle = { VK_NVX_IMAGE_VIEW_HANDLE_EXTENSION_NAME, DxvkExtMode::Disabled };
|
DxvkExt nvxImageViewHandle = { VK_NVX_IMAGE_VIEW_HANDLE_EXTENSION_NAME, DxvkExtMode::Disabled };
|
||||||
};
|
};
|
||||||
|
|
|
@ -177,7 +177,7 @@ namespace dxvk {
|
||||||
appInfo.pApplicationName = appName.c_str();
|
appInfo.pApplicationName = appName.c_str();
|
||||||
appInfo.applicationVersion = flags.raw();
|
appInfo.applicationVersion = flags.raw();
|
||||||
appInfo.pEngineName = "DXVK";
|
appInfo.pEngineName = "DXVK";
|
||||||
appInfo.engineVersion = VK_MAKE_VERSION(2, 3, 0);
|
appInfo.engineVersion = VK_MAKE_VERSION(2, 3, 1);
|
||||||
appInfo.apiVersion = VK_MAKE_VERSION(1, 3, 0);
|
appInfo.apiVersion = VK_MAKE_VERSION(1, 3, 0);
|
||||||
|
|
||||||
VkInstanceCreateInfo info = { VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO };
|
VkInstanceCreateInfo info = { VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO };
|
||||||
|
|
|
@ -188,7 +188,6 @@ namespace dxvk {
|
||||||
for (uint32_t i = 0; i < m_memProps.memoryHeapCount; i++) {
|
for (uint32_t i = 0; i < m_memProps.memoryHeapCount; i++) {
|
||||||
m_memHeaps[i].properties = m_memProps.memoryHeaps[i];
|
m_memHeaps[i].properties = m_memProps.memoryHeaps[i];
|
||||||
m_memHeaps[i].stats = DxvkMemoryStats { 0, 0 };
|
m_memHeaps[i].stats = DxvkMemoryStats { 0, 0 };
|
||||||
m_memHeaps[i].budget = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint32_t i = 0; i < m_memProps.memoryTypeCount; i++) {
|
for (uint32_t i = 0; i < m_memProps.memoryTypeCount; i++) {
|
||||||
|
@ -385,9 +384,6 @@ namespace dxvk {
|
||||||
bool useMemoryPriority = (info.flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
|
bool useMemoryPriority = (info.flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
|
||||||
&& (m_device->features().extMemoryPriority.memoryPriority);
|
&& (m_device->features().extMemoryPriority.memoryPriority);
|
||||||
|
|
||||||
if (type->heap->budget && type->heap->stats.memoryAllocated + size > type->heap->budget)
|
|
||||||
return DxvkDeviceMemory();
|
|
||||||
|
|
||||||
float priority = 0.0f;
|
float priority = 0.0f;
|
||||||
|
|
||||||
if (hints.test(DxvkMemoryFlag::GpuReadable))
|
if (hints.test(DxvkMemoryFlag::GpuReadable))
|
||||||
|
@ -547,11 +543,7 @@ namespace dxvk {
|
||||||
bool DxvkMemoryAllocator::shouldFreeEmptyChunks(
|
bool DxvkMemoryAllocator::shouldFreeEmptyChunks(
|
||||||
const DxvkMemoryHeap* heap,
|
const DxvkMemoryHeap* heap,
|
||||||
VkDeviceSize allocationSize) const {
|
VkDeviceSize allocationSize) const {
|
||||||
VkDeviceSize budget = heap->budget;
|
VkDeviceSize budget = (heap->properties.size * 4) / 5;
|
||||||
|
|
||||||
if (!budget)
|
|
||||||
budget = (heap->properties.size * 4) / 5;
|
|
||||||
|
|
||||||
return heap->stats.memoryAllocated + allocationSize > budget;
|
return heap->stats.memoryAllocated + allocationSize > budget;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -66,7 +66,6 @@ namespace dxvk {
|
||||||
struct DxvkMemoryHeap {
|
struct DxvkMemoryHeap {
|
||||||
VkMemoryHeap properties;
|
VkMemoryHeap properties;
|
||||||
DxvkMemoryStats stats;
|
DxvkMemoryStats stats;
|
||||||
VkDeviceSize budget;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -9,9 +9,6 @@
|
||||||
#include <dxvk_copy_color_1d.h>
|
#include <dxvk_copy_color_1d.h>
|
||||||
#include <dxvk_copy_color_2d.h>
|
#include <dxvk_copy_color_2d.h>
|
||||||
#include <dxvk_copy_color_ms.h>
|
#include <dxvk_copy_color_ms.h>
|
||||||
#include <dxvk_copy_depth_1d.h>
|
|
||||||
#include <dxvk_copy_depth_2d.h>
|
|
||||||
#include <dxvk_copy_depth_ms.h>
|
|
||||||
#include <dxvk_copy_depth_stencil_1d.h>
|
#include <dxvk_copy_depth_stencil_1d.h>
|
||||||
#include <dxvk_copy_depth_stencil_2d.h>
|
#include <dxvk_copy_depth_stencil_2d.h>
|
||||||
#include <dxvk_copy_depth_stencil_ms.h>
|
#include <dxvk_copy_depth_stencil_ms.h>
|
||||||
|
@ -84,11 +81,7 @@ namespace dxvk {
|
||||||
m_color {
|
m_color {
|
||||||
createShaderModule(dxvk_copy_color_1d),
|
createShaderModule(dxvk_copy_color_1d),
|
||||||
createShaderModule(dxvk_copy_color_2d),
|
createShaderModule(dxvk_copy_color_2d),
|
||||||
createShaderModule(dxvk_copy_color_ms) },
|
createShaderModule(dxvk_copy_color_ms) } {
|
||||||
m_depth {
|
|
||||||
createShaderModule(dxvk_copy_depth_1d),
|
|
||||||
createShaderModule(dxvk_copy_depth_2d),
|
|
||||||
createShaderModule(dxvk_copy_depth_ms) } {
|
|
||||||
if (device->features().vk12.shaderOutputLayer) {
|
if (device->features().vk12.shaderOutputLayer) {
|
||||||
m_shaderVert = createShaderModule(dxvk_fullscreen_layer_vert);
|
m_shaderVert = createShaderModule(dxvk_fullscreen_layer_vert);
|
||||||
} else {
|
} else {
|
||||||
|
@ -119,9 +112,6 @@ namespace dxvk {
|
||||||
m_vkd->vkDestroyShaderModule(m_vkd->device(), m_depthStencil.fragMs, nullptr);
|
m_vkd->vkDestroyShaderModule(m_vkd->device(), m_depthStencil.fragMs, nullptr);
|
||||||
m_vkd->vkDestroyShaderModule(m_vkd->device(), m_depthStencil.frag2D, nullptr);
|
m_vkd->vkDestroyShaderModule(m_vkd->device(), m_depthStencil.frag2D, nullptr);
|
||||||
m_vkd->vkDestroyShaderModule(m_vkd->device(), m_depthStencil.frag1D, nullptr);
|
m_vkd->vkDestroyShaderModule(m_vkd->device(), m_depthStencil.frag1D, nullptr);
|
||||||
m_vkd->vkDestroyShaderModule(m_vkd->device(), m_depth.fragMs, nullptr);
|
|
||||||
m_vkd->vkDestroyShaderModule(m_vkd->device(), m_depth.frag2D, nullptr);
|
|
||||||
m_vkd->vkDestroyShaderModule(m_vkd->device(), m_depth.frag1D, nullptr);
|
|
||||||
m_vkd->vkDestroyShaderModule(m_vkd->device(), m_color.fragMs, nullptr);
|
m_vkd->vkDestroyShaderModule(m_vkd->device(), m_color.fragMs, nullptr);
|
||||||
m_vkd->vkDestroyShaderModule(m_vkd->device(), m_color.frag2D, nullptr);
|
m_vkd->vkDestroyShaderModule(m_vkd->device(), m_color.frag2D, nullptr);
|
||||||
m_vkd->vkDestroyShaderModule(m_vkd->device(), m_color.frag1D, nullptr);
|
m_vkd->vkDestroyShaderModule(m_vkd->device(), m_color.frag1D, nullptr);
|
||||||
|
@ -130,32 +120,29 @@ namespace dxvk {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
VkFormat DxvkMetaCopyObjects::getCopyDestinationFormat(
|
DxvkMetaCopyFormats DxvkMetaCopyObjects::getFormats(
|
||||||
|
VkFormat dstFormat,
|
||||||
VkImageAspectFlags dstAspect,
|
VkImageAspectFlags dstAspect,
|
||||||
VkImageAspectFlags srcAspect,
|
VkFormat srcFormat,
|
||||||
VkFormat srcFormat) const {
|
VkImageAspectFlags srcAspect) const {
|
||||||
if (srcAspect == dstAspect)
|
if (dstAspect == srcAspect)
|
||||||
return srcFormat;
|
return { dstFormat, srcFormat };
|
||||||
|
|
||||||
if (dstAspect == VK_IMAGE_ASPECT_COLOR_BIT
|
if (dstAspect == VK_IMAGE_ASPECT_COLOR_BIT && srcAspect == VK_IMAGE_ASPECT_DEPTH_BIT) {
|
||||||
&& srcAspect == VK_IMAGE_ASPECT_DEPTH_BIT) {
|
|
||||||
switch (srcFormat) {
|
switch (srcFormat) {
|
||||||
case VK_FORMAT_D16_UNORM: return VK_FORMAT_R16_UNORM;
|
case VK_FORMAT_D16_UNORM: return { VK_FORMAT_R16_UNORM, VK_FORMAT_D16_UNORM };
|
||||||
case VK_FORMAT_D32_SFLOAT: return VK_FORMAT_R32_SFLOAT;
|
case VK_FORMAT_D32_SFLOAT: return { VK_FORMAT_R32_SFLOAT, VK_FORMAT_D32_SFLOAT };
|
||||||
default: return VK_FORMAT_UNDEFINED;
|
default: return { VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED };
|
||||||
|
}
|
||||||
|
} else if (dstAspect == VK_IMAGE_ASPECT_DEPTH_BIT && srcAspect == VK_IMAGE_ASPECT_COLOR_BIT) {
|
||||||
|
switch (dstFormat) {
|
||||||
|
case VK_FORMAT_D16_UNORM: return { VK_FORMAT_D16_UNORM, VK_FORMAT_R16_UNORM };
|
||||||
|
case VK_FORMAT_D32_SFLOAT: return { VK_FORMAT_D32_SFLOAT, VK_FORMAT_R32_SFLOAT };
|
||||||
|
default: return { VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dstAspect == VK_IMAGE_ASPECT_DEPTH_BIT
|
return { VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED };
|
||||||
&& srcAspect == VK_IMAGE_ASPECT_COLOR_BIT) {
|
|
||||||
switch (srcFormat) {
|
|
||||||
case VK_FORMAT_R16_UNORM: return VK_FORMAT_D16_UNORM;
|
|
||||||
case VK_FORMAT_R32_SFLOAT: return VK_FORMAT_D32_SFLOAT;
|
|
||||||
default: return VK_FORMAT_UNDEFINED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return VK_FORMAT_UNDEFINED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -313,7 +300,7 @@ namespace dxvk {
|
||||||
|
|
||||||
std::array<std::pair<const FragShaders*, VkImageAspectFlags>, 3> shaderSets = {{
|
std::array<std::pair<const FragShaders*, VkImageAspectFlags>, 3> shaderSets = {{
|
||||||
{ &m_color, VK_IMAGE_ASPECT_COLOR_BIT },
|
{ &m_color, VK_IMAGE_ASPECT_COLOR_BIT },
|
||||||
{ &m_depth, VK_IMAGE_ASPECT_DEPTH_BIT },
|
{ &m_color, VK_IMAGE_ASPECT_DEPTH_BIT },
|
||||||
{ &m_depthStencil, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT },
|
{ &m_depthStencil, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT },
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,14 @@ namespace dxvk {
|
||||||
VkExtent2D srcSize;
|
VkExtent2D srcSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Pair of view formats for copy operation
|
||||||
|
*/
|
||||||
|
struct DxvkMetaCopyFormats {
|
||||||
|
VkFormat dstFormat;
|
||||||
|
VkFormat srcFormat;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Copy pipeline
|
* \brief Copy pipeline
|
||||||
*
|
*
|
||||||
|
@ -122,13 +130,17 @@ namespace dxvk {
|
||||||
* Returns the color format that we need to use
|
* Returns the color format that we need to use
|
||||||
* as the destination image view format in case
|
* as the destination image view format in case
|
||||||
* of depth to color image copies.
|
* of depth to color image copies.
|
||||||
* \param [in] format Depth format
|
* \param [in] dstFormat Destination image format
|
||||||
|
* \param [in] dstAspect Destination aspect mask
|
||||||
|
* \param [in] srcFormat Source image format
|
||||||
|
* \param [in] srcAspect Source aspect mask
|
||||||
* \returns Corresponding color format
|
* \returns Corresponding color format
|
||||||
*/
|
*/
|
||||||
VkFormat getCopyDestinationFormat(
|
DxvkMetaCopyFormats getFormats(
|
||||||
|
VkFormat dstFormat,
|
||||||
VkImageAspectFlags dstAspect,
|
VkImageAspectFlags dstAspect,
|
||||||
VkImageAspectFlags srcAspect,
|
VkFormat srcFormat,
|
||||||
VkFormat srcFormat) const;
|
VkImageAspectFlags srcAspect) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Creates pipeline for meta copy operation
|
* \brief Creates pipeline for meta copy operation
|
||||||
|
|
|
@ -382,6 +382,9 @@ namespace dxvk {
|
||||||
|
|
||||||
|
|
||||||
bool Presenter::supportsColorSpace(VkColorSpaceKHR colorspace) {
|
bool Presenter::supportsColorSpace(VkColorSpaceKHR colorspace) {
|
||||||
|
if (!m_surface)
|
||||||
|
return false;
|
||||||
|
|
||||||
std::vector<VkSurfaceFormatKHR> surfaceFormats;
|
std::vector<VkSurfaceFormatKHR> surfaceFormats;
|
||||||
getSupportedFormats(surfaceFormats, VK_FULL_SCREEN_EXCLUSIVE_DEFAULT_EXT);
|
getSupportedFormats(surfaceFormats, VK_FULL_SCREEN_EXCLUSIVE_DEFAULT_EXT);
|
||||||
|
|
||||||
|
|
|
@ -20,9 +20,6 @@ dxvk_shaders = files([
|
||||||
'shaders/dxvk_copy_color_1d.frag',
|
'shaders/dxvk_copy_color_1d.frag',
|
||||||
'shaders/dxvk_copy_color_2d.frag',
|
'shaders/dxvk_copy_color_2d.frag',
|
||||||
'shaders/dxvk_copy_color_ms.frag',
|
'shaders/dxvk_copy_color_ms.frag',
|
||||||
'shaders/dxvk_copy_depth_1d.frag',
|
|
||||||
'shaders/dxvk_copy_depth_2d.frag',
|
|
||||||
'shaders/dxvk_copy_depth_ms.frag',
|
|
||||||
'shaders/dxvk_copy_depth_stencil_1d.frag',
|
'shaders/dxvk_copy_depth_stencil_1d.frag',
|
||||||
'shaders/dxvk_copy_depth_stencil_2d.frag',
|
'shaders/dxvk_copy_depth_stencil_2d.frag',
|
||||||
'shaders/dxvk_copy_depth_stencil_ms.frag',
|
'shaders/dxvk_copy_depth_stencil_ms.frag',
|
||||||
|
|
|
@ -13,6 +13,8 @@ uniform u_info_t {
|
||||||
} u_info;
|
} u_info;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
o_color = texelFetch(s_image,
|
vec4 color = texelFetch(s_image,
|
||||||
ivec2(gl_FragCoord.x + u_info.offset.x, gl_Layer), 0);
|
ivec2(gl_FragCoord.x + u_info.offset.x, gl_Layer), 0);
|
||||||
}
|
o_color = color;
|
||||||
|
gl_FragDepth = color.r;
|
||||||
|
}
|
||||||
|
|
|
@ -13,6 +13,8 @@ uniform u_info_t {
|
||||||
} u_info;
|
} u_info;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
o_color = texelFetch(s_image,
|
vec4 color = texelFetch(s_image,
|
||||||
ivec3(gl_FragCoord.xy + u_info.offset, gl_Layer), 0);
|
ivec3(gl_FragCoord.xy + u_info.offset, gl_Layer), 0);
|
||||||
}
|
o_color = color;
|
||||||
|
gl_FragDepth = color.r;
|
||||||
|
}
|
||||||
|
|
|
@ -13,7 +13,9 @@ uniform u_info_t {
|
||||||
} u_info;
|
} u_info;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
o_color = texelFetch(s_image,
|
vec4 color = texelFetch(s_image,
|
||||||
ivec3(gl_FragCoord.xy + u_info.offset, gl_Layer),
|
ivec3(gl_FragCoord.xy + u_info.offset, gl_Layer),
|
||||||
gl_SampleID);
|
gl_SampleID);
|
||||||
}
|
o_color = color;
|
||||||
|
gl_FragDepth = color.r;
|
||||||
|
}
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
#version 450
|
|
||||||
|
|
||||||
#extension GL_EXT_samplerless_texture_functions : require
|
|
||||||
|
|
||||||
layout(set = 0, binding = 0)
|
|
||||||
uniform texture1DArray s_image;
|
|
||||||
|
|
||||||
layout(push_constant)
|
|
||||||
uniform u_info_t {
|
|
||||||
ivec2 offset;
|
|
||||||
} u_info;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
gl_FragDepth = texelFetch(s_image,
|
|
||||||
ivec2(gl_FragCoord.x + u_info.offset.x, gl_Layer), 0).r;
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
#version 450
|
|
||||||
|
|
||||||
#extension GL_EXT_samplerless_texture_functions : require
|
|
||||||
|
|
||||||
layout(set = 0, binding = 0)
|
|
||||||
uniform texture2DArray s_image;
|
|
||||||
|
|
||||||
layout(push_constant)
|
|
||||||
uniform u_info_t {
|
|
||||||
ivec2 offset;
|
|
||||||
} u_info;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
gl_FragDepth = texelFetch(s_image,
|
|
||||||
ivec3(gl_FragCoord.xy + u_info.offset, gl_Layer), 0).r;
|
|
||||||
}
|
|
|
@ -1,17 +0,0 @@
|
||||||
#version 450
|
|
||||||
|
|
||||||
#extension GL_EXT_samplerless_texture_functions : require
|
|
||||||
|
|
||||||
layout(set = 0, binding = 0)
|
|
||||||
uniform texture2DMSArray s_image;
|
|
||||||
|
|
||||||
layout(push_constant)
|
|
||||||
uniform u_info_t {
|
|
||||||
ivec2 offset;
|
|
||||||
} u_info;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
gl_FragDepth = texelFetch(s_image,
|
|
||||||
ivec3(gl_FragCoord.xy + u_info.offset, gl_Layer),
|
|
||||||
gl_SampleID).r;
|
|
||||||
}
|
|
|
@ -470,6 +470,13 @@ namespace dxvk {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t SpirvModule::constNull(
|
||||||
|
uint32_t typeId) {
|
||||||
|
return this->defConst(spv::OpConstantNull,
|
||||||
|
typeId, 0, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32_t SpirvModule::lateConst32(
|
uint32_t SpirvModule::lateConst32(
|
||||||
uint32_t typeId) {
|
uint32_t typeId) {
|
||||||
uint32_t resultId = this->allocateId();
|
uint32_t resultId = this->allocateId();
|
||||||
|
@ -2697,6 +2704,30 @@ namespace dxvk {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t SpirvModule::opRawAccessChain(
|
||||||
|
uint32_t resultType,
|
||||||
|
uint32_t base,
|
||||||
|
uint32_t stride,
|
||||||
|
uint32_t index,
|
||||||
|
uint32_t offset,
|
||||||
|
uint32_t operand) {
|
||||||
|
uint32_t resultId = this->allocateId();
|
||||||
|
|
||||||
|
m_code.putIns (spv::OpRawAccessChainNV, operand ? 8 : 7);
|
||||||
|
m_code.putWord(resultType);
|
||||||
|
m_code.putWord(resultId);
|
||||||
|
m_code.putWord(base);
|
||||||
|
m_code.putWord(stride);
|
||||||
|
m_code.putWord(index);
|
||||||
|
m_code.putWord(offset);
|
||||||
|
|
||||||
|
if (operand)
|
||||||
|
m_code.putWord(operand);
|
||||||
|
|
||||||
|
return resultId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32_t SpirvModule::opReflect(
|
uint32_t SpirvModule::opReflect(
|
||||||
uint32_t resultType,
|
uint32_t resultType,
|
||||||
uint32_t incident,
|
uint32_t incident,
|
||||||
|
|
|
@ -217,6 +217,9 @@ namespace dxvk {
|
||||||
uint32_t constUndef(
|
uint32_t constUndef(
|
||||||
uint32_t typeId);
|
uint32_t typeId);
|
||||||
|
|
||||||
|
uint32_t constNull(
|
||||||
|
uint32_t typeId);
|
||||||
|
|
||||||
uint32_t lateConst32(
|
uint32_t lateConst32(
|
||||||
uint32_t typeId);
|
uint32_t typeId);
|
||||||
|
|
||||||
|
@ -951,6 +954,14 @@ namespace dxvk {
|
||||||
uint32_t resultType,
|
uint32_t resultType,
|
||||||
uint32_t operand);
|
uint32_t operand);
|
||||||
|
|
||||||
|
uint32_t opRawAccessChain(
|
||||||
|
uint32_t resultType,
|
||||||
|
uint32_t base,
|
||||||
|
uint32_t stride,
|
||||||
|
uint32_t index,
|
||||||
|
uint32_t offset,
|
||||||
|
uint32_t operand);
|
||||||
|
|
||||||
uint32_t opReflect(
|
uint32_t opReflect(
|
||||||
uint32_t resultType,
|
uint32_t resultType,
|
||||||
uint32_t incident,
|
uint32_t incident,
|
||||||
|
|
|
@ -13,7 +13,10 @@
|
||||||
|
|
||||||
namespace dxvk {
|
namespace dxvk {
|
||||||
|
|
||||||
const static std::vector<std::pair<const char*, Config>> g_appDefaults = {{
|
using ProfileList = std::vector<std::pair<const char*, Config>>;
|
||||||
|
|
||||||
|
|
||||||
|
const static ProfileList g_profiles = {{
|
||||||
/* Assassin's Creed Syndicate: amdags issues */
|
/* Assassin's Creed Syndicate: amdags issues */
|
||||||
{ R"(\\ACS\.exe$)", {{
|
{ R"(\\ACS\.exe$)", {{
|
||||||
{ "dxgi.customVendorId", "10de" },
|
{ "dxgi.customVendorId", "10de" },
|
||||||
|
@ -26,10 +29,6 @@ namespace dxvk {
|
||||||
* when running on AMD hardware */
|
* when running on AMD hardware */
|
||||||
{ R"(\\EliteDangerous64\.exe$)", {{
|
{ R"(\\EliteDangerous64\.exe$)", {{
|
||||||
{ "dxgi.customVendorId", "10de" },
|
{ "dxgi.customVendorId", "10de" },
|
||||||
}} },
|
|
||||||
/* The Vanishing of Ethan Carter Redux */
|
|
||||||
{ R"(\\EthanCarter-Win64-Shipping\.exe$)", {{
|
|
||||||
{ "dxgi.customVendorId", "10de" },
|
|
||||||
}} },
|
}} },
|
||||||
/* EVE Online: Needs this to expose D3D12 *
|
/* EVE Online: Needs this to expose D3D12 *
|
||||||
* otherwise D3D12 option on launcher is *
|
* otherwise D3D12 option on launcher is *
|
||||||
|
@ -126,8 +125,6 @@ namespace dxvk {
|
||||||
}} },
|
}} },
|
||||||
/* NieR Replicant */
|
/* NieR Replicant */
|
||||||
{ R"(\\NieR Replicant ver\.1\.22474487139\.exe)", {{
|
{ R"(\\NieR Replicant ver\.1\.22474487139\.exe)", {{
|
||||||
{ "dxgi.syncInterval", "1" },
|
|
||||||
{ "dxgi.maxFrameRate", "60" },
|
|
||||||
{ "d3d11.cachedDynamicResources", "vi" },
|
{ "d3d11.cachedDynamicResources", "vi" },
|
||||||
}} },
|
}} },
|
||||||
/* SteamVR performance test */
|
/* SteamVR performance test */
|
||||||
|
@ -234,11 +231,6 @@ namespace dxvk {
|
||||||
{ R"(\\nioh2\.exe$)", {{
|
{ R"(\\nioh2\.exe$)", {{
|
||||||
{ "dxgi.deferSurfaceCreation", "True" },
|
{ "dxgi.deferSurfaceCreation", "True" },
|
||||||
}} },
|
}} },
|
||||||
/* DIRT 5 - uses amd_ags_x64.dll when it *
|
|
||||||
* detects an AMD GPU */
|
|
||||||
{ R"(\\DIRT5\.exe$)", {{
|
|
||||||
{ "dxgi.customVendorId", "10de" },
|
|
||||||
}} },
|
|
||||||
/* Crazy Machines 3 - crashes on long device *
|
/* Crazy Machines 3 - crashes on long device *
|
||||||
* descriptions */
|
* descriptions */
|
||||||
{ R"(\\cm3\.exe$)", {{
|
{ R"(\\cm3\.exe$)", {{
|
||||||
|
@ -340,11 +332,6 @@ namespace dxvk {
|
||||||
{ R"(\\SonicFrontiers\.exe$)", {{
|
{ R"(\\SonicFrontiers\.exe$)", {{
|
||||||
{ "dxgi.maxFrameLatency", "1" },
|
{ "dxgi.maxFrameLatency", "1" },
|
||||||
}} },
|
}} },
|
||||||
/* TRAHA Global *
|
|
||||||
* Shadow issues when it sees AMD/Nvidia */
|
|
||||||
{ R"(\\RapaNui-Win64-Shipping\.exe$)", {{
|
|
||||||
{ "dxgi.customVendorId", "8086" },
|
|
||||||
}} },
|
|
||||||
/* SpellForce 3 Reforced & expansions *
|
/* SpellForce 3 Reforced & expansions *
|
||||||
* Greatly improves CPU bound performance */
|
* Greatly improves CPU bound performance */
|
||||||
{ R"(\\SF3ClientFinal\.exe$)", {{
|
{ R"(\\SF3ClientFinal\.exe$)", {{
|
||||||
|
@ -420,20 +407,18 @@ namespace dxvk {
|
||||||
{ R"(\\RidersRepublic(_BE)?\.exe$)", {{
|
{ R"(\\RidersRepublic(_BE)?\.exe$)", {{
|
||||||
{ "dxgi.hideAmdGpu", "True" },
|
{ "dxgi.hideAmdGpu", "True" },
|
||||||
}} },
|
}} },
|
||||||
/* HoloCure - Save the Fans!
|
|
||||||
Same as Cyberpunk 2077 */
|
|
||||||
{ R"(\\HoloCure\.exe$)", {{
|
|
||||||
{ "dxgi.useMonitorFallback", "True" },
|
|
||||||
}} },
|
|
||||||
/* Kenshi *
|
/* Kenshi *
|
||||||
* Helps CPU bound performance */
|
* Helps CPU bound performance */
|
||||||
{ R"(\\kenshi_x64\.exe$)", {{
|
{ R"(\\kenshi_x64\.exe$)", {{
|
||||||
{ "d3d11.cachedDynamicResources", "v" },
|
{ "d3d11.cachedDynamicResources", "v" },
|
||||||
}} },
|
}} },
|
||||||
/* Granblue Relink: Spams pixel shader UAVs *
|
/* Granblue Relink: Spams pixel shader UAVs *
|
||||||
* like crazy, much like God of War */
|
* and assumes that AMD GPUs do not expose *
|
||||||
|
* native command lists for AGS usage */
|
||||||
{ R"(\\granblue_fantasy_relink\.exe$)", {{
|
{ R"(\\granblue_fantasy_relink\.exe$)", {{
|
||||||
{ "d3d11.ignoreGraphicsBarriers", "True" },
|
{ "d3d11.ignoreGraphicsBarriers", "True" },
|
||||||
|
{ "d3d11.exposeDriverCommandLists", "False" },
|
||||||
|
{ "dxgi.hideNvidiaGpu", "False" },
|
||||||
}} },
|
}} },
|
||||||
|
|
||||||
/**********************************************/
|
/**********************************************/
|
||||||
|
@ -811,6 +796,7 @@ namespace dxvk {
|
||||||
* Black textures */
|
* Black textures */
|
||||||
{ R"(\\eldorado\.exe$)", {{
|
{ R"(\\eldorado\.exe$)", {{
|
||||||
{ "d3d9.floatEmulation", "Strict" },
|
{ "d3d9.floatEmulation", "Strict" },
|
||||||
|
{ "d3d9.allowDirectBufferMapping", "False" },
|
||||||
}} },
|
}} },
|
||||||
/* Injustice: Gods Among Us *
|
/* Injustice: Gods Among Us *
|
||||||
* Locks a buffer that's still in use */
|
* Locks a buffer that's still in use */
|
||||||
|
@ -867,10 +853,10 @@ namespace dxvk {
|
||||||
{ R"(\\UK Truck Simulator\\bin\\win_x86\\game\.exe$)", {{
|
{ R"(\\UK Truck Simulator\\bin\\win_x86\\game\.exe$)", {{
|
||||||
{ "d3d9.floatEmulation", "Strict" },
|
{ "d3d9.floatEmulation", "Strict" },
|
||||||
}} },
|
}} },
|
||||||
/* Supreme Ruler Ultimate *
|
/* d3d9 Supreme Ruler games *
|
||||||
* Leaks a StateBlock leading *
|
* Leaks a StateBlock leading *
|
||||||
* to Reset calls failing */
|
* to Reset calls failing */
|
||||||
{ R"(\\SupremeRulerUltimate\.exe$)", {{
|
{ R"(\\SupremeRuler(Ultimate|GreatWar|1936|CW)\.exe$)", {{
|
||||||
{ "d3d9.countLosableResources", "False" },
|
{ "d3d9.countLosableResources", "False" },
|
||||||
}} },
|
}} },
|
||||||
/* Operation Flashpoint: Red River *
|
/* Operation Flashpoint: Red River *
|
||||||
|
@ -878,6 +864,16 @@ namespace dxvk {
|
||||||
{ R"(\\RedRiver\.exe$)", {{
|
{ R"(\\RedRiver\.exe$)", {{
|
||||||
{ "d3d9.floatEmulation", "Strict" },
|
{ "d3d9.floatEmulation", "Strict" },
|
||||||
}} },
|
}} },
|
||||||
|
/* Dark Void - Crashes above 60fps in places */
|
||||||
|
{ R"(\\ShippingPC-SkyGame\.exe$)", {{
|
||||||
|
{ "d3d9.maxFrameRate", "60" },
|
||||||
|
}} },
|
||||||
|
/* 9th Dawn II *
|
||||||
|
* OpenGL game that also spins up d3d9 *
|
||||||
|
* Black screens without config */
|
||||||
|
{ R"(\\ninthdawnii\.exe$)", {{
|
||||||
|
{ "d3d9.deferSurfaceCreation", "True" },
|
||||||
|
}} },
|
||||||
|
|
||||||
|
|
||||||
/**********************************************/
|
/**********************************************/
|
||||||
|
@ -902,17 +898,6 @@ namespace dxvk {
|
||||||
{ R"(\\RiftApart\.exe$)", {{
|
{ R"(\\RiftApart\.exe$)", {{
|
||||||
{ "dxgi.hideNvidiaGpu", "False" },
|
{ "dxgi.hideNvidiaGpu", "False" },
|
||||||
}} },
|
}} },
|
||||||
/* CP2077 enumerates display outputs each frame.
|
|
||||||
* Avoid using QueryDisplayConfig to avoid
|
|
||||||
* performance degradation until the
|
|
||||||
* optimization of that function is in Proton. */
|
|
||||||
{ R"(\\Cyberpunk2077\.exe$)", {{
|
|
||||||
{ "dxgi.useMonitorFallback", "True" },
|
|
||||||
}} },
|
|
||||||
/* Hitman 3 - Ray Tracing */
|
|
||||||
{ R"(\\HITMAN3\.exe$)", {{
|
|
||||||
{ "dxgi.hideNvidiaGpu", "False" },
|
|
||||||
}} },
|
|
||||||
/* Metro Exodus Enhanced Edition picks GPU adapters
|
/* Metro Exodus Enhanced Edition picks GPU adapters
|
||||||
* by available VRAM, which causes issues on some
|
* by available VRAM, which causes issues on some
|
||||||
* systems with integrated graphics. */
|
* systems with integrated graphics. */
|
||||||
|
@ -927,6 +912,28 @@ namespace dxvk {
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
|
||||||
|
const static ProfileList g_deckProfiles = {{
|
||||||
|
/* Fallout 4: Defaults to 45 FPS on OLED, but also breaks above 60 FPS */
|
||||||
|
{ R"(\\Fallout4\.exe$)", {{
|
||||||
|
{ "dxgi.syncInterval", "1" },
|
||||||
|
{ "dxgi.maxFrameRate", "60" },
|
||||||
|
}} },
|
||||||
|
}};
|
||||||
|
|
||||||
|
|
||||||
|
const Config* findProfile(const ProfileList& profiles, const std::string& appName) {
|
||||||
|
auto appConfig = std::find_if(profiles.begin(), profiles.end(),
|
||||||
|
[&appName] (const std::pair<const char*, Config>& pair) {
|
||||||
|
std::regex expr(pair.first, std::regex::extended | std::regex::icase);
|
||||||
|
return std::regex_search(appName, expr);
|
||||||
|
});
|
||||||
|
|
||||||
|
return appConfig != profiles.end()
|
||||||
|
? &appConfig->second
|
||||||
|
: nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool isWhitespace(char ch) {
|
static bool isWhitespace(char ch) {
|
||||||
return ch == ' ' || ch == '\x9' || ch == '\r';
|
return ch == ' ' || ch == '\x9' || ch == '\r';
|
||||||
}
|
}
|
||||||
|
@ -1176,20 +1183,22 @@ namespace dxvk {
|
||||||
|
|
||||||
|
|
||||||
Config Config::getAppConfig(const std::string& appName) {
|
Config Config::getAppConfig(const std::string& appName) {
|
||||||
auto appConfig = std::find_if(g_appDefaults.begin(), g_appDefaults.end(),
|
const Config* config = nullptr;
|
||||||
[&appName] (const std::pair<const char*, Config>& pair) {
|
|
||||||
std::regex expr(pair.first, std::regex::extended | std::regex::icase);
|
|
||||||
return std::regex_search(appName, expr);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (appConfig != g_appDefaults.end()) {
|
if (env::getEnvVar("SteamDeck") == "1")
|
||||||
|
config = findProfile(g_deckProfiles, appName);
|
||||||
|
|
||||||
|
if (!config)
|
||||||
|
config = findProfile(g_profiles, appName);
|
||||||
|
|
||||||
|
if (config) {
|
||||||
// Inform the user that we loaded a default config
|
// Inform the user that we loaded a default config
|
||||||
Logger::info(str::format("Found built-in config:"));
|
Logger::info(str::format("Found built-in config:"));
|
||||||
|
|
||||||
for (auto& pair : appConfig->second.m_options)
|
for (auto& pair : config->m_options)
|
||||||
Logger::info(str::format(" ", pair.first, " = ", pair.second));
|
Logger::info(str::format(" ", pair.first, " = ", pair.second));
|
||||||
|
|
||||||
return appConfig->second;
|
return *config;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Config();
|
return Config();
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#if defined(__x86_64__) || defined(_M_X64) || defined(__i386__) || defined(_M_IX86) || defined(__e2k__)
|
#if (defined(__x86_64__) && !defined(__arm64ec__)) || (defined(_M_X64) && !defined(_M_ARM64EC)) \
|
||||||
|
|| defined(__i386__) || defined(_M_IX86) || defined(__e2k__)
|
||||||
#define DXVK_ARCH_X86
|
#define DXVK_ARCH_X86
|
||||||
#if defined(__x86_64__) || defined(_M_X64) || defined(__e2k__)
|
#if defined(__x86_64__) || defined(_M_X64) || defined(__e2k__)
|
||||||
#define DXVK_ARCH_X86_64
|
#define DXVK_ARCH_X86_64
|
||||||
#endif
|
#endif
|
||||||
#elif defined(__aarch64__) || defined(_M_ARM64)
|
#elif defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC)
|
||||||
#define DXVK_ARCH_ARM64
|
#define DXVK_ARCH_ARM64
|
||||||
#else
|
#else
|
||||||
#error "Unknown CPU Architecture"
|
#error "Unknown CPU Architecture"
|
||||||
|
|
Loading…
Reference in New Issue