Compare commits

...

556 Commits
v2.0 ... master

Author SHA1 Message Date
Blisto91 c1f665f92b [util] Disable supportDFFormats for Prototype
Incorrect shadows on AMD & Intel
2024-05-18 19:31:07 +02:00
WinterSnowfall 20185a5309 [d3d9] Do not enable support for DF formats on Nvidia 2024-05-18 16:16:34 +00:00
Blisto91 0c2efda804 [meta] Add DXVK Native section to the readme 2024-05-16 10:57:35 +00:00
Blisto91 c7d61b2fc0 [native] Change DXVK_WSIDRIVER to DXVK_WSI_DRIVER 2024-05-16 10:57:35 +00:00
Ethan Lee 6259e86392 [meson] Use dependency() instead of find_library() for SDL2/GLFW detection.
Since we're not linking to the libraries anymore, it doesn't make much sense to
use find_library, and in fact we need to use dependency() in order to get the
right CFLAGS for includes, defines, etc, so use that instead.

As a result, we can remove the 'SDL2/' folders from the includes, making the SDL
includes more correct.
2024-05-13 13:18:03 +00:00
Ethan Lee d5d236a1e2 [wsi] Refactor platform system to support multiple WSI implementations 2024-05-13 13:18:03 +00:00
Ethan Lee 10b83d184b [native] Dynamically load SDL2/GLFW at runtime.
Removing these link-time dependencies is important for making a single binary that is compatible with either backend, regardless of whether or not each one is currently available to the program.
2024-05-13 13:18:03 +00:00
Ethan Lee 0f7c1f753a [wsi] Refactor the WSI backends to be implementations of a WsiDriver interface.
Rather than directly calling functions, the API now calls shared functions that call into a WsiDriver instance, which is allocated and implemented by the backend. Functionally this should be the same, it just has the extra allocation for the function table.

This prepares the WSI library for supporting multiple implementations in a single binary.
2024-05-13 13:18:03 +00:00
Ethan Lee 529129c332 [dxvk] Move getInstanceExtensions platform logic to wsi.
This ensures that all of the WSI backend logic is in one place rather than two.
2024-05-13 13:18:03 +00:00
Ethan Lee 4055a92856 [wsi] Add init/quit functions, integrate them into DxvkInstance.
This is preparation for loading/unloading WSI backends at runtime, which will be in an upcoming commit.
2024-05-13 13:18:03 +00:00
Blisto91 7bad17c1d1 [util] Set deviceLossOnFocusLoss for The Sims 3
Prevents the game black screening on alt-tab
2024-05-11 14:38:43 +02:00
Blisto91 6b76d70d9d [util] Enable d3d11.longMad for Guild Wars 2
Fixes invisibility effect flicker when invariantPosition is enabled
2024-05-09 00:47:13 +02:00
Philip Rebohle 611dc60018 [d3d9] Do not support cube textures with depth formats 2024-05-08 17:05:48 +00:00
WinterSnowfall b2789ab894 [d3d9] Validate DS format support during CheckDepthStencilMatch 2024-05-06 20:26:09 +00:00
Philip Rebohle ab715a8876 [d3d11] Implement better filtering when blitting video content
Unlike linear filtering this guarantees that we never read outside the source
region, and this also lets us perform color space conversion prior to filtering.
2024-05-03 16:23:17 +02:00
talkingerbil 1fb35b6d19
[dxgi] Initialize UMD version quad to a max signed int64 (#3985) 2024-05-03 16:22:58 +02:00
Rémi Bernon 4333ee872d [d3d11] Use nearest filter for ID3D11VideoContext scaling 2024-05-02 18:17:54 +02:00
Rémi Bernon b99d42c688 [d3d11] Implement VideoProcessorSetStreamSourceRect scaling 2024-05-02 18:17:54 +02:00
Blisto91 dacb8b434b [util] Add configs for Delta Force Xtreme 1 & 2
Prevents the games from black screening on Alt-Tab and helps big performance dips.
2024-05-01 14:08:03 +02:00
Philip Rebohle ea4cb84d8a [dxvk] Remove workaround for non-dynamic depth clip
Kind of pointless and everyone supports the required EDS3 subset anyway.
2024-04-29 17:43:40 +02:00
Philip Rebohle 65373792d2 [dxvk] Forward link flags when using shader identifiers
Fixes a long-standing bug that now causes validation errors.
2024-04-29 17:43:40 +02:00
Lierrmm 29253da356 feat: add H2M-Mod to config 2024-04-29 16:19:42 +02:00
Robin Kertels 79398b468d [util] Enable longMad for Red Faction Guerrila Remastered 2024-04-29 13:17:21 +02:00
Robin Kertels e7d14e97de [dxbc] Implement option to split up fma 2024-04-29 13:17:21 +02:00
Philip Rebohle c613078ba8 [dxvk] Bump internal version number
Potentially useful for drivers and tools to deal with the new pipeline
layout changes.
2024-04-26 19:54:52 +02:00
Philip Rebohle 2970645f33 [dxvk] Fix push constant compatibility for pipeline libraries
When linking pipelines, all pipeline libraries are required to declare
the exact same set of push constants, even for stages not part of the
respective libraries.

This invalidates all fossilize databases.
2024-04-26 19:54:52 +02:00
Philip Rebohle 462165da19 [util] Add Deck profile for Fallout 4
Should fix the FPS problem on Deck OLED.
2024-04-26 14:34:08 +02:00
Philip Rebohle 3f27a0ee58 [util] Add a way to define app profiles exclusive to Steam Deck 2024-04-26 14:34:08 +02:00
Katharine Chui aac3396671 [dxgi] unchain DxgiFactory::CreateSwapChain and CreateSwapChainForHwnd
similar to https://github.com/doitsujin/dxvk/pull/3966, avoid
chaining so that dxgi tools attempting to wrap swapchains don't
end up double wrapping

ref: https://github.com/SpecialKO/SpecialK/issues/168
2024-04-25 12:07:50 +02:00
Katharine Chui 92a43ebf65 [dxgi] unchain DxgiSwapChain::Present1 and Present
dxgi hooking tools might hook both, eg. https://github.com/SpecialKO/SpecialK/issues/167
2024-04-22 14:04:43 +02:00
Blisto91 8ba5256dc7 [util] Set deferSurfaceCreation for 9th Dawn II
OpenGL game that also spins up d3d9. Will black screen without deferSurfaceCreation when using dxvk
2024-04-22 04:48:56 +02:00
Philip Rebohle 2b70ba8f77 [dxbc] Do not emit OpImageQueryLevels for multisampled images 2024-04-19 13:55:31 +02:00
Philip Rebohle 9c66c4bf1d [build] Target SPIR-V 1.6 for built-in GLSL shaders
Silences a Mesa warning when the HUD is enabled.
2024-04-19 13:36:32 +02:00
Philip Rebohle 00872e9e4f [dxvk] Fix render target clears with format reinterpretation
With LOAD_OP_CLEAR, we cannot rely on the clear actually being performed
with the view format in mind. Use a vkCmdClearAttachment path instead.
2024-04-19 13:08:36 +02:00
Philip Rebohle 35157357dd [dxvk] Fix stencil discard being broken 2024-04-19 01:43:23 +02:00
Philip Rebohle 617ebf4e05 [dxbc] Take used components into account for PS inputs 2024-04-19 01:01:52 +02:00
Philip Rebohle c2489d5a45 [dxbc] Fix array register anaylsis with multiple dst operands 2024-04-19 01:01:52 +02:00
Philip Rebohle 6ef98c613f [dxvk] Re-enable maintenance4 feature
Sileces some validation errors.
2024-04-19 01:01:52 +02:00
Philip Rebohle 7441137a33 [dxbc] Ignore system value components when declaring inputs 2024-04-19 01:01:52 +02:00
WinterSnowfall 571948cfc0 [d3d9] Remove support for VERTEXSTATS queries 2024-04-13 19:11:00 +01:00
Martino Fontana 133f0794bc [util] Remove framerate limiter for Nier Replicant
Without mods, Nier Replicant runs faster when going above 60 FPS.
The game had an official patch that implemented a framerate limiter to prevent this. This limiter is terrible, because it's not a stable 60 FPS, but a weird 57-58 FPS. There's no way to disable this in-game, it has to be done by editing a config file or through a mod.

So, why remove the default frame limiter from DXVK?
- In the default case (a user plays the game as it is), it does nothing, since 57-58 is lower than 60.
- If a user is going out of their way to edit the config file, why would they assume that DXVK already provides a frame limiter? They are going to follow [a guide](https://www.pcgamingwiki.com/wiki/NieR_Replicant#Framerate_limited_to_57.7E58_FPS) that says to set up a frame limiter, it doesn't say "set up a frame limiter, unless you are using DXVK, in that case it's already there".
- They are using [Special K in order to use a mod to play at high refresh rates at normal speed](https://wiki.special-k.info/SpecialK/Custom/Replicant). In this case, DXVK's default limiter is harmful, since it is not documented that it's there by default.

Since this default limiter is useless in the first two cases and harmful in the third, I think it should be removed.
The alternative would be to document this (e.g. in PCGamingWiki), but the instructions wouldn't look pretty... "After following the instructions to use Special K in order to play at higher framerates at normal speed, if are using DXVK/Proton, also do these things to disable its default 60 FPS cap: [...]"

Especially because that the game isn't broken in the default case, I don't think DXVK should tamper with these things in a way that requires documentation to revert.

Tested Special K's mod to play at higher refresh rates on Linux.
2024-04-08 21:48:47 +02:00
Philip Rebohle 44695f9311 [dxvk] Adjust desciptor pool reset heuristic
Drastically limits the amount of descriptor memory we allocate in situations
where an application renders without presenting anything to a swap chain.

The new limit is a bit tight for some real-world use cases (e.g. Ashes of the Singularity),
but at worst we will start calling vkAllocateDescriptorSets once per set and draw.
2024-04-08 15:40:25 +02:00
Casey Bowman 49e9ea5f5a [dxgi] Force vendor ID change when XeSS is detected on an Intel GPU
Games using libxess.dll or wrapper modules will crash.
To work around this, we hide the Intel GPU's vendor ID to avoid using the
XeSS module.
2024-04-03 20:32:04 +02:00
Blisto91 198bd3a4b8 [d3d11] Remove missed Shared Keyedmutex warning
D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX is implemented.
2024-04-03 20:31:52 +02:00
Philip Rebohle f06c646315 [dxbc] Remove broken atomic counter subgroup optimization
This is not a legal optimization inside non-uniform control flow due
to Vulkan's extremely permissive convergence rules, and apparently
breaks on Nvidia as a result.

Mesa drivers already do the same thing internally anyway.
2024-04-03 14:55:43 +02:00
Philip Rebohle 855b2746b6 [util] Remove TRAHA Global config
This game apparently no longer exists.
2024-03-26 13:42:55 +01:00
Blisto91 28c7c09bf5 [dxgi] Remove useMonitorFallback option
QueryDisplayConfig optimization is now in Proton 9 Wine
2024-03-21 17:23:38 +01:00
Philip Rebohle 2742486540 [dxvk] Don't query color space support for null surfaces
Fixes a crash in games with the dxgi.deferSurfaceCreation workaround set.
Note that this potentially breaks HDR.
2024-03-21 15:32:48 +01:00
Philip Rebohle 037d0fa1ad [meta] Release 2.3.1 2024-03-20 13:48:30 +01:00
Philip Rebohle cbf51a7a25 [d3d11] Enable copy usage for typeless images as necessary 2024-03-20 13:30:31 +01:00
Philip Rebohle 70e34dc31c [dxvk] Support arbitrary source formats for color<->depth copies
Fixes rendering bugs in War Thunder.
2024-03-20 13:29:59 +01:00
Philip Rebohle c5aeb0f87a [dxvk] Get rid of separate depth shaders for shader-based copies
We can export both depth and color in a single shader instead.
2024-03-19 19:32:12 +01:00
Philip Rebohle a163082770 [dxvk] Align index buffer size to index size
Fixes validation errors in FFXIV.
2024-03-19 19:32:12 +01:00
Blisto91 2e1a19c7fd [util] Cap Dark Void to 60fps
Game crashes in certain places like specific cutscenes unless capped at 60fps.
2024-03-18 12:56:27 +01:00
Joshua Ashton 0beb18ef73 [d3d9] Wait for submission when calling ReturnUnderlyingResource 2024-03-16 19:11:11 +00:00
Joshua Ashton ef4428ab8c [d3d9] Improve ReturnUnderlyingResource stub for 9on12 2024-03-16 18:59:03 +00:00
Philip Rebohle 1085ba713e [dxgi] Implicitly set HDR color space for RGBA16_FLOAT swap chains 2024-03-16 18:56:41 +00:00
Philip Rebohle e857b09432 [dxgi] Change default behaviour of hideNvkGpu option 2024-03-15 22:48:57 +01:00
Kaitlyn 538f1d13d4 Fix UAV as well 2024-03-15 15:22:13 +01:00
Kaitlyn 783c9d4591 Fix MiscFlags check in GetDescFromResource 2024-03-15 15:22:13 +01:00
Kaitlyn 1a685b1c67 Implement D3D11DXGIDevice::EnqueueSetEvent 2024-03-15 13:47:28 +01:00
Robin Kertels 8b8be7c2bf [d3d9] Fix stream count in Reset 2024-03-10 17:12:22 +01:00
Billy Laws 0776d764a4
build: Support building for ARM64EC
When targeting ARM64EC, both __x86_64__ and _M_X86_64 are defined but
not all x86 intrinsics are present, treat EC as regular ARM64 so the
native intrinsics are used instead.
2024-03-09 05:43:46 +00:00
Robin Kertels 15ddadc4de [d3d9] Fix number of streams 2024-03-08 18:42:15 +01:00
Philip Rebohle 69a52b3da0 [dxbc] Do not emit depth compare for unsupported image types
Fixes invalid SPIR-V.
2024-03-07 16:11:23 +01:00
Philip Rebohle 707ad6f328 [spirv] Add OpConstantNull 2024-03-07 16:11:23 +01:00
Philip Rebohle 3a6992ea97 [dxbc] Enable depth compare types for 1D images
Used by Renderdoc internal shaders.
2024-03-07 16:11:23 +01:00
Robin Kertels 72c86b8229 [d3d9] Only unbind in EndScene if the game cleared the binding 2024-03-06 22:58:48 +01:00
Robin Kertels 85215b10d6 [d3d9] Respect vertex buffer offset when dynamically uploading geometry 2024-03-06 18:13:26 +01:00
Philip Rebohle fd3fbf6607 [dxvk] Remove old memory budget code
Obsolete since we removed the Nvidia HVV workaround for old drivers.

Closes #3877.
2024-03-06 15:48:34 +01:00
Minelelol 0a699fddb6 Update config.cpp
Insane Performance increase
2024-03-06 15:25:16 +01:00
Blisto91 afec5cce88 [util] Remove some unneeded built in configs
Dirt 5 does not crash without working ags anymore and Ethan Carter Redux also starts fine without a spoof.
This allows the built in AMD ags in Proton 9 to be used for these games.

The Hitman 3 config is redundant as it doesn't allow RT to be enabled without Nvapi anyway.
2024-03-06 15:24:54 +01:00
Ethan Lee 4b0e3111d1 meson: Check for bundled Vulkan/SPIR-V headers before adding them to the include list.
This feature requires Meson 0.58 or newer.
2024-03-06 15:21:15 +01:00
Philip Rebohle 0414bbe2d5 [dxgi] Add separate option to override vendor IDs for NVK 2024-03-06 14:46:21 +01:00
Robin Kertels 20490b678f [d3d9] Fix missing else brackets in ResetSwapchain 2024-03-06 12:08:45 +01:00
Blisto91 428c98bc63 [util] Disable countLosableResources for all d3d9 Supreme Ruler games
All the d3d9 Supreme ruler games have this issue.
2024-03-05 15:28:11 +01:00
Robin Kertels a0e39e94fa [d3d9] Use most recently used swapchain for GetFrontBufferData 2024-03-05 13:54:15 +00:00
Robin Kertels eaa732d0b3 [d3d9] Place GetFrontBufferData screenshot at window position 2024-03-05 13:54:15 +00:00
Robin Kertels 49b18f03fe [d3d9] Unbind buffers in EndScene & Reset 2024-03-05 13:52:51 +00:00
Philip Rebohle c9cea93b7b [dxbc] Use raw access chains for buffer loads and stores
Maps more or less perfectly to D3D raw and structured buffers.
2024-03-05 14:41:18 +01:00
Philip Rebohle 69d74a46a0 [dxbc] Remove emitRawBuffer{Load,Store}
And factor these into the callers. We need to preserve the raw
index and offset parameters to use raw access chains.
2024-03-05 14:41:18 +01:00
Philip Rebohle 94098aa97d [dxbc] Enable SPV_NV_raw_access_chains 2024-03-05 14:41:18 +01:00
Philip Rebohle c677ba9b3e [dxvk] Enable VK_NV_raw_access_chains if available 2024-03-05 14:41:18 +01:00
Philip Rebohle 77c7396ee1 [spirv] Add support for OpRawAccessChainNV 2024-03-05 14:41:18 +01:00
Philip Rebohle f07e5f9eaa [include] Update SPIR-V headers 2024-03-05 14:41:18 +01:00
Philip Rebohle d5c3011f54 [include] Update Vulkan headers 2024-03-05 14:41:18 +01:00
Blisto91 6b3b934471 [util] Clarify maxDeviceMemory and maxSharedMemory
This config often leads to confusion as people expect applications to honor the limit.
2024-03-02 20:41:19 +01:00
Philip Rebohle 9004c132ed [dxbc] Declare dynamically indexed UBOs with the maximum possible size
Fixes #3861.
2024-02-23 13:39:29 +01:00
Philip Rebohle 24d4c9c938 [util] Disable command lists for Granblue Fantasy Relink
The uses deferred contexts for rendering if driver command lists are enabled,
but when AMDAGS is loaded, it will also unconditionally use MultiDrawIndirect
functions. Since the AGS version in use does not support deferred contexts,
this breaks rendering, so we will have to force it into the immediate context
path.

Testing also shows slightly higher performance (~3-5%) with this path in
CPU-bound scenarios.
2024-02-22 16:07:24 +01:00
Philip Rebohle 5ded7d67f0 [d3d11] Implement UpdateSubresource bug if native command lists are disabled 2024-02-22 16:07:24 +01:00
Philip Rebohle 234f3ea071 [d3d11] Add option to hide native command list support 2024-02-22 16:07:24 +01:00
Robin Kertels c5a37d443a [d3d9] Handle null IBO when uploading data for draw 2024-02-20 13:04:01 -08:00
Robin Kertels f254afb4fb [util] Enable strict float emulation for Red River 2024-02-20 12:58:03 -08:00
Robin Kertels 39c19e9299 [d3d9] End scene on reset 2024-02-20 12:58:03 -08:00
Robin Kertels 738fd4f895 [d3d9] Don't actually unbind buffers 2024-02-20 12:58:03 -08:00
Philip Rebohle 9491b56beb util: Enable d3d11.ignoreGraphicsBarriers for Granblue Relink
Improves GPU-bound performance due to the game using PS UAVs.
2024-02-15 20:33:55 +01:00
Robin Kertels ab3593185f [d3d9] Fail GetRTData if src and dst have mismatching sizes
MySims tries to do this and needs this to fail,
otherwise mouse picking is off.
2024-02-06 11:02:43 +01:00
Robin Kertels e9a0fec5b3 [dxso] Clamp Exp when fast float emulation is enabled 2024-02-06 11:02:20 +01:00
Echo J fae78407a2 d3d9: Remove an unused variable
This fixes a gcc warning (originally reported by Saancreed)
2024-02-06 10:19:28 +01:00
Robin Kertels 5312ef1cf9 [d3d9] Upload DYNAMIC+SYSMEM vertex and index data for each draw 2024-02-05 13:13:18 +00:00
Robin Kertels 62d64bd63a [d3d9] Don't upload buffers before Up draws 2024-02-05 13:13:18 +00:00
Robin Kertels f83ba898af [dxvk] Use signed int for vertexOffset
BaseVertexIndex is signed in Vulkan, D3D11 & D3D9.
2024-02-05 13:13:18 +00:00
Ethan Lee 30f2b2df31 package-native.sh should force libdisplay-info subproject
This ensures that the script produces a build similar to the default steamrt build, even if libdisplay-info is available on the build system root.
2024-02-05 13:08:30 +01:00
Philip Rebohle 05cb963e22 [util] Set sync interval override for P3R 2024-02-02 17:30:13 +01:00
Philip Rebohle eb339bc7e4 [dxgi,d3d11] Move syncInterval override to DXGI swap chain
This way it also applies to D3D12 games.
2024-02-02 17:30:13 +01:00
Ethan Lee c423819e90 [meson] Only use the libdisplay-info subproject as a fallback 2024-01-30 20:48:40 +01:00
Tatsuyuki Ishi e2a46a347d [meta] Declare bool conversion operators as explicit
Non-explicit conversion operators in general can participate in very
surprising conversion chains. Explicit bool operator is a good place to
start with, because even with explicit they do get automatic contextual
conversion in a lot of places, e.g., if conditions.
2024-01-27 11:44:51 +01:00
Tatsuyuki Ishi afc6aa70fb [d3d11] Explicitly convert DxvkExt to bool in D3D11DeviceFeatures
When assigning to a BOOL (which is an uint in disguise) and using explicit
bool conversion operators (introduced in a latter commit) an explicit cast
is required.
2024-01-27 11:44:51 +01:00
Tatsuyuki Ishi 799aeff560 [dxvk] Fix incorrect comparison in DxvkSparsePageTable::updateMapping
m_mappings[page] was getting implicitly converted to bool.
2024-01-27 11:44:51 +01:00
Robin Kertels 2ca8fdf890 [util] Disable counting losable resources for Supreme Ruler Ultimate
The game is broken and leaks a state block.
2024-01-26 18:11:25 +00:00
Robin Kertels 0841f5faf4 [d3d9] Implement config option to disable rejecting reset 2024-01-26 18:11:25 +00:00
Ethan Lee 2334bbccb0 [native] Add a DECLARE_INTERFACE define for !CONST_VTABLE.
This helps avoid some compiler warnings on GCC in particular.
2024-01-26 17:48:44 +00:00
Robin Kertels 7d9864c077 [d3d9] Only enable ATOC when rendering to MS RT 2024-01-26 17:48:21 +00:00
Dean Beeler d4c5fc74e7
d3d11: Fix crash when srv is submitted to ClearUnorderedAccessViewUint
* The Settlers submits (possibly incorrectly) an SRV to ClearUnorderedAccessViewUint. The static_cast in the function does not translate correctly and crashes.

Native D3D11 behavior is to ignore the bad parameter entirely. It does not clear the SRV nor does it fault or even error with the DEBUG validator.
2024-01-23 16:01:12 +01:00
Tatsuyuki Ishi 6199776869 [build] Set filealign for MSVC builds
Useful if you want to run a MSVC build on Wine.
2024-01-23 15:45:42 +01:00
Tatsuyuki Ishi 6faf3c1acd [build] Don't pass unix compiler and link args to MSVC
clang-cl accepts both style of options but these will be generally meaningless:
- Static CRT is unnecessary.
- File alignment will be introduced in another commit.
- Wine has partial support for PDB backtrace so there is probably no need to
  insist on DWARF (which is unsupported by real MSVC anyway).
- MSVC doesn't have the weird stdcall ordinal naming convention that
  necessiates fixup and kill-at.
2024-01-23 15:45:42 +01:00
Tatsuyuki Ishi ab6bd8b17f [build] Recognize more MSVC-like compilers as MSVC
clang-cl has its own compiler id but supports MSVC argument conventions.
Use get_argument_syntax to recognize MSVC-like compilers generally.
2024-01-23 15:45:42 +01:00
Tatsuyuki Ishi 89267b62ad [build] Remove declspec UUID annotations
MIDL_INTERFACE already implies struct DECLSPEC_UUID.
2024-01-23 15:44:47 +01:00
Blisto91 34d8e65fd7 [util] cachedDynamicBuffers for Codename Panzers Phase One/Two
Helps CPU bound performance
2024-01-23 15:44:28 +01:00
Joshua Ashton 1568c263fb [d3d9] Only add unique modes to mode list 2024-01-19 16:28:22 +00:00
Joshua Ashton 0cd4165658 [d3d9] Add D3DDISPLAYMODEEX operator 2024-01-19 16:28:22 +00:00
Joshua Ashton 4b8e8bed6e [d3d9] Move operators out of dxvk namespace 2024-01-19 16:28:22 +00:00
r-a-sattarov ac78048c23 [util] Fix e2k build 2024-01-16 22:03:31 +01:00
Richard Yao 14560600a9 Micro-optimize locking in fences
When a fence has been missed, we can avoid locking *most* of the time
via the double-checked locking pattern. We still lock before a second
check in case the scheduler caused us to miss the fence. If the
scheduler did cause us to miss the fence, we can drop the lock prior to
executing the callback function, as a second micro-optimization.

Signed-off-by: Richard Yao <richard.yao@alumni.stonybrook.edu>
2024-01-15 12:42:19 +01:00
Blisto91 854e06d3f0 [util] Enable deviceLossOnFocusLoss for BF2 and BF2142
The ingame spawn and gear selection GUI can disappear from view unless this is set.
2024-01-14 22:25:43 +01:00
Blisto91 eb806952d8
[util] Set deviceLossOnFocusLoss for Assassin's Creed 2 (#3763)
Makes it not crash on alt tab using at least Proton. 
Windows will still have issues with alt tab.
2024-01-09 10:43:48 +01:00
Blisto91 a44dfabe26 [util] Set float emulation to Strict for UK Truck Simulator 1
Fixes black foliage
2024-01-09 10:42:52 +01:00
spiffeeroo 5e06cf9573 [util] Limit Sonic CD to 60 fps
Game engine physics/speed for Sonic CD is tied to frame rate so limit max frame rate to 60 fps. Otherwise, the game runs too quickly for high refresh rate monitors.
2024-01-02 19:05:44 +01:00
Blisto91 2cf590f636 [util] Enable cached vertex buffers for Kenshi
Improves the games performance when CPU bound.
2023-12-30 22:47:24 +01:00
Robin Kertels a7a63b37c3 [util] Fix incorrect config option name 2023-12-27 03:06:49 +01:00
Robin Kertels 9cde0b5798 [d3d9] Fix off-by-one when copying shader defined constants 2023-12-25 14:51:02 +00:00
Blisto91 adb33d3af1 [util] Hide Intel in Far Cry 3, 4 and Primal
Also unhides Nvidia in Primal as it has the same clear value rounding assumptions as Far Cry 3 and 4
2023-12-23 09:23:27 +01:00
Philip Rebohle 1b31aa5dbc [util] Enable hideIntegratedGraphics for Metro Exodus EE 2023-12-01 14:14:36 +01:00
Philip Rebohle 03c09ce15f [dxvk] Add option to skip integrated GPU adapters 2023-12-01 14:14:13 +01:00
Blisto91 91f7f43c35 [util] Don't spoof Nvidia on AMD GPUs in Hitman 3
Spoofing to Nvidia prevents ray tracing enablement on AMD and the game does not crash without ags anymore
2023-11-18 12:18:08 +01:00
Robin Kertels d998dee46e [d3d11] Lock context in KeyedMutex::ReleaseSync
Co-authored-by: Yuxuan Shui <yshuiv7@gmail.com>
2023-11-16 15:43:07 +01:00
Philip Rebohle ea3149801f [d3d9] Return empty buffer slice for out-of-bounds offsets
Fixes #3715.
2023-11-14 10:54:54 -08:00
xpander69 1cb58b0732 [Util] two more executables to workaround Warhammer Online
Test server executables need the same VendorID to work around the rendering issues.
2023-11-14 12:23:50 +01:00
Philip Rebohle 2ed1778df9 [d3d11] Handle potential integer overflow when validating draw offsets
Apparently some games use -1 as an argument offset, which is nonsensical
and leads to issues.
2023-11-02 17:49:38 +01:00
Philip Rebohle a427d22cde [dxvk] Add Vulkan instance flag for D3D9 apps 2023-10-31 16:05:58 +01:00
Joshua Ashton 22c2abb9b7 [dxgi] Treat R16G16B16A16_FLOAT as 32bpp for display
HDR in Control (a patch released by a developer post-launch, not
actually in the game sadly) tries to set a video mode with
DXGI_FORMAT_R16G16B16A16_FLOAT.

This seemingly works on Windows, and based on FindClosestMode etc
documentaton, this seems required to work for any format that scanout
it supported for.

It's really not like the bpp is meaningful on Windows with the
distinction of 8bit and 10bit not working in GDI modes at all.
Nor does it end up actually setting anything on Linux/Deck where
modesets are emulated.

So, treat DXGI_FORMAT_R16G16B16A16_FLOAT as 32bpp so the
FindClosestMatchingMode and EnterFullscreenMode calls succeed.
2023-10-29 10:09:34 +01:00
Blisto91 f45911a28f [util] Disable allowDirectBufferMapping for SkyDrift
Works around a alt tab OOM crash
2023-10-23 14:52:44 +02:00
Blisto91 e00db24557 [util] Enable useMonitorFallback for Holocure
Temporary performance drop workaround until QueryDisplayConfig optimization is in Proton Wine.
2023-10-10 19:32:23 +02:00
Paul Gofman 552d2f0a6d [dxgi] Add useMonitorFallback option
And enable it for CP2077.
It is supposed to be dropped once QueryDisplayConfig optimization
is in Proton Wine.
2023-10-10 12:01:51 +02:00
WinterSnowfall 4d974685c9 [d3d9] Mark presenter for recreation on device reset with deferSurfaceCreation 2023-10-06 14:05:39 +02:00
Blisto91 f0ff0007dc [util] Enable cachedDynamicBuffers for Battlestations Midway
Helps performance dips that can happen in some areas
2023-10-06 14:05:04 +02:00
Robin Kertels 494f7fd38d [d3d9] Only set initial NeedsUpload for D3DPOOL_MANAGED textures 2023-09-19 13:25:12 -07:00
WinterSnowfall 0632da1935 [d3d9] Add a device compatibility mode for d3d8 2023-09-19 09:19:55 -07:00
Philip Rebohle 83dc4678df [util] Set maximum frame latency to 1 for Age of Empires 2 (2013)
Game seems to be doing something horrible on its own, literally impossible
to make it run smoothly. This at least seems to limit excursions to ±10ms
and fix the camera flinging back and forth when running the game through
Gamescope.
2023-09-14 16:50:30 +02:00
Paul Gofman f93cfbc26a [d3d11] Pass device directly to D3D11DXGIKeyedMutex 2023-09-13 14:29:25 -07:00
Philip Rebohle c113b791a1 [util] Enable 60 FPS lock for Aviary Attorney
This game (or nw.js) comes with a hard-coded frame rate limit that
behaves more like a random number generator which happens to average
out at around 16ms on a good day.

Fix this complete mess by enabling ours on top of that.
2023-09-08 03:04:02 +02:00
Ellie Hermaszewska 41191af3b1 A few more WinDef types in windows_base.h
These specific ones are used in MS's d3dx12 headers
2023-09-07 16:31:32 +02:00
Philip Rebohle 5828f0e2b9 Revert "[dxgi] Use VK_FORMAT_A8_UNORM if available"
This reverts commit 6a5ed02db3.

Native A8 breaks Crysis 2/3 Remastered for unknown reasons.
2023-09-07 03:58:39 +02:00
Philip Rebohle 80e075406b [meta] Release 2.3 2023-09-04 17:59:12 +02:00
Margen67 a53f0e8168 [util] Remove whitespace 2023-09-04 03:10:49 +02:00
Margen67 4705de5725 [util] Escape . 2023-09-04 03:10:49 +02:00
Robin Kertels 9e26964a96 [d3d9] Divide projected textures by w if ProjectedCount is 0 2023-09-03 18:08:47 -07:00
Blisto91 ce2f9f35ce [util] Hide AMD in Riders Republic
Works around crashing because of statically linked amd ags
2023-09-01 00:21:16 +02:00
Philip Rebohle a3fa9c26dc Revert "[d3d11] Implement DXGI_SWAP_EFFECT_SEQUENTIAL and FLIP_SEQUENTIAL"
This reverts commit 79f6239df3.

Some engines use SEQUENTIAL presentation despite not making use of it, and
sparse binding is much slower than expected on Nvidia drivers, which leads
to massive performance regressions across the board.
2023-09-01 00:15:09 +02:00
Joshua Ashton ff5507769a [wsi] Add proper values for SDR metadata fallbacks 2023-08-31 22:54:02 +01:00
WinterSnowfall 5c56fa0df4 [util] Enable deferSurfaceCreation for Drakensang 2023-08-30 18:02:02 +02:00
Tatsuyuki Ishi 7e10021eac Remove unused DxvkResource::waitIdle
Spinning-based wait idle is no longer used.
2023-08-29 11:05:42 +02:00
Joshua Ashton bbd1d84cd0 [dxgi] Set BitsPerColor to 10
For two reasons:
1) Some apps will only enable or attempt to enable HDR if BitsPerColor is >= 10.

2) Encouraging apps to create 10-bit swapchains for use in hardware dithering on Gamescope/Steam Deck and to have more precision thru scanout color transforms
2023-08-26 01:43:42 -07:00
Jens Peters 02db89ac30 [dxgi] Allow HDR on UE4/D3D11 when NVAPI is enabled 2023-08-24 21:21:29 -07:00
Philip Rebohle 92dc61f161 [d3d11] Fix up UAV clears for A8_UNORM 2023-08-24 13:12:07 +02:00
Philip Rebohle 6a5ed02db3 [dxgi] Use VK_FORMAT_A8_UNORM if available 2023-08-24 13:12:07 +02:00
Philip Rebohle 64828e2c6c [dxvk] Use vkCmdBindIndexBuffer2 if supported 2023-08-24 13:12:07 +02:00
Philip Rebohle a4f2a49a02 [dxvk] Add description for new image formats 2023-08-24 13:12:07 +02:00
Philip Rebohle aa41a7a351 [dxvk] Enable VK_KHR_maintenance5 if available. 2023-08-24 13:12:07 +02:00
Philip Rebohle fb71c08d8c [include] Update Vulkan headers. 2023-08-24 13:12:07 +02:00
Philip Rebohle 79f6239df3 [d3d11] Implement DXGI_SWAP_EFFECT_SEQUENTIAL and FLIP_SEQUENTIAL
Requires sparse since we have no other means to swap the backing image.
2023-08-24 13:00:35 +02:00
Philip Rebohle 53a68635b2 [dxvk] Optimize page table updates for images
Dramatically reduces overhead when binding full subresources.
2023-08-24 13:00:35 +02:00
Philip Rebohle 179c5ec998 [dxvk] Sort allocated memory pages for sparse allocator
This way, memory regions bound to consecutive pages are more likely
to end up in consecutive memory regions, which allows batching page
table updates more efficiently.
2023-08-24 13:00:35 +02:00
Philip Rebohle d6e0107e23 [dxvk] Ensure to submit sparse binding commands 2023-08-24 13:00:35 +02:00
Joshua Ashton 428ca9416d [d3d11] Implement synchronization on keyed mutexes
Co-authored-by: Paul Gofman <pgofman@codeweavers.com>
2023-08-23 16:50:52 +02:00
Joshua Ashton c26f40229a [vulkan] Query wine_vk{Acquire,Release}KeyedMutex
Non-standard functions, but exposed by winevulkan to support keyed mutexes.

Co-authored-by: Paul Gofman <pgofman@codeweavers.com>
2023-08-23 16:50:52 +02:00
Joshua Ashton 8226690298 [dxvk] Enable VK_KHR_win32_keyed_mutex
Co-authored-by: Paul Gofman <pgofman@codeweavers.com>
2023-08-23 16:50:52 +02:00
Joshua Ashton 138f727fbb [native] Add WAIT_* defines 2023-08-23 16:50:52 +02:00
Philip Rebohle c2cd129b89 [dxvk] Fix xfb counter buffer draw tracking 2023-08-23 13:44:35 +02:00
Philip Rebohle 915244c00c [d3d11] Fix various D3D10 interface queries 2023-08-23 01:06:04 +02:00
Blisto91 6fce094942 [util] Limit fps in Project: Snowblind
Player movement and animation can bug out at high fps like issues moving around objects and the players head detaching slightly when moving backwards.
Seems like it also helps some crash issues.
2023-08-21 01:43:24 +02:00
Robin Kertels 740ebec7ee [d3d9+dxso] Consider DMAP sampler in bit masks 2023-08-20 10:21:16 -07:00
Robin Kertels bcaaac4ad7 [d3d9] Handle sampling from DS_READONLY properly 2023-08-18 18:59:53 -07:00
Joshua Ashton 1130512db5 [dxgi] Add global HDR interop interface for NVAPI/AGS 2023-08-18 22:57:06 +01:00
Blisto91 143eb8c710 [meta] Document DXVK_CONFIG in readme 2023-08-16 12:57:42 +02:00
Philip Rebohle 4ae542e875 [util] Do not hide Nvidia GPUs from Ratchet & Clank
NVAPI is disabled now due to crashing issues in a wine-specific code
path within the game, but we still want it to detect the correct GPU
so that it doesn't complain about drivers and also allows users to
enable Raytracing.
2023-08-15 00:23:19 +02:00
Philip Rebohle 952c66fe2a [dxgi] Add options to hide Intel or AMD GPUs. 2023-08-14 20:12:02 +02:00
Philip Rebohle b6a7714e67 [dxgi,util] Rename dxgi.nvapiHack option to dxgi.hideNvidiaGpu 2023-08-14 19:21:16 +02:00
Etaash Mathamsetty 037669f715 [dxso] Don't assume 32 registers. 2023-08-13 20:34:38 +01:00
Robin Kertels 295a58afdf [d3d9] Check depth bounds test when deciding to bind DSV 2023-08-13 20:32:20 +01:00
Robin Kertels 0746a3b91a [d3d9] Don't resolve an image with 1 sample 2023-08-10 13:45:40 +02:00
Etaash Mathamsetty 429555a540 [dxgi] Fix behavior of GetWindowAssociation 2023-08-09 12:18:24 +02:00
Blisto91 dfcd7aedd8
[util] Limit Conflict Vietnam to 60fps (#3606)
Physics can bug out at higher fps making the character fly or get stuck when running up or down slopes.
2023-08-09 12:18:10 +02:00
gofman cbda22a040
[d3d11] Add stub IDXGIKeyedMutex interface. (#3601)
Partially based on a patch by Derek Lesho.

Co-authored-by: Paul Gofman <pgofman@codeweavers.com>
2023-08-07 17:23:32 +02:00
Georg Lehmann 549bd86f03 [d3d9] use strict float emulation for nvk
nvk supports nir_op_fmulz/ffmaz
2023-08-06 11:01:03 +01:00
WinterSnowfall b0b46fd075 [d3d9] Don't show/hide a software cursor 2023-08-02 01:51:19 +01:00
Joshua Ashton a62117cd13 build: Disable stdcall alias-ing and use kill-at
Disable stdcall aliasing and enable kill-at to ensure our exported
functions don't have the @8, @40, etc suffixes.

This still keeps `--enable-stdcall-fixup` as otherwise the linker can
get confused trying to find exports from the .def. This does not result
in aliases being added, just for them to be found to add to the export
table.

This also switches d3d11 to use the MinGW provided dxgi.lib for linking
and d3d10 to use the MinGW provided d3d11.lib for linking.
Unfortunately the .a's we output seem to still have the @blah that we
killed so we cannot use them for internal linkage since using kill-at.

Tested that what we get out of MinGW now is what we want with dllexp.

Supercedes: #3590

Exports

```
➜  build git:(master) ✗ winedump -j export src/dxgi/dxgi.dll
Contents of src/dxgi/dxgi.dll: 129505860 bytes

  Name:            DXGI.DLL
  Characteristics: 00000000
  TimeDateStamp:   64C97A2D Tue Aug  1 22:33:33 2023
  Version:         0.00
  Ordinal base:    9
  # of functions:  9
  # of Names:      5
Addresses of functions: 00423028
Addresses of name ordinals: 00423060
Addresses of names: 0042304C

  Entry Pt  Ordn  Name
  00007C17     9 CreateDXGIFactory
  00007BF3    10 CreateDXGIFactory1
  00007B62    11 CreateDXGIFactory2
  00007C3B    16 DXGIDeclareAdapterRemovalSupport
  00007CD8    17 DXGIGetDebugInterface1

Done dumping src/dxgi/dxgi.dll
```

```
➜  build git:(fix-stdcall-32-bit) winedump -j export src/d3d11/d3d11.dll
Contents of src/d3d11/d3d11.dll: 263021637 bytes

  Name:            D3D11.DLL
  Characteristics: 00000000
  TimeDateStamp:   64C97A2E Tue Aug  1 22:33:34 2023
  Version:         0.00
  Ordinal base:    18
  # of functions:  7
  # of Names:      4
Addresses of functions: 005E3028
Addresses of name ordinals: 005E3054
Addresses of names: 005E3044

  Entry Pt  Ordn  Name
  00020045    18 D3D11CoreCreateDevice
  000200AA    22 D3D11CreateDevice
  0002010E    23 D3D11CreateDeviceAndSwapChain
  0002025F    24 D3D11On12CreateDevice

Done dumping src/d3d11/d3d11.dll
```

Import of DXGI in D3D11

```
  offset 005e1014 dxgi.dll
  Hint/Name Table: 005E408C
  TimeDateStamp:   00000000 (Thu Jan  1 01:00:00 1970)
  ForwarderChain:  00000000
  First thunk RVA: 005E4300
   Thunk    Ordn  Name
  005e4300     4  CreateDXGIFactory1
```
2023-08-01 23:35:09 +01:00
pchome e598dcd77e
[util] Add DXVK_CONFIG to define additional options 2023-08-01 22:09:29 +02:00
Philip Rebohle 09857dcaa9 [dxvk] Dirty multisample state if sample mask export changes.
This affects Alpha-to-Coverage.
2023-08-01 18:07:47 +02:00
Philip Rebohle d66f8385c3 [dxvk] Disable alpha to coverage if sample mask is written
Matches D3D11 behaviour and fixes tree rendering in A Total War Saga: TROY.
2023-08-01 16:58:46 +02:00
Philip Rebohle 007e9f4c89 [dxvk] Check whether fragment shader exports sample mask 2023-08-01 16:27:23 +02:00
Philip Rebohle 9b019d26ac [dxgi] Forward IDXGIOutput::GetFrameStatistics to full-screen swap chain
Testing on Windows reveals that this function does not work with windowed
mode swap chains even in flip model.
2023-07-31 21:47:44 +02:00
Philip Rebohle 228615b639 [d3d11] Rework D3D11CoreCreateDevice
FiveM calls this directly and apparently our signature wasn't quite
what they expect it to be.
2023-07-31 13:13:48 +02:00
Ellie Hermaszewska dfbebba6b5
[native] Add CHAR and PCSTR to windows_base.h 2023-07-29 18:01:01 +01:00
Blisto91 4ed04268fd [build] Use new glslang name with fallback 2023-07-29 14:54:32 +02:00
Blisto91 4ed1474030 [meta] Move up Vulkan driver section in readme 2023-07-23 19:59:31 +02:00
Blisto91 13440a5d89 [dxvk] Clarify Vulkan 1.3 driver requirement in log 2023-07-23 19:59:31 +02:00
Blisto91 1daae75048 [util] Set Cached Dynamic Resources for d3d11 Vindictus
Co-authored-by: NorbertHarangozo <maszek.solutions@gmail.com>
2023-07-23 19:12:12 +02:00
Philip Rebohle b4d87eaac0 [dxbc] Fix constant texture offsets with 1D textures
Fixes #3572.
2023-07-22 17:37:37 +02:00
Philip Rebohle 1e11db98d0 [dxvk] Use separate mutex for completed chunk counter
Fixes a possible deadlock.
2023-07-21 21:45:50 +02:00
Philip Rebohle f689ddd838 [dxvk] Use dual queues for CS thread
Reduces lock contention since we can just swap out the entire queue
any time the worker thread runs out of stuff to do.
2023-07-21 21:21:34 +02:00
Philip Rebohle eed43c8524 [dxgi] Fix QPC time in frame statistics 2023-07-21 10:22:56 +02:00
Philip Rebohle d066fbbaed [d3d11] Set up line rasterization mode appropriately 2023-07-20 23:43:03 +02:00
Philip Rebohle a67c99943a [dxbc] Set output topology for GS and TES correctly 2023-07-20 23:43:03 +02:00
Philip Rebohle 5ece97f769 [dxvk] Add line rasterization mode to rasterization state 2023-07-20 23:43:03 +02:00
Philip Rebohle 228cd4c331 [dxvk] Enable VK_EXT_line_rasterization if supported. 2023-07-20 23:43:03 +02:00
Blisto91 98f3887680 [util] Cleanup a couple of example config options 2023-07-17 15:38:13 +02:00
Blisto91 3a9a70b5f0 [meta] Add Graphics Pipeline Library section to readme 2023-07-17 15:38:13 +02:00
Philip Rebohle 878da4984b [util] Disable single-use command lists for Ghost Recon Wildlands 2023-07-17 15:00:55 +02:00
Philip Rebohle c599f95e5d [d3d11] Do not cache GetCurrentProcess result
This is just a constant.
2023-07-16 21:16:16 +02:00
Paul Gofman 4893788d9b [d3d11] Fixup incorrect MiscFlags in D3D11Device::OpenSharedResourceGeneric()
So texture sharing works with vkd3d-proton before correcting flags
there.
2023-07-16 15:34:39 +02:00
Paul Gofman fc952a3ca3 [d3d11] Validate texture sharing parameters at texture creation 2023-07-16 15:34:39 +02:00
Paul Gofman 01ad79278b [d3d11] Support just one handle type in D3D11DXGIResource::{Get|Create}SharedHandle 2023-07-16 15:34:39 +02:00
Paul Gofman 48557886de [d3d11] Determine shared texture handle type through D3D11_RESOURCE_MISC_SHARED_NTHANDLE 2023-07-16 15:34:39 +02:00
Paul Gofman 8319793a98 [d3d11] Always close handle in D3D11CommonTexture::ExportImageInfo()
For KMT handle openKmtHandle() creates new handle, for NT handle
m_image->sharedHandle() gets duplicated handle from
vkGetMemoryWin32HandleKHR().
2023-07-16 15:34:39 +02:00
Blisto91 886268fcf9 [util] Remove Secret World Legends config 2023-07-16 15:26:46 +02:00
Hans-Kristian Arntzen 84e59fc9e5 [ci] Download glslangValidator.exe directly rather than using choco.
The choco package is extremely outdated and breaks now.
2023-07-16 15:25:21 +02:00
Blisto91 6be1f6d7bd [util] Limit fps in The Incredibles 2023-07-05 20:48:19 +02:00
Joshua Ashton 2f72115f91 [d3d9] Keep 1 presenter per swapchain window
Some apps such as level editors such as Hammer World Editor, some GUI apps/launchers etc use window overrides in presentation.

Previously we'd remake a new surface every time, which was incredibly slow making these apps basically unusable.

Now we keep one surface + swapchain + image views around per window/window override we have, along with the frame latency objs + frame counter.
(Obviously an app may present to multiple windows in a frame, so for frame latency purposes we track that per-window.
2023-07-04 16:44:31 +02:00
Alpyne 026aa49ef8 [util] replaceNaN: Align result
Otherwise _mm_store_ps can fail
2023-07-03 15:36:21 +02:00
Trevonn 3a368f4780 Bladestorm Nightmare - Game speed increases when above 60 FPS outside of missions
The game has 3 v-sync options but doesn't explain what they do.
0 = 60 FPS
1 = Monitor Refresh Rate
2 = 30 FPS

Framerate is capped at 60 in missions and then up to monitor refresh in the main menu and tavern area

This PR would provide a better default experience for people using option 1 with high refresh displays
2023-07-01 17:12:36 +02:00
Tatsuyuki Ishi 2ef41bdbf6 build: Switch symbols to DWARF 4
Since [1], Wine's supports and uses DWARF 4 as default. Make use of it, which
should fix inlined stacks and some other small details.

[1]: https://www.winehq.org/pipermail/wine-devel/2021-November/201333.html
2023-07-01 17:12:18 +02:00
Philip Rebohle 0f4458e173 [dxvk] Remove pending submission counter 2023-06-26 01:37:46 +01:00
Philip Rebohle ccb87d5ea9 [d3d9] Port flush heuristic from D3D11 2023-06-26 01:37:46 +01:00
Alpyne 022bf1d134 [d3d9] Allow changing API name for d3d8 2023-06-24 18:18:38 +01:00
Alpyne d6e7e3e780 [d3d9] Add DxvkD3D8Bridge for d3d8 interop 2023-06-24 17:58:49 +01:00
Blisto91 b77928b6fe [util] Fix Modern Warfare 2 Campaign Remastered config 2023-06-24 13:28:49 +02:00
Philip Rebohle 987df8a487 [util] Filter out internal private ref on object destruction
Closes #3531 for real this time.
2023-06-24 12:45:38 +02:00
Philip Rebohle a7278cdab1 [dxgi] Do not interact with other DXGI objects during swapchain destruction
This trips up Stalker Anomaly for some reason, but initializing an output
is not meaningful anyway in this situation since we either know the output
in question already, or we don't and it cannot be in a non-default state.

Closes #3531.
2023-06-24 12:38:10 +02:00
Joshua Ashton 3b3ebc9350 [d3d9] Rename some members to be clearer 2023-06-24 04:09:04 +01:00
Joshua Ashton 00ae118655 [d3d9] Don't use m_activeRTs in SetPixelShader
These are just textures, not surfaces.
2023-06-24 04:07:19 +01:00
Joshua Ashton 55be12daa5 Revert "[d3d9] Use m_activeRTs in BindFramebuffer"
This is only textures. Oops.

This reverts commit ff65599dba.
2023-06-24 04:06:24 +01:00
Joshua Ashton 0e36a07a93 [d3d9] Don't mark DS as hazardous if depth write is disabled 2023-06-24 03:55:16 +01:00
Joshua Ashton ff65599dba [d3d9] Use m_activeRTs in BindFramebuffer
Can roll in the anyColorWrites this way.
2023-06-24 03:42:54 +01:00
Joshua Ashton 6b60de2d31 [d3d9] Fix unbinding RTs
Fixes a regression with 8560efa3c7 in ND1.

Also more optimized.
2023-06-24 03:41:31 +01:00
Joshua Ashton 362743c1d6 [d3d9] Update DS hazards when PS shader masks change 2023-06-24 02:55:38 +01:00
Joshua Ashton 7f302fc350 [d3d9] Don't mark DS hazards if not used by shader 2023-06-24 02:53:14 +01:00
Philip Rebohle 8704ed7af6 [dxvk] Ignore some pipeline flags when ending render pass 2023-06-22 23:41:24 +02:00
Philip Rebohle 0895858901 [dxvk] Only decrement pending submission count for command submissions
Otherwise we'll underflow the integer and break the D3D9 flush heuristic.
2023-06-22 20:15:42 +02:00
Joshua Ashton 80b27f95bc [d3d9] Fix active hazards RT only being 4 bits 2023-06-22 16:37:09 +01:00
Joshua Ashton a791493d14 [d3d9] Don't rebind AlphaTest when changing RT if not necessary 2023-06-22 16:37:09 +01:00
Joshua Ashton c768196251 [d3d9] Compress hazard state going into CS
This can potentially happen per-draw so make it as small as possible.
2023-06-22 16:37:09 +01:00
Joshua Ashton 3625c5d481 [d3d9] Optimize DS active hazard check
There can only be one DS, so no need to loop over.
2023-06-22 16:37:09 +01:00
Philip Rebohle b3cbe36c08 [dxvk] Apply frame rate limit on presentation timeline
This may reduce latency as we no longer end up stalling subsequent
GPU submissions.
2023-06-22 16:17:03 +02:00
Philip Rebohle 166d90b04c [d3d11] Fix frame latency based on buffer count
We need to ignore the front buffer here since we synchronize after
presentation.
2023-06-22 16:16:30 +02:00
Robin Kertels 60b6e98529 [d3d9] Transition DS too if there's a feedback loop 2023-06-21 15:16:43 +01:00
Robin Kertels a20869fb93 [d3d9] Track textures in m_activeHazardsRT instead of RT
There's 21 textures and only 4 RTs.
Tracking the textures allows us to mask off the active texture bitfield
instead of the active render target one, potentially resulting in fewer iterations.
2023-06-21 15:16:43 +01:00
Philip Rebohle a287566c65 [dxgi] Implement frame statistics based on IDXGIVkSwapChain1 2023-06-21 15:16:37 +02:00
Philip Rebohle 28f48f9fdc [dxgi] Initialize output refresh counts with non-zero values
Matches Windows behaviour.
2023-06-21 15:16:37 +02:00
Philip Rebohle e02a800c33 [d3d11] Implement IDXGIVkSwapChain1 interface for D3D11 swap chain 2023-06-21 15:16:37 +02:00
Philip Rebohle d7fa39c4eb [util] Be more robust against timing weirdness when computing vblank count 2023-06-21 15:16:37 +02:00
Philip Rebohle d1e39be7e7 [dxgi] Add IDXGIVkSwapChain1 interface definition 2023-06-21 15:16:37 +02:00
Philip Rebohle 438c535fe7 [d3d11] Always release frame latency semaphore in Present 2023-06-21 15:16:37 +02:00
Philip Rebohle 7dbe4abb48 [d3d9] Use new presenter signal mechanism for frame pacing 2023-06-21 15:16:37 +02:00
Philip Rebohle e99bc591df [d3d11] Use new presenter signal mechanism for frame latency event 2023-06-21 15:16:37 +02:00
Philip Rebohle 08363edb05 [dxvk] Only synchronize with presents with FIFO present modes 2023-06-21 15:16:37 +02:00
Philip Rebohle 5d1196733b [dxvk] Implement waiting for specific present requests 2023-06-21 15:16:37 +02:00
Philip Rebohle ca3492570c [dxvk] Add functionality to wait for a given present operation 2023-06-21 15:16:37 +02:00
Philip Rebohle 215c4f8f6f [dxvk] Enable VK_KHR_present_id and VK_KHR_present_wait if supported 2023-06-21 15:16:37 +02:00
Robin Kertels 5a1ebfa4ee Revert "[d3d9] Only use direct buffer mapping for DYNAMIC buffers"
This reverts commit 1850819483.
2023-06-20 23:08:52 +01:00
Joshua Ashton 6f87ccdafc [d3d11] Use FORCE_UNORM depth bias representation for UNORM formats 2023-06-20 13:31:48 +01:00
Joshua Ashton b30a4f0cc7 [d3d9] Use FLOAT or FORCE_UNORM depth bias representation 2023-06-20 13:31:48 +01:00
Joshua Ashton 4e9853f608 [dxvk] Expose depth bias representation/exact controls 2023-06-20 13:31:48 +01:00
Joshua Ashton 5fbb0dd4ba [dxvk] Enable EXT_depth_bias_control 2023-06-20 13:31:48 +01:00
Joshua Ashton 77f6f2a84b [include] Bump Vulkan headers to v1.3.254 2023-06-20 13:31:48 +01:00
Alpyne 0b9acf3a25 [util] Add str::split
Used by d3d8
2023-06-20 13:31:17 +01:00
Timo Gurr 211d095ee4 [util] Limit STEINS;GATE ELITE to 60 fps
Intros, menu and ui animations are playing way too fast, also causing
input issues.
2023-06-20 13:27:52 +02:00
Trevonn 77e7e8bfba [util] Report NVIDIA for Star Wars Battlefront as it errors out on AMD 2023-06-20 13:23:52 +02:00
Alpyne 42a0264e69 [build] Fix libdisplay-info
See https://gitlab.freedesktop.org/JoshuaAshton/libdisplay-info/-/merge_requests/4
2023-06-19 21:14:03 +01:00
Alpyne 5d29140f74 [util] replaceNaN: Use unaligned SIMD _mm_loadu_ps
There is no good reason to expect games will have aligned the data they're passing in.
2023-06-19 21:13:37 +01:00
Alpyne 0236e780a7 [d3d9] Fix std::hex in D3D9CommonTexture 2023-06-19 21:02:10 +01:00
Alpyne 24dbcf8fd8 [dxso] Shared code for texbem and bem 2023-06-19 20:59:18 +01:00
Alpyne 404c984f9c [dxso] Implement bem instruction 2023-06-19 20:59:18 +01:00
Alpyne a79772322b [d3d9] Initialize m_mapFlags to 0
Can sometimes get weird default values in there.
2023-06-19 19:52:03 +01:00
Trevonn 36e6a7c2e5 [util] Set maxChunkSize to 1 for GOG and fix EA App exe name
Similar to the other launchers the VRAM goes 600MB+ to 100MB+
2023-06-16 16:28:31 +01:00
Trevonn c5ab5be48d [util] Set maxChunkSize to 1 for EA App
Reduces GPU VRAM usage of EADesktop.exe from 162MB to 6MB
2023-06-15 19:39:28 +01:00
Paul Gofman af9bd16b8d [dxvk] Always reference library in VR extension providers 2023-06-15 19:07:26 +02:00
Winter Snowfall 2c014fdb34 [util] Match on the GOG version of KoF XIII as well 2023-06-15 19:06:45 +02:00
Timo Gurr 6478c10a18 [util] Set maxChunkSize to 1 for Battle.net
Currently when Diablo 4 is running the Battle.net launcher it uses around
600MB of VRAM. Reducing the max chunk size to 1MB reduces the memory usage
to around 150MB.
2023-06-15 19:06:26 +02:00
Philip Rebohle 7388c243d2 [dxvk] Fix incorrect fullScreenExclusive feature check 2023-06-15 17:32:05 +02:00
Lilium bd575a4a46 [d3d11] implement 'clampNegativeLodBias' as a conf option 2023-06-14 20:22:27 +01:00
Lilium 3fce9886f5 [d3d9] implement 'clampNegativeLodBias' as a conf option 2023-06-14 20:22:27 +01:00
Lilium 5d134b877a [d3d9] implement 'samplerLodBias' as a conf option 2023-06-14 20:22:27 +01:00
Robin Kertels c75ed86909 [d3d9] Reset vertex & index buffer in Reset 2023-06-13 22:47:55 +01:00
Robin Kertels d1707026f9 [d3d9] Remove uninitialized device present params 2023-06-13 22:47:55 +01:00
Robin Kertels b8d36eeacc [d3d9] Fix losing auto depth stencil surface 2023-06-13 22:47:55 +01:00
Robin Kertels 8f740c53b4 [d3d9] Remove IsLosable
Redundant.
2023-06-13 22:47:55 +01:00
Robin Kertels 52ac271acb [d3d9] Reject Reset if there's any remaining DEFAULT resources 2023-06-13 14:15:18 +01:00
Robin Kertels a1a91dd766 [d3d9] Fix potential race when discarding systemmem textures 2023-06-11 16:57:17 +01:00
Robin Kertels 22f6246fd6 [util] Fix app profile grouping 2023-06-11 16:57:17 +01:00
Robin Kertels 9d6804e40a [util] Disable direct buffer mapping for Injustice 2023-06-11 16:57:17 +01:00
Robin Kertels 5fd025c513 [d3d9] Rename apitraceMode
It's not just used for apitrace and the new name
is more consistent with the D3D11 equivalent option.
2023-06-11 16:57:17 +01:00
Robin Kertels d9d6316609 [d3d9] Remove allowDiscard hack 2023-06-11 16:57:17 +01:00
Robin Kertels 9b877cf623 [util] Remove D&D - The Temple of Evil workaround
The game uses SWVP, so we don't need an app hack here.
2023-06-11 16:57:17 +01:00
Robin Kertels 2c3f2b9ad1 [d3d9] Ignore DISCARD after device loss 2023-06-11 16:57:17 +01:00
Robin Kertels 1850819483 [d3d9] Only use direct buffer mapping for DYNAMIC buffers
Tests show that buffers with just D3DUSAGE_WRITEONLY are uploaded on Unlock.
2023-06-11 16:57:17 +01:00
Robin Kertels 1db2e3a6ec [util] Re-enable direct buffer mapping for Dark Romance
The game uses SWVP, so we don't need the hack anymore.
2023-06-11 16:57:17 +01:00
Robin Kertels 2efd3f3698 [util] Re-enable direct buffer mapping for RE games
I cannot reproduce the stalls anymore.
2023-06-11 16:57:17 +01:00
Robin Kertels bbaf01d9e6 [d3d9] Force staging buffer mapping for pure SWVP devices 2023-06-11 16:57:17 +01:00
Robin Kertels 4a55047dde [d3d9] Forbid disabling SWVP on a pure SWVP device 2023-06-11 16:57:17 +01:00
Joshua Ashton 3fddc364ee [util] Fix UTF8 encodeTypedChar for 4 byte chars
Some flipped logic here...
2023-06-10 13:58:33 +02:00
Blisto91 f3fb5ba320 [util] Example config wording changes 2023-06-06 13:47:00 -07:00
Philip Rebohle 4d254b13be [dxgi] Unlock presenter lock early during presentation
If SetGammaControl and Present are called at the same time, we'll
otherwise have a deadlock due to reversed lock order.

Fixes #3458.
2023-06-05 17:02:15 +02:00
Joshua Ashton d241daa0b1 [util] Add app profile for Fallout 76 2023-06-05 03:00:53 +02:00
Eric Sullivan 2e70a2b07d [util] Set maxChunkSize to 1 for the Rockstar launcher and social club
Currently when Red Dead Redemption 2 is running the Rockstar launcher,
and social club each use over 600MB of VRAM. The root cause of this is
DXVK creating two memory pools of 256MB for read, and read/write resources.
Reducing the max chunk size to 1MB reduces the memory usage of each to
around 40MB.
2023-06-05 02:17:26 +02:00
Robin Kertels 52f04ca3d4 [d3d9] FF: Fix using wrong texCoord mask 2023-06-04 17:52:18 +01:00
Joshua Ashton c585ea251e [dxso] Respect all PS input elements for registers
Fixes shadows in Test Drive Unlimited 2.

Closes: #3469
2023-06-02 23:12:22 +02:00
Philip Rebohle ab00591297 [dxvk] Introduce dxvk.tearFree option
And replace the old frontend-specific options.
2023-06-01 17:48:51 +02:00
Philip Rebohle 85d52ccb88 [dxvk] Implement dynamic present mode switching
This way, we don't need to recreate the swap chain when the app switches
between vsync enabled and disabled. Currently only works when running
bleeding-edge Gamescope with ENABLE_GAMESCOPE_WSI=1.
2023-06-01 17:48:51 +02:00
Philip Rebohle e6be0cf996 [dxvk] Rework present mode selection for swap chains 2023-06-01 17:48:51 +02:00
Philip Rebohle 1728d9e89d [dxvk] Rework presenter creation to take a DxvkDevice
This way we can easily query available Vulkan features.
2023-06-01 17:48:51 +02:00
Philip Rebohle b1b0abdbbf [dxvk] Move presenter implementation to DXVK module 2023-06-01 17:48:51 +02:00
Philip Rebohle be875cd7e6 [dxvk] Enable VK_EXT_swapchain_maintenance1 and surface_maintenance1 2023-06-01 17:48:51 +02:00
Philip Rebohle 0543956ea0 [meta] Update Vulkan headers 2023-06-01 17:48:51 +02:00
Blisto91 e9e0949717 [meta] Clarify readme setup instructions 2023-05-31 12:58:28 +02:00
WinterSnowfall 8b6cbda6de [d3d9] Properly expose the MaxVertexBlendMatrixIndex capability 2023-05-30 23:56:26 +01:00
Robin Kertels 4b10846008 [dxso] Fix RT mask for SM1 2023-05-26 04:28:49 +01:00
Joshua Ashton e0654977c9 [d3d9] Stub out D3D9On12 interfaces
Closes: #3445
2023-05-24 14:36:45 +01:00
Joshua Ashton b5c18a02ae [d3d9] Optimize UpdateAnyColorWrites for 0th case
This is the most common
2023-05-24 14:21:30 +01:00
Joshua Ashton cafd104783 [d3d9] Pack RT bitmasks tightly
No need to waste a whole 32-bits for each entry here when we only have 4 possible RTs at a time.
2023-05-24 14:10:41 +01:00
Joshua Ashton 269bab2c34 [d3d9] Track if any color writes are enabled for an RT
Use this for determining whether to rebind FB and in checks, otherwise we can miss stuff for pure surface RTs
2023-05-24 14:05:13 +01:00
Joshua Ashton 075c0bf203 [d3d9] Use m_boundRTs for COLORWRITEENABLE checks
Also allows us to check for NULL RTs with this too and avoid extra work!
2023-05-24 13:42:42 +01:00
Joshua Ashton 8560efa3c7 [d3d9] Unbind RTs which are unwritten by a PS
Otherwise we can end up with feedback loops on RTs with a 0 color mask.

Closes: #3447
2023-05-24 13:40:17 +01:00
Blisto91 b9b2db510e [util] Limit fps for some Tomb Raider games 2023-05-24 14:31:38 +02:00
Lilium d5c6ae2e4d [dxvk] dxvk_adapter: implement macro to check for feature need in checkFeatureSupport 2023-05-24 11:53:34 +01:00
Lilium 633f6663a4 [dxvk] fix copy mistake in dxvk_adapter 2023-05-24 11:53:34 +01:00
Robin Kertels d2759c20ba [d3d9+d3d11] Remove DEVICE_LOCAL flag when forcing cached memory
Otherwise DXVK removes both flags at once
and we may end up with uncached memory.
2023-05-22 23:53:01 +02:00
Robin Kertels 1a2e724c16 [util] Enable apitrace mode for Tomb Raider Anniversary
... and Underworld.
2023-05-22 12:24:49 +02:00
Blisto91 6449f583f8 [util] Set dcSingleUseMode to false for SnowRunner 2023-05-21 16:05:41 +02:00
Joshua Ashton f2bb1d4b69 [d3d9] Add extended swapchain interfaces
Allows for controling colorspace, etc.
2023-05-19 19:26:27 +01:00
Joshua Ashton 495dc75ab2 [wsi] Pull out NormalizeDisplayMetadata 2023-05-19 19:26:27 +01:00
Paul Gofman 550e04c579 [dxgi] Preserve system monitor sort order in enumMonitors() 2023-05-19 18:17:40 +02:00
WinterSnowfall d4a7346198 [dxvk] Add configurable HUD opacity 2023-05-19 18:11:25 +02:00
Blisto91 99b367cdd6 [util] Set floatEmulation to Strict for Halo Online 2023-05-18 17:40:01 +01:00
Blisto91 65520fa18e [util] Fix BlazBlue Centralfiction config 2023-05-16 18:56:23 +02:00
Joshua Ashton f30376a1e4 [d3d11] Fix min luminance of HDR Metadata
This should be a multiply instead of a divide. Values are 1/10000th of a nit (0.0001 nit).
2023-05-13 21:16:29 +00:00
Philip Rebohle cae0a1cef3 [meta] Release 2.2 2023-05-12 11:26:07 +02:00
Philip Rebohle 14eb469005 [dxgi] Be more robust against monitor enumeration issues.
If there are monitors on the system that are not associated with
any adapter, enumerate all monitors for all adatpers. May solve
some issues if device filter options are used on multi-GPU systems.
2023-05-11 16:38:45 +02:00
Oleksii Bozhenko 80f7d2abd8 [d3d9] fix opCompositeExtract out of bound
Closes: https://github.com/doitsujin/dxvk/issues/3293

Signed-by: Oleksii Bozhenko <oleksii.bozhenko@globallogic.com>
2023-05-09 20:39:55 +00:00
Alpyne 2b09932d51 [d3d9] Fix crash if device is freed with bound textures 2023-05-09 00:12:35 +00:00
Robin Kertels bef2ef69ab [d3d9] Fix stupid variable name 2023-05-07 14:05:39 +02:00
Robin Kertels b08665c808 [d3d9] Fix compiler warning in Clear size check 2023-05-06 14:16:54 +01:00
Robin Kertels 96e22e7c67 [d3d9+util] Remove a bunch of redundant config options 2023-05-06 14:16:54 +01:00
Robin Kertels 5443a2f9f5 [d3d9] Don't swap buffers for SWAPEFFECT_COPY & DISCARD with 1 backbuffer 2023-05-06 14:16:54 +01:00
Paul Gofman 83a294285e [dxgi] Only enumerate outputs which belong to the adapter or associated iGPU 2023-05-05 16:44:51 +02:00
Robin Kertels 242ac20752 [d3d9] Release DC in fallback present path 2023-05-04 18:42:04 +02:00
Robin Kertels b357d16940 [util] Enable deviceLost for DC Universe Online and GTA IV 2023-05-03 13:04:00 +01:00
Robin Kertels b4366db398 [d3d9] Implement rudimentary device loss 2023-05-03 13:04:00 +01:00
Blisto91 b5f43063b1 [util] Spoof Nvidia for Modern Warfare 2 Campaign Remastered 2023-05-03 13:02:08 +01:00
Joshua Ashton f140d2de0d [d3d9] Handle swapchain OOM and other errors more gracefully
Supercedes: #2964
2023-05-03 12:59:02 +01:00
Aleksey Komarov 20356148af
include: Add few defines and types in windows.h for DXVK Native (#3307)
* windows: add define for ZeroMemory

* windows: add few *LP types, DUMMYUNIONNAME*, __C89_NAMELESSSTRUCTNAME

---------

Co-authored-by: Joshie <joshua@froggi.es>
2023-05-03 12:58:33 +01:00
Ellie Hermaszewska b81536458f
include: Implement some small utilities in native headers (#3361)
* Add QueryInterface template to IUnknown

As described here https://learn.microsoft.com/en-us/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface\(q\)\?source\=recommendations

* Implement DEFINE_ENUM_FLAG_OPERATORS

* Add REFCLSID to windows_base.h

This is used by the latest d3d12 headers for D3D12GetInterface
2023-05-03 12:39:51 +01:00
Robin Kertels 9ce1c4df0d [dxvk] Update tracked rtLayouts when changing image layout 2023-05-03 13:23:47 +02:00
Robin Kertels 860237e775 [d3d9] Skip 0x0 clears 2023-05-03 13:23:47 +02:00
Robin Kertels ceb3a7f8c6 [dxvk] Do direct FB resolve if resolve format is UNDEFINED
If the format is undefined, we use the format of each image
which is obviously also view compatible with the imge.
2023-05-03 13:23:47 +02:00
Robin Kertels a42643b235 [d3d9] Fall back to GDI blit for partial presents 2023-05-03 12:18:11 +01:00
Philip Rebohle 5c8ed491ab [dxvk] Rewrite thread wrapper
Addresses some issues raised in #3378.
2023-04-26 10:48:47 +02:00
Joshua Ashton b44c5bbd18 [dxgi] Fallback to P3 color primaries for HDR displays without chroma info in edid 2023-04-21 04:21:16 +01:00
mbriar 16d2a6045c [util] Switch Nioh deferSurfaceCreation from dxgi to d3d9
This game seems to behave similar to all the Tecmo Koei Atelier games
and not deferring surface creation for d3d9 prevents VRR from working on
X11.
2023-04-19 16:42:42 +02:00
mbriar 1971a5d187 [util] Also add d3d9.deferSurfaceCreation for Atelier Ryza 3
Reported to help with VRR, see https://github.com/ValveSoftware/Proton/issues/6648#issuecomment-1514394149
2023-04-19 16:42:42 +02:00
Philip Rebohle e074d83d0b [dxvk] Introduce GetContext method to retrieve immediate context.
Bypasses vtable hooks when retrieving the immediate context internally.
Remaining uses of GetImmediateContext are fine since those only interact
with public methods.
2023-04-18 12:42:24 +02:00
Robin Kertels 990a720525 [d3d9] Handle a bunch of texture converter edge cases 2023-04-16 09:18:30 +01:00
Rémi Bernon 0cf563d5df [dxgi] Leave current fullscreen mode when SetFullscreenState changes monitors
This fixes RiME not moving its window when output display is
changed in the game settings.
2023-04-14 00:41:18 +02:00
Florian Will 01dc9ddc7d [util] Add new "Zusi 3" exe filename
In addition to the legacy "ZusiSim.exe" executable, the recent 3.5
release added a 64-bit "ZusiSim.64.exe" executable. This is now the
default executable when launching the game in Steam. The game is
unplayable without this option, so update the regex for Zusi 3.

Fixes #3250.
2023-04-13 13:37:07 +02:00
oltolm 6b779206d9 remove unneeded definitions 2023-04-11 18:30:46 +02:00
Blisto91 8508633ba3 [util] Disable allowDirectBufferMapping for Dark Romance: Vampire in Love 2023-04-11 08:37:50 +01:00
Robin Kertels af0009c5de [d3d9] Use DxvkFormatInfo for video formats
And fix UYUY and YUY2 in the process.
2023-04-08 03:15:44 +01:00
Robin Kertels 31af522cbc [dxvk] Add VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM 2023-04-08 03:15:44 +01:00
Philip Rebohle d9a6b40ae3 [dxvk] Create and copy temporary image for resolves as necessary
Fixes #3337.
2023-04-06 21:04:56 +02:00
Tatsuyuki Ishi 6d14fffdbd [spirv] Declare defaulted copy and move constructor for SpirvCodeBuffer.
If a type has a destructor it will not get an implicit move constructor.

But if we declare a defaulted move constructor then we will get the copy
constructor deleted. So declare both to be defaulted.

Cuts 8.8% off shader translation time during loading in Overwatch 2.
2023-04-06 10:23:11 +02:00
Blisto91 3ce3209e3e [util] Set syncInterval to 1 for Crash Bandicoot N sane trilogy 2023-04-05 16:25:05 +01:00
Philip Rebohle f212cc8f7d [dxvk] Only enable dynamic MSAA state if sample shading is enabled
Otherwise, create a more specialized fragment output library on demand.
May help RADV since dynamic alpha-to-coverage triggers a less efficient
code path.
2023-04-04 17:34:07 +02:00
Philip Rebohle 306919047b [dxvk] Log driver name in addition to version
Fixes #3313.
2023-03-27 15:44:19 +02:00
Philip Rebohle 977669c613 [util] Enable cached dynamic vertex/index buffers in GTA V
Fixes #3311.
2023-03-25 22:40:43 +01:00
Zhiyi Zhang 631171cf45 [util] Disable nvapiHack for Tom Clancy's Ghost Recon Breakpoint.
Otherwise, it shows a DirectX error dialog and exits when using an NVIDIA GPU.
2023-03-25 22:38:07 +01:00
František Zatloukal 1a5afc77b1 [util] Include cstdint to fix compilation with GCC 13 2023-03-23 23:37:10 +01:00
Robin Kertels d11878e793 [d3d9] Only apply viewport zBias if minZ is below 0.5
Fixes Space Marine shadows.
Tests show that Windows D3D9 (Nvidia) works like that.
2023-03-23 03:52:08 +00:00
Philip Rebohle 4b74d1a97b [meta] Clarify file paths for install instructions
We got half a dozen issues about this in the past couple of weeks, and
it's quite frankly getting annoying, so just explain it in such a way
that everyone should understand it.
2023-03-23 02:05:42 +01:00
Blisto91 b0ed97e070 [util] Disable nvapiHack for Diablo 4 2023-03-22 17:10:18 +01:00
Philip Rebohle 3d5becaf6a [d3d11] Implement Acquire/ReleaseWrappedResource 2023-03-18 00:50:42 +01:00
Philip Rebohle 5595844f75 [dxvk] Add explicit buffer/image memory barrier methods
Useful for interop.
2023-03-18 00:50:42 +01:00
Philip Rebohle 9bdad71dc6 [d3d11] Implement CreateWrappedResource for D3D12 textures 2023-03-18 00:50:42 +01:00
Philip Rebohle 3c99314332 [d3d11] Implement CreateWrappedResource for D3D12 buffers 2023-03-18 00:50:42 +01:00
Philip Rebohle fa8cf50263 [dxvk] Implement functionality to import foreign buffers 2023-03-18 00:50:42 +01:00
Philip Rebohle 3f9d2269f6 [d3d11] Synchronize queue submissions for 11on12 devices as necessary
When the app explicitly calls Flush, Signal or Wait, we need to wait
for the submission to actually take place so that subsequent D3D12
submissions execute in the correct order.
2023-03-18 00:50:42 +01:00
Philip Rebohle 6432787ac3 [d3d11] Implement D3D11on12 device creation 2023-03-18 00:50:42 +01:00
Philip Rebohle da32453b42 [dxvk] Add submission feedback to command submissions 2023-03-16 20:59:43 +01:00
Philip Rebohle 27f3648a44 [dxvk] Check instance extensions for feature enablement as necessary 2023-03-16 20:59:43 +01:00
Philip Rebohle 35895ba05b [dxvk] Add callback to lock submission queue
Can be used to perform additional synchronization as necessary.
2023-03-16 20:59:43 +01:00
Philip Rebohle 56a8fa2e6f [dxvk] Implement functionality to import existing Vulkan device 2023-03-16 20:59:43 +01:00
Philip Rebohle d8f3a1c83d [dxvk] Rework device queue initialization 2023-03-16 20:59:43 +01:00
Philip Rebohle ef9d5048f3 [dxvk] Rework instance creation
Allows importing foreign Vulkan instances.
2023-03-16 20:59:43 +01:00
Philip Rebohle f50f5bc9bc [vulkan] Allow importing existing Vulkan dispatch tables 2023-03-16 20:59:43 +01:00
Philip Rebohle b06e82591e [include] Add definitions for D3D12 header 2023-03-16 20:59:43 +01:00
Philip Rebohle 687d32cac5 [dxvk] Fix memory reporting derp 2023-03-15 02:14:54 +01:00
WinterSnowfall 243c2f3cf5 [d3d9] remove support for the A1/X1R5G5B5 formats 2023-03-14 13:17:13 +00:00
Philip Rebohle af811656bb [meta] Update issue template 2023-03-13 17:54:34 +01:00
Philip Rebohle 05fb634f91 [util] Use __wine_dbg_output if available 2023-03-13 16:32:32 +01:00
Blisto91 3a123222e5 [util] Enable cached vertex buffers for SpellForce 3 2023-03-13 13:22:39 +01:00
Philip Rebohle 4faa598e09 [dxvk] Report memory used rather than allocated for heap properties
We can do this at least for DXVK's own memory allocations.
2023-03-12 13:59:47 +01:00
Philip Rebohle 6783123654 [dxgi] Use heap size to determine reservable memory
Budgets can change dynamically, so this should be more robust.
2023-03-12 13:59:17 +01:00
Robin Kertels d14dcf5d47 [d3d9] Fix redundant copy of SWVP VS consts
Fixes performance regression caused by state block changes.
2023-03-10 03:24:32 +00:00
Joshua Ashton 996acbe3f2 [d3d9] Refactor state blocks to allocate dynamically. 2023-03-07 23:24:01 +00:00
Blisto91 8ecd1b3b6b [util] enableDialogMode for Codename Panzers Phase One/Two 2023-03-07 22:51:23 +00:00
Philip Rebohle 7f21a6c491 [dxvk] Accumulate query data into query object
And do so when adding additional query handles, in order
to avoid allocating queries indefinitely if End is never
called, which Halo:MCC supposedly does.

Co-authored-by: Sam Edwards <CFSworks@gmail.com>
2023-03-06 12:35:22 +01:00
Philip Rebohle e430ff5cfd [dxvk] Use small_vector to store query handles. 2023-03-06 12:35:22 +01:00
Joshua Ashton 1acf885109 [dxvk] Call SDL_Vulkan_LoadLibrary in getInstanceExtensions for SDL WSI
Closes: #3275
2023-03-03 00:14:22 +00:00
Robin Kertels 1c6fc7b5b8 [d3d9] Clamp stage and type in [G,S]etTextureStageState
This is what happens on the Nvidia D3D9 driver.
Dawn of Magic 2 calls SetTextureStageState with a
stage > 7 and expects that to succeed.
2023-03-02 13:41:32 +00:00
Guy1524 5609c5e076
[util] Reduce maximum chunk size for WILD HEARTS.
Co-authored-by: Blisto91 <47954800+Blisto91@users.noreply.github.com>
2023-03-01 15:38:14 +01:00
Philip Rebohle 55e7cb1d54 [dxgi] Only log QueryInterface errors once 2023-03-01 13:25:56 +01:00
Philip Rebohle 4c78964679 [d3d9] Only log QueryInterface errors once 2023-03-01 13:25:56 +01:00
Philip Rebohle cc78276897 [d3d11] Only log QueryInterface errors once 2023-03-01 13:25:56 +01:00
Philip Rebohle aa92cf48f5 [util] Add function to cache QueryInterface errors 2023-03-01 13:25:56 +01:00
Philip Rebohle 81440340ac [d3d9,dxvk,util] Actually use dxvk::mutex 2023-03-01 13:03:43 +01:00
Philip Rebohle 2356d34f2e [d3d11] Create video context resources on demand
Saves another memory allocation that we will often not need.
2023-03-01 12:37:06 +01:00
Philip Rebohle f4b91817fe [dxvk] Create dummy sampler and buffer on demand
We only need the dummy buffer for transform feedback, all other cases
are handled by null descriptors. May save a memory allocation.
2023-03-01 12:10:48 +01:00
Philip Rebohle 2be0d6842e [dxvk] Add option to limit memory chunk size 2023-03-01 11:53:18 +01:00
Robin Kertels 0d28be4ab8 [d3d9] Fix capturing lights in state block 2023-02-23 13:15:17 +00:00
Blisto91 081181313e
[util] Limit Battle Fantasia Revisited Edition to 60fps (#3256) 2023-02-18 10:54:14 +01:00
TacoDeBoss caf31033d7
[util] Far Cry 2: Set VendorId to Nvidia, enable apitraceMode (#3241) 2023-02-07 12:14:48 +01:00
Paul Gofman 2263dcad95 [d3d11] Improve video processor caps query stubs 2023-01-31 13:39:09 +01:00
Jens Peters 41b1efd7ce [dxgi] Fix potential division by zero in log statement
Apparently 0/0 is legal and should be interpreted as 0/1.
2023-01-28 00:51:01 +01:00
Philip Rebohle c6111eaf61 [dxvk] Fix small_vector size
Kind of harmless since we're not using this much.
2023-01-27 05:27:49 +01:00
Philip Rebohle 2abc102d2c [meta] Release 2.1 2023-01-24 14:54:09 +01:00
Philip Rebohle 61d72eebc1 [dxgi,d3d9] Use global singleton for DXVK instances
No reason to have multiple of these around, and instance creation
is fairly expensive.
2023-01-23 17:17:56 +01:00
Philip Rebohle d4143429c4 [util] Add Singleton helper 2023-01-23 17:17:43 +01:00
Philip Rebohle 255ab1a63c [hud] Display more useful driver info in HUD
Vulkan versions are irrelevant anyway, not sure why we
ever displayed that in the first place.
2023-01-23 00:10:39 +01:00
Philip Rebohle 3128f4ea8e [dxgi] Implement IDXGIVkInteropFactory for DXGI factory 2023-01-22 20:04:39 +01:00
Philip Rebohle 0ee69fef00 [dxgi] Define IDXGIVkInteropFactory interface 2023-01-22 19:57:17 +01:00
Philip Rebohle 41ee092b97 [dxvk] Get rid of global timeline semaphore
Timeline semaphores are broken on 32-bit Proton, so just use the existing
command list binary semaphore to synchronize sparse binding operation.

This will introduce some additional graphics queue submissions around
sparse binding, but since that is basically unused it's not a concern.
2023-01-21 13:15:09 +01:00
Philip Rebohle d020f4451a [dxvk] Invalidate all v16 cache files
We were randomly writing bogus data in an irrecoverable way,
so in order to not cause any problems for users, invalidate
all caches created with this version.
2023-01-21 01:24:02 +01:00
Philip Rebohle 3d24560af7 [dxvk] Fix reading out-of-bounds memory in state cache
Fixes #3196, not to mention that this was god-awful code anyway.
2023-01-21 01:14:45 +01:00
Philip Rebohle 0af5ececa6 [dxvk] Also reset descriptor pool when only one pool is in use
This way we can often avoid allocating additional descriptor pools.
2023-01-20 15:23:25 +01:00
Philip Rebohle eacb8da9f7 [dxvk] Tweak descriptor pool numbers
Increases the descriptor pool size on 64-bit, but also makes
significantly better use of descriptor pool memory in situations
with very high draw counts and many UBO descriptor set updates.
2023-01-20 14:34:46 +01:00
Philip Rebohle 4d0d455895 [vulkan] Try loading winevulkan.dll before vulkan-1.dll
Should bypass issues with third-party overlays trying to hook Vulkan.
2023-01-18 18:10:57 +01:00
Philip Rebohle c6668ffbaa [dxvk] Drop shader module workaround for compute pipelines.
This was a bug in early Nvidia development drivers, but has been fixed since.
2023-01-18 15:56:00 +01:00
Blisto91 906b931e61 [util] Disable unmapping for BlazBlue Centralfiction 2023-01-17 20:49:26 +01:00
Philip Rebohle d7a4ddb5d0 [d3d11] Implement more accurate resource tracking on deferred contexts
Allows us to track chunks that access any given tracked resource more
accurately and flush as needed, e.g. if a staging buffer is written at
the start of a long command list.
2023-01-17 15:01:06 +01:00
Philip Rebohle cf5adb8b12 [d3d11] Improve flushing around deferred context submissions 2023-01-17 15:01:06 +01:00
Philip Rebohle 591e2df701 [d3d11] Consider flushing after each CS chunk
This way we will never end up with overly long command lists.
2023-01-17 15:01:06 +01:00
Philip Rebohle 2a3d7ee7dc [d3d11] Use new flush heuristic 2023-01-17 15:01:06 +01:00
Philip Rebohle f952418958 [d3d11] Determine pending commands based on sequence number
We get this for free and this allows us to query how many CS chunks
have been emitted since the last flush.
2023-01-17 15:01:06 +01:00
Philip Rebohle 0ac247c89c [util] Add helper class for common flush heuristic 2023-01-17 15:01:06 +01:00
Philip Rebohle 741cc493c6 [dxvk] Increase maximum number of command buffers in flight 2023-01-17 15:01:06 +01:00
Philip Rebohle f7aa310fdd [dxvk] Disable pipeline lifetime tracking for RADV
Seems like this is not needed on this driver, so let's just use
the fast path by default. Makes the current implementation work
with 32-bit games as well since caching does not work yet.
2023-01-17 14:02:38 +01:00
Philip Rebohle 421d7d9077 Revert "[vulkan] Use fence for acquiring a swap chain image"
Breaks things and we don't really need this right now anyway.
2023-01-16 23:16:38 +01:00
Philip Rebohle 599357721a [hud] Support HDR color spaces
Blending is broken if we need to do encoding in the shader, but we
cannot do much about that without changing the rendering process,
so this will have to do for now.
2023-01-16 18:04:18 +00:00
Philip Rebohle 0e503ce795 [vulkan] Log swap chain color space 2023-01-16 18:04:18 +00:00
Philip Rebohle 1482715fd1 [vulkan] Use fence for acquiring a swap chain image
In practice, drivers will block here anyway.
2023-01-16 16:20:56 +01:00
Joshua Ashton 132bc529c3 [dxgi] Only allow colorspace punting if we started in sRGB 2023-01-16 13:45:03 +01:00
Joshua Ashton 28ee6867be [dxgi] Expose only sRGB when enableHDR is disabled
Death Stranding: Director's Cut crashes if HDR was last enabled in-game and CheckColorSpaceSupport reports support for HDR but it is not globally enabled in DXGIOutput::GetDesc1's ColorSpace.

It seems safer to just lock HDR behind an option to avoid any teething issues like this. It sucks, but it also makes sense in a way.
2023-01-16 13:45:03 +01:00
Joshua Ashton bb75e214d6 [dxgi] Store top-level DxgiFactory in DxgiSwapChain
Can do this now that we tossed the old stuff that depended on the swapchain factory being resident in D3D11.
2023-01-16 13:45:03 +01:00
Joshua Ashton 9010f11adf [dxgi, d3d11] Remove support for legacy IWineDXGISwapChainFactory interface
vkd3d-proton 2.8 released last year with support for the new swapchain
interface.

No need to keep support for this legacy interface hanging around when
it complicates adding DxgiOptions support to the swapchain.
2023-01-16 13:45:03 +01:00
Philip Rebohle af05265cb6 [dxvk] Set thread priority for background workers
We accidentally lost this somehow.
2023-01-15 15:54:03 +01:00
Philip Rebohle 459758c6ff [d3d9] Don't set storage buffer usage unless necessary
This actually matters now to some degree.
2023-01-15 15:36:05 +01:00
Philip Rebohle d35bf455d9 [dxvk] Rename bindResourceBuffer to bindUniformBuffer 2023-01-15 15:36:05 +01:00
Philip Rebohle a8f9fdb21d [dxvk] Rearrange descriptor sets
This allows us not to unnecessarily dirty the FS UBO set when
changing tetxure bindings, leading to a cleaner separation.
2023-01-15 15:36:05 +01:00
Philip Rebohle 4a30933359 [dxvk] Add UBO set property to descriptor info
Used to explicitly propagate storage buffer bindings
to the respective UBO set.
2023-01-15 15:36:05 +01:00
Philip Rebohle 6f194b0e7b [d3d11] Bind UAV counter buffers as views 2023-01-15 15:36:05 +01:00
Philip Rebohle 82f500250f [hud] Bind data buffers as views 2023-01-15 15:36:05 +01:00
Philip Rebohle c347bd4d8b [dxvk] Allow creating buffer views with undefined format 2023-01-15 15:36:05 +01:00
Philip Rebohle 92de3f3f5f [d3d11] Add missing context locks 2023-01-14 18:40:41 +01:00
Philip Rebohle 1c2df54bdf [dxvk] Improve logging in case of memory errors 2023-01-14 03:39:55 +01:00
Philip Rebohle 2922b780c1 [dxvk] Properly handle bufferImageGranularity for images
Fixes validation errors about dedicated allocations being
bigger than the image's memory requirement on Nvidia.
2023-01-14 03:39:55 +01:00
Robin Kertels 97a91c816f [d3d9] Disable instancing for non-indexed draws 2023-01-13 21:58:41 +00:00
Philip Rebohle 3a84838ac4 [hud] Display approximate progress when compiling shaders 2023-01-13 16:43:27 +01:00
Philip Rebohle c978e62ec8 [dxvk] Implement better priority system for background shader compiles
Reduces the number of workers that perform background optimization,
which may reduce the performance impact when encountering a large
number of new pipelines at once.
2023-01-13 16:43:27 +01:00
Blisto91 cc9266edaa [util] Add config for Alien Rage
Reporting a GTX 295 puts us into the highest behind the scenes graphics settings preset bucket and prevents the shadow issue with `FloatingPointRenderTargets` set to false in the lower preset bucket.
NvapiHack needs to be disabled on Linux since the game pings it in the Windows system folder and want's the VendorId to match your GPU. Else the issue will still happen on Nvidia Linux
2023-01-13 14:15:54 +01:00
Philip Rebohle 070a340115 [dxvk] Remove path to look up optimized pipeline in cache
For some reason this sometimes takes several milliseconds, which
leads to noticeable stutter. Linking a pipeline is more consistent.
2023-01-13 11:40:01 +01:00
Philip Rebohle a22d70e184 [dxvk] Remove unused compileComputePipeline function 2023-01-12 17:35:05 +01:00
Philip Rebohle e5157a5360 [dxvk] Add pre-rasterization pipeline libraries to the state cache
This allows compiling tessellation or geometry shader pipelines
early while still using the pipeline library path.

Also removes compute shaders. Since API-provided compute shaders
are always compiled early, supporting them is no longer needed.
2023-01-11 11:48:16 +01:00
Philip Rebohle 28ae85b7ab [dxvk] Enable creating full pre-rasterization pipeline libraries 2023-01-11 11:48:16 +01:00
Philip Rebohle 17529101d5 [dxvk] Allow creating pipeline libraries with more than one shader 2023-01-11 11:48:16 +01:00
Philip Rebohle f9ff96d727 [dxvk] Implement checks for pre-raster pipeline library compatibility 2023-01-11 11:48:16 +01:00
Philip Rebohle b916dc04e5 [dxbc] Fill in patch vertex count info 2023-01-11 11:48:16 +01:00
Philip Rebohle 5e42230b95 [dxvk] Add patch vertex count to shader info struct 2023-01-11 11:48:16 +01:00
Philip Rebohle f76a7c285c [dxvk] Rework DxvkShaderPipelineLibrary to work with multiple shaders 2023-01-11 11:48:16 +01:00
Philip Rebohle 8011a40843 Revert "[dxbc] Handle dead code in shader binaries"
Apparently this regressed something, but the reporter who asked
for this fix in the first place did not specify what, so let's
just revert this and break the whole thing again until we get
something to actually work with.

This reverts commit 5115d80d51.
2023-01-10 20:37:22 +01:00
Philip Rebohle 8052347a22 [dxvk] Keep more empty system memory chunks alive 2023-01-10 03:42:37 +01:00
Philip Rebohle 0342a25e61 [d3d9,dxso] Add d3d9.forceSampleRateShading option 2023-01-09 18:35:02 +01:00
Philip Rebohle e426ec09a1 [d3d11,dxbc] Add d3d11.forceSampleRateShading option 2023-01-09 18:35:02 +01:00
Philip Rebohle 06fb93daf0 [dxvk] Only create state cache file on demand
If no pipelines are ever written to it, we should not create
the cache file in the first place.
2023-01-09 18:31:18 +01:00
Philip Rebohle 6a4fe06ac6 [dxvk] Fix incorrect flags for null fs pipeline layout 2023-01-09 18:31:18 +01:00
Joshua Ashton 5206d97710 [dxgi] Workaround UE4 DX11 + HDR crashes
Unreal Engine 4 titles use AGS/NVAPI to try and enable
HDR globally.
They can key this off IDXGIOutput::GetDesc1's ColorSpace
being HDR10.
Many of these UE4 games statically link against AGS.

This is a problem as when UE4 tries to enable HDR via AGS,
it does not check if AGSContext, and the display info etc
are nullptr unlike the rest of the code using AGS.
So we need to special-case UE4 titles to disable reporting a HDR
when they are in DX11 mode.

The simplest way to do this is to key off the fact that all
UE4 titles have an executable ending with "-Win64-Shipping".

We check if d3d12.dll is present, to determine what path in
UE4 we are on, as there are some games that ship both and support HDR.
(eg. The Dark Pictures: House of Ashes, 1281590)
Luckily for us, they only load d3d12.dll on the D3D12 render path
so we can key off that to force disable HDR only in D3D11.
2023-01-09 12:54:28 +00:00
Blisto91 3ed0a4fd43 [util] Set Secret World Legends launcher to SM 2 2023-01-08 10:47:04 +01:00
Beyley Thomas c11a63f5e5 [wsi] Add GLFW backend 2023-01-08 10:36:25 +01:00
Hunter Kvalevog 3491895960 [dxvk] Remove SDL dummy window
SDL >= 2.0.9 permits passing a nullptr window to
SDL_Vulkan_GetInstanceExtensions, so there's no
point in going though the work of creating a
window just to call this function.
2023-01-07 22:43:32 +00:00
Philip Rebohle 196fefec4c [dxvk] Enable dynamic multisample state if supported by the device
Eliminates stutter in situations where sample rate shading is used with MSAA.
2023-01-06 23:48:31 +01:00
Philip Rebohle f269cde749 [dxvk] Enable device features for dynamic multisample state 2023-01-06 23:48:31 +01:00
Philip Rebohle 4612113227 [meta] Update hopelessly outdated README entry 2023-01-06 23:48:14 +01:00
Philip Rebohle 389634f9b9 [d3d11] Fix D3D11Texture2D reference counting 2023-01-06 22:52:29 +01:00
Philip Rebohle 5115d80d51 [dxbc] Handle dead code in shader binaries
We should not emit any code when not inside a function.

Fixes #3154.
2023-01-06 20:49:13 +01:00
Joshua Ashton c10b53ed3e [dxgi] Add dxgi.enableHDR option 2023-01-06 17:27:38 +01:00
Joshua Ashton 3375cdf1fa [dxgi] Initialize DxgiOptions before DxgiMonitorInfo
Needed to we can access DxgiOptions inside of DxgiMonitorInfo for the dxgi.enableHDR property coming up in a future commit.
2023-01-06 17:27:38 +01:00
Joshua Ashton f25475d05e [dxgi] Normalize display metadata to something rational
Sometimes we can't get an EDID if things aren't plumbed fully, or some displays just have broken EDIDs.

This accounts for both of those cases by using some dummy data if we are missing information.

Fixes value reporting to match Windows on common displays such as LG OLEDs.
2023-01-06 17:27:38 +01:00
Joshua Ashton f453d6ee2a [dxgi] Implement DXGIOutput::GetDesc1's ColorSpace
Adds the ability to punt the global colorspace into HDR from SetColorSpace1.

We have no way of checking the actual Windows colorspace as the
only public method for this *is* DXGI which we are re-implementing.
So we just pick our color space based on the DXVK_HDR env var
and the punting from SetColorSpace1.

We might expand on this in future, but this is good enough for an
initial implementation.
2023-01-06 17:27:38 +01:00
Blisto91 dd660585c0 [meta] Remove current year from copyright notice 2023-01-06 16:48:04 +01:00
Joshua Ashton 4d2e90ceba [build] Bump libdisplay-info fork again 🐸
Bruh moment with MAX_PATH define between MinGW and Windows headers going on. Should have just PRed it from the start to avoid the churn :(
2023-01-06 11:29:50 +00:00
Joshua Ashton 421ac48007 [build] Bump libdisplay-info fork subproject to fix MSVC builds 2023-01-06 10:38:17 +00:00
Joshua Ashton fd34dba070 [build] Bump libdisplay-info fork
Should fix issues running under Windows with MinGW builds.
2023-01-06 10:08:52 +00:00
Robin Kertels f94b42f23f [d3d9] Dont use GenerateDrawInfo in DrawPrimitiveUp
This is confusing because it looks like a race condition
at first glance.
2022-12-30 19:29:34 +00:00
Philip Rebohle 12901b52f1 [dxvk] Split barriers with very large VkDependencyInfo structures
Works around an AMD driver bug. Fixes #3138.
2022-12-20 03:10:44 +01:00
Philip Rebohle f4f4f3647f [d3d11] Do not create storage image views with swizzle
This happens when a game uses A8_UNORM UAVs. Vulkan doesn't allow this,
and it's not meaningful for stores anyway, we'd need shader emulation.
2022-12-20 02:20:11 +01:00
Joshua Ashton c7be18cb26 [d3d11] Implement SetHDRMetadata 2022-12-19 22:15:18 +01:00
Joshua Ashton e5418a956a [vulkan] Add setHdrMetadata method to Presenter 2022-12-19 22:15:18 +01:00
Joshua Ashton 731bf84edd [dxvk] Enable VK_EXT_hdr_metadata 2022-12-19 22:15:18 +01:00
Joshua Ashton 4335eccae9 [dxvk] Enable VK_EXT_swapchain_colorspace 2022-12-19 22:15:18 +01:00
Joshua Ashton 33acf58ac7 [d3d11] Implement CheckColorSpaceSupport and SetColorSpace 2022-12-19 22:15:18 +01:00
Joshua Ashton 50054d4675 [vulkan] Add supportsColorSpace method to Presenter 2022-12-19 22:15:18 +01:00
Joshua Ashton fd661d587e [vulkan] Simplify args to Presenter GetSupported* methods 2022-12-19 22:15:18 +01:00
Robin Kertels 18b0ef697c [dxvk] Rework SetEventOnCompletion
* Create the waiter thread on demand
* Don't wake up the waiter thread every 10ms
  when no events are queued
* Wait on caller thread when hEvent = null
2022-12-16 17:37:19 +01:00
Philip Rebohle 6d4161cd6e [meta] Fix issues with build scripts if there are spaces in the path 2022-12-16 17:15:50 +01:00
Philip Rebohle c55c09368b [d3d11] Only store low 8 bits of stencil reference
Seems to match behaviour of the D3D11 runtime, in that OMGetDepthStencilState
will not retain the high bits.

Found by CME. Should fix #1784.
2022-12-11 19:51:57 +01:00
Blisto91 7b2024888e [util] disable unmapping for Final Fantasy XIV d3d9 2022-12-11 14:01:27 +01:00
Joshua Ashton c0d843c578 [wsi] Fix overwriting colorimetry info to NULL 2022-12-08 06:48:30 +00:00
bno1 858452a0bd [build] Fix submodule url for libdisplay-info 2022-12-06 22:53:49 +01:00
Philip Rebohle b838b65516 [d3d9] Correctly mask alpha reference push constant
We accidentally lost this during the rework, since the initial
implementation scaled the alpha ref value on the CPU.

Fixes #3123.
2022-12-06 21:25:55 +00:00
Blisto91 4a4d880130 [util] Set TRAHA Global to Intel vendor id 2022-12-04 23:06:59 +01:00
Robin Kertels 522909b165 [d3d9] Don't set NeedsReadback when dirtying mip maps
It's impossible to lock non 0 mips anyway.
2022-12-03 15:18:40 +00:00
Philip Rebohle 573be24269 [wsi] Fix crash when parsing EDID fails
If info is null then we shouldn't pass it around.

Also improve formatting a bit.
2022-12-02 00:23:38 +00:00
Philip Rebohle 9f70666777 [build] Allow standalone DXGI builds 2022-11-28 13:48:05 +01:00
Hans-Kristian Arntzen 42332f7fb8 [dxgi] Fix IDXGISwapchain::CheckColorSpaceSuport 2022-11-28 12:45:34 +01:00
wael 7644776f7a README: fix wine dll path 2022-11-26 13:05:15 +01:00
Philip Rebohle 57176e77ea [meta] Don't try to package setup script in a release tarball 2022-11-25 14:51:52 +01:00
Philip Rebohle 64cb1ad208 [meta] Remove setup script 2022-11-25 14:50:31 +01:00
Philip Rebohle 4f90d7bf5f [dxbc,d3d11] Don't access shex chunk if it is not defined 2022-11-25 12:45:32 +01:00
Joshua Ashton d01c9cb6d4 [wsi] Free edid info after parsing 2022-11-25 08:44:39 +00:00
Philip Rebohle ebd29007d4 [dxgi] Actually unlock monitor info
Fixes some deadlocks.
2022-11-21 20:24:15 +01:00
Philip Rebohle c6611dffa7 Revert "[dxbc] Move shex check to constructor"
Breaks stuff for unknown reasons.
2022-11-21 19:35:21 +01:00
Joshua Ashton f0a0e1b964 [dxgi] Report display metadata in IDXGIOutput6::GetDesc1 2022-11-21 17:26:53 +01:00
Joshua Ashton aa71e7e323 [dxgi] Cache display metadata + colorimetry in DXGI_VK_MONITOR_DATA 2022-11-21 17:26:53 +01:00
Joshua Ashton fabe4a85e3 [wsi] Add parseColorimetryInfo helper 2022-11-21 17:26:53 +01:00
Joshua Ashton ac10c75ca0 [build] Add Josh's libdisplay-info fork for parsing EDIDs
This will be used to parse static HDR metadata and chromaticity of the display.

Upstream currently has no Windows or MSVC support so use my fork for now.
2022-11-21 17:26:53 +01:00
Philip Rebohle 3b9235fe23 [util] Set max frame latency to 1 for Sonic Frontiers
Seems like the only reason this game passes QA is because there *was* no
QA. Seriously broken when GPU-bound even on Windows.
2022-11-21 17:18:01 +01:00
Robin Kertels 4796eb0b0d [d3d9] Implement capturing lights in state blocks 2022-11-21 16:06:49 +00:00
Robin Kertels 1a3b576d35 [util] Implement bit vector 2022-11-21 16:06:49 +00:00
Robin Kertels d0a10cc9f8 [d3d9] Handle DS texture uploads 2022-11-21 15:59:25 +00:00
Blisto91 2c53459f4c [util] disable floatControls for Bad Company 2 2022-11-21 13:13:57 +01:00
Robin Kertels dd7ec24269 [dxbc] Move shex check to constructor
Otherwise we dereference a null pointer when
accessing the DxbcProgramInfo.
2022-11-21 01:49:35 +01:00
Robin Kertels 3393c5f4ff [d3d9] Only upload mip 0 of managed automipgen textures 2022-11-19 17:34:02 +00:00
Philip Rebohle a130146f15 [dxvk] Remove dead enableRtOutputNanFixup option
Dead code since 2.0, not sure why this was still in here.
2022-11-18 22:31:54 +01:00
Joshua Ashton e037d24017 [util] Default initialize BitMask to 0
Found via an MSVC warning, may not fix anything, but good to do anyway.
2022-11-17 17:38:46 +01:00
Joshua Ashton 287412f746 [util] Cast _tzcnt_u64 to uint32_t
MSVC has _tzcnt_u64 return a uint64_t, which obviously, it can never return a number that big.
2022-11-17 17:38:46 +01:00
Joshua Ashton 69b1aa251d [wsi] Add getMonitorEdid function
What an unbelievable pain this is to do on Windows...

No-op on SDL2 right now, as there is nothing for that.
2022-11-17 17:38:16 +01:00
Blisto91 ad3c316d0c [util] Set Black Mesa customVendorId to Nvidia 2022-11-16 11:30:40 +01:00
Robin Kertels 785bc9738f [util] Disable DC Single Use Mode for Cardfight!! Vanguard Dear Days 2022-11-15 16:55:38 +01:00
290 changed files with 13984 additions and 5331 deletions

View File

@ -26,6 +26,6 @@ Name of the game, settings used etc.
For instructions on how to use apitrace, see: https://github.com/doitsujin/dxvk/wiki/Using-Apitrace
### Log files
- d3d9.log:
- d3d11.log:
- dxgi.log:
Please attach Proton or Wine logs as a text file:
- When using Proton, set the Steam launch options for your game to `PROTON_LOG=1 %command%` and attach the corresponding `steam-xxxxx.log` file in your home directory.
- When using regular Wine, use `wine game.exe > game.log 2>&1` and attach the resulting `game.log` file.

View File

@ -16,9 +16,8 @@ jobs:
- name: Setup glslangValidator
shell: pwsh
run: |
choco install vulkan-sdk -y
Write-Output "$([System.Environment]::GetEnvironmentVariable('VULKAN_SDK', 'Machine'))\Bin" `
| Out-File -FilePath "${Env:GITHUB_PATH}" -Append
Invoke-WebRequest -Uri "https://raw.githubusercontent.com/HansKristian-Work/vkd3d-proton-ci/main/glslangValidator.exe" -OutFile "glslangValidator.exe"
Write-Output "$pwd" | Out-File -FilePath "${Env:GITHUB_PATH}" -Append
- name: Setup Meson
shell: pwsh

4
.gitmodules vendored
View File

@ -7,3 +7,7 @@
[submodule "include/spirv"]
path = include/spirv
url = https://github.com/KhronosGroup/SPIRV-Headers.git
[submodule "subprojects/libdisplay-info"]
path = subprojects/libdisplay-info
url = https://gitlab.freedesktop.org/JoshuaAshton/libdisplay-info.git
branch = windows

View File

@ -1,5 +1,5 @@
Copyright (c) 2017-2021 Philip Rebohle
Copyright (c) 2019-2021 Joshua Ashton
Copyright (c) 2017 Philip Rebohle
Copyright (c) 2019 Joshua Ashton
zlib/libpng license

View File

@ -9,27 +9,32 @@ The most recent development builds can be found [here](https://github.com/doitsu
Release builds can be found [here](https://github.com/doitsujin/dxvk/releases).
## How to use
In order to install a DXVK package obtained from the [release](https://github.com/doitsujin/dxvk/releases) page into a given wine prefix, run the following commands from within the DXVK directory:
In order to install a DXVK package obtained from the [release](https://github.com/doitsujin/dxvk/releases) page into a given wine prefix, copy or symlink the DLLs into the following directories as follows, then open `winecfg` and manually add DLL overrides for `d3d11`, `d3d10core`, `dxgi`, and `d3d9`.
In a default Wine prefix that would be as follows:
```
export WINEPREFIX=/path/to/.wine-prefix
./setup_dxvk.sh install
export WINEPREFIX=/path/to/wineprefix
cp x64/*.dll $WINEPREFIX/drive_c/windows/system32
cp x32/*.dll $WINEPREFIX/drive_c/windows/syswow64
winecfg
```
This will **copy** the DLLs into the `system32` and `syswow64` directories of your wine prefix and set up the required DLL overrides. Pure 32-bit prefixes are also supported.
The setup script optionally takes the following arguments:
- `--symlink`: Create symbolic links to the DLL files instead of copying them. This is especially useful for development.
- `--without-dxgi`: Do not install DXVK's DXGI implementation and use the one provided by wine instead.
Verify that your application uses DXVK instead of wined3d by checking for the presence of the log file `d3d9.log` or `d3d11.log` in the application's directory, or by enabling the HUD (see notes below).
In order to remove DXVK from a prefix, run the following command:
For a pure 32-bit Wine prefix (non default) the 32-bit DLLs instead go to the `system32` directory:
```
export WINEPREFIX=/path/to/.wine-prefix
./setup_dxvk.sh uninstall
export WINEPREFIX=/path/to/wineprefix
cp x32/*.dll $WINEPREFIX/drive_c/windows/system32
winecfg
```
Verify that your application uses DXVK instead of wined3d by enabling the HUD (see notes below).
In order to remove DXVK from a prefix, remove the DLLs and DLL overrides, and run `wineboot -u` to restore the original DLL files.
Tools such as Steam Play, Lutris, Bottles, Heroic Launcher, etc will automatically handle setup of dxvk on their own when enabled.
### Notes on Vulkan drivers
Before reporting an issue, please check the [Wiki](https://github.com/doitsujin/dxvk/wiki/Driver-support) page on the current driver status and make sure you run a recent enough driver version for your hardware.
## Build instructions
In order to pull in all submodules that are needed for building, clone the repository using the following command:
@ -40,7 +45,7 @@ git clone --recursive https://github.com/doitsujin/dxvk.git
### Requirements:
- [wine 3.10](https://www.winehq.org/) or newer
- [wine 7.1](https://www.winehq.org/) or newer
- [Meson](https://mesonbuild.com/) build system (at least version 0.49)
- [Mingw-w64](https://www.mingw-w64.org) compiler and headers (at least version 10.0)
- [glslang](https://github.com/KhronosGroup/glslang) compiler
@ -73,12 +78,14 @@ ninja install
The D3D9, D3D10, D3D11 and DXGI DLLs will be located in `/your/dxvk/directory/bin`. Setup has to be done manually in this case.
### Notes on Vulkan drivers
Before reporting an issue, please check the [Wiki](https://github.com/doitsujin/dxvk/wiki/Driver-support) page on the current driver status and make sure you run a recent enough driver version for your hardware.
### Online multi-player games
Manipulation of Direct3D libraries in multi-player games may be considered cheating and can get your account **banned**. This may also apply to single-player games with an embedded or dedicated multiplayer portion. **Use at your own risk.**
### Logs
When used with Wine, DXVK will print log messages to `stderr`. Additionally, standalone log files can optionally be generated by setting the `DXVK_LOG_PATH` variable, where log files in the given directory will be called `app_d3d11.log`, `app_dxgi.log` etc., where `app` is the name of the game executable.
On Windows, log files will be created in the game's working directory by default, which is usually next to the game executable.
### HUD
The `DXVK_HUD` environment variable controls a HUD which can display the framerate and some stat counters. It accepts a comma-separated list of the following options:
- `devinfo`: Displays the name of the GPU and the driver version.
@ -96,6 +103,7 @@ The `DXVK_HUD` environment variable controls a HUD which can display the framera
- `compiler`: Shows shader compiler activity
- `samplers`: Shows the current number of sampler pairs used *[D3D9 Only]*
- `scale=x`: Scales the HUD by a factor of `x` (e.g. `1.5`)
- `opacity=y`: Adjusts the HUD opacity by a factor of `y` (e.g. `0.5`, `1.0` being fully opaque).
Additionally, `DXVK_HUD=1` has the same effect as `DXVK_HUD=devinfo,fps`, and `DXVK_HUD=full` enables all available HUD elements.
@ -108,6 +116,15 @@ Some applications do not provide a method to select a different GPU. In that cas
**Note:** If the device filter is configured incorrectly, it may filter out all devices and applications will be unable to create a D3D device.
### Graphics Pipeline Library
On drivers which support `VK_EXT_graphics_pipeline_library` Vulkan shaders will be compiled at the time the game loads its D3D shaders, rather than at draw time. This reduces or eliminates shader compile stutter in many games when compared to the previous system.
In games that load their shaders during loading screens or in the menu, this can lead to prolonged periods of very high CPU utilization, especially on weaker CPUs. For affected games it is recommended to wait for shader compilation to finish before starting the game to avoid stutter and low performance. Shader compiler activity can be monitored with `DXVK_HUD=compiler`.
This feature largely replaces the state cache.
**Note:** Games which only load their D3D shaders at draw time (e.g. most Unreal Engine games) will still exhibit some stutter, although it should still be less severe than without this feature.
### State cache
DXVK caches pipeline state by default, so that shaders can be recompiled ahead of time on subsequent runs of an application, even if the driver's own shader cache got invalidated in the meantime. This cache is enabled by default, and generally reduces stuttering.
@ -117,13 +134,16 @@ The following environment variables can be used to control the cache:
- `reset`: Clears the cache file.
- `DXVK_STATE_CACHE_PATH=/some/directory` Specifies a directory where to put the cache files. Defaults to the current working directory of the application.
This feature is mostly only relevant on systems without support for `VK_EXT_graphics_pipeline_library`
### Debugging
The following environment variables can be used for **debugging** purposes.
- `VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation` Enables Vulkan debug layers. Highly recommended for troubleshooting rendering issues and driver crashes. Requires the Vulkan SDK to be installed on the host system.
- `DXVK_LOG_LEVEL=none|error|warn|info|debug` Controls message logging.
- `DXVK_LOG_PATH=/some/directory` Changes path where log files are stored. Set to `none` to disable log file creation entirely, without disabling logging.
- `DXVK_CONFIG_FILE=/xxx/dxvk.conf` Sets path to the configuration file.
- `DXVK_DEBUG=markers|validation` Enables use of the `VK_EXT_debug_utils` extension for translating performance event markers, or to enable Vulkan validation, respecticely.
- `DXVK_CONFIG_FILE=/xxx/dxvk.conf` Sets path to the configuration file.
- `DXVK_CONFIG="dxgi.hideAmdGpu = True; dxgi.syncInterval = 0"` Can be used to set config variables through the environment instead of a configuration file using the same syntax. `;` is used as a seperator.
## Troubleshooting
DXVK requires threading support from your mingw-w64 build environment. If you
@ -143,3 +163,22 @@ For non debian based distros, make sure that your mingw-w64-gcc cross compiler
does have `--enable-threads=posix` enabled during configure. If your distro does
ship its mingw-w64-gcc binary with `--enable-threads=win32` you might have to
recompile locally or open a bug at your distro's bugtracker to ask for it.
# DXVK Native
DXVK Native is a version of DXVK which allows it to be used natively without Wine.
This is primarily useful for game and application ports to either avoid having to write another rendering backend, or to help with port bringup during development.
[Release builds](https://github.com/doitsujin/dxvk/releases) are built using the Steam Runtime.
### How does it work?
DXVK Native replaces certain Windows-isms with a platform and framework-agnostic replacement, for example, `HWND`s can become `SDL_Window*`s, etc.
All it takes to do that is to add another WSI backend.
**Note:** DXVK Native requires a backend to be explicitly set via the `DXVK_WSI_DRIVER` environment variable. The current built-in options are `SDL2` and `GLFW`.
DXVK Native comes with a slim set of Windows header definitions required for D3D9/11 and the MinGW headers for D3D9/11.
In most cases, it will end up being plug and play with your renderer, but there may be certain teething issues such as:
- `__uuidof(type)` is supported, but `__uuidof(variable)` is not supported. Use `__uuidof_var(variable)` instead.

View File

@ -1 +1 @@
2.0
2.3.1

View File

@ -185,7 +185,9 @@
"VK_EXT_memory_priority": 1,
"VK_EXT_vertex_attribute_divisor": 1,
"VK_EXT_custom_border_color": 1,
"VK_EXT_depth_clip_enable": 1
"VK_EXT_depth_clip_enable": 1,
"VK_EXT_swapchain_colorspace": 1,
"VK_EXT_hdr_metadata": 1
},
"features": {
"VkPhysicalDeviceFeatures": {
@ -385,6 +387,12 @@
}
},
"history": [
{
"revision": 4,
"date": "2022-12-18",
"author": "Joshua Ashton",
"comment": "Add VK_EXT_swapchain_colorspace and VK_EXT_hdr_metadata to d3d11_baseline_optional"
},
{
"revision": 3,
"date": "2022-10-13",

164
dxvk.conf
View File

@ -1,3 +1,15 @@
# Expose the HDR10 ColorSpace (DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020)
# to the application by default.
# This shows to the game that the global Windows 'HDR Mode' is enabled.
# Many (broken) games will need this to be set to consider exposing HDR output
# as determine it based on the DXGIOutput's current ColorSpace instead of
# using CheckColorSpaceSupport.
# This defaults to the value of the DXVK_HDR environment variable.
#
# Supported values: True, False
# dxgi.enableHDR = True
# Create the VkSurface on the first call to IDXGISwapChain::Present,
# rather than when creating the swap chain. Some games that start
# rendering with a different graphics API may require this option,
@ -49,18 +61,43 @@
# d3d9.customDeviceDesc = ""
# Report Nvidia GPUs as AMD GPUs by default. This is enabled by default
# to work around issues with NVAPI, but may cause issues in some games.
# Report Nvidia GPUs as AMD GPUs. Unless NVAPI support is explicitly
# enabled through Proton, this is done by default in order to work
# around crashes or low performance with Nvidia-speciic code paths
# in games, especially Unreal Engine.
#
# Supported values: True, False
# Supported values: Auto, True, False
# dxgi.nvapiHack = True
# 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
# known to have issues with AMDAGS or other AMD-specific code paths.
#
# Supported values: Auto, True, False
# dxgi.hideAmdGpu = Auto
# Report Intel GPUs as AMD GPUs. This is only done for games that are
# known to have issues with Intel-specific libraries such as XESS.
#
# Supported values: Auto, True, False
# dxgi.hideIntelGpu = Auto
# Override maximum amount of device memory and shared system memory
# reported to the application. This may fix texture streaming issues
# 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.
@ -110,8 +147,7 @@
#
# Supported values: Auto, True, False
# dxgi.tearFree = Auto
# d3d9.tearFree = Auto
# dxvk.tearFree = Auto
# Assume single-use mode for command lists created on deferred contexts.
@ -178,6 +214,16 @@
# Supported values: Any number between -2.0 and 1.0
# d3d11.samplerLodBias = 0.0
# d3d9.samplerLodBias = 0.0
# Clamps any negative LOD bias to 0. Applies after samplerLodBias has been
# applied. May help with games that use a high negative LOD bias by default.
#
# Supported values: True, False
# d3d11.clampNegativeLodBias = False
# d3d9.clampNegativeLodBias = False
# Declares vertex positions as invariant in order to solve
@ -189,6 +235,16 @@
# d3d9.invariantPosition = True
# Forces per-sample rate shading when MSAA is enabled, rather than per-pixel
# shading. May improve visual clarity at a significant performance cost, but
# may also introduce visual issues in some games.
#
# Supported values: True, False
# d3d11.forceSampleRateShading = False
# d3d9.forceSampleRateShading = False
# Forces the sample count of all textures to 1, and performs
# the needed fixups in resolve operations and shaders.
#
@ -244,6 +300,18 @@
# 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.
#
# If the graphics pipeline library feature is enabled, the given
@ -272,6 +340,17 @@
# dxvk.useRawSsbo = Auto
# Changes memory chunk size.
#
# Can be used to override the maximum memory chunk size.
#
# Supported values:
# - 0 to use the defaults
# - any positive integer to limit the chunk size, in MiB
# dxvk.maxChunkSize = 0
# Controls graphics pipeline library behaviour
#
# Can be used to change VK_EXT_graphics_pipeline_library usage for
@ -420,6 +499,7 @@
# Supported values:
# - True/False
# d3d11.longMad = False
# d3d9.longMad = False
# Device Local Constant Buffers
@ -433,18 +513,11 @@
# d3d9.deviceLocalConstantBuffers = False
# No Explicit Front Buffer
#
# Disables the front buffer
#
# Supported values:
# - True/False
# d3d9.noExplicitFrontBuffer = False
# Support DF formats
#
# Support the vendor extension DF floating point depth formats
# Support the vendor extension DF floating point depth formats on AMD and Intel.
# Note that this config is ignored and disabled by default on Nvidia, or when
# spoofing a Nvidia GPU, as it does not support these formats natively.
#
# Supported values:
# - True/False
@ -463,7 +536,7 @@
# Support X4R4G4B4
#
# Support the X4R4G4B4 format.
# The Sims 2 is a horrible game made by complete morons.
# The Sims 2 is a very broken game.
#
# Supported values:
# - True/False
@ -482,7 +555,7 @@
# Disable A8 as a Render Target
#
# Disable support for A8 format render targets
# Once again, The Sims 2 is a horrible game made by complete morons.
# Once again, The Sims 2 is a very broken game.
#
# Supported values:
# - True/False
@ -522,16 +595,6 @@
# d3d9.forceAspectRatio = ""
# Allow Discard
#
# Allow the discard lock flag to be used
# Useful if some apps use this incorrectly.
#
# Supported values:
# - True/False
# d3d9.allowDiscard = True
# Enumerate by Displays
#
# Whether we should enumerate D3D9 adapters by display (windows behaviour)
@ -543,16 +606,17 @@
# d3d9.enumerateByDisplays = True
# APITrace Mode
# Cached Dynamic Buffers
#
# Makes all host visible buffers cached and coherent
# Improves performance when apitracing, but also can impact
# some dumb games.
# Allocates dynamic resources in D3DPOOL_DEFAULT in
# cached system memory rather than uncached memory or host-visible
# VRAM, in order to allow fast readback from the CPU. This is only
# useful for buggy applications, and may reduce GPU-bound performance.
#
# Supported values:
# - True/False
# d3d9.apitraceMode = False
# d3d9.cachedDynamicBuffers = False
# Seamless Cubes
#
@ -582,3 +646,37 @@
# DO NOT CHANGE THIS UNLESS YOU HAVE A VERY GOOD REASON.
# d3d9.textureMemory = 100
# Hide integrated graphics from applications
#
# Only has an effect when dedicated GPUs are present on the system. It is
# not recommended to use this option at all unless absolutely necessary for
# a game to work; prefer using DXVK_FILTER_DEVICE_NAME whenever possible.
#
# Supported values:
# - True/False
# dxvk.hideIntegratedGraphics = False
# Trigger DEVICELOST when losing focus
#
# D3D9 requires the application to call Device::Reset after
# it loses focus in fullscreen.
# Some games rely on observing a D3DERR_DEVICELOST or D3DERR_NOTRESET.
# Others don't handle it correctly.
#
# Supported values:
# - True/False
# d3d9.deviceLossOnFocusLoss = False
# Reject Device::Reset if any losable resource is still alive
#
# D3D9 rejects Device::Reset if there's still any alive resources of specific types.
# (State blocks, additional swapchains, D3DPOOL_DEFAULT resources)
# Some games leak resources leading to a hang.
#
# Supported values:
# - True/False
# d3d9.countLosableResources = True

View File

@ -12,6 +12,10 @@ struct IUnknown {
public:
virtual HRESULT QueryInterface(REFIID riid, void** ppvObject) = 0;
template<class Q>
HRESULT STDMETHODCALLTYPE QueryInterface(Q **pp) {
return QueryInterface(__uuidof(Q), (void **)pp);
}
virtual ULONG AddRef() = 0;
virtual ULONG Release() = 0;

View File

@ -23,10 +23,16 @@ typedef uint32_t UINT;
typedef int32_t LONG;
typedef uint32_t ULONG;
typedef int32_t *LPLONG;
typedef int32_t HRESULT;
typedef wchar_t WCHAR;
typedef WCHAR *NWPSTR, *LPWSTR, *PWSTR;
typedef unsigned char UCHAR, *PUCHAR;
typedef char CHAR;
typedef const CHAR *LPCSTR, *PCSTR;
typedef INT BOOL;
typedef BOOL WINBOOL;
@ -35,11 +41,13 @@ typedef uint16_t UINT16;
typedef uint32_t UINT32;
typedef uint64_t UINT64;
typedef void VOID;
typedef void* PVOID;
typedef void* LPVOID;
typedef const void* LPCVOID;
typedef size_t SIZE_T;
typedef int8_t INT8;
typedef uint8_t UINT8;
typedef uint8_t BYTE;
@ -47,7 +55,13 @@ typedef int16_t SHORT;
typedef uint16_t USHORT;
typedef int64_t LONGLONG;
typedef int64_t INT64;
typedef uint64_t ULONGLONG;
typedef uint64_t UINT64;
typedef intptr_t LONG_PTR;
typedef uintptr_t ULONG_PTR;
typedef float FLOAT;
@ -66,9 +80,11 @@ typedef GUID IID;
#ifdef __cplusplus
#define REFIID const IID&
#define REFGUID const GUID&
#define REFCLSID const GUID&
#else
#define REFIID const IID*
#define REFGUID const GUID*
#define REFCLSID const GUID* const
#endif // __cplusplus
#ifdef __cplusplus
@ -86,6 +102,7 @@ inline bool operator!=(const GUID& a, const GUID& b) { return std::memcmp(&a, &b
typedef uint32_t DWORD;
typedef uint16_t WORD;
typedef DWORD *LPDWORD;
typedef void* HANDLE;
typedef HANDLE HMONITOR;
@ -107,6 +124,12 @@ typedef uint32_t UINT_PTR;
typedef INT_PTR* PINT_PTR;
typedef UINT_PTR* PUINT_PTR;
#ifdef STRICT
#define DECLARE_HANDLE(a) typedef struct a##__ { int unused; } *a
#else /*STRICT*/
#define DECLARE_HANDLE(a) typedef HANDLE a
#endif /*STRICT*/
typedef char* LPSTR;
typedef wchar_t* LPWSTR;
typedef const char* LPCSTR;
@ -129,12 +152,12 @@ typedef struct RECT {
LONG top;
LONG right;
LONG bottom;
} RECT;
} RECT,*PRECT,*NPRECT,*LPRECT;
typedef struct SIZE {
LONG cx;
LONG cy;
} SIZE;
} SIZE,*PSIZE,*LPSIZE;
typedef union {
struct {
@ -166,7 +189,7 @@ typedef struct PALETTEENTRY {
BYTE peGreen;
BYTE peBlue;
BYTE peFlags;
} PALETTEENTRY;
} PALETTEENTRY, *PPALETTEENTRY, *LPPALETTEENTRY;
typedef struct RGNDATAHEADER {
DWORD dwSize;
@ -179,7 +202,7 @@ typedef struct RGNDATAHEADER {
typedef struct RGNDATA {
RGNDATAHEADER rdh;
char Buffer[1];
} RGNDATA;
} RGNDATA,*PRGNDATA,*NPRGNDATA,*LPRGNDATA;
// Ignore these.
#define STDMETHODCALLTYPE
@ -191,6 +214,11 @@ typedef struct RGNDATA {
#define TRUE 1
#define FALSE 0
#define WAIT_TIMEOUT 0x00000102
#define WAIT_FAILED 0xffffffff
#define WAIT_OBJECT_0 0
#define WAIT_ABANDONED 0x00000080
#define interface struct
#define MIDL_INTERFACE(x) struct
@ -278,6 +306,7 @@ typedef struct RGNDATA {
#define THIS_
#define THIS
#define __C89_NAMELESSSTRUCTNAME
#define __C89_NAMELESSUNIONNAME
#define __C89_NAMELESSUNIONNAME1
#define __C89_NAMELESSUNIONNAME2
@ -290,17 +319,35 @@ typedef struct RGNDATA {
#define __C89_NAMELESS
#define DUMMYUNIONNAME
#define DUMMYSTRUCTNAME
#define DUMMYUNIONNAME1
#define DUMMYUNIONNAME2
#define DUMMYUNIONNAME3
#define DUMMYUNIONNAME4
#define DUMMYUNIONNAME5
#define DUMMYUNIONNAME6
#define DUMMYUNIONNAME7
#define DUMMYUNIONNAME8
#define DUMMYUNIONNAME9
#ifdef __cplusplus
#define DECLARE_INTERFACE(x) struct x
#define DECLARE_INTERFACE_(x, y) struct x : public y
#else
#ifdef CONST_VTABLE
#define DECLARE_INTERFACE(x) \
typedef interface x { \
const struct x##Vtbl *lpVtbl; \
} x; \
typedef const struct x##Vtbl x##Vtbl; \
const struct x##Vtbl
#else
#define DECLARE_INTERFACE(x) \
typedef interface x { \
struct x##Vtbl *lpVtbl; \
} x; \
typedef struct x##Vtbl x##Vtbl; \
struct x##Vtbl
#endif // CONST_VTABLE
#define DECLARE_INTERFACE_(x, y) DECLARE_INTERFACE(x)
#endif // __cplusplus
@ -327,3 +374,25 @@ typedef struct RGNDATA {
#define FAILED(hr) ((HRESULT)(hr) < 0)
#define SUCCEEDED(hr) ((HRESULT)(hr) >= 0)
#define RtlZeroMemory(Destination,Length) memset((Destination),0,(Length))
#define ZeroMemory RtlZeroMemory
#ifndef DEFINE_ENUM_FLAG_OPERATORS
#ifdef __cplusplus
# define DEFINE_ENUM_FLAG_OPERATORS(type) \
extern "C++" \
{ \
inline type operator &(type x, type y) { return (type)((int)x & (int)y); } \
inline type operator &=(type &x, type y) { return (type &)((int &)x &= (int)y); } \
inline type operator ~(type x) { return (type)~(int)x; } \
inline type operator |(type x, type y) { return (type)((int)x | (int)y); } \
inline type operator |=(type &x, type y) { return (type &)((int &)x |= (int)y); } \
inline type operator ^(type x, type y) { return (type)((int)x ^ (int)y); } \
inline type operator ^=(type &x, type y) { return (type &)((int &)x ^= (int)y); } \
}
#else
# define DEFINE_ENUM_FLAG_OPERATORS(type)
#endif
#endif /* DEFINE_ENUM_FLAG_OPERATORS */

View File

@ -0,0 +1,25 @@
#include <windows.h>
#include <GLFW/glfw3.h>
namespace dxvk::wsi {
inline GLFWwindow* fromHwnd(HWND hWindow) {
return reinterpret_cast<GLFWwindow*>(hWindow);
}
inline HWND toHwnd(GLFWwindow* pWindow) {
return reinterpret_cast<HWND>(pWindow);
}
// Offset so null HMONITORs go to -1
inline int32_t fromHmonitor(HMONITOR hMonitor) {
return static_cast<int32_t>(reinterpret_cast<intptr_t>(hMonitor)) - 1;
}
// Offset so -1 display id goes to 0 == NULL
inline HMONITOR toHmonitor(int32_t displayId) {
return reinterpret_cast<HMONITOR>(static_cast<intptr_t>(displayId + 1));
}
}

View File

@ -1,6 +1,6 @@
#include <windows.h>
#include <SDL2/SDL.h>
#include <SDL.h>
namespace dxvk::wsi {
@ -22,4 +22,4 @@ namespace dxvk::wsi {
return reinterpret_cast<HMONITOR>(static_cast<intptr_t>(displayId + 1));
}
}
}

View File

@ -4,6 +4,8 @@
#error You shouldnt be using this code path.
#elif DXVK_WSI_SDL2
#include "wsi/native_sdl2.h"
#elif DXVK_WSI_GLFW
#include "wsi/native_glfw.h"
#else
#error Unknown wsi!
#endif

@ -1 +1 @@
Subproject commit 0bcc624926a25a2a273d07877fd25a6ff5ba1cfb
Subproject commit 8b246ff75c6615ba4532fe4fde20f1be090c3764

@ -1 +1 @@
Subproject commit 98f440ce6868c94f5ec6e198cc1adda4760e8849
Subproject commit 46dc0f6e514f5730784bb2cac2a7c731636839e8

View File

@ -1,11 +1,12 @@
project('dxvk', ['c', 'cpp'], version : 'v2.0', 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()
platform = target_machine.system()
fs = import('fs')
cpp = meson.get_compiler('cpp')
cc = meson.get_compiler('c')
dxvk_is_msvc = cpp.get_id() == 'msvc'
dxvk_is_msvc = cpp.get_argument_syntax() == 'msvc'
compiler_args = [
'-msse',
@ -33,11 +34,24 @@ if get_option('build_id')
]
endif
dxvk_include_dirs = [
'./include',
'./include/vulkan/include',
'./include/spirv/include'
]
dxvk_include_dirs = ['./include']
if fs.is_dir('./include/vulkan/include')
dxvk_include_dirs += ['./include/vulkan/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(
'libdisplay-info',
version: ['>= 0.0.0', '< 0.2.0'],
fallback: ['libdisplay-info', 'di_dep'],
default_options: ['default_library=static'],
)
if platform == 'windows'
compiler_args += [
@ -45,29 +59,34 @@ if platform == 'windows'
'-D_WIN32_WINNT=0xa00',
]
link_args += [
'-static',
'-static-libgcc',
'-static-libstdc++',
# We need to set the section alignment for debug symbols to
# work properly as well as avoiding a memcpy from the Wine loader.
'-Wl,--file-alignment=4096',
]
# Wine's built-in back traces only work with dwarf2 symbols
if get_option('debug')
compiler_args += [
'-gstrict-dwarf',
'-gdwarf-2',
]
endif
# Enable stdcall fixup on 32-bit
if cpu_family == 'x86'
if not dxvk_is_msvc
link_args += [
'-Wl,--enable-stdcall-fixup',
'-Wl,--add-stdcall-alias',
]
'-static',
'-static-libgcc',
'-static-libstdc++',
# We need to set the section alignment for debug symbols to
# work properly as well as avoiding a memcpy from the Wine loader.
'-Wl,--file-alignment=4096',
]
# Wine's built-in back traces only work with dwarf4 symbols
if get_option('debug')
compiler_args += [
'-gdwarf-4',
]
endif
# Enable stdcall fixup on 32-bit
if cpu_family == 'x86'
link_args += [
'-Wl,--enable-stdcall-fixup',
'-Wl,--kill-at',
]
endif
else
link_args += [
'/FILEALIGN:4096',
]
endif
lib_d3d9 = cpp.find_library('d3d9')
@ -96,12 +115,9 @@ if platform == 'windows'
)
endif
dxvk_wsi = 'win32'
dxvk_name_prefix = ''
compiler_args += ['-DDXVK_WSI_WIN32']
else
lib_sdl2 = cpp.find_library('SDL2')
wrc = find_program('touch')
wrc_generator = generator(wrc, output : [ '@BASENAME@_ignored.h' ], arguments : [ '@OUTPUT@' ] )
@ -111,9 +127,19 @@ else
'./include/native/directx'
]
dxvk_wsi = 'sdl2'
lib_sdl2 = dependency('SDL2', required: false)
lib_glfw = dependency('glfw', required: false)
if lib_sdl2.found()
compiler_args += ['-DDXVK_WSI_SDL2']
endif
if lib_glfw.found()
compiler_args += ['-DDXVK_WSI_GLFW']
endif
if (not lib_sdl2.found() and not lib_glfw.found())
error('SDL2 or GLFW are required to build dxvk-native')
endif
dxvk_name_prefix = 'libdxvk_'
compiler_args += ['-DDXVK_WSI_SDL2']
link_args += [
'-static-libgcc',
@ -132,10 +158,10 @@ exe_ext = ''
dll_ext = ''
def_spec_ext = '.def'
glsl_compiler = find_program('glslangValidator')
glsl_compiler = find_program('glslang', 'glslangValidator')
glsl_args = [
'--quiet',
'--target-env', 'vulkan1.2',
'--target-env', 'vulkan1.3',
'--vn', '@BASENAME@',
'--depfile', '@DEPFILE@',
'@INPUT@',

View File

@ -3,3 +3,5 @@ option('enable_d3d9', type : 'boolean', value : true, description: 'Build D3D9'
option('enable_d3d10', type : 'boolean', value : true, description: 'Build D3D10')
option('enable_d3d11', type : 'boolean', value : true, description: 'Build D3D11')
option('build_id', type : 'boolean', value : false)
option('dxvk_native_wsi', type : 'string', value : 'sdl2', description: 'WSI system to use if building natively.')

View File

@ -10,7 +10,8 @@ if [ -z "$1" ] || [ -z "$2" ]; then
fi
DXVK_VERSION="$1"
DXVK_SRC_DIR=`dirname $(readlink -f $0)`
DXVK_SRC_DIR=$(readlink -f "$0")
DXVK_SRC_DIR=$(dirname "$DXVK_SRC_DIR")
DXVK_BUILD_DIR=$(realpath "$2")"/dxvk-native-$DXVK_VERSION"
DXVK_ARCHIVE_PATH=$(realpath "$2")"/dxvk-native-$DXVK_VERSION.tar.gz"
@ -55,13 +56,14 @@ function build_arch {
opt_strip=--strip
fi
CC="$CC -m$1" CXX="$CXX -m$1" meson setup \
--buildtype "release" \
--prefix "$DXVK_BUILD_DIR/usr" \
$opt_strip \
--bindir "$2" \
--libdir "$2" \
-Dbuild_id=$opt_buildid \
CC="$CC -m$1" CXX="$CXX -m$1" meson setup \
--buildtype "release" \
--prefix "$DXVK_BUILD_DIR/usr" \
$opt_strip \
--bindir "$2" \
--libdir "$2" \
-Dbuild_id=$opt_buildid \
--force-fallback-for=libdisplay-info \
"$DXVK_BUILD_DIR/build.$1"
cd "$DXVK_BUILD_DIR/build.$1"

View File

@ -10,7 +10,8 @@ if [ -z "$1" ] || [ -z "$2" ]; then
fi
DXVK_VERSION="$1"
DXVK_SRC_DIR=`dirname $(readlink -f $0)`
DXVK_SRC_DIR=$(readlink -f "$0")
DXVK_SRC_DIR=$(dirname "$DXVK_SRC_DIR")
DXVK_BUILD_DIR=$(realpath "$2")"/dxvk-$DXVK_VERSION"
DXVK_ARCHIVE_PATH=$(realpath "$2")"/dxvk-$DXVK_VERSION.tar.gz"
@ -76,11 +77,6 @@ function build_arch {
fi
}
function build_script {
cp "$DXVK_SRC_DIR/setup_dxvk.sh" "$DXVK_BUILD_DIR/setup_dxvk.sh"
chmod +x "$DXVK_BUILD_DIR/setup_dxvk.sh"
}
function package {
cd "$DXVK_BUILD_DIR/.."
tar -czf "$DXVK_ARCHIVE_PATH" "dxvk-$DXVK_VERSION"
@ -89,7 +85,6 @@ function package {
build_arch 64
build_arch 32
build_script
if [ $opt_nopackage -eq 0 ]; then
package

View File

@ -1,206 +0,0 @@
#!/usr/bin/env bash
# default directories
dxvk_lib32=${dxvk_lib32:-"x32"}
dxvk_lib64=${dxvk_lib64:-"x64"}
# figure out where we are
basedir="$(dirname "$(readlink -f "$0")")"
# figure out which action to perform
action="$1"
case "$action" in
install)
;;
uninstall)
;;
*)
echo "Unrecognized action: $action"
echo "Usage: $0 [install|uninstall] [--without-dxgi] [--symlink]"
exit 1
esac
# process arguments
shift
with_dxgi=true
file_cmd="cp -v --reflink=auto"
while (($# > 0)); do
case "$1" in
"--without-dxgi")
with_dxgi=false
;;
"--symlink")
file_cmd="ln -s -v"
;;
esac
shift
done
# check wine prefix before invoking wine, so that we
# don't accidentally create one if the user screws up
if [ -n "$WINEPREFIX" ] && ! [ -f "$WINEPREFIX/system.reg" ]; then
echo "$WINEPREFIX:"' Not a valid wine prefix.' >&2
exit 1
fi
# find wine executable
export WINEDEBUG=-all
# disable mscoree and mshtml to avoid downloading
# wine gecko and mono
export WINEDLLOVERRIDES="mscoree,mshtml="
wine="wine"
wine64="wine64"
wineboot="wineboot"
# $PATH is the way for user to control where wine is located (including custom Wine versions).
# Pure 64-bit Wine (non Wow64) requries skipping 32-bit steps.
# In such case, wine64 and winebooot will be present, but wine binary will be missing,
# however it can be present in other PATHs, so it shouldn't be used, to avoid versions mixing.
wine_path=$(dirname "$(which $wineboot)")
wow64=true
if ! [ -f "$wine_path/$wine" ]; then
wine=$wine64
wow64=false
fi
# resolve 32-bit and 64-bit system32 path
winever=$($wine --version | grep wine)
if [ -z "$winever" ]; then
echo "$wine:"' Not a wine executable. Check your $wine.' >&2
exit 1
fi
# ensure wine placeholder dlls are recreated
# if they are missing
$wineboot -u
win64_sys_path=$($wine64 winepath -u 'C:\windows\system32' 2> /dev/null)
win64_sys_path="${win64_sys_path/$'\r'/}"
if $wow64; then
win32_sys_path=$($wine winepath -u 'C:\windows\system32' 2> /dev/null)
win32_sys_path="${win32_sys_path/$'\r'/}"
fi
if [ -z "$win32_sys_path" ] && [ -z "$win64_sys_path" ]; then
echo 'Failed to resolve C:\windows\system32.' >&2
exit 1
fi
# create native dll override
overrideDll() {
$wine reg add 'HKEY_CURRENT_USER\Software\Wine\DllOverrides' /v $1 /d native /f >/dev/null 2>&1
if [ $? -ne 0 ]; then
echo -e "Failed to add override for $1"
exit 1
fi
}
# remove dll override
restoreDll() {
$wine reg delete 'HKEY_CURRENT_USER\Software\Wine\DllOverrides' /v $1 /f > /dev/null 2>&1
if [ $? -ne 0 ]; then
echo "Failed to remove override for $1"
fi
}
# copy or link dxvk dll, back up original file
installFile() {
dstfile="${1}/${3}.dll"
srcfile="${basedir}/${2}/${3}.dll"
if [ -f "${srcfile}.so" ]; then
srcfile="${srcfile}.so"
fi
if ! [ -f "${srcfile}" ]; then
echo "${srcfile}: File not found. Skipping." >&2
return 1
fi
if [ -n "$1" ]; then
if [ -f "${dstfile}" ] || [ -h "${dstfile}" ]; then
if ! [ -f "${dstfile}.old" ]; then
mv -v "${dstfile}" "${dstfile}.old"
else
rm -v "${dstfile}"
fi
$file_cmd "${srcfile}" "${dstfile}"
else
echo "${dstfile}: File not found in wine prefix" >&2
return 1
fi
fi
return 0
}
# remove dxvk dll, restore original file
uninstallFile() {
dstfile="${1}/${3}.dll"
srcfile="${basedir}/${2}/${3}.dll"
if [ -f "${srcfile}.so" ]; then
srcfile="${srcfile}.so"
fi
if ! [ -f "${srcfile}" ]; then
echo "${srcfile}: File not found. Skipping." >&2
return 1
fi
if ! [ -f "${dstfile}" ] && ! [ -h "${dstfile}" ]; then
echo "${dstfile}: File not found. Skipping." >&2
return 1
fi
if [ -f "${dstfile}.old" ]; then
rm -v "${dstfile}"
mv -v "${dstfile}.old" "${dstfile}"
return 0
else
return 1
fi
}
install() {
installFile "$win64_sys_path" "$dxvk_lib64" "$1"
inst64_ret="$?"
inst32_ret=-1
if $wow64; then
installFile "$win32_sys_path" "$dxvk_lib32" "$1"
inst32_ret="$?"
fi
if (( ($inst32_ret == 0) || ($inst64_ret == 0) )); then
overrideDll "$1"
fi
}
uninstall() {
uninstallFile "$win64_sys_path" "$dxvk_lib64" "$1"
uninst64_ret="$?"
uninst32_ret=-1
if $wow64; then
uninstallFile "$win32_sys_path" "$dxvk_lib32" "$1"
uninst32_ret="$?"
fi
if (( ($uninst32_ret == 0) || ($uninst64_ret == 0) )); then
restoreDll "$1"
fi
}
# skip dxgi during install if not explicitly
# enabled, but always try to uninstall it
if $with_dxgi || [ "$action" == "uninstall" ]; then
$action dxgi
fi
$action d3d9
$action d3d10core
$action d3d11

View File

@ -9,10 +9,14 @@ extern "C" {
HRESULT __stdcall D3D11CoreCreateDevice(
IDXGIFactory* pFactory,
IDXGIAdapter* pAdapter,
D3D_DRIVER_TYPE DriverType,
HMODULE Software,
UINT Flags,
const D3D_FEATURE_LEVEL* pFeatureLevels,
UINT FeatureLevels,
ID3D11Device** ppDevice);
UINT SDKVersion,
ID3D11Device** ppDevice,
D3D_FEATURE_LEVEL* pFeatureLevel);
DLLEXPORT HRESULT __stdcall D3D10CoreCreateDevice(
@ -31,8 +35,8 @@ extern "C" {
if (FAILED(hr))
return hr;
hr = D3D11CoreCreateDevice(pFactory, pAdapter,
Flags, &FeatureLevel, 1, &d3d11Device);
hr = D3D11CoreCreateDevice(pFactory, pAdapter, D3D_DRIVER_TYPE_UNKNOWN,
nullptr, Flags, &FeatureLevel, 1, D3D11_SDK_VERSION, &d3d11Device, nullptr);
if (FAILED(hr))
return hr;

View File

@ -7,14 +7,17 @@ d3d10_core_src = [
d3d10_core_ld_args = []
d3d10_core_link_depends = []
if platform != 'windows'
if platform == 'windows'
d3d10_d3d11_dep = lib_d3d11
else
d3d10_core_ld_args += [ '-Wl,--version-script', join_paths(meson.current_source_dir(), 'd3d10core.sym') ]
d3d10_core_link_depends += files('d3d10core.sym')
d3d10_d3d11_dep = d3d11_dep
endif
d3d10_core_dll = shared_library('d3d10core'+dll_ext, d3d10_core_src, d3d10_core_res,
name_prefix : dxvk_name_prefix,
dependencies : [ d3d11_dep ],
dependencies : [ d3d10_d3d11_dep ],
include_directories : dxvk_include_path,
install : true,
vs_module_defs : 'd3d10core'+def_spec_ext,

View File

@ -58,8 +58,11 @@ namespace dxvk {
return S_OK;
}
Logger::warn("D3D11BlendState::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
if (logQueryInterfaceError(__uuidof(ID3D11BlendState), riid)) {
Logger::warn("D3D11BlendState::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
}
return E_NOINTERFACE;
}

View File

@ -8,10 +8,11 @@ namespace dxvk {
D3D11Buffer::D3D11Buffer(
D3D11Device* pDevice,
const D3D11_BUFFER_DESC* pDesc)
const D3D11_BUFFER_DESC* pDesc,
const D3D11_ON_12_RESOURCE_INFO* p11on12Info)
: D3D11DeviceChild<ID3D11Buffer>(pDevice),
m_desc (*pDesc),
m_resource (this),
m_resource (this, pDevice),
m_d3d10 (this) {
DxvkBufferCreateInfo info;
info.flags = 0;
@ -83,17 +84,27 @@ namespace dxvk {
info.access |= VK_ACCESS_HOST_WRITE_BIT;
}
if (!(pDesc->MiscFlags & D3D11_RESOURCE_MISC_TILE_POOL)) {
if (p11on12Info) {
m_11on12 = *p11on12Info;
DxvkBufferImportInfo importInfo;
importInfo.buffer = VkBuffer(m_11on12.VulkanHandle);
importInfo.offset = m_11on12.VulkanOffset;
if (m_desc.CPUAccessFlags)
m_11on12.Resource->Map(0, nullptr, &importInfo.mapPtr);
m_buffer = m_parent->GetDXVKDevice()->importBuffer(info, importInfo, GetMemoryFlags());
m_mapped = m_buffer->getSliceHandle();
m_mapMode = DetermineMapMode();
} else if (!(pDesc->MiscFlags & D3D11_RESOURCE_MISC_TILE_POOL)) {
// Create the buffer and set the entire buffer slice as mapped,
// so that we only have to update it when invalidating the buffer
m_buffer = m_parent->GetDXVKDevice()->createBuffer(info, GetMemoryFlags());
m_mapped = m_buffer->getSliceHandle();
m_mapMode = DetermineMapMode();
// For Stream Output buffers we need a counter
if (pDesc->BindFlags & D3D11_BIND_STREAM_OUTPUT)
m_soCounter = CreateSoCounterBuffer();
} else {
m_sparseAllocator = m_parent->GetDXVKDevice()->createSparsePageAllocator();
m_sparseAllocator->setCapacity(info.size / SparseMemoryPageSize);
@ -101,11 +112,16 @@ namespace dxvk {
m_mapped = DxvkBufferSliceHandle();
m_mapMode = D3D11_COMMON_BUFFER_MAP_MODE_NONE;
}
// For Stream Output buffers we need a counter
if (pDesc->BindFlags & D3D11_BIND_STREAM_OUTPUT)
m_soCounter = CreateSoCounterBuffer();
}
D3D11Buffer::~D3D11Buffer() {
if (m_desc.CPUAccessFlags && m_11on12.Resource != nullptr)
m_11on12.Resource->Unmap(0, nullptr);
}
@ -138,8 +154,11 @@ namespace dxvk {
return S_OK;
}
Logger::warn("D3D11Buffer::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
if (logQueryInterfaceError(__uuidof(ID3D11Buffer), riid)) {
Logger::warn("D3D11Buffer::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
}
return E_NOINTERFACE;
}
@ -238,6 +257,36 @@ namespace dxvk {
}
HRESULT D3D11Buffer::GetDescFromD3D12(
ID3D12Resource* pResource,
const D3D11_RESOURCE_FLAGS* pResourceFlags,
D3D11_BUFFER_DESC* pBufferDesc) {
D3D12_RESOURCE_DESC desc12 = pResource->GetDesc();
pBufferDesc->ByteWidth = desc12.Width;
pBufferDesc->Usage = D3D11_USAGE_DEFAULT;
pBufferDesc->BindFlags = D3D11_BIND_SHADER_RESOURCE;
pBufferDesc->MiscFlags = 0;
pBufferDesc->CPUAccessFlags = 0;
pBufferDesc->StructureByteStride = 0;
if (desc12.Flags & D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET)
pBufferDesc->BindFlags |= D3D11_BIND_RENDER_TARGET;
if (desc12.Flags & D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS)
pBufferDesc->BindFlags |= D3D11_BIND_UNORDERED_ACCESS;
if (pResourceFlags) {
pBufferDesc->BindFlags = pResourceFlags->BindFlags;
pBufferDesc->MiscFlags |= pResourceFlags->MiscFlags;
pBufferDesc->CPUAccessFlags = pResourceFlags->CPUAccessFlags;
pBufferDesc->StructureByteStride = pResourceFlags->StructureByteStride;
}
return S_OK;
}
BOOL D3D11Buffer::CheckFormatFeatureSupport(
VkFormat Format,
VkFormatFeatureFlags2 Features) const {
@ -290,6 +339,7 @@ namespace dxvk {
|| (m_parent->GetOptions()->cachedDynamicResources & m_desc.BindFlags);
if ((memoryFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) && useCached) {
memoryFlags &= ~VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
memoryFlags |= VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
| VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
}

View File

@ -7,6 +7,7 @@
#include "d3d11_device_child.h"
#include "d3d11_interfaces.h"
#include "d3d11_on_12.h"
#include "d3d11_resource.h"
namespace dxvk {
@ -41,7 +42,9 @@ namespace dxvk {
D3D11Buffer(
D3D11Device* pDevice,
const D3D11_BUFFER_DESC* pDesc);
const D3D11_BUFFER_DESC* pDesc,
const D3D11_ON_12_RESOURCE_INFO* p11on12Info);
~D3D11Buffer();
HRESULT STDMETHODCALLTYPE QueryInterface(
@ -142,6 +145,14 @@ namespace dxvk {
: DxvkCsThread::SynchronizeAll;
}
/**
* \brief Retrieves D3D11on12 resource info
* \returns 11on12 resource info
*/
D3D11_ON_12_RESOURCE_INFO Get11on12Info() const {
return m_11on12;
}
/**
* \brief Normalizes buffer description
*
@ -151,9 +162,23 @@ namespace dxvk {
static HRESULT NormalizeBufferProperties(
D3D11_BUFFER_DESC* pDesc);
/**
* \brief Initializes D3D11 buffer description from D3D12
*
* \param [in] pResource D3D12 resource
* \param [in] pResourceFlags D3D11 flag overrides
* \param [out] pBufferDesc D3D11 buffer description
* \returns \c S_OK if the parameters are valid
*/
static HRESULT GetDescFromD3D12(
ID3D12Resource* pResource,
const D3D11_RESOURCE_FLAGS* pResourceFlags,
D3D11_BUFFER_DESC* pBufferDesc);
private:
D3D11_BUFFER_DESC m_desc;
D3D11_ON_12_RESOURCE_INFO m_11on12;
D3D11_COMMON_BUFFER_MAP_MODE m_mapMode;
Rc<DxvkBuffer> m_buffer;

View File

@ -28,8 +28,11 @@ namespace dxvk {
return S_OK;
}
Logger::warn("D3D11ClassLinkage::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
if (logQueryInterfaceError(__uuidof(ID3D11ClassLinkage), riid)) {
Logger::warn("D3D11ClassLinkage::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
}
return E_NOINTERFACE;
}

View File

@ -30,8 +30,11 @@ namespace dxvk {
return S_OK;
}
Logger::warn("D3D11CommandList::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
if (logQueryInterfaceError(__uuidof(ID3D11CommandList), riid)) {
Logger::warn("D3D11CommandList::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
}
return E_NOINTERFACE;
}
@ -41,54 +44,79 @@ namespace dxvk {
}
void D3D11CommandList::AddChunk(DxvkCsChunkRef&& Chunk) {
m_chunks.push_back(std::move(Chunk));
}
void D3D11CommandList::AddQuery(D3D11Query* pQuery) {
m_queries.emplace_back(pQuery);
}
void D3D11CommandList::EmitToCommandList(ID3D11CommandList* pCommandList) {
auto cmdList = static_cast<D3D11CommandList*>(pCommandList);
for (const auto& chunk : m_chunks)
cmdList->m_chunks.push_back(chunk);
for (const auto& query : m_queries)
cmdList->m_queries.push_back(query);
for (const auto& resource : m_resources)
cmdList->m_resources.push_back(resource);
MarkSubmitted();
uint64_t D3D11CommandList::AddChunk(DxvkCsChunkRef&& Chunk) {
m_chunks.push_back(std::move(Chunk));
return m_chunks.size() - 1;
}
uint64_t D3D11CommandList::EmitToCsThread(DxvkCsThread* CsThread) {
uint64_t seq = 0;
uint64_t D3D11CommandList::AddCommandList(
D3D11CommandList* pCommandList) {
// This will be the chunk ID of the first chunk
// added, for the purpose of resource tracking.
uint64_t baseChunkId = m_chunks.size();
for (const auto& chunk : pCommandList->m_chunks)
m_chunks.push_back(chunk);
for (const auto& query : pCommandList->m_queries)
m_queries.push_back(query);
for (const auto& resource : pCommandList->m_resources) {
TrackedResource entry = resource;
entry.chunkId += baseChunkId;
m_resources.push_back(std::move(entry));
}
pCommandList->MarkSubmitted();
// Return ID of the last chunk added. The command list
// added can never be empty, so do not handle zero.
return m_chunks.size() - 1;
}
void D3D11CommandList::EmitToCsThread(
const D3D11ChunkDispatchProc& DispatchProc) {
for (const auto& query : m_queries)
query->DoDeferredEnd();
for (const auto& chunk : m_chunks)
seq = CsThread->dispatchChunk(DxvkCsChunkRef(chunk));
for (const auto& resource : m_resources)
TrackResourceSequenceNumber(resource, seq);
for (size_t i = 0, j = 0; i < m_chunks.size(); i++) {
// If there are resources to track for the current chunk,
// use a strong flush hint to dispatch GPU work quickly.
GpuFlushType flushType = GpuFlushType::ImplicitWeakHint;
if (j < m_resources.size() && m_resources[j].chunkId == i)
flushType = GpuFlushType::ImplicitStrongHint;
// Dispatch the chunk and capture its sequence number
uint64_t seq = DispatchProc(DxvkCsChunkRef(m_chunks[i]), flushType);
// Track resource sequence numbers for the added chunk
while (j < m_resources.size() && m_resources[j].chunkId == i)
TrackResourceSequenceNumber(m_resources[j++].ref, seq);
}
MarkSubmitted();
return seq;
}
void D3D11CommandList::TrackResourceUsage(
ID3D11Resource* pResource,
D3D11_RESOURCE_DIMENSION ResourceType,
UINT Subresource) {
m_resources.emplace_back(pResource, Subresource, ResourceType);
UINT Subresource,
uint64_t ChunkId) {
TrackedResource entry;
entry.ref = D3D11ResourceRef(pResource, Subresource, ResourceType);
entry.chunkId = ChunkId;
m_resources.push_back(std::move(entry));
}
@ -96,7 +124,6 @@ namespace dxvk {
const D3D11ResourceRef& Resource,
uint64_t Seq) {
ID3D11Resource* iface = Resource.Get();
UINT subresource = Resource.GetSubresource();
switch (Resource.GetType()) {
case D3D11_RESOURCE_DIMENSION_UNKNOWN:
@ -109,17 +136,17 @@ namespace dxvk {
case D3D11_RESOURCE_DIMENSION_TEXTURE1D: {
auto impl = static_cast<D3D11Texture1D*>(iface)->GetCommonTexture();
impl->TrackSequenceNumber(subresource, Seq);
impl->TrackSequenceNumber(Resource.GetSubresource(), Seq);
} break;
case D3D11_RESOURCE_DIMENSION_TEXTURE2D: {
auto impl = static_cast<D3D11Texture2D*>(iface)->GetCommonTexture();
impl->TrackSequenceNumber(subresource, Seq);
impl->TrackSequenceNumber(Resource.GetSubresource(), Seq);
} break;
case D3D11_RESOURCE_DIMENSION_TEXTURE3D: {
auto impl = static_cast<D3D11Texture3D*>(iface)->GetCommonTexture();
impl->TrackSequenceNumber(subresource, Seq);
impl->TrackSequenceNumber(Resource.GetSubresource(), Seq);
} break;
}
}

View File

@ -1,9 +1,13 @@
#pragma once
#include <functional>
#include "d3d11_context.h"
namespace dxvk {
using D3D11ChunkDispatchProc = std::function<uint64_t (DxvkCsChunkRef&&, GpuFlushType)>;
class D3D11CommandList : public D3D11DeviceChild<ID3D11CommandList> {
public:
@ -20,30 +24,36 @@ namespace dxvk {
UINT STDMETHODCALLTYPE GetContextFlags() final;
void AddChunk(
DxvkCsChunkRef&& Chunk);
void AddQuery(
D3D11Query* pQuery);
void EmitToCommandList(
ID3D11CommandList* pCommandList);
uint64_t EmitToCsThread(
DxvkCsThread* CsThread);
uint64_t AddChunk(
DxvkCsChunkRef&& Chunk);
uint64_t AddCommandList(
D3D11CommandList* pCommandList);
void EmitToCsThread(
const D3D11ChunkDispatchProc& DispatchProc);
void TrackResourceUsage(
ID3D11Resource* pResource,
D3D11_RESOURCE_DIMENSION ResourceType,
UINT Subresource);
UINT Subresource,
uint64_t ChunkId);
private:
UINT const m_contextFlags;
struct TrackedResource {
D3D11ResourceRef ref;
uint64_t chunkId;
};
UINT m_contextFlags;
std::vector<DxvkCsChunkRef> m_chunks;
std::vector<Com<D3D11Query, false>> m_queries;
std::vector<D3D11ResourceRef> m_resources;
std::vector<TrackedResource> m_resources;
std::atomic<bool> m_submitted = { false };
std::atomic<bool> m_warned = { false };

View File

@ -61,8 +61,11 @@ namespace dxvk {
return S_OK;
}
Logger::warn("D3D11DeviceContext::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
if (logQueryInterfaceError(__uuidof(ID3D11DeviceContext), riid)) {
Logger::warn("D3D11DeviceContext::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
}
return E_NOINTERFACE;
}
@ -329,13 +332,14 @@ namespace dxvk {
if (!buf || !uav)
return;
auto counterSlice = uav->GetCounterSlice();
if (!counterSlice.defined())
auto counterView = uav->GetCounterView();
if (counterView == nullptr)
return;
EmitCs([
cDstSlice = buf->GetBufferSlice(DstAlignedByteOffset),
cSrcSlice = std::move(counterSlice)
cSrcSlice = counterView->slice()
] (DxvkContext* ctx) {
ctx->copyBuffer(
cDstSlice.buffer(),
@ -382,11 +386,16 @@ namespace dxvk {
const UINT Values[4]) {
D3D10DeviceLock lock = LockContext();
auto uav = static_cast<D3D11UnorderedAccessView*>(pUnorderedAccessView);
if (!uav)
if (!pUnorderedAccessView)
return;
Com<ID3D11UnorderedAccessView> qiUav;
if (FAILED(pUnorderedAccessView->QueryInterface(IID_PPV_ARGS(&qiUav))))
return;
auto uav = static_cast<D3D11UnorderedAccessView*>(qiUav.ptr());
// Gather UAV format info. We'll use this to determine
// whether we need to create a temporary view or not.
D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc;
@ -402,15 +411,22 @@ namespace dxvk {
VkClearValue clearValue;
// R11G11B10 is a special case since there's no corresponding
// integer format with the same bit layout. Use R32 instead.
if (uavFormat == VK_FORMAT_B10G11R11_UFLOAT_PACK32) {
if (uavDesc.Format == DXGI_FORMAT_R11G11B10_FLOAT) {
// R11G11B10 is a special case since there's no corresponding
// integer format with the same bit layout. Use R32 instead.
clearValue.color.uint32[0] = ((Values[0] & 0x7FF) << 0)
| ((Values[1] & 0x7FF) << 11)
| ((Values[2] & 0x3FF) << 22);
clearValue.color.uint32[1] = 0;
clearValue.color.uint32[2] = 0;
clearValue.color.uint32[3] = 0;
} else if (uavDesc.Format == DXGI_FORMAT_A8_UNORM) {
// We need to use R8_UINT to clear A8_UNORM images,
// so remap the alpha component to the red channel.
clearValue.color.uint32[0] = Values[3];
clearValue.color.uint32[1] = 0;
clearValue.color.uint32[2] = 0;
clearValue.color.uint32[3] = 0;
} else {
clearValue.color.uint32[0] = Values[0];
clearValue.color.uint32[1] = Values[1];
@ -912,6 +928,34 @@ namespace dxvk {
const void* pSrcData,
UINT SrcRowPitch,
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,
pSrcData, SrcRowPitch, SrcDepthPitch, 0);
}
@ -2193,9 +2237,6 @@ namespace dxvk {
ID3D11DepthStencilView* pDepthStencilView) {
D3D10DeviceLock lock = LockContext();
if constexpr (!IsDeferred)
GetTypedContext()->FlushImplicit(true);
SetRenderTargetsAndUnorderedAccessViews(
NumViews, ppRenderTargetViews, pDepthStencilView,
NumViews, 0, nullptr, nullptr);
@ -2213,9 +2254,6 @@ namespace dxvk {
const UINT* pUAVInitialCounts) {
D3D10DeviceLock lock = LockContext();
if constexpr (!IsDeferred)
GetTypedContext()->FlushImplicit(true);
SetRenderTargetsAndUnorderedAccessViews(
NumRTVs, ppRenderTargetViews, pDepthStencilView,
UAVStartSlot, NumUAVs, ppUnorderedAccessViews, pUAVInitialCounts);
@ -2261,6 +2299,10 @@ namespace dxvk {
ApplyDepthStencilState();
}
// The D3D11 runtime only appears to store the low 8 bits,
// and some games rely on this behaviour. Do the same here.
StencilRef &= 0xFF;
if (m_state.om.stencilRef != StencilRef) {
m_state.om.stencilRef = StencilRef;
ApplyStencilRef();
@ -2628,6 +2670,8 @@ namespace dxvk {
ID3D11Buffer* pBuffer,
UINT64 BufferStartOffsetInBytes,
UINT Flags) {
D3D10DeviceLock lock = LockContext();
if (!pTiledResource || !pBuffer)
return;
@ -2658,11 +2702,13 @@ namespace dxvk {
const D3D11_TILED_RESOURCE_COORDINATE* pSourceRegionCoordinate,
const D3D11_TILE_REGION_SIZE* pTileRegionSize,
UINT Flags) {
D3D10DeviceLock lock = LockContext();
if (!pDestTiledResource || !pSourceTiledResource)
return E_INVALIDARG;
if constexpr (!IsDeferred)
GetTypedContext()->FlushImplicit(false);
GetTypedContext()->ConsiderFlush(GpuFlushType::ImplicitWeakHint);
DxvkSparseBindInfo bindInfo;
bindInfo.dstResource = GetPagedResource(pDestTiledResource);
@ -2736,6 +2782,8 @@ namespace dxvk {
HRESULT STDMETHODCALLTYPE D3D11CommonContext<ContextType>::ResizeTilePool(
ID3D11Buffer* pTilePool,
UINT64 NewSizeInBytes) {
D3D10DeviceLock lock = LockContext();
if (NewSizeInBytes % SparseMemoryPageSize)
return E_INVALIDARG;
@ -2761,6 +2809,8 @@ namespace dxvk {
void STDMETHODCALLTYPE D3D11CommonContext<ContextType>::TiledResourceBarrier(
ID3D11DeviceChild* pTiledResourceOrViewAccessBeforeBarrier,
ID3D11DeviceChild* pTiledResourceOrViewAccessAfterBarrier) {
D3D10DeviceLock lock = LockContext();
DxvkGlobalPipelineBarrier srcBarrier = GetTiledResourceDependency(pTiledResourceOrViewAccessBeforeBarrier);
DxvkGlobalPipelineBarrier dstBarrier = GetTiledResourceDependency(pTiledResourceOrViewAccessAfterBarrier);
@ -2789,11 +2839,13 @@ namespace dxvk {
const UINT* pRangeTileOffsets,
const UINT* pRangeTileCounts,
UINT Flags) {
D3D10DeviceLock lock = LockContext();
if (!pTiledResource || !NumRegions || !NumRanges)
return E_INVALIDARG;
if constexpr (!IsDeferred)
GetTypedContext()->FlushImplicit(false);
GetTypedContext()->ConsiderFlush(GpuFlushType::ImplicitWeakHint);
// Find sparse allocator if the tile pool is defined
DxvkSparseBindInfo bindInfo;
@ -2942,6 +2994,8 @@ namespace dxvk {
const D3D11_TILE_REGION_SIZE* pDestTileRegionSize,
const void* pSourceTileData,
UINT Flags) {
D3D10DeviceLock lock = LockContext();
if (!pDestTiledResource || !pSourceTileData)
return;
@ -3358,7 +3412,7 @@ namespace dxvk {
ctx->bindShader<stage>(
Forwarder::move(cShader));
ctx->bindResourceBuffer(stage, slotId,
ctx->bindUniformBuffer(stage, slotId,
Forwarder::move(cBuffer));
});
} else {
@ -3369,14 +3423,30 @@ namespace dxvk {
D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT);
ctx->bindShader<stage>(nullptr);
ctx->bindResourceBuffer(stage, slotId, DxvkBufferSlice());
ctx->bindUniformBuffer(stage, slotId, DxvkBufferSlice());
});
}
}
static VkDepthBiasRepresentationEXT FormatToDepthBiasRepresentation(DXGI_FORMAT format) {
switch (format) {
default:
case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
case DXGI_FORMAT_D32_FLOAT:
return VK_DEPTH_BIAS_REPRESENTATION_LEAST_REPRESENTABLE_VALUE_FORMAT_EXT;
case DXGI_FORMAT_D24_UNORM_S8_UINT:
case DXGI_FORMAT_D16_UNORM:
return VK_DEPTH_BIAS_REPRESENTATION_LEAST_REPRESENTABLE_VALUE_FORCE_UNORM_EXT;
}
}
template<typename ContextType>
void D3D11CommonContext<ContextType>::BindFramebuffer() {
DxvkDepthBiasRepresentation depthBiasRepresentation =
{ VK_DEPTH_BIAS_REPRESENTATION_LEAST_REPRESENTABLE_VALUE_FORMAT_EXT,
m_device->features().extDepthBiasControl.depthBiasExact };
DxvkRenderTargets attachments;
uint32_t sampleCount = 0;
@ -3397,12 +3467,17 @@ namespace dxvk {
m_state.om.dsv->GetImageView(),
m_state.om.dsv->GetRenderLayout() };
sampleCount = m_state.om.dsv->GetSampleCount();
if (m_device->features().extDepthBiasControl.leastRepresentableValueForceUnormRepresentation)
depthBiasRepresentation.depthBiasRepresentation = FormatToDepthBiasRepresentation(m_state.om.dsv->GetViewFormat());
}
// Create and bind the framebuffer object to the context
EmitCs([
cAttachments = std::move(attachments)
cAttachments = std::move(attachments),
cRepresentation = depthBiasRepresentation
] (DxvkContext* ctx) mutable {
ctx->setDepthBiasRepresentation(cRepresentation);
ctx->bindRenderTargets(Forwarder::move(cAttachments), 0u);
});
@ -3581,7 +3656,7 @@ namespace dxvk {
cBufferSlice = pBuffer->GetBufferSlice(16 * Offset, 16 * Length)
] (DxvkContext* ctx) mutable {
VkShaderStageFlagBits stage = GetShaderStage(ShaderStage);
ctx->bindResourceBuffer(stage, cSlotId,
ctx->bindUniformBuffer(stage, cSlotId,
Forwarder::move(cBufferSlice));
});
} else {
@ -3589,7 +3664,7 @@ namespace dxvk {
cSlotId = Slot
] (DxvkContext* ctx) {
VkShaderStageFlagBits stage = GetShaderStage(ShaderStage);
ctx->bindResourceBuffer(stage, cSlotId, DxvkBufferSlice());
ctx->bindUniformBuffer(stage, cSlotId, DxvkBufferSlice());
});
}
}
@ -3607,7 +3682,7 @@ namespace dxvk {
cLength = 16 * Length
] (DxvkContext* ctx) {
VkShaderStageFlagBits stage = GetShaderStage(ShaderStage);
ctx->bindResourceBufferRange(stage, cSlotId, cOffset, cLength);
ctx->bindUniformBufferRange(stage, cSlotId, cOffset, cLength);
});
}
@ -3686,25 +3761,27 @@ namespace dxvk {
cUavSlotId = UavSlot,
cCtrSlotId = CtrSlot,
cBufferView = pUav->GetBufferView(),
cCounterSlice = pUav->GetCounterSlice(),
cCounterView = pUav->GetCounterView(),
cCounterValue = Counter
] (DxvkContext* ctx) mutable {
VkShaderStageFlags stages = ShaderStage == DxbcProgramType::ComputeShader
? VK_SHADER_STAGE_COMPUTE_BIT
: VK_SHADER_STAGE_ALL_GRAPHICS;
if (cCounterSlice.defined() && cCounterValue != ~0u) {
if (cCounterView != nullptr && cCounterValue != ~0u) {
auto counterSlice = cCounterView->slice();
ctx->updateBuffer(
cCounterSlice.buffer(),
cCounterSlice.offset(),
counterSlice.buffer(),
counterSlice.offset(),
sizeof(uint32_t),
&cCounterValue);
}
ctx->bindResourceBufferView(stages, cUavSlotId,
Forwarder::move(cBufferView));
ctx->bindResourceBuffer(stages, cCtrSlotId,
Forwarder::move(cCounterSlice));
ctx->bindResourceBufferView(stages, cCtrSlotId,
Forwarder::move(cCounterView));
});
} else {
EmitCs([
@ -3718,7 +3795,7 @@ namespace dxvk {
ctx->bindResourceImageView(stages, cUavSlotId,
Forwarder::move(cImageView));
ctx->bindResourceBuffer(stages, cCtrSlotId, DxvkBufferSlice());
ctx->bindResourceBufferView(stages, cCtrSlotId, nullptr);
});
}
} else {
@ -3731,7 +3808,7 @@ namespace dxvk {
: VK_SHADER_STAGE_ALL_GRAPHICS;
ctx->bindResourceImageView(stages, cUavSlotId, nullptr);
ctx->bindResourceBuffer(stages, cCtrSlotId, DxvkBufferSlice());
ctx->bindResourceBufferView(stages, cCtrSlotId, nullptr);
});
}
}
@ -4371,10 +4448,10 @@ namespace dxvk {
// Unbind constant buffers, including the shader's ICB
auto cbSlotId = computeConstantBufferBinding(programType, 0);
ctx->bindResourceBuffer(stage, cbSlotId + D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, DxvkBufferSlice());
ctx->bindUniformBuffer(stage, cbSlotId + D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, DxvkBufferSlice());
for (uint32_t j = 0; j < cUsedBindings.stages[i].cbvCount; j++)
ctx->bindResourceBuffer(stage, cbSlotId + j, DxvkBufferSlice());
ctx->bindUniformBuffer(stage, cbSlotId + j, DxvkBufferSlice());
// Unbind shader resource views
auto srvSlotId = computeSrvBinding(programType, 0);
@ -4400,7 +4477,7 @@ namespace dxvk {
for (uint32_t j = 0; j < cUsedBindings.stages[i].uavCount; j++) {
ctx->bindResourceImageView(stages, uavSlotId, nullptr);
ctx->bindResourceBuffer(stages, ctrSlotId, DxvkBufferSlice());
ctx->bindResourceBufferView(stages, ctrSlotId, nullptr);
}
}
}
@ -4902,8 +4979,14 @@ namespace dxvk {
}
}
if (needsUpdate)
if (needsUpdate) {
BindFramebuffer();
if constexpr (!IsDeferred) {
// Doing this makes it less likely to flush during render passes
GetTypedContext()->ConsiderFlush(GpuFlushType::ImplicitWeakHint);
}
}
}
@ -5358,6 +5441,7 @@ namespace dxvk {
pRsState->conservativeMode = VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT;
pRsState->sampleCount = 0;
pRsState->flatShading = VK_FALSE;
pRsState->lineMode = VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT;
}

View File

@ -10,6 +10,8 @@
#include "../d3d10/d3d10_multithread.h"
#include "../util/util_flush.h"
#include "d3d11_annotation.h"
#include "d3d11_buffer.h"
#include "d3d11_cmd.h"
@ -1064,27 +1066,35 @@ namespace dxvk {
DxvkMultisampleState* pMsState,
UINT SampleMask);
template<typename Cmd>
template<bool AllowFlush = !IsDeferred, typename Cmd>
void EmitCs(Cmd&& command) {
m_cmdData = nullptr;
if (unlikely(!m_csChunk->push(command))) {
GetTypedContext()->EmitCsChunk(std::move(m_csChunk));
m_csChunk = AllocCsChunk();
if constexpr (AllowFlush)
GetTypedContext()->ConsiderFlush(GpuFlushType::ImplicitWeakHint);
m_csChunk->push(command);
}
}
template<typename M, typename Cmd, typename... Args>
template<typename M, bool AllowFlush = !IsDeferred, typename Cmd, typename... Args>
M* EmitCsCmd(Cmd&& command, Args&&... args) {
M* data = m_csChunk->pushCmd<M, Cmd, Args...>(
command, std::forward<Args>(args)...);
if (unlikely(!data)) {
GetTypedContext()->EmitCsChunk(std::move(m_csChunk));
m_csChunk = AllocCsChunk();
if constexpr (AllowFlush)
GetTypedContext()->ConsiderFlush(GpuFlushType::ImplicitWeakHint);
// We must record this command after the potential
// flush since the caller may still access the data
data = m_csChunk->pushCmd<M, Cmd, Args...>(
command, std::forward<Args>(args)...);
}
@ -1120,7 +1130,7 @@ namespace dxvk {
if (likely(pBuffer != nullptr))
bufferSize = static_cast<D3D11Buffer*>(pBuffer)->Desc()->ByteWidth;
return bufferSize >= Offset + Size;
return uint64_t(bufferSize) >= uint64_t(Offset) + uint64_t(Size);
}
private:

View File

@ -148,8 +148,9 @@ namespace dxvk {
// Record any chunks from the given command list into the
// current command list and deal with context state
auto commandList = static_cast<D3D11CommandList*>(pCommandList);
commandList->EmitToCommandList(m_commandList.ptr());
m_chunkId = m_commandList->AddCommandList(commandList);
// Restore deferred context state
if (RestoreContextState)
RestoreCommandListState();
else
@ -166,7 +167,8 @@ namespace dxvk {
FinalizeQueries();
// Clean up command list state so that the any state changed
// by this command list does not affect the calling context
// by this command list does not affect the calling context.
// This also ensures that the command list is never empty.
ResetCommandListState();
// Make sure all commands are visible to the command list
@ -180,6 +182,7 @@ namespace dxvk {
// Any use of ExecuteCommandList will reset command list state
// before the command list is actually executed.
m_commandList = CreateCommandList();
m_chunkId = 0;
if (RestoreDeferredContextState)
RestoreCommandListState();
@ -388,7 +391,12 @@ namespace dxvk {
void D3D11DeferredContext::EmitCsChunk(DxvkCsChunkRef&& chunk) {
m_commandList->AddChunk(std::move(chunk));
m_chunkId = m_commandList->AddChunk(std::move(chunk));
}
uint64_t D3D11DeferredContext::GetCurrentChunkId() const {
return m_csChunk->empty() ? m_chunkId : m_chunkId + 1;
}
@ -398,14 +406,15 @@ namespace dxvk {
m_commandList->TrackResourceUsage(
pResource->GetInterface(),
pResource->GetDimension(),
Subresource);
Subresource, GetCurrentChunkId());
}
void D3D11DeferredContext::TrackBufferSequenceNumber(
D3D11Buffer* pResource) {
m_commandList->TrackResourceUsage(
pResource, D3D11_RESOURCE_DIMENSION_BUFFER, 0);
m_commandList->TrackResourceUsage(pResource,
D3D11_RESOURCE_DIMENSION_BUFFER, 0,
GetCurrentChunkId());
}

View File

@ -96,6 +96,9 @@ namespace dxvk {
// Begun and ended queries, will also be stored in command list
std::vector<Com<D3D11Query, false>> m_queriesBegun;
// Chunk ID within the current command list
uint64_t m_chunkId = 0ull;
HRESULT MapBuffer(
ID3D11Resource* pResource,
D3D11_MAPPED_SUBRESOURCE* pMappedResource);
@ -118,6 +121,8 @@ namespace dxvk {
void EmitCsChunk(DxvkCsChunkRef&& chunk);
uint64_t GetCurrentChunkId() const;
void TrackTextureSequenceNumber(
D3D11CommonTexture* pResource,
UINT Subresource);

View File

@ -18,6 +18,7 @@ namespace dxvk {
: D3D11CommonContext<D3D11ImmediateContext>(pParent, Device, 0, DxvkCsChunkFlag::SingleUse),
m_csThread(Device, Device->createContext(DxvkContextType::Primary)),
m_maxImplicitDiscardSize(pParent->GetOptions()->maxImplicitDiscardSize),
m_submissionFence(new sync::CallbackFence()),
m_multithread(this, false, pParent->GetOptions()->enableContextLock),
m_videoContext(this, Device) {
EmitCs([
@ -48,7 +49,7 @@ namespace dxvk {
if (this_thread::isInModuleDetachment())
return;
Flush();
ExecuteFlush(GpuFlushType::ExplicitFlush, nullptr, true);
SynchronizeCsThread(DxvkCsThread::SynchronizeAll);
SynchronizeDevice();
}
@ -99,7 +100,8 @@ namespace dxvk {
// Ignore the DONOTFLUSH flag here as some games will spin
// on queries without ever flushing the context otherwise.
FlushImplicit(FALSE);
D3D10DeviceLock lock = LockContext();
ConsiderFlush(GpuFlushType::ImplicitSynchronization);
}
return hr;
@ -148,47 +150,33 @@ namespace dxvk {
query->NotifyEnd();
if (query->IsStalling())
Flush();
ExecuteFlush(GpuFlushType::ImplicitSynchronization, nullptr, false);
else if (query->IsEvent())
FlushImplicit(TRUE);
ConsiderFlush(GpuFlushType::ImplicitStrongHint);
}
}
void STDMETHODCALLTYPE D3D11ImmediateContext::Flush() {
Flush1(D3D11_CONTEXT_TYPE_ALL, nullptr);
D3D10DeviceLock lock = LockContext();
ExecuteFlush(GpuFlushType::ExplicitFlush, nullptr, true);
}
void STDMETHODCALLTYPE D3D11ImmediateContext::Flush1(
D3D11_CONTEXT_TYPE ContextType,
HANDLE hEvent) {
m_parent->FlushInitContext();
if (hEvent)
SignalEvent(hEvent);
D3D10DeviceLock lock = LockContext();
if (m_csIsBusy || !m_csChunk->empty()) {
// Add commands to flush the threaded
// context, then flush the command list
EmitCs([] (DxvkContext* ctx) {
ctx->flushCommandList();
});
FlushCsChunk();
// Reset flush timer used for implicit flushes
m_lastFlush = dxvk::high_resolution_clock::now();
m_csIsBusy = false;
}
ExecuteFlush(GpuFlushType::ExplicitFlush, hEvent, true);
}
HRESULT STDMETHODCALLTYPE D3D11ImmediateContext::Signal(
ID3D11Fence* pFence,
UINT64 Value) {
D3D10DeviceLock lock = LockContext();
auto fence = static_cast<D3D11Fence*>(pFence);
if (!fence)
@ -201,7 +189,7 @@ namespace dxvk {
ctx->signalFence(cFence, cValue);
});
Flush();
ExecuteFlush(GpuFlushType::ExplicitFlush, nullptr, true);
return S_OK;
}
@ -209,12 +197,13 @@ namespace dxvk {
HRESULT STDMETHODCALLTYPE D3D11ImmediateContext::Wait(
ID3D11Fence* pFence,
UINT64 Value) {
D3D10DeviceLock lock = LockContext();
auto fence = static_cast<D3D11Fence*>(pFence);
if (!fence)
return E_INVALIDARG;
Flush();
ExecuteFlush(GpuFlushType::ExplicitFlush, nullptr, true);
EmitCs([
cFence = fence->GetFence(),
@ -246,21 +235,27 @@ namespace dxvk {
// As an optimization, flush everything if the
// number of pending draw calls is high enough.
FlushImplicit(FALSE);
// Dispatch command list to the CS thread and
// restore the immediate context's state
uint64_t csSeqNum = commandList->EmitToCsThread(&m_csThread);
m_csSeqNum = std::max(m_csSeqNum, csSeqNum);
ConsiderFlush(GpuFlushType::ImplicitWeakHint);
// Dispatch command list to the CS thread
commandList->EmitToCsThread([this] (DxvkCsChunkRef&& chunk, GpuFlushType flushType) {
EmitCsChunk(std::move(chunk));
// Return the sequence number from before the flush since
// that is actually going to be needed for resource tracking
uint64_t csSeqNum = m_csSeqNum;
// Consider a flush after every chunk in case the app
// submits a very large command list or the GPU is idle
ConsiderFlush(flushType);
return csSeqNum;
});
// Restore the immediate context's state
if (RestoreContextState)
RestoreCommandListState();
else
ResetContextState();
// Mark CS thread as busy so that subsequent
// flush operations get executed correctly.
m_csIsBusy = true;
}
@ -390,8 +385,6 @@ namespace dxvk {
}
if (doInvalidatePreserve) {
FlushImplicit(TRUE);
auto prevSlice = pResource->GetMappedSlice();
auto physSlice = pResource->DiscardSlice();
@ -537,8 +530,6 @@ namespace dxvk {
}
if (doFlags & DoInvalidate) {
FlushImplicit(TRUE);
DxvkBufferSliceHandle prevSlice = pResource->GetMappedSlice(Subresource);
DxvkBufferSliceHandle physSlice = pResource->DiscardSlice(Subresource);
@ -762,6 +753,74 @@ namespace dxvk {
}
void D3D11ImmediateContext::Acquire11on12Resource(
ID3D11Resource* pResource,
VkImageLayout SrcLayout) {
D3D10DeviceLock lock = LockContext();
auto texture = GetCommonTexture(pResource);
auto buffer = GetCommonBuffer(pResource);
if (buffer) {
EmitCs([
cBuffer = buffer->GetBuffer()
] (DxvkContext* ctx) {
ctx->emitBufferBarrier(cBuffer,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
VK_ACCESS_MEMORY_WRITE_BIT | VK_ACCESS_MEMORY_READ_BIT,
cBuffer->info().stages,
cBuffer->info().access);
});
} else if (texture) {
EmitCs([
cImage = texture->GetImage(),
cLayout = SrcLayout
] (DxvkContext* ctx) {
ctx->emitImageBarrier(cImage, cLayout,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
VK_ACCESS_MEMORY_WRITE_BIT | VK_ACCESS_MEMORY_READ_BIT,
cImage->info().layout,
cImage->info().stages,
cImage->info().access);
});
}
}
void D3D11ImmediateContext::Release11on12Resource(
ID3D11Resource* pResource,
VkImageLayout DstLayout) {
D3D10DeviceLock lock = LockContext();
auto texture = GetCommonTexture(pResource);
auto buffer = GetCommonBuffer(pResource);
if (buffer) {
EmitCs([
cBuffer = buffer->GetBuffer()
] (DxvkContext* ctx) {
ctx->emitBufferBarrier(cBuffer,
cBuffer->info().stages,
cBuffer->info().access,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
VK_ACCESS_MEMORY_WRITE_BIT | VK_ACCESS_MEMORY_READ_BIT);
});
} else if (texture) {
EmitCs([
cImage = texture->GetImage(),
cLayout = DstLayout
] (DxvkContext* ctx) {
ctx->emitImageBarrier(cImage,
cImage->info().layout,
cImage->info().stages,
cImage->info().access,
cLayout, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
VK_ACCESS_MEMORY_WRITE_BIT | VK_ACCESS_MEMORY_READ_BIT);
});
}
}
void D3D11ImmediateContext::SynchronizeCsThread(uint64_t SequenceNumber) {
D3D10DeviceLock lock = LockContext();
@ -782,7 +841,7 @@ namespace dxvk {
void D3D11ImmediateContext::EndFrame() {
D3D10DeviceLock lock = LockContext();
EmitCs([] (DxvkContext* ctx) {
EmitCs<false>([] (DxvkContext* ctx) {
ctx->endFrame();
});
}
@ -813,14 +872,14 @@ namespace dxvk {
// We don't have to wait, but misbehaving games may
// still try to spin on `Map` until the resource is
// idle, so we should flush pending commands
FlushImplicit(FALSE);
ConsiderFlush(GpuFlushType::ImplicitSynchronization);
return false;
}
} else {
if (isInUse) {
// Make sure pending commands using the resource get
// executed on the the GPU if we have to wait for it
Flush();
ExecuteFlush(GpuFlushType::ImplicitSynchronization, nullptr, false);
SynchronizeCsThread(SequenceNumber);
m_device->waitForResource(Resource, access);
@ -833,7 +892,6 @@ namespace dxvk {
void D3D11ImmediateContext::EmitCsChunk(DxvkCsChunkRef&& chunk) {
m_csSeqNum = m_csThread.dispatchChunk(std::move(chunk));
m_csIsBusy = true;
}
@ -843,7 +901,7 @@ namespace dxvk {
uint64_t sequenceNumber = GetCurrentSequenceNumber();
pResource->TrackSequenceNumber(Subresource, sequenceNumber);
FlushImplicit(TRUE);
ConsiderFlush(GpuFlushType::ImplicitStrongHint);
}
@ -852,7 +910,7 @@ namespace dxvk {
uint64_t sequenceNumber = GetCurrentSequenceNumber();
pResource->TrackSequenceNumber(sequenceNumber);
FlushImplicit(TRUE);
ConsiderFlush(GpuFlushType::ImplicitStrongHint);
}
@ -864,40 +922,67 @@ namespace dxvk {
}
void D3D11ImmediateContext::FlushImplicit(BOOL StrongHint) {
// Flush only if the GPU is about to go idle, in
// order to keep the number of submissions low.
uint32_t pending = m_device->pendingSubmissions();
if (StrongHint || pending <= MaxPendingSubmits) {
auto now = dxvk::high_resolution_clock::now();
uint32_t delay = MinFlushIntervalUs
+ IncFlushIntervalUs * pending;
// Prevent flushing too often in short intervals.
if (now - m_lastFlush >= std::chrono::microseconds(delay))
Flush();
}
uint64_t D3D11ImmediateContext::GetPendingCsChunks() {
return GetCurrentSequenceNumber() - m_flushSeqNum;
}
void D3D11ImmediateContext::SignalEvent(HANDLE hEvent) {
uint64_t value = ++m_eventCount;
void D3D11ImmediateContext::ConsiderFlush(
GpuFlushType FlushType) {
uint64_t chunkId = GetCurrentSequenceNumber();
uint64_t submissionId = m_submissionFence->value();
if (m_eventSignal == nullptr)
m_eventSignal = new sync::CallbackFence();
if (m_flushTracker.considerFlush(FlushType, chunkId, submissionId))
ExecuteFlush(FlushType, nullptr, false);
}
m_eventSignal->setCallback(value, [hEvent] {
SetEvent(hEvent);
});
EmitCs([
cSignal = m_eventSignal,
cValue = value
void D3D11ImmediateContext::ExecuteFlush(
GpuFlushType FlushType,
HANDLE hEvent,
BOOL Synchronize) {
bool synchronizeSubmission = Synchronize && m_parent->Is11on12Device();
if (synchronizeSubmission)
m_submitStatus.result = VK_NOT_READY;
// Flush init context so that new resources are fully initialized
// before the app can access them in any way. This has to happen
// unconditionally since we may otherwise deadlock on Map.
m_parent->FlushInitContext();
// Exit early if there's nothing to do
if (!GetPendingCsChunks() && !hEvent)
return;
// Signal the submission fence and flush the command list
uint64_t submissionId = ++m_submissionId;
if (hEvent) {
m_submissionFence->setCallback(submissionId, [hEvent] {
SetEvent(hEvent);
});
}
EmitCs<false>([
cSubmissionFence = m_submissionFence,
cSubmissionId = submissionId,
cSubmissionStatus = synchronizeSubmission ? &m_submitStatus : nullptr
] (DxvkContext* ctx) {
ctx->signal(cSignal, cValue);
ctx->signal(cSubmissionFence, cSubmissionId);
ctx->flushCommandList(cSubmissionStatus);
});
FlushCsChunk();
// Notify flush tracker about the flush
m_flushSeqNum = m_csSeqNum;
m_flushTracker.notifyFlush(m_flushSeqNum, submissionId);
// If necessary, block calling thread until the
// Vulkan queue submission is performed.
if (synchronizeSubmission)
m_device->waitForSubmission(&m_submitStatus);
}
}

View File

@ -12,11 +12,12 @@ namespace dxvk {
class D3D11Buffer;
class D3D11CommonTexture;
class D3D11ImmediateContext : public D3D11CommonContext<D3D11ImmediateContext> {
friend class D3D11CommonContext<D3D11ImmediateContext>;
friend class D3D11SwapChain;
friend class D3D11VideoContext;
friend class D3D11DXGIKeyedMutex;
public:
D3D11ImmediateContext(
@ -77,9 +78,21 @@ namespace dxvk {
ID3DDeviceContextState* pState,
ID3DDeviceContextState** ppPreviousState);
void Acquire11on12Resource(
ID3D11Resource* pResource,
VkImageLayout SrcLayout);
void Release11on12Resource(
ID3D11Resource* pResource,
VkImageLayout DstLayout);
void SynchronizeCsThread(
uint64_t SequenceNumber);
D3D10Multithread& GetMultithread() {
return m_multithread;
}
D3D10DeviceLock LockContext() {
return m_multithread.AcquireLock();
}
@ -88,19 +101,20 @@ namespace dxvk {
DxvkCsThread m_csThread;
uint64_t m_csSeqNum = 0ull;
bool m_csIsBusy = false;
Rc<sync::CallbackFence> m_eventSignal;
uint64_t m_eventCount = 0ull;
uint32_t m_mappedImageCount = 0u;
VkDeviceSize m_maxImplicitDiscardSize = 0ull;
dxvk::high_resolution_clock::time_point m_lastFlush
= dxvk::high_resolution_clock::now();
D3D10Multithread m_multithread;
D3D11VideoContext m_videoContext;
Rc<sync::CallbackFence> m_submissionFence;
uint64_t m_submissionId = 0ull;
DxvkSubmitStatus m_submitStatus;
uint64_t m_flushSeqNum = 0ull;
GpuFlushTracker m_flushTracker;
D3D10Multithread m_multithread;
D3D11VideoContext m_videoContext;
Com<D3D11DeviceContextState, false> m_stateObject;
@ -131,21 +145,21 @@ namespace dxvk {
const D3D11_COMMON_TEXTURE_REGION* pRegion);
void UpdateMappedBuffer(
D3D11Buffer* pDstBuffer,
UINT Offset,
UINT Length,
const void* pSrcData,
UINT CopyFlags);
D3D11Buffer* pDstBuffer,
UINT Offset,
UINT Length,
const void* pSrcData,
UINT CopyFlags);
void SynchronizeDevice();
void EndFrame();
bool WaitForResource(
const Rc<DxvkResource>& Resource,
uint64_t SequenceNumber,
D3D11_MAP MapType,
UINT MapFlags);
const Rc<DxvkResource>& Resource,
uint64_t SequenceNumber,
D3D11_MAP MapType,
UINT MapFlags);
void EmitCsChunk(DxvkCsChunkRef&& chunk);
@ -158,10 +172,16 @@ namespace dxvk {
uint64_t GetCurrentSequenceNumber();
void FlushImplicit(BOOL StrongHint);
uint64_t GetPendingCsChunks();
void ConsiderFlush(
GpuFlushType FlushType);
void ExecuteFlush(
GpuFlushType FlushType,
HANDLE hEvent,
BOOL Synchronize);
void SignalEvent(HANDLE hEvent);
};
}

View File

@ -37,12 +37,15 @@ namespace dxvk {
if (riid == __uuidof(ID3D10DeviceChild)
|| riid == __uuidof(ID3D10DepthStencilState)) {
*ppvObject = ref(this);
*ppvObject = ref(&m_d3d10);
return S_OK;
}
Logger::warn("D3D11DepthStencilState::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
if (logQueryInterfaceError(__uuidof(ID3D11DepthStencilState), riid)) {
Logger::warn("D3D11DepthStencilState::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
}
return E_NOINTERFACE;
}

View File

@ -45,10 +45,10 @@ namespace dxvk {
m_dxvkDevice (pContainer->GetDXVKDevice()),
m_dxvkAdapter (m_dxvkDevice->adapter()),
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_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_context = new D3D11ImmediateContext(this, m_dxvkDevice);
m_d3d10Device = new D3D10Device(this, m_context.ptr());
@ -100,7 +100,7 @@ namespace dxvk {
return S_FALSE;
try {
const Com<D3D11Buffer> buffer = new D3D11Buffer(this, &desc);
const Com<D3D11Buffer> buffer = new D3D11Buffer(this, &desc, nullptr);
if (!(desc.MiscFlags & D3D11_RESOURCE_MISC_TILE_POOL))
m_initializer->InitBuffer(buffer.ptr(), pInitialData);
@ -149,7 +149,7 @@ namespace dxvk {
return S_FALSE;
try {
const Com<D3D11Texture1D> texture = new D3D11Texture1D(this, &desc);
const Com<D3D11Texture1D> texture = new D3D11Texture1D(this, &desc, nullptr);
m_initializer->InitTexture(texture->GetCommonTexture(), pInitialData);
*ppTexture1D = texture.ref();
return S_OK;
@ -229,7 +229,7 @@ namespace dxvk {
return S_FALSE;
try {
Com<D3D11Texture2D> texture = new D3D11Texture2D(this, &desc, nullptr);
Com<D3D11Texture2D> texture = new D3D11Texture2D(this, &desc, nullptr, nullptr);
m_initializer->InitTexture(texture->GetCommonTexture(), pInitialData);
*ppTexture2D = texture.ref();
return S_OK;
@ -308,7 +308,7 @@ namespace dxvk {
return S_FALSE;
try {
Com<D3D11Texture3D> texture = new D3D11Texture3D(this, &desc);
Com<D3D11Texture3D> texture = new D3D11Texture3D(this, &desc, nullptr);
m_initializer->InitTexture(texture->GetCommonTexture(), pInitialData);
*ppTexture3D = texture.ref();
return S_OK;
@ -1348,7 +1348,7 @@ namespace dxvk {
m_deviceFeatures = D3D11DeviceFeatures(
m_dxvkDevice->instance(),
m_dxvkDevice->adapter(),
m_featureLevel);
m_d3d11Options, m_featureLevel);
}
if (pChosenFeatureLevel)
@ -1832,6 +1832,11 @@ namespace dxvk {
DXGI_VK_FORMAT_MODE Mode) const {
return m_d3d11Formats.GetFormatFamily(Format, Mode);
}
bool D3D11Device::Is11on12Device() const {
return m_container->Is11on12Device();
}
void D3D11Device::FlushInitContext() {
@ -1948,6 +1953,11 @@ namespace dxvk {
enabled.core.features.shaderFloat64 = supported.core.features.shaderFloat64;
enabled.core.features.shaderInt64 = supported.core.features.shaderInt64;
// Depth bias control
enabled.extDepthBiasControl.depthBiasControl = supported.extDepthBiasControl.depthBiasControl;
enabled.extDepthBiasControl.depthBiasExact = supported.extDepthBiasControl.depthBiasExact;
enabled.extDepthBiasControl.leastRepresentableValueForceUnormRepresentation = supported.extDepthBiasControl.leastRepresentableValueForceUnormRepresentation;
return enabled;
}
@ -2299,10 +2309,14 @@ namespace dxvk {
d3d11Desc.CPUAccessFlags = metadata.CPUAccessFlags;
d3d11Desc.MiscFlags = metadata.MiscFlags;
d3d11Desc.TextureLayout = metadata.TextureLayout;
if ((d3d11Desc.MiscFlags & D3D11_RESOURCE_MISC_SHARED_NTHANDLE) && !(d3d11Desc.MiscFlags & (D3D11_RESOURCE_MISC_SHARED | D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX))) {
Logger::warn("Fixing up wrong MiscFlags");
d3d11Desc.MiscFlags |= D3D11_RESOURCE_MISC_SHARED;
}
// Only 2D textures may be shared
try {
const Com<D3D11Texture2D> texture = new D3D11Texture2D(this, &d3d11Desc, hResource);
const Com<D3D11Texture2D> texture = new D3D11Texture2D(this, &d3d11Desc, nullptr, hResource);
texture->QueryInterface(ReturnedInterface, ppResource);
return S_OK;
}
@ -3019,85 +3033,6 @@ namespace dxvk {
WineDXGISwapChainFactory::WineDXGISwapChainFactory(
D3D11DXGIDevice* pContainer,
D3D11Device* pDevice)
: m_container(pContainer), m_device(pDevice) {
}
ULONG STDMETHODCALLTYPE WineDXGISwapChainFactory::AddRef() {
return m_device->AddRef();
}
ULONG STDMETHODCALLTYPE WineDXGISwapChainFactory::Release() {
return m_device->Release();
}
HRESULT STDMETHODCALLTYPE WineDXGISwapChainFactory::QueryInterface(
REFIID riid,
void** ppvObject) {
return m_device->QueryInterface(riid, ppvObject);
}
HRESULT STDMETHODCALLTYPE WineDXGISwapChainFactory::CreateSwapChainForHwnd(
IDXGIFactory* pFactory,
HWND hWnd,
const DXGI_SWAP_CHAIN_DESC1* pDesc,
const DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pFullscreenDesc,
IDXGIOutput* pRestrictToOutput,
IDXGISwapChain1** ppSwapChain) {
InitReturnPtr(ppSwapChain);
if (!ppSwapChain || !pDesc || !hWnd)
return DXGI_ERROR_INVALID_CALL;
// Make sure the back buffer size is not zero
DXGI_SWAP_CHAIN_DESC1 desc = *pDesc;
wsi::getWindowSize(hWnd,
desc.Width ? nullptr : &desc.Width,
desc.Height ? nullptr : &desc.Height);
// If necessary, set up a default set of
// fullscreen parameters for the swap chain
DXGI_SWAP_CHAIN_FULLSCREEN_DESC fsDesc;
if (pFullscreenDesc) {
fsDesc = *pFullscreenDesc;
} else {
fsDesc.RefreshRate = { 0, 0 };
fsDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
fsDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
fsDesc.Windowed = TRUE;
}
try {
auto vki = m_device->GetDXVKDevice()->adapter()->vki();
// Create surface factory for the window
Com<IDXGIVkSurfaceFactory> surfaceFactory = new DxgiSurfaceFactory(vki->getLoaderProc(), hWnd);
// Create presenter for the device
Com<D3D11SwapChain> presenter = new D3D11SwapChain(
m_container, m_device, surfaceFactory.ptr(), &desc);
// Create the actual swap chain
*ppSwapChain = ref(new DxgiSwapChain(
pFactory, presenter.ptr(), hWnd, &desc, &fsDesc));
return S_OK;
} catch (const DxvkError& e) {
Logger::err(e.message());
return E_INVALIDARG;
}
}
DXGIDXVKDevice::DXGIDXVKDevice(D3D11DXGIDevice* pContainer)
: m_container(pContainer), m_apiVersion(11) {
@ -3136,27 +3071,30 @@ namespace dxvk {
D3D11DXGIDevice::D3D11DXGIDevice(
IDXGIAdapter* pAdapter,
const Rc<DxvkInstance>& pDxvkInstance,
const Rc<DxvkAdapter>& pDxvkAdapter,
ID3D12Device* pD3D12Device,
ID3D12CommandQueue* pD3D12Queue,
Rc<DxvkInstance> pDxvkInstance,
Rc<DxvkAdapter> pDxvkAdapter,
Rc<DxvkDevice> pDxvkDevice,
D3D_FEATURE_LEVEL FeatureLevel,
UINT FeatureFlags)
: m_dxgiAdapter (pAdapter),
m_dxvkInstance (pDxvkInstance),
m_dxvkAdapter (pDxvkAdapter),
m_dxvkDevice (CreateDevice(FeatureLevel)),
m_dxvkDevice (pDxvkDevice),
m_d3d11Device (this, FeatureLevel, FeatureFlags),
m_d3d11DeviceExt(this, &m_d3d11Device),
m_d3d11Interop (this, &m_d3d11Device),
m_d3d11Video (this, &m_d3d11Device),
m_d3d11on12 (this, &m_d3d11Device, pD3D12Device, pD3D12Queue),
m_metaDevice (this),
m_dxvkFactory (this, &m_d3d11Device),
m_wineFactory (this, &m_d3d11Device) {
m_dxvkFactory (this, &m_d3d11Device) {
}
D3D11DXGIDevice::~D3D11DXGIDevice() {
}
@ -3215,16 +3153,18 @@ namespace dxvk {
return S_OK;
}
if (riid == __uuidof(IWineDXGISwapChainFactory)) {
*ppvObject = ref(&m_wineFactory);
return S_OK;
}
if (riid == __uuidof(ID3D11VideoDevice)) {
*ppvObject = ref(&m_d3d11Video);
return S_OK;
}
if (m_d3d11on12.Is11on12Device()) {
if (riid == __uuidof(ID3D11On12Device)) {
*ppvObject = ref(&m_d3d11on12);
return S_OK;
}
}
if (riid == __uuidof(ID3D10Multithread)) {
Com<ID3D11DeviceContext> context;
m_d3d11Device.GetImmediateContext(&context);
@ -3238,8 +3178,11 @@ namespace dxvk {
if (riid == GUID{0xd56e2a4c,0x5127,0x8437,{0x65,0x8a,0x98,0xc5,0xbb,0x78,0x94,0x98}})
return E_NOINTERFACE;
Logger::warn("D3D11DXGIDevice::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
if (logQueryInterfaceError(__uuidof(IDXGIDXVKDevice), riid)) {
Logger::warn("D3D11DXGIDevice::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
}
return E_NOINTERFACE;
}
@ -3468,8 +3411,9 @@ namespace dxvk {
HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::EnqueueSetEvent(HANDLE hEvent) {
Logger::err("D3D11DXGIDevice::EnqueueSetEvent: Not implemented");
return DXGI_ERROR_UNSUPPORTED;
auto immediateContext = m_d3d11Device.GetContext();
immediateContext->Flush1(D3D11_CONTEXT_TYPE_ALL, hEvent);
return S_OK;
}
@ -3485,10 +3429,4 @@ namespace dxvk {
return m_dxvkDevice;
}
Rc<DxvkDevice> D3D11DXGIDevice::CreateDevice(D3D_FEATURE_LEVEL FeatureLevel) {
DxvkDeviceFeatures deviceFeatures = D3D11Device::GetDeviceFeatures(m_dxvkAdapter);
return m_dxvkAdapter->createDevice(m_dxvkInstance, deviceFeatures);
}
}

View File

@ -20,6 +20,7 @@
#include "d3d11_initializer.h"
#include "d3d11_interfaces.h"
#include "d3d11_interop.h"
#include "d3d11_on_12.h"
#include "d3d11_options.h"
#include "d3d11_shader.h"
#include "d3d11_state.h"
@ -420,7 +421,13 @@ namespace dxvk {
D3D10Device* GetD3D10Interface() const {
return m_d3d10Device;
}
D3D11ImmediateContext* GetContext() const {
return m_context.ptr();
}
bool Is11on12Device() const;
static D3D_FEATURE_LEVEL GetMaxFeatureLevel(
const Rc<DxvkInstance>& Instance,
const Rc<DxvkAdapter>& Adapter);
@ -430,7 +437,7 @@ namespace dxvk {
private:
IDXGIObject* m_container;
D3D11DXGIDevice* m_container;
D3D_FEATURE_LEVEL m_featureLevel;
UINT m_featureFlags;
@ -722,41 +729,6 @@ namespace dxvk {
};
/**
* \brief DXGI swap chain factory
*/
class WineDXGISwapChainFactory : public IWineDXGISwapChainFactory {
public:
WineDXGISwapChainFactory(
D3D11DXGIDevice* pContainer,
D3D11Device* pDevice);
ULONG STDMETHODCALLTYPE AddRef();
ULONG STDMETHODCALLTYPE Release();
HRESULT STDMETHODCALLTYPE QueryInterface(
REFIID riid,
void** ppvObject);
HRESULT STDMETHODCALLTYPE CreateSwapChainForHwnd(
IDXGIFactory* pFactory,
HWND hWnd,
const DXGI_SWAP_CHAIN_DESC1* pDesc,
const DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pFullscreenDesc,
IDXGIOutput* pRestrictToOutput,
IDXGISwapChain1** ppSwapChain);
private:
D3D11DXGIDevice* m_container;
D3D11Device* m_device;
};
/**
* \brief D3D11 device metadata shenanigans
*/
@ -799,8 +771,11 @@ namespace dxvk {
D3D11DXGIDevice(
IDXGIAdapter* pAdapter,
const Rc<DxvkInstance>& pDxvkInstance,
const Rc<DxvkAdapter>& pDxvkAdapter,
ID3D12Device* pD3D12Device,
ID3D12CommandQueue* pD3D12Queue,
Rc<DxvkInstance> pDxvkInstance,
Rc<DxvkAdapter> pDxvkAdapter,
Rc<DxvkDevice> pDxvkDevice,
D3D_FEATURE_LEVEL FeatureLevel,
UINT FeatureFlags);
@ -869,6 +844,10 @@ namespace dxvk {
Rc<DxvkDevice> STDMETHODCALLTYPE GetDXVKDevice();
BOOL Is11on12Device() const {
return m_d3d11on12.Is11on12Device();
}
private:
Com<IDXGIAdapter> m_dxgiAdapter;
@ -881,15 +860,13 @@ namespace dxvk {
D3D11DeviceExt m_d3d11DeviceExt;
D3D11VkInterop m_d3d11Interop;
D3D11VideoDevice m_d3d11Video;
D3D11on12Device m_d3d11on12;
DXGIDXVKDevice m_metaDevice;
DXGIVkSwapChainFactory m_dxvkFactory;
WineDXGISwapChainFactory m_wineFactory;
uint32_t m_frameLatency = DefaultFrameLatency;
Rc<DxvkDevice> CreateDevice(D3D_FEATURE_LEVEL FeatureLevel);
};
}

View File

@ -12,6 +12,7 @@ namespace dxvk {
D3D11DeviceFeatures::D3D11DeviceFeatures(
const Rc<DxvkInstance>& Instance,
const Rc<DxvkAdapter>& Adapter,
const D3D11Options& Options,
D3D_FEATURE_LEVEL FeatureLevel)
: m_features (Adapter->features()),
m_properties (Adapter->devicePropertiesExt()) {
@ -107,7 +108,7 @@ namespace dxvk {
m_gpuVirtualAddress.MaxGPUVirtualAddressBitsPerProcess = 40;
// Marker support only depends on the debug utils extension
m_marker.Profile = Instance->extensions().extDebugUtils;
m_marker.Profile = static_cast<bool>(Instance->extensions().extDebugUtils);
// DXVK will keep all shaders in memory once created, and all Vulkan
// drivers that we know of that can run DXVK have an on-disk cache.
@ -118,11 +119,11 @@ namespace dxvk {
m_shaderMinPrecision.PixelShaderMinPrecision = 0;
m_shaderMinPrecision.AllOtherShaderStagesMinPrecision = 0;
// Report native support for command lists here so that we do not actually have
// to re-implement the UpdateSubresource bug from the D3D11 runtime, see MSDN:
// https://msdn.microsoft.com/en-us/library/windows/desktop/ff476486(v=vs.85).aspx)
// Report native support for command lists by default. Deferred context
// usage can be beneficial for us as ExecuteCommandList has low overhead,
// and we avoid having to deal with known UpdateSubresource bugs this way.
m_threading.DriverConcurrentCreates = TRUE;
m_threading.DriverCommandLists = TRUE;
m_threading.DriverCommandLists = Options.exposeDriverCommandLists;
}
@ -182,7 +183,8 @@ namespace dxvk {
D3D_FEATURE_LEVEL D3D11DeviceFeatures::GetMaxFeatureLevel(
const Rc<DxvkInstance>& Instance,
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();
}

View File

@ -1,6 +1,7 @@
#pragma once
#include "d3d11_include.h"
#include "d3d11_options.h"
#include "../dxvk/dxvk_adapter.h"
#include "../dxvk/dxvk_instance.h"
@ -21,6 +22,7 @@ namespace dxvk {
D3D11DeviceFeatures(
const Rc<DxvkInstance>& Instance,
const Rc<DxvkAdapter>& Adapter,
const D3D11Options& Options,
D3D_FEATURE_LEVEL FeatureLevel);
~D3D11DeviceFeatures();

View File

@ -48,8 +48,11 @@ namespace dxvk {
return S_OK;
}
Logger::warn("D3D11Fence: Unknown interface query");
Logger::warn(str::format(riid));
if (logQueryInterfaceError(__uuidof(ID3D11Fence), riid)) {
Logger::warn("D3D11Fence: Unknown interface query");
Logger::warn(str::format(riid));
}
return E_NOINTERFACE;
}
@ -81,13 +84,13 @@ namespace dxvk {
HRESULT STDMETHODCALLTYPE D3D11Fence::SetEventOnCompletion(
UINT64 Value,
HANDLE hEvent) {
// TODO in case of rewinds, the stored value may be higher.
// For shared fences, calling vkWaitSemaphores here could alleviate the issue.
m_fence->enqueueWait(Value, [hEvent] {
SetEvent(hEvent);
});
if (hEvent) {
m_fence->enqueueWait(Value, [hEvent] {
SetEvent(hEvent);
});
} else {
m_fence->wait(Value);
}
return S_OK;
}

View File

@ -150,11 +150,8 @@ namespace dxvk {
HRESULT D3D11GDISurface::CreateReadbackResource() {
auto tex = GetCommonTexture(m_resource);
Com<ID3D11Device> device;
Com<ID3D11DeviceContext> context;
Com<ID3D11Device> device;
m_resource->GetDevice(&device);
device->GetImmediateContext(&context);
D3D11_RESOURCE_DIMENSION dim = { };
m_resource->GetType(&dim);

View File

@ -49,23 +49,28 @@ namespace dxvk {
InitHostVisibleTexture(pTexture, pInitialData);
else
InitDeviceLocalTexture(pTexture, pInitialData);
SyncKeyedMutex(pTexture->GetInterface());
}
void D3D11Initializer::InitUavCounter(
D3D11UnorderedAccessView* pUav) {
auto counterBuffer = pUav->GetCounterSlice();
auto counterView = pUav->GetCounterView();
if (!counterBuffer.defined())
if (counterView == nullptr)
return;
auto counterSlice = counterView->slice();
std::lock_guard<dxvk::mutex> lock(m_mutex);
m_transferCommands += 1;
const uint32_t zero = 0;
m_context->updateBuffer(
counterBuffer.buffer(),
0, sizeof(zero), &zero);
counterSlice.buffer(),
counterSlice.offset(),
sizeof(zero), &zero);
FlushImplicit();
}
@ -275,10 +280,20 @@ namespace dxvk {
void D3D11Initializer::FlushInternal() {
m_context->flushCommandList();
m_context->flushCommandList(nullptr);
m_transferCommands = 0;
m_transferMemory = 0;
}
void D3D11Initializer::SyncKeyedMutex(ID3D11Resource *pResource) {
Com<IDXGIKeyedMutex> keyedMutex;
if (pResource->QueryInterface(__uuidof(IDXGIKeyedMutex), reinterpret_cast<void**>(&keyedMutex)) != S_OK)
return;
keyedMutex->AcquireSync(0, 0);
keyedMutex->ReleaseSync(0);
}
}

View File

@ -71,6 +71,8 @@ namespace dxvk {
void FlushImplicit();
void FlushInternal();
void SyncKeyedMutex(ID3D11Resource *pResource);
};
}

View File

@ -46,8 +46,11 @@ namespace dxvk {
return S_OK;
}
Logger::warn("D3D11InputLayout::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
if (logQueryInterfaceError(__uuidof(ID3D11InputLayout), riid)) {
Logger::warn("D3D11InputLayout::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
}
return E_NOINTERFACE;
}

View File

@ -183,13 +183,7 @@ ID3D11VkExtContext1 : public ID3D11VkExtContext {
};
#ifdef _MSC_VER
struct __declspec(uuid("bb8a4fb9-3935-4762-b44b-35189a26414a")) ID3D11VkExtShader;
struct __declspec(uuid("8a6e3c42-f74c-45b7-8265-a231b677ca17")) ID3D11VkExtDevice;
struct __declspec(uuid("cfcf64ef-9586-46d0-bca4-97cf2ca61b06")) ID3D11VkExtDevice1;
struct __declspec(uuid("fd0bca13-5cb6-4c3a-987e-4750de2ca791")) ID3D11VkExtContext;
struct __declspec(uuid("874b09b2-ae0b-41d8-8476-5f3b7a0e879d")) ID3D11VkExtContext1;
#else
#ifndef _MSC_VER
__CRT_UUID_DECL(ID3D11VkExtShader, 0xbb8a4fb9,0x3935,0x4762,0xb4,0x4b,0x35,0x18,0x9a,0x26,0x41,0x4a);
__CRT_UUID_DECL(ID3D11VkExtDevice, 0x8a6e3c42,0xf74c,0x45b7,0x82,0x65,0xa2,0x31,0xb6,0x77,0xca,0x17);
__CRT_UUID_DECL(ID3D11VkExtDevice1, 0xcfcf64ef,0x9586,0x46d0,0xbc,0xa4,0x97,0xcf,0x2c,0xa6,0x1b,0x06);

View File

@ -75,21 +75,15 @@ namespace dxvk {
const VkImageSubresourceRange* pSubresources,
VkImageLayout OldLayout,
VkImageLayout NewLayout) {
Com<ID3D11DeviceContext> deviceContext = nullptr;
m_device->GetImmediateContext(&deviceContext);
auto immediateContext = static_cast<D3D11ImmediateContext*>(deviceContext.ptr());
auto immediateContext = m_device->GetContext();
immediateContext->TransitionSurfaceLayout(
pSurface, pSubresources, OldLayout, NewLayout);
}
void STDMETHODCALLTYPE D3D11VkInterop::FlushRenderingCommands() {
Com<ID3D11DeviceContext> deviceContext = nullptr;
m_device->GetImmediateContext(&deviceContext);
auto immediateContext = static_cast<D3D11ImmediateContext*>(deviceContext.ptr());
auto immediateContext = m_device->GetContext();
immediateContext->Flush();
immediateContext->SynchronizeCsThread(DxvkCsThread::SynchronizeAll);
}

View File

@ -15,7 +15,7 @@ namespace dxvk {
extern "C" {
using namespace dxvk;
DLLEXPORT HRESULT __stdcall D3D11CoreCreateDevice(
HRESULT D3D11InternalCreateDevice(
IDXGIFactory* pFactory,
IDXGIAdapter* pAdapter,
UINT Flags,
@ -34,11 +34,11 @@ extern "C" {
dxvkAdapter = dxgiVkAdapter->GetDXVKAdapter();
dxvkInstance = dxgiVkAdapter->GetDXVKInstance();
} else {
Logger::warn("D3D11CoreCreateDevice: Adapter is not a DXVK adapter");
Logger::warn("D3D11InternalCreateDevice: Adapter is not a DXVK adapter");
DXGI_ADAPTER_DESC desc;
pAdapter->GetDesc(&desc);
dxvkInstance = new DxvkInstance();
dxvkInstance = new DxvkInstance(0);
dxvkAdapter = dxvkInstance->findAdapterByLuid(&desc.AdapterLuid);
if (dxvkAdapter == nullptr)
@ -70,7 +70,7 @@ extern "C" {
D3D_FEATURE_LEVEL minFeatureLevel = D3D_FEATURE_LEVEL();
D3D_FEATURE_LEVEL devFeatureLevel = D3D_FEATURE_LEVEL();
Logger::info(str::format("D3D11CoreCreateDevice: Maximum supported feature level: ", maxFeatureLevel));
Logger::info(str::format("D3D11InternalCreateDevice: Maximum supported feature level: ", maxFeatureLevel));
for (uint32_t flId = 0 ; flId < FeatureLevels; flId++) {
minFeatureLevel = pFeatureLevels[flId];
@ -82,21 +82,26 @@ extern "C" {
}
if (!devFeatureLevel) {
Logger::err(str::format("D3D11CoreCreateDevice: Minimum required feature level ", minFeatureLevel, " not supported"));
Logger::err(str::format("D3D11InternalCreateDevice: Minimum required feature level ", minFeatureLevel, " not supported"));
return E_INVALIDARG;
}
try {
Logger::info(str::format("D3D11CoreCreateDevice: Using feature level ", devFeatureLevel));
Logger::info(str::format("D3D11InternalCreateDevice: Using feature level ", devFeatureLevel));
DxvkDeviceFeatures deviceFeatures = D3D11Device::GetDeviceFeatures(dxvkAdapter);
Rc<DxvkDevice> dxvkDevice = dxvkAdapter->createDevice(dxvkInstance, deviceFeatures);
Com<D3D11DXGIDevice> device = new D3D11DXGIDevice(
pAdapter, dxvkInstance, dxvkAdapter, devFeatureLevel, Flags);
pAdapter, nullptr, nullptr,
dxvkInstance, dxvkAdapter, dxvkDevice,
devFeatureLevel, Flags);
return device->QueryInterface(
__uuidof(ID3D11Device),
reinterpret_cast<void**>(ppDevice));
} catch (const DxvkError& e) {
Logger::err("D3D11CoreCreateDevice: Failed to create D3D11 device");
Logger::err("D3D11InternalCreateDevice: Failed to create D3D11 device");
return E_FAIL;
}
}
@ -168,7 +173,7 @@ extern "C" {
}
// Create the actual device
hr = D3D11CoreCreateDevice(
hr = D3D11InternalCreateDevice(
dxgiFactory.ptr(), dxgiAdapter.ptr(),
Flags, pFeatureLevels, FeatureLevels,
&device);
@ -207,6 +212,25 @@ extern "C" {
}
DLLEXPORT HRESULT __stdcall D3D11CoreCreateDevice(
IDXGIFactory* pFactory,
IDXGIAdapter* pAdapter,
D3D_DRIVER_TYPE DriverType,
HMODULE Software,
UINT Flags,
const D3D_FEATURE_LEVEL* pFeatureLevels,
UINT FeatureLevels,
UINT SDKVersion,
ID3D11Device** ppDevice,
D3D_FEATURE_LEVEL* pFeatureLevel) {
return D3D11InternalCreateDeviceAndSwapChain(
pAdapter, DriverType, Software, Flags,
pFeatureLevels, FeatureLevels, SDKVersion,
nullptr, nullptr,
ppDevice, pFeatureLevel, nullptr);
}
DLLEXPORT HRESULT __stdcall D3D11CreateDevice(
IDXGIAdapter* pAdapter,
D3D_DRIVER_TYPE DriverType,
@ -258,12 +282,169 @@ extern "C" {
ID3D11Device** ppDevice,
ID3D11DeviceContext** ppImmediateContext,
D3D_FEATURE_LEVEL* pChosenFeatureLevel) {
static bool s_errorShown = false;
InitReturnPtr(ppDevice);
InitReturnPtr(ppImmediateContext);
if (!std::exchange(s_errorShown, true))
Logger::err("D3D11On12CreateDevice: Not implemented");
if (pChosenFeatureLevel)
*pChosenFeatureLevel = D3D_FEATURE_LEVEL(0);
return E_NOTIMPL;
if (!pDevice)
return E_INVALIDARG;
// Figure out D3D12 objects
Com<ID3D12Device> d3d12Device;
Com<ID3D12CommandQueue> d3d12Queue;
if (FAILED(pDevice->QueryInterface(__uuidof(ID3D12Device), reinterpret_cast<void**>(&d3d12Device)))) {
Logger::err("D3D11On12CreateDevice: Device is not a valid D3D12 device");
return E_INVALIDARG;
}
if (NodeMask & (NodeMask - 1)) {
Logger::err("D3D11On12CreateDevice: Invalid node mask");
return E_INVALIDARG;
}
if (!NumQueues || !ppCommandQueues || !ppCommandQueues[0]) {
Logger::err("D3D11On12CreateDevice: No command queue specified");
return E_INVALIDARG;
}
if (NumQueues > 1) {
// Not sure what to do with more than one graphics queue
Logger::warn("D3D11On12CreateDevice: Only one queue supported");
}
if (FAILED(ppCommandQueues[0]->QueryInterface(__uuidof(ID3D12CommandQueue), reinterpret_cast<void**>(&d3d12Queue)))) {
Logger::err("D3D11On12CreateDevice: Queue is not a valid D3D12 command queue");
return E_INVALIDARG;
}
// Determine feature level for the D3D11 device
std::array<D3D_FEATURE_LEVEL, 4> defaultFeatureLevels = {{
D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_11_1,
D3D_FEATURE_LEVEL_12_0, D3D_FEATURE_LEVEL_12_1,
}};
D3D12_FEATURE_DATA_FEATURE_LEVELS featureLevel = { };
if (!FeatureLevels || !pFeatureLevels) {
featureLevel.NumFeatureLevels = defaultFeatureLevels.size();
featureLevel.pFeatureLevelsRequested = defaultFeatureLevels.data();
} else {
featureLevel.NumFeatureLevels = FeatureLevels;
featureLevel.pFeatureLevelsRequested = pFeatureLevels;
}
HRESULT hr = d3d12Device->CheckFeatureSupport(D3D12_FEATURE_FEATURE_LEVELS, &featureLevel, sizeof(featureLevel));
if (FAILED(hr) || !featureLevel.MaxSupportedFeatureLevel) {
Logger::err(str::format("D3D11On12CreateDevice: Minimum required feature level not supported"));
return hr;
}
Logger::info(str::format("D3D11On12CreateDevice: Chosen feature level: ", featureLevel.MaxSupportedFeatureLevel));
Com<ID3D12DXVKInteropDevice> interopDevice;
if (FAILED(d3d12Device->QueryInterface(__uuidof(ID3D12DXVKInteropDevice), reinterpret_cast<void**>(&interopDevice)))) {
Logger::err("D3D11On12CreateDevice: Device not a vkd3d-proton device.");
return E_INVALIDARG;
}
Com<IDXGIAdapter> dxgiAdapter;
if (FAILED(interopDevice->GetDXGIAdapter(IID_PPV_ARGS(&dxgiAdapter)))) {
Logger::err("D3D11On12CreateDevice: Failed to query DXGI adapter.");
return E_INVALIDARG;
}
try {
// Initialize DXVK instance
DxvkInstanceImportInfo instanceInfo = { };
DxvkDeviceImportInfo deviceInfo = { };
VkPhysicalDevice vulkanAdapter = VK_NULL_HANDLE;
interopDevice->GetVulkanHandles(&instanceInfo.instance, &vulkanAdapter, &deviceInfo.device);
uint32_t instanceExtensionCount = 0;
interopDevice->GetInstanceExtensions(&instanceExtensionCount, nullptr);
std::vector<const char*> instanceExtensions(instanceExtensionCount);
interopDevice->GetInstanceExtensions(&instanceExtensionCount, instanceExtensions.data());
instanceInfo.extensionCount = instanceExtensions.size();
instanceInfo.extensionNames = instanceExtensions.data();
Rc<DxvkInstance> dxvkInstance = new DxvkInstance(instanceInfo, 0);
// Find adapter by physical device handle
Rc<DxvkAdapter> dxvkAdapter;
for (uint32_t i = 0; i < dxvkInstance->adapterCount(); i++) {
Rc<DxvkAdapter> curr = dxvkInstance->enumAdapters(i);
if (curr->handle() == vulkanAdapter)
dxvkAdapter = std::move(curr);
}
if (dxvkAdapter == nullptr) {
Logger::err("D3D11On12CreateDevice: No matching adapter found");
return E_INVALIDARG;
}
interopDevice->GetVulkanQueueInfo(d3d12Queue.ptr(), &deviceInfo.queue, &deviceInfo.queueFamily);
interopDevice->GetDeviceFeatures(&deviceInfo.features);
uint32_t deviceExtensionCount = 0;
interopDevice->GetDeviceExtensions(&deviceExtensionCount, nullptr);
std::vector<const char*> deviceExtensions(deviceExtensionCount);
interopDevice->GetDeviceExtensions(&deviceExtensionCount, deviceExtensions.data());
deviceInfo.extensionCount = deviceExtensions.size();
deviceInfo.extensionNames = deviceExtensions.data();
deviceInfo.queueCallback = [
cDevice = interopDevice,
cQueue = d3d12Queue
] (bool doLock) {
HRESULT hr = doLock
? cDevice->LockCommandQueue(cQueue.ptr())
: cDevice->UnlockCommandQueue(cQueue.ptr());
if (FAILED(hr))
Logger::err(str::format("Failed to lock vkd3d-proton device queue: ", hr));
};
Rc<DxvkDevice> dxvkDevice = dxvkAdapter->importDevice(dxvkInstance, deviceInfo);
// Create and return the actual D3D11 device
Com<D3D11DXGIDevice> device = new D3D11DXGIDevice(
dxgiAdapter.ptr(), d3d12Device.ptr(), d3d12Queue.ptr(),
dxvkInstance, dxvkAdapter, dxvkDevice,
featureLevel.MaxSupportedFeatureLevel, Flags);
Com<ID3D11Device> d3d11Device;
device->QueryInterface(__uuidof(ID3D11Device), reinterpret_cast<void**>(&d3d11Device));
if (ppDevice)
*ppDevice = d3d11Device.ref();
if (ppImmediateContext)
d3d11Device->GetImmediateContext(ppImmediateContext);
if (pChosenFeatureLevel)
*pChosenFeatureLevel = d3d11Device->GetFeatureLevel();
if (!ppDevice && !ppImmediateContext)
return S_FALSE;
return S_OK;
} catch (const DxvkError& e) {
Logger::err("D3D11On12CreateDevice: Failed to create D3D11 device");
return E_FAIL;
}
}
}

150
src/d3d11/d3d11_on_12.cpp Normal file
View File

@ -0,0 +1,150 @@
#include "d3d11_context_imm.h"
#include "d3d11_device.h"
#include "d3d11_on_12.h"
namespace dxvk {
D3D11on12Device::D3D11on12Device(
D3D11DXGIDevice* pContainer,
D3D11Device* pDevice,
ID3D12Device* pD3D12Device,
ID3D12CommandQueue* pD3D12Queue)
: m_container (pContainer),
m_device (pDevice),
m_d3d12Device (pD3D12Device),
m_d3d12Queue (pD3D12Queue) {
}
D3D11on12Device::~D3D11on12Device() {
}
ULONG STDMETHODCALLTYPE D3D11on12Device::AddRef() {
return m_container->AddRef();
}
ULONG STDMETHODCALLTYPE D3D11on12Device::Release() {
return m_container->Release();
}
HRESULT STDMETHODCALLTYPE D3D11on12Device::QueryInterface(
REFIID riid,
void** ppvObject) {
return m_container->QueryInterface(riid, ppvObject);
}
HRESULT STDMETHODCALLTYPE D3D11on12Device::CreateWrappedResource(
IUnknown* pResource12,
const D3D11_RESOURCE_FLAGS* pResourceFlags,
D3D12_RESOURCE_STATES InputState,
D3D12_RESOURCE_STATES OutputState,
REFIID riid,
void** ppResource11) {
Com<ID3D12DXVKInteropDevice> interopDevice;
m_d3d12Device->QueryInterface(__uuidof(ID3D12DXVKInteropDevice), reinterpret_cast<void**>(&interopDevice));
D3D11_ON_12_RESOURCE_INFO info = { };
info.InputState = InputState;
info.OutputState = OutputState;
info.IsWrappedResource = TRUE;
// 11on12 technically allows importing D3D12 heaps as tile pools,
// but we don't support importing sparse resources at this time.
if (FAILED(pResource12->QueryInterface(__uuidof(ID3D12Resource), reinterpret_cast<void**>(&info.Resource)))) {
Logger::err("D3D11on12Device::CreateWrappedResource: Resource not a valid D3D12 resource");
return E_INVALIDARG;
}
// Query Vulkan resource handle and buffer offset as necessary
if (FAILED(interopDevice->GetVulkanResourceInfo(info.Resource.ptr(), &info.VulkanHandle, &info.VulkanOffset))) {
Logger::err("D3D11on12Device::CreateWrappedResource: Failed to retrieve Vulkan resource info");
return E_INVALIDARG;
}
Com<ID3D11Resource> resource;
D3D12_RESOURCE_DESC desc = info.Resource->GetDesc();
if (desc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) {
D3D11_BUFFER_DESC bufferDesc;
if (FAILED(D3D11Buffer::GetDescFromD3D12(info.Resource.ptr(), pResourceFlags, &bufferDesc)))
return E_INVALIDARG;
resource = new D3D11Buffer(m_device, &bufferDesc, &info);
} else {
D3D11_COMMON_TEXTURE_DESC textureDesc;
if (FAILED(D3D11CommonTexture::GetDescFromD3D12(info.Resource.ptr(), pResourceFlags, &textureDesc)))
return E_INVALIDARG;
switch (desc.Dimension) {
case D3D12_RESOURCE_DIMENSION_TEXTURE1D:
resource = new D3D11Texture1D(m_device, &textureDesc, &info);
break;
case D3D12_RESOURCE_DIMENSION_TEXTURE2D:
resource = new D3D11Texture2D(m_device, &textureDesc, &info, nullptr);
break;
case D3D12_RESOURCE_DIMENSION_TEXTURE3D:
resource = new D3D11Texture3D(m_device, &textureDesc, &info);
break;
default:
Logger::err("D3D11on12Device::CreateWrappedResource: Unhandled resource dimension");
return E_INVALIDARG;
}
}
return resource->QueryInterface(riid, ppResource11);
}
void STDMETHODCALLTYPE D3D11on12Device::ReleaseWrappedResources(
ID3D11Resource* const* ppResources,
UINT ResourceCount) {
Com<ID3D12DXVKInteropDevice> interopDevice;
m_d3d12Device->QueryInterface(__uuidof(ID3D12DXVKInteropDevice), reinterpret_cast<void**>(&interopDevice));
for (uint32_t i = 0; i < ResourceCount; i++) {
D3D11_ON_12_RESOURCE_INFO info;
if (FAILED(GetResource11on12Info(ppResources[i], &info)) || !info.IsWrappedResource) {
Logger::warn("D3D11on12Device::ReleaseWrappedResources: Resource not a wrapped resource, skipping");
continue;
}
VkImageLayout layout = VK_IMAGE_LAYOUT_UNDEFINED;
interopDevice->GetVulkanImageLayout(info.Resource.ptr(), info.OutputState, &layout);
m_device->GetContext()->Release11on12Resource(ppResources[i], layout);
}
}
void STDMETHODCALLTYPE D3D11on12Device::AcquireWrappedResources(
ID3D11Resource* const* ppResources,
UINT ResourceCount) {
Com<ID3D12DXVKInteropDevice> interopDevice;
m_d3d12Device->QueryInterface(__uuidof(ID3D12DXVKInteropDevice), reinterpret_cast<void**>(&interopDevice));
for (uint32_t i = 0; i < ResourceCount; i++) {
D3D11_ON_12_RESOURCE_INFO info;
if (FAILED(GetResource11on12Info(ppResources[i], &info)) || !info.IsWrappedResource) {
Logger::warn("D3D11on12Device::AcquireWrappedResources: Resource not a wrapped resource, skipping");
continue;
}
VkImageLayout layout = VK_IMAGE_LAYOUT_UNDEFINED;
interopDevice->GetVulkanImageLayout(info.Resource.ptr(), info.InputState, &layout);
m_device->GetContext()->Acquire11on12Resource(ppResources[i], layout);
}
}
}

75
src/d3d11/d3d11_on_12.h Normal file
View File

@ -0,0 +1,75 @@
#pragma once
#include "d3d11_on_12_interfaces.h"
#include "../util/log/log.h"
namespace dxvk {
class D3D11Device;
class D3D11DXGIDevice;
/**
* \brief Resource info for 11on12 resources
*/
struct D3D11_ON_12_RESOURCE_INFO {
Com<ID3D12Resource> Resource;
UINT64 VulkanHandle = 0;
UINT64 VulkanOffset = 0;
BOOL IsWrappedResource = FALSE;
D3D12_RESOURCE_STATES InputState = D3D12_RESOURCE_STATE_COMMON;
D3D12_RESOURCE_STATES OutputState = D3D12_RESOURCE_STATE_COMMON;
};
class D3D11on12Device : public ID3D11On12Device {
public:
D3D11on12Device(
D3D11DXGIDevice* pContainer,
D3D11Device* pDevice,
ID3D12Device* pD3D12Device,
ID3D12CommandQueue* pD3D12Queue);
~D3D11on12Device();
ULONG STDMETHODCALLTYPE AddRef();
ULONG STDMETHODCALLTYPE Release();
HRESULT STDMETHODCALLTYPE QueryInterface(
REFIID riid,
void** ppvObject);
HRESULT STDMETHODCALLTYPE CreateWrappedResource(
IUnknown* pResource12,
const D3D11_RESOURCE_FLAGS* pResourceFlags,
D3D12_RESOURCE_STATES InputState,
D3D12_RESOURCE_STATES OutputState,
REFIID riid,
void** ppResource11);
void STDMETHODCALLTYPE ReleaseWrappedResources(
ID3D11Resource* const* ppResources,
UINT ResourceCount);
void STDMETHODCALLTYPE AcquireWrappedResources(
ID3D11Resource* const* ppResources,
UINT ResourceCount);
bool Is11on12Device() const {
return m_d3d12Device != nullptr;
}
private:
D3D11DXGIDevice* m_container;
D3D11Device* m_device;
Com<ID3D12Device> m_d3d12Device;
Com<ID3D12CommandQueue> m_d3d12Queue;
};
}

View File

@ -0,0 +1,54 @@
#pragma once
#include "../vulkan/vulkan_loader.h"
#include <d3d11on12.h>
MIDL_INTERFACE("39da4e09-bd1c-4198-9fae-86bbe3be41fd")
ID3D12DXVKInteropDevice : public IUnknown {
virtual HRESULT STDMETHODCALLTYPE GetDXGIAdapter(
REFIID iid,
void** ppvObject) = 0;
virtual HRESULT STDMETHODCALLTYPE GetInstanceExtensions(
UINT* pExtensionCount,
const char** ppExtensions) = 0;
virtual HRESULT STDMETHODCALLTYPE GetDeviceExtensions(
UINT* pExtensionCount,
const char** ppExtensions) = 0;
virtual HRESULT STDMETHODCALLTYPE GetDeviceFeatures(
const VkPhysicalDeviceFeatures2** ppFeatures) = 0;
virtual HRESULT STDMETHODCALLTYPE GetVulkanHandles(
VkInstance* pVkInstance,
VkPhysicalDevice* pVkPhysicalDevice,
VkDevice* pVkDevice) = 0;
virtual HRESULT STDMETHODCALLTYPE GetVulkanQueueInfo(
ID3D12CommandQueue* pCommandQueue,
VkQueue* pVkQueue,
UINT32* pVkQueueFamily) = 0;
virtual void STDMETHODCALLTYPE GetVulkanImageLayout(
ID3D12Resource* pResource,
D3D12_RESOURCE_STATES State,
VkImageLayout* pVkLayout) = 0;
virtual HRESULT STDMETHODCALLTYPE GetVulkanResourceInfo(
ID3D12Resource* pResource,
UINT64* pVkHandle,
UINT64* pBufferOffset) = 0;
virtual HRESULT STDMETHODCALLTYPE LockCommandQueue(
ID3D12CommandQueue* pCommandQueue) = 0;
virtual HRESULT STDMETHODCALLTYPE UnlockCommandQueue(
ID3D12CommandQueue* pCommandQueue) = 0;
};
#ifndef _MSC_VER
__CRT_UUID_DECL(ID3D12DXVKInteropDevice, 0x39da4e09, 0xbd1c, 0x4198, 0x9f,0xae, 0x86,0xbb,0xe3,0xbe,0x41,0xfd)
#endif

View File

@ -12,9 +12,8 @@ namespace dxvk {
#endif
}
D3D11Options::D3D11Options(const Config& config, const Rc<DxvkDevice>& device) {
D3D11Options::D3D11Options(const Config& config) {
this->dcSingleUseMode = config.getOption<bool>("d3d11.dcSingleUseMode", true);
this->enableRtOutputNanFixup = config.getOption<bool>("d3d11.enableRtOutputNanFixup", false);
this->zeroInitWorkgroupMemory = config.getOption<bool>("d3d11.zeroInitWorkgroupMemory", false);
this->forceVolatileTgsmAccess = config.getOption<bool>("d3d11.forceVolatileTgsmAccess", false);
this->relaxedBarriers = config.getOption<bool>("d3d11.relaxedBarriers", false);
@ -22,16 +21,18 @@ namespace dxvk {
this->maxTessFactor = config.getOption<int32_t>("d3d11.maxTessFactor", 0);
this->samplerAnisotropy = config.getOption<int32_t>("d3d11.samplerAnisotropy", -1);
this->samplerLodBias = config.getOption<float>("d3d11.samplerLodBias", 0.0f);
this->clampNegativeLodBias = config.getOption<bool>("d3d11.clampNegativeLodBias", false);
this->invariantPosition = config.getOption<bool>("d3d11.invariantPosition", true);
this->floatControls = config.getOption<bool>("d3d11.floatControls", true);
this->forceSampleRateShading = config.getOption<bool>("d3d11.forceSampleRateShading", false);
this->disableMsaa = config.getOption<bool>("d3d11.disableMsaa", false);
this->enableContextLock = config.getOption<bool>("d3d11.enableContextLock", false);
this->deferSurfaceCreation = config.getOption<bool>("dxgi.deferSurfaceCreation", false);
this->numBackBuffers = config.getOption<int32_t>("dxgi.numBackBuffers", 0);
this->maxFrameLatency = config.getOption<int32_t>("dxgi.maxFrameLatency", 0);
this->maxFrameRate = config.getOption<int32_t>("dxgi.maxFrameRate", 0);
this->syncInterval = config.getOption<int32_t>("dxgi.syncInterval", -1);
this->tearFree = config.getOption<Tristate>("dxgi.tearFree", Tristate::Auto);
this->exposeDriverCommandLists = config.getOption<bool>("d3d11.exposeDriverCommandLists", true);
this->longMad = config.getOption<bool>("d3d11.longMad", false);
// Clamp LOD bias so that people don't abuse this in unintended ways
this->samplerLodBias = dxvk::fclamp(this->samplerLodBias, -2.0f, 1.0f);

View File

@ -11,7 +11,7 @@
namespace dxvk {
struct D3D11Options {
D3D11Options(const Config& config, const Rc<DxvkDevice>& device);
D3D11Options(const Config& config);
/// Enables speed hack for mapping on deferred contexts
///
@ -20,10 +20,6 @@ namespace dxvk {
/// than once.
bool dcSingleUseMode;
/// Enables workaround to replace NaN render target
/// outputs with zero
bool enableRtOutputNanFixup;
/// Zero-initialize workgroup memory
///
/// Workargound for games that don't initialize
@ -67,6 +63,9 @@ namespace dxvk {
/// Enforces the given LOD bias for all samplers.
float samplerLodBias;
/// Clamps negative LOD bias
bool clampNegativeLodBias;
/// Declare vertex positions in shaders as invariant
bool invariantPosition;
@ -77,14 +76,6 @@ namespace dxvk {
/// Overrides DXGI_SWAP_CHAIN_DESC::BufferCount.
int32_t numBackBuffers;
/// Sync interval. Overrides the value
/// passed to IDXGISwapChain::Present.
int32_t syncInterval;
/// Tear-free mode if vsync is disabled
/// Tearing mode if vsync is enabled
Tristate tearFree;
/// Override maximum frame latency if the app specifies
/// a higher value. May help with frame timing issues.
int32_t maxFrameLatency;
@ -103,6 +94,11 @@ namespace dxvk {
/// for a single window that may interfere with each other.
bool deferSurfaceCreation;
/// Enables sample rate shading by interpolating fragment shader
/// inputs at the sample location rather than pixel center,
/// unless otherwise specified by the application.
bool forceSampleRateShading;
/// Forces the sample count of all textures to be 1, and
/// performs the required shader and resolve fixups.
bool disableMsaa;
@ -117,8 +113,16 @@ namespace dxvk {
/// race conditions.
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
std::string shaderDumpPath;
/// Should we make our Mads a FFma or do it the long way with an FMul and an FAdd?
bool longMad;
};
}

View File

@ -120,8 +120,11 @@ namespace dxvk {
}
}
Logger::warn("D3D11Query: Unknown interface query");
Logger::warn(str::format(riid));
if (logQueryInterfaceError(__uuidof(ID3D11Query), riid)) {
Logger::warn("D3D11Query: Unknown interface query");
Logger::warn(str::format(riid));
}
return E_NOINTERFACE;
}

View File

@ -38,13 +38,22 @@ namespace dxvk {
m_state.conservativeMode = DecodeConservativeRasterizationMode(desc.ConservativeRaster);
m_state.sampleCount = VkSampleCountFlags(desc.ForcedSampleCount);
m_state.flatShading = VK_FALSE;
m_state.lineMode = VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT;
m_depthBias.depthBiasConstant = float(desc.DepthBias);
m_depthBias.depthBiasSlope = desc.SlopeScaledDepthBias;
m_depthBias.depthBiasClamp = desc.DepthBiasClamp;
if (desc.AntialiasedLineEnable)
Logger::err("D3D11RasterizerState: Antialiased lines not supported");
// Set up line rasterization mode
const auto& features = device->GetDXVKDevice()->features();
if (desc.MultisampleEnable) {
if (features.extLineRasterization.rectangularLines)
m_state.lineMode = VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT;
} else if (desc.AntialiasedLineEnable) {
if (features.extLineRasterization.smoothLines)
m_state.lineMode = VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT;
}
}
@ -74,8 +83,11 @@ namespace dxvk {
return S_OK;
}
Logger::warn("D3D11RasterizerState::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
if (logQueryInterfaceError(__uuidof(ID3D11RasterizerState), riid)) {
Logger::warn("D3D11RasterizerState::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
}
return E_NOINTERFACE;
}

View File

@ -1,14 +1,138 @@
#include "d3d11_buffer.h"
#include "d3d11_texture.h"
#include "d3d11_resource.h"
#include "d3d11_context_imm.h"
#include "d3d11_device.h"
#include "../util/util_shared_res.h"
namespace dxvk {
D3D11DXGIKeyedMutex::D3D11DXGIKeyedMutex(
ID3D11Resource* pResource,
D3D11Device* pDevice)
: m_resource(pResource),
m_device(pDevice) {
m_supported = m_device->GetDXVKDevice()->features().khrWin32KeyedMutex
&& m_device->GetDXVKDevice()->vkd()->wine_vkAcquireKeyedMutex != nullptr
&& m_device->GetDXVKDevice()->vkd()->wine_vkReleaseKeyedMutex != nullptr;
}
D3D11DXGIKeyedMutex::~D3D11DXGIKeyedMutex() {
}
ULONG STDMETHODCALLTYPE D3D11DXGIKeyedMutex::AddRef() {
return m_resource->AddRef();
}
ULONG STDMETHODCALLTYPE D3D11DXGIKeyedMutex::Release() {
return m_resource->Release();
}
HRESULT STDMETHODCALLTYPE D3D11DXGIKeyedMutex::QueryInterface(
REFIID riid,
void** ppvObject) {
return m_resource->QueryInterface(riid, ppvObject);
}
HRESULT STDMETHODCALLTYPE D3D11DXGIKeyedMutex::GetPrivateData(
REFGUID Name,
UINT* pDataSize,
void* pData) {
return m_resource->GetPrivateData(Name, pDataSize, pData);
}
HRESULT STDMETHODCALLTYPE D3D11DXGIKeyedMutex::SetPrivateData(
REFGUID Name,
UINT DataSize,
const void* pData) {
return m_resource->SetPrivateData(Name, DataSize, pData);
}
HRESULT STDMETHODCALLTYPE D3D11DXGIKeyedMutex::SetPrivateDataInterface(
REFGUID Name,
const IUnknown* pUnknown) {
return m_resource->SetPrivateDataInterface(Name, pUnknown);
}
HRESULT STDMETHODCALLTYPE D3D11DXGIKeyedMutex::GetParent(
REFIID riid,
void** ppParent) {
return GetDevice(riid, ppParent);
}
HRESULT STDMETHODCALLTYPE D3D11DXGIKeyedMutex::GetDevice(
REFIID riid,
void** ppDevice) {
Com<ID3D11Device> device;
m_resource->GetDevice(&device);
return device->QueryInterface(riid, ppDevice);
}
HRESULT STDMETHODCALLTYPE D3D11DXGIKeyedMutex::AcquireSync(
UINT64 Key,
DWORD dwMilliseconds) {
if (!m_supported) {
if (!m_warned) {
m_warned = true;
Logger::err("D3D11DXGIKeyedMutex::AcquireSync: Not supported");
}
return S_OK;
}
D3D11CommonTexture* texture = GetCommonTexture(m_resource);
Rc<DxvkDevice> dxvkDevice = m_device->GetDXVKDevice();
VkResult vr = dxvkDevice->vkd()->wine_vkAcquireKeyedMutex(dxvkDevice->handle(), texture->GetImage()->memory().memory(), Key, dwMilliseconds);
switch (vr) {
case VK_SUCCESS: return S_OK;
case VK_TIMEOUT: return WAIT_TIMEOUT;
default: return DXGI_ERROR_INVALID_CALL;
}
}
HRESULT STDMETHODCALLTYPE D3D11DXGIKeyedMutex::ReleaseSync(
UINT64 Key) {
if (!m_supported)
return S_OK;
D3D11CommonTexture* texture = GetCommonTexture(m_resource);
Rc<DxvkDevice> dxvkDevice = m_device->GetDXVKDevice();
{
D3D11ImmediateContext* context = m_device->GetContext();
D3D10Multithread& multithread = context->GetMultithread();
static bool s_errorShown = false;
if (!multithread.GetMultithreadProtected() && !std::exchange(s_errorShown, true))
Logger::warn("D3D11DXGIKeyedMutex::ReleaseSync: Called without context locking enabled.");
D3D10DeviceLock lock = context->LockContext();
context->WaitForResource(texture->GetImage(), DxvkCsThread::SynchronizeAll, D3D11_MAP_READ_WRITE, 0);
}
return dxvkDevice->vkd()->wine_vkReleaseKeyedMutex(dxvkDevice->handle(), texture->GetImage()->memory().memory(), Key) == VK_SUCCESS
? S_OK
: DXGI_ERROR_INVALID_CALL;
}
D3D11DXGIResource::D3D11DXGIResource(
ID3D11Resource* pResource)
: m_resource(pResource) {
ID3D11Resource* pResource,
D3D11Device* pDevice)
: m_resource(pResource),
m_keyedMutex(pResource, pDevice) {
}
@ -84,9 +208,15 @@ namespace dxvk {
HRESULT STDMETHODCALLTYPE D3D11DXGIResource::GetSharedHandle(
HANDLE* pSharedHandle) {
auto texture = GetCommonTexture(m_resource);
if (texture == nullptr || pSharedHandle == nullptr || !(texture->Desc()->MiscFlags & D3D11_RESOURCE_MISC_SHARED))
if (texture == nullptr || pSharedHandle == nullptr ||
(texture->Desc()->MiscFlags & D3D11_RESOURCE_MISC_SHARED_NTHANDLE))
return E_INVALIDARG;
if (!(texture->Desc()->MiscFlags & (D3D11_RESOURCE_MISC_SHARED | D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX))) {
*pSharedHandle = NULL;
return S_OK;
}
HANDLE kmtHandle = texture->GetImage()->sharedHandle();
if (kmtHandle == INVALID_HANDLE_VALUE)
@ -143,8 +273,9 @@ namespace dxvk {
LPCWSTR lpName,
HANDLE* pHandle) {
auto texture = GetCommonTexture(m_resource);
if (pHandle) *pHandle = nullptr;
if (texture == nullptr || pHandle == nullptr ||
!(texture->Desc()->MiscFlags & (D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX | D3D11_RESOURCE_MISC_SHARED_NTHANDLE)))
!(texture->Desc()->MiscFlags & D3D11_RESOURCE_MISC_SHARED_NTHANDLE))
return E_INVALIDARG;
if (lpName)
@ -155,9 +286,6 @@ namespace dxvk {
if (handle == INVALID_HANDLE_VALUE)
return E_INVALIDARG;
if (texture->Desc()->MiscFlags & D3D11_RESOURCE_MISC_SHARED)
handle = openKmtHandle( handle );
*pHandle = handle;
return S_OK;
}
@ -172,6 +300,36 @@ namespace dxvk {
}
HRESULT D3D11DXGIResource::GetKeyedMutex(
void **ppvObject) {
auto texture = GetCommonTexture(m_resource);
if (texture == nullptr || !(texture->Desc()->MiscFlags & D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX))
return E_NOINTERFACE;
*ppvObject = ref(&m_keyedMutex);
return S_OK;
}
HRESULT GetResource11on12Info(
ID3D11Resource* pResource,
D3D11_ON_12_RESOURCE_INFO* p11on12Info) {
auto buffer = GetCommonBuffer (pResource);
auto texture = GetCommonTexture(pResource);
if (buffer != nullptr)
*p11on12Info = buffer->Get11on12Info();
else if (texture != nullptr)
*p11on12Info = texture->Get11on12Info();
else
return E_INVALIDARG;
if (p11on12Info->Resource == nullptr)
return E_INVALIDARG;
return S_OK;
}
HRESULT GetCommonResourceDesc(
ID3D11Resource* pResource,
D3D11_COMMON_RESOURCE_DESC* pDesc) {

View File

@ -22,6 +22,65 @@ namespace dxvk {
};
/**
* \brief IDXGIKeyedMutex implementation
*/
class D3D11DXGIKeyedMutex : public IDXGIKeyedMutex {
public:
D3D11DXGIKeyedMutex(
ID3D11Resource* pResource,
D3D11Device* pDevice);
~D3D11DXGIKeyedMutex();
ULONG STDMETHODCALLTYPE AddRef();
ULONG STDMETHODCALLTYPE Release();
HRESULT STDMETHODCALLTYPE QueryInterface(
REFIID riid,
void** ppvObject);
HRESULT STDMETHODCALLTYPE GetPrivateData(
REFGUID Name,
UINT* pDataSize,
void* pData);
HRESULT STDMETHODCALLTYPE SetPrivateData(
REFGUID Name,
UINT DataSize,
const void* pData);
HRESULT STDMETHODCALLTYPE SetPrivateDataInterface(
REFGUID Name,
const IUnknown* pUnknown);
HRESULT STDMETHODCALLTYPE GetParent(
REFIID riid,
void** ppParent);
HRESULT STDMETHODCALLTYPE GetDevice(
REFIID riid,
void** ppDevice);
HRESULT STDMETHODCALLTYPE AcquireSync(
UINT64 Key,
DWORD dwMilliseconds);
HRESULT STDMETHODCALLTYPE ReleaseSync(
UINT64 Key);
private:
ID3D11Resource* m_resource;
D3D11Device* m_device;
bool m_warned = false;
bool m_supported = false;
};
/**
* \brief IDXGIResource implementation for D3D11 resources
*/
@ -30,7 +89,8 @@ namespace dxvk {
public:
D3D11DXGIResource(
ID3D11Resource* pResource);
ID3D11Resource* pResource,
D3D11Device* pDevice);
~D3D11DXGIResource();
@ -86,13 +146,27 @@ namespace dxvk {
UINT index,
IDXGISurface2** ppSurface);
HRESULT GetKeyedMutex(void **ppvObject);
private:
ID3D11Resource* m_resource;
D3D11DXGIKeyedMutex m_keyedMutex;
};
/**
* \brief Queries D3D11on12 resource info
*
* \param [in] pResource The resource to query
* \param [out] p11on12Info 11on12 info
* \returns \c S_OK on success, or \c E_INVALIDARG
*/
HRESULT GetResource11on12Info(
ID3D11Resource* pResource,
D3D11_ON_12_RESOURCE_INFO* p11on12Info);
/**
* \brief Queries common resource description
*
@ -261,4 +335,4 @@ namespace dxvk {
};
}
}

View File

@ -47,9 +47,13 @@ namespace dxvk {
if (desc.MaxAnisotropy > 16) info.maxAnisotropy = 16.0f;
// Enforce LOD bias specified in the device options
if (info.minFilter == VK_FILTER_LINEAR && info.magFilter == VK_FILTER_LINEAR)
if (info.minFilter == VK_FILTER_LINEAR && info.magFilter == VK_FILTER_LINEAR) {
info.mipmapLodBias += device->GetOptions()->samplerLodBias;
if (device->GetOptions()->clampNegativeLodBias)
info.mipmapLodBias = std::max(info.mipmapLodBias, 0.0f);
}
// Enforce anisotropy specified in the device options
int32_t samplerAnisotropyOption = device->GetOptions()->samplerAnisotropy;
@ -86,8 +90,11 @@ namespace dxvk {
return S_OK;
}
Logger::warn("D3D11SamplerState::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
if (logQueryInterfaceError(__uuidof(ID3D11SamplerState), riid)) {
Logger::warn("D3D11SamplerState::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
}
return E_NOINTERFACE;
}

View File

@ -20,8 +20,6 @@ namespace dxvk {
reinterpret_cast<const char*>(pShaderBytecode),
BytecodeLength);
DxbcModule module(reader);
// If requested by the user, dump both the raw DXBC
// shader and the compiled SPIR-V module to a file.
const std::string& dumpPath = pDevice->GetOptions()->shaderDumpPath;
@ -30,14 +28,21 @@ namespace dxvk {
reader.store(std::ofstream(str::topath(str::format(dumpPath, "/", name, ".dxbc").c_str()).c_str(),
std::ios_base::binary | std::ios_base::trunc));
}
// Error out if the shader is invalid
DxbcModule module(reader);
auto programInfo = module.programInfo();
if (!programInfo)
throw DxvkError("Invalid shader binary.");
// Decide whether we need to create a pass-through
// geometry shader for vertex shader stream output
bool passthroughShader = pDxbcModuleInfo->xfb != nullptr
&& (module.programInfo().type() == DxbcProgramType::VertexShader
|| module.programInfo().type() == DxbcProgramType::DomainShader);
&& (programInfo->type() == DxbcProgramType::VertexShader
|| programInfo->type() == DxbcProgramType::DomainShader);
if (module.programInfo().shaderStage() != pShaderKey->type() && !passthroughShader)
if (programInfo->shaderStage() != pShaderKey->type() && !passthroughShader)
throw DxvkError("Mismatching shader type.");
m_shader = passthroughShader

View File

@ -134,7 +134,11 @@ namespace dxvk {
return S_OK;
}
Logger::warn("D3D11Shader::QueryInterface: Unknown interface query");
if (logQueryInterfaceError(__uuidof(D3D11Interface), riid)) {
Logger::warn("D3D11Shader::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
}
return E_NOINTERFACE;
}

View File

@ -29,8 +29,11 @@ namespace dxvk {
return S_OK;
}
Logger::warn("D3D11DeviceContextState::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
if (logQueryInterfaceError(__uuidof(ID3DDeviceContextState), riid)) {
Logger::warn("D3D11DeviceContextState::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
}
return E_NOINTERFACE;
}

View File

@ -12,6 +12,46 @@ namespace dxvk {
return uint16_t(65535.0f * x);
}
static VkColorSpaceKHR ConvertColorSpace(DXGI_COLOR_SPACE_TYPE colorspace) {
switch (colorspace) {
case DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709: return VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
case DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020: return VK_COLOR_SPACE_HDR10_ST2084_EXT;
case DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709: return VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT;
default:
Logger::warn(str::format("DXGI: ConvertColorSpace: Unknown colorspace ", colorspace));
return VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
}
}
static VkXYColorEXT ConvertXYColor(const UINT16 (&dxgiColor)[2]) {
return VkXYColorEXT{ float(dxgiColor[0]) / 50000.0f, float(dxgiColor[1]) / 50000.0f };
}
static float ConvertMaxLuminance(UINT dxgiLuminance) {
return float(dxgiLuminance);
}
static float ConvertMinLuminance(UINT dxgiLuminance) {
return float(dxgiLuminance) * 0.0001f;
}
static float ConvertLevel(UINT16 dxgiLevel) {
return float(dxgiLevel);
}
static VkHdrMetadataEXT ConvertHDRMetadata(const DXGI_HDR_METADATA_HDR10& dxgiMetadata) {
VkHdrMetadataEXT vkMetadata = { VK_STRUCTURE_TYPE_HDR_METADATA_EXT };
vkMetadata.displayPrimaryRed = ConvertXYColor(dxgiMetadata.RedPrimary);
vkMetadata.displayPrimaryGreen = ConvertXYColor(dxgiMetadata.GreenPrimary);
vkMetadata.displayPrimaryBlue = ConvertXYColor(dxgiMetadata.BluePrimary);
vkMetadata.whitePoint = ConvertXYColor(dxgiMetadata.WhitePoint);
vkMetadata.maxLuminance = ConvertMaxLuminance(dxgiMetadata.MaxMasteringLuminance);
vkMetadata.minLuminance = ConvertMinLuminance(dxgiMetadata.MinMasteringLuminance);
vkMetadata.maxContentLightLevel = ConvertLevel(dxgiMetadata.MaxContentLightLevel);
vkMetadata.maxFrameAverageLightLevel = ConvertLevel(dxgiMetadata.MaxFrameAverageLightLevel);
return vkMetadata;
}
D3D11SwapChain::D3D11SwapChain(
D3D11DXGIDevice* pContainer,
@ -32,7 +72,7 @@ namespace dxvk {
CreateHud();
if (!pDevice->GetOptions()->deferSurfaceCreation)
RecreateSwapChain(false);
RecreateSwapChain();
}
@ -58,12 +98,17 @@ namespace dxvk {
InitReturnPtr(ppvObject);
if (riid == __uuidof(IUnknown)
|| riid == __uuidof(IDXGIVkSwapChain)) {
|| riid == __uuidof(IDXGIVkSwapChain)
|| riid == __uuidof(IDXGIVkSwapChain1)) {
*ppvObject = ref(this);
return S_OK;
}
Logger::warn("D3D11SwapChain::QueryInterface: Unknown interface query");
if (logQueryInterfaceError(__uuidof(IDXGIVkSwapChain), riid)) {
Logger::warn("D3D11SwapChain::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
}
return E_NOINTERFACE;
}
@ -116,12 +161,10 @@ namespace dxvk {
HANDLE STDMETHODCALLTYPE D3D11SwapChain::GetFrameLatencyEvent() {
HANDLE result = nullptr;
HANDLE processHandle = GetCurrentProcess();
if (!m_processHandle)
m_processHandle = GetCurrentProcess();
if (!DuplicateHandle(m_processHandle, m_frameLatencyEvent,
m_processHandle, &result, 0, FALSE, DUPLICATE_SAME_ACCESS)) {
if (!DuplicateHandle(processHandle, m_frameLatencyEvent,
processHandle, &result, 0, FALSE, DUPLICATE_SAME_ACCESS)) {
Logger::err("DxgiSwapChain::GetFrameLatencyWaitableObject: DuplicateHandle failed");
return nullptr;
}
@ -211,22 +254,13 @@ namespace dxvk {
UINT SyncInterval,
UINT PresentFlags,
const DXGI_PRESENT_PARAMETERS* pPresentParameters) {
auto options = m_parent->GetOptions();
if (options->syncInterval >= 0)
SyncInterval = options->syncInterval;
if (!(PresentFlags & DXGI_PRESENT_TEST)) {
bool vsync = SyncInterval != 0;
m_dirty |= vsync != m_vsync;
m_vsync = vsync;
}
if (!(PresentFlags & DXGI_PRESENT_TEST))
m_dirty |= m_presenter->setSyncInterval(SyncInterval) != VK_SUCCESS;
HRESULT hr = S_OK;
if (!m_presenter->hasSwapChain()) {
RecreateSwapChain(m_vsync);
RecreateSwapChain();
m_dirty = false;
}
@ -236,19 +270,29 @@ namespace dxvk {
if (m_device->getDeviceStatus() != VK_SUCCESS)
hr = DXGI_ERROR_DEVICE_RESET;
if ((PresentFlags & DXGI_PRESENT_TEST) || hr != S_OK)
if (PresentFlags & DXGI_PRESENT_TEST)
return hr;
if (hr != S_OK) {
SyncFrameLatency();
return hr;
}
if (std::exchange(m_dirty, false))
RecreateSwapChain(m_vsync);
RecreateSwapChain();
try {
PresentImage(SyncInterval);
hr = PresentImage(SyncInterval);
} catch (const DxvkError& e) {
Logger::err(e.message());
hr = E_FAIL;
}
// Ensure to synchronize and release the frame latency semaphore
// even if presentation failed with STATUS_OCCLUDED, or otherwise
// applications using the semaphore may deadlock. This works because
// we do not increment the frame ID in those situations.
SyncFrameLatency();
return hr;
}
@ -257,7 +301,8 @@ namespace dxvk {
DXGI_COLOR_SPACE_TYPE ColorSpace) {
UINT supportFlags = 0;
if (ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709)
const VkColorSpaceKHR vkColorSpace = ConvertColorSpace(ColorSpace);
if (m_presenter->supportsColorSpace(vkColorSpace))
supportFlags |= DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT;
return supportFlags;
@ -266,7 +311,13 @@ namespace dxvk {
HRESULT STDMETHODCALLTYPE D3D11SwapChain::SetColorSpace(
DXGI_COLOR_SPACE_TYPE ColorSpace) {
// Ignore, will only ever be sRGB
if (!(CheckColorSpaceSupport(ColorSpace) & DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT))
return E_INVALIDARG;
const VkColorSpaceKHR vkColorSpace = ConvertColorSpace(ColorSpace);
m_dirty |= vkColorSpace != m_colorspace;
m_colorspace = vkColorSpace;
return S_OK;
}
@ -274,51 +325,63 @@ namespace dxvk {
HRESULT STDMETHODCALLTYPE D3D11SwapChain::SetHDRMetaData(
const DXGI_VK_HDR_METADATA* pMetaData) {
// For some reason this call always seems to succeed on Windows
if (pMetaData->Type == DXGI_HDR_METADATA_TYPE_HDR10)
Logger::warn("D3D11: HDR10 metadata not supported");
if (pMetaData->Type == DXGI_HDR_METADATA_TYPE_HDR10) {
m_hdrMetadata = ConvertHDRMetadata(pMetaData->HDR10);
m_dirtyHdrMetadata = true;
}
return S_OK;
}
HRESULT D3D11SwapChain::PresentImage(UINT SyncInterval) {
Com<ID3D11DeviceContext> deviceContext = nullptr;
m_parent->GetImmediateContext(&deviceContext);
void STDMETHODCALLTYPE D3D11SwapChain::GetLastPresentCount(
UINT64* pLastPresentCount) {
*pLastPresentCount = UINT64(m_frameId - DXGI_MAX_SWAP_CHAIN_BUFFERS);
}
void STDMETHODCALLTYPE D3D11SwapChain::GetFrameStatistics(
DXGI_VK_FRAME_STATISTICS* pFrameStatistics) {
std::lock_guard<dxvk::mutex> lock(m_frameStatisticsLock);
*pFrameStatistics = m_frameStatistics;
}
HRESULT D3D11SwapChain::PresentImage(UINT SyncInterval) {
// Flush pending rendering commands before
auto immediateContext = static_cast<D3D11ImmediateContext*>(deviceContext.ptr());
auto immediateContext = m_parent->GetContext();
immediateContext->EndFrame();
immediateContext->Flush();
// Bump our frame id.
++m_frameId;
for (uint32_t i = 0; i < SyncInterval || i < 1; i++) {
SynchronizePresent();
if (!m_presenter->hasSwapChain())
return DXGI_STATUS_OCCLUDED;
return i ? S_OK : DXGI_STATUS_OCCLUDED;
// Presentation semaphores and WSI swap chain image
vk::PresenterInfo info = m_presenter->info();
vk::PresenterSync sync;
PresenterInfo info = m_presenter->info();
PresenterSync sync;
uint32_t imageIndex = 0;
VkResult status = m_presenter->acquireNextImage(sync, imageIndex);
while (status != VK_SUCCESS && status != VK_SUBOPTIMAL_KHR) {
RecreateSwapChain(m_vsync);
RecreateSwapChain();
if (!m_presenter->hasSwapChain())
return DXGI_STATUS_OCCLUDED;
return i ? S_OK : DXGI_STATUS_OCCLUDED;
info = m_presenter->info();
status = m_presenter->acquireNextImage(sync, imageIndex);
}
// Resolve back buffer if it is multisampled. We
// only have to do it only for the first frame.
if (m_hdrMetadata && m_dirtyHdrMetadata) {
m_presenter->setHdrMetadata(*m_hdrMetadata);
m_dirtyHdrMetadata = false;
}
m_context->beginRecording(
m_device->createCommandList());
@ -329,40 +392,45 @@ namespace dxvk {
if (m_hud != nullptr)
m_hud->render(m_context, info.format, info.imageExtent);
if (i + 1 >= SyncInterval)
m_context->signal(m_frameLatencySignal, m_frameId);
SubmitPresent(immediateContext, sync, i);
}
SyncFrameLatency();
return S_OK;
}
void D3D11SwapChain::SubmitPresent(
D3D11ImmediateContext* pContext,
const vk::PresenterSync& Sync,
uint32_t FrameId) {
const PresenterSync& Sync,
uint32_t Repeat) {
auto lock = pContext->LockContext();
// Bump frame ID as necessary
if (!Repeat)
m_frameId += 1;
// Present from CS thread so that we don't
// have to synchronize with it first.
m_presentStatus.result = VK_NOT_READY;
pContext->EmitCs([this,
cFrameId = FrameId,
cRepeat = Repeat,
cSync = Sync,
cHud = m_hud,
cPresentMode = m_presenter->info().presentMode,
cFrameId = m_frameId,
cCommandList = m_context->endRecording()
] (DxvkContext* ctx) {
cCommandList->setWsiSemaphores(cSync);
m_device->submitCommandList(cCommandList);
m_device->submitCommandList(cCommandList, nullptr);
if (cHud != nullptr && !cFrameId)
if (cHud != nullptr && !cRepeat)
cHud->update();
m_device->presentImage(m_presenter, &m_presentStatus);
uint64_t frameId = cRepeat ? 0 : cFrameId;
m_device->presentImage(m_presenter,
cPresentMode, frameId, &m_presentStatus);
});
pContext->FlushCsChunk();
@ -374,22 +442,22 @@ namespace dxvk {
VkResult status = m_device->waitForSubmission(&m_presentStatus);
if (status != VK_SUCCESS)
RecreateSwapChain(m_vsync);
RecreateSwapChain();
}
void D3D11SwapChain::RecreateSwapChain(BOOL Vsync) {
void D3D11SwapChain::RecreateSwapChain() {
// Ensure that we can safely destroy the swap chain
m_device->waitForSubmission(&m_presentStatus);
m_device->waitForIdle();
m_presentStatus.result = VK_SUCCESS;
m_dirtyHdrMetadata = true;
vk::PresenterDesc presenterDesc;
PresenterDesc presenterDesc;
presenterDesc.imageExtent = { m_desc.Width, m_desc.Height };
presenterDesc.imageCount = PickImageCount(m_desc.BufferCount + 1);
presenterDesc.numFormats = PickFormats(m_desc.Format, presenterDesc.formats);
presenterDesc.numPresentModes = PickPresentModes(Vsync, presenterDesc.presentModes);
presenterDesc.fullScreenExclusive = PickFullscreenMode();
VkResult vr = m_presenter->recreateSwapChain(presenterDesc);
@ -421,27 +489,13 @@ namespace dxvk {
void D3D11SwapChain::CreatePresenter() {
DxvkDeviceQueue graphicsQueue = m_device->queues().graphics;
vk::PresenterDevice presenterDevice;
presenterDevice.queueFamily = graphicsQueue.queueFamily;
presenterDevice.queue = graphicsQueue.queueHandle;
presenterDevice.adapter = m_device->adapter()->handle();
presenterDevice.features.fullScreenExclusive = m_device->features().extFullScreenExclusive;
vk::PresenterDesc presenterDesc;
PresenterDesc presenterDesc;
presenterDesc.imageExtent = { m_desc.Width, m_desc.Height };
presenterDesc.imageCount = PickImageCount(m_desc.BufferCount + 1);
presenterDesc.numFormats = PickFormats(m_desc.Format, presenterDesc.formats);
presenterDesc.numPresentModes = PickPresentModes(false, presenterDesc.presentModes);
presenterDesc.fullScreenExclusive = PickFullscreenMode();
m_presenter = new vk::Presenter(
m_device->adapter()->vki(),
m_device->vkd(),
presenterDevice,
presenterDesc);
m_presenter = new Presenter(m_device, m_frameLatencySignal, presenterDesc);
m_presenter->setFrameRateLimit(m_parent->GetOptions()->maxFrameRate);
}
@ -456,7 +510,7 @@ namespace dxvk {
void D3D11SwapChain::CreateRenderTargetViews() {
vk::PresenterInfo info = m_presenter->info();
PresenterInfo info = m_presenter->info();
m_imageViews.clear();
m_imageViews.resize(info.imageCount);
@ -490,7 +544,8 @@ namespace dxvk {
VkImage imageHandle = m_presenter->getImage(i).image;
Rc<DxvkImage> image = new DxvkImage(
m_device.ptr(), imageInfo, imageHandle);
m_device.ptr(), imageInfo, imageHandle,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
m_imageViews[i] = new DxvkImageView(
m_device->vkd(), image, viewInfo);
@ -570,7 +625,8 @@ namespace dxvk {
subresources, VK_IMAGE_LAYOUT_UNDEFINED);
m_device->submitCommandList(
m_context->endRecording());
m_context->endRecording(),
nullptr);
}
@ -596,11 +652,17 @@ namespace dxvk {
// Wait for the sync event so that we respect the maximum frame latency
m_frameLatencySignal->wait(m_frameId - GetActualFrameLatency());
if (m_frameLatencyEvent) {
m_frameLatencySignal->setCallback(m_frameId, [cFrameLatencyEvent = m_frameLatencyEvent] () {
m_frameLatencySignal->setCallback(m_frameId, [this,
cFrameId = m_frameId,
cFrameLatencyEvent = m_frameLatencyEvent
] () {
if (cFrameLatencyEvent)
ReleaseSemaphore(cFrameLatencyEvent, 1, nullptr);
});
}
std::lock_guard<dxvk::mutex> lock(m_frameStatisticsLock);
m_frameStatistics.PresentCount = cFrameId - DXGI_MAX_SWAP_CHAIN_BUFFERS;
m_frameStatistics.PresentQPCTime = dxvk::high_resolution_clock::get_counter();
});
}
@ -616,7 +678,7 @@ namespace dxvk {
if (m_frameLatencyCap)
maxFrameLatency = std::min(maxFrameLatency, m_frameLatencyCap);
maxFrameLatency = std::min(maxFrameLatency, m_desc.BufferCount + 1);
maxFrameLatency = std::min(maxFrameLatency, m_desc.BufferCount);
return maxFrameLatency;
}
@ -633,23 +695,23 @@ namespace dxvk {
case DXGI_FORMAT_R8G8B8A8_UNORM:
case DXGI_FORMAT_B8G8R8A8_UNORM: {
pDstFormats[n++] = { VK_FORMAT_R8G8B8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
pDstFormats[n++] = { VK_FORMAT_B8G8R8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
pDstFormats[n++] = { VK_FORMAT_R8G8B8A8_UNORM, m_colorspace };
pDstFormats[n++] = { VK_FORMAT_B8G8R8A8_UNORM, m_colorspace };
} break;
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: {
pDstFormats[n++] = { VK_FORMAT_R8G8B8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
pDstFormats[n++] = { VK_FORMAT_B8G8R8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
pDstFormats[n++] = { VK_FORMAT_R8G8B8A8_SRGB, m_colorspace };
pDstFormats[n++] = { VK_FORMAT_B8G8R8A8_SRGB, m_colorspace };
} break;
case DXGI_FORMAT_R10G10B10A2_UNORM: {
pDstFormats[n++] = { VK_FORMAT_A2B10G10R10_UNORM_PACK32, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
pDstFormats[n++] = { VK_FORMAT_A2R10G10B10_UNORM_PACK32, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
pDstFormats[n++] = { VK_FORMAT_A2B10G10R10_UNORM_PACK32, m_colorspace };
pDstFormats[n++] = { VK_FORMAT_A2R10G10B10_UNORM_PACK32, m_colorspace };
} break;
case DXGI_FORMAT_R16G16B16A16_FLOAT: {
pDstFormats[n++] = { VK_FORMAT_R16G16B16A16_SFLOAT, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
pDstFormats[n++] = { VK_FORMAT_R16G16B16A16_SFLOAT, m_colorspace };
} break;
}
@ -657,25 +719,6 @@ namespace dxvk {
}
uint32_t D3D11SwapChain::PickPresentModes(
BOOL Vsync,
VkPresentModeKHR* pDstModes) {
uint32_t n = 0;
if (Vsync) {
if (m_parent->GetOptions()->tearFree == Tristate::False)
pDstModes[n++] = VK_PRESENT_MODE_FIFO_RELAXED_KHR;
pDstModes[n++] = VK_PRESENT_MODE_FIFO_KHR;
} else {
if (m_parent->GetOptions()->tearFree != Tristate::True)
pDstModes[n++] = VK_PRESENT_MODE_IMMEDIATE_KHR;
pDstModes[n++] = VK_PRESENT_MODE_MAILBOX_KHR;
}
return n;
}
uint32_t D3D11SwapChain::PickImageCount(
UINT Preferred) {
int32_t option = m_parent->GetOptions()->numBackBuffers;

View File

@ -13,7 +13,7 @@ namespace dxvk {
class D3D11Device;
class D3D11DXGIDevice;
class D3D11SwapChain : public ComObject<IDXGIVkSwapChain> {
class D3D11SwapChain : public ComObject<IDXGIVkSwapChain1> {
constexpr static uint32_t DefaultFrameLatency = 1;
public:
@ -80,6 +80,12 @@ namespace dxvk {
HRESULT STDMETHODCALLTYPE SetHDRMetaData(
const DXGI_VK_HDR_METADATA* pMetaData);
void STDMETHODCALLTYPE GetLastPresentCount(
UINT64* pLastPresentCount);
void STDMETHODCALLTYPE GetFrameStatistics(
DXGI_VK_FRAME_STATISTICS* pFrameStatistics);
private:
enum BindingIds : uint32_t {
@ -97,7 +103,7 @@ namespace dxvk {
Rc<DxvkDevice> m_device;
Rc<DxvkContext> m_context;
Rc<vk::Presenter> m_presenter;
Rc<Presenter> m_presenter;
Rc<DxvkImage> m_swapImage;
Rc<DxvkImageView> m_swapImageView;
@ -116,22 +122,26 @@ namespace dxvk {
HANDLE m_frameLatencyEvent = nullptr;
Rc<sync::CallbackFence> m_frameLatencySignal;
HANDLE m_processHandle = nullptr;
bool m_dirty = true;
bool m_vsync = true;
VkColorSpaceKHR m_colorspace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
std::optional<VkHdrMetadataEXT> m_hdrMetadata;
bool m_dirtyHdrMetadata = true;
dxvk::mutex m_frameStatisticsLock;
DXGI_VK_FRAME_STATISTICS m_frameStatistics = { };
HRESULT PresentImage(UINT SyncInterval);
void SubmitPresent(
D3D11ImmediateContext* pContext,
const vk::PresenterSync& Sync,
uint32_t FrameId);
const PresenterSync& Sync,
uint32_t Repeat);
void SynchronizePresent();
void RecreateSwapChain(
BOOL Vsync);
void RecreateSwapChain();
void CreateFrameLatencyEvent();
@ -157,10 +167,6 @@ namespace dxvk {
DXGI_FORMAT Format,
VkSurfaceFormatKHR* pDstFormats);
uint32_t PickPresentModes(
BOOL Vsync,
VkPresentModeKHR* pDstModes);
uint32_t PickImageCount(
UINT Preferred);

View File

@ -11,11 +11,13 @@ namespace dxvk {
ID3D11Resource* pInterface,
D3D11Device* pDevice,
const D3D11_COMMON_TEXTURE_DESC* pDesc,
const D3D11_ON_12_RESOURCE_INFO* p11on12Info,
D3D11_RESOURCE_DIMENSION Dimension,
DXGI_USAGE DxgiUsage,
VkImage vkImage,
HANDLE hSharedHandle)
: m_interface(pInterface), m_device(pDevice), m_dimension(Dimension), m_desc(*pDesc), m_dxgiUsage(DxgiUsage) {
: m_interface(pInterface), m_device(pDevice), m_dimension(Dimension), m_desc(*pDesc),
m_11on12(p11on12Info ? *p11on12Info : D3D11_ON_12_RESOURCE_INFO()), m_dxgiUsage(DxgiUsage) {
DXGI_VK_FORMAT_MODE formatMode = GetFormatMode();
DXGI_VK_FORMAT_INFO formatInfo = m_device->LookupFormat(m_desc.Format, formatMode);
DXGI_VK_FORMAT_FAMILY formatFamily = m_device->LookupFamily(m_desc.Format, formatMode);
@ -46,15 +48,21 @@ namespace dxvk {
if (hSharedHandle == nullptr)
hSharedHandle = INVALID_HANDLE_VALUE;
if (m_desc.MiscFlags & (D3D11_RESOURCE_MISC_SHARED|D3D11_RESOURCE_MISC_SHARED_NTHANDLE)) {
if (m_desc.MiscFlags & D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX)
Logger::warn("D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX: not supported.");
const auto sharingFlags = D3D11_RESOURCE_MISC_SHARED|D3D11_RESOURCE_MISC_SHARED_NTHANDLE|D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
if (m_desc.MiscFlags & sharingFlags) {
if (pDevice->GetFeatureLevel() < D3D_FEATURE_LEVEL_10_0 ||
(m_desc.MiscFlags & (D3D11_RESOURCE_MISC_SHARED|D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX)) == (D3D11_RESOURCE_MISC_SHARED|D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX) ||
(m_desc.MiscFlags & sharingFlags) == D3D11_RESOURCE_MISC_SHARED_NTHANDLE)
throw DxvkError(str::format("D3D11: Cannot create shared texture:",
"\n MiscFlags: ", m_desc.MiscFlags,
"\n FeatureLevel: ", pDevice->GetFeatureLevel()));
imageInfo.shared = true;
imageInfo.sharing.mode = hSharedHandle == INVALID_HANDLE_VALUE ? DxvkSharedHandleMode::Export : DxvkSharedHandleMode::Import;
imageInfo.sharing.type = (m_desc.MiscFlags & D3D11_RESOURCE_MISC_SHARED)
? VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT
: VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT;
imageInfo.sharing.type = (m_desc.MiscFlags & D3D11_RESOURCE_MISC_SHARED_NTHANDLE)
? VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
: VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT;
imageInfo.sharing.handle = hSharedHandle;
}
@ -203,9 +211,12 @@ namespace dxvk {
// For some formats, we need to enable sampled and/or
// render target capabilities if available, but these
// 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 |= 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
if (!CheckImageSupport(&imageInfo, imageInfo.tiling)) {
throw DxvkError(str::format(
@ -228,10 +239,13 @@ namespace dxvk {
if (m_mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT)
memoryProperties = GetMemoryFlags();
if (vkImage == VK_NULL_HANDLE)
if (m_11on12.Resource != nullptr)
vkImage = VkImage(m_11on12.VulkanHandle);
if (!vkImage)
m_image = m_device->GetDXVKDevice()->createImage(imageInfo, memoryProperties);
else
m_image = m_device->GetDXVKDevice()->createImageFromVkImage(imageInfo, vkImage);
m_image = m_device->GetDXVKDevice()->importImage(imageInfo, vkImage, memoryProperties);
if (imageInfo.sharing.mode == DxvkSharedHandleMode::Export)
ExportImageInfo();
@ -469,9 +483,60 @@ namespace dxvk {
}
HRESULT D3D11CommonTexture::GetDescFromD3D12(
ID3D12Resource* pResource,
const D3D11_RESOURCE_FLAGS* pResourceFlags,
D3D11_COMMON_TEXTURE_DESC* pTextureDesc) {
D3D12_RESOURCE_DESC desc12 = pResource->GetDesc();
pTextureDesc->Width = desc12.Width;
pTextureDesc->Height = desc12.Height;
if (desc12.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D) {
pTextureDesc->Depth = desc12.DepthOrArraySize;
pTextureDesc->ArraySize = 1;
} else {
pTextureDesc->Depth = 1;
pTextureDesc->ArraySize = desc12.DepthOrArraySize;
}
pTextureDesc->MipLevels = desc12.MipLevels;
pTextureDesc->Format = desc12.Format;
pTextureDesc->SampleDesc = desc12.SampleDesc;
pTextureDesc->Usage = D3D11_USAGE_DEFAULT;
pTextureDesc->BindFlags = 0;
pTextureDesc->CPUAccessFlags = 0;
pTextureDesc->MiscFlags = 0;
if (!(desc12.Flags & D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE))
pTextureDesc->BindFlags |= D3D11_BIND_SHADER_RESOURCE;
if (desc12.Flags & D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET)
pTextureDesc->BindFlags |= D3D11_BIND_RENDER_TARGET;
if (desc12.Flags & D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL)
pTextureDesc->BindFlags |= D3D11_BIND_DEPTH_STENCIL;
if (desc12.Flags & D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS)
pTextureDesc->BindFlags |= D3D11_BIND_UNORDERED_ACCESS;
if (pResourceFlags) {
pTextureDesc->BindFlags = pResourceFlags->BindFlags;
pTextureDesc->MiscFlags |= pResourceFlags->MiscFlags;
pTextureDesc->CPUAccessFlags = pResourceFlags->CPUAccessFlags;
}
return S_OK;
}
BOOL D3D11CommonTexture::CheckImageSupport(
const DxvkImageCreateInfo* pImageInfo,
VkImageTiling Tiling) const {
// D3D12 images always use optimal tiling
if (m_11on12.Resource != nullptr && Tiling != VK_IMAGE_TILING_OPTIMAL)
return FALSE;
DxvkFormatQuery formatQuery = { };
formatQuery.format = pImageInfo->format;
formatQuery.type = pImageInfo->type;
@ -486,7 +551,7 @@ namespace dxvk {
if (!properties)
return FALSE;
return (pImageInfo->extent.width <= properties->maxExtent.width)
&& (pImageInfo->extent.height <= properties->maxExtent.height)
&& (pImageInfo->extent.depth <= properties->maxExtent.depth)
@ -640,10 +705,10 @@ namespace dxvk {
void D3D11CommonTexture::ExportImageInfo() {
HANDLE hSharedHandle;
if (m_desc.MiscFlags & D3D11_RESOURCE_MISC_SHARED)
hSharedHandle = openKmtHandle( m_image->sharedHandle() );
else
if (m_desc.MiscFlags & D3D11_RESOURCE_MISC_SHARED_NTHANDLE)
hSharedHandle = m_image->sharedHandle();
else
hSharedHandle = openKmtHandle( m_image->sharedHandle() );
DxvkSharedTextureMetadata metadata;
@ -663,7 +728,7 @@ namespace dxvk {
Logger::warn("D3D11: Failed to write shared resource info for a texture");
}
if ((m_desc.MiscFlags & D3D11_RESOURCE_MISC_SHARED) && hSharedHandle != INVALID_HANDLE_VALUE)
if (hSharedHandle != INVALID_HANDLE_VALUE)
CloseHandle(hSharedHandle);
}
@ -1028,12 +1093,13 @@ namespace dxvk {
// D 3 D 1 1 T E X T U R E 1 D
D3D11Texture1D::D3D11Texture1D(
D3D11Device* pDevice,
const D3D11_COMMON_TEXTURE_DESC* pDesc)
const D3D11_COMMON_TEXTURE_DESC* pDesc,
const D3D11_ON_12_RESOURCE_INFO* p11on12Info)
: D3D11DeviceChild<ID3D11Texture1D>(pDevice),
m_texture (this, pDevice, pDesc, D3D11_RESOURCE_DIMENSION_TEXTURE1D, 0, VK_NULL_HANDLE, nullptr),
m_texture (this, pDevice, pDesc, p11on12Info, D3D11_RESOURCE_DIMENSION_TEXTURE1D, 0, VK_NULL_HANDLE, nullptr),
m_interop (this, &m_texture),
m_surface (this, &m_texture),
m_resource(this),
m_resource(this, pDevice),
m_d3d10 (this) {
}
@ -1080,14 +1146,20 @@ namespace dxvk {
*ppvObject = ref(&m_resource);
return S_OK;
}
if (riid == __uuidof(IDXGIKeyedMutex))
return m_resource.GetKeyedMutex(ppvObject);
if (riid == __uuidof(IDXGIVkInteropSurface)) {
*ppvObject = ref(&m_interop);
return S_OK;
}
Logger::warn("D3D11Texture1D::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
if (logQueryInterfaceError(__uuidof(ID3D10Texture1D), riid)) {
Logger::warn("D3D11Texture1D::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
}
return E_NOINTERFACE;
}
@ -1127,12 +1199,13 @@ namespace dxvk {
D3D11Texture2D::D3D11Texture2D(
D3D11Device* pDevice,
const D3D11_COMMON_TEXTURE_DESC* pDesc,
const D3D11_ON_12_RESOURCE_INFO* p11on12Info,
HANDLE hSharedHandle)
: D3D11DeviceChild<ID3D11Texture2D1>(pDevice),
m_texture (this, pDevice, pDesc, D3D11_RESOURCE_DIMENSION_TEXTURE2D, 0, VK_NULL_HANDLE, hSharedHandle),
m_texture (this, pDevice, pDesc, p11on12Info, D3D11_RESOURCE_DIMENSION_TEXTURE2D, 0, VK_NULL_HANDLE, hSharedHandle),
m_interop (this, &m_texture),
m_surface (this, &m_texture),
m_resource (this),
m_resource (this, pDevice),
m_d3d10 (this),
m_swapChain (nullptr) {
}
@ -1144,10 +1217,10 @@ namespace dxvk {
DXGI_USAGE DxgiUsage,
VkImage vkImage)
: D3D11DeviceChild<ID3D11Texture2D1>(pDevice),
m_texture (this, pDevice, pDesc, D3D11_RESOURCE_DIMENSION_TEXTURE2D, DxgiUsage, vkImage, nullptr),
m_texture (this, pDevice, pDesc, nullptr, D3D11_RESOURCE_DIMENSION_TEXTURE2D, DxgiUsage, vkImage, nullptr),
m_interop (this, &m_texture),
m_surface (this, &m_texture),
m_resource (this),
m_resource (this, pDevice),
m_d3d10 (this),
m_swapChain (nullptr) {
@ -1160,10 +1233,10 @@ namespace dxvk {
const D3D11_COMMON_TEXTURE_DESC* pDesc,
DXGI_USAGE DxgiUsage)
: D3D11DeviceChild<ID3D11Texture2D1>(pDevice),
m_texture (this, pDevice, pDesc, D3D11_RESOURCE_DIMENSION_TEXTURE2D, DxgiUsage, VK_NULL_HANDLE, nullptr),
m_texture (this, pDevice, pDesc, nullptr, D3D11_RESOURCE_DIMENSION_TEXTURE2D, DxgiUsage, VK_NULL_HANDLE, nullptr),
m_interop (this, &m_texture),
m_surface (this, &m_texture),
m_resource (this),
m_resource (this, pDevice),
m_d3d10 (this),
m_swapChain (pSwapChain) {
@ -1176,27 +1249,24 @@ namespace dxvk {
ULONG STDMETHODCALLTYPE D3D11Texture2D::AddRef() {
uint32_t refCount = m_refCount++;
uint32_t refCount = D3D11DeviceChild<ID3D11Texture2D1>::AddRef();
if (unlikely(!refCount)) {
if (m_swapChain)
if (unlikely(m_swapChain != nullptr)) {
if (refCount == 1)
m_swapChain->AddRef();
AddRefPrivate();
}
return refCount + 1;
return refCount;
}
ULONG STDMETHODCALLTYPE D3D11Texture2D::Release() {
uint32_t refCount = --m_refCount;
IUnknown* swapChain = m_swapChain;
uint32_t refCount = D3D11DeviceChild<ID3D11Texture2D1>::Release();
if (unlikely(!refCount)) {
if (m_swapChain)
m_swapChain->Release();
ReleasePrivate();
if (unlikely(swapChain != nullptr)) {
if (refCount == 0)
swapChain->Release();
}
return refCount;
@ -1240,14 +1310,20 @@ namespace dxvk {
*ppvObject = ref(&m_resource);
return S_OK;
}
if (riid == __uuidof(IDXGIKeyedMutex))
return m_resource.GetKeyedMutex(ppvObject);
if (riid == __uuidof(IDXGIVkInteropSurface)) {
*ppvObject = ref(&m_interop);
return S_OK;
}
Logger::warn("D3D11Texture2D::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
if (logQueryInterfaceError(__uuidof(ID3D10Texture2D), riid)) {
Logger::warn("D3D11Texture2D::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
}
return E_NOINTERFACE;
}
@ -1303,11 +1379,12 @@ namespace dxvk {
// D 3 D 1 1 T E X T U R E 3 D
D3D11Texture3D::D3D11Texture3D(
D3D11Device* pDevice,
const D3D11_COMMON_TEXTURE_DESC* pDesc)
const D3D11_COMMON_TEXTURE_DESC* pDesc,
const D3D11_ON_12_RESOURCE_INFO* p11on12Info)
: D3D11DeviceChild<ID3D11Texture3D1>(pDevice),
m_texture (this, pDevice, pDesc, D3D11_RESOURCE_DIMENSION_TEXTURE3D, 0, VK_NULL_HANDLE, nullptr),
m_texture (this, pDevice, pDesc, p11on12Info, D3D11_RESOURCE_DIMENSION_TEXTURE3D, 0, VK_NULL_HANDLE, nullptr),
m_interop (this, &m_texture),
m_resource(this),
m_resource(this, pDevice),
m_d3d10 (this) {
}
@ -1347,14 +1424,20 @@ namespace dxvk {
*ppvObject = ref(&m_resource);
return S_OK;
}
if (riid == __uuidof(IDXGIKeyedMutex))
return m_resource.GetKeyedMutex(ppvObject);
if (riid == __uuidof(IDXGIVkInteropSurface)) {
*ppvObject = ref(&m_interop);
return S_OK;
}
Logger::warn("D3D11Texture3D::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
if (logQueryInterfaceError(__uuidof(ID3D10Texture3D), riid)) {
Logger::warn("D3D11Texture3D::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
}
return E_NOINTERFACE;
}

View File

@ -7,6 +7,7 @@
#include "d3d11_device_child.h"
#include "d3d11_interfaces.h"
#include "d3d11_on_12.h"
#include "d3d11_resource.h"
namespace dxvk {
@ -85,6 +86,7 @@ namespace dxvk {
ID3D11Resource* pInterface,
D3D11Device* pDevice,
const D3D11_COMMON_TEXTURE_DESC* pDesc,
const D3D11_ON_12_RESOURCE_INFO* p11on12Info,
D3D11_RESOURCE_DIMENSION Dimension,
DXGI_USAGE DxgiUsage,
VkImage vkImage,
@ -435,6 +437,14 @@ namespace dxvk {
DXGI_FORMAT Format,
UINT Plane) const;
/**
* \brief Retrieves D3D11on12 resource info
* \returns 11on12 resource info
*/
D3D11_ON_12_RESOURCE_INFO Get11on12Info() const {
return m_11on12;
}
/**
* \brief Normalizes and validates texture description
*
@ -447,6 +457,19 @@ namespace dxvk {
static HRESULT NormalizeTextureProperties(
D3D11_COMMON_TEXTURE_DESC* pDesc);
/**
* \brief Initializes D3D11 texture description from D3D12
*
* \param [in] pResource D3D12 resource
* \param [in] pResourceFlags D3D11 flag overrides
* \param [out] pTextureDesc D3D11 buffer description
* \returns \c S_OK if the parameters are valid
*/
static HRESULT GetDescFromD3D12(
ID3D12Resource* pResource,
const D3D11_RESOURCE_FLAGS* pResourceFlags,
D3D11_COMMON_TEXTURE_DESC* pTextureDesc);
private:
struct MappedBuffer {
@ -465,6 +488,7 @@ namespace dxvk {
D3D11Device* m_device;
D3D11_RESOURCE_DIMENSION m_dimension;
D3D11_COMMON_TEXTURE_DESC m_desc;
D3D11_ON_12_RESOURCE_INFO m_11on12;
D3D11_COMMON_TEXTURE_MAP_MODE m_mapMode;
DXGI_USAGE m_dxgiUsage;
VkFormat m_packedFormat;
@ -636,7 +660,8 @@ namespace dxvk {
D3D11Texture1D(
D3D11Device* pDevice,
const D3D11_COMMON_TEXTURE_DESC* pDesc);
const D3D11_COMMON_TEXTURE_DESC* pDesc,
const D3D11_ON_12_RESOURCE_INFO* p11on12Info);
~D3D11Texture1D();
@ -682,6 +707,7 @@ namespace dxvk {
D3D11Texture2D(
D3D11Device* pDevice,
const D3D11_COMMON_TEXTURE_DESC* pDesc,
const D3D11_ON_12_RESOURCE_INFO* p11on12Info,
HANDLE hSharedHandle);
D3D11Texture2D(
@ -747,7 +773,8 @@ namespace dxvk {
D3D11Texture3D(
D3D11Device* pDevice,
const D3D11_COMMON_TEXTURE_DESC* pDesc);
const D3D11_COMMON_TEXTURE_DESC* pDesc,
const D3D11_ON_12_RESOURCE_INFO* p11on12Info);
~D3D11Texture3D();

View File

@ -32,8 +32,11 @@ namespace dxvk {
return S_OK;
}
Logger::warn("D3D11VideoProcessorEnumerator::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
if (logQueryInterfaceError(__uuidof(ID3D11VideoProcessorEnumerator), riid)) {
Logger::warn("D3D11VideoProcessorEnumerator::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
}
return E_NOINTERFACE;
}
@ -48,23 +51,47 @@ namespace dxvk {
HRESULT STDMETHODCALLTYPE D3D11VideoProcessorEnumerator::CheckVideoProcessorFormat(
DXGI_FORMAT Format,
UINT* pFlags) {
Logger::err("D3D11VideoProcessorEnumerator::CheckVideoProcessorFormat: Stub");
return E_NOTIMPL;
Logger::err(str::format("D3D11VideoProcessorEnumerator::CheckVideoProcessorFormat: stub, format ", Format));
if (!pFlags)
return E_INVALIDARG;
*pFlags = D3D11_VIDEO_PROCESSOR_FORMAT_SUPPORT_INPUT | D3D11_VIDEO_PROCESSOR_FORMAT_SUPPORT_OUTPUT;
return S_OK;
}
HRESULT STDMETHODCALLTYPE D3D11VideoProcessorEnumerator::GetVideoProcessorCaps(
D3D11_VIDEO_PROCESSOR_CAPS* pCaps) {
Logger::err("D3D11VideoProcessorEnumerator::GetVideoProcessorCaps: Stub");
return E_NOTIMPL;
Logger::err("D3D11VideoProcessorEnumerator::GetVideoProcessorCaps: semi-stub");
if (!pCaps)
return E_INVALIDARG;
*pCaps = {};
pCaps->RateConversionCapsCount = 1;
pCaps->MaxInputStreams = 52;
pCaps->MaxStreamStates = 52;
return S_OK;
}
HRESULT STDMETHODCALLTYPE D3D11VideoProcessorEnumerator::GetVideoProcessorRateConversionCaps(
UINT TypeIndex,
D3D11_VIDEO_PROCESSOR_RATE_CONVERSION_CAPS* pCaps) {
Logger::err("D3D11VideoProcessorEnumerator::GetVideoProcessorRateConversionCaps: Stub");
return E_NOTIMPL;
Logger::err("D3D11VideoProcessorEnumerator::GetVideoProcessorRateConversionCaps: semi-stub");
if (!pCaps || TypeIndex)
return E_INVALIDARG;
*pCaps = {};
if (m_desc.InputFrameFormat == D3D11_VIDEO_FRAME_FORMAT_PROGRESSIVE) {
pCaps->ProcessorCaps = D3D11_VIDEO_PROCESSOR_PROCESSOR_CAPS_FRAME_RATE_CONVERSION;
} else {
pCaps->ProcessorCaps = D3D11_VIDEO_PROCESSOR_PROCESSOR_CAPS_DEINTERLACE_BOB;
pCaps->PastFrames = 1;
pCaps->FutureFrames = 1;
}
return S_OK;
}
@ -112,8 +139,11 @@ namespace dxvk {
return S_OK;
}
Logger::warn("D3D11VideoProcessor::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
if (logQueryInterfaceError(__uuidof(ID3D11VideoProcessor), riid)) {
Logger::warn("D3D11VideoProcessor::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
}
return E_NOINTERFACE;
}
@ -223,8 +253,11 @@ namespace dxvk {
return S_OK;
}
Logger::warn("D3D11VideoProcessorInputView::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
if (logQueryInterfaceError(__uuidof(ID3D11VideoProcessorInputView), riid)) {
Logger::warn("D3D11VideoProcessorInputView::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
}
return E_NOINTERFACE;
}
@ -302,8 +335,11 @@ namespace dxvk {
return S_OK;
}
Logger::warn("D3D11VideoProcessorOutputView::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
if (logQueryInterfaceError(__uuidof(ID3D11VideoProcessorOutputView), riid)) {
Logger::warn("D3D11VideoProcessorOutputView::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
}
return E_NOINTERFACE;
}
@ -324,56 +360,8 @@ namespace dxvk {
D3D11VideoContext::D3D11VideoContext(
D3D11ImmediateContext* pContext,
const Rc<DxvkDevice>& Device)
: m_ctx(pContext) {
SpirvCodeBuffer vsCode(d3d11_video_blit_vert);
SpirvCodeBuffer fsCode(d3d11_video_blit_frag);
: m_ctx(pContext), m_device(Device) {
const std::array<DxvkBindingInfo, 4> fsBindings = {{
{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, VK_IMAGE_VIEW_TYPE_MAX_ENUM, VK_SHADER_STAGE_FRAGMENT_BIT, VK_ACCESS_UNIFORM_READ_BIT },
{ VK_DESCRIPTOR_TYPE_SAMPLER, 1, VK_IMAGE_VIEW_TYPE_MAX_ENUM, VK_SHADER_STAGE_FRAGMENT_BIT, 0 },
{ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 2, VK_IMAGE_VIEW_TYPE_2D, VK_SHADER_STAGE_FRAGMENT_BIT, VK_ACCESS_SHADER_READ_BIT },
{ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 3, VK_IMAGE_VIEW_TYPE_2D, VK_SHADER_STAGE_FRAGMENT_BIT, VK_ACCESS_SHADER_READ_BIT },
}};
DxvkShaderCreateInfo vsInfo;
vsInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
vsInfo.outputMask = 0x1;
m_vs = new DxvkShader(vsInfo, std::move(vsCode));
DxvkShaderCreateInfo fsInfo;
fsInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
fsInfo.bindingCount = fsBindings.size();
fsInfo.bindings = fsBindings.data();
fsInfo.inputMask = 0x1;
fsInfo.outputMask = 0x1;
m_fs = new DxvkShader(fsInfo, std::move(fsCode));
DxvkSamplerCreateInfo samplerInfo;
samplerInfo.magFilter = VK_FILTER_LINEAR;
samplerInfo.minFilter = VK_FILTER_LINEAR;
samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
samplerInfo.mipmapLodBias = 0.0f;
samplerInfo.mipmapLodMin = 0.0f;
samplerInfo.mipmapLodMax = 0.0f;
samplerInfo.useAnisotropy = VK_FALSE;
samplerInfo.maxAnisotropy = 1.0f;
samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
samplerInfo.compareToDepth = VK_FALSE;
samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS;
samplerInfo.reductionMode = VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE;
samplerInfo.borderColor = VkClearColorValue();
samplerInfo.usePixelCoord = VK_FALSE;
samplerInfo.nonSeamless = VK_FALSE;
m_sampler = Device->createSampler(samplerInfo);
DxvkBufferCreateInfo bufferInfo;
bufferInfo.size = sizeof(UboData);
bufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
bufferInfo.stages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
bufferInfo.access = VK_ACCESS_UNIFORM_READ_BIT;
m_ubo = Device->createBuffer(bufferInfo, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
}
@ -603,7 +591,9 @@ namespace dxvk {
D3D11_VIDEO_PROCESSOR_OUTPUT_RATE Rate,
BOOL Repeat,
const DXGI_RATIONAL* CustomRate) {
Logger::err("D3D11VideoContext::VideoProcessorSetStreamOutputRate: Stub");
Logger::err(str::format("D3D11VideoContext::VideoProcessorSetStreamOutputRate: Stub, Rate ", Rate));
if (CustomRate)
Logger::err(str::format("CustomRate ", CustomRate->Numerator, "/", CustomRate->Denominator));
}
@ -1200,9 +1190,6 @@ namespace dxvk {
rt.color[0].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
ctx->bindRenderTargets(std::move(rt), 0u);
ctx->bindShader<VK_SHADER_STAGE_VERTEX_BIT>(Rc<DxvkShader>(m_vs));
ctx->bindShader<VK_SHADER_STAGE_FRAGMENT_BIT>(Rc<DxvkShader>(m_fs));
ctx->bindResourceBuffer(VK_SHADER_STAGE_FRAGMENT_BIT, 0, DxvkBufferSlice(m_ubo));
DxvkInputAssemblyState iaState;
iaState.primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
@ -1219,6 +1206,8 @@ namespace dxvk {
void D3D11VideoContext::BlitStream(
const D3D11VideoProcessorStreamState* pStreamState,
const D3D11_VIDEO_PROCESSOR_STREAM* pStream) {
CreateResources();
if (pStream->PastFrames || pStream->FutureFrames)
Logger::err("D3D11VideoContext: Ignoring non-zero PastFrames and FutureFrames");
@ -1273,12 +1262,28 @@ namespace dxvk {
viewport.height = float(cStreamState.dstRect.bottom) - viewport.y;
}
VkExtent3D viewExtent = cViews[0]->mipLevelExtent(0);
VkRect2D srcRect;
srcRect.offset = { 0, 0 };
srcRect.extent = { viewExtent.width, viewExtent.height };
if (cStreamState.srcRectEnabled) {
srcRect.offset.x = cStreamState.srcRect.left;
srcRect.offset.y = cStreamState.srcRect.top;
srcRect.extent.width = cStreamState.srcRect.right - srcRect.offset.x;
srcRect.extent.height = cStreamState.srcRect.bottom - srcRect.offset.y;
}
UboData uboData = { };
uboData.colorMatrix[0][0] = 1.0f;
uboData.colorMatrix[1][1] = 1.0f;
uboData.colorMatrix[2][2] = 1.0f;
uboData.coordMatrix[0][0] = 1.0f;
uboData.coordMatrix[1][1] = 1.0f;
uboData.coordMatrix[0][0] = float(srcRect.extent.width) / float(viewExtent.width);
uboData.coordMatrix[1][1] = float(srcRect.extent.height) / float(viewExtent.height);
uboData.coordMatrix[2][0] = float(srcRect.offset.x) / float(viewExtent.width);
uboData.coordMatrix[2][1] = float(srcRect.offset.y) / float(viewExtent.height);
uboData.srcRect = srcRect;
uboData.yMin = 0.0f;
uboData.yMax = 1.0f;
uboData.isPlanar = cViews[1] != nullptr;
@ -1296,21 +1301,67 @@ namespace dxvk {
ctx->invalidateBuffer(m_ubo, uboSlice);
ctx->setViewports(1, &viewport, &scissor);
ctx->bindResourceSampler(VK_SHADER_STAGE_FRAGMENT_BIT, 1, Rc<DxvkSampler>(m_sampler));
ctx->bindShader<VK_SHADER_STAGE_VERTEX_BIT>(Rc<DxvkShader>(m_vs));
ctx->bindShader<VK_SHADER_STAGE_FRAGMENT_BIT>(Rc<DxvkShader>(m_fs));
ctx->bindUniformBuffer(VK_SHADER_STAGE_FRAGMENT_BIT, 0, DxvkBufferSlice(m_ubo));
for (uint32_t i = 0; i < cViews.size(); i++)
ctx->bindResourceImageView(VK_SHADER_STAGE_FRAGMENT_BIT, 2 + i, Rc<DxvkImageView>(cViews[i]));
ctx->bindResourceImageView(VK_SHADER_STAGE_FRAGMENT_BIT, 1 + i, Rc<DxvkImageView>(cViews[i]));
ctx->draw(3, 1, 0, 0);
ctx->bindResourceSampler(VK_SHADER_STAGE_FRAGMENT_BIT, 1, nullptr);
for (uint32_t i = 0; i < cViews.size(); i++)
ctx->bindResourceImageView(VK_SHADER_STAGE_FRAGMENT_BIT, 2 + i, nullptr);
ctx->bindResourceImageView(VK_SHADER_STAGE_FRAGMENT_BIT, 1 + i, nullptr);
});
}
void D3D11VideoContext::CreateUniformBuffer() {
DxvkBufferCreateInfo bufferInfo;
bufferInfo.size = sizeof(UboData);
bufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
bufferInfo.stages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
bufferInfo.access = VK_ACCESS_UNIFORM_READ_BIT;
m_ubo = m_device->createBuffer(bufferInfo, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
}
void D3D11VideoContext::CreateShaders() {
SpirvCodeBuffer vsCode(d3d11_video_blit_vert);
SpirvCodeBuffer fsCode(d3d11_video_blit_frag);
const std::array<DxvkBindingInfo, 3> fsBindings = {{
{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, VK_IMAGE_VIEW_TYPE_MAX_ENUM, VK_SHADER_STAGE_FRAGMENT_BIT, VK_ACCESS_UNIFORM_READ_BIT, VK_TRUE },
{ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1, VK_IMAGE_VIEW_TYPE_2D, VK_SHADER_STAGE_FRAGMENT_BIT, VK_ACCESS_SHADER_READ_BIT },
{ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 2, VK_IMAGE_VIEW_TYPE_2D, VK_SHADER_STAGE_FRAGMENT_BIT, VK_ACCESS_SHADER_READ_BIT },
}};
DxvkShaderCreateInfo vsInfo;
vsInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
vsInfo.outputMask = 0x1;
m_vs = new DxvkShader(vsInfo, std::move(vsCode));
DxvkShaderCreateInfo fsInfo;
fsInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
fsInfo.bindingCount = fsBindings.size();
fsInfo.bindings = fsBindings.data();
fsInfo.inputMask = 0x1;
fsInfo.outputMask = 0x1;
m_fs = new DxvkShader(fsInfo, std::move(fsCode));
}
void D3D11VideoContext::CreateResources() {
if (std::exchange(m_resourcesCreated, true))
return;
CreateUniformBuffer();
CreateShaders();
}
void D3D11VideoContext::UnbindResources() {
m_ctx->EmitCs([] (DxvkContext* ctx) {
ctx->bindRenderTargets(DxvkRenderTargets(), 0u);
@ -1318,7 +1369,7 @@ namespace dxvk {
ctx->bindShader<VK_SHADER_STAGE_VERTEX_BIT>(nullptr);
ctx->bindShader<VK_SHADER_STAGE_FRAGMENT_BIT>(nullptr);
ctx->bindResourceBuffer(VK_SHADER_STAGE_FRAGMENT_BIT, 0, DxvkBufferSlice());
ctx->bindUniformBuffer(VK_SHADER_STAGE_FRAGMENT_BIT, 0, DxvkBufferSlice());
});
}

View File

@ -584,19 +584,22 @@ namespace dxvk {
struct alignas(16) UboData {
float colorMatrix[3][4];
float coordMatrix[3][2];
VkRect2D srcRect;
float yMin, yMax;
VkBool32 isPlanar;
};
D3D11ImmediateContext* m_ctx;
D3D11ImmediateContext* m_ctx;
Rc<DxvkSampler> m_sampler;
Rc<DxvkShader> m_vs;
Rc<DxvkShader> m_fs;
Rc<DxvkBuffer> m_ubo;
Rc<DxvkDevice> m_device;
Rc<DxvkShader> m_vs;
Rc<DxvkShader> m_fs;
Rc<DxvkBuffer> m_ubo;
VkExtent2D m_dstExtent = { 0u, 0u };
bool m_resourcesCreated = false;
void ApplyColorMatrix(float pDst[3][4], const float pSrc[3][4]);
void ApplyYCbCrMatrix(float pColorMatrix[3][4], bool UseBt709);
@ -608,6 +611,12 @@ namespace dxvk {
const D3D11VideoProcessorStreamState* pStreamState,
const D3D11_VIDEO_PROCESSOR_STREAM* pStream);
void CreateUniformBuffer();
void CreateShaders();
void CreateResources();
void UnbindResources();
};

View File

@ -126,12 +126,15 @@ namespace dxvk {
if (riid == __uuidof(ID3D10DeviceChild)
|| riid == __uuidof(ID3D10View)
|| riid == __uuidof(ID3D10DepthStencilView)) {
*ppvObject = ref(this);
*ppvObject = ref(&m_d3d10);
return S_OK;
}
Logger::warn("D3D11DepthStencilView::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
if (logQueryInterfaceError(__uuidof(ID3D11DepthStencilView), riid)) {
Logger::warn("D3D11DepthStencilView::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
}
return E_NOINTERFACE;
}

View File

@ -77,6 +77,10 @@ namespace dxvk {
return mask;
}
DXGI_FORMAT GetViewFormat() const {
return m_desc.Format;
}
D3D10DepthStencilView* GetD3D10Iface() {
return &m_d3d10;
}

View File

@ -137,12 +137,15 @@ namespace dxvk {
if (riid == __uuidof(ID3D10DeviceChild)
|| riid == __uuidof(ID3D10View)
|| riid == __uuidof(ID3D10RenderTargetView)) {
*ppvObject = ref(this);
*ppvObject = ref(&m_d3d10);
return S_OK;
}
Logger::warn("D3D11RenderTargetView::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
if (logQueryInterfaceError(__uuidof(ID3D11RenderTargetView), riid)) {
Logger::warn("D3D11RenderTargetView::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
}
return E_NOINTERFACE;
}

View File

@ -205,12 +205,15 @@ namespace dxvk {
|| riid == __uuidof(ID3D10View)
|| riid == __uuidof(ID3D10ShaderResourceView)
|| riid == __uuidof(ID3D10ShaderResourceView1)) {
*ppvObject = ref(this);
*ppvObject = ref(&m_d3d10);
return S_OK;
}
Logger::warn("D3D11ShaderResourceView::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
if (logQueryInterfaceError(__uuidof(ID3D11ShaderResourceView), riid)) {
Logger::warn("D3D11ShaderResourceView::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
}
return E_NOINTERFACE;
}
@ -295,7 +298,7 @@ namespace dxvk {
D3D11_BUFFER_DESC 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->ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
pDesc->Buffer.FirstElement = 0;

View File

@ -44,7 +44,7 @@ namespace dxvk {
}
if (pDesc->Buffer.Flags & (D3D11_BUFFER_UAV_FLAG_APPEND | D3D11_BUFFER_UAV_FLAG_COUNTER))
m_counterBuffer = CreateCounterBuffer();
m_counterView = CreateCounterBufferView();
// Populate view info struct
m_info.Buffer.Offset = viewInfo.rangeOffset;
@ -59,9 +59,11 @@ namespace dxvk {
DxvkImageViewCreateInfo viewInfo;
viewInfo.format = formatInfo.Format;
viewInfo.aspect = formatInfo.Aspect;
viewInfo.swizzle = formatInfo.Swizzle;
viewInfo.usage = VK_IMAGE_USAGE_STORAGE_BIT;
if (!util::isIdentityMapping(formatInfo.Swizzle))
Logger::warn(str::format("UAV format ", pDesc->Format, " has non-identity swizzle, but UAV swizzles are not supported"));
switch (pDesc->ViewDimension) {
case D3D11_UAV_DIMENSION_TEXTURE1D:
viewInfo.type = VK_IMAGE_VIEW_TYPE_1D;
@ -145,8 +147,11 @@ namespace dxvk {
return S_OK;
}
Logger::warn("D3D11UnorderedAccessView::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
if (logQueryInterfaceError(__uuidof(ID3D11UnorderedAccessView), riid)) {
Logger::warn("D3D11UnorderedAccessView::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
}
return E_NOINTERFACE;
}
@ -209,7 +214,7 @@ namespace dxvk {
D3D11_BUFFER_DESC 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->ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
pDesc->Buffer.FirstElement = 0;
@ -427,7 +432,7 @@ namespace dxvk {
}
Rc<DxvkBuffer> D3D11UnorderedAccessView::CreateCounterBuffer() {
Rc<DxvkBufferView> D3D11UnorderedAccessView::CreateCounterBufferView() {
Rc<DxvkDevice> device = m_parent->GetDXVKDevice();
DxvkBufferCreateInfo info;
@ -441,7 +446,15 @@ namespace dxvk {
| VK_ACCESS_TRANSFER_READ_BIT
| VK_ACCESS_SHADER_WRITE_BIT
| VK_ACCESS_SHADER_READ_BIT;
return device->createBuffer(info, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
Rc<DxvkBuffer> buffer = device->createBuffer(info, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
DxvkBufferViewCreateInfo viewInfo;
viewInfo.format = VK_FORMAT_UNDEFINED;
viewInfo.rangeOffset = 0;
viewInfo.rangeLength = sizeof(uint32_t);
return device->createBufferView(buffer, viewInfo);
}
}

View File

@ -57,10 +57,8 @@ namespace dxvk {
return m_imageView;
}
DxvkBufferSlice GetCounterSlice() const {
return m_counterBuffer != nullptr
? DxvkBufferSlice(m_counterBuffer)
: DxvkBufferSlice();
Rc<DxvkBufferView> GetCounterView() const {
return m_counterView;
}
static HRESULT GetDescFromResource(
@ -85,9 +83,9 @@ namespace dxvk {
D3D11_VK_VIEW_INFO m_info;
Rc<DxvkBufferView> m_bufferView;
Rc<DxvkImageView> m_imageView;
Rc<DxvkBuffer> m_counterBuffer;
Rc<DxvkBufferView> m_counterView;
Rc<DxvkBuffer> CreateCounterBuffer();
Rc<DxvkBufferView> CreateCounterBufferView();
};

View File

@ -2,9 +2,6 @@ d3d11_res = wrc_generator.process('version.rc')
dxgi_common_src = [
'../dxgi/dxgi_format.cpp',
'../dxgi/dxgi_monitor.cpp',
'../dxgi/dxgi_surface.cpp',
'../dxgi/dxgi_swapchain.cpp',
]
d3d10_src = [
@ -45,6 +42,7 @@ d3d11_src = [
'd3d11_input_layout.cpp',
'd3d11_interop.cpp',
'd3d11_main.cpp',
'd3d11_on_12.cpp',
'd3d11_options.cpp',
'd3d11_query.cpp',
'd3d11_rasterizer.cpp',
@ -71,15 +69,18 @@ d3d11_shaders = files([
d3d11_ld_args = []
d3d11_link_depends = []
if platform != 'windows'
if platform == 'windows'
d3d11_dxgi_dep = lib_dxgi
else
d3d11_ld_args += [ '-Wl,--version-script', join_paths(meson.current_source_dir(), 'd3d11.sym') ]
d3d11_link_depends += files('d3d11.sym')
d3d11_dxgi_dep = dxgi_dep
endif
d3d11_dll = shared_library('d3d11'+dll_ext, dxgi_common_src + d3d11_src + d3d10_src,
glsl_generator.process(d3d11_shaders), d3d11_res,
name_prefix : dxvk_name_prefix,
dependencies : [ dxgi_dep, dxbc_dep, dxvk_dep ],
dependencies : [ d3d11_dxgi_dep, dxbc_dep, dxvk_dep ],
include_directories : dxvk_include_path,
install : true,
vs_module_defs : 'd3d11'+def_spec_ext,

View File

@ -1,5 +1,7 @@
#version 450
#extension GL_EXT_samplerless_texture_functions : require
// Can't use matrix types here since even a two-row
// matrix will be padded to 16 bytes per column for
// absolutely no reason
@ -11,6 +13,8 @@ uniform ubo_t {
vec2 coord_matrix_c1;
vec2 coord_matrix_c2;
vec2 coord_matrix_c3;
uvec2 src_offset;
uvec2 src_extent;
float y_min;
float y_max;
bool is_planar;
@ -19,9 +23,8 @@ uniform ubo_t {
layout(location = 0) in vec2 i_texcoord;
layout(location = 0) out vec4 o_color;
layout(set = 0, binding = 1) uniform sampler s_sampler;
layout(set = 0, binding = 2) uniform texture2D s_inputY;
layout(set = 0, binding = 3) uniform texture2D s_inputCbCr;
layout(set = 0, binding = 1) uniform texture2D s_inputY;
layout(set = 0, binding = 2) uniform texture2D s_inputCbCr;
void main() {
// Transform input texture coordinates to
@ -31,25 +34,61 @@ void main() {
coord_matrix_c2,
coord_matrix_c3);
vec2 coord = coord_matrix * vec3(i_texcoord, 1.0f);
// Fetch source image color
vec4 color = vec4(0.0f, 0.0f, 0.0f, 1.0f);
if (is_planar) {
color.g = texture(sampler2D(s_inputY, s_sampler), coord).r;
color.rb = texture(sampler2D(s_inputCbCr, s_sampler), coord).gr;
color.g = clamp((color.g - y_min) / (y_max - y_min), 0.0f, 1.0f);
} else {
color = texture(sampler2D(s_inputY, s_sampler), coord);
}
// Color space transformation
// Load color space transform
mat3x4 color_matrix = mat3x4(
color_matrix_r1,
color_matrix_r2,
color_matrix_r3);
o_color.rgb = vec4(color.rgb, 1.0f) * color_matrix;
o_color.a = color.a;
// Compute actual pixel coordinates to sample. We filter
// manually in order to avoid bleeding from pixels outside
// the source rectangle.
vec2 abs_size_y = vec2(textureSize(s_inputY, 0));
vec2 abs_size_c = vec2(textureSize(s_inputCbCr, 0));
vec2 coord = coord_matrix * vec3(i_texcoord, 1.0f);
coord -= 0.5f / abs_size_y;
vec2 size_factor = abs_size_c / abs_size_y;
vec2 src_lo = vec2(src_offset);
vec2 src_hi = vec2(src_offset + src_extent - 1u);
vec2 abs_coord = coord * abs_size_y;
vec2 fract_coord = fract(clamp(abs_coord, src_lo, src_hi));
vec4 accum = vec4(0.0f, 0.0f, 0.0f, 0.0f);
for (int i = 0; i < 4; i++) {
ivec2 offset = ivec2(i & 1, i >> 1);
// Compute exact pixel coordinates for the current
// iteration and clamp it to the source rectangle.
vec2 fetch_coord = clamp(abs_coord + vec2(offset), src_lo, src_hi);
// Fetch actual pixel color in source color space
vec4 color;
if (is_planar) {
color.g = texelFetch(s_inputY, ivec2(fetch_coord), 0).r;
color.rb = texelFetch(s_inputCbCr, ivec2(fetch_coord * size_factor), 0).gr;
color.g = clamp((color.g - y_min) / (y_max - y_min), 0.0f, 1.0f);
color.a = 1.0f;
} else {
color = texelFetch(s_inputY, ivec2(fetch_coord), 0);
}
// Transform color space before accumulation
color.rgb = vec4(color.rgb, 1.0f) * color_matrix;
// Filter and accumulate final pixel color
vec2 factor = fract_coord;
if (offset.x == 0) factor.x = 1.0f - factor.x;
if (offset.y == 0) factor.y = 1.0f - factor.y;
accum += factor.x * factor.y * color;
}
o_color = accum;
}

View File

@ -25,3 +25,6 @@ EXPORTS
DXVK_UnRegisterAnnotation @28258 NONAME
Direct3D9ForceHybridEnumeration @16 NONAME PRIVATE
Direct3DCreate9On12 @20
Direct3DCreate9On12Ex @21

View File

@ -18,6 +18,8 @@
DXVK_RegisterAnnotation;
DXVK_UnRegisterAnnotation;
Direct3D9ForceHybridEnumeration;
Direct3DCreate9On12;
Direct3DCreate9On12Ex;
local:
*;

View File

@ -162,6 +162,9 @@ namespace dxvk {
if (mapping.FormatSrgb == VK_FORMAT_UNDEFINED && srgb)
return D3DERR_NOTAVAILABLE;
if (RType == D3DRTYPE_CUBETEXTURE && mapping.Aspect != VK_IMAGE_ASPECT_COLOR_BIT)
return D3DERR_NOTAVAILABLE;
if (RType == D3DRTYPE_VERTEXBUFFER || RType == D3DRTYPE_INDEXBUFFER)
return D3D_OK;
@ -224,11 +227,15 @@ namespace dxvk {
if (!IsDepthFormat(DepthStencilFormat))
return D3DERR_NOTAVAILABLE;
auto dsfMapping = ConvertFormatUnfixed(DepthStencilFormat);
if (dsfMapping.FormatColor == VK_FORMAT_UNDEFINED)
return D3DERR_NOTAVAILABLE;
if (RenderTargetFormat == dxvk::D3D9Format::NULL_FORMAT)
return D3D_OK;
auto mapping = ConvertFormatUnfixed(RenderTargetFormat);
if (mapping.FormatColor == VK_FORMAT_UNDEFINED)
auto rtfMapping = ConvertFormatUnfixed(RenderTargetFormat);
if (rtfMapping.FormatColor == VK_FORMAT_UNDEFINED)
return D3DERR_NOTAVAILABLE;
return D3D_OK;
@ -529,7 +536,7 @@ namespace dxvk {
// Max Vertex Blend Matrices
pCaps->MaxVertexBlendMatrices = 4;
// Max Vertex Blend Matrix Index
pCaps->MaxVertexBlendMatrixIndex = 8;
pCaps->MaxVertexBlendMatrixIndex = 0;
// Max Point Size
pCaps->MaxPointSize = 256.0f;
// Max Primitive Count
@ -788,7 +795,8 @@ namespace dxvk {
// Fix up the D3DFORMAT to match what we are enumerating
mode.Format = static_cast<D3DFORMAT>(Format);
m_modes.push_back(mode);
if (std::count(m_modes.begin(), m_modes.end(), mode) == 0)
m_modes.push_back(mode);
}
// Sort display modes by width, height and refresh rate,

View File

@ -2,8 +2,11 @@
#include "d3d9_device.h"
#include "d3d9_include.h"
#include "../dxvk/dxvk_annotation.h"
#include "../util/thread.h"
#include <atomic>
#include <mutex>
#include <vector>
@ -43,7 +46,7 @@ namespace dxvk {
std::atomic<bool> m_shouldAnnotate;
std::mutex m_mutex;
dxvk::mutex m_mutex;
std::vector<IDXVKUserDefinedAnnotation*> m_annotations;
// Provide our own event depth as we

111
src/d3d9/d3d9_bridge.cpp Normal file
View File

@ -0,0 +1,111 @@
#include "d3d9_device.h"
#include "d3d9_interface.h"
#include "d3d9_bridge.h"
#include "d3d9_swapchain.h"
#include "d3d9_surface.h"
namespace dxvk {
DxvkD3D8Bridge::DxvkD3D8Bridge(D3D9DeviceEx* pDevice)
: m_device(pDevice) {
}
DxvkD3D8Bridge::~DxvkD3D8Bridge() {
}
ULONG STDMETHODCALLTYPE DxvkD3D8Bridge::AddRef() {
return m_device->AddRef();
}
ULONG STDMETHODCALLTYPE DxvkD3D8Bridge::Release() {
return m_device->Release();
}
HRESULT STDMETHODCALLTYPE DxvkD3D8Bridge::QueryInterface(
REFIID riid,
void** ppvObject) {
return m_device->QueryInterface(riid, ppvObject);
}
void DxvkD3D8Bridge::SetAPIName(const char* name) {
m_device->m_implicitSwapchain->SetApiName(name);
}
void DxvkD3D8Bridge::SetD3D8CompatibilityMode(const bool compatMode) {
m_device->SetD3D8CompatibilityMode(compatMode);
}
HRESULT DxvkD3D8Bridge::UpdateTextureFromBuffer(
IDirect3DSurface9* pDestSurface,
IDirect3DSurface9* pSrcSurface,
const RECT* pSrcRect,
const POINT* pDestPoint) {
auto lock = m_device->LockDevice();
D3D9Surface* dst = static_cast<D3D9Surface*>(pDestSurface);
D3D9Surface* src = static_cast<D3D9Surface*>(pSrcSurface);
if (unlikely(dst == nullptr || src == nullptr))
return D3DERR_INVALIDCALL;
D3D9CommonTexture* srcTextureInfo = src->GetCommonTexture();
D3D9CommonTexture* dstTextureInfo = dst->GetCommonTexture();
VkOffset3D srcOffset = { 0u, 0u, 0u };
VkOffset3D dstOffset = { 0u, 0u, 0u };
VkExtent3D texLevelExtent = srcTextureInfo->GetExtentMip(src->GetSubresource());
VkExtent3D extent = texLevelExtent;
srcOffset = { pSrcRect->left,
pSrcRect->top,
0u };
extent = { uint32_t(pSrcRect->right - pSrcRect->left), uint32_t(pSrcRect->bottom - pSrcRect->top), 1 };
// TODO: Validate extents like in D3D9DeviceEx::UpdateSurface
dstOffset = { pDestPoint->x,
pDestPoint->y,
0u };
m_device->UpdateTextureFromBuffer(
srcTextureInfo, dstTextureInfo,
src->GetSubresource(), dst->GetSubresource(),
srcOffset, extent, dstOffset
);
dstTextureInfo->SetNeedsReadback(dst->GetSubresource(), true);
if (dstTextureInfo->IsAutomaticMip())
m_device->MarkTextureMipsDirty(dstTextureInfo);
return D3D_OK;
}
DxvkD3D8InterfaceBridge::DxvkD3D8InterfaceBridge(D3D9InterfaceEx* pObject)
: m_interface(pObject) {
}
DxvkD3D8InterfaceBridge::~DxvkD3D8InterfaceBridge() {
}
ULONG STDMETHODCALLTYPE DxvkD3D8InterfaceBridge::AddRef() {
return m_interface->AddRef();
}
ULONG STDMETHODCALLTYPE DxvkD3D8InterfaceBridge::Release() {
return m_interface->Release();
}
HRESULT STDMETHODCALLTYPE DxvkD3D8InterfaceBridge::QueryInterface(
REFIID riid,
void** ppvObject) {
return m_interface->QueryInterface(riid, ppvObject);
}
const Config* DxvkD3D8InterfaceBridge::GetConfig() const {
return &m_interface->GetInstance()->config();
}
}

118
src/d3d9/d3d9_bridge.h Normal file
View File

@ -0,0 +1,118 @@
#pragma once
#include <windows.h>
#include "../util/config/config.h"
#include "../vulkan/vulkan_loader.h"
/**
* The D3D9 bridge allows D3D8 to access DXVK internals.
* For Vulkan interop without needing DXVK internals, see d3d9_interop.h.
*
* NOTE: You must include "d3d9_include.h" or "d3d8_include.h" before this header.
*/
/**
* \brief D3D9 device interface for D3D8 interop
*/
MIDL_INTERFACE("D3D9D3D8-42A9-4C1E-AA97-BEEFCAFE2000")
IDxvkD3D8Bridge : public IUnknown {
// D3D8 keeps D3D9 objects contained in a namespace.
#ifdef DXVK_D3D9_NAMESPACE
using IDirect3DSurface9 = d3d9::IDirect3DSurface9;
#endif
/**
* \brief Changes the API name displayed on the HUD
*
* \param [in] name The new API name
*/
virtual void SetAPIName(const char* name) = 0;
/**
* \brief Enables or disables D3D9-specific device features and validations
*
* \param [in] compatibility state
*/
virtual void SetD3D8CompatibilityMode(const bool compatMode) = 0;
/**
* \brief Updates a D3D9 surface from a D3D9 buffer
*
* \param [in] pDestSurface Destination surface (typically in VRAM)
* \param [in] pSrcSurface Source surface (typically in system memory)
* \param [in] pSrcRect Source rectangle
* \param [in] pDestPoint Destination (top-left) point
*/
virtual HRESULT UpdateTextureFromBuffer(
IDirect3DSurface9* pDestSurface,
IDirect3DSurface9* pSrcSurface,
const RECT* pSrcRect,
const POINT* pDestPoint) = 0;
};
/**
* \brief D3D9 instance interface for D3D8 interop
*/
MIDL_INTERFACE("D3D9D3D8-A407-773E-18E9-CAFEBEEF3000")
IDxvkD3D8InterfaceBridge : public IUnknown {
/**
* \brief Retrieves the DXVK configuration
*
* \returns The DXVK Config object
*/
virtual const dxvk::Config* GetConfig() const = 0;
};
#ifndef _MSC_VER
__CRT_UUID_DECL(IDxvkD3D8Bridge, 0xD3D9D3D8, 0x42A9, 0x4C1E, 0xAA, 0x97, 0xBE, 0xEF, 0xCA, 0xFE, 0x20, 0x00);
__CRT_UUID_DECL(IDxvkD3D8InterfaceBridge, 0xD3D9D3D8, 0xA407, 0x773E, 0x18, 0xE9, 0xCA, 0xFE, 0xBE, 0xEF, 0x30, 0x00);
#endif
namespace dxvk {
class D3D9DeviceEx;
class D3D9InterfaceEx;
class DxvkD3D8Bridge : public IDxvkD3D8Bridge {
public:
DxvkD3D8Bridge(D3D9DeviceEx* pDevice);
~DxvkD3D8Bridge();
ULONG STDMETHODCALLTYPE AddRef();
ULONG STDMETHODCALLTYPE Release();
HRESULT STDMETHODCALLTYPE QueryInterface(
REFIID riid,
void** ppvObject);
void SetAPIName(const char* name);
void SetD3D8CompatibilityMode(const bool compatMode);
HRESULT UpdateTextureFromBuffer(
IDirect3DSurface9* pDestSurface,
IDirect3DSurface9* pSrcSurface,
const RECT* pSrcRect,
const POINT* pDestPoint);
private:
D3D9DeviceEx* m_device;
};
class DxvkD3D8InterfaceBridge : public IDxvkD3D8InterfaceBridge {
public:
DxvkD3D8InterfaceBridge(D3D9InterfaceEx* pObject);
~DxvkD3D8InterfaceBridge();
ULONG STDMETHODCALLTYPE AddRef();
ULONG STDMETHODCALLTYPE Release();
HRESULT STDMETHODCALLTYPE QueryInterface(
REFIID riid,
void** ppvObject);
const Config* GetConfig() const;
protected:
D3D9InterfaceEx* m_interface;
};
}

View File

@ -29,8 +29,11 @@ namespace dxvk {
return S_OK;
}
Logger::warn("D3D9VertexBuffer::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
if (logQueryInterfaceError(__uuidof(IDirect3DVertexBuffer9), riid)) {
Logger::warn("D3D9VertexBuffer::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
}
return E_NOINTERFACE;
}
@ -86,8 +89,11 @@ namespace dxvk {
return S_OK;
}
Logger::warn("D3D9IndexBuffer::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
if (logQueryInterfaceError(__uuidof(IDirect3DIndexBuffer9), riid)) {
Logger::warn("D3D9IndexBuffer::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
}
return E_NOINTERFACE;
}

View File

@ -20,6 +20,11 @@ namespace dxvk {
m_dirtyRange = D3D9Range(0, m_desc.Size);
}
D3D9CommonBuffer::~D3D9CommonBuffer() {
if (m_desc.Pool == D3DPOOL_DEFAULT)
m_parent->DecrementLosableCounter();
}
HRESULT D3D9CommonBuffer::Lock(
UINT OffsetToLock,
@ -57,6 +62,32 @@ namespace dxvk {
}
}
D3D9_COMMON_BUFFER_MAP_MODE D3D9CommonBuffer::DetermineMapMode(const D3D9Options* options) const {
if (m_desc.Pool != D3DPOOL_DEFAULT)
return D3D9_COMMON_BUFFER_MAP_MODE_BUFFER;
// CSGO keeps vertex buffers locked across multiple frames and writes to it. It uses them for drawing without unlocking first.
// Tests show that D3D9 DEFAULT + USAGE_DYNAMIC behaves like a directly mapped buffer even when unlocked.
// DEFAULT + WRITEONLY does not behave like a directly mapped buffer EXCEPT if its locked at the moment.
// That's annoying to implement so we just always directly map DEFAULT + WRITEONLY.
if (!(m_desc.Usage & (D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY)))
return D3D9_COMMON_BUFFER_MAP_MODE_BUFFER;
// Tests show that DISCARD does not work for pure SWVP devices.
// So force staging buffer path to avoid stalls.
// Dark Romance: Vampire in Love also expects draws to be synchronous
// and breaks if we respect NOOVERWRITE.
// D&D Temple of Elemental Evil breaks if we respect DISCARD.
if (m_parent->CanOnlySWVP())
return D3D9_COMMON_BUFFER_MAP_MODE_BUFFER;
if (!options->allowDirectBufferMapping)
return D3D9_COMMON_BUFFER_MAP_MODE_BUFFER;
return D3D9_COMMON_BUFFER_MAP_MODE_DIRECT;
}
Rc<DxvkBuffer> D3D9CommonBuffer::CreateBuffer() const {
DxvkBufferCreateInfo info;
@ -103,7 +134,8 @@ namespace dxvk {
memoryFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
}
if (memoryFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT && m_parent->GetOptions()->apitraceMode) {
if ((memoryFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) && m_parent->GetOptions()->cachedDynamicBuffers) {
memoryFlags &= ~VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
memoryFlags |= VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
| VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
}

View File

@ -78,6 +78,8 @@ namespace dxvk {
D3D9DeviceEx* pDevice,
const D3D9_BUFFER_DESC* pDesc);
~D3D9CommonBuffer();
HRESULT Lock(
UINT OffsetToLock,
UINT SizeToLock,
@ -89,11 +91,7 @@ namespace dxvk {
/**
* \brief Determine the mapping mode of the buffer, (ie. direct mapping or backed)
*/
inline D3D9_COMMON_BUFFER_MAP_MODE DetermineMapMode(const D3D9Options* options) const {
return (m_desc.Pool == D3DPOOL_DEFAULT && (m_desc.Usage & (D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY)) && options->allowDirectBufferMapping)
? D3D9_COMMON_BUFFER_MAP_MODE_DIRECT
: D3D9_COMMON_BUFFER_MAP_MODE_BUFFER;
}
D3D9_COMMON_BUFFER_MAP_MODE DetermineMapMode(const D3D9Options* options) const;
/**
* \brief Get the mapping mode of the buffer, (ie. direct mapping or backed)
@ -127,7 +125,12 @@ namespace dxvk {
template <D3D9_COMMON_BUFFER_TYPE Type>
inline DxvkBufferSlice GetBufferSlice(VkDeviceSize offset, VkDeviceSize length) const {
return DxvkBufferSlice(GetBuffer<Type>(), offset, length);
if (likely(length && offset < m_desc.Size)) {
return DxvkBufferSlice(GetBuffer<Type>(), offset,
std::min<VkDeviceSize>(m_desc.Size - offset, length));
}
return DxvkBufferSlice();
}
inline DxvkBufferSliceHandle AllocMapSlice() {
@ -208,6 +211,10 @@ namespace dxvk {
: DxvkCsThread::SynchronizeAll;
}
bool IsSysmemDynamic() const {
return m_desc.Pool == D3DPOOL_SYSTEMMEM && (m_desc.Usage & D3DUSAGE_DYNAMIC) != 0;
}
private:
Rc<DxvkBuffer> CreateBuffer() const;
@ -227,7 +234,7 @@ namespace dxvk {
D3D9DeviceEx* m_parent;
const D3D9_BUFFER_DESC m_desc;
DWORD m_mapFlags;
DWORD m_mapFlags = 0;
bool m_needsReadback = false;
D3D9_COMMON_BUFFER_MAP_MODE m_mapMode;

View File

@ -22,18 +22,21 @@ namespace dxvk {
? D3D9Format::D32
: D3D9Format::X8R8G8B8;
m_exposedMipLevels = m_desc.MipLevels;
if (m_desc.Usage & D3DUSAGE_AUTOGENMIPMAP)
m_exposedMipLevels = 1;
for (uint32_t i = 0; i < m_dirtyBoxes.size(); i++) {
AddDirtyBox(nullptr, i);
}
if (m_desc.Pool != D3DPOOL_DEFAULT) {
const uint32_t subresources = CountSubresources();
for (uint32_t i = 0; i < subresources; i++) {
SetNeedsUpload(i, true);
}
if (pSharedHandle) {
throw DxvkError("D3D9: Incompatible pool type for texture sharing.");
}
if (m_desc.Pool != D3DPOOL_DEFAULT && pSharedHandle) {
throw DxvkError("D3D9: Incompatible pool type for texture sharing.");
}
if (IsPoolManaged(m_desc.Pool)) {
SetAllNeedUpload();
}
m_mapping = pDevice->LookupFormat(m_desc.Format);
@ -88,11 +91,6 @@ namespace dxvk {
m_data = m_device->GetAllocator()->Alloc(m_totalSize);
else if (m_mapMode != D3D9_COMMON_TEXTURE_MAP_MODE_NONE && m_desc.Pool != D3DPOOL_DEFAULT)
CreateBuffer(false);
m_exposedMipLevels = m_desc.MipLevels;
if (m_desc.Usage & D3DUSAGE_AUTOGENMIPMAP)
m_exposedMipLevels = 1;
}
@ -101,6 +99,9 @@ namespace dxvk {
m_device->ChangeReportedMemory(m_size);
m_device->RemoveMappedTexture(this);
if (m_desc.Pool == D3DPOOL_DEFAULT)
m_device->DecrementLosableCounter();
}
@ -117,6 +118,7 @@ namespace dxvk {
HRESULT D3D9CommonTexture::NormalizeTextureProperties(
D3D9DeviceEx* pDevice,
D3DRESOURCETYPE ResourceType,
D3D9_COMMON_TEXTURE_DESC* pDesc) {
auto* options = pDevice->GetOptions();
@ -130,6 +132,11 @@ namespace dxvk {
options->disableA8RT)
return D3DERR_INVALIDCALL;
// Cube textures with depth formats are not supported on any native
// driver, and allowing them triggers a broken code path in Gothic 3.
if (ResourceType == D3DRTYPE_CUBETEXTURE && mapping.Aspect != VK_IMAGE_ASPECT_COLOR_BIT)
return D3DERR_INVALIDCALL;
// If the mapping is invalid then lets return invalid
// Some edge cases:
// NULL format does not map to anything, but should succeed
@ -241,13 +248,21 @@ namespace dxvk {
const VkExtent3D mipExtent = util::computeMipLevelExtent(
GetExtent(), MipLevel);
VkExtent3D blockSize = formatInfo->blockSize;
uint32_t elementSize = formatInfo->elementSize;
if (unlikely(formatInfo->flags.test(DxvkFormatFlag::MultiPlane))) {
// D3D9 doesn't allow specifying the plane when locking a texture.
// So the subsampled planes inherit the pitch of the first plane.
// That means the size is the size of plane 0 * plane count
elementSize = formatInfo->planes[0].elementSize;
blockSize = { formatInfo->planes[0].blockSize.width, formatInfo->planes[0].blockSize.height, 1u };
}
const VkExtent3D blockCount = util::computeBlockCount(
mipExtent, formatInfo->blockSize);
mipExtent, blockSize);
const uint32_t planeCount = m_mapping.ConversionFormatInfo.PlaneCount;
return std::min(planeCount, 2u)
* align(formatInfo->elementSize * blockCount.width, 4)
return std::min(GetPlaneCount(), 2u)
* align(elementSize * blockCount.width, 4)
* blockCount.height
* blockCount.depth;
}
@ -359,7 +374,7 @@ namespace dxvk {
if (!CheckImageSupport(&imageInfo, imageInfo.tiling)) {
throw DxvkError(str::format(
"D3D9: Cannot create texture:",
"\n Type: ", std::hex, ResourceType,
"\n Type: 0x", std::hex, ResourceType, std::dec,
"\n Format: ", m_desc.Format,
"\n Extent: ", m_desc.Width,
"x", m_desc.Height,
@ -367,8 +382,8 @@ namespace dxvk {
"\n Samples: ", m_desc.MultiSample,
"\n Layers: ", m_desc.ArraySize,
"\n Levels: ", m_desc.MipLevels,
"\n Usage: ", std::hex, m_desc.Usage,
"\n Pool: ", std::hex, m_desc.Pool));
"\n Usage: 0x", std::hex, m_desc.Usage, std::dec,
"\n Pool: 0x", std::hex, m_desc.Pool, std::dec));
}
return m_device->GetDXVKDevice()->createImage(imageInfo, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
@ -678,4 +693,13 @@ namespace dxvk {
return DxvkBufferSlice(GetBuffer(), m_memoryOffset[Subresource], GetMipSize(Subresource));
}
uint32_t D3D9CommonTexture::GetPlaneCount() const {
const DxvkFormatInfo* formatInfo = m_mapping.FormatColor != VK_FORMAT_UNDEFINED
? lookupFormatInfo(m_mapping.FormatColor)
: m_device->UnsupportedFormatInfo(m_desc.Format);
return vk::getPlaneCount(formatInfo->aspectMask);
}
}

View File

@ -179,11 +179,14 @@ namespace dxvk {
* Fills in undefined values and validates the texture
* parameters. Any error returned by this method should
* be forwarded to the application.
* \param [in] pDevice D3D9 device
* \param [in] ResourceType Resource type
* \param [in,out] pDesc Texture description
* \returns \c S_OK if the parameters are valid
*/
static HRESULT NormalizeTextureProperties(
D3D9DeviceEx* pDevice,
D3DRESOURCETYPE ResourceType,
D3D9_COMMON_TEXTURE_DESC* pDesc);
/**
@ -307,14 +310,16 @@ namespace dxvk {
return util::computeMipLevelExtent(GetExtent(), MipLevel);
}
bool MarkHazardous() {
return std::exchange(m_hazardous, true);
bool MarkTransitionedToHazardLayout() {
return std::exchange(m_transitionedToHazardLayout, true);
}
D3DRESOURCETYPE GetType() {
return m_type;
}
uint32_t GetPlaneCount() const;
const D3D9_VK_FORMAT_MAPPING& GetMapping() { return m_mapping; }
void SetLocked(UINT Subresource, bool value) { m_locked.set(Subresource, value); }
@ -338,7 +343,7 @@ namespace dxvk {
}
VkImageLayout DetermineRenderTargetLayout(VkImageLayout hazardLayout) const {
if (unlikely(m_hazardous))
if (unlikely(m_transitionedToHazardLayout))
return hazardLayout;
return m_image != nullptr &&
@ -348,18 +353,16 @@ namespace dxvk {
}
VkImageLayout DetermineDepthStencilLayout(bool write, bool hazardous, VkImageLayout hazardLayout) const {
VkImageLayout layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
if (unlikely(hazardous)) {
layout = write
? hazardLayout
: VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL;
}
if (unlikely(m_transitionedToHazardLayout))
return hazardLayout;
if (unlikely(m_image->info().tiling != VK_IMAGE_TILING_OPTIMAL))
layout = VK_IMAGE_LAYOUT_GENERAL;
return VK_IMAGE_LAYOUT_GENERAL;
return layout;
if (unlikely(hazardous && !write))
return VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL;
return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
}
Rc<DxvkImageView> CreateView(
@ -370,7 +373,15 @@ namespace dxvk {
D3D9SubresourceBitset& GetUploadBitmask() { return m_needsUpload; }
void SetAllNeedUpload() {
m_needsUpload.setAll();
if (likely(!IsAutomaticMip())) {
m_needsUpload.setAll();
} else {
for (uint32_t a = 0; a < m_desc.ArraySize; a++) {
for (uint32_t m = 0; m < ExposedMipLevels(); m++) {
SetNeedsUpload(CalcSubresource(a, m), true);
}
}
}
}
void SetNeedsUpload(UINT Subresource, bool upload) { m_needsUpload.set(Subresource, upload); }
bool NeedsUpload(UINT Subresource) const { return m_needsUpload.get(Subresource); }
@ -380,7 +391,7 @@ namespace dxvk {
void SetNeedsMipGen(bool value) { m_needsMipGen = value; }
bool NeedsMipGen() const { return m_needsMipGen; }
DWORD ExposedMipLevels() { return m_exposedMipLevels; }
DWORD ExposedMipLevels() const { return m_exposedMipLevels; }
void SetMipFilter(D3DTEXTUREFILTERTYPE filter) { m_mipFilter = filter; }
D3DTEXTUREFILTERTYPE GetMipFilter() const { return m_mipFilter; }
@ -502,7 +513,7 @@ namespace dxvk {
int64_t m_size = 0;
bool m_hazardous = false;
bool m_transitionedToHazardLayout = false;
D3D9ColorView m_sampleView;

View File

@ -13,7 +13,7 @@ namespace dxvk {
DxsoProgramType ShaderStage,
DxsoConstantBuffers BufferType,
VkDeviceSize Size)
: D3D9ConstantBuffer(pDevice, GetShaderStage(ShaderStage),
: D3D9ConstantBuffer(pDevice, getBufferUsage(pDevice, ShaderStage, BufferType), GetShaderStage(ShaderStage),
computeResourceSlotId(ShaderStage, DxsoBindingType::ConstantBuffer, BufferType),
Size) {
@ -22,11 +22,13 @@ namespace dxvk {
D3D9ConstantBuffer::D3D9ConstantBuffer(
D3D9DeviceEx* pDevice,
VkBufferUsageFlags Usage,
VkShaderStageFlags Stages,
uint32_t ResourceSlot,
VkDeviceSize Size)
: m_device (pDevice)
, m_binding (ResourceSlot)
, m_usage (Usage)
, m_stages (Stages)
, m_size (Size)
, m_align (getAlignment(pDevice->GetDXVKDevice())) {
@ -65,7 +67,7 @@ namespace dxvk {
cOffset = m_offset,
cLength = size
] (DxvkContext* ctx) {
ctx->bindResourceBufferRange(cStages, cBinding, cOffset, cLength);
ctx->bindUniformBufferRange(cStages, cBinding, cOffset, cLength);
});
void* mapPtr = reinterpret_cast<char*>(m_slice.mapPtr) + m_offset;
@ -98,12 +100,15 @@ namespace dxvk {
// in the backend, so set both STORAGE and UNIFORM usage/access.
DxvkBufferCreateInfo bufferInfo;
bufferInfo.size = align(m_size, m_align);
bufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT
| VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
bufferInfo.access = VK_ACCESS_UNIFORM_READ_BIT
| VK_ACCESS_SHADER_READ_BIT;
bufferInfo.usage = m_usage;
bufferInfo.access = 0;
bufferInfo.stages = util::pipelineStages(m_stages);
if (m_usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT)
bufferInfo.access |= VK_ACCESS_UNIFORM_READ_BIT;
if (m_usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT)
bufferInfo.access |= VK_ACCESS_SHADER_READ_BIT;
VkMemoryPropertyFlags memoryFlags
= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
| VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
@ -118,7 +123,7 @@ namespace dxvk {
cBinding = m_binding,
cSlice = DxvkBufferSlice(m_buffer)
] (DxvkContext* ctx) mutable {
ctx->bindResourceBuffer(cStages, cBinding, std::move(cSlice));
ctx->bindUniformBuffer(cStages, cBinding, std::move(cSlice));
});
}
@ -130,4 +135,21 @@ namespace dxvk {
device->properties().extRobustness2.robustUniformBufferAccessSizeAlignment);
}
VkBufferUsageFlags D3D9ConstantBuffer::getBufferUsage(
D3D9DeviceEx* pDevice,
DxsoProgramType ShaderStage,
DxsoConstantBuffers BufferType) {
VkBufferUsageFlags result = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
// We won't always need this, but the only buffer that
// this applies to is so large that it will not matter.
if (pDevice->CanSWVP()
&& ShaderStage == DxsoProgramType::VertexShader
&& BufferType == DxsoConstantBuffers::VSConstantBuffer)
result |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
return result;
}
}

View File

@ -29,6 +29,7 @@ namespace dxvk {
D3D9ConstantBuffer(
D3D9DeviceEx* pDevice,
VkBufferUsageFlags Usage,
VkShaderStageFlags Stages,
uint32_t ResourceSlot,
VkDeviceSize Size);
@ -66,6 +67,7 @@ namespace dxvk {
D3D9DeviceEx* m_device = nullptr;
uint32_t m_binding = 0u;
VkBufferUsageFlags m_usage = 0u;
VkShaderStageFlags m_stages = 0u;
VkDeviceSize m_size = 0ull;
VkDeviceSize m_align = 0ull;
@ -78,6 +80,11 @@ namespace dxvk {
VkDeviceSize getAlignment(const Rc<DxvkDevice>& device) const;
static VkBufferUsageFlags getBufferUsage(
D3D9DeviceEx* pDevice,
DxsoProgramType ShaderStage,
DxsoConstantBuffers BufferType);
};
}

View File

@ -16,7 +16,11 @@ namespace dxvk {
BOOL D3D9Cursor::ShowCursor(BOOL bShow) {
::SetCursor(bShow ? m_hCursor : nullptr);
if (likely(m_hCursor != nullptr))
::SetCursor(bShow ? m_hCursor : nullptr);
else
Logger::debug("D3D9Cursor::ShowCursor: Software cursor not implemented.");
return std::exchange(m_visible, bShow);
}
@ -63,4 +67,4 @@ namespace dxvk {
}
#endif
}
}

File diff suppressed because it is too large Load Diff

View File

@ -28,12 +28,17 @@
#include "d3d9_spec_constants.h"
#include "d3d9_interop.h"
#include "d3d9_on_12.h"
#include <cstdint>
#include <unordered_set>
#include "d3d9_bridge.h"
#include <vector>
#include <type_traits>
#include <unordered_map>
#include "../util/util_flush.h"
#include "../util/util_lru.h"
namespace dxvk {
@ -61,6 +66,8 @@ namespace dxvk {
DirtyInputLayout,
DirtyViewportScissor,
DirtyMultiSampleState,
DirtyVertexBuffers,
DirtyIndexBuffer,
DirtyFogState,
DirtyFogColor,
@ -87,6 +94,12 @@ namespace dxvk {
using D3D9DeviceFlags = Flags<D3D9DeviceFlag>;
enum class D3D9DeviceLostState {
Ok = 0,
Lost = 1,
NotReset = 2,
};
struct D3D9DrawInfo {
uint32_t vertexCount;
uint32_t instanceCount;
@ -117,8 +130,10 @@ namespace dxvk {
constexpr static VkDeviceSize StagingBufferSize = 4ull << 20;
friend class D3D9SwapChainEx;
friend struct D3D9WindowContext;
friend class D3D9ConstantBuffer;
friend class D3D9UserDefinedAnnotation;
friend class DxvkD3D8Bridge;
friend D3D9VkInteropDevice;
public:
@ -751,6 +766,24 @@ namespace dxvk {
HRESULT UnlockBuffer(
D3D9CommonBuffer* pResource);
/**
* @brief Uploads data from D3DPOOL_SYSMEM + D3DUSAGE_DYNAMIC buffers and binds the temporary buffers.
*
* @param FirstVertexIndex The first vertex
* @param NumVertices The number of vertices that are accessed. If this is 0, the vertex buffer binding will not be modified.
* @param FirstIndex The first index
* @param NumIndices The number of indices that will be drawn. If this is 0, the index buffer binding will not be modified.
*/
void UploadDynamicSysmemBuffers(
UINT& FirstVertexIndex,
UINT NumVertices,
UINT& FirstIndex,
UINT NumIndices,
INT& BaseVertexIndex,
bool* pDynamicVBOs,
bool* pDynamicIBO);
void SetupFPU();
int64_t DetermineInitialTextureMemory();
@ -760,6 +793,7 @@ namespace dxvk {
void SynchronizeCsThread(uint64_t SequenceNumber);
void Flush();
void FlushAndSync9On12();
void EndFrame();
@ -767,6 +801,9 @@ namespace dxvk {
void UpdateActiveRTs(uint32_t index);
template <uint32_t Index>
void UpdateAnyColorWrites(bool has);
void UpdateActiveTextures(uint32_t index, DWORD combinedUsage);
void UpdateActiveHazardsRT(uint32_t rtMask);
@ -800,7 +837,7 @@ namespace dxvk {
inline bool IsAlphaToCoverageEnabled() {
const bool alphaTest = m_state.renderStates[D3DRS_ALPHATESTENABLE] != 0;
return m_amdATOC || (m_nvATOC && alphaTest);
return (m_amdATOC || (m_nvATOC && alphaTest)) && m_flags.test(D3D9DeviceFlag::ValidSampleMask);
}
inline bool IsDepthBiasEnabled() {
@ -868,6 +905,10 @@ namespace dxvk {
void MarkTextureBindingDirty(IDirect3DBaseTexture9* texture);
HRESULT STDMETHODCALLTYPE SetRenderTargetInternal(
DWORD RenderTargetIndex,
IDirect3DSurface9* pRenderTarget);
D3D9DrawInfo GenerateDrawInfo(
D3DPRIMITIVETYPE PrimitiveType,
UINT PrimitiveCount,
@ -875,7 +916,7 @@ namespace dxvk {
uint32_t GetInstanceCount() const;
void PrepareDraw(D3DPRIMITIVETYPE PrimitiveType);
void PrepareDraw(D3DPRIMITIVETYPE PrimitiveType, bool UploadVBOs, bool UploadIBOs);
template <DxsoProgramType ShaderStage>
void BindShader(
@ -909,7 +950,7 @@ namespace dxvk {
void SetVertexBoolBitfield(uint32_t idx, uint32_t mask, uint32_t bits);
void SetPixelBoolBitfield (uint32_t idx, uint32_t mask, uint32_t bits);
void FlushImplicit(BOOL StrongHint);
void ConsiderFlush(GpuFlushType FlushType);
bool ChangeReportedMemory(int64_t delta) {
if (IsExtended())
@ -933,7 +974,7 @@ namespace dxvk {
const D3D9ConstantLayout& GetVertexConstantLayout() { return m_vsLayout; }
const D3D9ConstantLayout& GetPixelConstantLayout() { return m_psLayout; }
HRESULT ResetState(D3DPRESENT_PARAMETERS* pPresentationParameters);
void ResetState(D3DPRESENT_PARAMETERS* pPresentationParameters);
HRESULT ResetSwapChain(D3DPRESENT_PARAMETERS* pPresentationParameters, D3DDISPLAYMODEEX* pFullscreenDisplayMode);
HRESULT InitialReset(D3DPRESENT_PARAMETERS* pPresentationParameters, D3DDISPLAYMODEEX* pFullscreenDisplayMode);
@ -950,6 +991,37 @@ namespace dxvk {
void TouchMappedTexture(D3D9CommonTexture* pTexture);
void RemoveMappedTexture(D3D9CommonTexture* pTexture);
bool IsD3D8Compatible() const {
return m_isD3D8Compatible;
}
void SetD3D8CompatibilityMode(bool compatMode) {
if (compatMode)
Logger::info("The D3D9 device is now operating in D3D8 compatibility mode.");
m_isD3D8Compatible = compatMode;
}
// Device Lost
bool IsDeviceLost() const {
return m_deviceLostState != D3D9DeviceLostState::Ok;
}
void NotifyFullscreen(HWND window, bool fullscreen);
void NotifyWindowActivated(HWND window, bool activated);
void IncrementLosableCounter() {
m_losableResourceCounter++;
}
void DecrementLosableCounter() {
m_losableResourceCounter--;
}
bool CanOnlySWVP() const {
return m_behaviorFlags & D3DCREATE_SOFTWARE_VERTEXPROCESSING;
}
private:
DxvkCsChunkRef AllocCsChunk() {
@ -957,12 +1029,15 @@ namespace dxvk {
return DxvkCsChunkRef(chunk, &m_csChunkPool);
}
template<typename Cmd>
template<bool AllowFlush = true, typename Cmd>
void EmitCs(Cmd&& command) {
if (unlikely(!m_csChunk->push(command))) {
EmitCsChunk(std::move(m_csChunk));
m_csChunk = AllocCsChunk();
if constexpr (AllowFlush)
ConsiderFlush(GpuFlushType::ImplicitWeakHint);
m_csChunk->push(command);
}
}
@ -976,10 +1051,18 @@ namespace dxvk {
}
}
bool CanSWVP() {
bool CanSWVP() const {
return m_behaviorFlags & (D3DCREATE_MIXED_VERTEXPROCESSING | D3DCREATE_SOFTWARE_VERTEXPROCESSING);
}
// Device Reset detection for D3D9SwapChainEx::Present
bool IsDeviceReset() {
return std::exchange(m_deviceHasBeenReset, false);
}
template <bool Synchronize9On12>
void ExecuteFlush();
void DetermineConstantLayouts(bool canSWVP);
D3D9BufferSlice AllocUPBuffer(VkDeviceSize size);
@ -1004,7 +1087,7 @@ namespace dxvk {
}
inline uint32_t GetUPBufferSize(uint32_t vertexCount, uint32_t stride) {
return (vertexCount - 1) * stride + std::max(m_state.vertexDecl->GetSize(), stride);
return (vertexCount - 1) * stride + std::max(m_state.vertexDecl->GetSize(0), stride);
}
inline void FillUPVertexBuffer(void* buffer, const void* userData, uint32_t dataSize, uint32_t bufferSize) {
@ -1093,13 +1176,13 @@ namespace dxvk {
return D3DERR_INVALIDCALL;
if constexpr (ConstantType == D3D9ConstantType::Float) {
const float* source = set.fConsts[StartRegister].data;
const float* source = set->fConsts[StartRegister].data;
const size_t size = Count * sizeof(Vector4);
std::memcpy(pConstantData, source, size);
}
else if constexpr (ConstantType == D3D9ConstantType::Int) {
const int* source = set.iConsts[StartRegister].data;
const int* source = set->iConsts[StartRegister].data;
const size_t size = Count * sizeof(Vector4i);
std::memcpy(pConstantData, source, size);
@ -1112,7 +1195,7 @@ namespace dxvk {
const uint32_t bit = (1u << bitIdx);
bool constValue = set.bConsts[arrayIdx] & bit;
bool constValue = set->bConsts[arrayIdx] & bit;
pConstantData[i] = constValue ? TRUE : FALSE;
}
}
@ -1162,11 +1245,38 @@ namespace dxvk {
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;
D3DDEVTYPE m_deviceType;
HWND m_window;
WORD m_behaviorFlags;
D3DPRESENT_PARAMETERS m_presentParams;
D3D9Adapter* m_adapter;
Rc<DxvkDevice> m_dxvkDevice;
@ -1245,14 +1355,16 @@ namespace dxvk {
uint32_t m_dirtySamplerStates = 0;
uint32_t m_dirtyTextures = 0;
uint32_t m_boundRTs = 0;
uint32_t m_boundRTs : 4;
uint32_t m_anyColorWrites : 4;
uint32_t m_activeRTsWhichAreTextures : 4;
uint32_t m_alphaSwizzleRTs : 4;
uint32_t m_lastHazardsRT : 4;
uint32_t m_activeRTs = 0;
uint32_t m_activeRTTextures = 0;
uint32_t m_activeDSTextures = 0;
uint32_t m_activeTextureRTs = 0;
uint32_t m_activeTextureDSs = 0;
uint32_t m_activeHazardsRT = 0;
uint32_t m_activeHazardsDS = 0;
uint32_t m_alphaSwizzleRTs = 0;
uint32_t m_activeTextures = 0;
uint32_t m_activeTexturesToUpload = 0;
uint32_t m_activeTexturesToGen = 0;
@ -1267,7 +1379,6 @@ namespace dxvk {
uint32_t m_fetch4 = 0;
uint32_t m_lastHazardsDS = 0;
uint32_t m_lastHazardsRT = 0;
uint32_t m_lastSamplerTypesFF = 0;
D3D9SpecializationInfo m_specInfo = D3D9SpecializationInfo();
@ -1276,14 +1387,17 @@ namespace dxvk {
D3D9ShaderMasks m_psShaderMasks = FixedFunctionMask;
bool m_isSWVP;
bool m_amdATOC = false;
bool m_nvATOC = false;
bool m_ffZTest = false;
bool m_isD3D8Compatible = false;
bool m_amdATOC = false;
bool m_nvATOC = false;
bool m_ffZTest = false;
VkImageLayout m_hazardLayout = VK_IMAGE_LAYOUT_GENERAL;
bool m_usingGraphicsPipelines = false;
bool m_deviceHasBeenReset = false;
DxvkDepthBiasRepresentation m_depthBiasRepresentation = { VK_DEPTH_BIAS_REPRESENTATION_LEAST_REPRESENTABLE_VALUE_FORMAT_EXT, false };
float m_depthBiasScale = 0.0f;
uint32_t m_robustSSBOAlignment = 1;
@ -1305,23 +1419,37 @@ namespace dxvk {
D3D9ViewportInfo m_viewportInfo;
DxvkCsChunkPool m_csChunkPool;
dxvk::high_resolution_clock::time_point m_lastFlush
= dxvk::high_resolution_clock::now();
DxvkCsThread m_csThread;
DxvkCsChunkRef m_csChunk;
uint64_t m_csSeqNum = 0ull;
bool m_csIsBusy = false;
Rc<sync::Fence> m_submissionFence;
uint64_t m_submissionId = 0ull;
DxvkSubmitStatus m_submitStatus;
uint64_t m_flushSeqNum = 0ull;
GpuFlushTracker m_flushTracker;
std::atomic<int64_t> m_availableMemory = { 0 };
std::atomic<int32_t> m_samplerCount = { 0 };
Direct3DState9 m_state;
D3D9DeviceLostState m_deviceLostState = D3D9DeviceLostState::Ok;
HWND m_fullscreenWindow = NULL;
std::atomic<uint32_t> m_losableResourceCounter = { 0 };
D3D9SwapChainEx* m_mostRecentlyUsedSwapchain = nullptr;
#ifdef D3D9_ALLOW_UNMAPPING
lru_list<D3D9CommonTexture*> m_mappedTextures;
#endif
// m_state should be declared last (i.e. freed first), because it
// references objects that can call back into the device when freed.
Direct3DState9 m_state;
D3D9VkInteropDevice m_d3d9Interop;
D3D9On12 m_d3d9On12;
DxvkD3D8Bridge m_d3d8Bridge;
};
}

View File

@ -14,6 +14,7 @@ namespace dxvk {
D3D9FixedFunctionOptions::D3D9FixedFunctionOptions(const D3D9Options* options) {
invariantPosition = options->invariantPosition;
forceSampleRateShading = options->forceSampleRateShading;
}
uint32_t DoFixedFunctionFog(D3D9ShaderSpecConstantManager& spec, SpirvModule& spvModule, const D3D9FogContext& fogCtx) {
@ -335,7 +336,7 @@ namespace dxvk {
}
uint32_t SetupRenderStateBlock(SpirvModule& spvModule, uint32_t count) {
uint32_t SetupRenderStateBlock(SpirvModule& spvModule) {
uint32_t floatType = spvModule.defFloatType(32);
uint32_t uintType = spvModule.defIntType(32, 0);
uint32_t vec3Type = spvModule.defVectorType(floatType, 3);
@ -356,7 +357,7 @@ namespace dxvk {
floatType,
}};
uint32_t rsStruct = spvModule.defStructTypeUnique(count, rsMembers.data());
uint32_t rsStruct = spvModule.defStructTypeUnique(rsMembers.size(), rsMembers.data());
uint32_t rsBlock = spvModule.newVar(
spvModule.defPointerType(rsStruct, spv::StorageClassPushConstant),
spv::StorageClassPushConstant);
@ -368,9 +369,6 @@ namespace dxvk {
uint32_t memberIdx = 0;
auto SetMemberName = [&](const char* name, uint32_t offset) {
if (memberIdx >= count)
return;
spvModule.setDebugMemberName (rsStruct, memberIdx, name);
spvModule.memberDecorateOffset (rsStruct, memberIdx, offset);
memberIdx++;
@ -422,6 +420,7 @@ namespace dxvk {
binding.resourceBinding = getSpecConstantBufferSlot();
binding.viewType = VK_IMAGE_VIEW_TYPE_MAX_ENUM;
binding.access = VK_ACCESS_UNIFORM_READ_BIT;
binding.uboSet = VK_TRUE;
bindings.push_back(binding);
return specBlock;
@ -779,8 +778,6 @@ namespace dxvk {
uint32_t m_inputMask = 0u;
uint32_t m_outputMask = 0u;
uint32_t m_flatShadingMask = 0u;
uint32_t m_pushConstOffset = 0u;
uint32_t m_pushConstSize = 0u;
DxsoProgramType m_programType;
D3D9FFShaderKeyVS m_vsKey;
@ -890,8 +887,8 @@ namespace dxvk {
info.inputMask = m_inputMask;
info.outputMask = m_outputMask;
info.flatShadingInputs = m_flatShadingMask;
info.pushConstOffset = m_pushConstOffset;
info.pushConstSize = m_pushConstSize;
info.pushConstStages = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
info.pushConstSize = sizeof(D3D9RenderStateInfo);
return new DxvkShader(info, m_module.compile());
}
@ -933,10 +930,16 @@ namespace dxvk {
uint32_t ptr = m_module.newVar(ptrType, storageClass);
if (builtin == spv::BuiltInMax)
if (builtin == spv::BuiltInMax) {
m_module.decorateLocation(ptr, slot);
else
if (isPS() && input && m_options.forceSampleRateShading) {
m_module.enableCapability(spv::CapabilitySampleRateShading);
m_module.decorate(ptr, spv::DecorationSample);
}
} else {
m_module.decorateBuiltIn(ptr, builtin);
}
bool diffuseOrSpec = semantic == DxsoSemantic{ DxsoUsage::Color, 0 }
|| semantic == DxsoSemantic{ DxsoUsage::Color, 1 };
@ -1094,19 +1097,30 @@ namespace dxvk {
m_module.opStore(m_vs.out.NORMAL, outNrm);
for (uint32_t i = 0; i < caps::TextureStageCount; i++) {
uint32_t inputIndex = (m_vsKey.Data.Contents.TexcoordIndices >> (i * 3)) & 0b111;
uint32_t inputFlags = (m_vsKey.Data.Contents.TexcoordFlags >> (i * 3)) & 0b111;
uint32_t inputIndex = (m_vsKey.Data.Contents.TexcoordIndices >> (i * 3)) & 0b111;
uint32_t inputFlags = (m_vsKey.Data.Contents.TexcoordFlags >> (i * 3)) & 0b111;
uint32_t texcoordCount = (m_vsKey.Data.Contents.TexcoordDeclMask >> (inputIndex * 3)) & 0b111;
uint32_t transformed;
const uint32_t wIndex = 3;
uint32_t flags = (m_vsKey.Data.Contents.TransformFlags >> (i * 3)) & 0b111;
uint32_t count = flags;
uint32_t count;
switch (inputFlags) {
default:
case (DXVK_TSS_TCI_PASSTHRU >> TCIOffset):
transformed = m_vs.in.TEXCOORD[inputIndex & 0xFF];
// flags is actually the number of elements that get passed
// to the rasterizer.
count = flags;
if (texcoordCount) {
// Clamp by the number of elements in the texcoord input.
if (!count || count > texcoordCount)
count = texcoordCount;
}
else
flags = D3DTTFF_DISABLE;
break;
case (DXVK_TSS_TCI_CAMERASPACENORMAL >> TCIOffset):
@ -1365,20 +1379,7 @@ namespace dxvk {
void D3D9FFShaderCompiler::setupRenderStateInfo() {
uint32_t count;
if (m_programType == DxsoProgramType::PixelShader) {
m_pushConstOffset = 0;
m_pushConstSize = offsetof(D3D9RenderStateInfo, pointSize);
count = 5;
}
else {
m_pushConstOffset = offsetof(D3D9RenderStateInfo, pointSize);
m_pushConstSize = sizeof(float) * 6;
count = 11;
}
m_rsBlock = SetupRenderStateBlock(m_module, count);
m_rsBlock = SetupRenderStateBlock(m_module);
}
@ -1570,6 +1571,7 @@ namespace dxvk {
binding.resourceBinding = bindingId;
binding.viewType = VK_IMAGE_VIEW_TYPE_MAX_ENUM;
binding.access = VK_ACCESS_UNIFORM_READ_BIT;
binding.uboSet = VK_TRUE;
m_bindings.push_back(binding);
}
@ -1609,6 +1611,7 @@ namespace dxvk {
binding.resourceBinding = bindingId;
binding.viewType = VK_IMAGE_VIEW_TYPE_MAX_ENUM;
binding.access = VK_ACCESS_SHADER_READ_BIT;
binding.uboSet = VK_TRUE;
m_bindings.push_back(binding);
}
@ -1788,10 +1791,10 @@ namespace dxvk {
texcoord, texcoord, texcoordCnt, indices.data());
uint32_t projIdx = m_fsKey.Stages[i].Contents.ProjectedCount;
if (projIdx == 0)
projIdx = texcoordCnt;
else
projIdx--;
if (projIdx == 0 || projIdx > texcoordCnt) {
projIdx = 4; // Always use w if ProjectedCount is 0.
}
--projIdx;
uint32_t projValue = 0;
@ -2220,6 +2223,7 @@ namespace dxvk {
binding.resourceBinding = bindingId;
binding.viewType = VK_IMAGE_VIEW_TYPE_MAX_ENUM;
binding.access = VK_ACCESS_UNIFORM_READ_BIT;
binding.uboSet = VK_TRUE;
m_bindings.push_back(binding);
// Load constants
@ -2307,6 +2311,7 @@ namespace dxvk {
binding.resourceBinding = bindingId;
binding.viewType = VK_IMAGE_VIEW_TYPE_MAX_ENUM;
binding.access = VK_ACCESS_UNIFORM_READ_BIT;
binding.uboSet = VK_TRUE;
m_bindings.push_back(binding);
}
@ -2346,6 +2351,7 @@ namespace dxvk {
binding.resourceBinding = bindingId;
binding.viewType = VK_IMAGE_VIEW_TYPE_MAX_ENUM;
binding.access = VK_ACCESS_UNIFORM_READ_BIT;
binding.uboSet = VK_TRUE;
m_bindings.push_back(binding);
// Declare output array for clip distances

View File

@ -49,6 +49,7 @@ namespace dxvk {
D3D9FixedFunctionOptions(const D3D9Options* options);
bool invariantPosition;
bool forceSampleRateShading;
};
// Returns new oFog if VS
@ -58,7 +59,7 @@ namespace dxvk {
void DoFixedFunctionAlphaTest(SpirvModule& spvModule, const D3D9AlphaTestContext& ctx);
// Returns a render state block
uint32_t SetupRenderStateBlock(SpirvModule& spvModule, uint32_t count);
uint32_t SetupRenderStateBlock(SpirvModule& spvModule);
struct D3D9PointSizeInfoVS {
uint32_t defaultValue;

View File

@ -132,7 +132,7 @@ namespace dxvk {
VK_IMAGE_ASPECT_COLOR_BIT,
{ VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G,
VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A },
{ D3D9ConversionFormat_L6V5U5, 1u,
{ D3D9ConversionFormat_L6V5U5,
// Convert -> float (this is a mixed snorm and unorm type)
VK_FORMAT_R16G16B16A16_SFLOAT } };
@ -142,7 +142,7 @@ namespace dxvk {
VK_IMAGE_ASPECT_COLOR_BIT,
{ VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G,
VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_ONE },
{ D3D9ConversionFormat_X8L8V8U8, 1u,
{ D3D9ConversionFormat_X8L8V8U8,
// Convert -> float (this is a mixed snorm and unorm type)
VK_FORMAT_R16G16B16A16_SFLOAT } };
@ -164,7 +164,7 @@ namespace dxvk {
VK_IMAGE_ASPECT_COLOR_BIT,
{ VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G,
VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A },
{ D3D9ConversionFormat_A2W10V10U10, 1u,
{ D3D9ConversionFormat_A2W10V10U10,
// Convert -> float (this is a mixed snorm and unorm type)
VK_FORMAT_R16G16B16A16_SFLOAT } };
@ -174,17 +174,17 @@ namespace dxvk {
VK_IMAGE_ASPECT_COLOR_BIT,
{ VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G,
VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_ONE },
{ D3D9ConversionFormat_W11V11U10, 1u,
{ D3D9ConversionFormat_W11V11U10,
// can't use B10G11R11 bc this is a snorm type
VK_FORMAT_R16G16B16A16_SNORM } };
case D3D9Format::UYVY: return {
VK_FORMAT_B8G8R8A8_UNORM,
VK_FORMAT_G8B8G8R8_422_UNORM,
VK_FORMAT_UNDEFINED,
VK_IMAGE_ASPECT_COLOR_BIT,
{ VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY,
VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY },
{ D3D9ConversionFormat_UYVY, 1u }
{ D3D9ConversionFormat_UYVY, VK_FORMAT_B8G8R8A8_UNORM }
};
case D3D9Format::R8G8_B8G8: return {
@ -193,12 +193,12 @@ namespace dxvk {
VK_IMAGE_ASPECT_COLOR_BIT };
case D3D9Format::YUY2: return {
VK_FORMAT_B8G8R8A8_UNORM,
VK_FORMAT_G8B8G8R8_422_UNORM,
VK_FORMAT_UNDEFINED,
VK_IMAGE_ASPECT_COLOR_BIT,
{ VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY,
VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY },
{ D3D9ConversionFormat_YUY2, 1u }
{ D3D9ConversionFormat_YUY2, VK_FORMAT_B8G8R8A8_UNORM }
};
case D3D9Format::G8R8_G8B8: return {
@ -410,21 +410,21 @@ namespace dxvk {
VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R }};
case D3D9Format::NV12: return {
VK_FORMAT_R8_UNORM,
VK_FORMAT_G8_B8R8_2PLANE_420_UNORM,
VK_FORMAT_UNDEFINED,
VK_IMAGE_ASPECT_COLOR_BIT,
{ VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY,
VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY },
{ D3D9ConversionFormat_NV12, 2u, VK_FORMAT_B8G8R8A8_UNORM }
{ D3D9ConversionFormat_NV12, VK_FORMAT_B8G8R8A8_UNORM }
};
case D3D9Format::YV12: return {
VK_FORMAT_R8_UNORM,
VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM,
VK_FORMAT_UNDEFINED,
VK_IMAGE_ASPECT_COLOR_BIT,
{ VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY,
VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY },
{ D3D9ConversionFormat_YV12, 3u, VK_FORMAT_B8G8R8A8_UNORM }
{ D3D9ConversionFormat_YV12, VK_FORMAT_B8G8R8A8_UNORM }
};
case D3D9Format::RAWZ: return {}; // Unsupported
@ -438,7 +438,11 @@ namespace dxvk {
D3D9VkFormatTable::D3D9VkFormatTable(
const Rc<DxvkAdapter>& adapter,
const D3D9Options& options) {
m_dfSupport = options.supportDFFormats;
const auto& props = adapter->deviceProperties();
uint32_t vendorId = options.customVendorId == -1 ? props.vendorID : uint32_t(options.customVendorId);
m_dfSupport = options.supportDFFormats && DxvkGpuVendor(vendorId) != DxvkGpuVendor::Nvidia;
m_x4r4g4b4Support = options.supportX4R4G4B4;
m_d32supportFinal = options.supportD32;

View File

@ -143,7 +143,6 @@ namespace dxvk {
struct D3D9_CONVERSION_FORMAT_INFO {
D3D9ConversionFormat FormatType = D3D9ConversionFormat_None;
uint32_t PlaneCount = 1;
VkFormat FormatColor = VK_FORMAT_UNDEFINED;
VkFormat FormatSrgb = VK_FORMAT_UNDEFINED;
};

View File

@ -134,7 +134,7 @@ namespace dxvk {
info.stage = VK_SHADER_STAGE_COMPUTE_BIT;
info.bindingCount = bindings.size();
info.bindings = bindings.data();
info.pushConstOffset = 0;
info.pushConstStages = VK_SHADER_STAGE_COMPUTE_BIT;
info.pushConstSize = sizeof(VkExtent2D);
return new DxvkShader(info, std::move(code));
@ -142,7 +142,7 @@ namespace dxvk {
void D3D9FormatHelper::FlushInternal() {
m_context->flushCommandList();
m_context->flushCommandList(nullptr);
m_transferCommands = 0;
}

View File

@ -12,9 +12,9 @@
//for some reason we need to specify __declspec(dllexport) for MinGW
#if defined(__WINE__) || !defined(_WIN32)
#define DLLEXPORT __attribute__((visibility("default")))
#define DLLEXPORT __attribute__((visibility("default")))
#else
#define DLLEXPORT
#define DLLEXPORT
#endif
@ -40,55 +40,68 @@
// Missed definitions in Wine/MinGW.
#ifndef D3DPRESENT_BACK_BUFFERS_MAX_EX
#define D3DPRESENT_BACK_BUFFERS_MAX_EX 30
#endif
#ifndef D3DSI_OPCODE_MASK
#define D3DSI_OPCODE_MASK 0x0000FFFF
#endif
#ifndef D3DSP_TEXTURETYPE_MASK
#define D3DSP_TEXTURETYPE_MASK 0x78000000
#endif
#ifndef D3DUSAGE_AUTOGENMIPMAP
#define D3DUSAGE_AUTOGENMIPMAP 0x00000400L
#endif
#ifndef D3DSP_DCL_USAGE_MASK
#define D3DSP_DCL_USAGE_MASK 0x0000000f
#endif
#ifndef D3DSP_OPCODESPECIFICCONTROL_MASK
#define D3DSP_OPCODESPECIFICCONTROL_MASK 0x00ff0000
#endif
#ifndef D3DSP_OPCODESPECIFICCONTROL_SHIFT
#define D3DSP_OPCODESPECIFICCONTROL_SHIFT 16
#endif
#ifndef D3DCURSOR_IMMEDIATE_UPDATE
#define D3DCURSOR_IMMEDIATE_UPDATE 0x00000001L
#endif
#ifndef D3DPRESENT_FORCEIMMEDIATE
#define D3DPRESENT_FORCEIMMEDIATE 0x00000100L
#endif
#ifndef D3DSWAPEFFECT_COPY_VSYNC
#define D3DSWAPEFFECT_COPY_VSYNC 4
#endif
// MinGW headers are broken. Who'dve guessed?
#ifndef _MSC_VER
typedef struct _D3DDEVINFO_RESOURCEMANAGER
{
char dummy;
} D3DDEVINFO_RESOURCEMANAGER, * LPD3DDEVINFO_RESOURCEMANAGER;
#ifndef __WINE__
extern "C" WINUSERAPI WINBOOL WINAPI SetProcessDPIAware(VOID);
#endif
#endif
// This is the managed pool on D3D9Ex, it's just hidden!
#define D3DPOOL_MANAGED_EX D3DPOOL(6)
using D3D9VertexElements = std::vector<D3DVERTEXELEMENT9>;
/////////////////////
// D3D9On12 content
/////////////////////
#include <d3d12.h>
#define MAX_D3D9ON12_QUEUES 2
struct D3D9ON12_ARGS {
BOOL Enable9On12;
IUnknown* pD3D12Device;
IUnknown* ppD3D12Queues[MAX_D3D9ON12_QUEUES];
UINT NumQueues;
UINT NodeMask;
};
extern "C" {
// Ordinal 20
typedef IDirect3D9* (WINAPI* PFN_Direct3DCreate9On12)(UINT sdk_version, D3D9ON12_ARGS* override_list, UINT override_entry_count);
IDirect3D9* WINAPI Direct3DCreate9On12(UINT sdk_version, D3D9ON12_ARGS* override_list, UINT override_entry_count);
// Ordinal 21
typedef HRESULT(WINAPI* PFN_Direct3DCreate9On12Ex)(UINT sdk_version, D3D9ON12_ARGS* override_list, UINT override_entry_count, IDirect3D9Ex** output);
HRESULT WINAPI Direct3DCreate9On12Ex(UINT sdk_version, D3D9ON12_ARGS* override_list, UINT override_entry_count, IDirect3D9Ex** output);
}
MIDL_INTERFACE("e7fda234-b589-4049-940d-8878977531c8")
IDirect3DDevice9On12 : public IUnknown {
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** object) = 0;
virtual ULONG STDMETHODCALLTYPE AddRef() = 0;
virtual ULONG STDMETHODCALLTYPE Release() = 0;
virtual HRESULT STDMETHODCALLTYPE GetD3D12Device(REFIID riid, void** object) = 0;
virtual HRESULT STDMETHODCALLTYPE UnwrapUnderlyingResource(IDirect3DResource9* resource, ID3D12CommandQueue* command_queue, REFIID riid, void** object) = 0;
virtual HRESULT STDMETHODCALLTYPE ReturnUnderlyingResource(IDirect3DResource9* resource, UINT num_sync, UINT64* signal_values, ID3D12Fence** fences) = 0;
};
#ifndef _MSC_VER
__CRT_UUID_DECL(IDirect3DDevice9On12, 0xe7fda234,0xb589,0x4049,0x94,0x0d,0x88,0x78,0x97,0x75,0x31,0xc8);
#endif

View File

@ -153,7 +153,7 @@ namespace dxvk {
void D3D9Initializer::FlushInternal() {
m_context->flushCommandList();
m_context->flushCommandList(nullptr);
m_transferCommands = 0;
m_transferMemory = 0;

View File

@ -3,13 +3,19 @@
#include "d3d9_monitor.h"
#include "d3d9_caps.h"
#include "d3d9_device.h"
#include "d3d9_bridge.h"
#include "../util/util_singleton.h"
#include <algorithm>
namespace dxvk {
Singleton<DxvkInstance> g_dxvkInstance;
D3D9InterfaceEx::D3D9InterfaceEx(bool bExtended)
: m_instance ( new DxvkInstance() )
: m_instance ( g_dxvkInstance.acquire(DxvkInstanceFlag::ClientApiIsD3D9) )
, m_d3d8Bridge ( this )
, m_extended ( bExtended )
, m_d3d9Options ( nullptr, m_instance->config() )
, m_d3d9Interop ( this ) {
@ -64,6 +70,11 @@ namespace dxvk {
}
D3D9InterfaceEx::~D3D9InterfaceEx() {
g_dxvkInstance.release();
}
HRESULT STDMETHODCALLTYPE D3D9InterfaceEx::QueryInterface(REFIID riid, void** ppvObject) {
if (ppvObject == nullptr)
return E_POINTER;
@ -77,13 +88,21 @@ namespace dxvk {
return S_OK;
}
if (riid == __uuidof(IDxvkD3D8InterfaceBridge)) {
*ppvObject = ref(&m_d3d8Bridge);
return S_OK;
}
if (riid == __uuidof(ID3D9VkInteropInterface)) {
*ppvObject = ref(&m_d3d9Interop);
return S_OK;
}
Logger::warn("D3D9InterfaceEx::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
if (logQueryInterfaceError(__uuidof(IDirect3D9), riid)) {
Logger::warn("D3D9InterfaceEx::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
}
return E_NOINTERFACE;
}

View File

@ -1,6 +1,7 @@
#pragma once
#include "d3d9_adapter.h"
#include "d3d9_bridge.h"
#include "d3d9_interop.h"
#include "../dxvk/dxvk_instance.h"
@ -20,6 +21,8 @@ namespace dxvk {
D3D9InterfaceEx(bool bExtended);
~D3D9InterfaceEx();
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject);
HRESULT STDMETHODCALLTYPE RegisterSoftwareDevice(void* pInitializeFunction);
@ -138,6 +141,8 @@ namespace dxvk {
Rc<DxvkInstance> m_instance;
DxvkD3D8InterfaceBridge m_d3d8Bridge;
bool m_extended;
D3D9Options m_d3d9Options;

View File

@ -196,12 +196,42 @@ ID3D9VkInteropDevice : public IUnknown {
DWORD MapFlags) = 0;
};
#ifdef _MSC_VER
struct __declspec(uuid("3461a81b-ce41-485b-b6b5-fcf08ba6a6bd")) ID3D9VkInteropInterface;
struct __declspec(uuid("d56344f5-8d35-46fd-806d-94c351b472c1")) ID3D9VkInteropTexture;
struct __declspec(uuid("2eaa4b89-0107-4bdb-87f7-0f541c493ce0")) ID3D9VkInteropDevice;
#else
/**
* \brief D3D9 current output metadata
*/
struct D3D9VkExtOutputMetadata {
float RedPrimary[2];
float GreenPrimary[2];
float BluePrimary[2];
float WhitePoint[2];
float MinLuminance;
float MaxLuminance;
float MaxFullFrameLuminance;
};
/**
* \brief D3D9 extended swapchain
*/
MIDL_INTERFACE("13776e93-4aa9-430a-a4ec-fe9e281181d5")
ID3D9VkExtSwapchain : public IUnknown {
virtual BOOL STDMETHODCALLTYPE CheckColorSpaceSupport(
VkColorSpaceKHR ColorSpace) = 0;
virtual HRESULT STDMETHODCALLTYPE SetColorSpace(
VkColorSpaceKHR ColorSpace) = 0;
virtual HRESULT STDMETHODCALLTYPE SetHDRMetaData(
const VkHdrMetadataEXT *pHDRMetadata) = 0;
virtual HRESULT STDMETHODCALLTYPE GetCurrentOutputDesc(
D3D9VkExtOutputMetadata *pOutputDesc) = 0;
virtual void STDMETHODCALLTYPE UnlockAdditionalFormats() = 0;
};
#ifndef _MSC_VER
__CRT_UUID_DECL(ID3D9VkInteropInterface, 0x3461a81b,0xce41,0x485b,0xb6,0xb5,0xfc,0xf0,0x8b,0xa6,0xa6,0xbd);
__CRT_UUID_DECL(ID3D9VkInteropTexture, 0xd56344f5,0x8d35,0x46fd,0x80,0x6d,0x94,0xc3,0x51,0xb4,0x72,0xc1);
__CRT_UUID_DECL(ID3D9VkInteropDevice, 0x2eaa4b89,0x0107,0x4bdb,0x87,0xf7,0x0f,0x54,0x1c,0x49,0x3c,0xe0);
__CRT_UUID_DECL(ID3D9VkExtSwapchain, 0x13776e93,0x4aa9,0x430a,0xa4,0xec,0xfe,0x9e,0x28,0x11,0x81,0xd5);
#endif

Some files were not shown because too many files have changed in this diff Show More