Compare commits

...

1432 commits
v2.1 ... master

Author SHA1 Message Date
Philip Rebohle
a08579e555 [dxvk] Fix clear after late resolve 2025-03-06 09:54:34 +01:00
Philip Rebohle
45ec01a0a1 [d3d11] Add TRANSFER_SRC usage to icb
Needed for defrag.
2025-03-06 09:54:34 +01:00
Philip Rebohle
542e0d2ab0 [dxvk,d3d9,d3d11] Decouple ID3DUserDefinedAnnotation from internal markers
Some games nope out when we expose debug markers, so add a debug mode
that doesn't while still providing internal markers and debug names.
2025-03-06 09:54:34 +01:00
Philip Rebohle
91b48dd31d [d3d11] Make user defined annotation more robust 2025-03-06 09:54:34 +01:00
GranMinigun
d8eb4d0d66 [util] Spoof vendor ID for CivCity: Rome 2025-03-06 01:25:30 +01:00
Philip Rebohle
f161d9bc7b [dxvk] Fix synchronization on swapchain tear-down 2025-03-05 23:16:28 +01:00
Philip Rebohle
634f38b38d [dxvk] Enable sparse binding features if supported 2025-03-05 23:15:47 +01:00
Philip Rebohle
ff8378be19 [dxvk] Fix uploadImage barriers 2025-03-05 23:15:47 +01:00
Philip Rebohle
ad75fb17cd [dxvk] Fix uploadBuffer barriers 2025-03-05 23:15:47 +01:00
Philip Rebohle
76244812fb [dxvk] Move compressed image initialization to transfer queue
This is relatively common.
2025-03-05 23:15:47 +01:00
Philip Rebohle
9c0dec9f58 [dxvk] Move buffer initialization to transfer queue 2025-03-05 23:15:47 +01:00
Philip Rebohle
a4a5bf5d63 [dxvk] Add helpers for transfer queue release barriers 2025-03-05 23:15:47 +01:00
Philip Rebohle
49f0968f57 [dxvk] Use sparse residency for zero buffer
Saves a small amount of memory since reading from an unbound
buffer will return zero anyway.
2025-03-05 23:15:47 +01:00
Philip Rebohle
ec0deb73da [dxvk] Fix missing zero buffer tracking
Scary.
2025-03-05 23:15:47 +01:00
WinterSnowfall
fed51e6c92 [dxso] Fix uninitialized m_maxDefinedConstant variable 2025-03-05 15:02:11 +01:00
Philip Rebohle
196258111c [dxvk] Be more conservative with CS data alignment
Fixes #4734. Apparently, weak alignment hints are an error rather
than getting ignored.
2025-03-05 13:12:23 +01:00
Philip Rebohle
d04fe1cdc0 [meta] Add some missing documentation to dxvk.conf 2025-03-04 21:49:39 +01:00
Philip Rebohle
3cf453160c [d3d11] Ensure required image usage flags for video blits
Fixes some validation errors.
2025-03-04 21:05:59 +01:00
Philip Rebohle
9769df9dd8 [d3d11] Implement ID3D11On12Device1 2025-03-02 19:21:39 +01:00
Philip Rebohle
106032fa65 [dxvk] Use granular image access tracking in copyImageHw 2025-03-02 14:01:09 +01:00
Philip Rebohle
d2b53b76de [dxvk] Use granular image access tracking in copyBufferToImageHw 2025-03-02 14:01:09 +01:00
Philip Rebohle
02dc403074 [dxvk] Use granular image access tracking in copyImageToBufferCs 2025-03-02 14:01:09 +01:00
Philip Rebohle
420d083677 [dxvk] Use granular image access tracking in copyImageToBufferHw 2025-03-02 14:01:09 +01:00
Philip Rebohle
cd29f0feaa [dxvk] Add barrier helpers for granular image access tracking 2025-03-02 14:01:09 +01:00
Philip Rebohle
baaf72a373 [dxvk] Add helpers to compute more granular image address ranges 2025-03-02 14:01:09 +01:00
Philip Rebohle
1f0ad760e1 [dxvk] Refactor address range for barrier tracking
Allows us to bump the size and offset to 64 bits without increasing the
total size of the node.
2025-03-02 14:01:09 +01:00
Philip Rebohle
fe58b393d4 [util] Add helper for 2D and 3D morton codes 2025-03-02 14:01:09 +01:00
Philip Rebohle
c21f4e0190 [util] Add 48-bit integer type 2025-03-02 14:01:09 +01:00
Philip Rebohle
416f9c5a4a [d3d11] Embed UpdateBuffer data in CS chunk
Tiny optimization that gets rid of a copy and also lets us use chunk
memory more efficiently.
2025-03-02 13:29:48 +01:00
Philip Rebohle
5b68884fd9 [d3d11] Fix confusing debug color for GPU synchronization
Purple was already used for various other things.
2025-03-01 16:37:39 +01:00
Robin Kertels
8f84085370 [dxvk] Add CS thread load to the HUD 2025-03-01 14:23:22 +01:00
Philip Rebohle
b35e69b467 [d3d11] Skip empty draws
Watch Dogs 2 likes to do this with graphics UAVs bound, which
introduces quite a bit of unnecessary GPU synchronization.
2025-03-01 11:30:38 +01:00
Philip Rebohle
11dc0e7ce8 [util] Enable compute UAV barriers for Watch Dogs 2 2025-02-28 23:57:26 +01:00
Philip Rebohle
6b5d595b3e [d3d11] Add option to force compute shader UAV synchronization 2025-02-28 23:57:26 +01:00
Philip Rebohle
396a4e0235 [dxbc] Add option to implicitly synchronize UAV accesses 2025-02-28 23:57:26 +01:00
Philip Rebohle
c04410ca00 [dxbc] Increase maximum size of embedded icbs to 256 bytes
Gives drivers more info, while still avoiding duplication of large ICBs
when compiling the same shader into a large number of pipelines.
2025-02-28 12:07:49 +01:00
Philip Rebohle
fcbdff3b72 [d3d9] Set correct input topology for SWVP emulation
Otherwise we'll run the input patch pass, even if it doesn't do anything.
2025-02-26 20:58:47 +01:00
Philip Rebohle
0359a3521d [dxvk] Patch geometry shader if input topology does not match pipeline 2025-02-26 20:53:43 +01:00
Philip Rebohle
b41253e18d [dxvk] Add pass to patch GS input topology if necessary 2025-02-26 20:53:43 +01:00
Philip Rebohle
96a260e94e [dxbc] Write back GS input topology to shader info 2025-02-26 20:53:43 +01:00
Philip Rebohle
2cb9d40f88 [dxvk] Add input topology field to shader info 2025-02-26 20:53:43 +01:00
Philip Rebohle
2cd305e606 [dxvk] Enable uniformBufferStandardLayout feature
Core and required in Vulkan 1.2, but keep it optional anyway for now
since we're not really doing anything critical with it.
2025-02-26 20:52:25 +01:00
Philip Rebohle
ec5bd04378 [dxvk] Remove uniform data from shaders
No longer used
2025-02-26 20:52:25 +01:00
Philip Rebohle
43f360d20c [d3d11] Move immediate constant buffers to non-mapped VRAM
This has the advantage that icbs can be defragmented and don't
take up space in HVV chunks that would potentially go unused.
2025-02-26 20:52:25 +01:00
Philip Rebohle
6f59124e9a [dxbc] Retrieve icb data directly from shader module 2025-02-26 20:52:25 +01:00
Philip Rebohle
d6d13edb7a [dxbc] Use smallest aligned vector type for buffer-backed ubo 2025-02-26 20:52:25 +01:00
Philip Rebohle
31192b6d3f [dxbc] Rework embedded immediate constant buffers
Considerably reduces the size of immediate constant buffer arrays when
not all vector components are used. Also adds bound-checking.
2025-02-26 20:52:25 +01:00
WinterSnowfall
31a4679960 [dxvk] Don't skip CPU devices when a device filter is set 2025-02-25 21:39:22 +01:00
Philip Rebohle
13bd234cea [dxvk] Actually fix multidraw workaround
Otherwise we'll end up using the feature anyway.
2025-02-25 14:18:05 +01:00
Philip Rebohle
dafb71b18e [d3d11] Add debug labels for submissions 2025-02-25 00:17:35 +01:00
Philip Rebohle
a0c8bbaf10 [dxvk] Add method to retrieve resource debug names 2025-02-25 00:17:31 +01:00
Philip Rebohle
9c395fd60d [dxvk] Disable VK_EXT_multi_draw on qcom drivers 2025-02-24 22:16:37 +01:00
Philip Rebohle
866228a37d [dxvk] Fix memory type selection for non-device local property flags
Fixes potential memory allocation issues on unified memory setups
that have unique memory types for different resources.
2025-02-24 22:16:37 +01:00
Philip Rebohle
60bf1f9ec4 [dxvk] Enable tiler mode on proprietary drivers as well
Not like it really hurts anyone.
2025-02-24 16:32:32 +01:00
Philip Rebohle
95e12decf1 [dxbc] Remove spammy debug logging 2025-02-24 15:40:52 +01:00
Philip Rebohle
e3f047a96a [d3d11] Remove d3d11.dcSingleUseMode option 2025-02-24 15:34:30 +01:00
Philip Rebohle
7208d06548 [dxvk] Clean up indirect draw unrolling
Also don't report explicit multidraw as merged draws, to be more
consistent with reporting in games that also use IndirectCount.
2025-02-23 18:58:19 +01:00
Philip Rebohle
fc3cf3e822 [d3d11] Properly initialize minUav counter
And also use it when resetting UAV bindings. Fixes a small oversight
that didn't affect correctness.
2025-02-23 13:34:11 +01:00
Philip Rebohle
c69dbc4490 [dxvk] Move draw and dispatch stat counters back to the context
Otherwise we'll count the HUD by accident. Only keep the barrier counter
since there are so many different places where we issue pipeline barriers,
and they are interesting anyway.
2025-02-23 13:24:28 +01:00
Philip Rebohle
a0ea29a2fa [hud] Display number of merged draws, if any 2025-02-23 13:24:28 +01:00
Philip Rebohle
9b37ba679a [dxvk] Add stat counter for merged draws 2025-02-23 13:24:28 +01:00
Philip Rebohle
016f05a770 [dxvk] Implement draw batching via VK_EXT_multi_draw 2025-02-23 13:24:28 +01:00
Philip Rebohle
7e503fa053 [dxvk] Enable VK_EXT_multi_draw if supported 2025-02-23 13:24:28 +01:00
Philip Rebohle
7815b6942d [d3d11] Implement direct draw batching
Not super useful without backend support though.
2025-02-23 13:24:28 +01:00
Philip Rebohle
fc3d3ae331 [dxvk,d3d11] Refactor CS command data allocation
Allows us to allocate a (potentially growing) array of
arbitrary data structures for a CS command.
2025-02-23 13:24:28 +01:00
Philip Rebohle
20dc389ab7 [d3d11] Skip unnecessary iterations when binding graphics UAVs
Some games will unconditionally use a high index for UAVStartSlot.
2025-02-23 12:06:51 +01:00
Philip Rebohle
9f9d51d52c [d3d11] Lazy-bind pixel shader UAVs
Moderately cursed because PS UAVs are also available to other graphics
stages.
2025-02-23 12:06:51 +01:00
Philip Rebohle
9389456d20 [d3d11] Lazy-bind compute shader UAVs
And factor UAV counter updates out of binding.
2025-02-23 12:06:51 +01:00
Philip Rebohle
69171873fa [d3d11] Add compile-time debug flag for lazy binding 2025-02-23 12:06:51 +01:00
Philip Rebohle
c0983a32be [d3d11] Reset dirty bindings on command submission 2025-02-23 12:06:51 +01:00
Philip Rebohle
3e6dfcfb15 [d3d11] Reset dirty tracking when re-applying context state 2025-02-23 12:06:51 +01:00
Philip Rebohle
9d890c75ac [d3d11] Don't template methods that restore shader bindings
This was only needed because Bind* methods were also templated.
2025-02-23 12:06:51 +01:00
Philip Rebohle
771f14c466 [d3d11] Refactor BindUnorderedAccessView
We won't do lazy bindings for UAVs, but at least bring this function
in line with the rest of the binding functions.
2025-02-23 12:06:51 +01:00
Philip Rebohle
b0d881046f [d3d11] Lazy-bind samplers 2025-02-23 12:06:51 +01:00
Philip Rebohle
f2ab76c8db [d3d11] Lazy-bind shader resources 2025-02-23 12:06:51 +01:00
Philip Rebohle
4fdbfffdcc [d3d11] Lazy-bind constant buffers 2025-02-23 12:06:51 +01:00
Philip Rebohle
a61c114519 [d3d11] Change AllowFlush behaviour
No functional change, just makes it less annoying to use in methods that
can be called from both immediate and deferred contexts-
2025-02-23 12:06:51 +01:00
Philip Rebohle
41ec7b6a02 [d3d11] Track shader stages with dirty bindings as well as used bindings 2025-02-23 12:06:51 +01:00
Philip Rebohle
be61341178 [d3d11] Rework DXBC shader stage to Vulkan shader stage mapping
We're going to have to do this at runtime, so this needs to be fast.
2025-02-23 12:06:51 +01:00
Philip Rebohle
6080e6d24d [d3d11] Store used binding mask inside shader objects 2025-02-23 12:06:51 +01:00
Philip Rebohle
75599780f2 [dxbc] Gather binding info during shader compilation 2025-02-23 12:06:51 +01:00
Philip Rebohle
5f16faaae0 [util] Generalize bit mask iterator 2025-02-23 12:06:51 +01:00
Robin Kertels
94b48c1633 [d3d9] Slightly clean up sampler slot handling 2025-02-21 13:25:23 +01:00
Robin Kertels
f7d56886c5 [d3d9] Fix sampler slot correction not respecting dmap texture 2025-02-21 13:25:23 +01:00
Philip Rebohle
0691a7fc46 [dxvk] De-duplicate drawIndirectCount implementations
No functional change, just some code cleanup.
2025-02-20 13:30:31 +01:00
Philip Rebohle
a135e01f89 [dxvk] Unroll merged indirect draws as necessary 2025-02-20 13:30:31 +01:00
Philip Rebohle
1d8fb818fc [dxvk] Check whether pipeline has potentially hazardous stores 2025-02-20 13:30:31 +01:00
Philip Rebohle
6f7a468174 [dxvk] Fix global render pass barrier
Only need to deal with common write-after-read scenarios, we can
ignore writes since those will add extra barriers anyway. Also
move this work out of the somewhat hot pipeline bind function.
2025-02-20 13:30:31 +01:00
Philip Rebohle
dd1ca4ce59 [dxvk] Track order-invariant access ops in barrier tracker
This elides barriers between draws or dispatches if we can prove
order-invariance through atomic operations.
2025-02-20 13:30:31 +01:00
Philip Rebohle
c475960754 [dxvk] Pass store op around for barrier tracking 2025-02-20 13:30:31 +01:00
Philip Rebohle
e01a6eec3e [dxbc] Track bindings with order-invariant atomic stores 2025-02-20 13:30:31 +01:00
Philip Rebohle
d94e3633dc [dxvk] Introduce concept of order-invariant atomic stores 2025-02-20 13:30:31 +01:00
Philip Rebohle
8c7da07085 [util] Fix enum declaration 2025-02-20 13:30:31 +01:00
WinterSnowfall
22052106d8 [d3d9] Relax logging level on validateGammaRamp 2025-02-20 00:01:10 +01:00
WinterSnowfall
3716d48c89 [d3d8/9] Use numeric_limits globally 2025-02-20 00:01:10 +01:00
WinterSnowfall
317607e192 [d3d8/9] Prevent device child ref underruns on release 2025-02-20 00:01:10 +01:00
Philip Rebohle
19361c962c [dxvk] Add debug region for barrier control 2025-02-19 19:34:52 +01:00
Philip Rebohle
636669e1a5 [dxvk] Improve handling of nested debug regions 2025-02-19 19:34:52 +01:00
Philip Rebohle
b03d457ffb [dxvk,d3d11] Improve explicit UAV overlap behaviour
If the app explicitly enables UAV overlap, don't synchronize
back-to-back read-modify-write operations to the same UAV either.
2025-02-19 19:34:52 +01:00
Philip Rebohle
a2c9c0f740 [d3d11] Use resource cookies for draw buffer tracking
Avoids keeping draw buffers alive when the app stops using indirect
draws. Unlikely to have caused issues in practice, but draw buffers
are not part of the API state to begin with.
2025-02-19 19:34:52 +01:00
Philip Rebohle
07f7ccdc96 [dxvk,d3d11] Fix draw buffer tracking for DrawAuto
Not like anybody uses this feature, but we need to both check for
hazards and make sure the SO counter actually gets tracked. Use
the existing draw buffer mechanism for this.
2025-02-19 19:34:52 +01:00
Philip Rebohle
d37a13847a [dxvk] Rename and repurpose ignoreGraphicsBarriers option
Less nuclear approach that hopefully works just as well in practice.
2025-02-19 19:34:52 +01:00
Philip Rebohle
18e5c12b6d [dxvk] Fix resource hazard checks
Turns out we've had broken write-after-read checks for a while.
2025-02-19 19:34:52 +01:00
Philip Rebohle
48d145fff6 [dxvk] Change debug color for pipelines with side effects 2025-02-19 19:34:52 +01:00
Philip Rebohle
04d2609a91 [dxvk] Clean up shader resource hazard checking 2025-02-19 19:34:52 +01:00
Philip Rebohle
3bbae86ec9 [dxvk] Rework compute barrier tracking 2025-02-19 19:34:52 +01:00
Philip Rebohle
53b076be61 [dxvk] Rework graphics barrier tracking
Avoids having to insert redundant barriers when the app does UAV rendering.
2025-02-19 19:34:52 +01:00
Philip Rebohle
009f8ee356 [dxvk] Emit barriers when updating shader resources 2025-02-19 19:34:52 +01:00
Philip Rebohle
be9391ded5 [dxvk] Track transform feedback buffer access 2025-02-19 19:34:52 +01:00
Philip Rebohle
96337f11d4 [dxvk] Track vertex buffer access 2025-02-19 19:34:52 +01:00
Philip Rebohle
24b58e5858 [dxvk] Track index buffer access 2025-02-19 19:34:52 +01:00
Philip Rebohle
21eb682b39 [dxvk] Track indirect draw buffer access 2025-02-19 19:34:52 +01:00
Philip Rebohle
a7c1e7a2a0 [dxvk] Add resource flag to track graphics pipeline side effects 2025-02-19 19:34:52 +01:00
Philip Rebohle
978d7cb65b [dxvk] Add more convenience methods to track buffer barriers 2025-02-19 19:34:52 +01:00
Philip Rebohle
23067c48c7 [dxvk] Clean up CS chunk allocation
This also makes it more robust w.r.t. alignment.
2025-02-18 15:37:11 +01:00
Philip Rebohle
4c8ee300b5 [util] Add more optimal popcnt implementation 2025-02-18 15:28:41 +01:00
Robin Kertels
4282829f38 [d3d9] Route operations on unmappable memory through allocator
Fixes an extremely race condition that can happen when freeing a chunk.
2025-02-17 19:23:15 +01:00
WinterSnowfall
92523fc0dd [d3d9] Fix x64 crash on SetVertexShaderConstantF index overflow 2025-02-17 15:11:05 +01:00
WinterSnowfall
4a89b75bb7 [d3d8] Fix x64 crash on shader validation 2025-02-17 15:11:05 +01:00
WinterSnowfall
274c590ad6 [d3d9] Set priority only for D3DPOOL_MANAGED/DEFAULT resources 2025-02-17 15:11:05 +01:00
WinterSnowfall
84b2ac3f97 [d3d8] Set priority only for D3DPOOL_MANAGED resources 2025-02-17 15:11:05 +01:00
WinterSnowfall
8efa3ed84a [d3d8] A few minor formatting adjustments 2025-02-17 15:11:05 +01:00
Robin Kertels
3269f92138 [d3d9] Fix mismatching texture type mask updates 2025-02-17 14:32:34 +01:00
Jeff
0aebedae16 [d3d8] Add shadow perspective divide hack for Splinter Cell 2025-02-17 14:10:54 +01:00
Philip Rebohle
f2802dd2ff [dxvk] Fix some potential image layout bugs 2025-02-17 01:26:03 +01:00
Philip Rebohle
9389a0ca96 [dxvk] Don't transition image layout in clearImageViewCs unless necessary 2025-02-17 01:26:03 +01:00
Philip Rebohle
6d9e0baa27 [dxvk] Don't hold queue lock when invoking periodic memory tasks 2025-02-14 14:34:33 +01:00
Philip Rebohle
9573c389de [dxvk] Don't create GPL pipeline if we need to patch the vertex shader
Works around a game bug in Kingdom Come Deliverance and silences a validation
error.
2025-02-13 18:46:49 +01:00
Philip Rebohle
3453732bba [dxvk] Fix clear optimization edge case with multi-planar images 2025-02-12 21:42:27 +01:00
Philip Rebohle
0a84dbb787 [dxvk] Implement resolves with a render target clear if possible
Same idea as for copies, if the last use of the source image was a clear
then we can simply clear the destination image instead of performing a
much more expensive resolve operation.
2025-02-12 21:42:27 +01:00
Philip Rebohle
f5a5ec7c88 [dxvk] Factor out method to find pending deferred clears 2025-02-12 21:42:27 +01:00
Philip Rebohle
1cabbee2bb [dxvk] Rework render pass resolves
In an attempt to also support batching layered resolves.
2025-02-12 21:42:27 +01:00
Philip Rebohle
563129c863 [dxvk] Fix potential resolve attachment invalidation bug 2025-02-12 14:44:54 +01:00
Philip Rebohle
c5a3aa73a0 [util] Enable dummy composition swap chain for an upcoming game 2025-02-12 01:36:10 +01:00
Philip Rebohle
80bfd2ed97 [util] Add functionality to support hashed app profiles 2025-02-12 01:34:40 +01:00
Philip Rebohle
813ae020b6 [d3d11] Flush more around non-multisampled render passes 2025-02-11 16:14:53 +01:00
Philip Rebohle
7e3c6f819a [util] Add new flush type for render pass boundaries 2025-02-11 16:14:53 +01:00
Philip Rebohle
94b5cfc3d8 [dxvk] Don't use secondary command buffers for certain render passes
If we can't use any store/resolve op optimizations on a render pass, there
is no reason to pay for the overhead of secondary command buffers.
2025-02-11 16:14:53 +01:00
Philip Rebohle
beaf6dd2a6 [dxvk] Add context flag for active secondary command buffers
Makes some checks more explicit.
2025-02-11 16:14:53 +01:00
Philip Rebohle
cf9ccf711b [dxvk] Add perf hint to avoid secondary command buffers 2025-02-11 16:14:53 +01:00
Philip Rebohle
94254f556e [dxvk] Fix stencil resolve mode 2025-02-11 15:26:08 +01:00
Philip Rebohle
70492b2954 [dxvk] Avoid locking built-in latency tracker when calling into presenter
Same reason as for the Reflex one.
2025-02-11 15:12:13 +01:00
Philip Rebohle
b1174a1bdf [dxvk] Avoid locking Reflex latency tracker when calling into presenter
There are complex deadlock conditions during swap chain destruction.
2025-02-11 15:12:13 +01:00
Philip Rebohle
efeb15edbd [dxvk] Fix lack of forward progress guarantee in presenter
Turns out that relying on two threads to unblock another was a bad idea.
Fixes a potential deadlock w.r.t. swapchain recreation with Reflex.
2025-02-11 15:12:13 +01:00
Philip Rebohle
ac17d5f9b1 [dxvk] Enable tiler mode for more drivers 2025-02-10 18:36:01 +01:00
Philip Rebohle
11ec65d516 [include] Update Vulkan headers 2025-02-10 17:44:36 +01:00
Neal Gompa
4d3b35ae53 meson: Fix version construct by dropping the "v" prefix
The "v" prefix was causing the version to be incorrectly set for
generated files (such as pc files for pkg-config).

Dropping the prefix fixes the issue.
2025-02-10 16:38:03 +01:00
Philip Rebohle
3aeedb9c98 [d3d11] Forward DiscardResource calls to backend for images 2025-02-10 16:13:31 +01:00
Philip Rebohle
9b5499caf2 [dxvk] Ignore deferred discards that we can't fold into load ops 2025-02-10 16:13:31 +01:00
Philip Rebohle
fcabffc1e5 [dxvk] Add store op optimization for image discards in tiler mode 2025-02-10 16:13:31 +01:00
Philip Rebohle
821386aeff [dxvk] Add config option to toggle tiler optimizations 2025-02-10 16:13:31 +01:00
Philip Rebohle
fa2d791d79 [dxvk] Use resolve attachments if possible 2025-02-10 16:13:31 +01:00
Philip Rebohle
80fb7e2294 [d3d9,d3d11] Adjust flush heuristic on tiling GPUs
Probably needs work, just disable most of the heuristic for the time being.
2025-02-10 16:13:31 +01:00
Philip Rebohle
00299b264b [dxvk] Use secondary command buffers for rendering on tiling GPUs 2025-02-10 16:13:31 +01:00
Philip Rebohle
4a92b92f58 [dxvk] Add perf hint for tiling GPUs 2025-02-10 16:13:31 +01:00
Philip Rebohle
6c1bc35264 [dxvk] Add functionality to use secondary command buffers 2025-02-10 16:13:31 +01:00
Philip Rebohle
7d35afdc37 [dxvk] Add functionality to allocate secondary command buffer 2025-02-10 16:13:31 +01:00
Philip Rebohle
f615594f22 [dxgi] Create dummy window for composition swap chains
Obviously not a valid implementation, but allows composition swap chains
to exist with some basic functionality.
2025-02-10 14:23:12 +01:00
Philip Rebohle
76f9bec7cc [dxgi] Add option to expose composition swapchains 2025-02-10 14:14:38 +01:00
WinterSnowfall
0a19e5b6db [d3d8] Store the value of D3DRS_ZVISIBLE 2025-02-10 11:25:40 +01:00
WinterSnowfall
946419cda2 [d3d8] Fix invalid casting in GetRenderState 2025-02-10 11:25:40 +01:00
WinterSnowfall
13554f18bd [d3d9] Update software cursor position using SetCursorPosition 2025-02-08 22:28:48 +01:00
Blisto91
54a26dde3d [util] Disable dcSingleUseMode for Cardfight!! Vanguard Dear Days 2 2025-02-07 19:53:45 +01:00
Philip Rebohle
357484bd4b [d3d11] Don't call Flush from swap chain code
Use internal function instead.
2025-02-06 23:26:05 +01:00
Philip Rebohle
9664e0b850 [dxvk] Fix potential race conditions w.r.t. swapchain destruction
The signaling thread can queue up a wait while the swapchain is being
destroyed, which blows up. This also fixes a related race condition
where we would queue up a wait using the wrong present mode.

This is somewhat fragile in the sense that the queue worker *must* call
signalFrame for each and every present, or this will fall apart.
2025-02-06 20:25:32 +01:00
Philip Rebohle
e5a81f8c7e [dxvk] Don't probe buffer compatibility on image-only memory types
Silences a validation error.
2025-02-06 15:29:24 +01:00
Philip Rebohle
215cebc019 [dxvk] Remove superfluous function declaration 2025-02-06 14:29:19 +01:00
Philip Rebohle
a413eb0843 [dxvk] Only end render pass in invalidateImage if currently bound
Not really needed otherwise.
2025-02-05 22:49:25 +01:00
Philip Rebohle
0434b23167 [dxvk] Fix initializing buffers with non-dword sizes
Fixes #4641. This should be very rare in general though.
2025-02-05 18:36:01 +01:00
Philip Rebohle
cf946eb981 [dxvk] Add setupapi as a Windows WSI dependency 2025-02-02 21:22:19 +01:00
Philip Rebohle
3a34dae722 [dxvk] Work around locale-dependent regex parsing crash 2025-02-02 21:21:58 +01:00
WinterSnowfall
bd69d1efdc [d3d8/9] Use shader version macros where applicable 2025-02-02 18:17:10 +01:00
WinterSnowfall
e3f1d4c021 [d3d8] Fix up swizzle for all opcodes requiring a replicate swizzle 2025-02-02 18:17:10 +01:00
Philip Rebohle
5569274a97 [d3d9] Do not assume 16-byte alignment in replaceNaN
Stack alignment is 4 bytes on 32-bit, and we cannot align variables
on the stack, so this is technically broken.
2025-02-02 10:50:33 +01:00
WinterSnowfall
dd5b28e557 [d3d8] Use D3D8 compatibilty mode to set HUD API level 2025-02-02 10:47:32 +01:00
HunterCZ122
8860bde34b [util] Fix black screen after alt-tab for Trainz 2025-01-31 22:47:37 +01:00
Blisto91
8776cf2ce6 [util] Cleanup some deviceLossOnFocusLoss configs
These game work fine out of the box now
missed
2025-01-30 18:22:18 +01:00
Autumn Ashton
0cad97d5ec [util] Add scaleDref to SplinterCell2 2025-01-30 02:58:15 +00:00
Jeff
06bdc88eb6 [d3d8] Restore config for Splinter Cell 2025-01-30 01:59:22 +00:00
WinterSnowfall
1d90772eb2 [d3d9] Report vertex texture filtering support only for SM3 2025-01-27 18:53:10 +01:00
VPInventions
3d35925a05 Assign viewInfo.minLayer for D3D11VideoProcessorInputView 2025-01-27 18:48:46 +01:00
WinterSnowfall
5b21286377 [d3d9] Adjust SM2 VS/PS caps 2025-01-26 21:52:18 +01:00
WinterSnowfall
ad0920fe1e [d3d9] Relax SM2 minor version checks on shader creation 2025-01-26 20:02:45 +01:00
WinterSnowfall
c6dc7e0939 [d3d8/9] Proper (and age accurate) handling of d3d9.shaderModel = 0 2025-01-26 13:56:27 +01:00
WinterSnowfall
48d24893d4 [d3d8] Clean up and document D3D8-specific caps 2025-01-26 13:50:41 +01:00
WinterSnowfall
753c11d144 [d3d8] Implement SCRATCH pool copies with CopyRects 2025-01-26 13:50:41 +01:00
WinterSnowfall
7482e45534 [d3d8] Remove several empty explicit destructors 2025-01-26 13:50:41 +01:00
WinterSnowfall
e757170211 [d3d8] Remove superfluous methods from D3D8Surface 2025-01-26 13:50:41 +01:00
WinterSnowfall
e2a078d534 [d3d8] Properly return the value of D3DRS_SOFTWAREVERTEXPROCESSING 2025-01-26 13:50:41 +01:00
WinterSnowfall
d846e89a4b [d3d8] Improve handling of FullScreen_PresentationInterval 2025-01-26 13:50:41 +01:00
WinterSnowfall
e40f03b96a [d3d8] General TODO and comment cleanup 2025-01-26 13:50:41 +01:00
WinterSnowfall
088915e24c [d3d8] Don't forward D3DRS_ZVISIBLE changes to d3d9 2025-01-26 13:50:41 +01:00
WinterSnowfall
470764e24c [d3d8] Don't forward D3DRS_PATCHSEGMENTS changes to d3d9 2025-01-26 13:50:41 +01:00
WinterSnowfall
0983ab1f39 [d3d8] Don't forward D3DRS_LINEPATTERN changes to d3d9 2025-01-26 13:50:41 +01:00
WinterSnowfall
20b047600f [d3d8] Disable z-buffer discarding for depth stencil surfaces 2025-01-26 13:50:41 +01:00
WinterSnowfall
b61ea1db76 [d3d8] Address the MultiSampleQuality usage 2025-01-26 13:50:41 +01:00
WinterSnowfall
4184452f49 [d3d8] Validate srcRect/destPoint dimensions in UpdateTextureFromBuffer 2025-01-26 13:50:41 +01:00
Philip Rebohle
736ee20eb5 [d3d11] Implement ID3DLowLatencyDevice 2025-01-25 18:02:20 +01:00
Philip Rebohle
4f9b106d40 [d3d11] Stub out ID3DLowLatencyDevice for D3D11 2025-01-25 18:02:20 +01:00
Philip Rebohle
86c317fbbc [d3d11] Add ID3DLowLatencyDevice definitions 2025-01-25 18:02:20 +01:00
Philip Rebohle
59e53c1863 [d3d11] Add queue parameter to CS chunk injection 2025-01-25 18:02:20 +01:00
Philip Rebohle
539da5abdf [dxvk] Refactor CS chunk queues
Introduces two queues and allows us to dispatch chunks to the ordered
queue without disrupting the sequence number.
2025-01-25 18:02:20 +01:00
Philip Rebohle
0e9efa5183 [dxvk] Implement Reflex latency tracker 2025-01-25 18:02:20 +01:00
Philip Rebohle
4b009237d7 [dxvk] Add NV_low_latency2 path to latency tracker 2025-01-25 18:02:20 +01:00
Philip Rebohle
66dc0a9383 [dxvk] Pass present IDs to command submissions as necessary 2025-01-25 18:02:20 +01:00
Philip Rebohle
4c2990f199 [dxvk] Implement NV_low_latency2 functionality in presenter 2025-01-25 18:02:20 +01:00
Philip Rebohle
c700d76477 [dxvk] Add option to disable VK_NV_low_latency2 2025-01-25 18:02:20 +01:00
Philip Rebohle
859117797f [dxvk] Enable VK_NV_low_latency2 if supported 2025-01-25 18:02:20 +01:00
Philip Rebohle
4fcbf52752 [d3d9] Always limit to display refresh in low latency mode 2025-01-25 18:02:20 +01:00
Philip Rebohle
0e3ed707ba [d3d9] Implement latency tracking 2025-01-25 18:02:20 +01:00
Philip Rebohle
50375ee1ee [dxgi] Pass display refresh in windowed mode if latency sleep is enabled 2025-01-25 18:02:20 +01:00
Philip Rebohle
21f69eceaa [d3d11] Implement latency tracking 2025-01-25 18:02:20 +01:00
Philip Rebohle
23f08eaedd [hud] Add frame latency item 2025-01-25 18:02:20 +01:00
Philip Rebohle
2ee598b4af [dxvk] Add latency tracker to context 2025-01-25 18:02:20 +01:00
Philip Rebohle
95b8dc59fb [dxvk] Add latency tracker to presenter 2025-01-25 18:02:20 +01:00
Philip Rebohle
273e4abb14 [dxvk] Add latency tracker to queue submissions 2025-01-25 18:02:20 +01:00
Philip Rebohle
552470de63 [dxvk] Add latency tracker
Implements a basic latency sleep solution that is intended to work
without requiring games to support any related vendor features.

This alone is not enough to expose the Reflex API to applications via
dxvk-nvapi, but since that relies on NV_low_latency2 specifics anyway,
we are going to add an implementation based on that extension later
with an extended interface.
2025-01-25 18:02:20 +01:00
Philip Rebohle
55639889c7 [util] Expose frame rate environment variable
We'll need this in more places.
2025-01-25 18:02:20 +01:00
Philip Rebohle
53e5c4875f [util] Add parameter to initialize small_vector with a given size
Matches std::vector.
2025-01-25 18:02:20 +01:00
Blisto91
b73f9d8ecb [util] Extend Battlefield 2/2142 config to Project Reality 2025-01-22 19:56:41 +01:00
Vasiliy Stelmachenok
84ccad3528 [build] Use -mpreferred-stack-boundary=2 on 32-bit x86
Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
2025-01-21 21:17:28 +01:00
Blisto91
a3ba8fb4dc [util] Add configs for Star Wars Empire at War
In both the base game and expansion the Water and Shader Detail options are locked at their lowest value when they see Intel.
In the base game (not expansion) the AA option disappears for some reason whenit sees vram at 2075MB and above.
2025-01-20 23:01:25 +01:00
Vasiliy Stelmachenok
685126482d [d3d11] Fix missing argument reference
Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
2025-01-20 22:59:54 +01:00
Philip Rebohle
863591275c [dxvk] Error out on surface creation again
Unless it's NATIVE_WINDOW_IN_USE. Should fix a regression where
D3D swapchain creation would succeed on out-of-memory errors.
2025-01-20 18:20:14 +01:00
Philip Rebohle
c52a68a5be [dxvk] Fix typo that breaks HDR metadata 2025-01-16 17:47:56 +01:00
Philip Rebohle
5ed2d990af [d3d9] Fix software cursor texture format
The new code expects texture reads to be in linear space, so we need
to use an sRGB format here.
2025-01-16 12:05:17 +01:00
Philip Rebohle
3dbe8ad43c [d3d9] Rework device reset detection
More robust.
2025-01-16 11:38:39 +01:00
Philip Rebohle
f9c3dd1f5f [d3d9] Remove explicit swapchain synchronization
No longer necessary.
2025-01-16 11:38:39 +01:00
Philip Rebohle
c43cf6895b [d3d9] Refactor presenter management
There's basically no reason to ever recreate a presenter for an already
managed window with the new code.
2025-01-16 11:38:39 +01:00
Philip Rebohle
785649f3b8 [d3d11] Remove explicit swapchain synchronization 2025-01-16 11:38:39 +01:00
Philip Rebohle
42adc4ac11 [dxvk] Perform acquire and present synchronization in the backend
And add method to explicitly destroy relevant Vulkan objects.
2025-01-16 11:38:39 +01:00
Philip Rebohle
b03ff775ce [dxvk] Do not initialize present status from presentImage
Meaningless, this needs to be done elsewhere anyway.
2025-01-16 11:38:39 +01:00
Philip Rebohle
81c3242b6d [dxvk] Dirty swapchain if present returns SUBOPTIMAL
May fix some issues in case the WSI implementation can return SUBOPTIMAL
from present but not acquire. Also ensure to keep state consistent.
2025-01-16 11:38:39 +01:00
Philip Rebohle
816f8e9c87 [dxvk] Improve swapchain debug logging 2025-01-16 11:38:39 +01:00
Philip Rebohle
0f9245ff33 [d3d9,d3d11] Remove numBackBuffers option
Useless.
2025-01-16 11:38:39 +01:00
Philip Rebohle
cb42ea21be [dxvk] Adjust swapchain format preferences in various cases
For sRGB, using a native sRGB format allows the swapchain blitter
to use a more efficient code path for drawing the HUD.

Also allow RGB9E5 for sRGB and HDR10.
2025-01-16 11:38:39 +01:00
Philip Rebohle
d200184306 [dxvk] Rework swapchain composition
Also adds a separate set of shaders for the software cursor, provided it
can be drawn directly with alpha blending.
2025-01-16 11:38:39 +01:00
Philip Rebohle
a09d372caf [dxvk] Prepare swapchain blitter for compositing HUD and cursor
This will be necessary for non-linear color spaces to get proper blending.
2025-01-16 11:38:39 +01:00
Philip Rebohle
8be30d7d5a [hud] Add method to check whether HUD is empty 2025-01-16 11:38:39 +01:00
Philip Rebohle
5134a4b3c5 [dxvk] Move HUD update and rendering into swapchain blitter 2025-01-16 11:38:39 +01:00
Philip Rebohle
c1ed8cd1f3 [hud] Add function to change API name dynamically
Needed for D3D8 due to implicit swapchain shenanigans.
2025-01-16 11:38:39 +01:00
Philip Rebohle
0eeedf9259 [hud] Allow returning HUD item objects to the caller 2025-01-16 11:38:39 +01:00
Philip Rebohle
d5744e5a81 [dxvk] Enable automatic fallbacks for HDR color spaces
The swap chain blitter can deal with the conversion.
2025-01-16 11:38:39 +01:00
Philip Rebohle
d85d07c0ec [dxvk] Infer swap chain color space from image views 2025-01-16 11:38:39 +01:00
Philip Rebohle
1d790970d5 [d3d9] Set color space for swap chain image 2025-01-16 11:38:39 +01:00
Philip Rebohle
b586294e29 [d3d11] Set color space for swap chain image 2025-01-16 11:38:39 +01:00
Philip Rebohle
ed3c02906c [dxvk] Set color space for swap chain back buffers 2025-01-16 11:38:39 +01:00
Philip Rebohle
84317f913a [dxvk] Don't redundantly update image debug names 2025-01-16 11:38:39 +01:00
Philip Rebohle
ff41a5ab12 [dxvk] Add color space property to image description 2025-01-16 11:38:39 +01:00
Philip Rebohle
ad11509e83 [dxvk] Soften error reporting from the presenter 2025-01-16 11:38:39 +01:00
Philip Rebohle
43838d3df8 [dxvk] Move Vulkan swapchain management to backend
Massive cleanup reduce code duplication between D3D11 and D3D9,
and introduce a sane path to pass data around. Implicit swap
chain recreation is now entirely transparent to the frontends.
2025-01-16 11:38:39 +01:00
Philip Rebohle
06b44c6237 [dxvk] Rework HDR metadata updates 2025-01-16 11:38:39 +01:00
Philip Rebohle
63e88debee [dxvk] Move deferSurfaceCreation handling to backend 2025-01-16 11:38:39 +01:00
Philip Rebohle
ab9646551f [dxvk] Import swap chain images from the back-end 2025-01-16 11:38:39 +01:00
Philip Rebohle
073806df7c [dxvk] Move surface creation to the backend 2025-01-16 11:38:39 +01:00
Philip Rebohle
c707d9026f [meta] Release 2.5.3 2025-01-13 16:20:20 +01:00
Blisto91
3d401690cb [util] Enable Strict floatEmulation for Max Payne 3
Visual issues such as white, black or rainbow colored objects and effect on some driver such as ANV (and amdvlk when set to true)
2025-01-13 16:17:36 +01:00
Philip Rebohle
5f5c9a4cdd [d3d9] Improve logging for PS input register indices 2025-01-13 15:38:25 +01:00
Philip Rebohle
af45295a2f [d3d9] Log instruction stream in validator 2025-01-13 15:38:25 +01:00
Jeff
5b7726cf6f [d3d9] Fix invalid strings returned by GetInstanceExtensions 2025-01-13 11:08:45 +01:00
Philip Rebohle
d5832c3075 [dxbc] Improve code gen for zeroing workgroup memory 2025-01-12 14:10:47 +01:00
Philip Rebohle
f17317061c [dxbc] Bound-check dynamically indexed input registers
Halo MCC reads undefined PS inputs otherwise.
2025-01-12 14:10:47 +01:00
Blisto91
7f4e25267c [util] Enable hideIntegratedGraphics for Bright memory
The game will prefer other vendors over Intel even if the latter is the dGPU in the system. It likely assumes that Intel is always a iGPU.
This also happens with the native game on Windows and so isn't a Linux exclusive. Both in d3d11 and d3d12 mode.
2025-01-11 16:55:00 +01:00
Blisto91
07397305f1 [util] Enable zeroInitWorkgroupMemory for Far Cry 5 and New Dawn 2025-01-11 16:45:06 +01:00
Philip Rebohle
efb9d444c1 [dxvk] Introduce config option to enable FSE on Windows 2025-01-10 14:07:55 +01:00
Philip Rebohle
071dec7148 [hud] Add debug label for HUD rendering 2025-01-09 16:25:46 +01:00
Philip Rebohle
279c6f150a [dxvk] Add debug label for swap chain blitter 2025-01-09 16:25:46 +01:00
Philip Rebohle
50f9630250 [dxvk] Add debug regions for internal operations 2025-01-09 16:25:46 +01:00
Philip Rebohle
485090d039 [dxvk] Add debug region for mip generation 2025-01-09 16:25:46 +01:00
Philip Rebohle
498ecca81d [dxvk] Add debug region for memory defragmentation 2025-01-09 16:25:46 +01:00
Philip Rebohle
9bb06baaaa [dxvk] Add debug labels for pipeline binding 2025-01-09 16:25:46 +01:00
Philip Rebohle
ca2afb0b8b [dxvk] Add debug label for render target clears 2025-01-09 16:25:46 +01:00
Philip Rebohle
1b9ea8c6e3 [dxvk] Add debug regions for render passes 2025-01-09 16:25:46 +01:00
Philip Rebohle
d9b5f09239 [dxvk] Add debug region stack
Ensures that we correctly begin and end app-provided regions within
each command buffer.
2025-01-09 16:25:46 +01:00
Philip Rebohle
71bd780340 [dxvk] Add debug regions to command buffers 2025-01-09 16:25:46 +01:00
Philip Rebohle
b62a8c78b4 [dxvk] Add context feature flag for debug utils support 2025-01-09 16:25:46 +01:00
Philip Rebohle
8c3d7a1979 [d3d11] Support debug names for buffers and textures
Co-authored-by: Aaron Leiby <aleiby@gmail.com>
2025-01-09 16:25:46 +01:00
Philip Rebohle
4970dc3358 [d3d11] Set debug names for internal buffers 2025-01-09 16:25:46 +01:00
Philip Rebohle
1721be4973 [d3d9] Set debug names for internal buffers 2025-01-09 16:25:46 +01:00
Philip Rebohle
d2d46be8da [dxvk] Set debug names for memory allocations
Makes it easier to work out what is allocated where.
2025-01-09 16:25:46 +01:00
Philip Rebohle
3339b165cd [dxvk] Set debug names for internal buffers 2025-01-09 16:25:46 +01:00
Philip Rebohle
3e77893ef7 [dxvk] Set debug names for swap chain blitter resources 2025-01-09 16:25:46 +01:00
Philip Rebohle
098d5adca5 [hud] Set debug names for HUD resources 2025-01-09 16:25:46 +01:00
Philip Rebohle
2507820339 [dxvk] Add support for resource debug names 2025-01-09 16:25:46 +01:00
Philip Rebohle
7f4f927980 [dxvk] Add command buffer parameter to debug label functions 2025-01-09 16:25:46 +01:00
Philip Rebohle
5487f8b9a0 [dxvk] Add convenience methods to check for debug utils support 2025-01-09 16:25:46 +01:00
WinterSnowfall
4151d35e8e [d3d8] Alignment and formatting improvements 2025-01-09 15:50:46 +01:00
WinterSnowfall
639f815432 [d3d8] Refactor D3D8Vertex/IndexBuffer implementation 2025-01-09 15:50:46 +01:00
WinterSnowfall
13ec120289 [d3d8] Refactor D3D8Surface implementation 2025-01-09 15:50:46 +01:00
WinterSnowfall
9d37e4abb4 [d3d8] Refactor D3D8Volume implementation 2025-01-09 15:50:46 +01:00
WinterSnowfall
7bb8819fbc [d3d8] Refactor D3D8Texture2D/3D/Cube implementation 2025-01-09 15:50:46 +01:00
WinterSnowfall
8017607fe7 [d3d8] Refactor D3D8SwapChain implementation 2025-01-09 15:50:46 +01:00
WinterSnowfall
84ad2ea261 [d3d8] Properly initialize state block data 2025-01-09 15:50:46 +01:00
WinterSnowfall
8ead28e481 [d3d8] Unify source file endline delimiters 2025-01-09 15:50:46 +01:00
WinterSnowfall
475bf4e9c1 [d3d9] Use cdw to iterate over register tokens in D3D9ShaderValidator 2025-01-07 17:49:18 +01:00
WinterSnowfall
150cb0d4c7 [d3d9] Refactor the D3D9ShaderValidator implementation 2025-01-06 18:55:37 +01:00
WinterSnowfall
28a08cae6d [d3d8/9] Clear pLockedRect/Box contents universally on lock 2025-01-06 15:52:42 +01:00
Philip Rebohle
9a244e8951 [dxbc] Use NClamp for tess factors and depth clamp
This flushes NaN tess factors to 0, which should match D3D behaviour
for both outer and inner tess factors. The legacy code hasn't been
touched in 7 years.
2025-01-04 17:41:50 +01:00
Robin Kertels
24f98c5835 [d3d9] Skip texture type check when forceSpecConst option is active 2025-01-04 02:11:58 +00:00
esullivan
33498eb512 [spirv] Emit the grad and const offset image ops in the correct order
Currently the grad and const offset image operand ids are emitted in the
incorrect order. This causes incorrect code gen if both the grad and const
offset image operands are used.

This fixes the compilation error found when running TopSpin 2k25 through
DXVK using the NVIDIA proprietary Vulkan driver.
2025-01-03 23:30:56 +01:00
Blisto91
8b9b46dfff [util] Cap fps in The hurricane of the Varstray 2025-01-01 23:42:56 +01:00
Blisto91
7425a33dd7 [util] Merge the Arcana Heart 3 entries 2025-01-01 23:42:56 +01:00
spiffeeroo
39f4d804a2 [util] Limit frame rate to 60 fps for Arcana Heart 3 Love Max!!!!! and Arcana Heart 3 Love Max Six Stars!!!!!! Xtend
[Arcana Heart 3 Love Max!!!!!](https://store.steampowered.com/app/370460) runs too fast when frame rate is above 60 fps (like on high refresh rate monitor). Limit frame rate to 60 fps so game runs at correct speed.

[Arcana Heart 3 Love Max Six Stars!!!!!! Xtend](https://store.steampowered.com/app/661990) also suffers from the game speed being too fast while in windowed mode. Limit frame rate to 60 fps to fix game speed.
2025-01-01 19:46:37 +01:00
Robin Kertels
1eb0c687a6 [d3d9] Fix messing up the dirty textures bitmask 2024-12-20 18:26:02 +01:00
Philip Rebohle
b4faf0bb3e [meta] Release 2.5.2 2024-12-20 13:37:07 +01:00
Robin Kertels
acf93aa70a [util] Remove Alpha Protocol config
The texture type check makes this redundant.
2024-12-17 14:49:52 +01:00
Robin Kertels
65843aa016 [d3d9] Don't bind textures if texture type doesnt match 2024-12-17 14:49:52 +01:00
Tiagoquix
67f4ec73aa [util] Adjust "Earth Defense Force 5" position
Game uses D3D11 according to https://www.pcgamingwiki.com/wiki/Earth_Defense_Force_5#API. Currently it's listed in the D3D9 section.
2024-12-16 23:05:33 +01:00
Philip Rebohle
d1789c4d85 [dxvk] Always consider env var configuration as active
Fixes #4529.
2024-12-15 16:51:32 +01:00
Blisto91
fb8f79e4a7 [util] Add Sims 2 Content Manager & HomeCrafter Plus 2024-12-12 14:02:00 +01:00
Blisto91
0997719a73 [util] Set textureMemory to 0 for Dark Sector
Works around some crashes
2024-12-12 14:01:40 +01:00
Philip Rebohle
5868b067e4 [dxgi] Use VK_FORMAT_A8_UNORM if supported 2024-12-10 01:16:44 +01:00
Philip Rebohle
32399461da [dxvk] Properly encode KHR_maintenance5 formats 2024-12-10 01:16:44 +01:00
WinterSnowfall
4dd0afe121 [d3d9] Validate depth and stencil clears 2024-12-10 01:16:24 +01:00
Jeff
d1abce3be2 [d3d9] Add GetInstanceExtensions to interop API 2024-12-09 18:11:46 +01:00
Philip Rebohle
45da7d6678 [d3d11] Fix rectangle check in ClearView
It is legal to pass a potentially invalid pointer if NumRects is 0.
Fixes validation errors in TopSpin 2k25.
2024-12-09 17:43:53 +01:00
WinterSnowfall
b1ad43145b [d3d8] Add missing include to d3d8_state_block.h 2024-12-05 23:43:23 +01:00
Tiagoquix
a78c1bd6dd [util] Separate Borderlands 2 fixes from Borderlands: The Pre-Sequel 2024-12-05 15:00:19 +01:00
WinterSnowfall
d094053018 [d3d9] Implement several IDirect3DShaderValidator9 validations
Co-Authored-By: Joshua Ashton <joshua@froggi.es>
Co-Authored-By: Paul Gofman <gofmanp@gmail.com>
2024-12-05 14:59:56 +01:00
Autumn Ashton
d956b188ed [d3d9] Clip plane compaction
Compact clip planes to the smallest amount that are enabled.

Signed-off-by: Autumn Ashton <misyl@froggi.es>
2024-12-05 06:08:34 +00:00
Autumn Ashton
8c4c814fb7 [d3d9] Spec-constant out writes to clip distances when disabled
Add a new spec constant with a mask of the enabled clip planes such that they can be optimized out to improve performance.

For GPL shaders, override what we return here so it's always true and don't bother putting the mask in the UBO.

Signed-off-by: Autumn Ashton <misyl@froggi.es>
2024-12-05 06:08:34 +00:00
WinterSnowfall
027fe5963a [d3d9] Fixes for state block specific behavior 2024-12-04 13:06:28 +01:00
WinterSnowfall
17b85accfb [d3d9] Adjust device reset failure error codes 2024-12-04 13:06:28 +01:00
WinterSnowfall
f23c74949a [d3d9] Validate supported formats in D3D9Surface::GetDC 2024-12-04 13:06:28 +01:00
WinterSnowfall
fb56668dc0 [d3d9] Adjust out of bounds clip plane index handling 2024-12-04 13:06:28 +01:00
WinterSnowfall
9c012c8e75 [d3d9] Skip recording MultiplyTransform calls in state blocks 2024-12-04 13:06:28 +01:00
WinterSnowfall
640a266158 [d3d9] Only advertise SRCCOLOR2 & INVSRCCOLOR2 with 9Ex 2024-12-04 13:06:28 +01:00
WinterSnowfall
93d2715b7a [build] Suppress gcc misleading indentation warnings 2024-12-04 10:00:15 +01:00
WinterSnowfall
218b67dd0c [d3d9] Use header back buffer limits during validation
Co-authored-by: Blisto91 <47954800+Blisto91@users.noreply.github.com>
2024-11-28 15:44:00 +01:00
Jeff
4e07302cbf [d3d9] Fix race condition in PIX events 2024-11-28 07:24:12 +00:00
WinterSnowfall
b8ce414820 [util] Enable deferSurfaceCreation for the Codename Panzer series 2024-11-27 16:51:54 +01:00
Philip Rebohle
d7bd3cd58e [d3d9] Remove d3d9.enableDialogMode option 2024-11-25 11:54:55 +01:00
Philip Rebohle
15db475edf [dxvk] Always disable exclusive fullscreen 2024-11-25 11:54:55 +01:00
WinterSnowfall
9e1bc1db23 [d3d9] Expand NormalizeTextureProperties validations 2024-11-23 16:58:25 +01:00
WinterSnowfall
97ad37e409 [d3d9] Validate RT parent device during SetRenderTarget 2024-11-23 16:58:25 +01:00
WinterSnowfall
77020760f1 [d3d9] Fix behavior on multiple image unlocks 2024-11-23 16:58:25 +01:00
WinterSnowfall
bb227fa850 [d3d8] Partially implement ValidateVertexShader/ValidatePixelShader 2024-11-23 16:58:25 +01:00
WinterSnowfall
34165f3814 [d3d8] Validate PS/VS version on creation 2024-11-23 16:58:25 +01:00
WinterSnowfall
423c86bf5e [d3d8] Validate DS dimensions on SetRenderTarget 2024-11-23 16:58:25 +01:00
WinterSnowfall
dd183b4a53 [d3d8] Adjust function, declaration and delete behavior for VS/PS 2024-11-23 16:58:25 +01:00
WinterSnowfall
4f98844f47 [d3d9] Skip some validations for D3DDEVTYPE_NULLREF devices 2024-11-23 16:58:25 +01:00
Blisto91
43b79bcb23 [util] Set Borderlands 2 floatEmulation to Strict
Missing lava in Vault of the Warrior
2024-11-23 02:28:03 +01:00
Blisto91
dd15328ccf [build] Remove old d3dcompiler_47 dependency
Leftover from when tests were in the main repository
2024-11-19 10:50:09 +01:00
Blisto91
7f1e52703d [d3d9] Change correctness factor to 0.5f
The original issue that 0.5f - (1.0f / 128.0f) fixed is a game bug that also happens on Windows and the version of the addon used back then didn't fix correctly. With the latest version of the addon it looks correct.
2024-11-18 13:03:58 +01:00
Philip Rebohle
b276c60f49 [meta] Release 2.5.1 2024-11-18 12:32:41 +01:00
Philip Rebohle
7ffd6dae2c [meta] Document dxgi.enableUe4Workarounds option 2024-11-18 12:32:41 +01:00
Blisto91
987c132df2 [util] Don't include original WC3 in Reforged config
Reforged sits in a folder called x86_64 which should filter out the original Warcraft 3
2024-11-17 20:02:04 +01:00
Blisto91
fefa4ee1f6 [util] Hide iGPU for WoW and WC3 Reforged
Currently with Proton/Wine these games will prefer to use the iGPU. On systems usng the Nvidia proprietary driver this can make them bug out so they don't start or show a gray screen.

It has to be figured and fixed why they even want to use the iGPU, but in the meantime we might as well work around the issue.
2024-11-17 16:12:17 +01:00
WinterSnowfall
ce1b06d0c6 [d3d8] Use unsigned values to identify remapped sampler states 2024-11-16 17:56:57 +01:00
Philip Rebohle
482e758aee [dxgi] Introduce dxgi.enableUe4Workarounds option 2024-11-16 17:26:33 +01:00
Philip Rebohle
1dcc9f3b6a [dxvk] Fix struct <-> class warning 2024-11-16 16:58:17 +01:00
Philip Rebohle
4fb6403b8f [d3d11] Store map mode as raw integer
Fixes some annoying error with clang, hopefully.
2024-11-16 16:58:17 +01:00
60IQ
12c2b2f81b add --64-only and --32-only build options from package-native.sh 2024-11-15 21:14:51 +01:00
Philip Rebohle
4c09b006a5 [d3d9] Actually use correct sampler state for anisotropy 2024-11-13 14:35:59 +01:00
Blisto91
2dadad57f0 [util] Hide amd for GTA The Definitive Edition trilogy
Crashes because of static ags on amd systems which report HDR support.
2024-11-13 12:17:43 +01:00
Randy Eckenrode
8dc1fe1262 [build] Fix native GLFW build
Fixes an undefined reference to `glfwGetWindowAttrib` when building with
GLFW support enabled.
2024-11-11 22:33:52 +01:00
Philip Rebohle
e6209d28cd [build] Fix project version for native builds
Derp, wasn't tested.
2024-11-11 19:59:39 +01:00
Philip Rebohle
56b7c8cd41 [meta] Release 2.5 2024-11-11 15:27:07 +01:00
Philip Rebohle
757081a55a [hud] Pre-multiply alpha before color space conversion
Derp.
2024-11-11 12:53:52 +01:00
Philip Rebohle
3756e83ae4 [dxso] Don't emit FOrdNotEqual 2024-11-11 12:33:40 +01:00
Philip Rebohle
6610f4237f [dxso] Remove OpCross path for cross products 2024-11-11 12:33:40 +01:00
Philip Rebohle
bca3e8db5a [dxso] Explicitly emit long dot products
Potentially avoids vertex shader bugs if a game expects dot product and
a chain of mad instructions to return the same result.
2024-11-11 12:33:40 +01:00
Philip Rebohle
a71603a2a4 [dxso] Fix lrp instruction
Games expect this to be equivalent to add -> mad, but since we changed
mad to emit mul + add, this is no longer the case. Also remove OpFMix
path.
2024-11-11 12:33:40 +01:00
Philip Rebohle
f05b104310 [dxvk] Disable defragmentation on ANV 2024-11-11 12:33:20 +01:00
Philip Rebohle
d9d99445bd [hud] Properly pre-multiply graphs and bars with alpha
Oversight, our blend mode relies on pre-multiplied alpha.
2024-11-11 12:01:31 +01:00
WinterSnowfall
664783b290 [build] Use the static version of the run-time library for MSVC builds 2024-11-10 23:11:59 +01:00
Philip Rebohle
125f0acefd [util] Hide integrated graphics for Diablo 4 2024-11-10 21:39:07 +01:00
WinterSnowfall
d13375f4ed [CI] Use latest action runner images 2024-11-10 20:59:43 +01:00
Blisto91
847a581288 [CI] Add fetch-depth: 0 to Windows CI
Fixes the msvc CI builds not including the git commit in the dxvk version because 'git describe --dirty=+'  called though meson fails.
2024-11-10 20:08:35 +01:00
Philip Rebohle
c745136f67 [dxgi] Fix global variable declarations 2024-11-10 18:18:26 +01:00
Blisto91
8bca36460a [dxvk] Log build target and compiler used 2024-11-10 14:33:14 +01:00
Philip Rebohle
9b272fb3f6 [dxvk] Enable and use VK_EXT_pageable_device_local_memory if supported 2024-11-08 17:25:54 +01:00
Philip Rebohle
c5bc4d1bac [dxvk] Order allocations to relocate by offset
Potentially improves the situation where a chunk cannot be relocated
in its entirely by freeing up a larger block of memory at the end of
the chunk, which may be enough to service a subsequent defrag attempt
of a different chunk.
2024-11-08 13:39:47 +01:00
Philip Rebohle
8584fc7722 [d3d11] Simplify mapped resource tracking on deferred context 2024-11-08 11:19:21 +01:00
Philip Rebohle
bdd4956dd3 [d3d11] Properly validate map parameters for images 2024-11-08 11:19:21 +01:00
Philip Rebohle
2db10b0af8 [d3d11] Use D3D11_COMMON_TEXTURE_MAP_MODE_DYNAMIC where possible 2024-11-08 11:19:21 +01:00
Philip Rebohle
da406133f1 [d3d11] Add D3D11_COMMON_TEXTURE_MAP_MODE_DYNAMIC 2024-11-08 11:19:21 +01:00
Philip Rebohle
1d2d05dde0 [d3d11] Clean up some texture map mode checks 2024-11-08 11:19:21 +01:00
Philip Rebohle
43e636cf42 [dxvk] Rearrange DxvkBufferCreateInfo 2024-11-08 11:19:21 +01:00
Philip Rebohle
bd6b7aedc1 [d3d11] Clean up image staging buffer creation 2024-11-08 11:19:21 +01:00
Philip Rebohle
9e316b8c71 [d3d11] Disallow MAP_WRITE_NO_OVERWRITE on dynamic images
D3D11 explicitly bans this, so we shouldn't pretend to support it.
2024-11-08 11:19:21 +01:00
Philip Rebohle
1dfb869df2 [d3d11] Tie mapped image memory type to map mode selection
Allows us to keep video images in system memory in order to avoid
wasting precious HVV.
2024-11-08 11:19:21 +01:00
Philip Rebohle
ae67c026aa [d3d11] Implement image MAP_WRITE_DISCARD on immediate context 2024-11-08 11:19:21 +01:00
Philip Rebohle
789e8db699 [d3d11] Fix MAP_WRITE_DISCARD for mapped images on deferred contexts
The previous implementation was straight-up broken since it would use the
wrong subresource layout. We can discard the image now so let's just do that.
2024-11-08 11:19:21 +01:00
Philip Rebohle
30f2a8c26b [d3d11] Add methods to discard direct-mapped images 2024-11-08 11:19:21 +01:00
Philip Rebohle
64e32d4ee1 [d3d11] Clean up InitHostVisibleTexture
Also fixes a potential crash if pSysMem of any initial data structs is null.
2024-11-08 11:19:21 +01:00
Philip Rebohle
f5241d187c [d3d11] Use GetMapPtr when initializing mapped image buffer 2024-11-08 11:19:21 +01:00
Philip Rebohle
1832332d6d [d3d11] Add GetMapPtr method to D3D11CommonTexture
Fixes a bug in Read/WriteSubresource where discards result in the wrong
pointer being passed to the app.
2024-11-08 11:19:21 +01:00
Philip Rebohle
81bdf191cb [dxvk] Remove old querySubresourceLayout method 2024-11-08 11:19:21 +01:00
Philip Rebohle
c5d776c3b8 [d3d11] Cache subresource layouts for mapped images
Also adjust the way we expose certain direct-mapped images in order
to be as consistent with staging buffer behaviour as possible.
2024-11-08 11:19:21 +01:00
Philip Rebohle
a5e8a42288 [d3d11] Properly initialize optons struct
No bug, but it's good practice either way.
2024-11-08 11:19:21 +01:00
Philip Rebohle
bdf4cb765a [d3d11] Remove d3d11.maxDynamicImageBufferSize option 2024-11-08 11:19:21 +01:00
Philip Rebohle
116d488faa [d3d11] Use direct mapping for images in more situations 2024-11-08 11:19:21 +01:00
Philip Rebohle
35d94ae057 [d3d11] Improve memory type selection for direct-mapped images 2024-11-08 11:19:21 +01:00
Philip Rebohle
0896df7b9a [dxvk] Add back-end function to compute linear image subresource layouts 2024-11-08 11:19:21 +01:00
Robin Kertels
62970d24c3 [d3d9] Enable strict float emulation by default on new Nvidia drivers 2024-11-07 17:34:45 +01:00
WinterSnowfall
eb98047412 [d3d9] Skip some validations when hDeviceWindow is NULL 2024-11-07 01:10:05 +01:00
Blisto91
c466dec207 [CI] Make MSCV artifacts output match the regular artifact CI
Merges the two separate archives in to one and puts the dll and pdb files in a x32 and x64 folder.
Currently the two archives package the output in a folder called src and the files in subfolders of the respective names. E.g. `src/d3d9/d3d9.dll` etc.

This makes the MSCV artifacts archive match the regular artifacts CI output.
2024-11-04 17:56:16 +01:00
Philip Rebohle
c968ba624b [dxvk] Only force late clears on older Nvidia drivers
Disables the workaround introduced in 00872e9e4f
on drivers that were not affected by the bug.
2024-11-03 17:13:16 +01:00
WinterSnowfall
64b35c5c0f [d3d9] Early return D3D_OK on present with a NULL m_window 2024-11-03 13:35:55 +01:00
Philip Rebohle
3c88591326 [d3d9] Fix various other ColorFill edge cases
Fixes all remaining validation in wine's color_fill_test. Some failed
tests remain because apparently we do not validate resource txpes properly.
2024-11-03 12:41:35 +01:00
Philip Rebohle
ccd19ce90b [d3d9] Properly handle block-compressed formats in ColorFill 2024-11-03 12:41:35 +01:00
Philip Rebohle
c4421348cf [d3d9] Fix image layout for transfer-only images 2024-11-03 12:41:35 +01:00
Philip Rebohle
cde8661bc1 [dxvk] Add helper to compute clear values for compressed formats 2024-11-03 12:41:35 +01:00
Philip Rebohle
778b04f39a [d3d9] Properly destroy format conversion set and pipeline layouts 2024-11-03 12:41:35 +01:00
Philip Rebohle
54c45ef3fa [dxvk] Fix when tracking happens in resource relocation
Invalidation now resets tracking, so it is possible that after recreating
an image with different usage we'd use it on the wrong command buffer for
certain functions.
2024-11-03 12:25:53 +01:00
Philip Rebohle
c764dd97a6 [util] Fix __wine_dbg_output crash with very long lines
This sometimes happens with Vulkan validation layers enabled.
2024-11-03 12:02:03 +01:00
Philip Rebohle
f3c320b490 [dxvk] Fix broken sync in injectCsChunk 2024-11-02 20:56:02 +01:00
WinterSnowfall
b38c6b4dc2 [d3d8] Adjust ValidatePixel/VertexShader error return 2024-11-02 18:07:33 +01:00
WinterSnowfall
27ceecfad9 [d3d9] Fix cursor X/YHotSpot coordinate validation 2024-11-02 18:07:33 +01:00
WinterSnowfall
860d038d77 [d3d8] Don't record calls to MultiplyTransform 2024-11-02 18:07:33 +01:00
WinterSnowfall
88be8256e6 [d3d9] Add additional ValidateBufferProperties validations 2024-11-02 18:07:33 +01:00
WinterSnowfall
931796d1c2 [d3d9] Fix CreateQuery error return code 2024-11-02 18:07:33 +01:00
WinterSnowfall
0c117595b1 [d3d8] Strip all d3d9 device caps 2024-11-02 18:07:33 +01:00
WinterSnowfall
1181efd09d [d3d8] Adjust surface and texture clearing with D3DFMT_UNKNOWN 2024-11-02 18:07:33 +01:00
WinterSnowfall
a760f4a8dc [d3d9] Fixed return code on CheckAdapterFormat with D3DFMT_UNKNOWN 2024-11-02 18:07:33 +01:00
WinterSnowfall
a7c2eb140e [d3d9] Add present params validations on device creation and reset 2024-11-02 18:07:33 +01:00
WinterSnowfall
35352b9c52 [d3d8] Set D3D8 compatibility at D3D9 interface level 2024-11-02 18:07:33 +01:00
WinterSnowfall
11d5f9ee36 [d3d8] State block recording validations 2024-11-02 18:07:33 +01:00
WinterSnowfall
0e6be8a48b [d3d8/9] Add several Set/GetPrivateData validations 2024-11-02 18:07:33 +01:00
Robin Kertels
48d8e7c402 [d3d9] Improve code readability with comments 2024-11-02 17:48:13 +01:00
Robin Kertels
19fea8c48d [d3d9] Move remaining texture bitmask updates to function 2024-11-02 17:48:13 +01:00
Robin Kertels
8d10bfecd4 [d3d9] Remove unused readonly bitfield 2024-11-02 17:48:13 +01:00
WinterSnowfall
c606ab03e8 [util] Re-enable direct buffer mapping for Rayman 3 2024-11-02 15:41:34 +01:00
WinterSnowfall
f74b2cd6c6 [d3d9] Order modes descending by refresh rate 2024-10-31 20:37:04 +01:00
WinterSnowfall
6e43bf6d61 [util] Include Prince of Persia main executable 2024-10-31 14:57:32 +01:00
Philip Rebohle
d4f25c81be [d3d11] Remove d3d11.maxImplicitDiscardSize option 2024-10-31 12:13:27 +01:00
Philip Rebohle
f9bb8f0ad5 [d3d11] Consider discards when throttling immediate context 2024-10-31 12:13:26 +01:00
Philip Rebohle
65aa74aa7f [hud] Fix off-by-one error in memory type enumeration 2024-10-31 12:12:31 +01:00
Philip Rebohle
a91afc3a2f [d3d11] Do not touch row/depth pitch on failed map
Fixes a wine test.
2024-10-30 23:37:54 +01:00
Philip Rebohle
f0e9138886 [d3d11] Fix error return on MAP_WRITE_NO_OVERWRITE on deferred context
Fixes a wine test.
2024-10-30 23:37:54 +01:00
Philip Rebohle
67c5ab87f9 [d3d11] Add missing fragment shader stage to mapped image buffers
Relevant when uploading depth-stencil images.
2024-10-30 23:37:54 +01:00
Philip Rebohle
8ee7031742 [d3d11] Simplify InitHostVisibleBuffer 2024-10-30 23:37:54 +01:00
Philip Rebohle
223691b7aa [d3d11] Use device fence wait in ThrottleAllocation 2024-10-30 23:37:54 +01:00
Philip Rebohle
84ce80f931 [d3d9] Use new fence wait function in WaitStagingBuffer 2024-10-30 23:37:54 +01:00
Philip Rebohle
85684109b3 [dxvk] Add method to wait for fence as a GPU sync point 2024-10-30 23:37:54 +01:00
Philip Rebohle
3c389ae06b [dxvk] Adjust chunk size logic for mapped memory types
Total War Warhammer III discards a 48MB image every frame, so hitting
the dedicated allocation path pretty much at random leads to issues.
2024-10-30 23:37:54 +01:00
Philip Rebohle
ff78112271 [include] Add missing D3D11 error definition for native 2024-10-30 10:51:11 +01:00
Philip Rebohle
e41b1a11b2 [dxvk] Also add tracking ID to sampler objects 2024-10-30 09:42:53 +01:00
Philip Rebohle
0e14fff749 [dxvk] Introduce tracking ID for resource tracking
Replaces the existing bit masks, which is possible now because the
CS thread is the only place where submissions happen now.

This way we only count each resource once per submission, or twice
in case a read access is followed by a write.

This also fixes a potential tracking bug with shader-writeable resources.
2024-10-30 09:41:49 +01:00
Philip Rebohle
10fac66007 [dxvk] Don't override tracked write with a read
Fixes a regression in Control.
2024-10-30 03:39:45 +01:00
Jeff
201e1628b0 [d3d9] Add ID3D9VkInteropTexture to volumes 2024-10-30 02:17:35 +01:00
Philip Rebohle
e499f2e081 [d3d11] Fix potential crash when mapping a default image fails
This also marginally shortens common code paths.
2024-10-29 18:05:14 +01:00
Philip Rebohle
c2928ab3e2 [dxvk] Increment stat counters in command list rather than context
Might change some numbers, but it's closer to reality.
2024-10-28 23:03:46 +01:00
Philip Rebohle
7cd8a14673 [dxvk] Initialize additional command buffers on demand
The vast majority of submissions will only use one or two command buffers
rather than all five, and only the main command buffer will almost always
actually be used. This also saves us a bunch of CPU-side tracking.
2024-10-28 23:03:46 +01:00
Philip Rebohle
34b82a2b5b [dxvk] Add dedicated command buffers for initial layout transitions
This helps batch initial layout transitions for image uploads.
2024-10-28 23:03:46 +01:00
Philip Rebohle
d85cabe457 [dxvk] Refactor command buffer allocation 2024-10-28 23:03:46 +01:00
Philip Rebohle
b5e5d7a498 [dxvk] Use out-of-order transfer helper in clearImageViewCs
Covers image-related ClearUAV use cases.
2024-10-28 23:03:46 +01:00
Philip Rebohle
c795415c39 [dxvk] Use out-of-order transfer helper in clearBufferView
Covers some ClearUAV / ClearView use cases involving buffers.
2024-10-28 23:03:46 +01:00
Philip Rebohle
301f06bdfb [dxvk] Use out-of-order transfer helper in copyBufferToImage 2024-10-28 23:03:46 +01:00
Philip Rebohle
e69f09175f [dxvk] Use out-of-order transfer helper in updateBuffer 2024-10-28 23:03:46 +01:00
Philip Rebohle
28a1077c06 [dxvk] Use out-of-order transfer helper in copyBuffer 2024-10-28 23:03:46 +01:00
Philip Rebohle
8269b93f51 [dxvk] Use out-of-order transfer helper in clearBuffer 2024-10-28 23:03:46 +01:00
Philip Rebohle
c8ab88e8f5 [dxvk] Add helper for out-of-order resource transfers 2024-10-28 23:03:46 +01:00
Philip Rebohle
f0054e7e65 [dxvk] Add command list tracking to resource 2024-10-28 23:03:46 +01:00
Philip Rebohle
dd6d82e1ce [dxvk] Fix nonsensical layout check in ensureImageCompatibility
Derp, this fixes some unnecessary barriers.
2024-10-28 23:03:46 +01:00
Philip Rebohle
0fd00087e9 [dxvk] Filter out BDA usage for buffer invalidation early exit 2024-10-28 00:03:26 +01:00
Ethan Lee
469025d234 native: Add SDL3 WSI
Co-authored-by: Philip Rebohle <philip.rebohle@tu-dortmund.de>
2024-10-27 12:58:22 +01:00
Philip Rebohle
0259f55285 wsi: Pass window state to setWindowMode 2024-10-27 12:58:22 +01:00
WinterSnowfall
5ad84563dd [d3d9] Improve the naming of GetFormatBlockSize helper 2024-10-27 12:36:33 +01:00
WinterSnowfall
7ffe77f7c4 [d3d9] Validate pBox dimensions with LockBox 2024-10-27 12:36:33 +01:00
WinterSnowfall
a0d48cd2a2 [d3d9] Adjust pLockedRect/pLockedBox clearing and return behavior 2024-10-27 12:36:33 +01:00
WinterSnowfall
63d9affdcb [d3d9] Add volume texture creation and locking validations 2024-10-27 12:36:33 +01:00
WinterSnowfall
a323abe085 [d3d9] Validate alignment for block aligned formats 2024-10-27 12:36:33 +01:00
WinterSnowfall
678ccc721d [d3d9] Validate pRect dimensions with LockRect 2024-10-27 12:36:33 +01:00
Philip Rebohle
80fbaed291 Revert "[d3d11] Use existing MD5 hash to look up shader objects"
This reverts commit 800f71c4f5.

We can't do this without breaking fossilize DBs because we compile the
SHA1 hash into the shader binary.
2024-10-27 12:53:11 +01:00
Philip Rebohle
4709d429ed [dxbc] Fix EvalSnapped offset interpretation 2024-10-27 12:52:15 +01:00
Philip Rebohle
640758afcf [util] Enable mapped memory clearing for Vindictus 2024-10-27 02:43:58 +02:00
Philip Rebohle
ed83534970 [dxvk] Add option to clear mapped memory regions to zero 2024-10-27 02:43:58 +02:00
Philip Rebohle
e9574a4155 [dxvk] Add utility function to clear large regions of memory 2024-10-27 02:43:58 +02:00
Philip Rebohle
d535e2964f [dxvk] Remove obsolete comments 2024-10-25 19:22:58 +02:00
Philip Rebohle
3268bda4a2 [dxvk] Fix potential issues in invalidateImageWithUsage
Relevant for image recreation in D3D9, not so much for defrag
since we do everything late in the command list anyway.
2024-10-25 19:22:58 +02:00
Philip Rebohle
1a4ac219ed [dxvk] Properly flush everything before recording defrag commands 2024-10-25 19:22:58 +02:00
Philip Rebohle
7df58de815 [dxvk] Do not emit useless image barriers in relocateResources
Instead, fold barriers with no layout transition into a simple memory
barrier to bring this in line with the usual barrier logic.
2024-10-25 19:22:58 +02:00
Philip Rebohle
763780fb4c [dxvk] Remove obsolete fence code from command submissions
Unused since the timeline semaphore rework.
2024-10-25 11:31:01 +02:00
Philip Rebohle
662cfd49f5 [dxvk] Fix nonsensical pipeline stages when relocating resources 2024-10-24 15:19:43 +02:00
Philip Rebohle
640379e54b [dxvk] Remove obsolete DxvkDeviceOptions structure
This hasn't been used since 2.0.
2024-10-24 12:31:18 +02:00
Philip Rebohle
ec62551412 [dxvk] Add option to disable memory defragmentation 2024-10-24 12:31:18 +02:00
Philip Rebohle
9977313c32 [dxvk] Do not defragment chunks with immovable resources 2024-10-24 12:31:18 +02:00
Philip Rebohle
62f266098e [dxvk] Consider driver allocations when computing memory budget 2024-10-24 12:31:18 +02:00
Philip Rebohle
de400ae8a9 [dxvk] Increase memory task tick rate to 0.5s
Makes cleanup a bit quicker in some cases.
2024-10-24 12:31:18 +02:00
Philip Rebohle
7a09ab6c83 [dxvk] Limit amount of memory to relocate per submission
If the resources we're moving around are in slow memory, moving a full
chunk at once can already take several milliseconds. Try to avoid that.
2024-10-24 12:31:18 +02:00
Philip Rebohle
787671ef62 [dxvk] Limit number of allocations to move per submissions 2024-10-24 12:31:18 +02:00
Philip Rebohle
899f48bc43 [dxvk] Periodically defragment VRAM chunks 2024-10-24 12:31:18 +02:00
Philip Rebohle
c4cddebb89 [hud] Visualize inactive chunks 2024-10-24 12:31:18 +02:00
Philip Rebohle
2c8fe59924 [dxvk] Sort chunks by allocation time for statistics 2024-10-24 12:31:18 +02:00
Philip Rebohle
69437c2fea [dxvk] Include chunk status in statistics 2024-10-24 12:31:18 +02:00
Philip Rebohle
7a693ed41a [dxvk] Implement per-submission resource relocation 2024-10-24 12:31:18 +02:00
Philip Rebohle
9cbd45b8cf [dxvk] Add helper class for resource relocation 2024-10-24 12:31:18 +02:00
Philip Rebohle
0723250c12 [dxvk] Introduce flag to synchronize transfer queue
Also, get rid of superfluous binary semaphores since we have
a straight per-submission timeline anyway.
2024-10-24 12:31:18 +02:00
Philip Rebohle
13da763f9b [dxvk] Use small_vector in submission code 2024-10-24 12:31:18 +02:00
Philip Rebohle
800792a67d [dxvk] Add function to safely acquire a resource 2024-10-24 12:31:18 +02:00
Philip Rebohle
c7a9c626f5 [dxvk] Handle dead chunks in pool allocator 2024-10-24 12:31:18 +02:00
Philip Rebohle
a9bcb40655 [dxvk] Add concept of disabled chunks to allocator 2024-10-24 12:31:18 +02:00
Philip Rebohle
bfcfcab60f [dxvk] Add method to allocate backing storage with constraints 2024-10-24 12:31:18 +02:00
Philip Rebohle
a3c8c88222 [dxvk] Fix race condition in relocation check
The storage pointer is not safe to dereference outside the CS thread
for relocatable resources since the storage object may change.
2024-10-24 12:31:18 +02:00
Philip Rebohle
3a1de271cb [dxvk] Introduce allocation modes
Will be useful when relocating resources for defragmentation purposes.
2024-10-24 12:31:18 +02:00
Philip Rebohle
9a8406f28a [dxvk] Add global resource map to memory allocator 2024-10-24 12:31:18 +02:00
Philip Rebohle
8e94a8bcc6 [dxvk] Add per-chunk allocation list 2024-10-24 12:31:18 +02:00
Philip Rebohle
4e40d0b939 [dxvk] Add allocation flag for moveable resources 2024-10-24 12:31:18 +02:00
Philip Rebohle
bb05f123db [dxvk] Pass resource cookie to allocation objects 2024-10-24 12:31:18 +02:00
Philip Rebohle
efebceecbe [dxvk] Introduce DxvkAllocationInfo
Useful when more properties are added in the future.
2024-10-24 12:31:18 +02:00
Philip Rebohle
7ccfb57d57 [dxvk] Reintroduce resource cookies 2024-10-24 12:31:18 +02:00
Philip Rebohle
809257051b [dxvk] Rename unspecific "next" member in DxvkResourceAllocation 2024-10-24 12:31:18 +02:00
Philip Rebohle
3befea6516 [dxvk] Actually count barriers from resource relocation 2024-10-24 12:31:18 +02:00
Philip Rebohle
90f32d76ff [dxvk] Ignore uninitialized image subresources during relocation 2024-10-24 12:31:18 +02:00
Philip Rebohle
77a1164d1b [dxvk] Track initialization of internally managed images
Otherwise, these will not be relocated properly during defragmentation.
2024-10-24 12:31:18 +02:00
Philip Rebohle
1c157d1a63 [util] Properly return reference from small_vector emplace_back 2024-10-24 12:31:18 +02:00
Philip Rebohle
4af31a9d64 [dxvk] Remove context type concept
We only have a single context per device now.
2024-10-24 12:30:54 +02:00
Philip Rebohle
b4ed108105 [d3d9] Remove format conversion context 2024-10-24 12:30:54 +02:00
Philip Rebohle
f9a99e81f4 [dxvk] Bump state cache format to v18
All D3D11 shader keys change, so we should invalidte existing caches.
2024-10-23 16:56:32 +02:00
Philip Rebohle
f3fa2535e8 [d3d11] Validate shader creation parameters 2024-10-23 16:56:32 +02:00
Philip Rebohle
800f71c4f5 [d3d11] Use existing MD5 hash to look up shader objects
Skips the expensive SHA-1 pass.
2024-10-23 16:56:32 +02:00
Philip Rebohle
ae9024492b [d3d11] Devirtualize context method forwarding 2024-10-23 16:56:22 +02:00
Philip Rebohle
d10df6353b [d3d11] Devirtualize resource and view creation method forwarding 2024-10-23 16:56:22 +02:00
Philip Rebohle
565af8c311 [dxvk] Add important assert to object tracker 2024-10-23 11:30:37 +02:00
Blisto91
24e0440043 [util] Remove The Old Republic config
Looks fine without since dxvk 2.0
2024-10-23 11:19:01 +02:00
Philip Rebohle
01300bb884 [dxvk] Improve some descriptor setup code
Help the compiler out since it cannot fully prove that two consecutive
calls to DxvkImageView::handle with the same argument return the same result.
2024-10-23 10:26:24 +02:00
Philip Rebohle
cd4d68244d [dxvk] Use real shader access types for writeable descriptor types
Mostly relevant for storage buffers since those are often read-only.
2024-10-23 10:08:03 +02:00
Blisto91
f813549ced [util] Set forceSamplerTypeSpecConstants for Alpha Protocol
Some objects like metal containers will have unwanted reflection when they shouldn't otherwise.
2024-10-22 11:34:02 +02:00
Philip Rebohle
ce42ce2f3f [dxvk] Remove memory worker thread 2024-10-21 17:29:38 +02:00
Philip Rebohle
a5dc3400bd [dxvk] Use swap chain fences to synchronize WSI semaphores
Requires EXT_swapchain_maintenance1 to work, otherwise we won't use this.
2024-10-21 12:02:44 +02:00
Philip Rebohle
27539fc838 [dxvk] Use timeline semaphores for GPU synchronization
Ditches the old fence and binary semaphore code.
2024-10-21 12:02:44 +02:00
Philip Rebohle
1ee60048c0 [dxvk] Create timeline semaphores in submission queue 2024-10-21 12:02:44 +02:00
Philip Rebohle
4c0cbbef6a [dxvk] Factor DxvkResource code into DxvkPagedResource
And remove the now obsolete code.
2024-10-18 12:42:33 +02:00
Philip Rebohle
6540ab4f3e [dxvk] Use DxvkPagedResource for CPU synchronization 2024-10-18 12:42:33 +02:00
Philip Rebohle
3a587c5116 [dxvk] Remove old lifetime tracking code 2024-10-18 12:42:33 +02:00
Philip Rebohle
cc22ccfc5c [dxvk] Use new lifetime tracking for resources 2024-10-18 12:42:33 +02:00
Philip Rebohle
8389734e9f [dxvk] Use new lifetime tracking for raw allocations 2024-10-18 12:42:33 +02:00
Philip Rebohle
b011e22406 [dxvk] Use new lifetime tracking for samplers 2024-10-18 12:42:33 +02:00
Philip Rebohle
7fef97dae0 [dxvk] Use new lifetime tracking for events 2024-10-18 12:42:33 +02:00
Philip Rebohle
50d8e3933a [dxvk] Use new lifetime tracking for queries 2024-10-18 12:42:33 +02:00
Philip Rebohle
4a00623c40 [dxvk] Introduce DxvkTrackingRef and new tracking functions
The intention here is to clean up the code significantly while also
paving a way to perform more complex operations on resource release.
2024-10-18 12:42:33 +02:00
Philip Rebohle
56e8d55830 [dxvk] Remove direct resource allocation tracking
Track the containing virtual resources instead and only explicitly
keep allocations alive through invalidations.
2024-10-18 12:42:33 +02:00
Philip Rebohle
863ce5f117 [dxvk] Move DxvkAccess{Flags} to separate file 2024-10-18 12:42:33 +02:00
Philip Rebohle
d72346f2cb [dxvk] Rename various storage-related functions 2024-10-18 12:42:33 +02:00
Philip Rebohle
43355ecd73 [dxvk] Optimize small_vector reallocation code 2024-10-18 12:42:33 +02:00
num0005
f56b77942d [CI][Win] Copy version logic from artifacts script. 2024-10-17 22:40:08 +00:00
num0005
f85596ffbf [CI] Upload artifacts for Windows builds. 2024-10-17 22:40:08 +00:00
num0005
01684d36ba [build][msvc] Enable PDB output for all builds.
PDB generation even for release builds takes a little more time, but makes debugging DXVK on Windows easier. As the symbols are not embedded in the DLL it doesn't impact code generation or output binary size.
2024-10-17 22:40:08 +00:00
Philip Rebohle
e2b4060d43 [dxvk] Properly dirty multisample state when binding linked pipelines
Fixes a validation error in GTA V in very specific circumstances.
2024-10-17 19:40:17 +02:00
Philip Rebohle
990c7f562a [dxvk] Rework HUD to use a GPU query directly
Allows us to leverage the global timestamp query pool now that queries
are reference-counted properly.
2024-10-17 14:27:09 +02:00
Philip Rebohle
fb6e0ad6c1 [dxvk] Remove useless DxvkMarker class 2024-10-16 20:57:50 +02:00
Philip Rebohle
500c86c054 [d3d9] Replace staging buffer marker with monotonic fence
Brings this in line with D3D11.
2024-10-16 20:57:50 +02:00
Philip Rebohle
0249193403 [util] Avoid locking fence objects on wait if target value was reached 2024-10-16 20:57:50 +02:00
Philip Rebohle
bdec26b442 [dxvk] Actually flush layout transition in clearImageViewCs
Fixes 2864a5e474.
2024-10-16 20:55:59 +02:00
Philip Rebohle
f8b9efd11e [dxvk] Fix misaligned image uploads on transfer queue 2024-10-16 11:38:42 +02:00
Philip Rebohle
d2155c7f8c [dxvk] End transform feedback when changing the active graphics pipeline 2024-10-16 11:33:40 +02:00
Philip Rebohle
f69dc96c24 [dxvk] Sanitize multisample state for fragment output libraries
Validation complains about MS state being different between fragment shader
pipeline libraries and fragment output libraries on the EDS3 path.
2024-10-16 11:33:29 +02:00
Philip Rebohle
8ab6b8616b [dxvk] Track image initialization 2024-10-16 11:32:55 +02:00
Philip Rebohle
255e7b7d7a [dxvk] Add functions for image subresource initialization tracking 2024-10-16 11:32:55 +02:00
Philip Rebohle
af4ec3c63d [dxvk] Normalize render target layouts when binding framebuffer
No reason to use ATTACHMENT_OPTIMAL when the default layout is GENERAL.
2024-10-16 11:32:55 +02:00
Philip Rebohle
f76fb75956 [d3d9] Prefer GENERAL layout for read-only textures 2024-10-16 11:32:55 +02:00
Philip Rebohle
b2598906ca [d3d11] Prefer GENERAL layout for read-only textures 2024-10-16 11:32:55 +02:00
Philip Rebohle
6301b9d23d [dxvk] Remove old barrier tracking code 2024-10-16 11:32:55 +02:00
Philip Rebohle
708d23ca4b [dxvk] Use new barrier batch and barrier tracker for main command buffer 2024-10-16 11:32:55 +02:00
Philip Rebohle
4d2799f0d4 [dxvk] Add helper to determine pending barriers 2024-10-16 11:32:55 +02:00
Philip Rebohle
56a58095fe [dxvk] Use new barrier helpers for shader execution barriers 2024-10-16 11:32:55 +02:00
Philip Rebohle
4b94b8989d [dxvk] Use new barrier helpers in transition*Attachment 2024-10-16 11:32:55 +02:00
Philip Rebohle
0388f20cd3 [dxvk] Use new barrier helpers in updateGraphicsPipelineState 2024-10-16 11:32:55 +02:00
Philip Rebohle
7c274d0852 [dxvk] Use new barrier helpers in renderPassEmitPostBarriers 2024-10-16 11:32:55 +02:00
Philip Rebohle
3d12c1aea5 [dxvk] Use new barrier helpers in renderPassEmitInitBarriers 2024-10-16 11:32:55 +02:00
Philip Rebohle
d00d0a39ce [dxvk] Use new barrier helpers in spillRenderPass 2024-10-16 11:32:55 +02:00
Philip Rebohle
c2edd0f9bb [dxvk] Use new barrier helpers in resolveImageFb 2024-10-16 11:32:55 +02:00
Philip Rebohle
7b65ee00d9 [dxvk] Use new barrier helpers in resolveImageDs 2024-10-16 11:32:55 +02:00
Philip Rebohle
7b436a63fb [dxvk] Use new barrier helpers in resolveImageHw 2024-10-16 11:32:55 +02:00
Philip Rebohle
63347b5fce [dxvk] Use new barrier helpers in copySparsePages 2024-10-16 11:32:55 +02:00
Philip Rebohle
706d6cbc1c [dxvk] Use new barrier helpers in copyImageFb 2024-10-16 11:32:55 +02:00
Philip Rebohle
42da4348bf [dxvk] Use new barrier helpers in copyImageHw 2024-10-16 11:32:55 +02:00
Philip Rebohle
2864a5e474 [dxvk] Use new barrier helpers in clearImageViewCs
And ensure we're in GENERAL layout. We generally (pun intended) should
be, but there may be a universe where that is not the case.
2024-10-16 11:32:55 +02:00
Philip Rebohle
793f9b3d38 [dxvk] Use new barrier helpers in clearImageViewFb 2024-10-16 11:32:55 +02:00
Philip Rebohle
856a84e6fd [dxvk] Use new barrier helpers in copyImageToBufferCs
And actually rename that function to make sense.
2024-10-16 11:32:55 +02:00
Philip Rebohle
59d37757b0 [dxvk] Use new barrier helpers in copyImageToBufferHw 2024-10-16 11:32:55 +02:00
Philip Rebohle
e21c2977df [dxvk] Use new barrier helpers in copyBufferToImageFb 2024-10-16 11:32:55 +02:00
Philip Rebohle
d7dd80b62f [dxvk] Use new barrier helpers in copyBufferToImageHw 2024-10-16 11:32:55 +02:00
Philip Rebohle
389e40be67 [dxvk] Use new barrier helpers in blitImageHw 2024-10-16 11:32:55 +02:00
Philip Rebohle
82c2f5d5d1 [dxvk] Use new barrier helpers in blitImageFb 2024-10-16 11:32:55 +02:00
Philip Rebohle
a4daa63d2b [dxvk] Use new barrier helpers in launchCuKernelNVX 2024-10-16 11:32:55 +02:00
Philip Rebohle
ab9ade76d7 [dxvk] Use new barrier helpers in emitGraphicsBarrier 2024-10-16 11:32:55 +02:00
Philip Rebohle
e70e72f109 [dxvk] Use new barrier helpers in updateBuffer 2024-10-16 11:32:55 +02:00
Philip Rebohle
ab300dce2f [dxvk] Use new barrier helpers in performClear 2024-10-16 11:32:55 +02:00
Philip Rebohle
a1a9cd5bb6 [dxvk] Use new barrier helpers in transformImage 2024-10-16 11:32:55 +02:00
Philip Rebohle
7edfad763a [dxvk] Use new barrier helpers in ensureImageCompatibility 2024-10-16 11:32:55 +02:00
Philip Rebohle
33b146467a [dxvk] USe new barrier helpers in generateMipmaps 2024-10-16 11:32:55 +02:00
Philip Rebohle
03a716e308 [dxvk] Use new barrier helpers in emit*Barrier 2024-10-16 11:32:55 +02:00
Philip Rebohle
ee9d09c2e2 [dxvk] Use new barrier helpers in dispatchIndirect 2024-10-16 11:32:55 +02:00
Philip Rebohle
826114f612 [dxvk] Use new barrier helpers in copyPackedBufferImage 2024-10-16 11:32:55 +02:00
Philip Rebohle
3ecca3d171 [dxvk] Use new barrier helpers in copyBuffer 2024-10-16 11:32:55 +02:00
Philip Rebohle
6ef6cb3b45 [dxvk] Use new barrier helpers in clearBufferView 2024-10-16 11:32:55 +02:00
Philip Rebohle
5dfc4d6300 [dxvk] Use new barrier helpers in clearBuffer 2024-10-16 11:32:55 +02:00
Philip Rebohle
cc3dd31a5f [dxvk] Use new barrier helpers in changeImageLayout 2024-10-16 11:32:55 +02:00
Philip Rebohle
bbe7767475 [dxvk] Add helpers to flush pending execution barriers if needed 2024-10-16 11:32:55 +02:00
Philip Rebohle
318e79c2ad [dxvk] Use new barrier batch for init and sdma barriers
No tracking needed here.
2024-10-16 11:32:55 +02:00
Philip Rebohle
50b1932aea [dxvk] Use new barrier helper in uploadBuffer 2024-10-16 11:32:55 +02:00
Philip Rebohle
b33f0c3d30 [dxvk] Use new barrier helper in updateBuffer 2024-10-16 11:32:55 +02:00
Philip Rebohle
e6c0903600 [dxvk] Use new barrier helper in initSparseImage 2024-10-16 11:32:55 +02:00
Philip Rebohle
9698653055 [dxvk] Use new barrier helper in initImage 2024-10-16 11:32:55 +02:00
Philip Rebohle
94915fcbe3 [dxvk] Use new barrier helper in initBuffer 2024-10-16 11:32:55 +02:00
Philip Rebohle
6b01203ddf [dxvk] Use new barrier helper in copyBuffer 2024-10-16 11:32:55 +02:00
Philip Rebohle
6e6ee35587 [dxvk] Use new barrier helper in clearBuffer 2024-10-16 11:32:55 +02:00
Philip Rebohle
b771bef837 [dxvk] Add helper functions to record pending barriers 2024-10-16 11:32:55 +02:00
Philip Rebohle
d154a684ad [dxvk] Remove acquire barrier set 2024-10-16 11:32:55 +02:00
Philip Rebohle
3de0f27dd9 [dxvk] Use new layout transition helper in resolveImageFb 2024-10-16 11:32:55 +02:00
Philip Rebohle
801ef39895 [dxvk] Use new layout transition helper in resolveImageDs 2024-10-16 11:32:55 +02:00
Philip Rebohle
154eee96a0 [dxvk] Use new layout transition helper in resolveImageHw 2024-10-16 11:32:55 +02:00
Philip Rebohle
704fc4eaa7 [dxvk] Use new layout transition helper in copySparseImagePages 2024-10-16 11:32:55 +02:00
Philip Rebohle
4d19e58f51 [dxvk] Use new layout transition helper for copyImageFb 2024-10-16 11:32:55 +02:00
Philip Rebohle
7ffde27551 [dxvk] Use new layout transition helper in copyImageHw 2024-10-16 11:32:55 +02:00
Philip Rebohle
bbd041194b [dxvk] Use new layout transition helper in clearImageViewFb 2024-10-16 11:32:55 +02:00
Philip Rebohle
18cdc25773 [dxvk] Use new layout transition helper in copyImageToBufferFb 2024-10-16 11:32:55 +02:00
Philip Rebohle
e8a5583562 [dxvk] Use new layout transition helper in copyImageToBufferHw 2024-10-16 11:32:55 +02:00
Philip Rebohle
088e4024f5 [dxvk] Use new layout transition helper in copyBufferToImageFb 2024-10-16 11:32:55 +02:00
Philip Rebohle
ebd067f098 [dxvk] Use new layout transition helper in copyBufferToImageHw 2024-10-16 11:32:55 +02:00
Philip Rebohle
2353867d54 [dxvk] Use new layout transition helper for blitImageHw 2024-10-16 11:32:55 +02:00
Philip Rebohle
aff6cb744c [dxvk] Use new layout transition helper for blitImageFb 2024-10-16 11:32:55 +02:00
Philip Rebohle
971042b3d3 [dxvk] Use new layout transition helper in performClear 2024-10-16 11:32:55 +02:00
Philip Rebohle
c24be65f2a [dxvk] Use new layout transition helper in generateMipmaps 2024-10-16 11:32:55 +02:00
Philip Rebohle
ef79f8a617 [dxvk] Use new layout transition helper in initImage
Removes another barrier set.
2024-10-16 11:32:55 +02:00
Philip Rebohle
1e8631189c [dxvk] Use new layout transition helper in uploadImageHw
Allows us to get rid of a barrier set.
2024-10-16 11:32:55 +02:00
Philip Rebohle
8955d2a285 [dxvk] Add various helpers to emit image layout transitions 2024-10-16 11:32:55 +02:00
Philip Rebohle
756ff73c8a [dxvk] Add new barrier batch helper
Separates batching from tracking. This is useful because init
and transfer queue barriers do not need any tracking.
2024-10-16 11:32:55 +02:00
Philip Rebohle
c6c85d7532 [dxvk] Add new barrier tracker
Uses a hash table backed by RB trees in order to reduce
worst-case runtime overhead in some edge cases.
2024-10-16 11:32:55 +02:00
Philip Rebohle
af3c46d83c [dxvk] Remove unused buffer barrier array 2024-10-16 11:32:55 +02:00
Robin Kertels
763b82b1e4 [d3d9] Fix render target null pointer deref 2024-10-15 19:29:20 +02:00
Philip Rebohle
35ead85929 [d3d11] Manually free all view objects in view destructor 2024-10-15 11:48:51 +02:00
Philip Rebohle
de65e06831 [dxvk] Do not try to reset pointer in Rc destructor
This gets optimized away in release builds.
2024-10-15 11:48:51 +02:00
Jeff
e4630685e4 [d3d9] Fix mismatched case in MultiSample and MultisampleQuality 2024-10-15 10:09:51 +02:00
Jeff
01a1c8359a [d3d9] Fix spelling nit 2024-10-15 10:09:51 +02:00
Jeff
eafdf0bfd7 [d3d9] Add alternate constructor for D3D9Texture2D 2024-10-15 10:09:51 +02:00
Jeff
25069dbd1d [d3d9] Add alternate constructor for D3D9Surface 2024-10-15 10:09:51 +02:00
Jeff
a044c639f7 [d3d9] Add ID3D9VkInteropDevice::CreateImage to create custom texture/surfaces 2024-10-15 10:09:51 +02:00
Blisto91
98fa338be0 [util] Move Far Cry 2 config to d3d9 section 2024-10-14 18:39:02 +02:00
Blisto91
b707ca1309 [util] Enable memoryTrackTest for Secret World Legends
Otherwise d3d9 mode thinks we only have 512MB vram which will lock the higher graphics presets.
2024-10-14 18:39:02 +02:00
Robin Kertels
f65897be4c [d3d9] Remove a few unnecessary bitmasks 2024-10-13 17:13:31 +02:00
Robin Kertels
421ead5b30 [d3d9] Only dirty frame buffer on render state changes if render area is impacted 2024-10-13 17:13:31 +02:00
WinterSnowfall
b99012d332 [d3d9] Adjust matrix inversion boundary 2024-10-13 11:09:13 +00:00
Blisto91
05d089bee5 [d3d9] Silence unhandled render state D3DRS_ADAPTIVETESS_Y 2024-10-13 12:31:14 +02:00
Philip Rebohle
458b8e3b41 [util] Add missing includes small_vector
Fixes #4357.
2024-10-13 12:29:12 +02:00
Philip Rebohle
693ee7898d [dxvk] Refactor queries to be properly ref-counted
Should fix a long-standing lifetime tracking issue with timestamp
queries as well as invalid Vulkan usage with overlapping scoped
queries.
2024-10-13 12:08:35 +02:00
Philip Rebohle
1b9c59c964 [dxvk] Refactor events to be properly ref-counted
Mostly serves as a proof-of-concept for the pending query rework,
but also cleans up some silly code.
2024-10-13 12:08:35 +02:00
Philip Rebohle
d00669cb52 [dxvk] Rename DxvkGpu{Event,Query} to Dxvk{Event,Query}
The old name only ever existed because DXVK had two separate implementations
of these prior to version 1.1. Let's name them back so that more sensible
names are available for internal use.
2024-10-13 12:08:35 +02:00
Robin Kertels
5890eae32f [d3d9] Don't clear mipGenBit if texture is bound as attachment 2024-10-13 12:07:30 +02:00
Robin Kertels
5ff365b9f1 [d3d9] Remove initializer context 2024-10-12 10:09:17 +02:00
WinterSnowfall
48c57c11e9 [d3d9] Make proper use of X/YHotSpot for software cursors 2024-10-11 12:40:37 +02:00
WinterSnowfall
44b682051b [d3d8] Stub DebugSetMute to fix C&C:Generals performance 2024-10-10 13:06:54 +02:00
WinterSnowfall
c8759418af [d3d9] Fix device reset handling when no cursor is set 2024-10-10 09:31:13 +02:00
Robin Kertels
d39d879838 [d3d9] Add a bunch of missing likely/unlikely to PrepareDraw
PrepareDraw is pretty much the hottest part of the d3d9
frontend, so we take every tiny bit we get.
2024-10-09 21:28:59 +00:00
Robin Kertels
395ac38890 [d3d9] Fix fixed function texture mask
Fixed function supports 8 textures so we need 8 ones.
2024-10-09 21:28:59 +00:00
WinterSnowfall
a1a3800b3f [d3d9] Fix software cursor reset and transitions 2024-10-08 20:20:31 +02:00
Philip Rebohle
a30fdc466b [d3d11] Remove initializer context
This moves all initialization commands to the CS thread and the regular
context in such a way that resource initialization is processed before
any context commands can use the resource.
2024-10-08 17:46:18 +02:00
Philip Rebohle
ac1dfbacb6 [dxvk] Move image initialization to init command buffer 2024-10-08 17:46:18 +02:00
Philip Rebohle
0f6f543583 [dxvk] Silence validation error about invalid shaders
Known validation bug that is already fixed upstream, but this makes
validation layers unusable due to how spammy that is.
2024-10-08 17:46:18 +02:00
Philip Rebohle
df60a061a4 [d3d11] Throttle resource uploads via UpdateSubresource
Otherwise, some games (e.g. Frostpunk, New World) end up allocating over
a gigabyte of staging memory.
2024-10-08 17:46:18 +02:00
Philip Rebohle
ec18dd7846 [d3d11] Throttle resource uploads through staging buffer 2024-10-08 17:46:18 +02:00
Philip Rebohle
d330718353 [dxvk] Implement staging buffer statistics 2024-10-08 17:46:18 +02:00
Philip Rebohle
e137f049ee [dxvk] Make buffer<->image copy format checks more robust
There are situations where the source format may not match
the image format but the copy is valid nonetheless.
2024-10-08 17:46:18 +02:00
Philip Rebohle
e6f90b8003 [dxvk] Remove legacy depth/stencil repacking code 2024-10-08 17:46:18 +02:00
Philip Rebohle
ad1f70beea [dxvk] Support format conversion in copyImageToBuffer 2024-10-08 17:46:18 +02:00
Philip Rebohle
f67c8dd1da [dxvk] Support format conversion in copyBufferToImage 2024-10-08 17:46:18 +02:00
Philip Rebohle
501b0991da [dxvk] Remove per-context staging buffer
No longer used.
2024-10-08 17:46:18 +02:00
Philip Rebohle
725a04b954 [dxvk,d3d11] Refactor uploadImage to consume a staging buffer
And also handle format differences.
2024-10-08 17:46:18 +02:00
Philip Rebohle
34e0f6952b [dxvk] Always enable depth-stencil usage for depth-stencil formats 2024-10-08 17:46:18 +02:00
Philip Rebohle
2fac69b7f9 [dxvk] Add pipelines for buffer-to-image and image-to-buffer copies 2024-10-08 17:46:18 +02:00
Philip Rebohle
15d5b69d2c [dxvk] Add new format conversion shaders
Intended to replace the old pack/unpack shaders.
2024-10-08 17:46:18 +02:00
Philip Rebohle
3c50ac1f12 [dxvk] Rename DxvkCopyBufferImage* stuff
Slightly misleadning name when we're going to introduce copies
between buffers and images.
2024-10-08 17:46:18 +02:00
Philip Rebohle
c92ee8ee07 [dxvk,d3d11] Refactor uploadBuffer to consume a staging buffer 2024-10-08 17:46:18 +02:00
Philip Rebohle
c27cae2f10 [d3d11] Improve per-context staging buffer handling
In D3D11, the staging buffer is only used for UpdateSubresource, which
isn't always used much. Reducing the size and freeing the buffer after
every submission avoids situations where system memory chunks are kept
alive by a single unused 4MB allocation.
2024-10-08 17:46:18 +02:00
Philip Rebohle
c614e537a9 [dxvk] Remove alignment parameter from staging buffers
Just align all suballocations to 256 bytes as usual.
2024-10-08 17:46:18 +02:00
WinterSnowfall
7eec8fb8dc [d3d8] Various logging format adjustments 2024-10-08 00:25:55 +02:00
WinterSnowfall
559398f6a4 [d3d9] Check block alignment on texture creation with DXT formats 2024-10-08 00:25:55 +02:00
WinterSnowfall
1689cacc47 [d3d8] Stub ValidatePixelShader and ValidateVertexShader 2024-10-08 00:25:55 +02:00
WinterSnowfall
66bd9ec4dd [d3d8] Always forward SetRenderTarget calls to D3D9 2024-10-08 00:25:55 +02:00
WinterSnowfall
8c54969552 [d3d8] Skip stride updates for null buffers in SetStreamSource 2024-10-08 00:25:55 +02:00
WinterSnowfall
088cf45439 [d3d9] Validate 0 valued back buffer dimensions for fullscreen mode 2024-10-08 00:25:55 +02:00
WinterSnowfall
6e0c048b88 [d3d9] Return D3DERR_DEVICELOST on reset failure due to losable resources 2024-10-08 00:25:55 +02:00
WinterSnowfall
912a530d1c [d3d9] Enforce various CheckDeviceMultiSampleType validations 2024-10-08 00:25:55 +02:00
WinterSnowfall
eae12e6f23 [d3d8] Cache all back buffers for additional swapchains 2024-10-08 00:25:55 +02:00
WinterSnowfall
bc78fc6ed0 [d3d8] Validate D3D8 present params before conversion 2024-10-08 00:25:55 +02:00
WinterSnowfall
4a8ba388ff [d3d8] Validate CheckDeviceType windowed calls similarly to fullscreen 2024-10-08 00:25:55 +02:00
WinterSnowfall
653559979c [d3d8] Fix LookupSubresource texture type typo 2024-10-08 00:25:55 +02:00
Philip Rebohle
7935f3934f [dxvk] Sanitize sampler LOD range
Silences a validation error in Dishonored 2. At least on AMD,
MinLOD takes precedence over MaxLOD, so let's do the same.
2024-10-07 19:34:02 +02:00
Philip Rebohle
571a2d5811 [dxvk] Tweak staging memory allocation behaviour 2024-10-07 13:32:46 +02:00
Philip Rebohle
813524c146 [d3d11] Remove texel buffer path for ClearUAV
Instead, recreate the image with the given view format as
necessary. Most of the time we will not actually need this.
2024-10-06 08:47:42 +02:00
Philip Rebohle
851f02fa58 [dxvk] Actually apply new create flags when relocating image
Fixes a derp that leads to validation errors when adding view formats.
2024-10-06 08:47:42 +02:00
WinterSnowfall
36907ec01c [d3d8] Adjust shader handles to skip 0x0001 2024-10-05 20:03:05 +02:00
WinterSnowfall
980a8d185c [d3d9] Use D24X8 for D3DFMT_UNKNOWN depth stencils 2024-10-05 20:03:05 +02:00
WinterSnowfall
4f90ad46b9 [d3d8] Validate D3D9 auto depth stencil query 2024-10-05 20:03:05 +02:00
WinterSnowfall
1675aea857 [d3d8] CopyRects validation tweaks 2024-10-05 20:03:05 +02:00
WinterSnowfall
b13b875ca6 [d3d8] Rework D3D8 device GetInfo implementation 2024-10-05 20:03:05 +02:00
WinterSnowfall
bbe82aa534 [d3d9] Fix (most) cursor-related Wine tests 2024-10-05 18:27:19 +02:00
WinterSnowfall
7ff5321910 [d3d9] Implement a software cursor 2024-10-05 18:27:19 +02:00
WinterSnowfall
87a7882812 [d3d8] Automatically capture state on state block creation 2024-10-05 17:58:04 +02:00
WinterSnowfall
050886d08a [d3d8] Capture VB stream state in D3D8 state blocks 2024-10-05 17:58:04 +02:00
WinterSnowfall
9d19fa18a7 [d3d9] Set D3DRS_POINTSIZE_MIN to 0.0f in D3D8 compatibility mode 2024-10-05 17:58:04 +02:00
Philip Rebohle
329d9a0bb2 [dxvk] Add support for drawing a software cursor 2024-10-04 19:10:14 +02:00
Philip Rebohle
4420c39b62 [dxvk] Factor out swapchain blitter texture uploads 2024-10-04 19:10:14 +02:00
Philip Rebohle
dbaa4d8df4 [dxvk] Add blending toggle to swap chain blitter pipelines 2024-10-04 19:10:14 +02:00
Philip Rebohle
836e990dc5 [dxvk] Correctly use VK_SHARING_MODE_CONCURRENT for buffers
Fixes some out-of-spec behaviour introduced with the global buffer rework.
2024-10-04 18:49:23 +02:00
Philip Rebohle
a278d6bf1d [d3d11] Implement sequential swap effects 2024-10-04 12:58:55 +02:00
Philip Rebohle
c9ec2eeab2 [dxvk] Ensure image is in correct layout for invalidation
Otherwise, layout tracking might track a dead image and get confused.
2024-10-04 12:58:55 +02:00
Philip Rebohle
2af3fde5f2 [d3d9] Remove additional swap chain context 2024-10-04 12:58:55 +02:00
Philip Rebohle
172d3450d1 [d3d11] Rename EmitCsChunkExternal for consistency 2024-10-04 12:58:55 +02:00
Philip Rebohle
c678e8c803 [d3d11] Remove additional swap chain context
Do everything on the main context instead. Also only
present once regardless of sync interval.
2024-10-04 12:58:55 +02:00
Philip Rebohle
129efdaba6 [d3d11] Do not use separate context to initialize back buffers 2024-10-04 12:58:55 +02:00
Philip Rebohle
89ebabd8fd [dxgi] Enable frame rate limit for SyncInterval > 1 in windowed mode 2024-10-04 12:58:55 +02:00
Philip Rebohle
bf9dfc77ce [dxvk] Add context method for WSI synchronization
Mostly convenience, but we do want to get rid of Begin/EndRecording
at some point.
2024-10-04 12:58:55 +02:00
Philip Rebohle
63b200f08d [dxvk] Reimplement HUD rendering to use Vulkan directly
And change how rendering works in general so that we emit fewer
draw calls.
2024-10-04 12:58:55 +02:00
Philip Rebohle
b35c0bce4f [dxvk] Always enable multiDrawIndirect and shaderDrawParameters features 2024-10-04 12:58:55 +02:00
Philip Rebohle
46f10c8fd5 [dxvk] Add command list parameter to dispatch-related functions 2024-10-04 12:58:55 +02:00
Philip Rebohle
7d31a7f16f [dxvk] Add command list parameter to some query-related functions
And reintroduce cmdResetQueryPool.
2024-10-04 12:58:55 +02:00
Philip Rebohle
4ce200bcae [dxvk] Add command list parameter to cmdBindDescriptorSet(s) 2024-10-04 12:58:55 +02:00
Philip Rebohle
aa162365ce [dxvk] Add command list parameter to cmdPushConstants
We want to be able to invoke compute shaders during init commands.
2024-10-04 12:58:55 +02:00
Philip Rebohle
207e15eb24 [dxvk] Refactor swap chain blitter to use plain Vulkan
Temporarily disable the HUD until that is refactored too.
2024-10-04 12:58:55 +02:00
Philip Rebohle
1c06431e18 [dxvk] Add method to use a context's command list directly
Also provide the descriptor pool for convenience.
2024-10-04 12:58:55 +02:00
Philip Rebohle
09284988ff [hud] Show memory used percentage relative to budget 2024-10-03 23:47:56 +02:00
Philip Rebohle
0c49e30882 [dxvk] Add memory budget to memory stats 2024-10-03 23:47:56 +02:00
Philip Rebohle
513312885e [dxvk] Use actual memory budget if provided by the implementation
For now, this is only used for the heuristic on when to aggressively
free empty chunks and replaces the 80% heap size heuristic.

Periodically updates the memory budget from the worker thread.
2024-10-03 23:47:56 +02:00
Robin Kertels
7d05a99640 [d3d9] Fix StretchRect fast-path resolve 2024-10-03 00:06:51 +02:00
Robin Kertels
4807af01ad [d3d9] Resolve whole image in StretchRect
Fixes a validation error in Sims 4.
2024-10-02 20:22:37 +02:00
Philip Rebohle
1443e22626 [d3d11] Fix derp with anisotropy option
Fixes #4313.
2024-10-02 11:02:06 +02:00
Philip Rebohle
90b036f550 [dxvk] Fix undefined behaviour move 2024-09-30 17:44:45 +02:00
WinterSnowfall
a5e3f29074 [dxvk] Fix HUD memory chunk colors on UMA 2024-09-30 14:28:44 +02:00
Philip Rebohle
e83446f5c9 [d3d11] Fix remaining synchronization issues with CUDA interop 2024-09-30 10:29:27 +02:00
Philip Rebohle
c26c21edb4 [d3d11] Lock buffers in place when used with CUDA interop 2024-09-30 10:29:27 +02:00
Philip Rebohle
11f8dc0818 [dxvk] Add functions to lock in and query GPU buffer addresses 2024-09-30 10:29:27 +02:00
Philip Rebohle
9f0bd8e17f [d3d11] Lock textures in place when used with CUDA interop
Prevents images from being relocated by the backend.
2024-09-30 10:29:27 +02:00
Philip Rebohle
c59d6bd12c [dxvk] Add flag to ensure stable image GPU addresses 2024-09-30 10:29:27 +02:00
Philip Rebohle
438a08f87c [d3d11] Add functions to emit externally generated CS chunks 2024-09-30 10:29:27 +02:00
Philip Rebohle
abd888a0bb [dxvk] Clean up check whether buffer can be relocated 2024-09-30 10:29:27 +02:00
Philip Rebohle
b164d6e2a7 [d3d9] Do not proactively enable meta copy usage flags
Same as the corresponding D3D11 change, let the backend deal with this
when necessary.
2024-09-30 10:29:27 +02:00
Philip Rebohle
5f3fa9e423 [d3d11] Do not proactively enable meta copy usage flags
Instead, let the backend deal with this and recreate the image as necessary.
2024-09-30 10:29:27 +02:00
Philip Rebohle
2fa773e791 [dxvk] Bump maximum sampler count to 4000
All sampler allocations go through the pool now, so we can do this.
2024-09-30 10:29:27 +02:00
Philip Rebohle
150c40280f [dxvk] Get rid of internal blit samplers 2024-09-30 10:29:27 +02:00
Philip Rebohle
67d1285b08 [dxvk] Refactor meta blits 2024-09-30 10:29:27 +02:00
Philip Rebohle
58dab7e8c6 [dxvk] Refactor mip generation 2024-09-30 10:29:27 +02:00
Philip Rebohle
8c67af680c [dxvk] Refactor meta resolves 2024-09-30 10:29:27 +02:00
Philip Rebohle
2c176f4950 [dxvk] Refactor meta image copies 2024-09-30 10:29:27 +02:00
Philip Rebohle
ae90e74a5a [dxvk] Introduce concept of transfer-only views 2024-09-30 10:29:27 +02:00
Philip Rebohle
fd439c3e54 [dxvk] Ensure image compatibility for packed depth-stencil copies 2024-09-30 10:29:27 +02:00
Philip Rebohle
56a07b5bd0 [dxvk] Add function to recreate image views with guaranteed compatibility 2024-09-30 10:29:27 +02:00
Philip Rebohle
bfbb7987b2 [dxvk] Add functions to recreate images with additional usage info
Useful when we don't know in advance which usage flags are required
and don't want to set them preemptively for performance reasons.
2024-09-30 10:29:27 +02:00
Philip Rebohle
53f14e2914 [dxvk] Add functions to move resources to a different allocation
Basically a batched copy to use when one or more resources are being
recreated for any reason.
2024-09-30 10:29:27 +02:00
Philip Rebohle
ae3a9f595e [dxvk] Allow larger chunks on small heaps
Effectively doubles the size of HVV chunks to 32 MiB on systems that
do not have ReBAR enabled. 16 MiB is too small for some use cases.
2024-09-29 22:07:30 +02:00
Philip Rebohle
e6f89062f5 [d3d9] Ensure that we stay below the maximum sampler count 2024-09-28 20:21:06 +02:00
Philip Rebohle
07dfeeb319 [d3d9] Move building sampler key to CS thread
All this bit twiddling is a bit slow. Introduces another structure
containing a minimal amount of sampler parameters taken from the
raw D3D9 state.
2024-09-28 20:21:06 +02:00
Philip Rebohle
543b5c7af8 [d3d9] Optimize sampler state decoding
This code is rather hot now, so make sure it's fast.
2024-09-28 20:21:06 +02:00
Philip Rebohle
c7dab6a442 [d3d9] Remove internal sampler pool
We have a sampler pool in the backend now, let's use it.
2024-09-28 20:21:06 +02:00
Philip Rebohle
707ddd63a1 [dxvk] Add stat counter for samplers 2024-09-28 20:21:06 +02:00
Philip Rebohle
4635397bb1 [dxvk] Implement sampler pool
Deduplicates redundant sampler objects and makes sampler creation
as well as lifetime tracking a bit more efficient.
2024-09-28 20:21:06 +02:00
Philip Rebohle
5f9f43e658 [util] Add helpers to encode or decode fixed-point numbers 2024-09-28 20:21:06 +02:00
Philip Rebohle
b4e69dce76 [dxvk] Remove DxvkImageViewCreateInfo 2024-09-28 01:50:23 +02:00
Philip Rebohle
8195bea63e [dxvk] Remove DxvkBufferViewCreateInfo
Use the new key struct directly to avoid unnecessary struct conversion.
2024-09-28 01:21:07 +02:00
Philip Rebohle
b0d0959329 [dxvk] Remove DxvkDataBuffer
Unused.
2024-09-28 01:06:57 +02:00
Philip Rebohle
1cefe90ce7 [d3d11] Don't use data buffer for small buffer updates
Embed an array instead and lower the size threshold.
2024-09-28 01:05:40 +02:00
Philip Rebohle
01a7457a6f [dxvk] Remove createImageView function
Use the image's method instead, like we already do for buffers.
2024-09-28 00:03:56 +02:00
Paul Gofman
a172cab34f [dxgi] Delay qualifying foreground loss as occlusion 2024-09-27 18:15:24 +02:00
Philip Rebohle
4ed50ec6be [d3d9] Fix UP buffer allocation 2024-09-27 12:55:59 +02:00
Philip Rebohle
78f5136fde [dxvk] Fix image view swizzling 2024-09-26 17:42:02 +02:00
Philip Rebohle
5e5c283149 [d3d11] Always use fast MAP_WRITE_DISCARD path on deferred contexts
... but keep the SingleUse option as-is anyway because games do not release
their command lists after submission and end up wasting massive amounts of
memory.
2024-09-26 17:37:50 +02:00
Philip Rebohle
39f50999a3 [d3d11] Cache raw mapped pointer rather than allocation object
Reduces ref counting overhead again and matches previous behaviour.

We should probably do something about the possible case of deferred context
execution with MAP_WRITE_DISCARD followed by MAP_WRITE_NO_OVERWRITE on the
immediate context, but we haven't seen a game rely on this yet.
2024-09-26 17:37:50 +02:00
Philip Rebohle
50878f2846 [dxvk] Add function to invalidate images 2024-09-26 17:37:50 +02:00
Philip Rebohle
347925c8b7 [dxvk] Remove legacy DxvkMemory class 2024-09-26 17:37:50 +02:00
Philip Rebohle
25076d9220 [dxvk] Rework image view creation 2024-09-26 17:37:50 +02:00
Philip Rebohle
713b76bea5 [dxvk] Rework image creation
Uses DxvkResourceAllocation to manage image backing storage,
which will allow invalidating images in the future.
2024-09-26 17:37:50 +02:00
Philip Rebohle
d7e1794e29 [dxvk] Add function to import existing Vulkan image 2024-09-26 17:37:50 +02:00
Philip Rebohle
eec4f0fb35 [dxvk] Implement sparse image creation in allocator 2024-09-26 17:37:50 +02:00
Philip Rebohle
bcd12a5b56 [dxvk] Refactor sparse page table initialization for images 2024-09-26 17:37:50 +02:00
Philip Rebohle
0f23a17d8f [dxvk] Refactor sparse page allocation
Uses the new allocator directly.
2024-09-26 17:37:50 +02:00
Philip Rebohle
af4a2f7973 [dxvk] Introduce DxvkResourceMemoryInfo
And replace the old sparse thing.
2024-09-26 17:37:50 +02:00
Philip Rebohle
bbd2461c8f [dxvk] Reimplement sparse buffer support 2024-09-26 17:37:50 +02:00
Philip Rebohle
1ba6b81901 [dxvk] Reimplement imported buffers 2024-09-26 17:37:50 +02:00
Philip Rebohle
5263307c4a [dxvk] Improve lifetime tracking logic
Reduces ref counting overhead on the CS thread a bit.
2024-09-26 17:37:50 +02:00
Philip Rebohle
7ac9918b39 [hud] Add cache statistics to detailed memory item 2024-09-26 17:37:50 +02:00
Philip Rebohle
9cf72b5b19 [dxvk] Implement basic pool balancing for shared allocation cache
This makes the entire cache available to all allocation sizes rather than
having fixed-size pools for every allocation size. Improves hit rate in
games that primarily use one constant buffer size.
2024-09-26 17:37:50 +02:00
Philip Rebohle
428b1087a0 [dxvk] Implement shared cache statistics 2024-09-26 17:37:50 +02:00
Philip Rebohle
2722a41675 [dxvk] Implement shared allocation cache
Allows refilling local caches in constant time.
2024-09-26 17:37:50 +02:00
Philip Rebohle
9a51849920 [d3d11] Use allocation cache for dynamic buffers 2024-09-26 17:37:50 +02:00
Philip Rebohle
4db0007af3 [dxvk] Implement local allocation cache 2024-09-26 17:37:50 +02:00
Philip Rebohle
93547aec8d [dxvk] Do not track buffer view objects
No longer necessary as they have the same lifetime as the
parent buffer now. Only track the buffers themselves.
2024-09-26 17:37:50 +02:00
Philip Rebohle
088ba404a6 [dxvk] Rework buffer view creation 2024-09-26 17:37:50 +02:00
Philip Rebohle
1fd3c8040d [dxvk] Remove DxvkBufferAllocation 2024-09-26 17:37:50 +02:00
Philip Rebohle
14990dbb49 [dxvk] Rework buffer slice allocation
Temporary solution that hits the allocator on every single invalidation,
which isn't great but will do for now.
2024-09-26 17:37:50 +02:00
Philip Rebohle
ec2f43e5e3 [dxvk] Make DxvkResource manage its own destruction
Necessary for actual resource refactors. We want view objects
to use the resource's reference count wehenever possible.
2024-09-26 17:37:50 +02:00
Philip Rebohle
10164fdf4d [dxvk] Store GPU address for allocated chunk memory 2024-09-26 17:37:50 +02:00
Philip Rebohle
51649f6da6 [dxvk] Add function to create image resource 2024-09-26 17:37:50 +02:00
Philip Rebohle
5813e7c031 [dxvk] Add function to create buffer resource 2024-09-26 17:37:50 +02:00
Philip Rebohle
00f7545d15 [dxvk] Add helper to get memory type mask for buffer usage 2024-09-26 17:37:50 +02:00
Philip Rebohle
e80dd6db5f [dxvk] Cache memory type mask with global buffer support 2024-09-26 17:37:50 +02:00
Philip Rebohle
3bee390d91 [dxvk] Don't log memory errors prematurely
Fallback allocations are a thing.
2024-09-26 17:37:50 +02:00
Philip Rebohle
f36a536288 [dxvk] Use DxvkResourceAllocation internally
Changes DxvkMemory to be nothing more than a wrapper.
2024-09-26 17:37:50 +02:00
Philip Rebohle
5dd7a29261 [dxvk] Introduce DxvkResourceAllocation 2024-09-26 17:37:50 +02:00
Philip Rebohle
4064c89e8c [dxvk] Remove legacy buffer renaming interface 2024-09-26 17:37:50 +02:00
Philip Rebohle
6f6e75b4b8 [d3d9] Use DxvkBufferAllocation where appropriate 2024-09-26 17:37:50 +02:00
Philip Rebohle
8e45a60542 [d3d11] Use DxvkBufferAllocation where appropriate 2024-09-26 17:37:50 +02:00
Philip Rebohle
eae66201f6 [dxvk] Use DxvkBufferAllocation for HUD rendering 2024-09-26 17:37:50 +02:00
Philip Rebohle
75dadf2c1c [dxvk] Use DxvkBufferAllocation in swap chain blitter 2024-09-26 17:37:50 +02:00
Philip Rebohle
5c2f56c9cc [dxvk] Introduce DxvkBufferAllocation
For now, this is merely a wrapper around the existing buffer slice
struct in order to allow easier refactoring.
2024-09-26 17:37:50 +02:00
Philip Rebohle
d0832f8431 [vulkan] Move stage and access mask definitions to header 2024-09-26 17:37:50 +02:00
Philip Rebohle
7ec75aaf81 [util] Make likely/unlikely less annoying to use 2024-09-26 17:37:50 +02:00
Philip Rebohle
888906a6da [util] Add some functionality to smart pointer
Basically lets us deal with objects that manage their own destruction,
which ideally shold be all of them at some point.

Also adds some missing comparison operators.
2024-09-26 17:37:50 +02:00
Philip Rebohle
06baa48c2b [dxvk] Align allocation size to create global buffer 2024-09-26 13:13:48 +02:00
Philip Rebohle
401ca41091 [dxvk] Do not always keep an empty chunk around
Outdated thinking, we have a 20 second timer on this which should
be more than enough to ensure we're not spamming device memory
allocations.
2024-09-26 13:13:48 +02:00
Philip Rebohle
3cd7e3efb5 [dxvk] Tweak memory allocation behaviour on mapped memory types 2024-09-26 13:13:48 +02:00
Philip Rebohle
5c8728abd2 [hud] Use different colors to highlight mapped or non-mapped allocations
Useful on UMA systems or when we have to fall back to system memory.
2024-09-26 13:13:48 +02:00
Philip Rebohle
d00ca261af [dxvk] Use worker to update adapter's memory statistics
Takes a bunch of pointer indirections and atomics off the hot path.
2024-09-26 13:13:48 +02:00
Philip Rebohle
27088beea8 [dxvk] Use worker thread to periodically free unused memory
System memory allocations typically peak very high while loading, but
just sit there unused afterwards. This allows us to free them based
on when they have last been used.

Works well in practice since best-fit avoids using empty chunks as much
as possible.
2024-09-26 13:13:48 +02:00
Philip Rebohle
e1fd2bff2c [dxvk] Rewrite memory allocator
Uses a single allocator pair per memory type in order to make memory
allocations on the entire memory pool faster, and further reduce
fragmentation by applying the best fit strategy to the whole memory
pool.
2024-09-26 13:13:48 +02:00
Philip Rebohle
3a4dadb528 [dxvk] Add chunk concept to page allocator
This allows the allocator to operate on the entire allocated memory pool.
2024-09-26 13:13:48 +02:00
Philip Rebohle
266b99ad8d [hud] Add HUD item to visualize memory chunk allocation 2024-09-26 13:13:48 +02:00
Philip Rebohle
f679d7d90f [dxvk] Add detailed allocation statistics 2024-09-26 13:13:48 +02:00
Philip Rebohle
b46ef2ceff [dxvk] Move memory statistics from memory types to heaps 2024-09-26 13:13:48 +02:00
Philip Rebohle
35fea6475d [dxvk] Tune small buffer allocation sizes
The pool allocator works on powers of two, so buffers should too.
2024-09-26 13:13:48 +02:00
Philip Rebohle
3faa1a76da [dxvk] Simplify memory chunk allocation
Reduces overall waste of memory by reusing already allocated
chunks more aggressively.
2024-09-26 13:13:48 +02:00
Philip Rebohle
661385584a [dxvk] Use new allocators for chunk suballocation 2024-09-26 13:13:48 +02:00
Philip Rebohle
5efaa06c61 [dxvk] Add new page allocator implementation 2024-09-26 13:13:48 +02:00
Philip Rebohle
1eec969448 [util] Add 64-bit lzcnt 2024-09-26 13:13:48 +02:00
Philip Rebohle
343af21594 [build] Disable assertions for release builds 2024-09-26 13:13:48 +02:00
Philip Rebohle
0cf05780ab [meta] Release 2.4.1 2024-09-26 12:09:26 +02:00
Philip Rebohle
15365f2d82 [d3d11] Synchronize shared texture initialization 2024-09-26 08:21:43 +02:00
WinterSnowfall
97091aad39 [util] Enable legacy DISCARD for Rayman 3 2024-09-26 06:48:13 +02:00
WinterSnowfall
a7b3b1e3a4 [d3d8] Add an option to respect DISCARD only for dynamic write-only buffers 2024-09-26 06:48:13 +02:00
WinterSnowfall
4fad20d77c [d3d8] Relax viewport validation in windowed mode 2024-09-25 20:46:48 +02:00
琴梨梨OvO
bb6d1b3b4c [util]Add support for Time Leap Paradise 2024-09-25 19:54:24 +02:00
Robin Kertels
f5ca3cf5df [d3d9] ResolveZ: Only copy aspects that both images support 2024-09-25 00:32:13 +01:00
Robin Kertels
d7c2e3ac76 [d3d9] Use correct aspect mask when blitting depth stencil textures
We don't want to blit stencil when the D3D9 format doesn't have
stencil.
2024-09-25 00:32:13 +01:00
Robin Kertels
ca3aa2014b [d3d9] Improve comment about synchronization with ProcessVertices 2024-09-22 22:53:55 +02:00
Robin Kertels
1d49f247ac [d3d9] Remove incorrect early-exit
The same texture could be bound to
multiple slots and if the shader doesn't
use the lower index texture, we'd never
end up uploading it.
2024-09-22 22:53:55 +02:00
Robin Kertels
ef8bad33a5 [d3d9] Optimize late buffer uploads
... similar to what we're doing for textures.
2024-09-22 22:53:55 +02:00
Blisto91
5a08b3c451 [util] Cap fps for F.E.A.R 1 & expansions
Visual glitches can occur at very high fps
2024-09-22 21:07:08 +02:00
Robin Kertels
04ad98690b [d3d9] Add SWVP HUD item 2024-09-22 21:03:23 +02:00
Robin Kertels
033104f335 [d3d9] Cleanup buffer memory flag selection 2024-09-22 21:03:23 +02:00
Robin Kertels
5bb8d09a96 [d3d9] Always use per-draw buffer uploads on pure SWVP devices 2024-09-22 21:03:23 +02:00
WinterSnowfall
97fb6e4f6d [d3d9] Clean up supported formats from GetUnsupportedFormatInfo 2024-09-22 20:51:15 +02:00
WinterSnowfall
7985ac9cdb [d3d9] Add R16 and AL16 as known unsupported formats 2024-09-22 20:51:15 +02:00
Blisto91
e687303197 [util] Cap Prince of Persia (2008) max fps
Game can get stuck when loading at very high fps
2024-09-22 17:47:51 +02:00
Robin Kertels
07e7781c0b [d3d9] Only add meta image usage after determining layout 2024-09-22 15:48:18 +02:00
WinterSnowfall
c7cf0a7368 [d3d8] Respect D3DCREATE_MULTITHREADED and make d3d8 thread safe 2024-09-21 16:05:25 +02:00
Robin Kertels
c8791a6ba5 [d3d9] Don't emit 1-sized vector type in SWVP Emu
Fixes a validation error.
2024-09-20 12:57:11 +02:00
Robin Kertels
900edf55b5 [d3d9] Only create sampling image views if the image supports sampling
Fixes validation error
2024-09-20 12:57:11 +02:00
Robin Kertels
46e8161649 [d3d9] Enable shaderInt8 for ProcessVertices 2024-09-20 12:57:11 +02:00
Robin Kertels
828aaa5cdd [d3d9] Add missing TRANSFER_SRC usage for swapchain helper images 2024-09-20 12:57:11 +02:00
Philip Rebohle
43c27670ef [dxvk] Fix buffer view stuff again
Testing fallback paths that we only ever hit in scenarios without validation
output sure is fun....
2024-09-20 02:00:50 +02:00
Philip Rebohle
dd8af9da78 [dxvk] Fix buffer view derp systems not supporting maintenance5 2024-09-20 01:25:06 +02:00
Robin Kertels
80e950ac32 [util] Fix small_vector move
... again. We can only move over the ptr
if the other small_vector has MORE than N
elements, otherwise it will still use the local array.
2024-09-20 01:20:25 +02:00
Robin Kertels
2f9ce66879 [util] Fix small_vector move constructor 2024-09-19 20:56:09 +02:00
Philip Rebohle
398c198df6 [dxvk] Fix BDA validation error with dedicated allocations 2024-09-19 18:32:40 +02:00
Philip Rebohle
18ecc17e59 [dxvk] Remove unused discardBuffer method
Unused and not safe to use.
2024-09-18 15:55:57 +02:00
Philip Rebohle
c8410e578e [d3d11] Enable device address usage for non-mappable buffers
NVAPI queries the GPU address of certain resources in a way that could
break otherwise.
2024-09-18 15:55:57 +02:00
Philip Rebohle
fb552db65f [dxvk] Do not invalidate buffers that allow querying the device address 2024-09-18 15:55:57 +02:00
Philip Rebohle
ddb59ae394 [dxvk] Add usage property to buffer views
And pass it to the Vulkan driver depending on maintenance5 support.
2024-09-18 15:55:57 +02:00
Philip Rebohle
ab557a2eed [dxvk] Use global buffer whenever possible
Drastically reduces the number of Vulkan buffer objects allocated.
2024-09-18 15:55:57 +02:00
Philip Rebohle
901861c20b [dxvk] Create global buffer for allocated memory chunks 2024-09-18 15:55:57 +02:00
Blisto91
11ec603540 [util] Enable cachedDynamicBuffers for Battle Mages
Helps CPU bound performance
2024-09-18 00:25:05 +02:00
Paul Gofman
ed9ffa6584 [dxgi] Leave fullscreen mode when window looses focus 2024-09-18 00:19:56 +02:00
Paul Gofman
758dc805bb [dxgi] Prevent recursive fullscreen mode change. 2024-09-18 00:19:56 +02:00
WinterSnowfall
5cf0783edb [d3d8] Clean up D3D9 shaders on D3D8 device release 2024-09-17 19:45:18 +02:00
Robin Kertels
010738c107 [d3d9] Add HUD item for FF shaders 2024-09-17 18:30:27 +02:00
WinterSnowfall
89e190b771 [d3d8] Ensure d3d9 interface release 2024-09-17 18:30:00 +02:00
WinterSnowfall
84a8ea9d4a [d3d8] Remove some unneeded explicit ptr use 2024-09-17 18:30:00 +02:00
WinterSnowfall
9f8832dd14 [d3d8] Improve handling of failed d3d9 calls 2024-09-17 18:30:00 +02:00
Blisto91
f3fa4b102a [meta] Note DLLs need native override in readme 2024-09-17 02:08:28 +02:00
WinterSnowfall
0a2f2275da [d3d8] Add a framecap for Chrome: Gold Edition 2024-09-14 23:52:20 +02:00
Philip Rebohle
04cf0008a0 [dxvk] Correctly enable VK_EXT_line_rasterization
Oversight, and fixes a validation error.
2024-09-13 11:58:11 +02:00
WinterSnowfall
8e03b64ca4 [d3d8] Validate viewport dimensions on SetViewport 2024-09-12 16:39:40 +02:00
Robin Kertels
903f1af176 [d3d9] Fix PresentGDI 2024-09-12 15:39:21 +02:00
Kacper Michajłow
26a14c5175
[util] Fix GetEnvironmentVariableW usage 2024-09-12 00:04:49 +02:00
WinterSnowfall
3e26958906 [util] Add a framecap for Pandora Tomorrow 2024-09-12 00:02:34 +02:00
llyyr
1a1c3a4202 [d3d9,d3d11] recreate swapchain on VK_SUBOPTIMAL_KHR
The vulkan wayland wsi returns suboptimal when the window is
fullscreened and not directly scanned out, and there are modifiers
available that would allow the window to be directly scanned out.
Recreate the swapchain if we receive suboptimal result.

This allows us recreate the swapchain to use a modifier that allows
direct scan-out under winewayland on wayland compositors.
2024-09-11 16:38:26 +02:00
Philip Rebohle
c1a25df468 [dxvk] Fix some logic errors around sysmem chunk size 2024-09-11 15:21:03 +02:00
Philip Rebohle
565ec7e0d3 [dxvk] Remove dxvk.maxChunkSize option 2024-09-09 18:45:34 +02:00
Philip Rebohle
619b9b12c2 [dxvk] Implement dynamically growing chunk size
May reduce memory footprint for launchers.
2024-09-09 18:45:34 +02:00
WinterSnowfall
63506ee1ff [util] Enable cachedDynamicBuffers for Steel Soldiers and FIFA 2003 2024-09-08 19:26:46 +02:00
WinterSnowfall
22ff53013a [d3d8] Ignore unsupported D3DPRESENT_RATE_UNLIMITED 2024-09-08 19:25:16 +02:00
Billy Laws
9077e5212d [util] Use cdecl calling convention for __wine_dbg_output
This matches wine's definition, fixes crashes when wine is built with clang.
Since __cdecl isn't defined for non-windows targets ifdef this needs all
dbg callback uses to be ifdefed out.
2024-09-07 19:44:36 +02:00
Robin Kertels
daccde7643 [d3d9] Don't set IMAGE_USAGE_SAMPLED_BIT for non-msaa depth stencil surfaces 2024-09-04 22:17:10 +00:00
Robin Kertels
7f8cfec46f [d3d9] Always set IsAttachmentOnly for CreateOffscreenPlainSurfaceEx
Surfaces cannot be bound as textures.
2024-09-04 22:17:10 +00:00
Robin Kertels
1b172344eb [d3d9] Remove redundant scene check in StretchRect 2024-09-04 22:17:10 +00:00
Robin Kertels
11efd5092e [d3d9] Handle remaining edge cases of Discard & Lockable 2024-09-04 22:17:10 +00:00
WinterSnowfall
2c23e462b3 [d3d8] Clamp BaseVertexIndex to INT_MAX during use 2024-09-04 21:11:08 +02:00
Philip Rebohle
d0ea5a4a87 [spirv] Account for unreachable continue blocks
Fixes code gen in the following pattern encountered in Black Ops 3:

loop
  break
endloop

We cannot eliminate the loop since we have to adhere to structured
control flow rules, which might be broken if the code inside the
loop was non-trivial.
2024-09-04 02:26:35 +02:00
Philip Rebohle
427e706a40 [util,d3d11] Be more robust against use-after-free
Sims 4 binds an SRV after destroying it, so we need to ensure our internal
view pointers are null or we'll create a problem otherwise.
2024-09-02 22:03:26 +02:00
Philip Rebohle
04d558cf2e [util] Make frame rate limiter enablement heuristic more robust
Allow for more buffering to happen in order to not enable the limiter
too eagerly.
2024-09-02 17:50:47 +02:00
ericzlmd
38308d443e [build] added <algorithm> header for failed subcommand fix - remove_if 2024-08-31 13:23:26 +02:00
Tiagoquix
d31b7997c0 [util] Enable cachedDynamicBuffers for APB:Reloaded
Fixes frametime jumps when shooting.
Discussed on the Discord server.
2024-08-30 20:27:05 +02:00
MickAlmighty
8c58bef9cf [util] Hide Intel for Kena: Bridge of Spirits to skip faulty water rendering path. 2024-08-30 17:39:21 +02:00
Robin Kertels
a5fc08d176 [util] Disable direct buffer mapping for Max Payne 1
Improves performance by avoiding stalls.
2024-08-30 00:37:58 +02:00
Robin Kertels
e4fd9ff16b [d3d11] Always keep barrier control options set by app profile 2024-08-26 23:15:32 +02:00
Robin Kertels
eb8d1885bd [dxgi] Remove emulateUMA option
The option was only used for GTA IV.
It broke and we have a better solution now.
2024-08-24 19:05:44 +02:00
Robin Kertels
9a280b063a [util] Set maxDeviceMemory for GTA IV
... and replace emulateUMA
2024-08-24 19:05:44 +02:00
Philip Rebohle
1c30bc92bb [d3d11] Validate viewport parameters
And skip invalid calls. Fixes Senran Kagura Peach Ball.
2024-08-23 14:39:56 +02:00
Philip Rebohle
6da1ba7cff [dxgi] Avoid reporting large VRAM amounts as a power of two 2024-08-23 01:13:10 +02:00
Philip Rebohle
d89e324bc4 [util] Remove obsolete Metro Exodus EE config
No longer necessary or useful.
2024-08-20 13:33:04 +02:00
Philip Rebohle
be45907479 [dxgi] Under-report iGPU memory if dGPUs are present
Should help games pick the correct GPU on setups with integrated graphics.
2024-08-20 13:33:04 +02:00
Philip Rebohle
02d8fa593b [dxgi] Change reported UMD driver version
Fixes a potential crash in Hunt Showdown.
2024-08-15 22:04:06 +02:00
Philip Rebohle
71e44b380d [util] Enable context lock for EDF6
May or may not fix random crashing.
2024-08-15 20:55:17 +02:00
Philip Rebohle
159f540e10 [dxvk] Bump internal engine version
Due to large shader-related changes.
2024-08-14 22:15:50 +02:00
Philip Rebohle
1e5b78e8ea [d3d9] Enable longMad behaviour by default
And remove the respective config option.
2024-08-14 22:15:50 +02:00
Philip Rebohle
60e04503a6 [d3d11] Enable longMad/longDot behaviour by default
And remove the respective config options.
2024-08-14 22:15:50 +02:00
Philip Rebohle
beaf01ecad [dxbc] Reverse order of long dot products
Matches output of AMD's dxbc compiler this way.
2024-08-14 22:15:50 +02:00
Philip Rebohle
813b653645 [spirv] Implement basic dead code elimination
Fixes invalid SPIR-V in Trails through Daybreak.
2024-08-14 22:15:50 +02:00
Blisto91
6308266a0f [d3d9] Default to Strict floatEmulation for amdvlk 2024.Q3.1
The AMD Linux open source driver now optimizes for the Strict floatEmulation path.
2024-08-13 17:18:34 +02:00
Philip Rebohle
0d0b9eaac1 [util] Enable d3d11.longDot for Trails through Daybreak 2024-08-11 18:30:59 +02:00
Philip Rebohle
4ee907a6df [dxbc,d3d11] Add option to explicitly emit long dot products 2024-08-11 18:30:59 +02:00
Paul Gofman
5c987ea3d1 [d3d9] Handle map failure in texture initializer 2024-08-08 21:42:04 +02:00
Jeff
e38693cdbc [d3d9] Allow querying ID3D9VkInteropTexture from surfaces 2024-08-08 05:25:41 +01:00
Blisto91
7c9e1ed7cd [util] Set maxChunkSize to 1 for Epic Games Launcher
Also move up Battle.net so the launchers are grouped
2024-08-03 14:57:36 +02:00
Blisto91
e2b823b760 [util] Enable cachedDynamicBuffers for Art of Murder
Horrible CPU bound perf
2024-07-31 18:34:39 +02:00
Blisto91
1077d6a67f [util] Set textureMemory to 0 for Operation Racoon City
Works around a crash
2024-07-30 09:15:28 +02:00
Blisto91
33bf09122c [util] Add configs for Splinter Cell Conviction
The game will sometimes black screen upon alt-tab without deviceLossOnFocusLoss.
Spoofing the GPU through dxgi to a known one from its list prevents the System Detection tool from complaining that it is unsupported on some setups.
2024-07-28 23:04:35 +02:00
Eric Sullivan
c26b2ade1d [dxvk] Update shouldSubmit to correctly handle descriptorPoolOverallocation
Currently shouldSubmit will force the dxvk context to be flushed when
too many descriptor pools have been allocated. This heuristic does not
work when VK_NV_descriptor_pool_overallocation is in use because there
will only ever be a single pool.

This change updates the heuristic to use the number of allocated sets
when VK_NV_descriptor_pool_overallocation is in use.
2024-07-25 23:53:03 +02:00
Tobias Jakobi
10ab85c3ba [d3d8] Remove references to d3d8.useShadowBuffers for now
The current D3D8 codebase in DXVK does not implement this
feature, i.e. setting this option is a NOP. It was
implemented in D8VK at some point, but was removed before
the big merge.

Remove any references to avoid confusion.
2024-07-22 00:14:15 +02:00
Robin Kertels
031a98c232 [d3d9] Allow fourcc formats as the source in CheckFormatConversion
The docs say:
"The source format must be a FOURCC format or a valid back buffer format."
2024-07-19 19:25:31 +00:00
Robin Kertels
b7d61b70c1 [d3d9] Use converted format for multiplane formats in CheckFormat 2024-07-19 19:25:31 +00:00
WinterSnowfall
bac7ae2929 [util] Disable countLosableResources for Inquisitor 2024-07-16 16:42:44 +02:00
Felix Klinge
2a2d51e049 changed dxgi.customVendorId to dxgi.hideIntelGpu for Batman Arkham Knight 2024-07-16 16:21:08 +02:00
Felix Klinge
b74725b264 Add Batman Arkham Knight Custom Vendor ID to config to fix the game for Intel GPUs 2024-07-16 16:21:08 +02:00
Robin Kertels
af1ba1b205 [d3d9] FF: Fix return type for lighting op 2024-07-16 16:08:33 +02:00
WinterSnowfall
a8dbbcfa31 [util] Reorder config options by API 2024-07-12 16:42:31 +02:00
Blisto91
ba47af53da [meta] Rearrange readme
Rearrange the readme so the entries are consistently listed in a given section it makes sense. They are ordered from project info, usage, building and native.
2024-07-11 17:49:56 +02:00
Philip Rebohle
008afc1c5f [meta] Release 2.4 2024-07-10 11:56:14 +02:00
WinterSnowfall
d731608d5e [d3d8] Mimic native token allocations 2024-07-10 00:28:10 +02:00
WinterSnowfall
ff137dac9f [d3d8] Implement monotonic state block tokens 2024-07-09 23:20:52 +02:00
Robin Kertels
d456d0b437 [d3d9] StretchRect: Allow using an offscreen surface as dst when stretching 2024-07-09 13:54:59 +00:00
Robin Kertels
cc87870be1 [d3d9] Relax stretch rect check in D3D8 mode 2024-07-09 13:54:59 +00:00
Robin Kertels
a7ae5999a9 [d3d8] Slightly clean up CopyRects 2024-07-09 13:54:59 +00:00
Blisto91
5f9ca08071 [util] Enable deviceLossOnFocussLoss for Rise of Nations
To prevent it from crashing on a alt-tab
2024-07-09 15:42:49 +02:00
4b0c9c611c
[meta] Added d3d8 to list of overrides to create to README 2024-07-08 11:37:02 +01:00
Blisto91
fe9c875fe9 [util] Set cachedDynamicBuffers for The Sims 2 and friends
Helps very low CPU bound performance especially in Castaway Stories.
2024-07-07 14:31:37 +02:00
Blisto91
a63a5753d4 [util] Enable longMad for Tomb Raider Legend
Since the enablement of invariant position by default the game suffers from white flickers on characters when you use the Next Generation Content option
2024-07-07 14:23:11 +02:00
Robin Kertels
5a0f05ae66 [util] Disable counting losables for Battlefield 2 & 2142 2024-07-07 14:21:59 +02:00
WinterSnowfall
6ffd5acefa [util] dxvk.conf cleanup 2024-07-07 14:21:39 +02:00
Robin Kertels
33e7497ef4 [meta] Add Robin Kertels to LICENSE file 2024-07-07 11:51:34 +00:00
Er2
38006e9cda
[dxvk] Add FreeBSD support 2024-07-07 11:22:43 +00:00
Jeff
60e523b4bf
[d3d8] Implement Direct3D 8 Frontend
Co-authored-by: WinterSnowfall <WinterSnowfall@users.noreply.github.com>

## Config Changes

Co-authored-by: Blisto91 <47954800+Blisto91@users.noreply.github.com>
Co-authored-by: simifor <simirmonfor@gmail.com>
2024-07-07 11:10:48 +00:00
WinterSnowfall
ef0c6b6f6f [d3d9] Hardware cursor fixes 2024-07-07 01:32:40 -07:00
Robin Kertels
9b504b506e [d3d9] Rework FF texcoord processing to be more accurate 2024-07-07 01:28:44 -07:00
Blisto91
b2d89db8d8 [util] Disable countLosableResources for Myst V
Works around a crash regression in dxvk 2.3 upon resolution change.
2024-07-05 14:16:18 +02:00
Blisto91
fa5ce49675 [util] Enable longMad for Watch_Dogs 2 and Legion
Works around flickering on characters when a outline or highlight effect is showing.
2024-07-05 13:04:59 +02:00
Robin Kertels
bbe851f6a2 [d3d9] Reduce data copied for SWVP vertex decls 2024-07-05 00:44:28 -07:00
Robin Kertels
7de88ff993 [util] Add move & copy constructors to small_vector 2024-07-05 00:44:28 -07:00
Robin Kertels
ab12ffa0da [d3d9] Use max point size of Vulkan device
The default render state value has to match what we report in the device caps.
Fixes a Wine stateblock test.
2024-07-05 00:44:28 -07:00
Robin Kertels
dc3dd0f88c [d3d9] Ignore the vertex stream offset in StateBlock::Capture
Fixes a Wine test and matches further testing on Windows.
2024-07-05 00:44:28 -07:00
Robin Kertels
da814668bc [d3d9] FF: Prevent specular highlights on the back of geometry
Fixes the Wine test "test_specular_lighting".
2024-07-05 00:44:28 -07:00
Robin Kertels
df9bdfc6ea [util] Return unchanged matrix if matrix cannot be inverted 2024-07-05 00:44:28 -07:00
Robin Kertels
9e422a2b63 [d3d9] Fix default light
Fixes the diffuse alpha and the direction.
2024-07-05 00:44:28 -07:00
Robin Kertels
11db6d691c [d3d9] Fix reference leak in ProcessVertices
Also fixes a Wine test.
2024-07-05 00:44:28 -07:00
Robin Kertels
9c898bd269 [d3d9] Skip presenting if D3D9Swapchain has no associated window 2024-07-05 00:44:28 -07:00
Robin Kertels
175772944c [d3d9] Fix Wine test failures in StretchRect 2024-07-05 00:44:28 -07:00
WinterSnowfall
5ae3cfe402 [d3d9] Fix DF Formats selection logic 2024-07-05 00:43:09 -07:00
WinterSnowfall
b03de97f1b [d3d9] Expose support for D16_LOCKABLE only on AMD 2024-07-05 00:43:09 -07:00
WinterSnowfall
18035820de [d3d9] Remove vestigial D32 support 2024-07-05 00:43:09 -07:00
Łukasz Zając
1783b9591a
[util] Enable 60 FPS lock for WRC4
Fixes an audio issue.
2024-07-04 20:12:08 +02:00
Philip Rebohle
499460184a [build] Zero-pad soversion components as necessary 2024-07-03 13:23:25 +00:00
Philip Rebohle
afbcd94569 [util] Fix up recently added app profiles 2024-06-26 00:44:43 +02:00
Philip Rebohle
86f04a2da3 Revert "[util] Consolidate maxFrameRate options"
This reverts commit 1811f4b995.

The D3D12 Beyond Good and Evil remaster uses the same exe name as the
original D3D9 game, so it turns out the separation was useful after all.
2024-06-26 00:42:31 +02:00
Philip Rebohle
8573190c7d [dxvk] Apply frame rate limiter before signaling frame latency event
Otherwise we add latency for no reason.
2024-06-24 18:12:59 +02:00
Blisto91
fe0e02de18 [util] Set cachedDynamicBuffers for Battle for Middle-Earth 2
Helps slowdowns below 30fps in certain scenarios like when moving the camera over heavy vegetation areas among others
2024-06-22 21:58:16 +02:00
Robin Kertels
3145020a62 [d3d9] Only change vertex offset draw parameters when necessary
... Only change it when the vertex data is actually dynamically uploaded.
2024-06-21 13:18:39 +02:00
WinterSnowfall
e9fc071d95 [d3d9] Validate D3DCREATE_PUREDEVICE usage 2024-06-20 03:34:45 +00:00
Blisto91
a276e13821 [util] Set deviceLossOnFocusLoss for Guild Wars
Works around the game black screening on alt-tab when it is set to fullscreen with a non native resolution
2024-06-19 15:08:37 +02:00
Blisto91
4b4d323ec3 [util] Set cachedDynamicBuffers for Dragonshard
Works around massive FPS decreases in some scenes
2024-06-17 22:49:25 +02:00
Blisto91
d9994665a8 [util] Set strict floatEmulation for New Vegas
Fixes various visual issues with some effects in mods such as New Vegas Reloaded. White spots/shapes, black streaks across the screen (rain?) and probably more.
2024-06-17 22:49:25 +02:00
Blisto91
22b13a94ca [util] Enable deviceLossOnFocusLoss for The Force Unleased
Prevents the game from black screening on each alt-tab
2024-06-16 22:04:22 +02:00
Jeff
3e5eb1660f
[d3d8] Implement Dref scaling and fixed-function depth textures (#3565) 2024-06-14 12:10:49 +02:00
Trevonn
a8710f70a5 [util] Dead Space 2 - Lock to 60 FPS and enable vsync
Similar to the first game it has a poor vsync implementation and physics issues when the frame rate is unlocked.

Locking to 60 FPS and enabling vsync externally provides a better experience after the ingame vsync is disabled
2024-06-13 18:03:12 +02:00
Philip Rebohle
336c9b6acc [dxgi] Allow changing refresh rate even without ALLOW_MODE_SWITCH
Matches Windows behaviour, entering fullscreen state will only prevent
us from changing the display resolution if the flag is not set.
2024-06-12 17:33:41 +02:00
Blisto91
018db92342 [util] Disable Crysis 1 refresh rate fps limiter
Game bug in its d3d10 mode where it selects the lowest supported refresh rate.
2024-06-11 15:45:30 +02:00
Philip Rebohle
51f2e246fa [util,dxvk] Limit frame rate based on deadline
This should work better now that present_wait is universally supported.
2024-06-11 15:45:17 +02:00
Philip Rebohle
1811f4b995 [util] Consolidate maxFrameRate options 2024-06-11 15:45:17 +02:00
Philip Rebohle
5674abe483 [d3d9] Limit frame rate to display refresh as necessary 2024-06-11 15:45:17 +02:00
Philip Rebohle
1c198dcd48 [dxgi] Limit frame rate to display refresh as necessary 2024-06-11 15:45:17 +02:00
Philip Rebohle
379346751a [util] Implement refresh rate heuristic for frame rate limiter 2024-06-11 15:45:17 +02:00
Philip Rebohle
b4c4c9e683 [util] Remove useless vsync parameter from FPS limiter 2024-06-11 15:45:17 +02:00
Sanakan8472
2188caae8e Fix GLFW exception at startup
`GlfwWsiDriver::getInstanceExtensions` was creating an `std::vector` with a size argument in the ctor but then used `push_back` instead of filling the pre-allocated elements, leading to a bunch of nullptr entries at the start that caused an exception later on when accessed.
2024-06-10 13:41:50 +02:00
Blisto91
8d965359a5 [util] Set longMad for Watch_Dogs
Works around flickering on some objects such as the blue light arrow on lowering gates
2024-06-06 19:01:42 +02:00
Philip Rebohle
fd978704fb [dxvk] Add dxvk.deviceFilter config option 2024-06-05 00:49:26 +02:00
Tiagoquix
ee18aecb8a
[util] Add dxvk.maxChunkSize 1 for Origin Web Helper Service and Ubisoft Connect (UPlay) (#4047)
* Add dxvk.maxChunkSize 1 to Ubisoft Connect (UPlay)

* Add Origin Web Helper Service and fix Rockstar Games entries

* Revert Rockstar changes, improve Origin and Ubisoft
2024-06-02 20:08:52 +02:00
Blisto91
c2fd91f835 [util] Set longMad for Ghostbusters Remastered
Works around flickering on character faces
2024-06-02 11:10:13 +02:00
Tiagoquix
79eea564fb Add dxvk.maxChunkSize 1 to Origin 2024-05-31 23:46:26 +02:00
Robin Kertels
7df8017e46 [d3d9] FF: Apply transform flags count to generated texture coords
... and fix cases where projection doesn't get applied.
2024-05-27 20:52:32 +00:00
WinterSnowfall
c98152683f [d3d9] Tweak VCache query results 2024-05-27 19:53:19 +02:00
Blisto91
890ad3f47f [CI] Update CI actions 2024-05-27 19:38:16 +02:00
Robin Kertels
60cfafe027 [d3d9] Fix strange type in dynamic vertex upload 2024-05-26 04:58:47 +00:00
Robin Kertels
889802887f [d3d9] Rework uploading dynamic sysmem buffers at draw time
... and handle mismatching vertex sizes and vertex strides.
2024-05-23 16:44:49 +02:00
WinterSnowfall
a1ce690c5c [d3d9] Determine DF format support in the options parser 2024-05-23 16:37:09 +02:00
WinterSnowfall
07d007c642 [d3d9] Use customVendorId to determine the options vendorId 2024-05-23 16:37:09 +02:00
Danylo Piliaiev
58d8ea2d31 [d3d11,d3d9,util] Add a config option for reproducible VK output
It ensures that for the same D3D commands the output VK commands
don't change between runs.

Useful for comparative benchmarking, can negatively affect performance.

Signed-off-by: Danylo Piliaiev <dpiliaiev@igalia.com>
2024-05-23 15:20:28 +02:00
Philip Rebohle
61bd62c327 [dxvk] Allow descriptor pool overallocation if supported 2024-05-23 14:27:28 +02:00
Philip Rebohle
7bc77b597e [dxvk] Enable VK_NV_descriptor_pool_overallocation if available 2024-05-23 14:27:28 +02:00
Simon McVittie
2ff2c826a5 [build] Generate pkg-config metadata to link to DXVK libraries
This allows dependent projects to query the version and location of DXVK
via the pkg-config interface.

The include directories aren't yet set, because the headers aren't
installed; that will follow in a subsequent commit.

The naming of these pkg-config files is based on proposed Fedora packages
for DXVK 2.0, and is not compatible with older Fedora packages for DXVK
1.x (which used the naming convention dxvk-native-d3d9 and so on).
Packagers can create symlinks such as dxvk-native-d3d9.pc -> dxvk-d3d9.pc
if they want to retain compatibility with older names.

Signed-off-by: Simon McVittie <smcv@collabora.com>
2024-05-21 19:18:12 +00:00
Simon McVittie
f9b4046223 [build] Install headers for native builds
When building a game that has been ported to Linux using DXVK Native,
these headers are necessary to provide the Direct3D and DXVK APIs.

Signed-off-by: Simon McVittie <smcv@collabora.com>
2024-05-21 19:18:12 +00:00
Simon McVittie
83436a97f2 [meson] Set the stem of library names instead of the name_prefix
This is necessary for compatibility with Meson's pkg module, which
generates pkg-config metadata containing "-lNAME" where NAME is the
first argument to shared_library(). Changing the name_prefix parameter
would break that.

Conversely, including .dll or .so in the first parameter would also
break that, so remove the `+dll_ext` part (in practice this is not a
functional change, because `dll_ext` is always set to an empty string).

Signed-off-by: Simon McVittie <smcv@collabora.com>
2024-05-21 19:18:12 +00:00
Ethan Lee
e991bfa604 [ci] Use a tarball for the steamrt-sniper artifact.
Zips can't preserve the symlink, so make the .tar.gz package with package_native.sh and zip that up instead.
2024-05-21 19:18:12 +00:00
Ethan Lee
f33453afbb [build] Add soversion to dxvk-native binaries 2024-05-21 19:18:12 +00:00
Robin Kertels
65dd3c7df3 [d3d9] Always enable STORAGE_BUFFER usage
Fixes a validation error. Drivers don't care about buffer usage bits anyway.
2024-05-21 20:32:13 +02:00
Robin Kertels
dfc3776b24 [d3d9] FF: Fix a bunch of wine tests with FF texture coordinates 2024-05-21 20:32:13 +02:00
Philip Rebohle
3420cd78ac [dxvk] Use new Version helper to deal with driver version numbers 2024-05-20 18:30:36 +02:00
Philip Rebohle
4225f35034 [util] Add version helper class
Useful to decode, store and compare human-readable driver versions.
2024-05-20 18:30:36 +02:00
Philip Rebohle
2cb2f8694e [dxvk] Use VK_MAKE_API_VERSION instead of VK_MAKE_VERSION.
The old macro is deprecated.
2024-05-20 18:30:36 +02:00
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
444 changed files with 50385 additions and 18181 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

@ -4,18 +4,18 @@ on: [push, pull_request, workflow_dispatch]
jobs:
artifacts-mingw-w64:
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
steps:
- name: Checkout code
id: checkout-code
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
submodules: recursive
fetch-depth: 0
- name: Setup problem matcher
uses: Joshua-Ashton/gcc-problem-matcher@v2
uses: Joshua-Ashton/gcc-problem-matcher@v3
- name: Build release
id: build-release
@ -28,39 +28,56 @@ jobs:
- name: Upload artifacts
id: upload-artifacts
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: dxvk-${{ env.VERSION_NAME }}
name: dxvk-win-${{ env.VERSION_NAME }}
path: build/dxvk-${{ env.VERSION_NAME }}
if-no-files-found: error
artifacts-steamrt-sniper:
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
container: registry.gitlab.steamos.cloud/steamrt/sniper/sdk:beta
steps:
- name: Checkout code
id: checkout-code
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
submodules: recursive
fetch-depth: 0
- name: Setup problem matcher
uses: Joshua-Ashton/gcc-problem-matcher@v2
uses: Joshua-Ashton/gcc-problem-matcher@v3
- name: Build release
id: build-release
shell: bash
run: |
export VERSION_NAME="${GITHUB_REF##*/}-${GITHUB_SHA##*/}"
./package-native.sh ${VERSION_NAME} build --no-package
./package-native.sh ${VERSION_NAME} build
echo "VERSION_NAME=${VERSION_NAME}" >> $GITHUB_ENV
- name: Upload artifacts
id: upload-artifacts
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: dxvk-${{ env.VERSION_NAME }}
path: build/dxvk-native-${{ env.VERSION_NAME }}
name: dxvk-native-${{ env.VERSION_NAME }}
path: build/dxvk-native-${{ env.VERSION_NAME }}.tar.gz
if-no-files-found: error
merge-artifacts:
runs-on: ubuntu-latest
needs: [artifacts-mingw-w64, artifacts-steamrt-sniper]
steps:
- name: Get version
id: get-version
shell: bash
run: |
echo "VERSION_NAME=${GITHUB_REF##*/}-${GITHUB_SHA##*/}" >> $GITHUB_ENV
- name: Merge Artifacts
uses: actions/upload-artifact/merge@v4
with:
name: dxvk-${{ env.VERSION_NAME }}
pattern: dxvk*
delete-merged: true

View file

@ -4,21 +4,21 @@ on: [push, pull_request, workflow_dispatch]
jobs:
build-set-windows:
runs-on: windows-2022
runs-on: windows-latest
steps:
- name: Checkout code
id: checkout-code
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
submodules: recursive
fetch-depth: 0
- 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
@ -33,6 +33,19 @@ jobs:
Write-Output "VSDEVCMD=${installationPath}\Common7\Tools\VsDevCmd.bat" `
| Out-File -FilePath "${Env:GITHUB_ENV}" -Append
- name: Download D3D8 SDK Headers
shell: pwsh
run: |
Invoke-WebRequest -URI https://raw.githubusercontent.com/NovaRain/DXSDK_Collection/master/DXSDK_Aug2007/Include/d3d8.h -OutFile include/d3d8.h
Invoke-WebRequest -URI https://raw.githubusercontent.com/NovaRain/DXSDK_Collection/master/DXSDK_Aug2007/Include/d3d8types.h -OutFile include/d3d8types.h
Invoke-WebRequest -URI https://raw.githubusercontent.com/NovaRain/DXSDK_Collection/master/DXSDK_Aug2007/Include/d3d8caps.h -OutFile include/d3d8caps.h
- name: Get version
id: get-version
shell: bash
run: |
echo "VERSION_NAME=${GITHUB_REF##*/}-${GITHUB_SHA##*/}" >> $GITHUB_ENV
- name: Build MSVC x86
shell: pwsh
run: |
@ -50,3 +63,19 @@ jobs:
| % { [System.Environment]::SetEnvironmentVariable($_[0], $_[1]) }
meson --buildtype release --backend vs2022 build-msvc-x64
msbuild -m build-msvc-x64/dxvk.sln
- name: Prepare artifacts
shell: pwsh
run: |
mkdir artifacts\x32
ls -Path build-msvc-x86\src -Include *.dll,*.pdb -Recurse
| cp -Destination (Join-Path -Path (pwd) -ChildPath artifacts\x32)
mkdir artifacts\x64
ls -Path build-msvc-x64\src -Include *.dll,*.pdb -Recurse
| cp -Destination (Join-Path -Path (pwd) -ChildPath artifacts\x64)
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: dxvk-${{ env.VERSION_NAME }}-msvc-output
path: artifacts\*

View file

@ -1,5 +1,7 @@
Copyright (c) 2017 Philip Rebohle
Copyright (c) 2019 Joshua Ashton
Copyright (c) 2019 Robin Kertels
Copyright (c) 2023 Jeffrey Ellison
zlib/libpng license

179
README.md
View file

@ -1,6 +1,6 @@
# DXVK
A Vulkan-based translation layer for Direct3D 9/10/11 which allows running 3D applications on Linux using Wine.
A Vulkan-based translation layer for Direct3D 8/9/10/11 which allows running 3D applications on Linux using Wine.
For the current status of the project, please refer to the [project wiki](https://github.com/doitsujin/dxvk/wiki).
@ -9,18 +9,110 @@ 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, 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 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 `native` DLL overrides for `d3d8`, `d3d9`, `d3d10core`, `d3d11` and `dxgi` under the Libraries tab.
In a default Wine prefix that would be as follows:
```
WINEPREFIX=/path/to/wineprefix
export WINEPREFIX=/path/to/wineprefix
cp x64/*.dll $WINEPREFIX/drive_c/windows/system32
cp x32/*.dll $WINEPREFIX/drive_c/windows/syswow64
winecfg
```
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).
For a pure 32-bit Wine prefix (non default) the 32-bit DLLs instead go to the `system32` directory:
```
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.
#### DLL dependencies
Listed below are the DLL requirements for using DXVK with any single API.
- d3d8: `d3d8.dll` and `d3d9.dll`
- d3d9: `d3d9.dll`
- d3d10: `d3d10core.dll`, `d3d11.dll` and `dxgi.dll`
- d3d11: `d3d11.dll` and `dxgi.dll`
### 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.**
### 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.
- `fps`: Shows the current frame rate.
- `frametimes`: Shows a frame time graph.
- `submissions`: Shows the number of command buffers submitted per frame.
- `drawcalls`: Shows the number of draw calls and render passes per frame.
- `pipelines`: Shows the total number of graphics and compute pipelines.
- `descriptors`: Shows the number of descriptor pools and descriptor sets.
- `memory`: Shows the amount of device memory allocated and used.
- `allocations`: Shows detailed memory chunk suballocation info.
- `gpuload`: Shows estimated GPU load. May be inaccurate.
- `version`: Shows DXVK version.
- `api`: Shows the D3D feature level used by the application.
- `cs`: Shows worker thread statistics.
- `compiler`: Shows shader compiler activity
- `samplers`: Shows the current number of sampler pairs used *[D3D9 Only]*
- `ffshaders`: Shows the current number of shaders generated from fixed function state *[D3D9 Only]*
- `swvp`: Shows whether or not the device is running in software vertex processing mode *[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.
### 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.
### Frame rate limit
The `DXVK_FRAME_RATE` environment variable can be used to limit the frame rate. A value of `0` uncaps the frame rate, while any positive value will limit rendering to the given number of frames per second. Alternatively, the configuration file can be used.
### Device filter
Some applications do not provide a method to select a different GPU. In that case, DXVK can be forced to use a given device:
- `DXVK_FILTER_DEVICE_NAME="Device Name"` Selects devices with a matching Vulkan device name, which can be retrieved with tools such as `vulkaninfo`. Matches on substrings, so "VEGA" or "AMD RADV VEGA10" is supported if the full device name is "AMD RADV VEGA10 (LLVM 9.0.0)", for example. If the substring matches more than one device, the first device matched will be used.
**Note:** If the device filter is configured incorrectly, it may filter out all devices and applications will be unable to create a D3D device.
### 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_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.
### 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.
The following environment variables can be used to control the cache:
- `DXVK_STATE_CACHE`: Controls the state cache. The following values are supported:
- `disable`: Disables the cache entirely.
- `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`
## Build instructions
In order to pull in all submodules that are needed for building, clone the repository using the following command:
@ -28,11 +120,9 @@ In order to pull in all submodules that are needed for building, clone the repos
git clone --recursive https://github.com/doitsujin/dxvk.git
```
### Requirements:
- [wine 7.1](https://www.winehq.org/) or newer
- [Meson](https://mesonbuild.com/) build system (at least version 0.49)
- [Meson](https://mesonbuild.com/) build system (at least version 0.58)
- [Mingw-w64](https://www.mingw-w64.org) compiler and headers (at least version 10.0)
- [glslang](https://github.com/KhronosGroup/glslang) compiler
@ -62,61 +152,9 @@ cd build.w64
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.
The D3D8, D3D9, D3D10, D3D11 and DXGI DLLs will be located in `/your/dxvk/directory/bin`.
### 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.**
### 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.
- `fps`: Shows the current frame rate.
- `frametimes`: Shows a frame time graph.
- `submissions`: Shows the number of command buffers submitted per frame.
- `drawcalls`: Shows the number of draw calls and render passes per frame.
- `pipelines`: Shows the total number of graphics and compute pipelines.
- `descriptors`: Shows the number of descriptor pools and descriptor sets.
- `memory`: Shows the amount of device memory allocated and used.
- `gpuload`: Shows estimated GPU load. May be inaccurate.
- `version`: Shows DXVK version.
- `api`: Shows the D3D feature level used by the application.
- `cs`: Shows worker thread statistics.
- `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`)
Additionally, `DXVK_HUD=1` has the same effect as `DXVK_HUD=devinfo,fps`, and `DXVK_HUD=full` enables all available HUD elements.
### Frame rate limit
The `DXVK_FRAME_RATE` environment variable can be used to limit the frame rate. A value of `0` uncaps the frame rate, while any positive value will limit rendering to the given number of frames per second. Alternatively, the configuration file can be used.
### Device filter
Some applications do not provide a method to select a different GPU. In that case, DXVK can be forced to use a given device:
- `DXVK_FILTER_DEVICE_NAME="Device Name"` Selects devices with a matching Vulkan device name, which can be retrieved with tools such as `vulkaninfo`. Matches on substrings, so "VEGA" or "AMD RADV VEGA10" is supported if the full device name is "AMD RADV VEGA10 (LLVM 9.0.0)", for example. If the substring matches more than one device, the first device matched will be used.
**Note:** If the device filter is configured incorrectly, it may filter out all devices and applications will be unable to create a D3D device.
### 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.
The following environment variables can be used to control the cache:
- `DXVK_STATE_CACHE`: Controls the state cache. The following values are supported:
- `disable`: Disables the cache entirely.
- `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.
### 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.
## Troubleshooting
### Build troubleshooting
DXVK requires threading support from your mingw-w64 build environment. If you
are missing this, you may see "error: std::cv_status has not been declared"
or similar threading related errors.
@ -134,3 +172,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 `SDL3`, `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.1
2.5.3

6
buildenv.h.in Normal file
View file

@ -0,0 +1,6 @@
#pragma once
#define DXVK_TARGET "@BUILD_TARGET@"
#define DXVK_COMPILER "@BUILD_COMPILER@"
#define DXVK_COMPILER_VERSION "@BUILD_COMPILER_VERSION@"

361
dxvk.conf
View file

@ -1,3 +1,10 @@
# Device filter. Only exposes devices whose Vulkan device name contains
# the given string. May be useful to force an application to run on a
# specific GPU, but not applications launched by that application.
# dxvk.deviceFilter = ""
# 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.
@ -10,6 +17,40 @@
# dxgi.enableHDR = True
# Expose support for dcomp swap chains with a dummy window.
#
# This is not a valid implementation of DirectComposition swapchains,
# however some games may rely on this functionality to be present while
# others may require swap chain creation to fail.
#
# Supported values: True, False
# dxgi.enableDummyCompositionSwapchain = False
# Allows the Vulkan driver to opt-in to exclusive full-screen mode on
# Windows. Certain features, such as variable refresh rate or HDR, will
# not work without this setting, however enabling it will break certain
# games that use additional GDI windows, and it will also break alt+tab.
#
# This setting has no effect on non-Windows platforms.
#
# Supported values: True, False
# dxvk.allowFse = False
# Enables Unreal Engine 4 HDR workarounds for games that do not follow
# the standard -Win64-Shipping.exe naming scheme. May be needed to avoid
# crashes in D3D11 games on HDR-enabled systems due to statically linked
# AMDAGS.
#
# Supported values: True, False
# dxgi.enableUe4Workarounds = False
# 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,
@ -35,12 +76,57 @@
# bugs in games that have physics or other simulation tied to their frame
# rate, but do not provide their own limiter.
#
# Supported values : Any non-negative integer
# Supported values
# -1: Always disables the limiter
# 0: Default behaviour. Limits the frame rate to the selected display
# refresh rate when vertical synchronization is enabled if the
# actual display mode does not match the game's one.
# n: Limit to n frames per second.
# dxgi.maxFrameRate = 0
# d3d9.maxFrameRate = 0
# Controls latency sleep and Nvidia Reflex support.
#
# Supported values:
# - Auto: By default, DXVK only supports latency sleep in D3D11 games that
# use Reflex if the graphics driver supports VK_NV_low_latency2,
# and if dxvk-nvapi is enabled in Proton.
# - True: Enables built-in latency reduction based on internal timings.
# This assumes that input sampling for any given frame happens after
# the D3D9 or DXGI Present call returns; games that render and present
# asynchronously will not behave as intended.
# Similarly, this will not have any effect in games with built-in frame
# rate limiters, or if an external limiter (such as MangoHud) is used.
# In some games, enabling this may reduce performance or lead to less
# consistent frame pacing.
# The implementation will either use VK_NV_low_latency2 if supported
# by the driver, or a custom algorithm.
# - False: Disable Reflex support as well as built-in latency reduction.
# dxvk.latencySleep = Auto
# Tolerance for the latency sleep heuristic, in microseconds. Higher values
# increase latency, but may lead to better frame pacing in some cases. Does
# not have any effect if NV_low_latency2 is used.
#
# Supported values: Any non-negative number
# dxvk.latencyTolerance = 1000
# Disables the use of VK_NV_low_latency2. This will make Reflex unavailable
# in games, and if dxvk.latencySleep is set to True, a custom algorithm will
# be used for latency control. By default, the extension will not be used in
# 32-bit applications due to driver issues.
#
# Supported values: Auto, True, False
# dxvk.disableNvLowLatency2 = Auto
# Override PCI vendor and device IDs reported to the application. Can
# cause the app to adjust behaviour depending on the selected values.
#
@ -61,18 +147,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.
@ -80,24 +191,6 @@
# dxgi.maxSharedMemory = 0
# Some games think we are on Intel given a lack of NVAPI or
# AGS/atiadlxx support. Report our device memory as shared memory,
# and some small amount for a "carveout".
# Supported values: True, False
# dxgi.emulateUMA = False
# Override back buffer count for the Vulkan swap chain.
# Setting this to 0 or less will have no effect.
#
# Supported values: Any number greater than or equal to 2.
# dxgi.numBackBuffers = 0
# d3d9.numBackBuffers = 0
# Overrides synchronization interval (Vsync) for presentation.
# Setting this to 0 disables vertical synchronization entirely.
# A positive value 'n' will enable Vsync and repeat the same
@ -109,10 +202,10 @@
# d3d9.presentInterval = -1
# Controls tearing behaviour with regards to in-game Vsync settings.
#
# True enables the mailbox present mode in case regular Vsync is disabled.
# This should avoid tearing, but may be unsupported on some systems
# or require setting dxgi.numBackBuffers to a higher value in order
# to work properly.
# This eliminates tearing, but may be unsupported on some systems.
#
# False enables the relaxed fifo present mode in case regular Vsync is enabled.
# This should result in tearing but reduce stutter if FPS are too low,
@ -122,17 +215,17 @@
#
# 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.
# This may need to be disabled for some applications to avoid rendering
# issues, which may come at a significant performance cost.
# Controls tiler optimizations. Enabling these will alter the behaviour of
# submission heuristics and enables some non-default behaviour in DXVK.
# This option is only intended to be changed for performance testing and
# debugging purposes.
#
# Supported values: True, False
# Supported values: Auto, True, False
# d3d11.dcSingleUseMode = True
# dxvk.tilerMode = Auto
# Override the maximum feature level that a D3D11 device can be created
@ -153,23 +246,25 @@
# Enables relaxed pipeline barriers around UAV writes.
#
# This may improve performance in some games, but may also introduce
# rendering issues. Please don't report bugs with the option enabled.
#
# Ignores write-after-write hazards in compute shaders, and all UAV
# hazards in graphics shaders. This may improve performance in some
# games, but may also introduce rendering issues. Please don't report
# bugs with the option enabled.
#
# Supported values: True, False
# d3d11.relaxedBarriers = False
# Ignores barriers around UAV writes from fragment shaders.
# Enables relaxed UAV pipeline barriers in graphics shaders only.
#
# This may improve performance in some games, but may also introduce
# rendering issues. Please don't report bugs with the option enabled.
# Similar to the relaxedBarriers option, except it does not apply to
# compute UAVs. Please do not report bugs with this option enabled.
#
# Supported values: True, False
# d3d11.ignoreGraphicsBarriers = False
# d3d11.relaxedGraphicsBarriers = False
# Overrides anisotropic filtering for all samplers. Set this to a positive
@ -190,6 +285,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
@ -227,20 +332,33 @@
# d3d11.zeroWorkgroupMemory = False
# Resource size limit for implicit discards, in kilobytes. For small staging
# resources mapped with MAP_WRITE, DXVK will sometimes allocate new backing
# storage in order to avoid GPU synchronization, so setting this too high
# may cause memory issues, setting it to -1 disables the feature.
# Forces insertion of memory barriers after writes to group-shared memory in
# compute shaders. This is only intended to be used as a workaround for games
# that don't properly synchronize access to groupshard variables, and may have
# a negative performance impact as it prevents compiler optimizations.
#
# Supported values: True, False
# d3d11.maxImplicitDiscardSize = 256
# d3d11.forceVolatileTgsmAccess = False
# Resource size limit for buffer-mapped dynamic images, in kilobytes.
# A higher threshold may reduce memory usage and PCI-E bandwidth in
# some games, but may also increase GPU synchronizations. Setting it
# to -1 disables the feature.
# Forces insertion of full memory and control barriers after accessing any
# read-write UAV inside compute shaders. This is only intended to be used as
# a workaround for games that do not synchronize access to coherent UAVs,
# and will likely have a negative performance impact.
#
# Supported values: True, False
# d3d11.maxDynamicImageBufferSize = -1
# d3d11.forceComputeUavBarriers = False
# Clears mapped memory to zero when suballocated memory is freed. This will
# drastically increase CPU overhead and should only be used as a last resort
# if a game does not properly initialize mapped buffers on its own.
#
# Supported values: True, False
# dxvk.zeroMappedMemory = False
# Allocates dynamic resources with the given set of bind flags in
@ -266,6 +384,32 @@
# 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
# Reproducible Command Stream
#
# Ensure that for the same D3D commands the output VK commands
# don't change between runs. Useful for comparative benchmarking,
# can negatively affect performance and can break some games
# that don't use queries correctly.
#
# Supported values:
# - True/False
# d3d11.reproducibleCommandStream = False
# d3d9.reproducibleCommandStream = False
# Sets number of pipeline compiler threads.
#
# If the graphics pipeline library feature is enabled, the given
@ -322,6 +466,21 @@
# dxvk.trackPipelineLifetime = Auto
# Controls memory defragmentation
#
# By default, DXVK will try to defragment video memory if there is a
# significant amount of memory wasted, or if the allocation budget of
# the application is exceeded. This option is provided solely for
# debug purposes.
#
# Supported values:
# - True: Enable defragmentation
# - Auto: Enable defragmentation, except on blocked drivers
# - False: Disable defragmentation
# dxvk.enableMemoryDefrag = Auto
# Sets enabled HUD elements
#
# Behaves like the DXVK_HUD environment variable if the
@ -337,6 +496,7 @@
# capabilities that the applicatation queries.
#
# Supported values:
# - 0: Fixed-function only
# - 1: Shader Model 1
# - 2: Shader Model 2
# - 3: Shader Model 3
@ -416,16 +576,6 @@
# d3d9.floatEmulation = Auto
# Enable dialog box mode
#
# Changes the default state of dialog box mode.
# *Disables* exclusive fullscreen when enabled.
#
# Supported values:
# - True, False: Always enable / disable
# d3d9.enableDialogMode = False
# Overrides the application's MSAA level on the swapchain
#
# Supported values: -1 (application) and 0 to 16 (user override)
@ -433,17 +583,6 @@
# d3d9.forceSwapchainMSAA = -1
# Long Mad
#
# Should we make our Mads a FFma or do it the long way with an FMul and an FAdd?
# This solves some rendering bugs in games that have z-pass shaders which
# don't match entirely to the regular vertex shader in this way.
#
# Supported values:
# - True/False
# d3d9.longMad = False
# Device Local Constant Buffers
#
# Enables using device local, host accessible memory for constant buffers in D3D9.
@ -455,18 +594,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
@ -485,26 +617,28 @@
# 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
# d3d9.supportX4R4G4B4 = True
# Support D32
# Support D16_LOCKABLE
#
# Support the D32 format.
# Support the D16_LOCKABLE format.
# Always enabled on AMD, or when spoofing an AMD GPU
# via customVendorId, disabled by default on Nvidia and Intel.
#
# Supported values:
# - True/False
# d3d9.supportD32 = True
# d3d9.supportD16Lockable = False
# 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
@ -544,16 +678,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)
@ -565,16 +689,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
#
@ -604,3 +729,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

@ -0,0 +1,20 @@
install_subdir(
'directx',
install_dir: get_option('includedir') / 'dxvk',
strip_directory: true,
exclude_files: '.git'
)
install_subdir(
'windows',
install_dir: get_option('includedir') / 'dxvk',
strip_directory: true,
)
install_headers(
'wsi/native_wsi.h',
'wsi/native_sdl3.h',
'wsi/native_sdl2.h',
'wsi/native_glfw.h',
subdir: 'dxvk/wsi',
)

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
@ -259,6 +287,8 @@ typedef struct RGNDATA {
#define DXGI_ERROR_NAME_ALREADY_EXISTS ((HRESULT)0x887A002C)
#define DXGI_ERROR_SDK_COMPONENT_MISSING ((HRESULT)0x887A002D)
#define D3D11_ERROR_DEFERRED_CONTEXT_MAP_WITHOUT_INITIAL_DISCARD ((HRESULT)0x887C0004)
#define WINAPI
#define WINUSERAPI
@ -278,6 +308,7 @@ typedef struct RGNDATA {
#define THIS_
#define THIS
#define __C89_NAMELESSSTRUCTNAME
#define __C89_NAMELESSUNIONNAME
#define __C89_NAMELESSUNIONNAME1
#define __C89_NAMELESSUNIONNAME2
@ -290,17 +321,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 +376,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

@ -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

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

View file

@ -2,6 +2,8 @@
#ifdef DXVK_WSI_WIN32
#error You shouldnt be using this code path.
#elif DXVK_WSI_SDL3
#include "wsi/native_sdl3.h"
#elif DXVK_WSI_SDL2
#include "wsi/native_sdl2.h"
#elif DXVK_WSI_GLFW

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

@ -1 +1 @@
Subproject commit 98f440ce6868c94f5ec6e198cc1adda4760e8849
Subproject commit 234c4b7370a8ea3239a214c9e871e4b17c89f4ab

View file

@ -1,11 +1,13 @@
project('dxvk', ['c', 'cpp'], version : 'v2.1', meson_version : '>= 0.49', default_options : [ 'cpp_std=c++17', 'warning_level=2' ])
project('dxvk', ['c', 'cpp'], version : '2.5.3', meson_version : '>= 0.58', default_options : [ 'cpp_std=c++17', 'b_vscrt=static_from_buildtype', 'warning_level=2' ])
pkg = import('pkgconfig')
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',
@ -16,6 +18,7 @@ compiler_args = [
# gcc
'-Wno-missing-field-initializers',
'-Wno-unused-parameter',
'-Wno-misleading-indentation',
'-Wno-cast-function-type', # Needed for GetProcAddress.
# clang
'-Wno-unused-private-field',
@ -33,56 +36,77 @@ 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
proj_displayinfo = subproject('libdisplay-info')
dep_displayinfo = proj_displayinfo.get_variable('di_dep')
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'
dxvk_so_version = {'name_prefix': ''}
compiler_args += [
'-DNOMINMAX',
'-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
if cpu_family == 'x86'
# Enable stdcall fixup on 32-bit
link_args += [
'-Wl,--enable-stdcall-fixup',
'-Wl,--kill-at',
]
# Fix stack alignment issues with mingw on 32-bit
compiler_args += [
'-mpreferred-stack-boundary=2'
]
endif
else
# setup file alignment + enable PDB output for MSVC builds
# PDBs are useful for Windows consumers of DXVK
compiler_args += [
'/Z7'
]
link_args += [
'/FILEALIGN:4096',
'/DEBUG:FULL'
]
endif
lib_d3d9 = cpp.find_library('d3d9')
lib_d3d11 = cpp.find_library('d3d11')
lib_dxgi = cpp.find_library('dxgi')
if dxvk_is_msvc
lib_d3dcompiler_47 = cpp.find_library('d3dcompiler')
else
lib_d3dcompiler_47 = cpp.find_library('d3dcompiler_47')
endif
if dxvk_is_msvc
res_ext = '.res'
wrc = find_program('rc')
@ -99,10 +123,21 @@ if platform == 'windows'
)
endif
dxvk_wsi = 'win32'
dxvk_name_prefix = ''
compiler_args += ['-DDXVK_WSI_WIN32']
else
dxvk_abi_version = '0'
dxvk_version_raw = meson.project_version().strip('v').split('.')
dxvk_version = [ dxvk_version_raw[0] ]
foreach i : [ 1, 2 ]
padded = dxvk_version_raw[i]
if padded.to_int() < 10
padded = '0' + padded
endif
dxvk_version += [ padded ]
endforeach
dxvk_so_version = {'version': dxvk_abi_version + '.' + dxvk_version[0] + dxvk_version[1] + dxvk_version[2]}
wrc = find_program('touch')
wrc_generator = generator(wrc, output : [ '@BASENAME@_ignored.h' ], arguments : [ '@OUTPUT@' ] )
@ -112,17 +147,24 @@ else
'./include/native/directx'
]
dxvk_wsi = get_option('dxvk_native_wsi')
if dxvk_wsi == 'sdl2'
lib_sdl2 = cpp.find_library('SDL2')
lib_sdl3 = dependency('SDL3', required: false)
lib_sdl2 = dependency('SDL2', required: false)
lib_glfw = dependency('glfw', required: false)
if lib_sdl3.found()
compiler_args += ['-DDXVK_WSI_SDL3']
endif
if lib_sdl2.found()
compiler_args += ['-DDXVK_WSI_SDL2']
elif dxvk_wsi == 'glfw'
lib_glfw = cpp.find_library('glfw')
endif
if lib_glfw.found()
compiler_args += ['-DDXVK_WSI_GLFW']
endif
if (not lib_sdl3.found() and not lib_sdl2.found() and not lib_glfw.found())
error('SDL3, SDL2, or GLFW are required to build dxvk-native')
endif
dxvk_name_prefix = 'libdxvk_'
dxvk_name_prefix = 'dxvk_'
dxvk_pkg_prefix = 'dxvk-'
link_args += [
'-static-libgcc',
@ -138,13 +180,12 @@ add_project_link_arguments(cpp.get_supported_link_arguments(link_args), language
add_project_link_arguments(cc.get_supported_link_arguments(link_args), language: 'c')
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@',
@ -163,4 +204,18 @@ dxvk_version = vcs_tag(
output: 'version.h',
)
conf_data = configuration_data()
conf_data.set('BUILD_COMPILER', cpp.get_id())
conf_data.set('BUILD_COMPILER_VERSION', cpp.version())
conf_data.set('BUILD_TARGET', cpu_family)
dxvk_buildenv = configure_file(
configuration : conf_data,
input: 'buildenv.h.in',
output: 'buildenv.h',
)
if platform != 'windows'
subdir('include/native')
endif
subdir('src')

View file

@ -1,4 +1,5 @@
option('enable_dxgi', type : 'boolean', value : true, description: 'Build DXGI')
option('enable_d3d8', type : 'boolean', value : true, description: 'Build D3D8')
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')

View file

@ -25,6 +25,8 @@ shift 2
opt_nopackage=0
opt_devbuild=0
opt_buildid=false
opt_64_only=0
opt_32_only=0
CC=${CC:="gcc"}
CXX=${CXX:="g++"}
@ -41,6 +43,12 @@ while [ $# -gt 0 ]; do
"--build-id")
opt_buildid=true
;;
"--64-only")
opt_64_only=1
;;
"--32-only")
opt_32_only=1
;;
*)
echo "Unrecognized option: $1" >&2
exit 1
@ -56,13 +64,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"
@ -80,8 +89,12 @@ function package {
rm -R "dxvk-native-$DXVK_VERSION"
}
build_arch 64 lib
build_arch 32 lib32
if [ $opt_32_only -eq 0 ]; then
build_arch 64 lib
fi
if [ $opt_64_only -eq 0 ]; then
build_arch 32 lib32
fi
if [ $opt_nopackage -eq 0 ]; then
package

View file

@ -25,6 +25,8 @@ shift 2
opt_nopackage=0
opt_devbuild=0
opt_buildid=false
opt_64_only=0
opt_32_only=0
crossfile="build-win"
@ -40,6 +42,12 @@ while [ $# -gt 0 ]; do
"--build-id")
opt_buildid=true
;;
"--64-only")
opt_64_only=1
;;
"--32-only")
opt_32_only=1
;;
*)
echo "Unrecognized option: $1" >&2
exit 1
@ -64,6 +72,7 @@ function build_arch {
$opt_strip \
--bindir "x$1" \
--libdir "x$1" \
-Db_ndebug=if-release \
-Dbuild_id=$opt_buildid \
"$DXVK_BUILD_DIR/build.$1"
@ -83,8 +92,12 @@ function package {
rm -R "dxvk-$DXVK_VERSION"
}
build_arch 64
build_arch 32
if [ $opt_32_only -eq 0 ]; then
build_arch 64
fi
if [ $opt_64_only -eq 0 ]; then
build_arch 32
fi
if [ $opt_nopackage -eq 0 ]; then
package

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,21 +7,31 @@ 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 ],
d3d10_core_dll = shared_library(dxvk_name_prefix+'d3d10core', d3d10_core_src, d3d10_core_res,
dependencies : [ d3d10_d3d11_dep ],
include_directories : dxvk_include_path,
install : true,
vs_module_defs : 'd3d10core'+def_spec_ext,
link_args : d3d10_core_ld_args,
link_depends : [ d3d10_core_link_depends ],
kwargs : dxvk_so_version,
)
d3d10_core_dep = declare_dependency(
link_with : [ d3d10_core_dll ],
)
if platform != 'windows'
pkg.generate(d3d10_core_dll,
filebase: dxvk_pkg_prefix + 'd3d10core',
subdirs: 'dxvk',
)
endif

View file

@ -37,8 +37,8 @@ namespace dxvk {
D3D11UserDefinedAnnotation<ContextType>::D3D11UserDefinedAnnotation(
ContextType* container,
const Rc<DxvkDevice>& dxvkDevice)
: m_container(container), m_eventDepth(0),
m_annotationsEnabled(dxvkDevice->instance()->extensions().extDebugUtils) {
: m_container(container),
m_annotationsEnabled(dxvkDevice->debugFlags().test(DxvkDebugFlag::Markers)) {
if (!IsDeferred && m_annotationsEnabled)
RegisterUserDefinedAnnotation<true>(this);
}
@ -75,19 +75,16 @@ namespace dxvk {
INT STDMETHODCALLTYPE D3D11UserDefinedAnnotation<ContextType>::BeginEvent(
D3DCOLOR Color,
LPCWSTR Name) {
if (!m_annotationsEnabled)
if (!m_annotationsEnabled || !Name)
return -1;
D3D10DeviceLock lock = m_container->LockContext();
m_container->EmitCs([color = Color, labelName = dxvk::str::fromws(Name)](DxvkContext *ctx) {
VkDebugUtilsLabelEXT label;
label.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
label.pNext = nullptr;
label.pLabelName = labelName.c_str();
DecodeD3DCOLOR(color, label.color);
ctx->beginDebugLabel(&label);
m_container->EmitCs([
cColor = Color,
cLabel = dxvk::str::fromws(Name)
] (DxvkContext* ctx) {
ctx->beginDebugLabel(vk::makeLabel(cColor, cLabel.c_str()));
});
return m_eventDepth++;
@ -101,11 +98,14 @@ namespace dxvk {
D3D10DeviceLock lock = m_container->LockContext();
m_container->EmitCs([](DxvkContext *ctx) {
if (!m_eventDepth)
return 0;
m_container->EmitCs([] (DxvkContext* ctx) {
ctx->endDebugLabel();
});
return m_eventDepth--;
return --m_eventDepth;
}
@ -113,19 +113,16 @@ namespace dxvk {
void STDMETHODCALLTYPE D3D11UserDefinedAnnotation<ContextType>::SetMarker(
D3DCOLOR Color,
LPCWSTR Name) {
if (!m_annotationsEnabled)
if (!m_annotationsEnabled || !Name)
return;
D3D10DeviceLock lock = m_container->LockContext();
m_container->EmitCs([color = Color, labelName = dxvk::str::fromws(Name)](DxvkContext *ctx) {
VkDebugUtilsLabelEXT label;
label.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
label.pNext = nullptr;
label.pLabelName = labelName.c_str();
DecodeD3DCOLOR(color, label.color);
ctx->insertDebugLabel(&label);
m_container->EmitCs([
cColor = Color,
cLabel = dxvk::str::fromws(Name)
] (DxvkContext* ctx) {
ctx->insertDebugLabel(vk::makeLabel(cColor, cLabel.c_str()));
});
}

View file

@ -48,9 +48,10 @@ namespace dxvk {
private:
ContextType* m_container;
int32_t m_eventDepth;
bool m_annotationsEnabled;
ContextType* m_container = nullptr;
int32_t m_eventDepth = 0u;
bool m_annotationsEnabled = false;
};
}

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

@ -1,17 +1,17 @@
#include "d3d11_buffer.h"
#include "d3d11_context.h"
#include "d3d11_context_imm.h"
#include "d3d11_device.h"
#include "../dxvk/dxvk_data.h"
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,29 +83,51 @@ namespace dxvk {
info.access |= VK_ACCESS_HOST_WRITE_BIT;
}
if (!(pDesc->MiscFlags & D3D11_RESOURCE_MISC_TILE_POOL)) {
// Always enable BDA usage if available so that CUDA interop can work
if (m_parent->GetDXVKDevice()->features().vk12.bufferDeviceAddress)
info.usage |= VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
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_cookie = m_buffer->cookie();
m_mapPtr = m_buffer->mapPtr(0);
m_mapMode = DetermineMapMode(m_buffer->memFlags());
} else if (!(pDesc->MiscFlags & D3D11_RESOURCE_MISC_TILE_POOL)) {
VkMemoryPropertyFlags memoryFlags = GetMemoryFlags();
m_mapMode = DetermineMapMode(memoryFlags);
// 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();
m_buffer = m_parent->GetDXVKDevice()->createBuffer(info, memoryFlags);
m_cookie = m_buffer->cookie();
m_mapPtr = m_buffer->mapPtr(0);
} else {
m_sparseAllocator = m_parent->GetDXVKDevice()->createSparsePageAllocator();
m_sparseAllocator->setCapacity(info.size / SparseMemoryPageSize);
m_mapped = DxvkBufferSliceHandle();
m_cookie = 0u;
m_mapPtr = nullptr;
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 +160,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;
}
@ -187,6 +212,18 @@ namespace dxvk {
}
void D3D11Buffer::SetDebugName(const char* pName) {
if (m_buffer) {
m_parent->GetContext()->InjectCs(DxvkCsQueue::HighPriority, [
cBuffer = m_buffer,
cName = std::string(pName ? pName : "")
] (DxvkContext* ctx) {
ctx->setDebugName(cBuffer, cName.c_str());
});
}
}
HRESULT D3D11Buffer::NormalizeBufferProperties(D3D11_BUFFER_DESC* pDesc) {
// Zero-sized buffers are illegal
if (!pDesc->ByteWidth && !(pDesc->MiscFlags & D3D11_RESOURCE_MISC_TILE_POOL))
@ -238,6 +275,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 +357,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;
}
@ -315,12 +383,14 @@ namespace dxvk {
| VK_ACCESS_INDIRECT_COMMAND_READ_BIT
| VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT
| VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT;
info.debugName = "SO counter";
return device->createBuffer(info, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
}
D3D11_COMMON_BUFFER_MAP_MODE D3D11Buffer::DetermineMapMode() {
return (m_buffer->memFlags() & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
D3D11_COMMON_BUFFER_MAP_MODE D3D11Buffer::DetermineMapMode(VkMemoryPropertyFlags MemFlags) {
return (MemFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
? D3D11_COMMON_BUFFER_MAP_MODE_DIRECT
: D3D11_COMMON_BUFFER_MAP_MODE_NONE;
}

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(
@ -58,6 +61,8 @@ namespace dxvk {
void STDMETHODCALLTYPE GetDesc(
D3D11_BUFFER_DESC *pDesc) final;
void STDMETHODCALLTYPE SetDebugName(const char* pName) final;
bool CheckViewCompatibility(
UINT BindFlags,
DXGI_FORMAT Format) const;
@ -74,6 +79,10 @@ namespace dxvk {
return m_mapMode;
}
uint64_t GetCookie() const {
return m_cookie;
}
Rc<DxvkBuffer> GetBuffer() const {
return m_buffer;
}
@ -110,17 +119,18 @@ namespace dxvk {
: DxvkBufferSlice();
}
DxvkBufferSliceHandle AllocSlice() {
return m_buffer->allocSlice();
Rc<DxvkResourceAllocation> AllocSlice(DxvkLocalAllocationCache* cache) {
return m_buffer->allocateStorage(cache);
}
DxvkBufferSliceHandle DiscardSlice() {
m_mapped = m_buffer->allocSlice();
return m_mapped;
Rc<DxvkResourceAllocation> DiscardSlice(DxvkLocalAllocationCache* cache) {
auto allocation = m_buffer->allocateStorage(cache);
m_mapPtr = allocation->mapPtr();
return allocation;
}
DxvkBufferSliceHandle GetMappedSlice() const {
return m_mapped;
void* GetMapPtr() const {
return m_mapPtr;
}
D3D10Buffer* GetD3D10Iface() {
@ -142,6 +152,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,17 +169,34 @@ 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;
uint64_t m_cookie = 0u;
Rc<DxvkBuffer> m_soCounter;
Rc<DxvkSparsePageAllocator> m_sparseAllocator;
DxvkBufferSliceHandle m_mapped;
uint64_t m_seq = 0ull;
void* m_mapPtr = nullptr;
D3D11DXGIResource m_resource;
D3D10Buffer m_d3d10;
@ -173,7 +208,8 @@ namespace dxvk {
Rc<DxvkBuffer> CreateSoCounterBuffer();
D3D11_COMMON_BUFFER_MAP_MODE DetermineMapMode();
static D3D11_COMMON_BUFFER_MAP_MODE DetermineMapMode(
VkMemoryPropertyFlags MemFlags);
};

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

@ -10,20 +10,12 @@ namespace dxvk {
* Used to identify the type of command
* data most recently added to a CS chunk.
*/
enum class D3D11CmdType {
enum class D3D11CmdType : uint32_t {
None,
DrawIndirect,
DrawIndirectIndexed,
};
/**
* \brief Command data header
*
* Stores the command type. All command
* data structs must inherit this struct.
*/
struct D3D11CmdData {
D3D11CmdType type;
Draw,
DrawIndexed,
};
@ -34,10 +26,10 @@ namespace dxvk {
* the first draw, as well as the number of
* draws to execute.
*/
struct D3D11CmdDrawIndirectData : public D3D11CmdData {
struct D3D11CmdDrawIndirectData {
uint32_t offset;
uint32_t count;
uint32_t stride;
};
}
}

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;
}
@ -71,8 +74,6 @@ namespace dxvk {
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;
@ -99,8 +100,6 @@ namespace dxvk {
while (j < m_resources.size() && m_resources[j].chunkId == i)
TrackResourceSequenceNumber(m_resources[j++].ref, seq);
}
MarkSubmitted();
}
@ -147,15 +146,5 @@ namespace dxvk {
} break;
}
}
void D3D11CommandList::MarkSubmitted() {
if (m_submitted.exchange(true) && !m_warned.exchange(true)
&& m_parent->GetOptions()->dcSingleUseMode) {
Logger::warn(
"D3D11: Command list submitted multiple times,\n"
" but d3d11.dcSingleUseMode is enabled");
}
}
}

View file

@ -55,14 +55,9 @@ namespace dxvk {
std::vector<Com<D3D11Query, false>> m_queries;
std::vector<TrackedResource> m_resources;
std::atomic<bool> m_submitted = { false };
std::atomic<bool> m_warned = { false };
void TrackResourceSequenceNumber(
const D3D11ResourceRef& Resource,
uint64_t Seq);
void MarkSubmitted();
};

File diff suppressed because it is too large Load diff

View file

@ -72,7 +72,14 @@ namespace dxvk {
template<typename T> friend class D3D11DeviceContextExt;
template<typename T> friend class D3D11UserDefinedAnnotation;
constexpr static VkDeviceSize StagingBufferSize = 4ull << 20;
// Use a local staging buffer to handle tiny uploads, most
// of the time we're fine with hitting the global allocator
constexpr static VkDeviceSize StagingBufferSize = 256ull << 10;
protected:
// Compile-time debug flag to force lazy binding on (True) or off (False)
constexpr static Tristate DebugLazyBinding = Tristate::Auto;
public:
D3D11CommonContext(
@ -102,6 +109,11 @@ namespace dxvk {
const D3D11_RECT* pRects,
UINT NumRects);
void STDMETHODCALLTYPE DiscardViewBase(
ID3D11View* pResourceView,
const D3D11_RECT* pRects,
UINT NumRects);
void STDMETHODCALLTYPE CopySubresourceRegion(
ID3D11Resource* pDstResource,
UINT DstSubresource,
@ -123,6 +135,17 @@ namespace dxvk {
const D3D11_BOX* pSrcBox,
UINT CopyFlags);
void STDMETHODCALLTYPE CopySubresourceRegionBase(
ID3D11Resource* pDstResource,
UINT DstSubresource,
UINT DstX,
UINT DstY,
UINT DstZ,
ID3D11Resource* pSrcResource,
UINT SrcSubresource,
const D3D11_BOX* pSrcBox,
UINT CopyFlags);
void STDMETHODCALLTYPE CopyResource(
ID3D11Resource* pDstResource,
ID3D11Resource* pSrcResource);
@ -769,19 +792,44 @@ namespace dxvk {
UINT m_flags;
DxvkStagingBuffer m_staging;
Rc<DxvkDataBuffer> m_updateBuffer;
D3D11CmdType m_csDataType = D3D11CmdType::None;
DxvkCsChunkFlags m_csFlags;
DxvkCsChunkRef m_csChunk;
D3D11CmdData* m_cmdData;
DxvkCsDataBlock* m_csData = nullptr;
DxvkLocalAllocationCache m_allocationCache;
DxvkCsChunkRef AllocCsChunk();
DxvkDataSlice AllocUpdateBufferSlice(size_t Size);
DxvkBufferSlice AllocStagingBuffer(
VkDeviceSize Size);
void ApplyDirtyConstantBuffers(
DxbcProgramType Stage,
const DxbcBindingMask& BoundMask,
DxbcBindingMask& DirtyMask);
void ApplyDirtySamplers(
DxbcProgramType Stage,
const DxbcBindingMask& BoundMask,
DxbcBindingMask& DirtyMask);
void ApplyDirtyShaderResources(
DxbcProgramType Stage,
const DxbcBindingMask& BoundMask,
DxbcBindingMask& DirtyMask);
void ApplyDirtyUnorderedAccessViews(
DxbcProgramType Stage,
const DxbcBindingMask& BoundMask,
DxbcBindingMask& DirtyMask);
void ApplyDirtyGraphicsBindings();
void ApplyDirtyComputeBindings();
void ApplyInputLayout();
void ApplyPrimitiveTopology();
@ -800,6 +848,12 @@ namespace dxvk {
void ApplyViewportState();
void BatchDraw(
const VkDrawIndirectCommand& draw);
void BatchDrawIndexed(
const VkDrawIndexedIndirectCommand& draw);
template<DxbcProgramType ShaderStage>
void BindShader(
const D3D11CommonShader* pShaderModule);
@ -837,35 +891,33 @@ namespace dxvk {
D3D11Buffer* pBuffer,
UINT Offset);
template<DxbcProgramType ShaderStage>
void BindConstantBuffer(
DxbcProgramType ShaderStage,
UINT Slot,
D3D11Buffer* pBuffer,
UINT Offset,
UINT Length);
template<DxbcProgramType ShaderStage>
void BindConstantBufferRange(
DxbcProgramType ShaderStage,
UINT Slot,
UINT Offset,
UINT Length);
template<DxbcProgramType ShaderStage>
void BindSampler(
DxbcProgramType ShaderStage,
UINT Slot,
D3D11SamplerState* pSampler);
template<DxbcProgramType ShaderStage>
void BindShaderResource(
DxbcProgramType ShaderStage,
UINT Slot,
D3D11ShaderResourceView* pResource);
template<DxbcProgramType ShaderStage>
void BindUnorderedAccessView(
UINT UavSlot,
D3D11UnorderedAccessView* pUav,
UINT CtrSlot,
UINT Counter);
DxbcProgramType ShaderStage,
UINT Slot,
D3D11UnorderedAccessView* pUav);
VkClearValue ConvertColorValue(
const FLOAT Color[4],
@ -894,6 +946,36 @@ namespace dxvk {
DxvkBufferSlice BufferSlice,
UINT Flags);
template<typename T>
bool DirtyBindingGeneric(
DxbcProgramType ShaderStage,
T BoundMask,
T& DirtyMask,
T DirtyBit,
bool IsNull);
bool DirtyConstantBuffer(
DxbcProgramType ShaderStage,
uint32_t Slot,
bool IsNull);
bool DirtySampler(
DxbcProgramType ShaderStage,
uint32_t Slot,
bool IsNull);
bool DirtyShaderResource(
DxbcProgramType ShaderStage,
uint32_t Slot,
bool IsNull);
bool DirtyComputeUnorderedAccessView(
uint32_t Slot,
bool IsNull);
bool DirtyGraphicsUnorderedAccessView(
uint32_t Slot);
void DiscardBuffer(
ID3D11Resource* pResource);
@ -926,10 +1008,16 @@ namespace dxvk {
D3D11MaxUsedBindings GetMaxUsedBindings();
bool HasDirtyComputeBindings();
bool HasDirtyGraphicsBindings();
void ResetCommandListState();
void ResetContextState();
void ResetDirtyTracking();
void ResetStagingBuffer();
template<DxbcProgramType ShaderStage, typename T>
@ -952,18 +1040,18 @@ namespace dxvk {
void RestoreCommandListState();
template<DxbcProgramType Stage>
void RestoreConstantBuffers();
template<DxbcProgramType Stage>
void RestoreSamplers();
template<DxbcProgramType Stage>
void RestoreShaderResources();
template<DxbcProgramType Stage>
void RestoreUnorderedAccessViews();
void RestoreConstantBuffers(
DxbcProgramType Stage);
void RestoreSamplers(
DxbcProgramType Stage);
void RestoreShaderResources(
DxbcProgramType Stage);
void RestoreUnorderedAccessViews(
DxbcProgramType Stage);
template<DxbcProgramType ShaderStage>
void SetConstantBuffers(
UINT StartSlot,
@ -1046,6 +1134,10 @@ namespace dxvk {
UINT SrcDepthPitch,
UINT CopyFlags);
void UpdateUnorderedAccessViewCounter(
D3D11UnorderedAccessView* pUav,
uint32_t CounterValue);
bool ValidateRenderTargets(
UINT NumViews,
ID3D11RenderTargetView* const* ppRenderTargetViews,
@ -1066,48 +1158,49 @@ namespace dxvk {
DxvkMultisampleState* pMsState,
UINT SampleMask);
template<bool AllowFlush = !IsDeferred, typename Cmd>
template<bool AllowFlush = true, typename Cmd>
void EmitCs(Cmd&& command) {
m_cmdData = nullptr;
if (unlikely(m_csDataType != D3D11CmdType::None)) {
m_csData = nullptr;
m_csDataType = D3D11CmdType::None;
}
if (unlikely(!m_csChunk->push(command))) {
GetTypedContext()->EmitCsChunk(std::move(m_csChunk));
m_csChunk = AllocCsChunk();
if constexpr (AllowFlush)
if constexpr (!IsDeferred && AllowFlush)
GetTypedContext()->ConsiderFlush(GpuFlushType::ImplicitWeakHint);
m_csChunk->push(command);
}
}
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)...);
template<typename M, bool AllowFlush = true, typename Cmd>
void EmitCsCmd(D3D11CmdType type, size_t count, Cmd&& command) {
m_csDataType = type;
m_csData = m_csChunk->pushCmd<M, Cmd>(command, count);
if (unlikely(!data)) {
if (unlikely(!m_csData)) {
GetTypedContext()->EmitCsChunk(std::move(m_csChunk));
m_csChunk = AllocCsChunk();
if constexpr (AllowFlush)
if constexpr (!IsDeferred && 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)...);
m_csData = m_csChunk->pushCmd<M, Cmd>(command, count);
}
m_cmdData = data;
return data;
}
void FlushCsChunk() {
if (likely(!m_csChunk->empty())) {
m_csData = nullptr;
m_csDataType = D3D11CmdType::None;
GetTypedContext()->EmitCsChunk(std::move(m_csChunk));
m_csChunk = AllocCsChunk();
m_cmdData = nullptr;
}
}
@ -1130,7 +1223,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

@ -7,7 +7,7 @@ namespace dxvk {
D3D11Device* pParent,
const Rc<DxvkDevice>& Device,
UINT ContextFlags)
: D3D11CommonContext<D3D11DeferredContext>(pParent, Device, ContextFlags, GetCsChunkFlags(pParent)),
: D3D11CommonContext<D3D11DeferredContext>(pParent, Device, ContextFlags, 0u),
m_commandList (CreateCommandList()) {
ResetContextState();
}
@ -206,39 +206,37 @@ namespace dxvk {
if (unlikely(!pResource || !pMappedResource))
return E_INVALIDARG;
if (MapType == D3D11_MAP_WRITE_DISCARD) {
if (likely(MapType == D3D11_MAP_WRITE_DISCARD)) {
D3D11_RESOURCE_DIMENSION resourceDim;
pResource->GetType(&resourceDim);
D3D11_MAPPED_SUBRESOURCE mapInfo;
HRESULT status = resourceDim == D3D11_RESOURCE_DIMENSION_BUFFER
? MapBuffer(pResource, &mapInfo)
: MapImage (pResource, Subresource, &mapInfo);
if (unlikely(FAILED(status))) {
*pMappedResource = D3D11_MAPPED_SUBRESOURCE();
return status;
}
AddMapEntry(pResource, Subresource, resourceDim, mapInfo);
*pMappedResource = mapInfo;
return S_OK;
} else if (MapType == D3D11_MAP_WRITE_NO_OVERWRITE) {
return likely(resourceDim == D3D11_RESOURCE_DIMENSION_BUFFER)
? MapBuffer(pResource, pMappedResource)
: MapImage(pResource, Subresource, pMappedResource);
} else if (likely(MapType == D3D11_MAP_WRITE_NO_OVERWRITE)) {
// The resource must be mapped with D3D11_MAP_WRITE_DISCARD
// before it can be mapped with D3D11_MAP_WRITE_NO_OVERWRITE.
auto entry = FindMapEntry(pResource, Subresource);
if (unlikely(!entry)) {
*pMappedResource = D3D11_MAPPED_SUBRESOURCE();
D3D11_RESOURCE_DIMENSION resourceDim;
pResource->GetType(&resourceDim);
if (likely(resourceDim == D3D11_RESOURCE_DIMENSION_BUFFER)) {
D3D11_MAPPED_SUBRESOURCE sr = FindMapEntry(static_cast<D3D11Buffer*>(pResource)->GetCookie());
pMappedResource->pData = sr.pData;
if (unlikely(!sr.pData))
return D3D11_ERROR_DEFERRED_CONTEXT_MAP_WITHOUT_INITIAL_DISCARD;
pMappedResource->RowPitch = sr.RowPitch;
pMappedResource->DepthPitch = sr.DepthPitch;
return S_OK;
} else {
// Images cannot be mapped with NO_OVERWRITE
pMappedResource->pData = nullptr;
return E_INVALIDARG;
}
// Return same memory region as earlier
*pMappedResource = entry->MapInfo;
return S_OK;
} else {
// Not allowed on deferred contexts
*pMappedResource = D3D11_MAPPED_SUBRESOURCE();
pMappedResource->pData = nullptr;
return E_INVALIDARG;
}
}
@ -265,44 +263,26 @@ namespace dxvk {
ID3D11Resource* pResource,
D3D11_MAPPED_SUBRESOURCE* pMappedResource) {
D3D11Buffer* pBuffer = static_cast<D3D11Buffer*>(pResource);
if (unlikely(pBuffer->GetMapMode() == D3D11_COMMON_BUFFER_MAP_MODE_NONE)) {
Logger::err("D3D11: Cannot map a device-local buffer");
pMappedResource->pData = nullptr;
return E_INVALIDARG;
}
auto bufferSlice = pBuffer->AllocSlice(&m_allocationCache);
pMappedResource->pData = bufferSlice->mapPtr();
pMappedResource->RowPitch = pBuffer->Desc()->ByteWidth;
pMappedResource->DepthPitch = pBuffer->Desc()->ByteWidth;
if (likely(m_csFlags.test(DxvkCsChunkFlag::SingleUse))) {
// For resources that cannot be written by the GPU,
// we may write to the buffer resource directly and
// just swap in the buffer slice as needed.
auto bufferSlice = pBuffer->AllocSlice();
pMappedResource->pData = bufferSlice.mapPtr;
EmitCs([
cDstBuffer = pBuffer->GetBuffer(),
cPhysSlice = bufferSlice
] (DxvkContext* ctx) {
ctx->invalidateBuffer(cDstBuffer, cPhysSlice);
});
} else {
// For GPU-writable resources, we need a data slice
// to perform the update operation at execution time.
auto dataSlice = AllocUpdateBufferSlice(pBuffer->Desc()->ByteWidth);
pMappedResource->pData = dataSlice.ptr();
EmitCs([
cDstBuffer = pBuffer->GetBuffer(),
cDstSlice = std::move(bufferSlice)
] (DxvkContext* ctx) {
ctx->invalidateBuffer(cDstBuffer, Rc<DxvkResourceAllocation>(cDstSlice));
});
EmitCs([
cDstBuffer = pBuffer->GetBuffer(),
cDataSlice = dataSlice
] (DxvkContext* ctx) {
DxvkBufferSliceHandle slice = cDstBuffer->allocSlice();
std::memcpy(slice.mapPtr, cDataSlice.ptr(), cDataSlice.length());
ctx->invalidateBuffer(cDstBuffer, slice);
});
}
AddMapEntry(pBuffer->GetCookie(), *pMappedResource);
return S_OK;
}
@ -313,33 +293,52 @@ namespace dxvk {
D3D11_MAPPED_SUBRESOURCE* pMappedResource) {
D3D11CommonTexture* pTexture = GetCommonTexture(pResource);
if (unlikely(pTexture->GetMapMode() == D3D11_COMMON_TEXTURE_MAP_MODE_NONE)) {
Logger::err("D3D11: Cannot map a device-local image");
if (unlikely(Subresource >= pTexture->CountSubresources())) {
pMappedResource->pData = nullptr;
return E_INVALIDARG;
}
if (unlikely(Subresource >= pTexture->CountSubresources()))
if (unlikely(pTexture->Desc()->Usage != D3D11_USAGE_DYNAMIC)) {
pMappedResource->pData = nullptr;
return E_INVALIDARG;
VkFormat packedFormat = pTexture->GetPackedFormat();
auto formatInfo = lookupFormatInfo(packedFormat);
auto subresource = pTexture->GetSubresourceFromIndex(
formatInfo->aspectMask, Subresource);
VkExtent3D levelExtent = pTexture->MipLevelExtent(subresource.mipLevel);
auto layout = pTexture->GetSubresourceLayout(formatInfo->aspectMask, Subresource);
auto dataSlice = AllocStagingBuffer(util::computeImageDataSize(packedFormat, levelExtent));
pMappedResource->RowPitch = layout.RowPitch;
pMappedResource->DepthPitch = layout.DepthPitch;
pMappedResource->pData = dataSlice.mapPtr(0);
}
UpdateImage(pTexture, &subresource,
VkOffset3D { 0, 0, 0 }, levelExtent,
std::move(dataSlice));
return S_OK;
VkFormat packedFormat = pTexture->GetPackedFormat();
auto formatInfo = lookupFormatInfo(packedFormat);
auto layout = pTexture->GetSubresourceLayout(formatInfo->aspectMask, Subresource);
if (pTexture->GetMapMode() == D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT) {
auto storage = pTexture->AllocStorage();
auto mapPtr = storage->mapPtr();
EmitCs([
cImage = pTexture->GetImage(),
cStorage = std::move(storage)
] (DxvkContext* ctx) {
ctx->invalidateImage(cImage, Rc<DxvkResourceAllocation>(cStorage));
ctx->initImage(cImage, cImage->getAvailableSubresources(), VK_IMAGE_LAYOUT_PREINITIALIZED);
});
pMappedResource->RowPitch = layout.RowPitch;
pMappedResource->DepthPitch = layout.DepthPitch;
pMappedResource->pData = mapPtr;
return S_OK;
} else {
auto dataSlice = AllocStagingBuffer(layout.Size);
pMappedResource->RowPitch = layout.RowPitch;
pMappedResource->DepthPitch = layout.DepthPitch;
pMappedResource->pData = dataSlice.mapPtr(0);
auto subresource = pTexture->GetSubresourceFromIndex(formatInfo->aspectMask, Subresource);
auto mipExtent = pTexture->MipLevelExtent(subresource.mipLevel);
UpdateImage(pTexture, &subresource,
VkOffset3D { 0, 0, 0 }, mipExtent,
std::move(dataSlice));
return S_OK;
}
}
@ -351,19 +350,15 @@ namespace dxvk {
UINT CopyFlags) {
void* mapPtr = nullptr;
if (unlikely(CopyFlags == D3D11_COPY_NO_OVERWRITE)) {
auto entry = FindMapEntry(pDstBuffer, 0);
if (entry)
mapPtr = entry->MapInfo.pData;
}
if (unlikely(CopyFlags == D3D11_COPY_NO_OVERWRITE))
mapPtr = FindMapEntry(pDstBuffer->GetCookie()).pData;
if (likely(!mapPtr)) {
// The caller validates the map mode, so we can
// safely ignore the MapBuffer return value here
D3D11_MAPPED_SUBRESOURCE mapInfo;
MapBuffer(pDstBuffer, &mapInfo);
AddMapEntry(pDstBuffer, 0, D3D11_RESOURCE_DIMENSION_BUFFER, mapInfo);
AddMapEntry(pDstBuffer->GetCookie(), mapInfo);
mapPtr = mapInfo.pData;
}
@ -418,40 +413,27 @@ namespace dxvk {
}
D3D11DeferredContextMapEntry* D3D11DeferredContext::FindMapEntry(
ID3D11Resource* pResource,
UINT Subresource) {
D3D11_MAPPED_SUBRESOURCE D3D11DeferredContext::FindMapEntry(
uint64_t Cookie) {
// Recently mapped resources as well as entries with
// up-to-date map infos will be located at the end
// of the resource array, so scan in reverse order.
size_t size = m_mappedResources.size();
for (size_t i = 1; i <= size; i++) {
auto entry = &m_mappedResources[size - i];
const auto& entry = m_mappedResources[size - i];
if (entry->Resource.Get() == pResource
&& entry->Resource.GetSubresource() == Subresource)
return entry;
if (entry.ResourceCookie == Cookie)
return entry.MapInfo;
}
return nullptr;
return D3D11_MAPPED_SUBRESOURCE();
}
void D3D11DeferredContext::AddMapEntry(
ID3D11Resource* pResource,
UINT Subresource,
D3D11_RESOURCE_DIMENSION ResourceType,
uint64_t Cookie,
const D3D11_MAPPED_SUBRESOURCE& MapInfo) {
m_mappedResources.emplace_back(pResource,
Subresource, ResourceType, MapInfo);
m_mappedResources.push_back({ Cookie, MapInfo });
}
DxvkCsChunkFlags D3D11DeferredContext::GetCsChunkFlags(
D3D11Device* pDevice) {
return pDevice->GetOptions()->dcSingleUseMode
? DxvkCsChunkFlags(DxvkCsChunkFlag::SingleUse)
: DxvkCsChunkFlags();
}
}
}

View file

@ -8,17 +8,8 @@
namespace dxvk {
struct D3D11DeferredContextMapEntry {
D3D11DeferredContextMapEntry() { }
D3D11DeferredContextMapEntry(
ID3D11Resource* pResource,
UINT Subresource,
D3D11_RESOURCE_DIMENSION ResourceType,
const D3D11_MAPPED_SUBRESOURCE& MappedResource)
: Resource(pResource, Subresource, ResourceType),
MapInfo(MappedResource) { }
D3D11ResourceRef Resource;
D3D11_MAPPED_SUBRESOURCE MapInfo;
uint64_t ResourceCookie = 0u;
D3D11_MAPPED_SUBRESOURCE MapInfo = { };
};
class D3D11DeferredContext : public D3D11CommonContext<D3D11DeferredContext> {
@ -130,14 +121,11 @@ namespace dxvk {
void TrackBufferSequenceNumber(
D3D11Buffer* pResource);
D3D11DeferredContextMapEntry* FindMapEntry(
ID3D11Resource* pResource,
UINT Subresource);
D3D11_MAPPED_SUBRESOURCE FindMapEntry(
uint64_t Coookie);
void AddMapEntry(
ID3D11Resource* pResource,
UINT Subresource,
D3D11_RESOURCE_DIMENSION ResourceType,
uint64_t Cookie,
const D3D11_MAPPED_SUBRESOURCE& MapInfo);
static DxvkCsChunkFlags GetCsChunkFlags(

View file

@ -48,12 +48,15 @@ namespace dxvk {
D3D10DeviceLock lock = m_ctx->LockContext();
m_ctx->SetDrawBuffers(pBufferForArgs, nullptr);
if (unlikely(m_ctx->HasDirtyGraphicsBindings()))
m_ctx->ApplyDirtyGraphicsBindings();
m_ctx->EmitCs([
cCount = DrawCount,
cOffset = ByteOffsetForArgs,
cStride = ByteStrideForArgs
] (DxvkContext* ctx) {
ctx->drawIndirect(cOffset, cCount, cStride);
ctx->drawIndirect(cOffset, cCount, cStride, false);
});
}
@ -67,12 +70,15 @@ namespace dxvk {
D3D10DeviceLock lock = m_ctx->LockContext();
m_ctx->SetDrawBuffers(pBufferForArgs, nullptr);
if (unlikely(m_ctx->HasDirtyGraphicsBindings()))
m_ctx->ApplyDirtyGraphicsBindings();
m_ctx->EmitCs([
cCount = DrawCount,
cOffset = ByteOffsetForArgs,
cStride = ByteStrideForArgs
] (DxvkContext* ctx) {
ctx->drawIndexedIndirect(cOffset, cCount, cStride);
ctx->drawIndexedIndirect(cOffset, cCount, cStride, false);
});
}
@ -88,6 +94,9 @@ namespace dxvk {
D3D10DeviceLock lock = m_ctx->LockContext();
m_ctx->SetDrawBuffers(pBufferForArgs, pBufferForCount);
if (unlikely(m_ctx->HasDirtyGraphicsBindings()))
m_ctx->ApplyDirtyGraphicsBindings();
m_ctx->EmitCs([
cMaxCount = MaxDrawCount,
cArgOffset = ByteOffsetForArgs,
@ -110,6 +119,9 @@ namespace dxvk {
D3D10DeviceLock lock = m_ctx->LockContext();
m_ctx->SetDrawBuffers(pBufferForArgs, pBufferForCount);
if (unlikely(m_ctx->HasDirtyGraphicsBindings()))
m_ctx->ApplyDirtyGraphicsBindings();
m_ctx->EmitCs([
cMaxCount = MaxDrawCount,
cArgOffset = ByteOffsetForArgs,
@ -143,13 +155,13 @@ namespace dxvk {
void STDMETHODCALLTYPE D3D11DeviceContextExt<ContextType>::SetBarrierControl(
UINT ControlFlags) {
D3D10DeviceLock lock = m_ctx->LockContext();
DxvkBarrierControlFlags flags;
if (ControlFlags & D3D11_VK_BARRIER_CONTROL_IGNORE_WRITE_AFTER_WRITE)
flags.set(DxvkBarrierControl::IgnoreWriteAfterWrite);
D3D11Device* parent = static_cast<D3D11Device*>(m_ctx->GetParentInterface());
DxvkBarrierControlFlags flags = parent->GetOptionsBarrierControlFlags();
if (ControlFlags & D3D11_VK_BARRIER_CONTROL_IGNORE_GRAPHICS_UAV)
flags.set(DxvkBarrierControl::IgnoreGraphicsBarriers);
if (ControlFlags & D3D11_VK_BARRIER_CONTROL_IGNORE_WRITE_AFTER_WRITE) {
flags.set(DxvkBarrierControl::ComputeAllowReadWriteOverlap,
DxvkBarrierControl::GraphicsAllowReadWriteOverlap);
}
m_ctx->EmitCs([cFlags = flags] (DxvkContext* ctx) {
ctx->setBarrierControl(cFlags);

View file

@ -16,28 +16,24 @@ namespace dxvk {
D3D11Device* pParent,
const Rc<DxvkDevice>& Device)
: D3D11CommonContext<D3D11ImmediateContext>(pParent, Device, 0, DxvkCsChunkFlag::SingleUse),
m_csThread(Device, Device->createContext(DxvkContextType::Primary)),
m_maxImplicitDiscardSize(pParent->GetOptions()->maxImplicitDiscardSize),
m_csThread(Device, Device->createContext()),
m_submissionFence(new sync::CallbackFence()),
m_flushTracker(GetMaxFlushType(pParent, Device)),
m_stagingBufferFence(new sync::Fence(0)),
m_multithread(this, false, pParent->GetOptions()->enableContextLock),
m_videoContext(this, Device) {
EmitCs([
cDevice = m_device,
cRelaxedBarriers = pParent->GetOptions()->relaxedBarriers,
cIgnoreGraphicsBarriers = pParent->GetOptions()->ignoreGraphicsBarriers
cBarrierControlFlags = pParent->GetOptionsBarrierControlFlags()
] (DxvkContext* ctx) {
ctx->beginRecording(cDevice->createCommandList());
DxvkBarrierControlFlags barrierControl;
if (cRelaxedBarriers)
barrierControl.set(DxvkBarrierControl::IgnoreWriteAfterWrite);
if (cIgnoreGraphicsBarriers)
barrierControl.set(DxvkBarrierControl::IgnoreGraphicsBarriers);
ctx->setBarrierControl(barrierControl);
ctx->setBarrierControl(cBarrierControlFlags);
});
// Stall here so that external submissions to the
// CS thread can actually access the command list
SynchronizeCsThread(DxvkCsThread::SynchronizeAll);
ClearState();
}
@ -49,7 +45,7 @@ namespace dxvk {
if (this_thread::isInModuleDetachment())
return;
ExecuteFlush(GpuFlushType::ExplicitFlush, nullptr);
ExecuteFlush(GpuFlushType::ExplicitFlush, nullptr, true);
SynchronizeCsThread(DxvkCsThread::SynchronizeAll);
SynchronizeDevice();
}
@ -101,6 +97,10 @@ namespace dxvk {
// Ignore the DONOTFLUSH flag here as some games will spin
// on queries without ever flushing the context otherwise.
D3D10DeviceLock lock = LockContext();
if (unlikely(m_device->debugFlags().test(DxvkDebugFlag::Capture)))
m_flushReason = "Query read-back";
ConsiderFlush(GpuFlushType::ImplicitSynchronization);
}
@ -150,7 +150,7 @@ namespace dxvk {
query->NotifyEnd();
if (query->IsStalling())
ExecuteFlush(GpuFlushType::ImplicitSynchronization, nullptr);
ExecuteFlush(GpuFlushType::ImplicitSynchronization, nullptr, false);
else if (query->IsEvent())
ConsiderFlush(GpuFlushType::ImplicitStrongHint);
}
@ -160,7 +160,10 @@ namespace dxvk {
void STDMETHODCALLTYPE D3D11ImmediateContext::Flush() {
D3D10DeviceLock lock = LockContext();
ExecuteFlush(GpuFlushType::ExplicitFlush, nullptr);
if (unlikely(m_device->debugFlags().test(DxvkDebugFlag::Capture)))
m_flushReason = "Explicit Flush";
ExecuteFlush(GpuFlushType::ExplicitFlush, nullptr, true);
}
@ -169,7 +172,10 @@ namespace dxvk {
HANDLE hEvent) {
D3D10DeviceLock lock = LockContext();
ExecuteFlush(GpuFlushType::ExplicitFlush, hEvent);
if (unlikely(m_device->debugFlags().test(DxvkDebugFlag::Capture)))
m_flushReason = "Explicit Flush";
ExecuteFlush(GpuFlushType::ExplicitFlush, hEvent, true);
}
@ -189,7 +195,10 @@ namespace dxvk {
ctx->signalFence(cFence, cValue);
});
ExecuteFlush(GpuFlushType::ExplicitFlush, nullptr);
if (unlikely(m_device->debugFlags().test(DxvkDebugFlag::Capture)))
m_flushReason = "Fence signal";
ExecuteFlush(GpuFlushType::ExplicitFlush, nullptr, true);
return S_OK;
}
@ -203,7 +212,10 @@ namespace dxvk {
if (!fence)
return E_INVALIDARG;
ExecuteFlush(GpuFlushType::ExplicitFlush, nullptr);
if (unlikely(m_device->debugFlags().test(DxvkDebugFlag::Capture)))
m_flushReason = "Fence wait";
ExecuteFlush(GpuFlushType::ExplicitFlush, nullptr, true);
EmitCs([
cFence = fence->GetFence(),
@ -222,7 +234,12 @@ namespace dxvk {
D3D10DeviceLock lock = LockContext();
auto commandList = static_cast<D3D11CommandList*>(pCommandList);
// Reset dirty binding tracking before submitting any CS chunks.
// This is needed so that any submission that might occur during
// this call does not disrupt bindings set by the deferred context.
ResetDirtyTracking();
// Clear state so that the command list can't observe any
// current context state. The command list itself will clean
// up after execution to ensure that no state changes done
@ -283,23 +300,14 @@ namespace dxvk {
D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
pResource->GetType(&resourceDim);
HRESULT hr;
if (likely(resourceDim == D3D11_RESOURCE_DIMENSION_BUFFER)) {
hr = MapBuffer(
return MapBuffer(
static_cast<D3D11Buffer*>(pResource),
MapType, MapFlags, pMappedResource);
} else {
hr = MapImage(
GetCommonTexture(pResource),
Subresource, MapType, MapFlags,
pMappedResource);
return MapImage(GetCommonTexture(pResource),
Subresource, MapType, MapFlags, pMappedResource);
}
if (unlikely(FAILED(hr)))
*pMappedResource = D3D11_MAPPED_SUBRESOURCE();
return hr;
}
@ -331,6 +339,7 @@ namespace dxvk {
if (unlikely(pResource->GetMapMode() == D3D11_COMMON_BUFFER_MAP_MODE_NONE)) {
Logger::err("D3D11: Cannot map a device-local buffer");
pMappedResource->pData = nullptr;
return E_INVALIDARG;
}
@ -340,24 +349,28 @@ namespace dxvk {
// Allocate a new backing slice for the buffer and set
// it as the 'new' mapped slice. This assumes that the
// only way to invalidate a buffer is by mapping it.
auto physSlice = pResource->DiscardSlice();
pMappedResource->pData = physSlice.mapPtr;
auto bufferSlice = pResource->DiscardSlice(&m_allocationCache);
pMappedResource->pData = bufferSlice->mapPtr();
pMappedResource->RowPitch = bufferSize;
pMappedResource->DepthPitch = bufferSize;
EmitCs([
cBuffer = pResource->GetBuffer(),
cBufferSlice = physSlice
] (DxvkContext* ctx) {
ctx->invalidateBuffer(cBuffer, cBufferSlice);
cBufferSlice = std::move(bufferSlice)
] (DxvkContext* ctx) mutable {
ctx->invalidateBuffer(cBuffer, std::move(cBufferSlice));
});
// Ignore small buffers here. These are often updated per
// draw and won't contribute much to memory waste anyway.
if (unlikely(bufferSize > DxvkPageAllocator::PageSize))
ThrottleDiscard(bufferSize);
return S_OK;
} else if (likely(MapType == D3D11_MAP_WRITE_NO_OVERWRITE)) {
// Put this on a fast path without any extra checks since it's
// a somewhat desired method to partially update large buffers
DxvkBufferSliceHandle physSlice = pResource->GetMappedSlice();
pMappedResource->pData = physSlice.mapPtr;
pMappedResource->pData = pResource->GetMapPtr();
pMappedResource->RowPitch = bufferSize;
pMappedResource->DepthPitch = bufferSize;
return S_OK;
@ -372,7 +385,7 @@ namespace dxvk {
auto buffer = pResource->GetBuffer();
auto sequenceNumber = pResource->GetSequenceNumber();
if (MapType != D3D11_MAP_READ && !MapFlags && bufferSize <= m_maxImplicitDiscardSize) {
if (MapType != D3D11_MAP_READ && !MapFlags && bufferSize <= D3D11Initializer::MaxMemoryPerSubmission) {
SynchronizeCsThread(sequenceNumber);
bool hasWoAccess = buffer->isInUse(DxvkAccess::Write);
@ -385,27 +398,32 @@ namespace dxvk {
}
if (doInvalidatePreserve) {
auto prevSlice = pResource->GetMappedSlice();
auto physSlice = pResource->DiscardSlice();
auto srcPtr = pResource->GetMapPtr();
auto dstSlice = pResource->DiscardSlice(nullptr);
auto dstPtr = dstSlice->mapPtr();
EmitCs([
cBuffer = std::move(buffer),
cBufferSlice = physSlice
] (DxvkContext* ctx) {
ctx->invalidateBuffer(cBuffer, cBufferSlice);
cBufferSlice = std::move(dstSlice)
] (DxvkContext* ctx) mutable {
ctx->invalidateBuffer(cBuffer, std::move(cBufferSlice));
});
std::memcpy(physSlice.mapPtr, prevSlice.mapPtr, physSlice.length);
pMappedResource->pData = physSlice.mapPtr;
std::memcpy(dstPtr, srcPtr, bufferSize);
pMappedResource->pData = dstPtr;
pMappedResource->RowPitch = bufferSize;
pMappedResource->DepthPitch = bufferSize;
ThrottleDiscard(bufferSize);
return S_OK;
} else {
if (!WaitForResource(buffer, sequenceNumber, MapType, MapFlags))
if (!WaitForResource(*buffer, sequenceNumber, MapType, MapFlags)) {
pMappedResource->pData = nullptr;
return DXGI_ERROR_WAS_STILL_DRAWING;
}
DxvkBufferSliceHandle physSlice = pResource->GetMappedSlice();
pMappedResource->pData = physSlice.mapPtr;
pMappedResource->pData = pResource->GetMapPtr();
pMappedResource->RowPitch = bufferSize;
pMappedResource->DepthPitch = bufferSize;
return S_OK;
@ -420,19 +438,46 @@ namespace dxvk {
D3D11_MAP MapType,
UINT MapFlags,
D3D11_MAPPED_SUBRESOURCE* pMappedResource) {
const Rc<DxvkImage> mappedImage = pResource->GetImage();
const Rc<DxvkBuffer> mappedBuffer = pResource->GetMappedBuffer(Subresource);
auto mapMode = pResource->GetMapMode();
if (unlikely(mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_NONE)) {
Logger::err("D3D11: Cannot map a device-local image");
return E_INVALIDARG;
}
if (pMappedResource)
pMappedResource->pData = nullptr;
if (unlikely(Subresource >= pResource->CountSubresources()))
return E_INVALIDARG;
switch (MapType) {
case D3D11_MAP_READ: {
if (!(pResource->Desc()->CPUAccessFlags & D3D11_CPU_ACCESS_READ))
return E_INVALIDARG;
} break;
case D3D11_MAP_READ_WRITE: {
if (!(pResource->Desc()->CPUAccessFlags & D3D11_CPU_ACCESS_READ)
|| !(pResource->Desc()->CPUAccessFlags & D3D11_CPU_ACCESS_WRITE))
return E_INVALIDARG;
} break;
case D3D11_MAP_WRITE: {
if (!(pResource->Desc()->CPUAccessFlags & D3D11_CPU_ACCESS_WRITE)
|| (pResource->Desc()->Usage == D3D11_USAGE_DYNAMIC))
return E_INVALIDARG;
} break;
case D3D11_MAP_WRITE_DISCARD: {
if (!(pResource->Desc()->CPUAccessFlags & D3D11_CPU_ACCESS_WRITE)
|| pResource->Desc()->Usage != D3D11_USAGE_DYNAMIC)
return E_INVALIDARG;
} break;
case D3D11_MAP_WRITE_NO_OVERWRITE: {
// NO_OVERWRITE is explcitly banned for dynamic images
if (!(pResource->Desc()->CPUAccessFlags & D3D11_CPU_ACCESS_WRITE)
|| (pResource->Desc()->Usage != D3D11_USAGE_DEFAULT))
return E_INVALIDARG;
} break;
}
if (likely(pMappedResource != nullptr)) {
// Resources with an unknown memory layout cannot return a pointer
if (pResource->Desc()->Usage == D3D11_USAGE_DEFAULT
@ -449,23 +494,32 @@ namespace dxvk {
uint64_t sequenceNumber = pResource->GetSequenceNumber(Subresource);
auto formatInfo = lookupFormatInfo(packedFormat);
void* mapPtr;
auto layout = pResource->GetSubresourceLayout(formatInfo->aspectMask, Subresource);
if (mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT) {
// Wait for the resource to become available. We do not
// support image renaming, so stall on DISCARD instead.
if (MapType == D3D11_MAP_WRITE_DISCARD)
MapFlags &= ~D3D11_MAP_FLAG_DO_NOT_WAIT;
Rc<DxvkImage> mappedImage = pResource->GetImage();
if (MapType != D3D11_MAP_WRITE_NO_OVERWRITE) {
if (!WaitForResource(mappedImage, sequenceNumber, MapType, MapFlags))
if (MapType == D3D11_MAP_WRITE_DISCARD) {
EmitCs([
cImage = std::move(mappedImage),
cStorage = pResource->DiscardStorage()
] (DxvkContext* ctx) {
ctx->invalidateImage(cImage, Rc<DxvkResourceAllocation>(cStorage));
ctx->initImage(cImage, cImage->getAvailableSubresources(), VK_IMAGE_LAYOUT_PREINITIALIZED);
});
ThrottleDiscard(layout.Size);
} else if (MapType != D3D11_MAP_WRITE_NO_OVERWRITE) {
if (!WaitForResource(*mappedImage, sequenceNumber, MapType, MapFlags))
return DXGI_ERROR_WAS_STILL_DRAWING;
}
// Query the subresource's memory layout and hope that
// the application respects the returned pitch values.
mapPtr = mappedImage->mapPtr(0);
} else if (mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_DYNAMIC) {
// Nothing else to really do here, NotifyMap will ensure that we
// actually get a staging buffer that isn't currently in use.
ThrottleDiscard(layout.Size);
} else {
Rc<DxvkBuffer> mappedBuffer = pResource->GetMappedBuffer(Subresource);
constexpr uint32_t DoInvalidate = (1u << 0);
constexpr uint32_t DoPreserve = (1u << 1);
constexpr uint32_t DoWait = (1u << 2);
@ -503,11 +557,11 @@ namespace dxvk {
// Need to synchronize thread to determine pending GPU accesses
SynchronizeCsThread(sequenceNumber);
// Don't implicitly discard large buffers or buffers of images with
// multiple subresources, as that is likely to cause memory issues.
VkDeviceSize bufferSize = pResource->GetMappedSlice(Subresource).length;
// Don't implicitly discard large very large resources
// since that might lead to memory issues.
VkDeviceSize bufferSize = mappedBuffer->info().size;
if (bufferSize >= m_maxImplicitDiscardSize || pResource->CountSubresources() > 1) {
if (bufferSize > D3D11Initializer::MaxMemoryPerSubmission) {
// Don't check access flags, WaitForResource will return
// early anyway if the resource is currently in use
doFlags = DoWait;
@ -530,20 +584,25 @@ namespace dxvk {
}
if (doFlags & DoInvalidate) {
DxvkBufferSliceHandle prevSlice = pResource->GetMappedSlice(Subresource);
DxvkBufferSliceHandle physSlice = pResource->DiscardSlice(Subresource);
VkDeviceSize bufferSize = mappedBuffer->info().size;
auto srcSlice = pResource->GetMappedSlice(Subresource);
auto dstSlice = pResource->DiscardSlice(Subresource);
auto srcPtr = srcSlice->mapPtr();
auto dstPtr = dstSlice->mapPtr();
EmitCs([
cImageBuffer = mappedBuffer,
cBufferSlice = physSlice
] (DxvkContext* ctx) {
ctx->invalidateBuffer(cImageBuffer, cBufferSlice);
cImageBuffer = std::move(mappedBuffer),
cImageBufferSlice = std::move(dstSlice)
] (DxvkContext* ctx) mutable {
ctx->invalidateBuffer(cImageBuffer, std::move(cImageBufferSlice));
});
if (doFlags & DoPreserve)
std::memcpy(physSlice.mapPtr, prevSlice.mapPtr, physSlice.length);
std::memcpy(dstPtr, srcPtr, bufferSize);
mapPtr = physSlice.mapPtr;
ThrottleDiscard(bufferSize);
} else {
if (doFlags & DoWait) {
// We cannot respect DO_NOT_WAIT for buffer-mapped resources since
@ -552,20 +611,17 @@ namespace dxvk {
MapFlags &= ~D3D11_MAP_FLAG_DO_NOT_WAIT;
// Wait for mapped buffer to become available
if (!WaitForResource(mappedBuffer, sequenceNumber, MapType, MapFlags))
if (!WaitForResource(*mappedBuffer, sequenceNumber, MapType, MapFlags))
return DXGI_ERROR_WAS_STILL_DRAWING;
}
mapPtr = pResource->GetMappedSlice(Subresource).mapPtr;
}
}
// Mark the given subresource as mapped
pResource->SetMapType(Subresource, MapType);
// Mark the subresource as successfully mapped
pResource->NotifyMap(Subresource, MapType);
if (pMappedResource) {
auto layout = pResource->GetSubresourceLayout(formatInfo->aspectMask, Subresource);
pMappedResource->pData = reinterpret_cast<char*>(mapPtr) + layout.Offset;
pMappedResource->pData = pResource->GetMapPtr(Subresource, layout.Offset);
pMappedResource->RowPitch = layout.RowPitch;
pMappedResource->DepthPitch = layout.DepthPitch;
}
@ -578,28 +634,35 @@ namespace dxvk {
void D3D11ImmediateContext::UnmapImage(
D3D11CommonTexture* pResource,
UINT Subresource) {
D3D11_MAP mapType = pResource->GetMapType(Subresource);
pResource->SetMapType(Subresource, D3D11_MAP(~0u));
auto mapType = pResource->GetMapType(Subresource);
auto mapMode = pResource->GetMapMode();
if (mapType == D3D11_MAP(~0u))
if (mapType == D3D11CommonTexture::UnmappedSubresource)
return;
// Decrement mapped image counter only after making sure
// the given subresource is actually mapped right now
m_mappedImageCount -= 1;
if ((mapType != D3D11_MAP_READ) && (pResource->GetMapMode() == D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER)) {
// If the texture has an image as well as a staging buffer,
// upload the written buffer data to the image
bool needsUpload = mapType != uint32_t(D3D11_MAP_READ)
&& (mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER || mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_DYNAMIC);
if (needsUpload) {
if (pResource->NeedsDirtyRegionTracking()) {
for (uint32_t i = 0; i < pResource->GetDirtyRegionCount(Subresource); i++) {
D3D11_COMMON_TEXTURE_REGION region = pResource->GetDirtyRegion(Subresource, i);
UpdateDirtyImageRegion(pResource, Subresource, &region);
}
pResource->ClearDirtyRegions(Subresource);
} else {
UpdateDirtyImageRegion(pResource, Subresource, nullptr);
}
}
// Unmap the subresource. This will implicitly destroy the
// staging buffer for dynamically mapped images.
pResource->NotifyUnmap(Subresource);
}
@ -618,18 +681,8 @@ namespace dxvk {
VkOffset3D offset = { 0, 0, 0 };
VkExtent3D extent = cSrcImage->mipLevelExtent(cSrcSubresource.mipLevel);
if (cSrcSubresource.aspectMask != (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
ctx->copyImageToBuffer(cDstBuffer, 0, 0, 0,
cSrcImage, cSrcSubresource, offset, extent);
} else {
ctx->copyDepthStencilImageToPackedBuffer(cDstBuffer, 0,
VkOffset2D { 0, 0 },
VkExtent2D { extent.width, extent.height },
cSrcImage, cSrcSubresource,
VkOffset2D { 0, 0 },
VkExtent2D { extent.width, extent.height },
cPackedFormat);
}
ctx->copyImageToBuffer(cDstBuffer, 0, 0, 0, cPackedFormat,
cSrcImage, cSrcSubresource, offset, extent);
});
if (pResource->HasSequenceNumber())
@ -676,20 +729,10 @@ namespace dxvk {
cSrcDepthPitch = subresourceLayout.DepthPitch,
cPackedFormat = pResource->GetPackedFormat()
] (DxvkContext* ctx) {
if (cDstSubresource.aspectMask != (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
ctx->copyBufferToImage(
cDstImage, cDstSubresource, cDstOffset, cDstExtent,
cSrcBuffer, cSrcOffset, cSrcRowPitch, cSrcDepthPitch);
} else {
ctx->copyPackedBufferToDepthStencilImage(
cDstImage, cDstSubresource,
VkOffset2D { cDstOffset.x, cDstOffset.y },
VkExtent2D { cDstExtent.width, cDstExtent.height },
cSrcBuffer, 0,
VkOffset2D { cDstOffset.x, cDstOffset.y },
VkExtent2D { cDstExtent.width, cDstExtent.height },
cPackedFormat);
}
ctx->copyBufferToImage(
cDstImage, cDstSubresource, cDstOffset, cDstExtent,
cSrcBuffer, cSrcOffset, cSrcRowPitch, cSrcDepthPitch,
cPackedFormat);
});
}
@ -704,22 +747,23 @@ namespace dxvk {
UINT Length,
const void* pSrcData,
UINT CopyFlags) {
DxvkBufferSliceHandle slice;
void* mapPtr = nullptr;
if (likely(CopyFlags != D3D11_COPY_NO_OVERWRITE)) {
slice = pDstBuffer->DiscardSlice();
auto bufferSlice = pDstBuffer->DiscardSlice(&m_allocationCache);
mapPtr = bufferSlice->mapPtr();
EmitCs([
cBuffer = pDstBuffer->GetBuffer(),
cBufferSlice = slice
] (DxvkContext* ctx) {
ctx->invalidateBuffer(cBuffer, cBufferSlice);
cBufferSlice = std::move(bufferSlice)
] (DxvkContext* ctx) mutable {
ctx->invalidateBuffer(cBuffer, std::move(cBufferSlice));
});
} else {
slice = pDstBuffer->GetMappedSlice();
mapPtr = pDstBuffer->GetMapPtr();
}
std::memcpy(reinterpret_cast<char*>(slice.mapPtr) + Offset, pSrcData, Length);
std::memcpy(reinterpret_cast<char*>(mapPtr) + Offset, pSrcData, Length);
}
@ -731,7 +775,11 @@ namespace dxvk {
if (!pState)
return;
// Reset all state affected by the current context state
// Clear dirty tracking here since all context state will be
// re-applied anyway when the context state is swapped in again.
ResetDirtyTracking();
// Reset all state affected by the current context state.
ResetCommandListState();
Com<D3D11DeviceContextState, false> oldState = std::move(m_stateObject);
@ -753,6 +801,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();
@ -770,17 +886,28 @@ namespace dxvk {
}
void D3D11ImmediateContext::EndFrame() {
void D3D11ImmediateContext::EndFrame(
Rc<DxvkLatencyTracker> LatencyTracker) {
D3D10DeviceLock lock = LockContext();
EmitCs<false>([] (DxvkContext* ctx) {
// Don't keep draw buffers alive indefinitely. This cannot be
// done in ExecuteFlush because command recording itself might
// flush, so no state changes are allowed to happen there.
SetDrawBuffers(nullptr, nullptr);
EmitCs<false>([
cTracker = std::move(LatencyTracker)
] (DxvkContext* ctx) {
ctx->endFrame();
if (cTracker && cTracker->needsAutoMarkers())
ctx->endLatencyTracking(cTracker);
});
}
bool D3D11ImmediateContext::WaitForResource(
const Rc<DxvkResource>& Resource,
const DxvkPagedResource& Resource,
uint64_t SequenceNumber,
D3D11_MAP MapType,
UINT MapFlags) {
@ -792,37 +919,52 @@ namespace dxvk {
// Wait for any CS chunk using the resource to execute, since
// otherwise we cannot accurately determine if the resource is
// actually being used by the GPU right now.
bool isInUse = Resource->isInUse(access);
if (!isInUse) {
if (!Resource.isInUse(access)) {
SynchronizeCsThread(SequenceNumber);
isInUse = Resource->isInUse(access);
if (!Resource.isInUse(access))
return true;
}
if (unlikely(m_device->debugFlags().test(DxvkDebugFlag::Capture))) {
m_flushReason = str::format("Map ", Resource.getDebugName(), " (MAP",
MapType != D3D11_MAP_WRITE ? "_READ" : "",
MapType != D3D11_MAP_READ ? "_WRITE" : "", ")");
}
if (MapFlags & D3D11_MAP_FLAG_DO_NOT_WAIT) {
if (isInUse) {
// 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
ConsiderFlush(GpuFlushType::ImplicitSynchronization);
return false;
}
// 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
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
ExecuteFlush(GpuFlushType::ImplicitSynchronization, nullptr);
SynchronizeCsThread(SequenceNumber);
// Make sure pending commands using the resource get
// executed on the the GPU if we have to wait for it
ExecuteFlush(GpuFlushType::ImplicitSynchronization, nullptr, false);
SynchronizeCsThread(SequenceNumber);
m_device->waitForResource(Resource, access);
}
m_device->waitForResource(Resource, access);
return true;
}
return true;
}
void D3D11ImmediateContext::InjectCsChunk(
DxvkCsQueue Queue,
DxvkCsChunkRef&& Chunk,
bool Synchronize) {
// Do not update the sequence number when emitting a chunk
// from an external source since that would break tracking
m_csThread.injectChunk(Queue, std::move(Chunk), Synchronize);
}
void D3D11ImmediateContext::EmitCsChunk(DxvkCsChunkRef&& chunk) {
// Flush init commands so that the CS thread
// can processe them before the first use.
m_parent->FlushInitCommands();
m_csSeqNum = m_csThread.dispatchChunk(std::move(chunk));
}
@ -859,28 +1001,130 @@ namespace dxvk {
}
void D3D11ImmediateContext::ApplyDirtyNullBindings() {
// At the end of a submission, set all bindings that have not been applied yet
// to null on the DXVK context. This way, we avoid keeping resources alive that
// are bound to the DXVK context but not to the immediate context.
//
// Note: This requires that all methods that may modify dirty bindings on the
// DXVK context also reset the corresponding dirty bits *before* performing the
// bind operation, or otherwise an implicit flush can potentially override them.
auto& dirtyState = m_state.lazy.bindingsDirty;
EmitCs<false>([
cDirtyState = dirtyState
] (DxvkContext* ctx) {
for (uint32_t i = 0; i < uint32_t(DxbcProgramType::Count); i++) {
auto dxStage = DxbcProgramType(i);
auto vkStage = GetShaderStage(dxStage);
// Unbind all dirty constant buffers
auto cbvSlot = computeConstantBufferBinding(dxStage, 0);
for (uint32_t index : bit::BitMask(cDirtyState[dxStage].cbvMask))
ctx->bindUniformBuffer(vkStage, cbvSlot + index, DxvkBufferSlice());
// Unbind all dirty samplers
auto samplerSlot = computeSamplerBinding(dxStage, 0);
for (uint32_t index : bit::BitMask(cDirtyState[dxStage].samplerMask))
ctx->bindResourceSampler(vkStage, samplerSlot + index, nullptr);
// Unbind all dirty shader resource views
auto srvSlot = computeSrvBinding(dxStage, 0);
for (uint32_t m = 0; m < cDirtyState[dxStage].srvMask.size(); m++) {
for (uint32_t index : bit::BitMask(cDirtyState[dxStage].srvMask[m]))
ctx->bindResourceImageView(vkStage, srvSlot + index + m * 64u, nullptr);
}
// Unbind all dirty unordered access views
VkShaderStageFlags uavStages = 0u;
if (dxStage == DxbcProgramType::ComputeShader)
uavStages = VK_SHADER_STAGE_COMPUTE_BIT;
else if (dxStage == DxbcProgramType::PixelShader)
uavStages = VK_SHADER_STAGE_ALL_GRAPHICS;
if (uavStages) {
auto uavSlot = computeUavBinding(dxStage, 0);
auto ctrSlot = computeUavCounterBinding(dxStage, 0);
for (uint32_t index : bit::BitMask(cDirtyState[dxStage].uavMask)) {
ctx->bindResourceImageView(vkStage, uavSlot + index, nullptr);
ctx->bindResourceBufferView(vkStage, ctrSlot + index, nullptr);
}
}
}
});
// Since we set the DXVK context bindings to null, any bindings that are null
// on the D3D context are no longer dirty, so we can clear the respective bits.
for (uint32_t i = 0; i < uint32_t(DxbcProgramType::Count); i++) {
auto stage = DxbcProgramType(i);
for (uint32_t index : bit::BitMask(dirtyState[stage].cbvMask)) {
if (!m_state.cbv[stage].buffers[index].buffer.ptr())
dirtyState[stage].cbvMask &= ~(1u << index);
}
for (uint32_t index : bit::BitMask(dirtyState[stage].samplerMask)) {
if (!m_state.samplers[stage].samplers[index])
dirtyState[stage].samplerMask &= ~(1u << index);
}
for (uint32_t m = 0; m < dirtyState[stage].srvMask.size(); m++) {
for (uint32_t index : bit::BitMask(dirtyState[stage].srvMask[m])) {
if (!m_state.srv[stage].views[index + m * 64u].ptr())
dirtyState[stage].srvMask[m] &= ~(uint64_t(1u) << index);
}
}
if (stage == DxbcProgramType::ComputeShader || stage == DxbcProgramType::PixelShader) {
auto& uavs = stage == DxbcProgramType::ComputeShader ? m_state.uav.views : m_state.om.uavs;
for (uint32_t index : bit::BitMask(dirtyState[stage].uavMask)) {
if (!uavs[index].ptr())
dirtyState[stage].uavMask &= ~(uint64_t(1u) << index);
}
}
if (dirtyState[stage].empty())
m_state.lazy.shadersDirty.clr(stage);
}
}
void D3D11ImmediateContext::ConsiderFlush(
GpuFlushType FlushType) {
// In stress test mode, behave as if this would always flush
if (DebugLazyBinding == Tristate::True)
ApplyDirtyNullBindings();
uint64_t chunkId = GetCurrentSequenceNumber();
uint64_t submissionId = m_submissionFence->value();
if (m_flushTracker.considerFlush(FlushType, chunkId, submissionId))
ExecuteFlush(FlushType, nullptr);
ExecuteFlush(FlushType, nullptr, false);
}
void D3D11ImmediateContext::ExecuteFlush(
GpuFlushType FlushType,
HANDLE hEvent) {
// 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();
HANDLE hEvent,
BOOL Synchronize) {
bool synchronizeSubmission = Synchronize && m_parent->Is11on12Device();
if (synchronizeSubmission)
m_submitStatus.result = VK_NOT_READY;
// Exit early if there's nothing to do
if (!GetPendingCsChunks() && !hEvent)
return;
// Unbind unused resources
ApplyDirtyNullBindings();
// Signal the submission fence and flush the command list
uint64_t submissionId = ++m_submissionId;
@ -892,10 +1136,17 @@ namespace dxvk {
EmitCs<false>([
cSubmissionFence = m_submissionFence,
cSubmissionId = submissionId
cSubmissionId = submissionId,
cSubmissionStatus = synchronizeSubmission ? &m_submitStatus : nullptr,
cStagingFence = m_stagingBufferFence,
cStagingMemory = GetStagingMemoryStatistics().allocatedTotal,
cFlushReason = std::exchange(m_flushReason, std::string())
] (DxvkContext* ctx) {
auto debugLabel = vk::makeLabel(0xff5959, cFlushReason.c_str());
ctx->signal(cSubmissionFence, cSubmissionId);
ctx->flushCommandList();
ctx->signal(cStagingFence, cStagingMemory);
ctx->flushCommandList(&debugLabel, cSubmissionStatus);
});
FlushCsChunk();
@ -903,6 +1154,74 @@ namespace dxvk {
// 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);
// Free local staging buffer so that we don't
// end up with a persistent allocation
ResetStagingBuffer();
// Reset counter for discarded memory in flight
m_discardMemoryOnFlush = m_discardMemoryCounter;
// Notify the device that the context has been flushed,
// this resets some resource initialization heuristics.
m_parent->NotifyContextFlush();
// No point in tracking this across submissions
m_hasPendingMsaaResolve = false;
}
void D3D11ImmediateContext::ThrottleAllocation() {
DxvkStagingBufferStats stats = GetStagingMemoryStatistics();
VkDeviceSize stagingMemoryInFlight = stats.allocatedTotal - m_stagingBufferFence->value();
if (stagingMemoryInFlight > stats.allocatedSinceLastReset + D3D11Initializer::MaxMemoryInFlight) {
// Stall calling thread to avoid situation where we keep growing the staging
// buffer indefinitely, but ignore the newly allocated amount so that we don't
// wait for the GPU to go fully idle in case of a large allocation.
ExecuteFlush(GpuFlushType::ExplicitFlush, nullptr, false);
m_device->waitForFence(*m_stagingBufferFence, stats.allocatedTotal -
stats.allocatedSinceLastReset - D3D11Initializer::MaxMemoryInFlight);
} else if (stats.allocatedSinceLastReset >= D3D11Initializer::MaxMemoryPerSubmission) {
// Flush somewhat aggressively if there's a lot of memory in flight
ExecuteFlush(GpuFlushType::ExplicitFlush, nullptr, false);
}
}
void D3D11ImmediateContext::ThrottleDiscard(
VkDeviceSize Size) {
m_discardMemoryCounter += Size;
if (m_discardMemoryCounter - m_discardMemoryOnFlush >= D3D11Initializer::MaxMemoryPerSubmission)
ThrottleAllocation();
}
DxvkStagingBufferStats D3D11ImmediateContext::GetStagingMemoryStatistics() {
DxvkStagingBufferStats stats = m_staging.getStatistics();
stats.allocatedTotal += m_discardMemoryCounter;
stats.allocatedSinceLastReset += m_discardMemoryCounter - m_discardMemoryOnFlush;
return stats;
}
GpuFlushType D3D11ImmediateContext::GetMaxFlushType(
D3D11Device* pParent,
const Rc<DxvkDevice>& Device) {
if (pParent->GetOptions()->reproducibleCommandStream)
return GpuFlushType::ExplicitFlush;
else if (Device->perfHints().preferRenderPassOps)
return GpuFlushType::ImplicitMediumHint;
else
return GpuFlushType::ImplicitWeakHint;
}
}

View file

@ -17,6 +17,7 @@ namespace dxvk {
friend class D3D11CommonContext<D3D11ImmediateContext>;
friend class D3D11SwapChain;
friend class D3D11VideoContext;
friend class D3D11DXGIKeyedMutex;
public:
D3D11ImmediateContext(
@ -77,13 +78,40 @@ 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();
}
void InjectCsChunk(
DxvkCsQueue Queue,
DxvkCsChunkRef&& Chunk,
bool Synchronize);
template<typename Fn>
void InjectCs(
DxvkCsQueue Queue,
Fn&& Command) {
auto chunk = AllocCsChunk();
chunk->push(std::move(Command));
InjectCsChunk(Queue, std::move(chunk), false);
}
private:
DxvkCsThread m_csThread;
@ -91,19 +119,27 @@ namespace dxvk {
uint32_t m_mappedImageCount = 0u;
VkDeviceSize m_maxImplicitDiscardSize = 0ull;
Rc<sync::CallbackFence> m_submissionFence;
uint64_t m_submissionId = 0ull;
DxvkSubmitStatus m_submitStatus;
uint64_t m_flushSeqNum = 0ull;
GpuFlushTracker m_flushTracker;
Rc<sync::Fence> m_stagingBufferFence;
VkDeviceSize m_discardMemoryCounter = 0u;
VkDeviceSize m_discardMemoryOnFlush = 0u;
bool m_hasPendingMsaaResolve = false;
D3D10Multithread m_multithread;
D3D11VideoContext m_videoContext;
Com<D3D11DeviceContextState, false> m_stateObject;
std::string m_flushReason;
HRESULT MapBuffer(
D3D11Buffer* pResource,
D3D11_MAP MapType,
@ -139,10 +175,11 @@ namespace dxvk {
void SynchronizeDevice();
void EndFrame();
void EndFrame(
Rc<DxvkLatencyTracker> LatencyTracker);
bool WaitForResource(
const Rc<DxvkResource>& Resource,
const DxvkPagedResource& Resource,
uint64_t SequenceNumber,
D3D11_MAP MapType,
UINT MapFlags);
@ -160,12 +197,26 @@ namespace dxvk {
uint64_t GetPendingCsChunks();
void ApplyDirtyNullBindings();
void ConsiderFlush(
GpuFlushType FlushType);
void ExecuteFlush(
GpuFlushType FlushType,
HANDLE hEvent);
HANDLE hEvent,
BOOL Synchronize);
void ThrottleAllocation();
void ThrottleDiscard(
VkDeviceSize Size);
DxvkStagingBufferStats GetStagingMemoryStatistics();
static GpuFlushType GetMaxFlushType(
D3D11Device* pParent,
const Rc<DxvkDevice>& Device);
};

View file

@ -199,10 +199,11 @@ namespace dxvk {
UINT stencilRef = D3D11_DEFAULT_STENCIL_REFERENCE;
UINT maxRtv = 0u;
UINT minUav = D3D11_1_UAV_SLOT_COUNT;
UINT maxUav = 0u;
void reset() {
for (uint32_t i = 0; i < maxUav; i++)
for (uint32_t i = minUav; i < maxUav; i++)
uavs[i] = nullptr;
for (uint32_t i = 0; i < maxRtv; i++)
@ -220,8 +221,9 @@ namespace dxvk {
sampleMask = D3D11_DEFAULT_SAMPLE_MASK;
stencilRef = D3D11_DEFAULT_STENCIL_REFERENCE;
maxRtv = 0;
maxUav = 0;
maxRtv = 0u;
minUav = D3D11_1_UAV_SLOT_COUNT;
maxUav = 0u;
}
};
@ -232,12 +234,12 @@ namespace dxvk {
* argument and draw count buffer.
*/
struct D3D11ContextStateID {
Com<D3D11Buffer, false> argBuffer = nullptr;
Com<D3D11Buffer, false> cntBuffer = nullptr;
uint64_t argBufferCookie = 0u;
uint64_t cntBufferCookie = 0u;
void reset() {
argBuffer = nullptr;
cntBuffer = nullptr;
argBufferCookie = 0u;
cntBufferCookie = 0u;
}
};
@ -302,6 +304,32 @@ namespace dxvk {
predicateValue = false;
}
};
/**
* \brief Lazy binding state
*
* Keeps track of what state needs to be
* re-applied to the context.
*/
struct D3D11LazyBindings {
DxbcProgramTypeFlags shadersUsed = 0u;
DxbcProgramTypeFlags shadersDirty = 0u;
DxbcProgramTypeFlags graphicsUavShaders = 0u;
D3D11ShaderStageState<DxbcBindingMask> bindingsUsed;
D3D11ShaderStageState<DxbcBindingMask> bindingsDirty;
void reset() {
shadersUsed = 0u;
shadersDirty = 0u;
graphicsUavShaders = 0u;
bindingsUsed.reset();
bindingsDirty.reset();
}
};
/**
* \brief Context state
@ -325,6 +353,8 @@ namespace dxvk {
D3D11SrvBindings srv;
D3D11UavBindings uav;
D3D11SamplerBindings samplers;
D3D11LazyBindings lazy;
};
/**
@ -342,9 +372,9 @@ namespace dxvk {
* \brief Maximum used binding numbers for all context state
*/
struct D3D11MaxUsedBindings {
std::array<D3D11MaxUsedStageBindings, 6> stages;
std::array<D3D11MaxUsedStageBindings, uint32_t(DxbcProgramType::Count)> stages;
uint32_t vbCount;
uint32_t soCount;
};
}
}

View file

@ -3,7 +3,8 @@
#include <utility>
#include <vector>
#include "../dxvk/dxvk_resource.h"
#include "../dxvk/dxvk_memory.h"
#include "../dxvk/dxvk_sparse.h"
#include "../util/com/com_guid.h"
#include "../util/com/com_object.h"

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;
@ -183,7 +183,7 @@ namespace dxvk {
desc.TextureLayout = D3D11_TEXTURE_LAYOUT_UNDEFINED;
ID3D11Texture2D1* texture2D = nullptr;
HRESULT hr = CreateTexture2D1(&desc, pInitialData, ppTexture2D ? &texture2D : nullptr);
HRESULT hr = CreateTexture2DBase(&desc, pInitialData, ppTexture2D ? &texture2D : nullptr);
if (hr != S_OK)
return hr;
@ -202,6 +202,14 @@ namespace dxvk {
if (!pDesc)
return E_INVALIDARG;
return CreateTexture2DBase(pDesc, pInitialData, ppTexture2D);
}
HRESULT STDMETHODCALLTYPE D3D11Device::CreateTexture2DBase(
const D3D11_TEXTURE2D_DESC1* pDesc,
const D3D11_SUBRESOURCE_DATA* pInitialData,
ID3D11Texture2D1** ppTexture2D) {
D3D11_COMMON_TEXTURE_DESC desc;
desc.Width = pDesc->Width;
desc.Height = pDesc->Height;
@ -229,7 +237,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;
@ -262,7 +270,7 @@ namespace dxvk {
desc.TextureLayout = D3D11_TEXTURE_LAYOUT_UNDEFINED;
ID3D11Texture3D1* texture3D = nullptr;
HRESULT hr = CreateTexture3D1(&desc, pInitialData, ppTexture3D ? &texture3D : nullptr);
HRESULT hr = CreateTexture3DBase(&desc, pInitialData, ppTexture3D ? &texture3D : nullptr);
if (hr != S_OK)
return hr;
@ -280,7 +288,15 @@ namespace dxvk {
if (!pDesc)
return E_INVALIDARG;
return CreateTexture3DBase(pDesc, pInitialData, ppTexture3D);
}
HRESULT STDMETHODCALLTYPE D3D11Device::CreateTexture3DBase(
const D3D11_TEXTURE3D_DESC1* pDesc,
const D3D11_SUBRESOURCE_DATA* pInitialData,
ID3D11Texture3D1** ppTexture3D) {
D3D11_COMMON_TEXTURE_DESC desc;
desc.Width = pDesc->Width;
desc.Height = pDesc->Height;
@ -308,7 +324,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;
@ -325,6 +341,9 @@ namespace dxvk {
ID3D11ShaderResourceView** ppSRView) {
InitReturnPtr(ppSRView);
if (!pResource)
return E_INVALIDARG;
uint32_t plane = GetViewPlaneIndex(pResource, pDesc ? pDesc->Format : DXGI_FORMAT_UNKNOWN);
D3D11_SHADER_RESOURCE_VIEW_DESC1 desc = pDesc
@ -333,7 +352,7 @@ namespace dxvk {
ID3D11ShaderResourceView1* view = nullptr;
HRESULT hr = CreateShaderResourceView1(pResource,
HRESULT hr = CreateShaderResourceViewBase(pResource,
pDesc ? &desc : nullptr,
ppSRView ? &view : nullptr);
@ -353,7 +372,15 @@ namespace dxvk {
if (!pResource)
return E_INVALIDARG;
return CreateShaderResourceViewBase(pResource, pDesc, ppSRView);
}
HRESULT STDMETHODCALLTYPE D3D11Device::CreateShaderResourceViewBase(
ID3D11Resource* pResource,
const D3D11_SHADER_RESOURCE_VIEW_DESC1* pDesc,
ID3D11ShaderResourceView1** ppSRView) {
D3D11_COMMON_RESOURCE_DESC resourceDesc;
GetCommonResourceDesc(pResource, &resourceDesc);
@ -402,21 +429,24 @@ namespace dxvk {
ID3D11UnorderedAccessView** ppUAView) {
InitReturnPtr(ppUAView);
if (!pResource)
return E_INVALIDARG;
uint32_t plane = GetViewPlaneIndex(pResource, pDesc ? pDesc->Format : DXGI_FORMAT_UNKNOWN);
D3D11_UNORDERED_ACCESS_VIEW_DESC1 desc = pDesc
? D3D11UnorderedAccessView::PromoteDesc(pDesc, plane)
: D3D11_UNORDERED_ACCESS_VIEW_DESC1();
ID3D11UnorderedAccessView1* view = nullptr;
HRESULT hr = CreateUnorderedAccessView1(pResource,
HRESULT hr = CreateUnorderedAccessViewBase(pResource,
pDesc ? &desc : nullptr,
ppUAView ? &view : nullptr);
if (hr != S_OK)
return hr;
*ppUAView = view;
return S_OK;
}
@ -430,7 +460,15 @@ namespace dxvk {
if (!pResource)
return E_INVALIDARG;
return CreateUnorderedAccessViewBase(pResource, pDesc, ppUAView);
}
HRESULT STDMETHODCALLTYPE D3D11Device::CreateUnorderedAccessViewBase(
ID3D11Resource* pResource,
const D3D11_UNORDERED_ACCESS_VIEW_DESC1* pDesc,
ID3D11UnorderedAccessView1** ppUAView) {
D3D11_COMMON_RESOURCE_DESC resourceDesc;
GetCommonResourceDesc(pResource, &resourceDesc);
@ -481,6 +519,9 @@ namespace dxvk {
ID3D11RenderTargetView** ppRTView) {
InitReturnPtr(ppRTView);
if (!pResource)
return E_INVALIDARG;
uint32_t plane = GetViewPlaneIndex(pResource, pDesc ? pDesc->Format : DXGI_FORMAT_UNKNOWN);
D3D11_RENDER_TARGET_VIEW_DESC1 desc = pDesc
@ -489,7 +530,7 @@ namespace dxvk {
ID3D11RenderTargetView1* view = nullptr;
HRESULT hr = CreateRenderTargetView1(pResource,
HRESULT hr = CreateRenderTargetViewBase(pResource,
pDesc ? &desc : nullptr,
ppRTView ? &view : nullptr);
@ -509,7 +550,15 @@ namespace dxvk {
if (!pResource)
return E_INVALIDARG;
return CreateRenderTargetViewBase(pResource, pDesc, ppRTView);
}
HRESULT STDMETHODCALLTYPE D3D11Device::CreateRenderTargetViewBase(
ID3D11Resource* pResource,
const D3D11_RENDER_TARGET_VIEW_DESC1* pDesc,
ID3D11RenderTargetView1** ppRTView) {
// DXVK only supports render target views for image resources
D3D11_COMMON_RESOURCE_DESC resourceDesc;
GetCommonResourceDesc(pResource, &resourceDesc);
@ -1202,7 +1251,7 @@ namespace dxvk {
desc.ContextType = D3D11_CONTEXT_TYPE_ALL;
ID3D11Query1* query = nullptr;
HRESULT hr = CreateQuery1(&desc, ppQuery ? &query : nullptr);
HRESULT hr = CreateQueryBase(&desc, ppQuery ? &query : nullptr);
if (hr != S_OK)
return hr;
@ -1219,7 +1268,14 @@ namespace dxvk {
if (!pQueryDesc)
return E_INVALIDARG;
return CreateQueryBase(pQueryDesc, ppQuery);
}
HRESULT STDMETHODCALLTYPE D3D11Device::CreateQueryBase(
const D3D11_QUERY_DESC1* pQueryDesc,
ID3D11Query1** ppQuery) {
HRESULT hr = D3D11Query::ValidateDesc(pQueryDesc);
if (FAILED(hr))
@ -1348,7 +1404,7 @@ namespace dxvk {
m_deviceFeatures = D3D11DeviceFeatures(
m_dxvkDevice->instance(),
m_dxvkDevice->adapter(),
m_featureLevel);
m_d3d11Options, m_featureLevel);
}
if (pChosenFeatureLevel)
@ -1396,10 +1452,10 @@ namespace dxvk {
|| texture->CountSubresources() <= SrcSubresource)
return;
D3D11_MAP map = texture->GetMapType(SrcSubresource);
uint32_t map = texture->GetMapType(SrcSubresource);
if (map != D3D11_MAP_READ
&& map != D3D11_MAP_READ_WRITE)
if (map != uint32_t(D3D11_MAP_READ)
&& map != uint32_t(D3D11_MAP_READ_WRITE))
return;
CopySubresourceData(
@ -1425,11 +1481,11 @@ namespace dxvk {
|| texture->CountSubresources() <= DstSubresource)
return;
D3D11_MAP map = texture->GetMapType(DstSubresource);
uint32_t map = texture->GetMapType(DstSubresource);
if (map != D3D11_MAP_WRITE
&& map != D3D11_MAP_WRITE_NO_OVERWRITE
&& map != D3D11_MAP_READ_WRITE)
if (map != uint32_t(D3D11_MAP_WRITE)
&& map != uint32_t(D3D11_MAP_WRITE_NO_OVERWRITE)
&& map != uint32_t(D3D11_MAP_READ_WRITE))
return;
CopySubresourceData(
@ -1832,10 +1888,10 @@ namespace dxvk {
DXGI_VK_FORMAT_MODE Mode) const {
return m_d3d11Formats.GetFormatFamily(Format, Mode);
}
void D3D11Device::FlushInitContext() {
m_initializer->Flush();
bool D3D11Device::Is11on12Device() const {
return m_container->Is11on12Device();
}
@ -1900,8 +1956,6 @@ namespace dxvk {
enabled.core.features.shaderImageGatherExtended = VK_TRUE;
enabled.core.features.textureCompressionBC = VK_TRUE;
enabled.vk11.shaderDrawParameters = VK_TRUE;
enabled.vk12.samplerMirrorClampToEdge = VK_TRUE;
enabled.vk13.shaderDemoteToHelperInvocation = VK_TRUE;
@ -1918,7 +1972,6 @@ namespace dxvk {
// Required for Feature Level 11_0
enabled.core.features.drawIndirectFirstInstance = supported.core.features.drawIndirectFirstInstance;
enabled.core.features.fragmentStoresAndAtomics = supported.core.features.fragmentStoresAndAtomics;
enabled.core.features.multiDrawIndirect = supported.core.features.multiDrawIndirect;
enabled.core.features.tessellationShader = supported.core.features.tessellationShader;
// Required for Feature Level 11_1
@ -1948,6 +2001,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;
}
@ -1959,6 +2017,9 @@ namespace dxvk {
size_t BytecodeLength,
ID3D11ClassLinkage* pClassLinkage,
const DxbcModuleInfo* pModuleInfo) {
if (!BytecodeLength || !pShaderBytecode)
return E_INVALIDARG;
if (pClassLinkage != nullptr)
Logger::warn("D3D11Device::CreateShaderModule: Class linkage not supported");
@ -2299,10 +2360,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;
}
@ -2370,11 +2435,7 @@ namespace dxvk {
D3D11_COMMON_TEXTURE_SUBRESOURCE_LAYOUT layout = pTexture->GetSubresourceLayout(aspect, Subresource);
// Compute actual map pointer, accounting for the region offset
VkDeviceSize mapOffset = pTexture->ComputeMappedOffset(Subresource, i, offset);
void* mapPtr = pTexture->GetMapMode() == D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER
? pTexture->GetMappedBuffer(Subresource)->mapPtr(mapOffset)
: image->mapPtr(mapOffset);
void* mapPtr = pTexture->GetMapPtr(Subresource, pTexture->ComputeMappedOffset(Subresource, i, offset));
if constexpr (std::is_const<Void>::value) {
// WriteToSubresource
@ -2478,15 +2539,15 @@ namespace dxvk {
D3D11SamplerState* pSS = static_cast<D3D11SamplerState*>(samplerState);
Rc<DxvkSampler> pDSS = pSS->GetDXVKSampler();
VkSampler vkSampler = pDSS->handle();
D3D11ShaderResourceView* pSRV = static_cast<D3D11ShaderResourceView*>(srv);
Rc<DxvkImageView> pIV = pSRV->GetImageView();
VkImageView vkImageView = pIV->handle();
VkImageViewHandleInfoNVX imageViewHandleInfo = {VK_STRUCTURE_TYPE_IMAGE_VIEW_HANDLE_INFO_NVX};
imageViewHandleInfo.imageView = vkImageView;
imageViewHandleInfo.sampler = vkSampler;
LockImage(pIV->image(), 0u);
VkImageViewHandleInfoNVX imageViewHandleInfo = { VK_STRUCTURE_TYPE_IMAGE_VIEW_HANDLE_INFO_NVX };
imageViewHandleInfo.imageView = pIV->handle();
imageViewHandleInfo.sampler = pDSS->handle();
imageViewHandleInfo.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
// note: there's no implicit lifetime management here; it's up to the
@ -2544,21 +2605,9 @@ namespace dxvk {
ID3D11Resource* pResource = static_cast<ID3D11Resource*>(hObject);
D3D11_COMMON_RESOURCE_DESC resourceDesc;
if (FAILED(GetCommonResourceDesc(pResource, &resourceDesc))) {
Logger::warn("GetResourceHandleGPUVirtualAddressAndSize() - GetCommonResourceDesc() failed");
return false;
}
switch (resourceDesc.Dim) {
case D3D11_RESOURCE_DIMENSION_BUFFER:
case D3D11_RESOURCE_DIMENSION_TEXTURE2D:
// okay - we can deal with those two dimensions
break;
case D3D11_RESOURCE_DIMENSION_TEXTURE1D:
case D3D11_RESOURCE_DIMENSION_TEXTURE3D:
case D3D11_RESOURCE_DIMENSION_UNKNOWN:
default:
Logger::warn(str::format("GetResourceHandleGPUVirtualAddressAndSize(?) - failure - unsupported dimension: ", resourceDesc.Dim));
if (FAILED(GetCommonResourceDesc(pResource, &resourceDesc))) {
Logger::warn("GetResourceHandleGPUVirtualAddressAndSize: Invalid resource");
return false;
}
@ -2567,57 +2616,49 @@ namespace dxvk {
if (resourceDesc.Dim == D3D11_RESOURCE_DIMENSION_TEXTURE2D) {
D3D11CommonTexture *texture = GetCommonTexture(pResource);
// Ensure that the image has a stable GPU address and
// won't be relocated by the backend going forward
Rc<DxvkImage> dxvkImage = texture->GetImage();
if (0 == (dxvkImage->info().usage & (VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT))) {
Logger::warn(str::format("GetResourceHandleGPUVirtualAddressAndSize(res=", pResource,") image info missing required usage bit(s); can't be used for vkGetImageViewHandleNVX - failure"));
if (!LockImage(dxvkImage, VK_IMAGE_USAGE_SAMPLED_BIT))
return false;
}
// The d3d11 nvapi provides us a texture but vulkan only lets us get the GPU address from an imageview. So, make a private imageview and get the address from that...
// The d3d11 nvapi provides us a texture, but vulkan only lets us
// get the GPU address from an image view. So, make a private image
// view and get the address from that.
DxvkImageViewKey viewInfo;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.format = dxvkImage->info().format;
viewInfo.aspects = dxvkImage->formatInfo()->aspectMask;
viewInfo.mipIndex = 0;
viewInfo.mipCount = dxvkImage->info().mipLevels;
viewInfo.layerIndex = 0;
viewInfo.layerCount = 1;
viewInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
D3D11_SHADER_RESOURCE_VIEW_DESC resourceViewDesc;
auto dxvkView = dxvkImage->createView(viewInfo);
VkImageViewAddressPropertiesNVX imageViewAddressProperties = { VK_STRUCTURE_TYPE_IMAGE_VIEW_ADDRESS_PROPERTIES_NVX };
const D3D11_COMMON_TEXTURE_DESC *texDesc = texture->Desc();
if (texDesc->ArraySize != 1) {
Logger::debug(str::format("GetResourceHandleGPUVirtualAddressAndSize(?) - unexpected array size: ", texDesc->ArraySize));
}
resourceViewDesc.Format = texDesc->Format;
resourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
resourceViewDesc.Texture2D.MostDetailedMip = 0;
resourceViewDesc.Texture2D.MipLevels = texDesc->MipLevels;
VkResult vr = dxvkDevice->vkd()->vkGetImageViewAddressNVX(vkDevice,
dxvkView->handle(), &imageViewAddressProperties);
Com<ID3D11ShaderResourceView> pNewSRV;
HRESULT hr = m_device->CreateShaderResourceView(pResource, &resourceViewDesc, &pNewSRV);
if (FAILED(hr)) {
Logger::warn("GetResourceHandleGPUVirtualAddressAndSize() - private CreateShaderResourceView() failed");
return false;
}
Rc<DxvkImageView> dxvkImageView = static_cast<D3D11ShaderResourceView*>(pNewSRV.ptr())->GetImageView();
VkImageView vkImageView = dxvkImageView->handle();
VkImageViewAddressPropertiesNVX imageViewAddressProperties = {VK_STRUCTURE_TYPE_IMAGE_VIEW_ADDRESS_PROPERTIES_NVX};
VkResult res = dxvkDevice->vkd()->vkGetImageViewAddressNVX(vkDevice, vkImageView, &imageViewAddressProperties);
if (res != VK_SUCCESS) {
Logger::warn(str::format("GetResourceHandleGPUVirtualAddressAndSize(): vkGetImageViewAddressNVX() result is failure: ", res));
if (vr != VK_SUCCESS) {
Logger::warn(str::format("GetResourceHandleGPUVirtualAddressAndSize(): Failed: vr = ", vr));
return false;
}
*gpuVAStart = imageViewAddressProperties.deviceAddress;
*gpuVASize = imageViewAddressProperties.size;
}
else if (resourceDesc.Dim == D3D11_RESOURCE_DIMENSION_BUFFER) {
D3D11Buffer *buffer = GetCommonBuffer(pResource);
const DxvkBufferSliceHandle bufSliceHandle = buffer->GetBuffer()->getSliceHandle();
VkBuffer vkBuffer = bufSliceHandle.handle;
} else if (resourceDesc.Dim == D3D11_RESOURCE_DIMENSION_BUFFER) {
Rc<DxvkBuffer> dxvkBuffer = GetCommonBuffer(pResource)->GetBuffer();
LockBuffer(dxvkBuffer);
VkBufferDeviceAddressInfo bdaInfo = { VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO };
bdaInfo.buffer = vkBuffer;
VkDeviceAddress bufAddr = dxvkDevice->vkd()->vkGetBufferDeviceAddress(vkDevice, &bdaInfo);
*gpuVAStart = uint64_t(bufAddr) + bufSliceHandle.offset;
*gpuVASize = bufSliceHandle.length;
*gpuVAStart = dxvkBuffer->gpuAddress();
*gpuVASize = dxvkBuffer->info().size;
} else {
Logger::warn(str::format("GetResourceHandleGPUVirtualAddressAndSize(): Unsupported resource type: ", resourceDesc.Dim));
return false;
}
if (!*gpuVAStart)
@ -2627,102 +2668,99 @@ namespace dxvk {
}
bool STDMETHODCALLTYPE D3D11DeviceExt::CreateUnorderedAccessViewAndGetDriverHandleNVX(ID3D11Resource* pResource, const D3D11_UNORDERED_ACCESS_VIEW_DESC* pDesc, ID3D11UnorderedAccessView** ppUAV, uint32_t* pDriverHandle) {
D3D11_COMMON_RESOURCE_DESC resourceDesc;
if (!SUCCEEDED(GetCommonResourceDesc(pResource, &resourceDesc))) {
Logger::warn("CreateUnorderedAccessViewAndGetDriverHandleNVX() - GetCommonResourceDesc() failed");
return false;
}
bool STDMETHODCALLTYPE D3D11DeviceExt::CreateUnorderedAccessViewAndGetDriverHandleNVX(
ID3D11Resource* pResource,
const D3D11_UNORDERED_ACCESS_VIEW_DESC* pDesc,
ID3D11UnorderedAccessView** ppUAV,
uint32_t* pDriverHandle) {
D3D11_COMMON_RESOURCE_DESC resourceDesc = { };
GetCommonResourceDesc(pResource, &resourceDesc);
if (resourceDesc.Dim != D3D11_RESOURCE_DIMENSION_TEXTURE2D) {
Logger::warn(str::format("CreateUnorderedAccessViewAndGetDriverHandleNVX() - failure - unsupported dimension: ", resourceDesc.Dim));
Logger::warn(str::format("CreateUnorderedAccessViewAndGetDriverHandleNVX(): Unsupported dimension: ", resourceDesc.Dim));
return false;
}
auto texture = GetCommonTexture(pResource);
Rc<DxvkImage> dxvkImage = texture->GetImage();
if (0 == (dxvkImage->info().usage & (VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT))) {
Logger::warn(str::format("CreateUnorderedAccessViewAndGetDriverHandleNVX(res=", pResource, ") image info missing required usage bit(s); can't be used for vkGetImageViewHandleNVX - failure"));
Rc<DxvkImage> dxvkImage = GetCommonTexture(pResource)->GetImage();
if (!(dxvkImage->info().usage & VK_IMAGE_USAGE_STORAGE_BIT)) {
Logger::warn(str::format("CreateUnorderedAccessViewAndGetDriverHandleNVX(res=", pResource, "): Image not UAV compatible"));
return false;
}
if (!SUCCEEDED(m_device->CreateUnorderedAccessView(pResource, pDesc, ppUAV))) {
return false;
}
Com<ID3D11UnorderedAccessView> uav;
D3D11UnorderedAccessView *pUAV = static_cast<D3D11UnorderedAccessView *>(*ppUAV);
Rc<DxvkDevice> dxvkDevice = m_device->GetDXVKDevice();
VkDevice vkDevice = dxvkDevice->handle();
if (FAILED(m_device->CreateUnorderedAccessView(pResource, pDesc, &uav)))
return false;
Rc<DxvkImageView> dxvkImageView = static_cast<D3D11UnorderedAccessView*>(uav.ptr())->GetImageView();
LockImage(dxvkImageView->image(), 0u);
VkImageViewHandleInfoNVX imageViewHandleInfo = {VK_STRUCTURE_TYPE_IMAGE_VIEW_HANDLE_INFO_NVX};
Rc<DxvkImageView> dxvkImageView = pUAV->GetImageView();
VkImageView vkImageView = dxvkImageView->handle();
imageViewHandleInfo.imageView = vkImageView;
imageViewHandleInfo.imageView = dxvkImageView->handle();
imageViewHandleInfo.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
*pDriverHandle = dxvkDevice->vkd()->vkGetImageViewHandleNVX(vkDevice, &imageViewHandleInfo);
Rc<DxvkDevice> dxvkDevice = m_device->GetDXVKDevice();
*pDriverHandle = dxvkDevice->vkd()->vkGetImageViewHandleNVX(
dxvkDevice->handle(), &imageViewHandleInfo);
if (!*pDriverHandle) {
Logger::warn("CreateUnorderedAccessViewAndGetDriverHandleNVX() handle==0 - failure");
pUAV->Release();
Logger::warn("CreateUnorderedAccessViewAndGetDriverHandleNVX(): Handle is 0");
return false;
}
*ppUAV = uav.ref();
return true;
}
bool STDMETHODCALLTYPE D3D11DeviceExt::CreateShaderResourceViewAndGetDriverHandleNVX(ID3D11Resource* pResource, const D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc, ID3D11ShaderResourceView** ppSRV, uint32_t* pDriverHandle) {
D3D11_COMMON_RESOURCE_DESC resourceDesc;
if (!SUCCEEDED(GetCommonResourceDesc(pResource, &resourceDesc))) {
Logger::warn("CreateShaderResourceViewAndGetDriverHandleNVX() - GetCommonResourceDesc() failed");
return false;
}
D3D11_COMMON_RESOURCE_DESC resourceDesc = { };
GetCommonResourceDesc(pResource, &resourceDesc);
if (resourceDesc.Dim != D3D11_RESOURCE_DIMENSION_TEXTURE2D) {
Logger::warn(str::format("CreateShaderResourceViewAndGetDriverHandleNVX() - failure - unsupported dimension: ", resourceDesc.Dim));
Logger::warn(str::format("CreateShaderResourceViewAndGetDriverHandleNVX(): Unsupported dimension: ", resourceDesc.Dim));
return false;
}
auto texture = GetCommonTexture(pResource);
Rc<DxvkImage> dxvkImage = texture->GetImage();
if (0 == (dxvkImage->info().usage & (VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT))) {
Logger::warn(str::format("CreateShaderResourceViewAndGetDriverHandleNVX(res=", pResource, ") image info missing required usage bit(s); can't be used for vkGetImageViewHandleNVX - failure"));
Rc<DxvkImage> dxvkImage = GetCommonTexture(pResource)->GetImage();
if (!(dxvkImage->info().usage & VK_IMAGE_USAGE_SAMPLED_BIT)) {
Logger::warn(str::format("CreateShaderResourceViewAndGetDriverHandleNVX(res=", pResource, "): Image not SRV compatible"));
return false;
}
if (!SUCCEEDED(m_device->CreateShaderResourceView(pResource, pDesc, ppSRV))) {
return false;
}
Com<ID3D11ShaderResourceView> srv;
D3D11ShaderResourceView* pSRV = static_cast<D3D11ShaderResourceView*>(*ppSRV);
Rc<DxvkDevice> dxvkDevice = m_device->GetDXVKDevice();
VkDevice vkDevice = dxvkDevice->handle();
if (FAILED(m_device->CreateShaderResourceView(pResource, pDesc, &srv)))
return false;
Rc<DxvkImageView> dxvkImageView = static_cast<D3D11ShaderResourceView*>(srv.ptr())->GetImageView();
LockImage(dxvkImageView->image(), 0u);
VkImageViewHandleInfoNVX imageViewHandleInfo = {VK_STRUCTURE_TYPE_IMAGE_VIEW_HANDLE_INFO_NVX};
Rc<DxvkImageView> dxvkImageView = pSRV->GetImageView();
VkImageView vkImageView = dxvkImageView->handle();
imageViewHandleInfo.imageView = vkImageView;
imageViewHandleInfo.imageView = dxvkImageView->handle();
imageViewHandleInfo.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
*pDriverHandle = dxvkDevice->vkd()->vkGetImageViewHandleNVX(vkDevice, &imageViewHandleInfo);
Rc<DxvkDevice> dxvkDevice = m_device->GetDXVKDevice();
*pDriverHandle = dxvkDevice->vkd()->vkGetImageViewHandleNVX(
dxvkDevice->handle(), &imageViewHandleInfo);
if (!*pDriverHandle) {
Logger::warn("CreateShaderResourceViewAndGetDriverHandleNVX() handle==0 - failure");
pSRV->Release();
Logger::warn("CreateShaderResourceViewAndGetDriverHandleNVX(): Handle is 0");
return false;
}
// will need to look-up resource from uint32 handle later
AddSrvAndHandleNVX(*ppSRV, *pDriverHandle);
*ppSRV = srv.ref();
AddSrvAndHandleNVX(srv.ptr(), *pDriverHandle);
return true;
}
bool STDMETHODCALLTYPE D3D11DeviceExt::CreateSamplerStateAndGetDriverHandleNVX(const D3D11_SAMPLER_DESC* pSamplerDesc, ID3D11SamplerState** ppSamplerState, uint32_t* pDriverHandle) {
if (!SUCCEEDED(m_device->CreateSamplerState(pSamplerDesc, ppSamplerState))) {
if (FAILED(m_device->CreateSamplerState(pSamplerDesc, ppSamplerState)))
return false;
}
// for our purposes the actual value doesn't matter, only its uniqueness
static std::atomic<ULONG> s_seqNum = 0;
@ -2768,8 +2806,57 @@ namespace dxvk {
}
bool D3D11DeviceExt::LockImage(
const Rc<DxvkImage>& Image,
VkImageUsageFlags Usage) {
if (!Image->canRelocate() && (Image->info().usage & Usage))
return true;
bool feedback = false;
auto chunk = m_device->AllocCsChunk(DxvkCsChunkFlag::SingleUse);
chunk->push([
cImage = Image,
cUsage = Usage,
&feedback
] (DxvkContext* ctx) {
DxvkImageUsageInfo usageInfo;
usageInfo.usage = cUsage;
usageInfo.stableGpuAddress = VK_TRUE;
feedback = ctx->ensureImageCompatibility(cImage, usageInfo);
});
m_device->GetContext()->InjectCsChunk(DxvkCsQueue::HighPriority, std::move(chunk), true);
if (!feedback) {
Logger::err(str::format("Failed to lock image:"
"\n Image format: ", Image->info().format,
"\n Image usage: ", std::hex, Image->info().usage,
"\n Desired usage: ", std::hex, Usage));
}
return feedback;
}
void D3D11DeviceExt::LockBuffer(
const Rc<DxvkBuffer>& Buffer) {
if (!Buffer->canRelocate())
return;
auto chunk = m_device->AllocCsChunk(DxvkCsChunkFlag::SingleUse);
chunk->push([cBuffer = Buffer] (DxvkContext* ctx) {
ctx->ensureBufferAddress(cBuffer);
});
m_device->GetContext()->InjectCsChunk(DxvkCsQueue::HighPriority, std::move(chunk), true);
}
D3D11VideoDevice::D3D11VideoDevice(
D3D11DXGIDevice* pContainer,
@ -2971,6 +3058,198 @@ namespace dxvk {
D3D11ReflexDevice::D3D11ReflexDevice(
D3D11DXGIDevice* pContainer,
D3D11Device* pDevice)
: m_container(pContainer), m_device(pDevice) {
auto dxvkDevice = pDevice->GetDXVKDevice();
m_reflexEnabled = dxvkDevice->features().nvLowLatency2
&& dxvkDevice->config().latencySleep == Tristate::Auto;
}
D3D11ReflexDevice::~D3D11ReflexDevice() {
}
ULONG STDMETHODCALLTYPE D3D11ReflexDevice::AddRef() {
return m_container->AddRef();
}
ULONG STDMETHODCALLTYPE D3D11ReflexDevice::Release() {
return m_container->Release();
}
HRESULT STDMETHODCALLTYPE D3D11ReflexDevice::QueryInterface(
REFIID riid,
void** ppvObject) {
return m_container->QueryInterface(riid, ppvObject);
}
BOOL STDMETHODCALLTYPE D3D11ReflexDevice::SupportsLowLatency() {
return m_reflexEnabled;
}
HRESULT STDMETHODCALLTYPE D3D11ReflexDevice::LatencySleep() {
if (!m_reflexEnabled)
return DXGI_ERROR_INVALID_CALL;
// Don't keep object locked while sleeping
Rc<DxvkReflexLatencyTrackerNv> tracker;
{ std::lock_guard lock(m_mutex);
tracker = m_tracker;
}
if (tracker)
tracker->latencySleep();
return S_OK;
}
HRESULT STDMETHODCALLTYPE D3D11ReflexDevice::SetLatencySleepMode(
BOOL LowLatencyEnable,
BOOL LowLatencyBoost,
UINT32 MinIntervalUs) {
if (!m_reflexEnabled)
return DXGI_ERROR_INVALID_CALL;
std::lock_guard lock(m_mutex);
if (m_tracker) {
m_tracker->setLatencySleepMode(
LowLatencyEnable, LowLatencyBoost, MinIntervalUs);
}
// Write back in case we have no swapchain yet
m_enableLowLatency = LowLatencyEnable;
m_enableBoost = LowLatencyBoost;
m_minIntervalUs = MinIntervalUs;
return S_OK;
}
HRESULT STDMETHODCALLTYPE D3D11ReflexDevice::SetLatencyMarker(
UINT64 FrameId,
UINT32 MarkerType) {
if (!m_reflexEnabled)
return DXGI_ERROR_INVALID_CALL;
std::lock_guard lock(m_mutex);
if (m_tracker) {
auto marker = VkLatencyMarkerNV(MarkerType);
m_tracker->setLatencyMarker(FrameId, marker);
if (marker == VK_LATENCY_MARKER_RENDERSUBMIT_START_NV) {
m_device->GetContext()->InjectCs(DxvkCsQueue::Ordered, [
cTracker = m_tracker,
cFrameId = FrameId
] (DxvkContext* ctx) {
uint64_t frameId = cTracker->frameIdFromAppFrameId(cFrameId);
if (frameId)
ctx->beginLatencyTracking(cTracker, frameId);
});
} else if (marker == VK_LATENCY_MARKER_RENDERSUBMIT_END_NV) {
m_device->GetContext()->InjectCs(DxvkCsQueue::Ordered, [
cTracker = m_tracker
] (DxvkContext* ctx) {
ctx->endLatencyTracking(cTracker);
});
}
}
return S_OK;
}
HRESULT STDMETHODCALLTYPE D3D11ReflexDevice::GetLatencyInfo(
D3D_LOW_LATENCY_RESULTS* pLowLatencyResults) {
constexpr static size_t FrameCount = 64;
if (!pLowLatencyResults)
return E_INVALIDARG;
for (size_t i = 0; i < FrameCount; i++)
pLowLatencyResults->frameReports[i] = D3D_LOW_LATENCY_FRAME_REPORT();
if (!m_reflexEnabled)
return DXGI_ERROR_INVALID_CALL;
std::lock_guard lock(m_mutex);
if (!m_tracker)
return S_OK;
// Apparently we have to report all 64 frames, or nothing
std::array<DxvkReflexFrameReport, FrameCount> reports = { };
uint32_t reportCount = m_tracker->getFrameReports(FrameCount, reports.data());
if (reportCount < FrameCount)
return S_OK;
for (uint32_t i = 0; i < FrameCount; i++) {
auto& src = reports[i];
auto& dst = pLowLatencyResults->frameReports[i];
dst.frameID = src.report.presentID;
dst.inputSampleTime = src.report.inputSampleTimeUs;
dst.simStartTime = src.report.simStartTimeUs;
dst.simEndTime = src.report.simEndTimeUs;
dst.renderSubmitStartTime = src.report.renderSubmitStartTimeUs;
dst.renderSubmitEndTime = src.report.renderSubmitEndTimeUs;
dst.presentStartTime = src.report.presentStartTimeUs;
dst.presentEndTime = src.report.presentEndTimeUs;
dst.driverStartTime = src.report.driverStartTimeUs;
dst.driverEndTime = src.report.driverEndTimeUs;
dst.osRenderQueueStartTime = src.report.osRenderQueueStartTimeUs;
dst.osRenderQueueEndTime = src.report.osRenderQueueEndTimeUs;
dst.gpuRenderStartTime = src.report.gpuRenderStartTimeUs;
dst.gpuRenderEndTime = src.report.gpuRenderEndTimeUs;
dst.gpuActiveRenderTimeUs = src.gpuActiveTimeUs;
dst.gpuFrameTimeUs = 0;
if (i) {
dst.gpuFrameTimeUs = reports[i - 0].report.gpuRenderEndTimeUs
- reports[i - 1].report.gpuRenderEndTimeUs;
}
}
return S_OK;
}
void D3D11ReflexDevice::RegisterLatencyTracker(
Rc<DxvkLatencyTracker> Tracker) {
std::lock_guard lock(m_mutex);
if (m_tracker)
return;
if ((m_tracker = dynamic_cast<DxvkReflexLatencyTrackerNv*>(Tracker.ptr())))
m_tracker->setLatencySleepMode(m_enableLowLatency, m_enableBoost, m_minIntervalUs);
}
void D3D11ReflexDevice::UnregisterLatencyTracker(
Rc<DxvkLatencyTracker> Tracker) {
std::lock_guard lock(m_mutex);
if (m_tracker == Tracker)
m_tracker = nullptr;
}
DXGIVkSwapChainFactory::DXGIVkSwapChainFactory(
D3D11DXGIDevice* pContainer,
D3D11Device* pDevice)
@ -3057,18 +3336,23 @@ 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_d3d11Reflex (this, &m_d3d11Device),
m_d3d11on12 (this, &m_d3d11Device, pD3D12Device, pD3D12Queue),
m_metaDevice (this),
m_dxvkFactory (this, &m_d3d11Device) {
@ -3076,7 +3360,7 @@ namespace dxvk {
D3D11DXGIDevice::~D3D11DXGIDevice() {
}
@ -3140,6 +3424,19 @@ namespace dxvk {
return S_OK;
}
if (riid == __uuidof(ID3DLowLatencyDevice)) {
*ppvObject = ref(&m_d3d11Reflex);
return S_OK;
}
if (m_d3d11on12.Is11on12Device()) {
if (riid == __uuidof(ID3D11On12Device)
|| riid == __uuidof(ID3D11On12Device1_DXVK)) {
*ppvObject = ref(&m_d3d11on12);
return S_OK;
}
}
if (riid == __uuidof(ID3D10Multithread)) {
Com<ID3D11DeviceContext> context;
m_d3d11Device.GetImmediateContext(&context);
@ -3153,8 +3450,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;
}
@ -3383,8 +3683,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;
}
@ -3400,10 +3701,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

@ -9,6 +9,7 @@
#include "../dxgi/dxgi_interfaces.h"
#include "../dxvk/dxvk_cs.h"
#include "../dxvk/dxvk_latency_reflex.h"
#include "../d3d10/d3d10_device.h"
@ -20,6 +21,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"
@ -86,6 +88,11 @@ namespace dxvk {
const D3D11_SUBRESOURCE_DATA* pInitialData,
ID3D11Texture2D1** ppTexture2D);
HRESULT STDMETHODCALLTYPE CreateTexture2DBase(
const D3D11_TEXTURE2D_DESC1* pDesc,
const D3D11_SUBRESOURCE_DATA* pInitialData,
ID3D11Texture2D1** ppTexture2D);
HRESULT STDMETHODCALLTYPE CreateTexture3D(
const D3D11_TEXTURE3D_DESC* pDesc,
const D3D11_SUBRESOURCE_DATA* pInitialData,
@ -96,6 +103,11 @@ namespace dxvk {
const D3D11_SUBRESOURCE_DATA* pInitialData,
ID3D11Texture3D1** ppTexture3D);
HRESULT STDMETHODCALLTYPE CreateTexture3DBase(
const D3D11_TEXTURE3D_DESC1* pDesc,
const D3D11_SUBRESOURCE_DATA* pInitialData,
ID3D11Texture3D1** ppTexture3D);
HRESULT STDMETHODCALLTYPE CreateShaderResourceView(
ID3D11Resource* pResource,
const D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc,
@ -106,6 +118,11 @@ namespace dxvk {
const D3D11_SHADER_RESOURCE_VIEW_DESC1* pDesc,
ID3D11ShaderResourceView1** ppSRView);
HRESULT STDMETHODCALLTYPE CreateShaderResourceViewBase(
ID3D11Resource* pResource,
const D3D11_SHADER_RESOURCE_VIEW_DESC1* pDesc,
ID3D11ShaderResourceView1** ppSRView);
HRESULT STDMETHODCALLTYPE CreateUnorderedAccessView(
ID3D11Resource* pResource,
const D3D11_UNORDERED_ACCESS_VIEW_DESC* pDesc,
@ -116,6 +133,11 @@ namespace dxvk {
const D3D11_UNORDERED_ACCESS_VIEW_DESC1* pDesc,
ID3D11UnorderedAccessView1** ppUAView);
HRESULT STDMETHODCALLTYPE CreateUnorderedAccessViewBase(
ID3D11Resource* pResource,
const D3D11_UNORDERED_ACCESS_VIEW_DESC1* pDesc,
ID3D11UnorderedAccessView1** ppUAView);
HRESULT STDMETHODCALLTYPE CreateRenderTargetView(
ID3D11Resource* pResource,
const D3D11_RENDER_TARGET_VIEW_DESC* pDesc,
@ -126,6 +148,11 @@ namespace dxvk {
const D3D11_RENDER_TARGET_VIEW_DESC1* pDesc,
ID3D11RenderTargetView1** ppRTView);
HRESULT STDMETHODCALLTYPE CreateRenderTargetViewBase(
ID3D11Resource* pResource,
const D3D11_RENDER_TARGET_VIEW_DESC1* pDesc,
ID3D11RenderTargetView1** ppRTView);
HRESULT STDMETHODCALLTYPE CreateDepthStencilView(
ID3D11Resource* pResource,
const D3D11_DEPTH_STENCIL_VIEW_DESC* pDesc,
@ -224,6 +251,10 @@ namespace dxvk {
const D3D11_QUERY_DESC1* pQueryDesc,
ID3D11Query1** ppQuery);
HRESULT STDMETHODCALLTYPE CreateQueryBase(
const D3D11_QUERY_DESC1* pQueryDesc,
ID3D11Query1** ppQuery);
HRESULT STDMETHODCALLTYPE CreatePredicate(
const D3D11_QUERY_DESC* pPredicateDesc,
ID3D11Predicate** ppPredicate);
@ -390,8 +421,21 @@ namespace dxvk {
return m_dxvkDevice;
}
void FlushInitContext();
void FlushInitCommands() {
m_initializer->FlushCsChunk();
}
void NotifyContextFlush() {
m_initializer->NotifyContextFlush();
}
void InitShaderIcb(
D3D11CommonShader* pShader,
size_t IcbSize,
const void* pIcbData) {
return m_initializer->InitShaderIcb(pShader, IcbSize, pIcbData);
}
VkPipelineStageFlags GetEnabledShaderStages() const {
return m_dxvkDevice->getShaderPipelineStages();
}
@ -420,17 +464,35 @@ 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);
static DxvkDeviceFeatures GetDeviceFeatures(
const Rc<DxvkAdapter>& Adapter);
DxvkBarrierControlFlags GetOptionsBarrierControlFlags() {
DxvkBarrierControlFlags barrierControl = 0u;
if (m_d3d11Options.relaxedBarriers)
barrierControl.set(DxvkBarrierControl::ComputeAllowWriteOnlyOverlap);
if (m_d3d11Options.relaxedBarriers || m_d3d11Options.relaxedGraphicsBarriers)
barrierControl.set(DxvkBarrierControl::GraphicsAllowReadWriteOverlap);
return barrierControl;
}
private:
IDXGIObject* m_container;
D3D11DXGIDevice* m_container;
D3D_FEATURE_LEVEL m_featureLevel;
UINT m_featureFlags;
@ -573,7 +635,14 @@ namespace dxvk {
ID3D11ShaderResourceView* HandleToSrvNVX(
uint32_t Handle);
bool LockImage(
const Rc<DxvkImage>& Image,
VkImageUsageFlags Usage);
void LockBuffer(
const Rc<DxvkBuffer>& Buffer);
dxvk::mutex m_mapLock;
std::unordered_map<uint32_t, ID3D11SamplerState*> m_samplerHandleToPtr;
std::unordered_map<uint32_t, ID3D11ShaderResourceView*> m_srvHandleToPtr;
@ -690,6 +759,66 @@ namespace dxvk {
};
/**
* \brief Nvidia Reflex interop
*/
class D3D11ReflexDevice : public ID3DLowLatencyDevice {
public:
D3D11ReflexDevice(
D3D11DXGIDevice* pContainer,
D3D11Device* pDevice);
~D3D11ReflexDevice();
ULONG STDMETHODCALLTYPE AddRef();
ULONG STDMETHODCALLTYPE Release();
HRESULT STDMETHODCALLTYPE QueryInterface(
REFIID riid,
void** ppvObject);
BOOL STDMETHODCALLTYPE SupportsLowLatency();
HRESULT STDMETHODCALLTYPE LatencySleep();
HRESULT STDMETHODCALLTYPE SetLatencySleepMode(
BOOL LowLatencyEnable,
BOOL LowLatencyBoost,
UINT32 MinIntervalUs);
HRESULT STDMETHODCALLTYPE SetLatencyMarker(
UINT64 FrameId,
UINT32 MarkerType);
HRESULT STDMETHODCALLTYPE GetLatencyInfo(
D3D_LOW_LATENCY_RESULTS* pLowLatencyResults);
void RegisterLatencyTracker(
Rc<DxvkLatencyTracker> Tracker);
void UnregisterLatencyTracker(
Rc<DxvkLatencyTracker> Tracker);
private:
D3D11DXGIDevice* m_container;
D3D11Device* m_device;
bool m_reflexEnabled = false;
dxvk::mutex m_mutex;
bool m_enableLowLatency = false;
bool m_enableBoost = false;
uint64_t m_minIntervalUs = 0u;
Rc<DxvkReflexLatencyTrackerNv> m_tracker;
};
/**
* \brief DXVK swap chain factory
*/
@ -764,8 +893,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);
@ -834,6 +966,10 @@ namespace dxvk {
Rc<DxvkDevice> STDMETHODCALLTYPE GetDXVKDevice();
BOOL Is11on12Device() const {
return m_d3d11on12.Is11on12Device();
}
private:
Com<IDXGIAdapter> m_dxgiAdapter;
@ -846,14 +982,14 @@ namespace dxvk {
D3D11DeviceExt m_d3d11DeviceExt;
D3D11VkInterop m_d3d11Interop;
D3D11VideoDevice m_d3d11Video;
D3D11ReflexDevice m_d3d11Reflex;
D3D11on12Device m_d3d11on12;
DXGIDXVKDevice m_metaDevice;
DXGIVkSwapChainFactory m_dxvkFactory;
uint32_t m_frameLatency = DefaultFrameLatency;
Rc<DxvkDevice> CreateDevice(D3D_FEATURE_LEVEL FeatureLevel);
};
}

View file

@ -19,24 +19,28 @@ namespace dxvk {
}
HRESULT STDMETHODCALLTYPE GetPrivateData(
REFGUID guid,
UINT *pDataSize,
void *pData) final {
REFGUID guid,
UINT* pDataSize,
void* pData) final {
return m_privateData.getData(
guid, pDataSize, pData);
}
HRESULT STDMETHODCALLTYPE SetPrivateData(
REFGUID guid,
UINT DataSize,
const void *pData) final {
REFGUID guid,
UINT DataSize,
const void* pData) final {
// WKPDID_D3DDebugObjectName, can't use directly due to MSVC link errors
if (guid == GUID{0x429b8c22,0x9188,0x4b0c,0x87,0x42,0xac,0xb0,0xbf,0x85,0xc2,0x00})
SetDebugName(static_cast<const char*>(pData));
return m_privateData.setData(
guid, DataSize, pData);
}
HRESULT STDMETHODCALLTYPE SetPrivateDataInterface(
REFGUID guid,
const IUnknown *pUnknown) final {
REFGUID guid,
const IUnknown* pUnknown) final {
return m_privateData.setInterface(
guid, pUnknown);
}
@ -46,6 +50,10 @@ namespace dxvk {
*ppDevice = ref(GetParentInterface());
}
virtual void STDMETHODCALLTYPE SetDebugName(const char* pName) {
// No-op by default
}
protected:
ID3D11Device* GetParentInterface() const {

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;
}

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

@ -1,5 +1,6 @@
#include <cstring>
#include "d3d11_context_imm.h"
#include "d3d11_device.h"
#include "d3d11_initializer.h"
@ -9,9 +10,10 @@ namespace dxvk {
D3D11Device* pParent)
: m_parent(pParent),
m_device(pParent->GetDXVKDevice()),
m_context(m_device->createContext(DxvkContextType::Supplementary)) {
m_context->beginRecording(
m_device->createCommandList());
m_stagingBuffer(m_device, StagingBufferSize),
m_stagingSignal(new sync::Fence(0)),
m_csChunk(m_parent->AllocCsChunk(DxvkCsChunkFlag::SingleUse)) {
}
@ -20,13 +22,12 @@ namespace dxvk {
}
void D3D11Initializer::Flush() {
void D3D11Initializer::NotifyContextFlush() {
std::lock_guard<dxvk::mutex> lock(m_mutex);
if (m_transferCommands != 0)
FlushInternal();
NotifyContextFlushLocked();
}
void D3D11Initializer::InitBuffer(
D3D11Buffer* pBuffer,
const D3D11_SUBRESOURCE_DATA* pInitialData) {
@ -49,6 +50,8 @@ namespace dxvk {
InitHostVisibleTexture(pTexture, pInitialData);
else
InitDeviceLocalTexture(pTexture, pInitialData);
SyncSharedTexture(pTexture);
}
@ -59,18 +62,45 @@ namespace dxvk {
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(
counterSlice.buffer(),
counterSlice.offset(),
sizeof(zero), &zero);
EmitCs([
cCounterSlice = DxvkBufferSlice(counterView)
] (DxvkContext* ctx) {
const uint32_t zero = 0;
ctx->updateBuffer(
cCounterSlice.buffer(),
cCounterSlice.offset(),
sizeof(zero), &zero);
});
}
FlushImplicit();
void D3D11Initializer::InitShaderIcb(
D3D11CommonShader* pShader,
size_t IcbSize,
const void* pIcbData) {
std::lock_guard<dxvk::mutex> lock(m_mutex);
m_transferCommands += 1;
auto icbSlice = pShader->GetIcb();
auto srcSlice = m_stagingBuffer.alloc(icbSlice.length());
std::memcpy(srcSlice.mapPtr(0), pIcbData, IcbSize);
if (IcbSize < icbSlice.length())
std::memset(srcSlice.mapPtr(IcbSize), 0, icbSlice.length() - IcbSize);
EmitCs([
cIcbSlice = std::move(icbSlice),
cSrcSlice = std::move(srcSlice)
] (DxvkContext* ctx) {
ctx->copyBuffer(cIcbSlice.buffer(), cIcbSlice.offset(),
cSrcSlice.buffer(), cSrcSlice.offset(), cIcbSlice.length());
});
ThrottleAllocationLocked();
}
@ -79,23 +109,33 @@ namespace dxvk {
const D3D11_SUBRESOURCE_DATA* pInitialData) {
std::lock_guard<dxvk::mutex> lock(m_mutex);
DxvkBufferSlice bufferSlice = pBuffer->GetBufferSlice();
Rc<DxvkBuffer> buffer = pBuffer->GetBuffer();
if (pInitialData != nullptr && pInitialData->pSysMem != nullptr) {
m_transferMemory += bufferSlice.length();
auto stagingSlice = m_stagingBuffer.alloc(buffer->info().size);
std::memcpy(stagingSlice.mapPtr(0), pInitialData->pSysMem, stagingSlice.length());
m_transferCommands += 1;
m_context->uploadBuffer(
bufferSlice.buffer(),
pInitialData->pSysMem);
EmitCs([
cBuffer = buffer,
cStagingSlice = std::move(stagingSlice)
] (DxvkContext* ctx) {
ctx->uploadBuffer(cBuffer,
cStagingSlice.buffer(),
cStagingSlice.offset());
});
} else {
m_transferCommands += 1;
m_context->initBuffer(
bufferSlice.buffer());
EmitCs([
cBuffer = buffer
] (DxvkContext* ctx) {
ctx->initBuffer(cBuffer);
});
}
FlushImplicit();
ThrottleAllocationLocked();
}
@ -105,18 +145,10 @@ namespace dxvk {
// If the buffer is mapped, we can write data directly
// to the mapped memory region instead of doing it on
// the GPU. Same goes for zero-initialization.
DxvkBufferSlice bufferSlice = pBuffer->GetBufferSlice();
if (pInitialData != nullptr && pInitialData->pSysMem != nullptr) {
std::memcpy(
bufferSlice.mapPtr(0),
pInitialData->pSysMem,
bufferSlice.length());
} else {
std::memset(
bufferSlice.mapPtr(0), 0,
bufferSlice.length());
}
if (pInitialData && pInitialData->pSysMem)
std::memcpy(pBuffer->GetMapPtr(), pInitialData->pSysMem, pBuffer->Desc()->ByteWidth);
else
std::memset(pBuffer->GetMapPtr(), 0, pBuffer->Desc()->ByteWidth);
}
@ -125,87 +157,96 @@ namespace dxvk {
const D3D11_SUBRESOURCE_DATA* pInitialData) {
std::lock_guard<dxvk::mutex> lock(m_mutex);
// Image migt be null if this is a staging resource
Rc<DxvkImage> image = pTexture->GetImage();
auto mapMode = pTexture->GetMapMode();
auto desc = pTexture->Desc();
VkFormat packedFormat = m_parent->LookupPackedFormat(desc->Format, pTexture->GetFormatMode()).Format;
auto formatInfo = lookupFormatInfo(packedFormat);
if (pInitialData != nullptr && pInitialData->pSysMem != nullptr) {
// pInitialData is an array that stores an entry for
// every single subresource. Since we will define all
// subresources, this counts as initialization.
for (uint32_t layer = 0; layer < desc->ArraySize; layer++) {
for (uint32_t level = 0; level < desc->MipLevels; level++) {
const uint32_t id = D3D11CalcSubresource(
level, layer, desc->MipLevels);
// Compute data size for all subresources and allocate staging buffer memory
DxvkBufferSlice stagingSlice;
VkOffset3D mipLevelOffset = { 0, 0, 0 };
VkExtent3D mipLevelExtent = pTexture->MipLevelExtent(level);
if (pTexture->HasImage()) {
VkDeviceSize dataSize = 0u;
for (uint32_t mip = 0; mip < image->info().mipLevels; mip++) {
dataSize += image->info().numLayers * align(util::computeImageDataSize(
packedFormat, image->mipLevelExtent(mip), formatInfo->aspectMask), CACHE_LINE_SIZE);
}
stagingSlice = m_stagingBuffer.alloc(dataSize);
}
// Copy initial data for each subresource into the staging buffer,
// as well as the mapped per-subresource buffers if available.
VkDeviceSize dataOffset = 0u;
for (uint32_t mip = 0; mip < desc->MipLevels; mip++) {
for (uint32_t layer = 0; layer < desc->ArraySize; layer++) {
uint32_t index = D3D11CalcSubresource(mip, layer, desc->MipLevels);
VkExtent3D mipLevelExtent = pTexture->MipLevelExtent(mip);
if (pTexture->HasImage()) {
VkDeviceSize mipSizePerLayer = util::computeImageDataSize(
packedFormat, image->mipLevelExtent(mip), formatInfo->aspectMask);
if (mapMode != D3D11_COMMON_TEXTURE_MAP_MODE_STAGING) {
m_transferCommands += 1;
m_transferMemory += pTexture->GetSubresourceLayout(formatInfo->aspectMask, id).Size;
VkImageSubresourceLayers subresourceLayers;
subresourceLayers.aspectMask = formatInfo->aspectMask;
subresourceLayers.mipLevel = level;
subresourceLayers.baseArrayLayer = layer;
subresourceLayers.layerCount = 1;
if (formatInfo->aspectMask != (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
m_context->uploadImage(
image, subresourceLayers,
pInitialData[id].pSysMem,
pInitialData[id].SysMemPitch,
pInitialData[id].SysMemSlicePitch);
} else {
m_context->updateDepthStencilImage(
image, subresourceLayers,
VkOffset2D { mipLevelOffset.x, mipLevelOffset.y },
VkExtent2D { mipLevelExtent.width, mipLevelExtent.height },
pInitialData[id].pSysMem,
pInitialData[id].SysMemPitch,
pInitialData[id].SysMemSlicePitch,
packedFormat);
}
util::packImageData(stagingSlice.mapPtr(dataOffset),
pInitialData[index].pSysMem, pInitialData[index].SysMemPitch, pInitialData[index].SysMemSlicePitch,
0, 0, pTexture->GetVkImageType(), mipLevelExtent, 1, formatInfo, formatInfo->aspectMask);
dataOffset += align(mipSizePerLayer, CACHE_LINE_SIZE);
}
if (mapMode != D3D11_COMMON_TEXTURE_MAP_MODE_NONE) {
util::packImageData(pTexture->GetMappedBuffer(id)->mapPtr(0),
pInitialData[id].pSysMem, pInitialData[id].SysMemPitch, pInitialData[id].SysMemSlicePitch,
if (pTexture->HasPersistentBuffers()) {
util::packImageData(pTexture->GetMapPtr(index, 0),
pInitialData[index].pSysMem, pInitialData[index].SysMemPitch, pInitialData[index].SysMemSlicePitch,
0, 0, pTexture->GetVkImageType(), mipLevelExtent, 1, formatInfo, formatInfo->aspectMask);
}
}
}
// Upload all subresources of the image in one go
if (pTexture->HasImage()) {
EmitCs([
cImage = std::move(image),
cStagingSlice = std::move(stagingSlice),
cFormat = packedFormat
] (DxvkContext* ctx) {
ctx->uploadImage(cImage,
cStagingSlice.buffer(),
cStagingSlice.offset(),
CACHE_LINE_SIZE, cFormat);
});
}
} else {
if (mapMode != D3D11_COMMON_TEXTURE_MAP_MODE_STAGING) {
if (pTexture->HasImage()) {
m_transferCommands += 1;
// While the Microsoft docs state that resource contents are
// undefined if no initial data is provided, some applications
// expect a resource to be pre-cleared.
VkImageSubresourceRange subresources;
subresources.aspectMask = formatInfo->aspectMask;
subresources.baseMipLevel = 0;
subresources.levelCount = desc->MipLevels;
subresources.baseArrayLayer = 0;
subresources.layerCount = desc->ArraySize;
m_context->initImage(image, subresources, VK_IMAGE_LAYOUT_UNDEFINED);
EmitCs([
cImage = std::move(image)
] (DxvkContext* ctx) {
ctx->initImage(cImage,
cImage->getAvailableSubresources(),
VK_IMAGE_LAYOUT_UNDEFINED);
});
}
if (mapMode != D3D11_COMMON_TEXTURE_MAP_MODE_NONE) {
if (pTexture->HasPersistentBuffers()) {
for (uint32_t i = 0; i < pTexture->CountSubresources(); i++) {
auto buffer = pTexture->GetMappedBuffer(i);
std::memset(buffer->mapPtr(0), 0, buffer->info().size);
auto layout = pTexture->GetSubresourceLayout(formatInfo->aspectMask, i);
std::memset(pTexture->GetMapPtr(i, layout.Offset), 0, layout.Size);
}
}
}
FlushImplicit();
ThrottleAllocationLocked();
}
@ -213,38 +254,47 @@ namespace dxvk {
D3D11CommonTexture* pTexture,
const D3D11_SUBRESOURCE_DATA* pInitialData) {
Rc<DxvkImage> image = pTexture->GetImage();
auto formatInfo = image->formatInfo();
for (uint32_t layer = 0; layer < pTexture->Desc()->ArraySize; layer++) {
for (uint32_t level = 0; level < pTexture->Desc()->MipLevels; level++) {
uint32_t subresourceIndex = D3D11CalcSubresource(level, layer, pTexture->Desc()->MipLevels);
for (uint32_t layer = 0; layer < image->info().numLayers; layer++) {
for (uint32_t level = 0; level < image->info().mipLevels; level++) {
VkImageSubresource subresource;
subresource.aspectMask = image->formatInfo()->aspectMask;
subresource.aspectMask = formatInfo->aspectMask;
subresource.mipLevel = level;
subresource.arrayLayer = layer;
VkExtent3D blockCount = util::computeBlockCount(
image->mipLevelExtent(level),
image->formatInfo()->blockSize);
image->mipLevelExtent(level), formatInfo->blockSize);
VkSubresourceLayout layout = image->querySubresourceLayout(subresource);
auto layout = pTexture->GetSubresourceLayout(
subresource.aspectMask, subresourceIndex);
auto initialData = pInitialData
? &pInitialData[D3D11CalcSubresource(level, layer, image->info().mipLevels)]
: nullptr;
if (pInitialData && pInitialData[subresourceIndex].pSysMem) {
const auto& initialData = pInitialData[subresourceIndex];
for (uint32_t z = 0; z < blockCount.depth; z++) {
for (uint32_t y = 0; y < blockCount.height; y++) {
auto size = blockCount.width * image->formatInfo()->elementSize;
auto dst = image->mapPtr(layout.offset + y * layout.rowPitch + z * layout.depthPitch);
for (uint32_t z = 0; z < blockCount.depth; z++) {
for (uint32_t y = 0; y < blockCount.height; y++) {
auto size = blockCount.width * formatInfo->elementSize;
auto dst = pTexture->GetMapPtr(subresourceIndex, layout.Offset
+ y * layout.RowPitch
+ z * layout.DepthPitch);
auto src = reinterpret_cast<const char*>(initialData.pSysMem)
+ y * initialData.SysMemPitch
+ z * initialData.SysMemSlicePitch;
if (initialData) {
auto src = reinterpret_cast<const char*>(initialData->pSysMem)
+ y * initialData->SysMemPitch
+ z * initialData->SysMemSlicePitch;
std::memcpy(dst, src, size);
} else {
std::memset(dst, 0, size);
if (size < layout.RowPitch)
std::memset(reinterpret_cast<char*>(dst) + size, 0, layout.RowPitch - size);
}
}
} else {
void* dst = pTexture->GetMapPtr(subresourceIndex, layout.Offset);
std::memset(dst, 0, layout.Size);
}
}
}
@ -252,36 +302,110 @@ namespace dxvk {
// Initialize the image on the GPU
std::lock_guard<dxvk::mutex> lock(m_mutex);
VkImageSubresourceRange subresources = image->getAvailableSubresources();
m_context->initImage(image, subresources, VK_IMAGE_LAYOUT_PREINITIALIZED);
EmitCs([
cImage = std::move(image)
] (DxvkContext* ctx) {
ctx->initImage(cImage,
cImage->getAvailableSubresources(),
VK_IMAGE_LAYOUT_PREINITIALIZED);
});
m_transferCommands += 1;
FlushImplicit();
ThrottleAllocationLocked();
}
void D3D11Initializer::InitTiledTexture(
D3D11CommonTexture* pTexture) {
m_context->initSparseImage(pTexture->GetImage());
std::lock_guard<dxvk::mutex> lock(m_mutex);
EmitCs([
cImage = pTexture->GetImage()
] (DxvkContext* ctx) {
ctx->initSparseImage(cImage);
});
m_transferCommands += 1;
FlushImplicit();
ThrottleAllocationLocked();
}
void D3D11Initializer::FlushImplicit() {
if (m_transferCommands > MaxTransferCommands
|| m_transferMemory > MaxTransferMemory)
FlushInternal();
void D3D11Initializer::ThrottleAllocationLocked() {
DxvkStagingBufferStats stats = m_stagingBuffer.getStatistics();
// If the amount of memory in flight exceeds the limit, stall the
// calling thread and wait for some memory to actually get released.
VkDeviceSize stagingMemoryInFlight = stats.allocatedTotal - m_stagingSignal->value();
if (stagingMemoryInFlight > MaxMemoryInFlight) {
ExecuteFlushLocked();
m_stagingSignal->wait(stats.allocatedTotal - MaxMemoryInFlight);
} else if (m_transferCommands >= MaxCommandsPerSubmission || stats.allocatedSinceLastReset >= MaxMemoryPerSubmission) {
// Flush pending commands if there are a lot of updates in flight
// to keep both execution time and staging memory in check.
ExecuteFlushLocked();
}
}
void D3D11Initializer::FlushInternal() {
m_context->flushCommandList();
void D3D11Initializer::ExecuteFlush() {
std::lock_guard lock(m_mutex);
ExecuteFlushLocked();
}
void D3D11Initializer::ExecuteFlushLocked() {
DxvkStagingBufferStats stats = m_stagingBuffer.getStatistics();
EmitCs([
cSignal = m_stagingSignal,
cSignalValue = stats.allocatedTotal
] (DxvkContext* ctx) {
ctx->signal(cSignal, cSignalValue);
ctx->flushCommandList(nullptr, nullptr);
});
FlushCsChunk();
NotifyContextFlushLocked();
}
void D3D11Initializer::SyncSharedTexture(D3D11CommonTexture* pResource) {
if (!(pResource->Desc()->MiscFlags & (D3D11_RESOURCE_MISC_SHARED | D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX | D3D11_RESOURCE_MISC_SHARED_NTHANDLE)))
return;
// Ensure that initialization commands are submitted and waited on before
// returning control to the application in order to avoid race conditions
// in case the texture is used immediately on a secondary device.
if (pResource->HasImage()) {
ExecuteFlush();
m_device->waitForResource(*pResource->GetImage(), DxvkAccess::Write);
}
// If a keyed mutex is used, initialize that to the correct state as well.
Com<IDXGIKeyedMutex> keyedMutex;
if (SUCCEEDED(pResource->GetInterface()->QueryInterface(
__uuidof(IDXGIKeyedMutex), reinterpret_cast<void**>(&keyedMutex)))) {
keyedMutex->AcquireSync(0, 0);
keyedMutex->ReleaseSync(0);
}
}
void D3D11Initializer::FlushCsChunkLocked() {
m_parent->GetContext()->InjectCsChunk(DxvkCsQueue::HighPriority, std::move(m_csChunk), false);
m_csChunk = m_parent->AllocCsChunk(DxvkCsChunkFlag::SingleUse);
}
void D3D11Initializer::NotifyContextFlushLocked() {
m_stagingBuffer.reset();
m_transferCommands = 0;
m_transferMemory = 0;
}
}
}

View file

@ -1,7 +1,11 @@
#pragma once
#include "../dxvk/dxvk_staging.h"
#include "d3d11_buffer.h"
#include "d3d11_shader.h"
#include "d3d11_texture.h"
#include "d3d11_view_uav.h"
namespace dxvk {
@ -16,16 +20,33 @@ namespace dxvk {
* zero-initialization for buffers and images.
*/
class D3D11Initializer {
constexpr static size_t MaxTransferMemory = 32 * 1024 * 1024;
constexpr static size_t MaxTransferCommands = 512;
// Use a staging buffer with a linear allocator to service small uploads
constexpr static VkDeviceSize StagingBufferSize = 1ull << 20;
public:
// Maximum number of copy and clear commands to record before flushing
constexpr static size_t MaxCommandsPerSubmission = 512u;
// Maximum amount of staging memory to allocate before flushing
constexpr static size_t MaxMemoryPerSubmission = (env::is32BitHostPlatform() ? 12u : 48u) << 20;
// Maximum amount of memory in flight. If there are pending uploads while
// this limit is exceeded, further initialization will be stalled.
constexpr static size_t MaxMemoryInFlight = 3u * MaxMemoryPerSubmission;
D3D11Initializer(
D3D11Device* pParent);
~D3D11Initializer();
void Flush();
void FlushCsChunk() {
std::lock_guard<dxvk::mutex> lock(m_csMutex);
if (!m_csChunk->empty())
FlushCsChunkLocked();
}
void NotifyContextFlush();
void InitBuffer(
D3D11Buffer* pBuffer,
@ -38,16 +59,25 @@ namespace dxvk {
void InitUavCounter(
D3D11UnorderedAccessView* pUav);
void InitShaderIcb(
D3D11CommonShader* pShader,
size_t IcbSize,
const void* pIcbData);
private:
dxvk::mutex m_mutex;
D3D11Device* m_parent;
Rc<DxvkDevice> m_device;
Rc<DxvkContext> m_context;
DxvkStagingBuffer m_stagingBuffer;
Rc<sync::Fence> m_stagingSignal;
size_t m_transferCommands = 0;
size_t m_transferMemory = 0;
dxvk::mutex m_csMutex;
DxvkCsChunkRef m_csChunk;
void InitDeviceLocalBuffer(
D3D11Buffer* pBuffer,
@ -68,9 +98,30 @@ namespace dxvk {
void InitTiledTexture(
D3D11CommonTexture* pTexture);
void FlushImplicit();
void FlushInternal();
void ThrottleAllocationLocked();
void ExecuteFlush();
void ExecuteFlushLocked();
void SyncSharedTexture(
D3D11CommonTexture* pResource);
void FlushCsChunkLocked();
void NotifyContextFlushLocked();
template<typename Cmd>
void EmitCs(Cmd&& command) {
std::lock_guard<dxvk::mutex> lock(m_csMutex);
if (unlikely(!m_csChunk->push(command))) {
FlushCsChunkLocked();
m_csChunk->push(command);
}
}
};
}
}

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

@ -24,7 +24,9 @@ enum D3D11_VK_EXTENSION : uint32_t {
*/
enum D3D11_VK_BARRIER_CONTROL : uint32_t {
D3D11_VK_BARRIER_CONTROL_IGNORE_WRITE_AFTER_WRITE = 1 << 0,
D3D11_VK_BARRIER_CONTROL_IGNORE_GRAPHICS_UAV = 1 << 1,
// Removed:
// D3D11_VK_BARRIER_CONTROL_IGNORE_GRAPHICS_UAV = 1 << 1,
};
@ -183,16 +185,70 @@ 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
/**
* \brief Frame reports used for Reflex interop
*/
struct D3D_LOW_LATENCY_FRAME_REPORT
{
UINT64 frameID;
UINT64 inputSampleTime;
UINT64 simStartTime;
UINT64 simEndTime;
UINT64 renderSubmitStartTime;
UINT64 renderSubmitEndTime;
UINT64 presentStartTime;
UINT64 presentEndTime;
UINT64 driverStartTime;
UINT64 driverEndTime;
UINT64 osRenderQueueStartTime;
UINT64 osRenderQueueEndTime;
UINT64 gpuRenderStartTime;
UINT64 gpuRenderEndTime;
UINT32 gpuActiveRenderTimeUs;
UINT32 gpuFrameTimeUs;
UINT8 rsvd[120];
};
/**
* \brief Data structure used for Reflex interop
*/
struct D3D_LOW_LATENCY_RESULTS
{
UINT32 version;
D3D_LOW_LATENCY_FRAME_REPORT frameReports[64];
UINT8 rsvd[32];
};
/**
* \brief D3D interop interface for Nvidia Reflex
*/
MIDL_INTERFACE("f3112584-41f9-348d-a59b-00b7e1d285d6")
ID3DLowLatencyDevice : public IUnknown {
virtual BOOL STDMETHODCALLTYPE SupportsLowLatency() = 0;
virtual HRESULT STDMETHODCALLTYPE LatencySleep() = 0;
virtual HRESULT STDMETHODCALLTYPE SetLatencySleepMode(
BOOL LowLatencyEnable,
BOOL LowLatencyBoost,
UINT32 MinIntervalUs) = 0;
virtual HRESULT STDMETHODCALLTYPE SetLatencyMarker(
UINT64 FrameId,
UINT32 MarkerType) = 0;
virtual HRESULT STDMETHODCALLTYPE GetLatencyInfo(
D3D_LOW_LATENCY_RESULTS* pLowLatencyResults) = 0;
};
#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);
__CRT_UUID_DECL(ID3D11VkExtContext, 0xfd0bca13,0x5cb6,0x4c3a,0x98,0x7e,0x47,0x50,0xde,0x2c,0xa7,0x91);
__CRT_UUID_DECL(ID3D11VkExtContext1, 0x874b09b2,0xae0b,0x41d8,0x84,0x76,0x5f,0x3b,0x7a,0x0e,0x87,0x9d);
__CRT_UUID_DECL(ID3DLowLatencyDevice, 0xf3112584,0x41f9,0x348d,0xa5,0x9b,0x00,0xb7,0xe1,0xd2,0x85,0xd6);
#endif

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;
}
}
}

157
src/d3d11/d3d11_on_12.cpp Normal file
View file

@ -0,0 +1,157 @@
#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);
}
}
HRESULT STDMETHODCALLTYPE D3D11on12Device::GetD3D12Device(
REFIID riid,
void** ppvDevice) {
return m_d3d12Queue->GetDevice(riid, ppvDevice);
}
}

98
src/d3d11/d3d11_on_12.h Normal file
View file

@ -0,0 +1,98 @@
#pragma once
#include "d3d11_on_12_interfaces.h"
#include "../util/log/log.h"
/**
* \brief Declaration of the ID3D11On12Device1 interface
*
* Various different headers that we need to be compatible with
* can't seem to agree on the signature of GetD3D12Device, and
* older wine/mingw headers don't support this interface at all.
*/
MIDL_INTERFACE("bdb64df4-ea2f-4c70-b861-aaab1258bb5d")
ID3D11On12Device1_DXVK : public ID3D11On12Device {
virtual HRESULT STDMETHODCALLTYPE GetD3D12Device(
REFIID riid,
void** ppvDevice) = 0;
};
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 ID3D11On12Device1_DXVK {
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);
HRESULT STDMETHODCALLTYPE GetD3D12Device(
REFIID riid,
void** ppvDevice);
bool Is11on12Device() const {
return m_d3d12Device != nullptr;
}
private:
D3D11DXGIDevice* m_container;
D3D11Device* m_device;
Com<ID3D12Device> m_d3d12Device;
Com<ID3D12CommandQueue> m_d3d12Queue;
};
}
#ifndef _MSC_VER
__CRT_UUID_DECL(ID3D11On12Device1_DXVK, 0xbdb64df4,0xea2f,0x4c70,0xb8,0x61,0xaa,0xab,0x12,0x58,0xbb,0x5d);
#endif

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,40 +12,29 @@ namespace dxvk {
#endif
}
D3D11Options::D3D11Options(const Config& config, const Rc<DxvkDevice>& device) {
this->dcSingleUseMode = config.getOption<bool>("d3d11.dcSingleUseMode", true);
D3D11Options::D3D11Options(const Config& config) {
this->zeroInitWorkgroupMemory = config.getOption<bool>("d3d11.zeroInitWorkgroupMemory", false);
this->forceVolatileTgsmAccess = config.getOption<bool>("d3d11.forceVolatileTgsmAccess", false);
this->forceComputeUavBarriers = config.getOption<bool>("d3d11.forceComputeUavBarriers", false);
this->relaxedBarriers = config.getOption<bool>("d3d11.relaxedBarriers", false);
this->ignoreGraphicsBarriers = config.getOption<bool>("d3d11.ignoreGraphicsBarriers", false);
this->relaxedGraphicsBarriers = config.getOption<bool>("d3d11.relaxedGraphicsBarriers", false);
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->reproducibleCommandStream = config.getOption<bool>("d3d11.reproducibleCommandStream", false);
// Clamp LOD bias so that people don't abuse this in unintended ways
this->samplerLodBias = dxvk::fclamp(this->samplerLodBias, -2.0f, 1.0f);
int32_t maxImplicitDiscardSize = config.getOption<int32_t>("d3d11.maxImplicitDiscardSize", 256);
this->maxImplicitDiscardSize = maxImplicitDiscardSize >= 0
? VkDeviceSize(maxImplicitDiscardSize) << 10
: VkDeviceSize(~0ull);
int32_t maxDynamicImageBufferSize = config.getOption<int32_t>("d3d11.maxDynamicImageBufferSize", -1);
this->maxDynamicImageBufferSize = maxDynamicImageBufferSize >= 0
? VkDeviceSize(maxDynamicImageBufferSize) << 10
: VkDeviceSize(~0ull);
auto cachedDynamicResources = config.getOption<std::string>("d3d11.cachedDynamicResources", std::string());
if (IsAPITracingDXGI()) {
@ -72,4 +61,4 @@ namespace dxvk {
this->shaderDumpPath = env::getEnvVar("DXVK_SHADER_DUMP_PATH");
}
}
}

View file

@ -11,115 +11,107 @@
namespace dxvk {
struct D3D11Options {
D3D11Options(const Config& config, const Rc<DxvkDevice>& device);
/// Enables speed hack for mapping on deferred contexts
///
/// This can substantially speed up some games, but may
/// cause issues if the game submits command lists more
/// than once.
bool dcSingleUseMode;
D3D11Options(const Config& config);
/// Zero-initialize workgroup memory
///
/// Workargound for games that don't initialize
/// TGSM in compute shaders before reading it.
bool zeroInitWorkgroupMemory;
bool zeroInitWorkgroupMemory = false;
/// Force thread-group shared memory accesses to be volatile
///
/// Workaround for compute shaders that read and
/// write from the same shared memory location
/// without explicit synchronization.
bool forceVolatileTgsmAccess;
bool forceVolatileTgsmAccess = false;
/// Force UAV synchronization insided compute shaders
///
/// Workaround for compute shaders that access overlapping
/// memory regions within a UAV without proper workgroup
/// synchroniation. Will have a negative performance impact.
bool forceComputeUavBarriers = false;
/// Use relaxed memory barriers
///
/// May improve performance in some games,
/// but might also cause rendering issues.
bool relaxedBarriers;
bool relaxedBarriers = false;
/// Ignore graphics barriers
///
/// May improve performance in some games,
/// but might also cause rendering issues.
bool ignoreGraphicsBarriers;
bool relaxedGraphicsBarriers = false;
/// Maximum tessellation factor.
///
/// Limits tessellation factors in tessellation
/// control shaders. Values from 8 to 64 are
/// supported, other values will be ignored.
int32_t maxTessFactor;
int32_t maxTessFactor = 0;
/// Anisotropic filter override
///
/// Enforces anisotropic filtering with the
/// given anisotropy value for all samplers.
int32_t samplerAnisotropy;
int32_t samplerAnisotropy = -1;
/// Mipmap LOD bias
///
/// Enforces the given LOD bias for all samplers.
float samplerLodBias;
float samplerLodBias = 0.0f;
/// Clamps negative LOD bias
bool clampNegativeLodBias = false;
/// Declare vertex positions in shaders as invariant
bool invariantPosition;
bool invariantPosition = true;
/// Enable float control bits
bool floatControls;
/// Back buffer count for the Vulkan swap chain.
/// 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;
bool floatControls = true;
/// Override maximum frame latency if the app specifies
/// a higher value. May help with frame timing issues.
int32_t maxFrameLatency;
/// Limit frame rate
int32_t maxFrameRate;
/// Limit discardable resource size
VkDeviceSize maxImplicitDiscardSize;
/// Limit size of buffer-mapped images
VkDeviceSize maxDynamicImageBufferSize;
int32_t maxFrameLatency = 0;
/// Defer surface creation until first present call. This
/// fixes issues with games that create multiple swap chains
/// for a single window that may interfere with each other.
bool deferSurfaceCreation;
bool deferSurfaceCreation = false;
/// 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;
bool forceSampleRateShading = false;
/// Forces the sample count of all textures to be 1, and
/// performs the required shader and resolve fixups.
bool disableMsaa;
bool disableMsaa = false;
/// Dynamic resources with the given bind flags will be allocated
/// in cached system memory. Enabled automatically when recording
/// an api trace.
uint32_t cachedDynamicResources;
uint32_t cachedDynamicResources = 0;
/// Always lock immediate context on every API call. May be
/// useful for debugging purposes or when applications have
/// race conditions.
bool enableContextLock;
bool enableContextLock = false;
/// 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 = true;
/// Ensure that for the same D3D commands the output VK commands
/// don't change between runs. Useful for comparative benchmarking,
/// can negatively affect performance.
bool reproducibleCommandStream = false;
/// Shader dump path
std::string shaderDumpPath;
};
}
}

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

@ -103,8 +103,8 @@ namespace dxvk {
D3D11_VK_QUERY_STATE m_state;
std::array<Rc<DxvkGpuQuery>, MaxGpuQueries> m_query;
std::array<Rc<DxvkGpuEvent>, MaxGpuEvents> m_event;
std::array<Rc<DxvkQuery>, MaxGpuQueries> m_query;
std::array<Rc<DxvkEvent>, MaxGpuEvents> m_event;
D3D10Query m_d3d10;

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,141 @@
#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()->getMemoryInfo().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);
}
VkResult vr = dxvkDevice->vkd()->wine_vkReleaseKeyedMutex(
dxvkDevice->handle(), texture->GetImage()->getMemoryInfo().memory, Key);
return vr == 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 +211,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 +276,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 +289,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 +303,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

@ -9,59 +9,58 @@ namespace dxvk {
const D3D11_SAMPLER_DESC& desc)
: D3D11StateObject<ID3D11SamplerState>(device),
m_desc(desc), m_d3d10(this) {
DxvkSamplerCreateInfo info;
DxvkSamplerKey info = { };
// While D3D11_FILTER is technically an enum, its value bits
// can be used to decode the filter properties more efficiently.
const uint32_t filterBits = uint32_t(desc.Filter);
info.magFilter = (filterBits & 0x04) ? VK_FILTER_LINEAR : VK_FILTER_NEAREST;
info.minFilter = (filterBits & 0x10) ? VK_FILTER_LINEAR : VK_FILTER_NEAREST;
VkFilter minFilter = (filterBits & 0x10) ? VK_FILTER_LINEAR : VK_FILTER_NEAREST;
VkFilter magFilter = (filterBits & 0x04) ? VK_FILTER_LINEAR : VK_FILTER_NEAREST;
info.setFilter(minFilter, magFilter,
(filterBits & 0x01) ? VK_SAMPLER_MIPMAP_MODE_LINEAR : VK_SAMPLER_MIPMAP_MODE_NEAREST);
// Enforce LOD bias specified in the device options
float lodBias = desc.MipLODBias;
if (minFilter == VK_FILTER_LINEAR && magFilter == VK_FILTER_LINEAR) {
lodBias += device->GetOptions()->samplerLodBias;
if (device->GetOptions()->clampNegativeLodBias)
lodBias = std::max(lodBias, 0.0f);
}
info.setLodRange(desc.MinLOD, desc.MaxLOD, lodBias);
// Enforce anisotropy specified in the device options
uint32_t anisotropy = (filterBits & 0x40) ? desc.MaxAnisotropy : 0u;
int32_t samplerAnisotropyOption = device->GetOptions()->samplerAnisotropy;
if (samplerAnisotropyOption >= 0 && minFilter == VK_FILTER_LINEAR)
anisotropy = samplerAnisotropyOption;
info.setAniso(anisotropy);
// Set up the remaining properties, which are
// stored directly in the sampler description
info.mipmapMode = (filterBits & 0x01) ? VK_SAMPLER_MIPMAP_MODE_LINEAR : VK_SAMPLER_MIPMAP_MODE_NEAREST;
info.mipmapLodBias = desc.MipLODBias;
info.mipmapLodMin = desc.MinLOD;
info.mipmapLodMax = desc.MaxLOD;
info.useAnisotropy = (filterBits & 0x40) ? VK_TRUE : VK_FALSE;
info.maxAnisotropy = float(desc.MaxAnisotropy);
info.addressModeU = DecodeAddressMode(desc.AddressU);
info.addressModeV = DecodeAddressMode(desc.AddressV);
info.addressModeW = DecodeAddressMode(desc.AddressW);
info.compareToDepth = (filterBits & 0x180) == 0x80 ? VK_TRUE : VK_FALSE;
info.compareOp = DecodeCompareOp(desc.ComparisonFunc);
info.setAddressModes(
DecodeAddressMode(desc.AddressU),
DecodeAddressMode(desc.AddressV),
DecodeAddressMode(desc.AddressW));
info.reductionMode = DecodeReductionMode(filterBits);
info.setDepthCompare((filterBits & 0x180) == 0x80,
DecodeCompareOp(desc.ComparisonFunc));
info.setReduction(DecodeReductionMode(filterBits));
for (uint32_t i = 0; i < 4; i++)
info.borderColor.float32[i] = desc.BorderColor[i];
info.usePixelCoord = VK_FALSE; // Not supported in D3D11
info.nonSeamless = VK_FALSE;
// Make sure to use a valid anisotropy value
if (desc.MaxAnisotropy < 1) info.maxAnisotropy = 1.0f;
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)
info.mipmapLodBias += device->GetOptions()->samplerLodBias;
// Enforce anisotropy specified in the device options
int32_t samplerAnisotropyOption = device->GetOptions()->samplerAnisotropy;
if (samplerAnisotropyOption >= 0 && info.minFilter == VK_FILTER_LINEAR) {
info.useAnisotropy = samplerAnisotropyOption > 0;
info.maxAnisotropy = float(samplerAnisotropyOption);
}
m_sampler = device->GetDXVKDevice()->createSampler(info);
}
D3D11SamplerState::~D3D11SamplerState() {
}
@ -86,8 +85,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

@ -59,25 +59,33 @@ namespace dxvk {
}
// Create shader constant buffer if necessary
const DxvkShaderCreateInfo& shaderInfo = m_shader->info();
auto icb = module.icbInfo();
if (shaderInfo.uniformSize) {
DxvkBufferCreateInfo info;
info.size = shaderInfo.uniformSize;
info.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
info.stages = util::pipelineStages(shaderInfo.stage);
info.access = VK_ACCESS_UNIFORM_READ_BIT;
VkMemoryPropertyFlags memFlags
= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
| VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
| VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
m_buffer = pDevice->GetDXVKDevice()->createBuffer(info, memFlags);
std::memcpy(m_buffer->mapPtr(0), shaderInfo.uniformData, shaderInfo.uniformSize);
if (icb.size) {
DxvkBufferCreateInfo info = { };
info.size = align(icb.size, 256u);
info.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT
| VK_BUFFER_USAGE_TRANSFER_SRC_BIT
| VK_BUFFER_USAGE_TRANSFER_DST_BIT;
info.stages = util::pipelineStages(m_shader->info().stage);
info.access = VK_ACCESS_UNIFORM_READ_BIT
| VK_ACCESS_TRANSFER_READ_BIT
| VK_ACCESS_TRANSFER_WRITE_BIT;
info.debugName = "Icb";
m_buffer = pDevice->GetDXVKDevice()->createBuffer(info, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
// Upload immediate constant buffer to VRAM
pDevice->InitShaderIcb(this, icb.size, icb.data);
}
pDevice->GetDXVKDevice()->registerShader(m_shader);
// Write back binding mask
auto bindings = module.bindings();
if (bindings)
m_bindings = *bindings;
}

View file

@ -18,7 +18,7 @@
namespace dxvk {
class D3D11Device;
/**
* \brief Common shader object
*
@ -52,12 +52,18 @@ namespace dxvk {
std::string GetName() const {
return m_shader->debugName();
}
DxbcBindingMask GetBindingMask() const {
return m_bindings;
}
private:
Rc<DxvkShader> m_shader;
Rc<DxvkBuffer> m_buffer;
DxbcBindingMask m_bindings = { };
};
@ -134,7 +140,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

@ -2,6 +2,8 @@
#include "d3d11_device.h"
#include "d3d11_swapchain.h"
#include "../dxvk/dxvk_latency_builtin.h"
#include "../util/util_win32_compat.h"
namespace dxvk {
@ -32,7 +34,7 @@ namespace dxvk {
}
static float ConvertMinLuminance(UINT dxgiLuminance) {
return float(dxgiLuminance) / 0.0001f;
return float(dxgiLuminance) * 0.0001f;
}
static float ConvertLevel(UINT16 dxgiLevel) {
@ -63,16 +65,11 @@ namespace dxvk {
m_surfaceFactory(pSurfaceFactory),
m_desc(*pDesc),
m_device(pDevice->GetDXVKDevice()),
m_context(m_device->createContext(DxvkContextType::Supplementary)),
m_frameLatencyCap(pDevice->GetOptions()->maxFrameLatency) {
CreateFrameLatencyEvent();
CreatePresenter();
CreateBackBuffer();
CreateBackBuffers();
CreateBlitter();
CreateHud();
if (!pDevice->GetOptions()->deferSurfaceCreation)
RecreateSwapChain(false);
}
@ -82,10 +79,10 @@ namespace dxvk {
if (this_thread::isInModuleDetachment())
return;
m_device->waitForSubmission(&m_presentStatus);
m_device->waitForIdle();
m_presenter->destroyResources();
DestroyFrameLatencyEvent();
DestroyLatencyTracker();
}
@ -98,12 +95,18 @@ namespace dxvk {
InitReturnPtr(ppvObject);
if (riid == __uuidof(IUnknown)
|| riid == __uuidof(IDXGIVkSwapChain)) {
|| riid == __uuidof(IDXGIVkSwapChain)
|| riid == __uuidof(IDXGIVkSwapChain1)
|| riid == __uuidof(IDXGIVkSwapChain2)) {
*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;
}
@ -135,12 +138,12 @@ namespace dxvk {
void** ppBuffer) {
InitReturnPtr(ppBuffer);
if (BufferId > 0) {
Logger::err("D3D11: GetImage: BufferId > 0 not supported");
if (BufferId >= m_backBuffers.size()) {
Logger::err("D3D11: GetImage: Invalid buffer ID");
return DXGI_ERROR_UNSUPPORTED;
}
return m_backBuffer->QueryInterface(riid, ppBuffer);
return m_backBuffers[BufferId]->QueryInterface(riid, ppBuffer);
}
@ -156,12 +159,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;
}
@ -174,14 +175,14 @@ namespace dxvk {
const DXGI_SWAP_CHAIN_DESC1* pDesc,
const UINT* pNodeMasks,
IUnknown* const* ppPresentQueues) {
m_dirty |= m_desc.Format != pDesc->Format
|| m_desc.Width != pDesc->Width
|| m_desc.Height != pDesc->Height
|| m_desc.BufferCount != pDesc->BufferCount
|| m_desc.Flags != pDesc->Flags;
if (m_desc.Format != pDesc->Format)
m_presenter->setSurfaceFormat(GetSurfaceFormat(pDesc->Format));
if (m_desc.Width != pDesc->Width || m_desc.Height != pDesc->Height)
m_presenter->setSurfaceExtent({ m_desc.Width, m_desc.Height });
m_desc = *pDesc;
CreateBackBuffer();
CreateBackBuffers();
return S_OK;
}
@ -251,44 +252,48 @@ 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;
}
HRESULT hr = S_OK;
if (!m_presenter->hasSwapChain()) {
RecreateSwapChain(m_vsync);
m_dirty = false;
}
if (!m_presenter->hasSwapChain())
hr = DXGI_STATUS_OCCLUDED;
if (m_device->getDeviceStatus() != VK_SUCCESS)
hr = DXGI_ERROR_DEVICE_RESET;
if ((PresentFlags & DXGI_PRESENT_TEST) || hr != S_OK)
return hr;
if (PresentFlags & DXGI_PRESENT_TEST) {
if (hr != S_OK)
return hr;
VkResult status = m_presenter->checkSwapChainStatus();
return status == VK_SUCCESS ? S_OK : DXGI_STATUS_OCCLUDED;
}
if (hr != S_OK) {
SyncFrameLatency();
return hr;
}
if (std::exchange(m_dirty, false))
RecreateSwapChain(m_vsync);
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();
// Ignore latency stuff if presentation failed
DxvkLatencyStats latencyStats = { };
if (hr == S_OK && m_latency) {
latencyStats = m_latency->getStatistics(m_frameId);
m_latency->sleepAndBeginFrame(m_frameId + 1, std::abs(m_targetFrameRate));
}
if (m_latencyHud)
m_latencyHud->accumulateStats(latencyStats);
return hr;
}
@ -297,7 +302,8 @@ namespace dxvk {
DXGI_COLOR_SPACE_TYPE ColorSpace) {
UINT supportFlags = 0;
const VkColorSpaceKHR vkColorSpace = ConvertColorSpace(ColorSpace);
VkColorSpaceKHR vkColorSpace = ConvertColorSpace(ColorSpace);
if (m_presenter->supportsColorSpace(vkColorSpace))
supportFlags |= DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT;
@ -307,13 +313,14 @@ namespace dxvk {
HRESULT STDMETHODCALLTYPE D3D11SwapChain::SetColorSpace(
DXGI_COLOR_SPACE_TYPE ColorSpace) {
if (!(CheckColorSpaceSupport(ColorSpace) & DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT))
VkColorSpaceKHR colorSpace = ConvertColorSpace(ColorSpace);
if (!m_presenter->supportsColorSpace(colorSpace))
return E_INVALIDARG;
const VkColorSpaceKHR vkColorSpace = ConvertColorSpace(ColorSpace);
m_dirty |= vkColorSpace != m_colorspace;
m_colorspace = vkColorSpace;
m_colorSpace = colorSpace;
m_presenter->setSurfaceFormat(GetSurfaceFormat(m_desc.Format));
return S_OK;
}
@ -321,149 +328,166 @@ 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) {
m_hdrMetadata = ConvertHDRMetadata(pMetaData->HDR10);
m_dirtyHdrMetadata = true;
}
if (pMetaData->Type == DXGI_HDR_METADATA_TYPE_HDR10)
m_presenter->setHdrMetadata(ConvertHDRMetadata(pMetaData->HDR10));
return S_OK;
}
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;
}
void STDMETHODCALLTYPE D3D11SwapChain::SetTargetFrameRate(
double FrameRate) {
m_targetFrameRate = FrameRate;
if (m_presenter != nullptr)
m_presenter->setFrameRateLimit(m_targetFrameRate, GetActualFrameLatency());
}
Rc<DxvkImageView> D3D11SwapChain::GetBackBufferView() {
Rc<DxvkImage> image = GetCommonTexture(m_backBuffers[0].ptr())->GetImage();
DxvkImageViewKey key;
key.viewType = VK_IMAGE_VIEW_TYPE_2D;
key.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
key.format = image->info().format;
key.aspects = VK_IMAGE_ASPECT_COLOR_BIT;
key.mipIndex = 0u;
key.mipCount = 1u;
key.layerIndex = 0u;
key.layerCount = 1u;
return image->createView(key);
}
HRESULT D3D11SwapChain::PresentImage(UINT SyncInterval) {
Com<ID3D11DeviceContext> deviceContext = nullptr;
m_parent->GetImmediateContext(&deviceContext);
// Flush pending rendering commands before
auto immediateContext = static_cast<D3D11ImmediateContext*>(deviceContext.ptr());
immediateContext->EndFrame();
immediateContext->Flush();
auto immediateContext = m_parent->GetContext();
auto immediateContextLock = immediateContext->LockContext();
// Bump our frame id.
++m_frameId;
for (uint32_t i = 0; i < SyncInterval || i < 1; i++) {
SynchronizePresent();
immediateContext->EndFrame(m_latency);
immediateContext->ExecuteFlush(GpuFlushType::ExplicitFlush, nullptr, true);
if (!m_presenter->hasSwapChain())
return DXGI_STATUS_OCCLUDED;
m_presenter->setSyncInterval(SyncInterval);
// Presentation semaphores and WSI swap chain image
vk::PresenterInfo info = m_presenter->info();
vk::PresenterSync sync;
// Presentation semaphores and WSI swap chain image
if (m_latency)
m_latency->notifyCpuPresentBegin(m_frameId + 1u);
uint32_t imageIndex = 0;
PresenterSync sync;
Rc<DxvkImage> backBuffer;
VkResult status = m_presenter->acquireNextImage(sync, imageIndex);
VkResult status = m_presenter->acquireNextImage(sync, backBuffer);
while (status != VK_SUCCESS && status != VK_SUBOPTIMAL_KHR) {
RecreateSwapChain(m_vsync);
if (status != VK_SUCCESS && m_latency)
m_latency->discardTimings();
if (!m_presenter->hasSwapChain())
return DXGI_STATUS_OCCLUDED;
info = m_presenter->info();
status = m_presenter->acquireNextImage(sync, imageIndex);
if (status < 0)
return E_FAIL;
if (status == VK_NOT_READY)
return DXGI_STATUS_OCCLUDED;
m_frameId += 1;
// Present from CS thread so that we don't
// have to synchronize with it first.
DxvkImageViewKey viewInfo = { };
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
viewInfo.format = backBuffer->info().format;
viewInfo.aspects = VK_IMAGE_ASPECT_COLOR_BIT;
viewInfo.mipIndex = 0u;
viewInfo.mipCount = 1u;
viewInfo.layerIndex = 0u;
viewInfo.layerCount = 1u;
immediateContext->EmitCs([
cDevice = m_device,
cBlitter = m_blitter,
cBackBuffer = backBuffer->createView(viewInfo),
cSwapImage = GetBackBufferView(),
cSync = sync,
cPresenter = m_presenter,
cLatency = m_latency,
cColorSpace = m_colorSpace,
cFrameId = m_frameId
] (DxvkContext* ctx) {
// Update back buffer color space as necessary
if (cSwapImage->image()->info().colorSpace != cColorSpace) {
DxvkImageUsageInfo usage = { };
usage.colorSpace = cColorSpace;
ctx->ensureImageCompatibility(cSwapImage->image(), usage);
}
if (m_hdrMetadata && m_dirtyHdrMetadata) {
m_presenter->setHdrMetadata(*m_hdrMetadata);
m_dirtyHdrMetadata = false;
// Blit the D3D back buffer onto the actual Vulkan
// swap chain and render the HUD if we have one.
auto contextObjects = ctx->beginExternalRendering();
cBlitter->present(contextObjects,
cBackBuffer, VkRect2D(),
cSwapImage, VkRect2D());
// Submit current command list and present
ctx->synchronizeWsi(cSync);
ctx->flushCommandList(nullptr, nullptr);
cDevice->presentImage(cPresenter, cLatency, cFrameId, nullptr);
});
if (m_backBuffers.size() > 1u)
RotateBackBuffers(immediateContext);
immediateContext->FlushCsChunk();
if (m_latency) {
m_latency->notifyCpuPresentEnd(m_frameId);
if (m_latency->needsAutoMarkers()) {
immediateContext->EmitCs([
cLatency = m_latency,
cFrameId = m_frameId
] (DxvkContext* ctx) {
ctx->beginLatencyTracking(cLatency, cFrameId + 1u);
});
}
// Resolve back buffer if it is multisampled. We
// only have to do it only for the first frame.
m_context->beginRecording(
m_device->createCommandList());
m_blitter->presentImage(m_context.ptr(),
m_imageViews.at(imageIndex), VkRect2D(),
m_swapImageView, VkRect2D());
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) {
auto lock = pContext->LockContext();
void D3D11SwapChain::RotateBackBuffers(D3D11ImmediateContext* ctx) {
small_vector<Rc<DxvkImage>, 4> images;
// Present from CS thread so that we don't
// have to synchronize with it first.
m_presentStatus.result = VK_NOT_READY;
for (uint32_t i = 0; i < m_backBuffers.size(); i++)
images.push_back(GetCommonTexture(m_backBuffers[i].ptr())->GetImage());
pContext->EmitCs([this,
cFrameId = FrameId,
cSync = Sync,
cHud = m_hud,
cCommandList = m_context->endRecording()
ctx->EmitCs([
cImages = std::move(images)
] (DxvkContext* ctx) {
cCommandList->setWsiSemaphores(cSync);
m_device->submitCommandList(cCommandList);
auto allocation = cImages[0]->storage();
if (cHud != nullptr && !cFrameId)
cHud->update();
for (size_t i = 0u; i + 1 < cImages.size(); i++)
ctx->invalidateImage(cImages[i], cImages[i + 1]->storage());
m_device->presentImage(m_presenter, &m_presentStatus);
ctx->invalidateImage(cImages[cImages.size() - 1u], std::move(allocation));
});
pContext->FlushCsChunk();
}
void D3D11SwapChain::SynchronizePresent() {
// Recreate swap chain if the previous present call failed
VkResult status = m_device->waitForSubmission(&m_presentStatus);
if (status != VK_SUCCESS)
RecreateSwapChain(m_vsync);
}
void D3D11SwapChain::RecreateSwapChain(BOOL Vsync) {
// 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.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);
if (vr == VK_ERROR_SURFACE_LOST_KHR) {
vr = m_presenter->recreateSurface([this] (VkSurfaceKHR* surface) {
return CreateSurface(surface);
});
if (vr)
throw DxvkError(str::format("D3D11SwapChain: Failed to recreate surface: ", vr));
vr = m_presenter->recreateSwapChain(presenterDesc);
}
if (vr)
throw DxvkError(str::format("D3D11SwapChain: Failed to recreate swap chain: ", vr));
CreateRenderTargetViews();
}
@ -476,90 +500,37 @@ namespace dxvk {
void D3D11SwapChain::CreatePresenter() {
DxvkDeviceQueue graphicsQueue = m_device->queues().graphics;
PresenterDesc presenterDesc = { };
presenterDesc.deferSurfaceCreation = m_parent->GetOptions()->deferSurfaceCreation;
vk::PresenterDevice presenterDevice;
presenterDevice.queueFamily = graphicsQueue.queueFamily;
presenterDevice.queue = graphicsQueue.queueHandle;
presenterDevice.adapter = m_device->adapter()->handle();
presenterDevice.features.fullScreenExclusive = m_device->features().extFullScreenExclusive;
presenterDevice.features.hdrMetadata = m_device->features().extHdrMetadata;
m_presenter = new Presenter(m_device, m_frameLatencySignal, presenterDesc, [
cAdapter = m_device->adapter(),
cFactory = m_surfaceFactory
] (VkSurfaceKHR* surface) {
return cFactory->CreateSurface(
cAdapter->vki()->instance(),
cAdapter->handle(), surface);
});
vk::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->setSurfaceFormat(GetSurfaceFormat(m_desc.Format));
m_presenter->setSurfaceExtent({ m_desc.Width, m_desc.Height });
m_presenter->setFrameRateLimit(m_targetFrameRate, GetActualFrameLatency());
m_presenter = new vk::Presenter(
m_device->adapter()->vki(),
m_device->vkd(),
presenterDevice,
presenterDesc);
m_presenter->setFrameRateLimit(m_parent->GetOptions()->maxFrameRate);
m_latency = m_device->createLatencyTracker(m_presenter);
Com<D3D11ReflexDevice> reflex = GetReflexDevice();
reflex->RegisterLatencyTracker(m_latency);
}
VkResult D3D11SwapChain::CreateSurface(VkSurfaceKHR* pSurface) {
Rc<DxvkAdapter> adapter = m_device->adapter();
return m_surfaceFactory->CreateSurface(
adapter->vki()->instance(),
adapter->handle(), pSurface);
}
void D3D11SwapChain::CreateRenderTargetViews() {
vk::PresenterInfo info = m_presenter->info();
m_imageViews.clear();
m_imageViews.resize(info.imageCount);
DxvkImageCreateInfo imageInfo;
imageInfo.type = VK_IMAGE_TYPE_2D;
imageInfo.format = info.format.format;
imageInfo.flags = 0;
imageInfo.sampleCount = VK_SAMPLE_COUNT_1_BIT;
imageInfo.extent = { info.imageExtent.width, info.imageExtent.height, 1 };
imageInfo.numLayers = 1;
imageInfo.mipLevels = 1;
imageInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
imageInfo.stages = 0;
imageInfo.access = 0;
imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
imageInfo.layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
imageInfo.shared = VK_TRUE;
DxvkImageViewCreateInfo viewInfo;
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.format = info.format.format;
viewInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
viewInfo.aspect = VK_IMAGE_ASPECT_COLOR_BIT;
viewInfo.minLevel = 0;
viewInfo.numLevels = 1;
viewInfo.minLayer = 0;
viewInfo.numLayers = 1;
for (uint32_t i = 0; i < info.imageCount; i++) {
VkImage imageHandle = m_presenter->getImage(i).image;
Rc<DxvkImage> image = new DxvkImage(
m_device.ptr(), imageInfo, imageHandle);
m_imageViews[i] = new DxvkImageView(
m_device->vkd(), image, viewInfo);
}
}
void D3D11SwapChain::CreateBackBuffer() {
void D3D11SwapChain::CreateBackBuffers() {
// Explicitly destroy current swap image before
// creating a new one to free up resources
m_swapImage = nullptr;
m_swapImageView = nullptr;
m_backBuffer = nullptr;
m_backBuffers.clear();
bool sequential = m_desc.SwapEffect == DXGI_SWAP_EFFECT_SEQUENTIAL ||
m_desc.SwapEffect == DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
uint32_t backBufferCount = sequential ? m_desc.BufferCount : 1u;
// Create new back buffer
D3D11_COMMON_TEXTURE_DESC desc;
@ -590,56 +561,49 @@ namespace dxvk {
DXGI_USAGE dxgiUsage = DXGI_USAGE_BACK_BUFFER;
if (m_desc.SwapEffect == DXGI_SWAP_EFFECT_DISCARD
|| m_desc.SwapEffect == DXGI_SWAP_EFFECT_FLIP_DISCARD)
dxgiUsage |= DXGI_USAGE_DISCARD_ON_PRESENT;
for (uint32_t i = 0; i < backBufferCount; i++) {
if (m_desc.SwapEffect == DXGI_SWAP_EFFECT_DISCARD
|| m_desc.SwapEffect == DXGI_SWAP_EFFECT_FLIP_DISCARD)
dxgiUsage |= DXGI_USAGE_DISCARD_ON_PRESENT;
m_backBuffer = new D3D11Texture2D(m_parent, this, &desc, dxgiUsage);
m_swapImage = GetCommonTexture(m_backBuffer.ptr())->GetImage();
m_backBuffers.push_back(new D3D11Texture2D(
m_parent, this, &desc, dxgiUsage));
// Create an image view that allows the
// image to be bound as a shader resource.
DxvkImageViewCreateInfo viewInfo;
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.format = m_swapImage->info().format;
viewInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
viewInfo.aspect = VK_IMAGE_ASPECT_COLOR_BIT;
viewInfo.minLevel = 0;
viewInfo.numLevels = 1;
viewInfo.minLayer = 0;
viewInfo.numLayers = 1;
m_swapImageView = m_device->createImageView(m_swapImage, viewInfo);
// Initialize the image so that we can use it. Clearing
dxgiUsage |= DXGI_USAGE_READ_ONLY;
}
small_vector<Rc<DxvkImage>, 4> images;
for (uint32_t i = 0; i < backBufferCount; i++)
images.push_back(GetCommonTexture(m_backBuffers[i].ptr())->GetImage());
// Initialize images so that we can use them. Clearing
// to black prevents garbled output for the first frame.
VkImageSubresourceRange subresources;
subresources.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
subresources.baseMipLevel = 0;
subresources.levelCount = 1;
subresources.baseArrayLayer = 0;
subresources.layerCount = 1;
m_parent->GetContext()->InjectCs(DxvkCsQueue::HighPriority, [
cImages = std::move(images)
] (DxvkContext* ctx) {
for (size_t i = 0; i < cImages.size(); i++) {
ctx->setDebugName(cImages[i], str::format("Back buffer ", i).c_str());
m_context->beginRecording(
m_device->createCommandList());
m_context->initImage(m_swapImage,
subresources, VK_IMAGE_LAYOUT_UNDEFINED);
m_device->submitCommandList(
m_context->endRecording());
ctx->initImage(cImages[i],
cImages[i]->getAvailableSubresources(),
VK_IMAGE_LAYOUT_UNDEFINED);
}
});
}
void D3D11SwapChain::CreateBlitter() {
m_blitter = new DxvkSwapchainBlitter(m_device);
}
Rc<hud::Hud> hud = hud::Hud::createHud(m_device);
if (hud) {
hud->addItem<hud::HudClientApiItem>("api", 1, GetApiName());
void D3D11SwapChain::CreateHud() {
m_hud = hud::Hud::createHud(m_device);
if (m_latency)
m_latencyHud = hud->addItem<hud::HudLatencyItem>("latency", 4);
}
if (m_hud != nullptr)
m_hud->addItem<hud::HudClientApiItem>("api", 1, GetApiName());
m_blitter = new DxvkSwapchainBlitter(m_device, std::move(hud));
}
@ -648,15 +612,35 @@ namespace dxvk {
}
void D3D11SwapChain::DestroyLatencyTracker() {
// Need to make sure the context stops using
// the tracker for submissions
m_parent->GetContext()->InjectCs(DxvkCsQueue::Ordered, [
cLatency = m_latency
] (DxvkContext* ctx) {
ctx->endLatencyTracking(cLatency);
});
Com<D3D11ReflexDevice> reflex = GetReflexDevice();
reflex->UnregisterLatencyTracker(m_latency);
}
void D3D11SwapChain::SyncFrameLatency() {
// 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();
});
}
@ -672,77 +656,39 @@ 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;
}
uint32_t D3D11SwapChain::PickFormats(
DXGI_FORMAT Format,
VkSurfaceFormatKHR* pDstFormats) {
uint32_t n = 0;
VkSurfaceFormatKHR D3D11SwapChain::GetSurfaceFormat(DXGI_FORMAT Format) {
switch (Format) {
default:
Logger::warn(str::format("D3D11SwapChain: Unexpected format: ", m_desc.Format));
[[fallthrough]];
[[fallthrough]];
case DXGI_FORMAT_R8G8B8A8_UNORM:
case DXGI_FORMAT_B8G8R8A8_UNORM: {
pDstFormats[n++] = { VK_FORMAT_R8G8B8A8_UNORM, m_colorspace };
pDstFormats[n++] = { VK_FORMAT_B8G8R8A8_UNORM, m_colorspace };
} break;
case DXGI_FORMAT_B8G8R8A8_UNORM:
return { VK_FORMAT_R8G8B8A8_UNORM, m_colorSpace };
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: {
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, m_colorspace };
pDstFormats[n++] = { VK_FORMAT_A2R10G10B10_UNORM_PACK32, m_colorspace };
} break;
case DXGI_FORMAT_R16G16B16A16_FLOAT: {
pDstFormats[n++] = { VK_FORMAT_R16G16B16A16_SFLOAT, m_colorspace };
} break;
case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
return { VK_FORMAT_R8G8B8A8_SRGB, m_colorSpace };
case DXGI_FORMAT_R10G10B10A2_UNORM:
return { VK_FORMAT_A2B10G10R10_UNORM_PACK32, m_colorSpace };
case DXGI_FORMAT_R16G16B16A16_FLOAT:
return { VK_FORMAT_R16G16B16A16_SFLOAT, m_colorSpace };
}
return n;
}
uint32_t D3D11SwapChain::PickPresentModes(
BOOL Vsync,
VkPresentModeKHR* pDstModes) {
uint32_t n = 0;
Com<D3D11ReflexDevice> D3D11SwapChain::GetReflexDevice() {
Com<ID3DLowLatencyDevice> llDevice;
m_parent->QueryInterface(__uuidof(ID3DLowLatencyDevice), reinterpret_cast<void**>(&llDevice));
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;
return option > 0 ? uint32_t(option) : uint32_t(Preferred);
}
VkFullScreenExclusiveEXT D3D11SwapChain::PickFullscreenMode() {
return m_desc.Flags & DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
? VK_FULL_SCREEN_EXCLUSIVE_ALLOWED_EXT
: VK_FULL_SCREEN_EXCLUSIVE_DISALLOWED_EXT;
return static_cast<D3D11ReflexDevice*>(llDevice.ptr());
}

View file

@ -4,6 +4,7 @@
#include "../dxvk/hud/dxvk_hud.h"
#include "../dxvk/dxvk_latency.h"
#include "../dxvk/dxvk_swapchain_blitter.h"
#include "../util/sync/sync_signal.h"
@ -13,7 +14,7 @@ namespace dxvk {
class D3D11Device;
class D3D11DXGIDevice;
class D3D11SwapChain : public ComObject<IDXGIVkSwapChain> {
class D3D11SwapChain : public ComObject<IDXGIVkSwapChain2> {
constexpr static uint32_t DefaultFrameLatency = 1;
public:
@ -80,6 +81,15 @@ namespace dxvk {
HRESULT STDMETHODCALLTYPE SetHDRMetaData(
const DXGI_VK_HDR_METADATA* pMetaData);
void STDMETHODCALLTYPE GetLastPresentCount(
UINT64* pLastPresentCount);
void STDMETHODCALLTYPE GetFrameStatistics(
DXGI_VK_FRAME_STATISTICS* pFrameStatistics);
void STDMETHODCALLTYPE SetTargetFrameRate(
double FrameRate);
private:
enum BindingIds : uint32_t {
@ -95,81 +105,53 @@ namespace dxvk {
DXGI_SWAP_CHAIN_DESC1 m_desc;
Rc<DxvkDevice> m_device;
Rc<DxvkContext> m_context;
Rc<Presenter> m_presenter;
Rc<vk::Presenter> m_presenter;
Rc<DxvkImage> m_swapImage;
Rc<DxvkImageView> m_swapImageView;
Rc<DxvkSwapchainBlitter> m_blitter;
Rc<DxvkLatencyTracker> m_latency;
Rc<hud::Hud> m_hud;
small_vector<Com<D3D11Texture2D, false>, 4> m_backBuffers;
Com<D3D11Texture2D, false> m_backBuffer;
DxvkSubmitStatus m_presentStatus;
uint64_t m_frameId = DXGI_MAX_SWAP_CHAIN_BUFFERS;
uint32_t m_frameLatency = DefaultFrameLatency;
uint32_t m_frameLatencyCap = 0;
HANDLE m_frameLatencyEvent = nullptr;
Rc<sync::CallbackFence> m_frameLatencySignal;
std::vector<Rc<DxvkImageView>> m_imageViews;
VkColorSpaceKHR m_colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
uint64_t m_frameId = DXGI_MAX_SWAP_CHAIN_BUFFERS;
uint32_t m_frameLatency = DefaultFrameLatency;
uint32_t m_frameLatencyCap = 0;
HANDLE m_frameLatencyEvent = nullptr;
Rc<sync::CallbackFence> m_frameLatencySignal;
double m_targetFrameRate = 0.0;
HANDLE m_processHandle = nullptr;
dxvk::mutex m_frameStatisticsLock;
DXGI_VK_FRAME_STATISTICS m_frameStatistics = { };
bool m_dirty = true;
bool m_vsync = true;
Rc<hud::HudLatencyItem> m_latencyHud;
VkColorSpaceKHR m_colorspace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
std::optional<VkHdrMetadataEXT> m_hdrMetadata;
bool m_dirtyHdrMetadata = true;
Rc<DxvkImageView> GetBackBufferView();
HRESULT PresentImage(UINT SyncInterval);
void SubmitPresent(
D3D11ImmediateContext* pContext,
const vk::PresenterSync& Sync,
uint32_t FrameId);
void SynchronizePresent();
void RecreateSwapChain(
BOOL Vsync);
void RotateBackBuffers(D3D11ImmediateContext* ctx);
void CreateFrameLatencyEvent();
void CreatePresenter();
VkResult CreateSurface(VkSurfaceKHR* pSurface);
void CreateRenderTargetViews();
void CreateBackBuffer();
void CreateBackBuffers();
void CreateBlitter();
void CreateHud();
void DestroyFrameLatencyEvent();
void DestroyLatencyTracker();
void SyncFrameLatency();
uint32_t GetActualFrameLatency();
uint32_t PickFormats(
DXGI_FORMAT Format,
VkSurfaceFormatKHR* pDstFormats);
uint32_t PickPresentModes(
BOOL Vsync,
VkPresentModeKHR* pDstModes);
uint32_t PickImageCount(
UINT Preferred);
VkFullScreenExclusiveEXT PickFullscreenMode();
VkSurfaceFormatKHR GetSurfaceFormat(DXGI_FORMAT Format);
Com<D3D11ReflexDevice> GetReflexDevice();
std::string GetApiName() const;

View file

@ -1,4 +1,5 @@
#include "d3d11_device.h"
#include "d3d11_context_imm.h"
#include "d3d11_gdi.h"
#include "d3d11_texture.h"
@ -11,11 +12,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 +49,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;
}
@ -160,7 +169,8 @@ namespace dxvk {
imageInfo.tiling = VK_IMAGE_TILING_LINEAR;
// Determine map mode based on our findings
m_mapMode = DetermineMapMode(&imageInfo);
VkMemoryPropertyFlags memoryProperties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
std::tie(m_mapMode, memoryProperties) = DetermineMapMode(&imageInfo);
// If the image is mapped directly to host memory, we need
// to enable linear tiling, and DXVK needs to be aware that
@ -179,14 +189,25 @@ namespace dxvk {
}
// If necessary, create the mapped linear buffer
if (m_mapMode != D3D11_COMMON_TEXTURE_MAP_MODE_NONE) {
for (uint32_t i = 0; i < m_desc.ArraySize; i++) {
for (uint32_t j = 0; j < m_desc.MipLevels; j++) {
if (m_mapMode != D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT)
m_buffers.push_back(CreateMappedBuffer(j));
uint32_t subresourceCount = m_desc.ArraySize * m_desc.MipLevels;
m_mapInfo.push_back({ D3D11_MAP(~0u), 0ull });
}
if (m_mapMode != D3D11_COMMON_TEXTURE_MAP_MODE_NONE) {
m_mapInfo.resize(subresourceCount);
for (uint32_t i = 0; i < subresourceCount; i++) {
m_mapInfo[i].layout = DetermineSubresourceLayout(&imageInfo,
GetSubresourceFromIndex(formatProperties->aspectMask, i));
}
}
if (m_mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER
|| m_mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_STAGING
|| m_mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_DYNAMIC) {
m_buffers.resize(subresourceCount);
if (m_mapMode != D3D11_COMMON_TEXTURE_MAP_MODE_DYNAMIC) {
for (uint32_t i = 0; i < subresourceCount; i++)
CreateMappedBuffer(i);
}
}
@ -200,12 +221,6 @@ namespace dxvk {
if (imageInfo.tiling == VK_IMAGE_TILING_OPTIMAL && !isMultiPlane && imageInfo.sharing.mode == DxvkSharedHandleMode::None)
imageInfo.layout = OptimizeLayout(imageInfo.usage);
// 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);
// Check if we can actually create the image
if (!CheckImageSupport(&imageInfo, imageInfo.tiling)) {
throw DxvkError(str::format(
@ -220,18 +235,17 @@ namespace dxvk {
"\n Usage: ", std::hex, m_desc.BindFlags,
"\n Flags: ", std::hex, m_desc.MiscFlags));
}
// Create the image on a host-visible memory type
// in case it is going to be mapped directly.
VkMemoryPropertyFlags memoryProperties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
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 (m_mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT)
m_mapPtr = m_image->mapPtr(0);
if (imageInfo.sharing.mode == DxvkSharedHandleMode::Export)
ExportImageInfo();
@ -267,73 +281,24 @@ namespace dxvk {
}
VkImageSubresource D3D11CommonTexture::GetSubresourceFromIndex(
VkImageAspectFlags Aspect,
UINT Subresource) const {
VkImageSubresource result;
result.aspectMask = Aspect;
result.mipLevel = Subresource % m_desc.MipLevels;
result.arrayLayer = Subresource / m_desc.MipLevels;
return result;
}
D3D11_COMMON_TEXTURE_SUBRESOURCE_LAYOUT D3D11CommonTexture::GetSubresourceLayout(
VkImageAspectFlags AspectMask,
UINT Subresource) const {
// Color is mapped directly and depth-stencil are interleaved
// in packed formats, so just use the cached subresource layout
constexpr VkImageAspectFlags PlaneAspects = VK_IMAGE_ASPECT_PLANE_0_BIT
| VK_IMAGE_ASPECT_PLANE_1_BIT | VK_IMAGE_ASPECT_PLANE_2_BIT;
if ((Subresource < m_mapInfo.size()) && !(AspectMask & PlaneAspects))
return m_mapInfo[Subresource].layout;
// Safe-guard against invalid subresource index
if (Subresource >= m_desc.ArraySize * m_desc.MipLevels)
return D3D11_COMMON_TEXTURE_SUBRESOURCE_LAYOUT();
// Image info is only needed for direct-mapped images
VkImageSubresource subresource = GetSubresourceFromIndex(AspectMask, Subresource);
D3D11_COMMON_TEXTURE_SUBRESOURCE_LAYOUT layout = { };
switch (m_mapMode) {
case D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT: {
auto vkLayout = m_image->querySubresourceLayout(subresource);
layout.Offset = vkLayout.offset;
layout.Size = vkLayout.size;
layout.RowPitch = vkLayout.rowPitch;
layout.DepthPitch = vkLayout.depthPitch;
} break;
case D3D11_COMMON_TEXTURE_MAP_MODE_NONE:
case D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER:
case D3D11_COMMON_TEXTURE_MAP_MODE_STAGING: {
auto packedFormatInfo = lookupFormatInfo(m_packedFormat);
VkImageAspectFlags aspects = packedFormatInfo->aspectMask;
VkExtent3D mipExtent = MipLevelExtent(subresource.mipLevel);
while (aspects) {
auto aspect = vk::getNextAspect(aspects);
auto extent = mipExtent;
auto elementSize = packedFormatInfo->elementSize;
if (packedFormatInfo->flags.test(DxvkFormatFlag::MultiPlane)) {
auto plane = &packedFormatInfo->planes[vk::getPlaneIndex(aspect)];
extent.width /= plane->blockSize.width;
extent.height /= plane->blockSize.height;
elementSize = plane->elementSize;
}
auto blockCount = util::computeBlockCount(extent, packedFormatInfo->blockSize);
if (!layout.RowPitch) {
layout.RowPitch = elementSize * blockCount.width;
layout.DepthPitch = elementSize * blockCount.width * blockCount.height;
}
VkDeviceSize size = elementSize * blockCount.width * blockCount.height * blockCount.depth;
if (aspect & AspectMask)
layout.Size += size;
else if (!layout.Size)
layout.Offset += size;
}
} break;
}
// D3D wants us to return the total subresource size in some instances
if (m_dimension < D3D11_RESOURCE_DIMENSION_TEXTURE2D) layout.RowPitch = layout.Size;
if (m_dimension < D3D11_RESOURCE_DIMENSION_TEXTURE3D) layout.DepthPitch = layout.Size;
return layout;
return DetermineSubresourceLayout(nullptr, subresource);
}
@ -408,8 +373,31 @@ namespace dxvk {
return viewFormat.Format == baseFormat.Format && planeCount == 1;
}
}
void D3D11CommonTexture::SetDebugName(const char* pName) {
if (m_image) {
m_device->GetContext()->InjectCs(DxvkCsQueue::HighPriority, [
cImage = m_image,
cName = std::string(pName ? pName : "")
] (DxvkContext* ctx) {
ctx->setDebugName(cImage, cName.c_str());
});
}
if (m_mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_STAGING) {
for (uint32_t i = 0; i < m_buffers.size(); i++) {
m_device->GetContext()->InjectCs(DxvkCsQueue::HighPriority, [
cBuffer = m_buffers[i].buffer,
cName = std::string(pName ? pName : "")
] (DxvkContext* ctx) {
ctx->setDebugName(cBuffer, cName.c_str());
});
}
}
}
HRESULT D3D11CommonTexture::NormalizeTextureProperties(D3D11_COMMON_TEXTURE_DESC* pDesc) {
if (pDesc->Width == 0 || pDesc->Height == 0 || pDesc->Depth == 0 || pDesc->ArraySize == 0)
return E_INVALIDARG;
@ -469,9 +457,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 +525,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)
@ -504,146 +543,188 @@ namespace dxvk {
return (support.linear & Features) == Features
|| (support.optimal & Features) == Features;
}
VkImageUsageFlags D3D11CommonTexture::EnableMetaCopyUsage(
VkFormat Format,
VkImageTiling Tiling) const {
VkFormatFeatureFlags2 requestedFeatures = 0;
if (Format == VK_FORMAT_D16_UNORM || Format == VK_FORMAT_D32_SFLOAT) {
requestedFeatures |= VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT
| VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT;
}
if (Format == VK_FORMAT_R16_UNORM || Format == VK_FORMAT_R32_SFLOAT) {
requestedFeatures |= VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT
| VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT;
}
if (Format == VK_FORMAT_D32_SFLOAT_S8_UINT || Format == VK_FORMAT_D24_UNORM_S8_UINT)
requestedFeatures |= VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT;
if (!requestedFeatures)
return 0;
// Enable usage flags for all supported and requested features
DxvkFormatFeatures support = m_device->GetDXVKDevice()->getFormatFeatures(Format);
requestedFeatures &= Tiling == VK_IMAGE_TILING_OPTIMAL
? support.optimal
: support.linear;
VkImageUsageFlags requestedUsage = 0;
if (requestedFeatures & VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT)
requestedUsage |= VK_IMAGE_USAGE_SAMPLED_BIT;
if (requestedFeatures & VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT)
requestedUsage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
if (requestedFeatures & VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT)
requestedUsage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
return requestedUsage;
}
VkImageUsageFlags D3D11CommonTexture::EnableMetaPackUsage(
VkFormat Format,
UINT CpuAccess) const {
if ((CpuAccess & D3D11_CPU_ACCESS_READ) == 0)
return 0;
const auto dsMask = VK_IMAGE_ASPECT_DEPTH_BIT
| VK_IMAGE_ASPECT_STENCIL_BIT;
auto formatInfo = lookupFormatInfo(Format);
return formatInfo->aspectMask == dsMask
? VK_IMAGE_USAGE_SAMPLED_BIT
: 0;
}
VkMemoryPropertyFlags D3D11CommonTexture::GetMemoryFlags() const {
std::pair<D3D11_COMMON_TEXTURE_MAP_MODE, VkMemoryPropertyFlags> D3D11CommonTexture::DetermineMapMode(
const DxvkImageCreateInfo* pImageInfo) const {
// Don't map an image unless the application requests it
if (!m_desc.CPUAccessFlags)
return { D3D11_COMMON_TEXTURE_MAP_MODE_NONE, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT };
// For default images, always use a persistent staging buffer. Readback
// may cause a GPU sync, but nobody seems to be using this feature anyway.
if (m_desc.Usage == D3D11_USAGE_DEFAULT)
return { D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT };
// If the resource cannot be used in the actual rendering pipeline, we
// do not need to create an actual image and can instead implement copy
// functions as buffer-to-image and image-to-buffer copies.
if (m_desc.Usage == D3D11_USAGE_STAGING)
return { D3D11_COMMON_TEXTURE_MAP_MODE_STAGING, 0u };
// If the packed format and image format don't match, we need to use
// a staging buffer and perform format conversion when mapping.
if (m_packedFormat != pImageInfo->format)
return { D3D11_COMMON_TEXTURE_MAP_MODE_DYNAMIC, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT };
// Multi-plane and depth-stencil images have a special memory layout
// in D3D11, so we can't expose those directly to the app
auto formatInfo = lookupFormatInfo(pImageInfo->format);
if (formatInfo->aspectMask != VK_IMAGE_ASPECT_COLOR_BIT)
return { D3D11_COMMON_TEXTURE_MAP_MODE_DYNAMIC, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT };
// If we can't use linear tiling for this image, we have to use a buffer
if (!CheckImageSupport(pImageInfo, VK_IMAGE_TILING_LINEAR))
return { D3D11_COMMON_TEXTURE_MAP_MODE_DYNAMIC, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT };
// Determine memory flags for the actual image if we use direct mapping.
// Depending on the concrete use case, we may fall back to different
// memory types.
VkMemoryPropertyFlags memoryFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
| VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
bool useCached = (m_device->GetOptions()->cachedDynamicResources == ~0u)
|| (m_device->GetOptions()->cachedDynamicResources & m_desc.BindFlags);
|| (m_device->GetOptions()->cachedDynamicResources & m_desc.BindFlags)
|| (m_desc.CPUAccessFlags & D3D11_CPU_ACCESS_READ);
if (m_desc.Usage == D3D11_USAGE_STAGING || useCached)
memoryFlags |= VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
else if (m_desc.Usage == D3D11_USAGE_DEFAULT || m_desc.BindFlags)
else if (m_desc.BindFlags)
memoryFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
return memoryFlags;
// If there are multiple subresources, go through a buffer because
// we can otherwise not really discard individual subresources.
if (m_desc.ArraySize > 1u || m_desc.MipLevels != 1u)
return { D3D11_COMMON_TEXTURE_MAP_MODE_DYNAMIC, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT };
// If the image is essentially linear already, expose it directly since
// there won't be any tangible benefit to using optimal tiling anyway.
VkExtent3D blockCount = util::computeBlockCount(pImageInfo->extent, formatInfo->blockSize);
if (blockCount.height == 1u && blockCount.depth == 1u)
return { D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT, memoryFlags };
// If the image looks like a video, we can generally expect it to get
// updated and read once per frame. This is one of the most common use
// cases for a mapped image, expose it directly in order to avoid copies.
if (blockCount.depth == 1u && blockCount.height >= 160 && formatInfo->elementSize <= 4u) {
static const std::array<std::pair<uint32_t, uint32_t>, 3> videoApectRatios = {{
{ 4, 3 },
{ 16, 9 },
{ 21, 9 },
}};
bool isVideoAspectRatio = false;
for (const auto& a : videoApectRatios) {
// Due to codec limitations, video dimensions are often rounded to
// a multiple of 8. Account for this when checking the size.
isVideoAspectRatio |= blockCount.width > (a.first * (blockCount.height - 8u)) / a.second
&& blockCount.width < (a.first * (blockCount.height + 8u)) / a.second;
}
if (isVideoAspectRatio) {
// Keep video images in system memory to not waste precious HVV space
return { D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT, memoryFlags & ~VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT };
}
}
// If the image exceeds a certain size, map it directly because the overhead
// of potentially copying the whole thing every frame likely outweighs any
// benefit we might get from faster memory and tiling. This solves such an
// issue in Warhammer III, which discards a 48 MB texture every single frame.
constexpr VkDeviceSize MaxImageStagingBufferSize = 1ull << 20;
VkDeviceSize imageSize = util::flattenImageExtent(blockCount) * formatInfo->elementSize;
if (imageSize > MaxImageStagingBufferSize)
return { D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT, memoryFlags };
// For smaller images, use a staging buffer. There are some common use
// cases where the image will only get written once, e.g. SMAA look-up
// tables in some games, which will benefit from faster GPU access.
return { D3D11_COMMON_TEXTURE_MAP_MODE_DYNAMIC, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT };
}
D3D11_COMMON_TEXTURE_MAP_MODE D3D11CommonTexture::DetermineMapMode(
const DxvkImageCreateInfo* pImageInfo) const {
// Don't map an image unless the application requests it
if (!m_desc.CPUAccessFlags)
return D3D11_COMMON_TEXTURE_MAP_MODE_NONE;
// If the resource cannot be used in the actual rendering pipeline, we
// do not need to create an actual image and can instead implement copy
// functions as buffer-to-image and image-to-buffer copies.
if (!m_desc.BindFlags && m_desc.Usage != D3D11_USAGE_DEFAULT)
return D3D11_COMMON_TEXTURE_MAP_MODE_STAGING;
D3D11_COMMON_TEXTURE_SUBRESOURCE_LAYOUT D3D11CommonTexture::DetermineSubresourceLayout(
const DxvkImageCreateInfo* pImageInfo,
const VkImageSubresource& subresource) const {
auto formatInfo = lookupFormatInfo(m_packedFormat);
// Depth-stencil formats in D3D11 can be mapped and follow special
// packing rules, so we need to copy that data into a buffer first
if (GetPackedDepthStencilFormat(m_desc.Format))
return D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER;
if (m_mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT) {
VkSubresourceLayout vkLayout = m_device->GetDXVKDevice()->queryImageSubresourceLayout(*pImageInfo, subresource);
// Multi-plane images have a special memory layout in D3D11
if (lookupFormatInfo(pImageInfo->format)->flags.test(DxvkFormatFlag::MultiPlane))
return D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER;
D3D11_COMMON_TEXTURE_SUBRESOURCE_LAYOUT result = { };
result.Offset = vkLayout.offset;
result.RowPitch = vkLayout.rowPitch;
result.DepthPitch = vkLayout.depthPitch;
// If we can't use linear tiling for this image, we have to use a buffer
if (!this->CheckImageSupport(pImageInfo, VK_IMAGE_TILING_LINEAR))
return D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER;
// We will only ever use direct mapping for single-aspect images,
// so ignore any sort of multi-plane shenanigans on this path
auto mipExtent = MipLevelExtent(subresource.mipLevel);
auto blockCount = util::computeBlockCount(mipExtent, formatInfo->blockSize);
// If supported and requested, create a linear image. Default images
// can be used for resolves and other operations regardless of bind
// flags, so we need to use a proper image for those.
if (m_desc.TextureLayout == D3D11_TEXTURE_LAYOUT_ROW_MAJOR)
return D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT;
// If the image dimensions support it, try to look as close to a
// linear buffer as we can. Some games use the depth pitch as a
// subresource size and will crash if it includes any padding.
if (blockCount.depth == 1u) {
if (blockCount.height == 1u) {
result.RowPitch = formatInfo->elementSize * blockCount.width;
result.DepthPitch = result.RowPitch;
} else {
result.DepthPitch = vkLayout.rowPitch * blockCount.height;
}
}
// For default images, prefer direct mapping if the image is CPU readable
// since mapping for reads would have to stall otherwise. If the image is
// only writable, prefer a write-through buffer.
if (m_desc.Usage == D3D11_USAGE_DEFAULT) {
return (m_desc.CPUAccessFlags & D3D11_CPU_ACCESS_READ)
? D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT
: D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER;
result.Size = blockCount.depth * result.DepthPitch;
return result;
} else {
D3D11_COMMON_TEXTURE_SUBRESOURCE_LAYOUT result = { };
VkImageAspectFlags aspects = formatInfo->aspectMask;
VkExtent3D mipExtent = MipLevelExtent(subresource.mipLevel);
while (aspects) {
auto aspect = vk::getNextAspect(aspects);
auto extent = mipExtent;
auto elementSize = formatInfo->elementSize;
if (formatInfo->flags.test(DxvkFormatFlag::MultiPlane)) {
auto plane = &formatInfo->planes[vk::getPlaneIndex(aspect)];
extent.width /= plane->blockSize.width;
extent.height /= plane->blockSize.height;
elementSize = plane->elementSize;
}
auto blockCount = util::computeBlockCount(extent, formatInfo->blockSize);
if (!result.RowPitch) {
result.RowPitch = elementSize * blockCount.width;
result.DepthPitch = elementSize * blockCount.width * blockCount.height;
}
VkDeviceSize size = elementSize * blockCount.width * blockCount.height * blockCount.depth;
if (aspect & subresource.aspectMask)
result.Size += size;
else if (!result.Size)
result.Offset += size;
}
return result;
}
// The overhead of frequently uploading large dynamic images may outweigh
// the benefit of linear tiling, so use a linear image in those cases.
VkDeviceSize threshold = m_device->GetOptions()->maxDynamicImageBufferSize;
VkDeviceSize size = util::computeImageDataSize(pImageInfo->format, pImageInfo->extent);
if (size > threshold)
return D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT;
// Dynamic images that can be sampled by a shader should generally go
// through a buffer to allow optimal tiling and to avoid running into
// bugs where games ignore the pitch when mapping the image.
return D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER;
}
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 +744,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);
}
@ -679,23 +760,25 @@ namespace dxvk {
}
D3D11CommonTexture::MappedBuffer D3D11CommonTexture::CreateMappedBuffer(UINT MipLevel) const {
void D3D11CommonTexture::CreateMappedBuffer(UINT Subresource) {
const DxvkFormatInfo* formatInfo = lookupFormatInfo(
m_device->LookupPackedFormat(m_desc.Format, GetFormatMode()).Format);
DxvkBufferCreateInfo info;
info.size = GetSubresourceLayout(formatInfo->aspectMask, MipLevel).Size;
info.size = GetSubresourceLayout(formatInfo->aspectMask, Subresource).Size;
info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT
| VK_BUFFER_USAGE_TRANSFER_DST_BIT
| VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
| VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT
| VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT;
info.stages = VK_PIPELINE_STAGE_TRANSFER_BIT
| VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
| VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT
| VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
info.access = VK_ACCESS_TRANSFER_READ_BIT
| VK_ACCESS_TRANSFER_WRITE_BIT
| VK_ACCESS_SHADER_READ_BIT
| VK_ACCESS_SHADER_WRITE_BIT;
info.debugName = "Image buffer";
// We may read mapped buffers even if it is
// marked as CPU write-only on the D3D11 side.
@ -714,11 +797,18 @@ namespace dxvk {
if (m_desc.Usage == D3D11_USAGE_STAGING || useCached)
memType |= VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
MappedBuffer result;
result.buffer = m_device->GetDXVKDevice()->createBuffer(info, memType);
result.slice = result.buffer->getSliceHandle();
return result;
auto& entry = m_buffers[Subresource];
entry.buffer = m_device->GetDXVKDevice()->createBuffer(info, memType);
entry.slice = entry.buffer->storage();
}
void D3D11CommonTexture::FreeMappedBuffer(
UINT Subresource) {
auto& entry = m_buffers[Subresource];
entry.buffer = nullptr;
entry.slice = nullptr;
}
@ -734,33 +824,34 @@ namespace dxvk {
VkImageLayout D3D11CommonTexture::OptimizeLayout(VkImageUsageFlags Usage) {
const VkImageUsageFlags usageFlags = Usage;
// Filter out unnecessary flags. Transfer operations
// are handled by the backend in a transparent manner.
Usage &= ~(VK_IMAGE_USAGE_TRANSFER_DST_BIT
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
// Storage images require GENERAL.
if (Usage & VK_IMAGE_USAGE_STORAGE_BIT)
return VK_IMAGE_LAYOUT_GENERAL;
// Also use GENERAL if the image cannot be rendered to. This
// should not harm any hardware in practice and may avoid some
// redundant layout transitions for regular textures.
if (Usage == VK_IMAGE_USAGE_SAMPLED_BIT)
return VK_IMAGE_LAYOUT_GENERAL;
// If the image is used only as an attachment, we never
// have to transform the image back to a different layout
// have to transform the image back to a different layout.
if (Usage == VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
if (Usage == VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)
return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
Usage &= ~(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
| VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
// If the image is used for reading but not as a storage
// image, we can optimize the image for texture access
if (Usage == VK_IMAGE_USAGE_SAMPLED_BIT) {
return usageFlags & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
? VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL
: VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
}
// Otherwise, we have to stick with the default layout
return VK_IMAGE_LAYOUT_GENERAL;
// Otherwise, pick a layout that can be used for reading.
return usageFlags & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
? VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL
: VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
}
@ -1028,12 +1119,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 +1172,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;
}
@ -1120,19 +1218,25 @@ namespace dxvk {
pDesc->CPUAccessFlags = m_texture.Desc()->CPUAccessFlags;
pDesc->MiscFlags = m_texture.Desc()->MiscFlags;
}
void STDMETHODCALLTYPE D3D11Texture1D::SetDebugName(const char* pName) {
m_texture.SetDebugName(pName);
}
///////////////////////////////////////////
// D 3 D 1 1 T E X T U R E 2 D
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 +1248,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 +1264,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) {
@ -1237,14 +1341,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;
}
@ -1296,15 +1406,21 @@ namespace dxvk {
}
void STDMETHODCALLTYPE D3D11Texture2D::SetDebugName(const char* pName) {
m_texture.SetDebugName(pName);
}
///////////////////////////////////////////
// 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) {
}
@ -1344,14 +1460,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;
}
@ -1400,6 +1522,11 @@ namespace dxvk {
}
void STDMETHODCALLTYPE D3D11Texture3D::SetDebugName(const char* pName) {
m_texture.SetDebugName(pName);
}
D3D11CommonTexture* GetCommonTexture(ID3D11Resource* pResource) {
D3D11_RESOURCE_DIMENSION dimension = D3D11_RESOURCE_DIMENSION_UNKNOWN;
pResource->GetType(&dimension);

View file

@ -1,5 +1,7 @@
#pragma once
#include "../util/util_small_vector.h"
#include "../dxvk/dxvk_cs.h"
#include "../dxvk/dxvk_device.h"
@ -7,6 +9,7 @@
#include "d3d11_device_child.h"
#include "d3d11_interfaces.h"
#include "d3d11_on_12.h"
#include "d3d11_resource.h"
namespace dxvk {
@ -23,6 +26,7 @@ namespace dxvk {
enum D3D11_COMMON_TEXTURE_MAP_MODE {
D3D11_COMMON_TEXTURE_MAP_MODE_NONE, ///< Not mapped
D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER, ///< Mapped through buffer
D3D11_COMMON_TEXTURE_MAP_MODE_DYNAMIC, ///< Mapped through temporary buffer
D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT, ///< Directly mapped to host mem
D3D11_COMMON_TEXTURE_MAP_MODE_STAGING, ///< Buffer only, no image
};
@ -80,11 +84,14 @@ namespace dxvk {
class D3D11CommonTexture {
public:
static constexpr uint32_t UnmappedSubresource = ~0u;
D3D11CommonTexture(
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,
@ -168,29 +175,73 @@ namespace dxvk {
return m_mapMode;
}
/**
* \brief Checks whether this texture has an image
*
* Staging textures will not use an image, only mapped buffers.
* \returns \c true for non-staging textures.
*/
bool HasImage() const {
return m_mapMode != D3D11_COMMON_TEXTURE_MAP_MODE_STAGING;
}
/**
* \brief Checks whether this texture has persistent buffers
* \returns \c true for buffer-mapped textures or staging textures.
*/
bool HasPersistentBuffers() const {
return m_mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER
|| m_mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_STAGING;
}
/**
* \brief Map type of a given subresource
*
* \param [in] Subresource Subresource index
* \returns Current map mode of that subresource
*/
D3D11_MAP GetMapType(UINT Subresource) const {
uint32_t GetMapType(UINT Subresource) const {
return Subresource < m_mapInfo.size()
? D3D11_MAP(m_mapInfo[Subresource].mapType)
: D3D11_MAP(~0u);
? m_mapInfo[Subresource].mapType
: UnmappedSubresource;
}
/**
* \brief Sets map type for a given subresource
*
*
* Also ensures taht a staging buffer is created
* in case of dynamic mapping.
* \param [in] Subresource The subresource
* \param [in] MapType The map type
*/
void SetMapType(UINT Subresource, D3D11_MAP MapType) {
if (Subresource < m_mapInfo.size())
m_mapInfo[Subresource].mapType = MapType;
void NotifyMap(UINT Subresource, D3D11_MAP MapType) {
if (likely(Subresource < m_mapInfo.size())) {
m_mapInfo[Subresource].mapType = uint32_t(MapType);
if (m_mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_DYNAMIC)
CreateMappedBuffer(Subresource);
}
}
/**
* \brief Resets map info for a given subresource
*
* For dynamic mapping, this will also free the
* staging buffer.
* \param [in] Subresource The subresource
*/
void NotifyUnmap(UINT Subresource) {
if (likely(Subresource < m_mapInfo.size())) {
m_mapInfo[Subresource].mapType = UnmappedSubresource;
if (m_mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_DYNAMIC)
FreeMappedBuffer(Subresource);
if (Subresource < m_buffers.size())
m_buffers[Subresource].dirtyRegions.clear();
}
}
/**
* \brief The DXVK image
* \returns The DXVK image
@ -217,13 +268,13 @@ namespace dxvk {
* \param [in] Subresource Subresource to discard
* \returns Newly allocated mapped buffer slice
*/
DxvkBufferSliceHandle DiscardSlice(UINT Subresource) {
Rc<DxvkResourceAllocation> DiscardSlice(UINT Subresource) {
if (Subresource < m_buffers.size()) {
DxvkBufferSliceHandle slice = m_buffers[Subresource].buffer->allocSlice();
Rc<DxvkResourceAllocation> slice = m_buffers[Subresource].buffer->allocateStorage();
m_buffers[Subresource].slice = slice;
return slice;
} else {
return DxvkBufferSliceHandle();
return nullptr;
}
}
@ -233,10 +284,10 @@ namespace dxvk {
* \param [in] Subresource Subresource index to query
* \returns Currently mapped buffer slice
*/
DxvkBufferSliceHandle GetMappedSlice(UINT Subresource) const {
Rc<DxvkResourceAllocation> GetMappedSlice(UINT Subresource) const {
return Subresource < m_buffers.size()
? m_buffers[Subresource].slice
: DxvkBufferSliceHandle();
: nullptr;
}
/**
@ -259,17 +310,7 @@ namespace dxvk {
* \returns \c true if tracking is supported for this resource
*/
bool HasSequenceNumber() const {
if (m_mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_NONE)
return false;
// For buffer-mapped images we only need to track copies to
// and from that buffer, so we can safely ignore bind flags
if (m_mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER)
return m_desc.Usage != D3D11_USAGE_DEFAULT;
// Otherwise we can only do accurate tracking if the
// image cannot be used in the rendering pipeline.
return m_desc.BindFlags == 0;
return m_mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_STAGING;
}
/**
@ -301,6 +342,52 @@ namespace dxvk {
}
}
/**
* \brief Allocates new backing storage
* \returns New backing storage for the image
*/
Rc<DxvkResourceAllocation> AllocStorage() {
return m_image->allocateStorage();
}
/**
* \brief Discards backing storage
*
* Also updates the mapped pointer if the image is mapped.
* \returns New backing storage for the image
*/
Rc<DxvkResourceAllocation> DiscardStorage() {
auto storage = m_image->allocateStorage();
m_mapPtr = storage->mapPtr();
return storage;
}
/**
* \brief Queries map pointer of the raw image
*
* If the image is mapped directly, the returned pointer will
* point directly to the image, otherwise it will point to a
* buffer that contains image data.
* \param [in] Subresource Subresource index
* \param [in] Offset Offset derived from the subresource layout
*/
void* GetMapPtr(uint32_t Subresource, size_t Offset) const {
switch (m_mapMode) {
case D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT:
return reinterpret_cast<char*>(m_mapPtr) + Offset;
case D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER:
case D3D11_COMMON_TEXTURE_MAP_MODE_DYNAMIC:
case D3D11_COMMON_TEXTURE_MAP_MODE_STAGING:
return reinterpret_cast<char*>(m_buffers[Subresource].slice->mapPtr()) + Offset;
case D3D11_COMMON_TEXTURE_MAP_MODE_NONE:
return nullptr;
}
return nullptr;
}
/**
* \brief Adds a dirty region
*
@ -318,17 +405,6 @@ namespace dxvk {
m_buffers[Subresource].dirtyRegions.push_back(region);
}
/**
* \brief Clears dirty regions
*
* Removes all dirty regions from the given subresource.
* \param [in] Subresource Subresource index
*/
void ClearDirtyRegions(UINT Subresource) {
if (Subresource < m_buffers.size())
m_buffers[Subresource].dirtyRegions.clear();
}
/**
* \brief Counts dirty regions
*
@ -388,7 +464,13 @@ namespace dxvk {
*/
VkImageSubresource GetSubresourceFromIndex(
VkImageAspectFlags Aspect,
UINT Subresource) const;
UINT Subresource) const {
VkImageSubresource result;
result.aspectMask = Aspect;
result.mipLevel = Subresource % m_desc.MipLevels;
result.arrayLayer = Subresource / m_desc.MipLevels;
return result;
}
/**
* \brief Computes subresource layout for the given subresource
@ -435,6 +517,22 @@ 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 Sets debug name for texture
*
* Passes the given name to the backing image or buffer.
* \param [in] name Debug name
*/
void SetDebugName(const char* pName);
/**
* \brief Normalizes and validates texture description
*
@ -447,34 +545,54 @@ 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 {
Rc<DxvkBuffer> buffer;
DxvkBufferSliceHandle slice;
Rc<DxvkBuffer> buffer;
Rc<DxvkResourceAllocation> slice;
std::vector<D3D11_COMMON_TEXTURE_REGION> dirtyRegions;
};
struct MappedInfo {
D3D11_MAP mapType;
uint64_t seq;
D3D11_COMMON_TEXTURE_SUBRESOURCE_LAYOUT layout = { };
uint32_t mapType = UnmappedSubresource;
uint64_t seq = 0u;
};
ID3D11Resource* m_interface;
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;
Rc<DxvkImage> m_image;
std::vector<MappedBuffer> m_buffers;
std::vector<MappedInfo> m_mapInfo;
small_vector<MappedBuffer, 6> m_buffers;
small_vector<MappedInfo, 6> m_mapInfo;
void* m_mapPtr = nullptr;
void CreateMappedBuffer(
UINT Subresource);
MappedBuffer CreateMappedBuffer(
UINT MipLevel) const;
void FreeMappedBuffer(
UINT Subresource);
BOOL CheckImageSupport(
const DxvkImageCreateInfo* pImageInfo,
@ -484,21 +602,15 @@ namespace dxvk {
VkFormat Format,
VkFormatFeatureFlags2 Features) const;
VkImageUsageFlags EnableMetaCopyUsage(
VkFormat Format,
VkImageTiling Tiling) const;
VkImageUsageFlags EnableMetaPackUsage(
VkFormat Format,
UINT CpuAccess) const;
VkMemoryPropertyFlags GetMemoryFlags() const;
D3D11_COMMON_TEXTURE_MAP_MODE DetermineMapMode(
std::pair<D3D11_COMMON_TEXTURE_MAP_MODE, VkMemoryPropertyFlags> DetermineMapMode(
const DxvkImageCreateInfo* pImageInfo) const;
D3D11_COMMON_TEXTURE_SUBRESOURCE_LAYOUT DetermineSubresourceLayout(
const DxvkImageCreateInfo* pImageInfo,
const VkImageSubresource& subresource) const;
void ExportImageInfo();
static BOOL IsR32UavCompatibleFormat(
DXGI_FORMAT Format);
@ -636,7 +748,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();
@ -654,6 +767,8 @@ namespace dxvk {
void STDMETHODCALLTYPE GetDesc(
D3D11_TEXTURE1D_DESC *pDesc) final;
void STDMETHODCALLTYPE SetDebugName(const char* pName) final;
D3D11CommonTexture* GetCommonTexture() {
return &m_texture;
}
@ -682,6 +797,7 @@ namespace dxvk {
D3D11Texture2D(
D3D11Device* pDevice,
const D3D11_COMMON_TEXTURE_DESC* pDesc,
const D3D11_ON_12_RESOURCE_INFO* p11on12Info,
HANDLE hSharedHandle);
D3D11Texture2D(
@ -719,6 +835,8 @@ namespace dxvk {
void STDMETHODCALLTYPE GetDesc1(
D3D11_TEXTURE2D_DESC1* pDesc) final;
void STDMETHODCALLTYPE SetDebugName(const char* pName) final;
D3D11CommonTexture* GetCommonTexture() {
return &m_texture;
}
@ -747,7 +865,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();
@ -768,6 +887,8 @@ namespace dxvk {
void STDMETHODCALLTYPE GetDesc1(
D3D11_TEXTURE3D_DESC1* pDesc) final;
void STDMETHODCALLTYPE SetDebugName(const char* pName) final;
D3D11CommonTexture* GetCommonTexture() {
return &m_texture;
}

View file

@ -52,15 +52,15 @@ namespace dxvk {
* \returns Corresponding Vulkan shader stage
*/
constexpr VkShaderStageFlagBits GetShaderStage(DxbcProgramType ProgramType) {
switch (ProgramType) {
case DxbcProgramType::VertexShader: return VK_SHADER_STAGE_VERTEX_BIT;
case DxbcProgramType::HullShader: return VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
case DxbcProgramType::DomainShader: return VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
case DxbcProgramType::GeometryShader: return VK_SHADER_STAGE_GEOMETRY_BIT;
case DxbcProgramType::PixelShader: return VK_SHADER_STAGE_FRAGMENT_BIT;
case DxbcProgramType::ComputeShader: return VK_SHADER_STAGE_COMPUTE_BIT;
default: return VkShaderStageFlagBits(0);
}
constexpr uint64_t lut
= (uint64_t(VK_SHADER_STAGE_VERTEX_BIT) << (8u * uint32_t(DxbcProgramType::VertexShader)))
| (uint64_t(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) << (8u * uint32_t(DxbcProgramType::HullShader)))
| (uint64_t(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) << (8u * uint32_t(DxbcProgramType::DomainShader)))
| (uint64_t(VK_SHADER_STAGE_GEOMETRY_BIT) << (8u * uint32_t(DxbcProgramType::GeometryShader)))
| (uint64_t(VK_SHADER_STAGE_FRAGMENT_BIT) << (8u * uint32_t(DxbcProgramType::PixelShader)))
| (uint64_t(VK_SHADER_STAGE_COMPUTE_BIT) << (8u * uint32_t(DxbcProgramType::ComputeShader)));
return VkShaderStageFlagBits((lut >> (8u * uint32_t(ProgramType))) & 0xff);
}
}
}

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;
}
@ -143,35 +173,23 @@ namespace dxvk {
Rc<DxvkImage> dxvkImage = GetCommonTexture(pResource)->GetImage();
if (!(dxvkImage->info().usage & VK_IMAGE_USAGE_SAMPLED_BIT)) {
DxvkImageCreateInfo info = dxvkImage->info();
info.flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | VK_IMAGE_CREATE_EXTENDED_USAGE_BIT;
info.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
info.stages = VK_PIPELINE_STAGE_TRANSFER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
info.access = VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT;
info.tiling = VK_IMAGE_TILING_OPTIMAL;
info.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
info.shared = VK_FALSE;
dxvkImage = m_copy = pDevice->GetDXVKDevice()->createImage(info, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
}
DXGI_VK_FORMAT_INFO formatInfo = pDevice->LookupFormat(resourceDesc.Format, DXGI_VK_FORMAT_MODE_COLOR);
DXGI_VK_FORMAT_FAMILY formatFamily = pDevice->LookupFamily(resourceDesc.Format, DXGI_VK_FORMAT_MODE_COLOR);
VkImageAspectFlags aspectMask = lookupFormatInfo(formatInfo.Format)->aspectMask;
DxvkImageViewCreateInfo viewInfo;
viewInfo.format = formatInfo.Format;
viewInfo.swizzle = formatInfo.Swizzle;
viewInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
DxvkImageViewKey viewInfo;
viewInfo.format = formatInfo.Format;
viewInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
viewInfo.packedSwizzle = DxvkImageViewKey::packSwizzle(formatInfo.Swizzle);
switch (m_desc.ViewDimension) {
case D3D11_VPIV_DIMENSION_TEXTURE2D:
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.minLevel = m_desc.Texture2D.MipSlice;
viewInfo.numLevels = 1;
viewInfo.minLayer = 0;
viewInfo.numLayers = 1;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.mipIndex = m_desc.Texture2D.MipSlice;
viewInfo.mipCount = 1;
viewInfo.layerIndex = m_desc.Texture2D.ArraySlice;
viewInfo.layerCount = 1;
break;
case D3D11_VPIV_DIMENSION_UNKNOWN:
@ -179,17 +197,17 @@ namespace dxvk {
}
m_subresources.aspectMask = aspectMask;
m_subresources.baseArrayLayer = viewInfo.minLayer;
m_subresources.layerCount = viewInfo.numLayers;
m_subresources.mipLevel = viewInfo.minLevel;
m_subresources.baseArrayLayer = viewInfo.layerIndex;
m_subresources.layerCount = viewInfo.layerCount;
m_subresources.mipLevel = viewInfo.mipIndex;
for (uint32_t i = 0; aspectMask && i < m_views.size(); i++) {
viewInfo.aspect = vk::getNextAspect(aspectMask);
viewInfo.aspects = vk::getNextAspect(aspectMask);
if (viewInfo.aspect != VK_IMAGE_ASPECT_COLOR_BIT)
if (viewInfo.aspects != VK_IMAGE_ASPECT_COLOR_BIT)
viewInfo.format = formatFamily.Formats[i];
m_views[i] = pDevice->GetDXVKDevice()->createImageView(dxvkImage, viewInfo);
m_views[i] = dxvkImage->createView(viewInfo);
}
m_isYCbCr = IsYCbCrFormat(resourceDesc.Format);
@ -223,8 +241,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;
}
@ -254,35 +275,34 @@ namespace dxvk {
DXGI_VK_FORMAT_INFO formatInfo = pDevice->LookupFormat(
resourceDesc.Format, DXGI_VK_FORMAT_MODE_COLOR);
DxvkImageViewCreateInfo viewInfo;
viewInfo.format = formatInfo.Format;
viewInfo.aspect = lookupFormatInfo(viewInfo.format)->aspectMask;
viewInfo.swizzle = formatInfo.Swizzle;
viewInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
DxvkImageViewKey viewInfo;
viewInfo.format = formatInfo.Format;
viewInfo.aspects = lookupFormatInfo(viewInfo.format)->aspectMask;
viewInfo.packedSwizzle = DxvkImageViewKey::packSwizzle(formatInfo.Swizzle);
viewInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
switch (m_desc.ViewDimension) {
case D3D11_VPOV_DIMENSION_TEXTURE2D:
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.minLevel = m_desc.Texture2D.MipSlice;
viewInfo.numLevels = 1;
viewInfo.minLayer = 0;
viewInfo.numLayers = 1;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.mipIndex = m_desc.Texture2D.MipSlice;
viewInfo.mipCount = 1;
viewInfo.layerIndex = 0;
viewInfo.layerCount = 1;
break;
case D3D11_VPOV_DIMENSION_TEXTURE2DARRAY:
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
viewInfo.minLevel = m_desc.Texture2DArray.MipSlice;
viewInfo.numLevels = 1;
viewInfo.minLayer = m_desc.Texture2DArray.FirstArraySlice;
viewInfo.numLayers = m_desc.Texture2DArray.ArraySize;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
viewInfo.mipIndex = m_desc.Texture2DArray.MipSlice;
viewInfo.mipCount = 1;
viewInfo.layerIndex = m_desc.Texture2DArray.FirstArraySlice;
viewInfo.layerCount = m_desc.Texture2DArray.ArraySize;
break;
case D3D11_VPOV_DIMENSION_UNKNOWN:
throw DxvkError("Invalid view dimension");
}
m_view = pDevice->GetDXVKDevice()->createImageView(
GetCommonTexture(pResource)->GetImage(), viewInfo);
m_view = GetCommonTexture(pResource)->GetImage()->createView(viewInfo);
}
@ -302,8 +322,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 +347,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_TRUE },
{ 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 +578,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));
}
@ -1036,6 +1013,10 @@ namespace dxvk {
const D3D11_VIDEO_PROCESSOR_STREAM* pStreams) {
D3D10DeviceLock lock = m_ctx->LockContext();
m_ctx->EmitCs([] (DxvkContext* ctx) {
ctx->beginDebugLabel(vk::makeLabel(0x59eaff, "Video blit"));
});
auto videoProcessor = static_cast<D3D11VideoProcessor*>(pVideoProcessor);
bool hasStreamsEnabled = false;
@ -1048,7 +1029,9 @@ namespace dxvk {
continue;
if (!hasStreamsEnabled) {
m_ctx->ResetDirtyTracking();
m_ctx->ResetCommandListState();
BindOutputView(pOutputView);
hasStreamsEnabled = true;
}
@ -1058,9 +1041,14 @@ namespace dxvk {
if (hasStreamsEnabled) {
UnbindResources();
m_ctx->RestoreCommandListState();
}
m_ctx->EmitCs([] (DxvkContext* ctx) {
ctx->endDebugLabel();
});
return S_OK;
}
@ -1195,14 +1183,18 @@ namespace dxvk {
auto dxvkView = static_cast<D3D11VideoProcessorOutputView*>(pOutputView)->GetView();
m_ctx->EmitCs([this, cView = dxvkView] (DxvkContext* ctx) {
DxvkImageUsageInfo usage = { };
usage.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
usage.stages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
usage.access = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
ctx->ensureImageCompatibility(cView->image(), usage);
DxvkRenderTargets rt;
rt.color[0].view = cView;
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->bindUniformBuffer(VK_SHADER_STAGE_FRAGMENT_BIT, 0, DxvkBufferSlice(m_ubo));
DxvkInputAssemblyState iaState;
iaState.primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
@ -1219,6 +1211,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");
@ -1230,30 +1224,19 @@ namespace dxvk {
auto view = static_cast<D3D11VideoProcessorInputView*>(pStream->pInputSurface);
if (view->NeedsCopy()) {
m_ctx->EmitCs([
cDstImage = view->GetShadowCopy(),
cSrcImage = view->GetImage(),
cSrcLayers = view->GetImageSubresources()
] (DxvkContext* ctx) {
VkImageSubresourceLayers cDstLayers;
cDstLayers.aspectMask = cSrcLayers.aspectMask;
cDstLayers.baseArrayLayer = 0;
cDstLayers.layerCount = cSrcLayers.layerCount;
cDstLayers.mipLevel = cSrcLayers.mipLevel;
ctx->copyImage(
cDstImage, cDstLayers, VkOffset3D(),
cSrcImage, cSrcLayers, VkOffset3D(),
cDstImage->info().extent);
});
}
m_ctx->EmitCs([this,
cStreamState = *pStreamState,
cImage = view->GetImage(),
cViews = view->GetViews(),
cIsYCbCr = view->IsYCbCr()
] (DxvkContext* ctx) {
DxvkImageUsageInfo usage = { };
usage.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
usage.stages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
usage.access = VK_ACCESS_SHADER_READ_BIT;
ctx->ensureImageCompatibility(cImage, usage);
VkViewport viewport;
viewport.x = 0.0f;
viewport.y = 0.0f;
@ -1273,12 +1256,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;
@ -1291,26 +1290,78 @@ namespace dxvk {
uboData.yMax = 0.9215686f;
}
DxvkBufferSliceHandle uboSlice = m_ubo->allocSlice();
memcpy(uboSlice.mapPtr, &uboData, sizeof(uboData));
Rc<DxvkResourceAllocation> uboSlice = m_ubo->allocateStorage();
memcpy(uboSlice->mapPtr(), &uboData, sizeof(uboData));
ctx->invalidateBuffer(m_ubo, uboSlice);
ctx->invalidateBuffer(m_ubo, std::move(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);
VkDrawIndirectCommand draw = { };
draw.vertexCount = 3u;
draw.instanceCount = 1u;
ctx->bindResourceSampler(VK_SHADER_STAGE_FRAGMENT_BIT, 1, nullptr);
ctx->draw(1, &draw);
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;
bufferInfo.debugName = "Video blit parameters";
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);

View file

@ -138,10 +138,6 @@ namespace dxvk {
return m_isYCbCr;
}
bool NeedsCopy() const {
return m_copy != nullptr;
}
Rc<DxvkImage> GetImage() const {
return GetCommonTexture(m_resource.ptr())->GetImage();
}
@ -150,10 +146,6 @@ namespace dxvk {
return m_subresources;
}
Rc<DxvkImage> GetShadowCopy() const {
return m_copy;
}
std::array<Rc<DxvkImageView>, 2> GetViews() const {
return m_views;
}
@ -163,7 +155,6 @@ namespace dxvk {
Com<ID3D11Resource> m_resource;
D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC m_desc;
VkImageSubresourceLayers m_subresources;
Rc<DxvkImage> m_copy;
std::array<Rc<DxvkImageView>, 2> m_views;
bool m_isYCbCr = false;
@ -584,19 +575,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 +602,12 @@ namespace dxvk {
const D3D11VideoProcessorStreamState* pStreamState,
const D3D11_VIDEO_PROCESSOR_STREAM* pStream);
void CreateUniformBuffer();
void CreateShaders();
void CreateResources();
void UnbindResources();
};

View file

@ -55,7 +55,7 @@ namespace dxvk {
* \param [in] b Second view to check
* \returns \c true if the views overlap
*/
inline bool CheckViewOverlap(const D3D11_VK_VIEW_INFO& a, const D3D11_VK_VIEW_INFO b) {
inline bool CheckViewOverlap(const D3D11_VK_VIEW_INFO& a, const D3D11_VK_VIEW_INFO& b) {
if (likely(a.pResource != b.pResource))
return false;
@ -78,4 +78,4 @@ namespace dxvk {
return a && b && CheckViewOverlap(a->GetViewInfo(), b->GetViewInfo());
}
}
}

View file

@ -17,58 +17,58 @@ namespace dxvk {
D3D11_COMMON_RESOURCE_DESC resourceDesc;
GetCommonResourceDesc(pResource, &resourceDesc);
DxvkImageViewCreateInfo viewInfo;
DxvkImageViewKey viewInfo;
viewInfo.format = pDevice->LookupFormat(pDesc->Format, DXGI_VK_FORMAT_MODE_DEPTH).Format;
viewInfo.aspect = lookupFormatInfo(viewInfo.format)->aspectMask;
viewInfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
viewInfo.aspects = lookupFormatInfo(viewInfo.format)->aspectMask;
viewInfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
switch (pDesc->ViewDimension) {
case D3D11_DSV_DIMENSION_TEXTURE1D:
viewInfo.type = VK_IMAGE_VIEW_TYPE_1D;
viewInfo.minLevel = pDesc->Texture1D.MipSlice;
viewInfo.numLevels = 1;
viewInfo.minLayer = 0;
viewInfo.numLayers = 1;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_1D;
viewInfo.mipIndex = pDesc->Texture1D.MipSlice;
viewInfo.mipCount = 1;
viewInfo.layerIndex = 0;
viewInfo.layerCount = 1;
break;
case D3D11_DSV_DIMENSION_TEXTURE1DARRAY:
viewInfo.type = VK_IMAGE_VIEW_TYPE_1D_ARRAY;
viewInfo.minLevel = pDesc->Texture1DArray.MipSlice;
viewInfo.numLevels = 1;
viewInfo.minLayer = pDesc->Texture1DArray.FirstArraySlice;
viewInfo.numLayers = pDesc->Texture1DArray.ArraySize;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_1D_ARRAY;
viewInfo.mipIndex = pDesc->Texture1DArray.MipSlice;
viewInfo.mipCount = 1;
viewInfo.layerIndex = pDesc->Texture1DArray.FirstArraySlice;
viewInfo.layerCount = pDesc->Texture1DArray.ArraySize;
break;
case D3D11_DSV_DIMENSION_TEXTURE2D:
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.minLevel = pDesc->Texture2D.MipSlice;
viewInfo.numLevels = 1;
viewInfo.minLayer = 0;
viewInfo.numLayers = 1;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.mipIndex = pDesc->Texture2D.MipSlice;
viewInfo.mipCount = 1;
viewInfo.layerIndex = 0;
viewInfo.layerCount = 1;
break;
case D3D11_DSV_DIMENSION_TEXTURE2DARRAY:
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
viewInfo.minLevel = pDesc->Texture2DArray.MipSlice;
viewInfo.numLevels = 1;
viewInfo.minLayer = pDesc->Texture2DArray.FirstArraySlice;
viewInfo.numLayers = pDesc->Texture2DArray.ArraySize;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
viewInfo.mipIndex = pDesc->Texture2DArray.MipSlice;
viewInfo.mipCount = 1;
viewInfo.layerIndex = pDesc->Texture2DArray.FirstArraySlice;
viewInfo.layerCount = pDesc->Texture2DArray.ArraySize;
break;
case D3D11_DSV_DIMENSION_TEXTURE2DMS:
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.minLevel = 0;
viewInfo.numLevels = 1;
viewInfo.minLayer = 0;
viewInfo.numLayers = 1;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.mipIndex = 0;
viewInfo.mipCount = 1;
viewInfo.layerIndex = 0;
viewInfo.layerCount = 1;
break;
case D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY:
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
viewInfo.minLevel = 0;
viewInfo.numLevels = 1;
viewInfo.minLayer = pDesc->Texture2DMSArray.FirstArraySlice;
viewInfo.numLayers = pDesc->Texture2DMSArray.ArraySize;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
viewInfo.mipIndex = 0;
viewInfo.mipCount = 1;
viewInfo.layerIndex = pDesc->Texture2DMSArray.FirstArraySlice;
viewInfo.layerCount = pDesc->Texture2DMSArray.ArraySize;
break;
default:
@ -77,20 +77,22 @@ namespace dxvk {
// Normalize view type so that we won't accidentally
// bind 2D array views and 2D views at the same time
if (viewInfo.numLayers == 1) {
if (viewInfo.type == VK_IMAGE_VIEW_TYPE_1D_ARRAY) viewInfo.type = VK_IMAGE_VIEW_TYPE_1D;
if (viewInfo.type == VK_IMAGE_VIEW_TYPE_2D_ARRAY) viewInfo.type = VK_IMAGE_VIEW_TYPE_2D;
if (viewInfo.layerCount == 1) {
if (viewInfo.viewType == VK_IMAGE_VIEW_TYPE_1D_ARRAY)
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_1D;
if (viewInfo.viewType == VK_IMAGE_VIEW_TYPE_2D_ARRAY)
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
}
// Populate view info struct
m_info.pResource = pResource;
m_info.Dimension = resourceDesc.Dim;
m_info.BindFlags = resourceDesc.BindFlags;
m_info.Image.Aspects = viewInfo.aspect;
m_info.Image.MinLevel = viewInfo.minLevel;
m_info.Image.MinLayer = viewInfo.minLayer;
m_info.Image.NumLevels = viewInfo.numLevels;
m_info.Image.NumLayers = viewInfo.numLayers;
m_info.Image.Aspects = viewInfo.aspects;
m_info.Image.MinLevel = viewInfo.mipIndex;
m_info.Image.MinLayer = viewInfo.layerIndex;
m_info.Image.NumLevels = viewInfo.mipCount;
m_info.Image.NumLayers = viewInfo.layerCount;
if (m_desc.Flags & D3D11_DSV_READ_ONLY_DEPTH)
m_info.Image.Aspects &= ~VK_IMAGE_ASPECT_DEPTH_BIT;
@ -99,13 +101,15 @@ namespace dxvk {
m_info.Image.Aspects &= ~VK_IMAGE_ASPECT_STENCIL_BIT;
// Create the underlying image view object
m_view = pDevice->GetDXVKDevice()->createImageView(
GetCommonTexture(pResource)->GetImage(), viewInfo);
m_view = GetCommonTexture(pResource)->GetImage()->createView(viewInfo);
}
D3D11DepthStencilView::~D3D11DepthStencilView() {
ResourceReleasePrivate(m_resource);
m_resource = nullptr;
m_view = nullptr;
}
@ -126,12 +130,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

@ -50,24 +50,20 @@ namespace dxvk {
}
VkImageLayout GetRenderLayout() const {
if (m_view->imageInfo().tiling == VK_IMAGE_TILING_OPTIMAL) {
switch (m_desc.Flags & (D3D11_DSV_READ_ONLY_DEPTH | D3D11_DSV_READ_ONLY_STENCIL)) {
default: // case 0
return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
case D3D11_DSV_READ_ONLY_DEPTH:
return VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL_KHR;
case D3D11_DSV_READ_ONLY_STENCIL:
return VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL_KHR;
case D3D11_DSV_READ_ONLY_DEPTH | D3D11_DSV_READ_ONLY_STENCIL:
return VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
}
} else {
return VK_IMAGE_LAYOUT_GENERAL;
switch (m_desc.Flags & (D3D11_DSV_READ_ONLY_DEPTH | D3D11_DSV_READ_ONLY_STENCIL)) {
default: // case 0
return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
case D3D11_DSV_READ_ONLY_DEPTH:
return VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL_KHR;
case D3D11_DSV_READ_ONLY_STENCIL:
return VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL_KHR;
case D3D11_DSV_READ_ONLY_DEPTH | D3D11_DSV_READ_ONLY_STENCIL:
return VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
}
}
UINT GetSampleCount() const {
return UINT(m_view->imageInfo().sampleCount);
return UINT(m_view->image()->info().sampleCount);
}
VkImageAspectFlags GetWritableAspectMask() const {
@ -77,6 +73,10 @@ namespace dxvk {
return mask;
}
DXGI_FORMAT GetViewFormat() const {
return m_desc.Format;
}
D3D10DepthStencilView* GetD3D10Iface() {
return &m_d3d10;
}

View file

@ -22,67 +22,67 @@ namespace dxvk {
DXGI_VK_FORMAT_INFO formatInfo = pDevice->LookupFormat(
pDesc->Format, DXGI_VK_FORMAT_MODE_COLOR);
DxvkImageViewCreateInfo viewInfo;
viewInfo.format = formatInfo.Format;
viewInfo.aspect = lookupFormatInfo(viewInfo.format)->aspectMask;
viewInfo.swizzle = formatInfo.Swizzle;
viewInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
DxvkImageViewKey viewInfo;
viewInfo.format = formatInfo.Format;
viewInfo.aspects = lookupFormatInfo(viewInfo.format)->aspectMask;
viewInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
viewInfo.packedSwizzle = DxvkImageViewKey::packSwizzle(formatInfo.Swizzle);
switch (pDesc->ViewDimension) {
case D3D11_RTV_DIMENSION_TEXTURE1D:
viewInfo.type = VK_IMAGE_VIEW_TYPE_1D;
viewInfo.minLevel = pDesc->Texture1D.MipSlice;
viewInfo.numLevels = 1;
viewInfo.minLayer = 0;
viewInfo.numLayers = 1;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_1D;
viewInfo.mipIndex = pDesc->Texture1D.MipSlice;
viewInfo.mipCount = 1;
viewInfo.layerIndex = 0;
viewInfo.layerCount = 1;
break;
case D3D11_RTV_DIMENSION_TEXTURE1DARRAY:
viewInfo.type = VK_IMAGE_VIEW_TYPE_1D_ARRAY;
viewInfo.minLevel = pDesc->Texture1DArray.MipSlice;
viewInfo.numLevels = 1;
viewInfo.minLayer = pDesc->Texture1DArray.FirstArraySlice;
viewInfo.numLayers = pDesc->Texture1DArray.ArraySize;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_1D_ARRAY;
viewInfo.mipIndex = pDesc->Texture1DArray.MipSlice;
viewInfo.mipCount = 1;
viewInfo.layerIndex = pDesc->Texture1DArray.FirstArraySlice;
viewInfo.layerCount = pDesc->Texture1DArray.ArraySize;
break;
case D3D11_RTV_DIMENSION_TEXTURE2D:
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.minLevel = pDesc->Texture2D.MipSlice;
viewInfo.numLevels = 1;
viewInfo.minLayer = 0;
viewInfo.numLayers = 1;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.mipIndex = pDesc->Texture2D.MipSlice;
viewInfo.mipCount = 1;
viewInfo.layerIndex = 0;
viewInfo.layerCount = 1;
break;
case D3D11_RTV_DIMENSION_TEXTURE2DARRAY:
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
viewInfo.minLevel = pDesc->Texture2DArray.MipSlice;
viewInfo.numLevels = 1;
viewInfo.minLayer = pDesc->Texture2DArray.FirstArraySlice;
viewInfo.numLayers = pDesc->Texture2DArray.ArraySize;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
viewInfo.mipIndex = pDesc->Texture2DArray.MipSlice;
viewInfo.mipCount = 1;
viewInfo.layerIndex = pDesc->Texture2DArray.FirstArraySlice;
viewInfo.layerCount = pDesc->Texture2DArray.ArraySize;
break;
case D3D11_RTV_DIMENSION_TEXTURE2DMS:
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.minLevel = 0;
viewInfo.numLevels = 1;
viewInfo.minLayer = 0;
viewInfo.numLayers = 1;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.mipIndex = 0;
viewInfo.mipCount = 1;
viewInfo.layerIndex = 0;
viewInfo.layerCount = 1;
break;
case D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY:
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
viewInfo.minLevel = 0;
viewInfo.numLevels = 1;
viewInfo.minLayer = pDesc->Texture2DMSArray.FirstArraySlice;
viewInfo.numLayers = pDesc->Texture2DMSArray.ArraySize;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
viewInfo.mipIndex = 0;
viewInfo.mipCount = 1;
viewInfo.layerIndex = pDesc->Texture2DMSArray.FirstArraySlice;
viewInfo.layerCount = pDesc->Texture2DMSArray.ArraySize;
break;
case D3D11_RTV_DIMENSION_TEXTURE3D:
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
viewInfo.minLevel = pDesc->Texture3D.MipSlice;
viewInfo.numLevels = 1;
viewInfo.minLayer = pDesc->Texture3D.FirstWSlice;
viewInfo.numLayers = pDesc->Texture3D.WSize;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
viewInfo.mipIndex = pDesc->Texture3D.MipSlice;
viewInfo.mipCount = 1;
viewInfo.layerIndex = pDesc->Texture3D.FirstWSlice;
viewInfo.layerCount = pDesc->Texture3D.WSize;
break;
default:
@ -90,32 +90,37 @@ namespace dxvk {
}
if (texture->GetPlaneCount() > 1)
viewInfo.aspect = vk::getPlaneAspect(GetPlaneSlice(pDesc));
viewInfo.aspects = vk::getPlaneAspect(GetPlaneSlice(pDesc));
// Normalize view type so that we won't accidentally
// bind 2D array views and 2D views at the same time
if (viewInfo.numLayers == 1) {
if (viewInfo.type == VK_IMAGE_VIEW_TYPE_1D_ARRAY) viewInfo.type = VK_IMAGE_VIEW_TYPE_1D;
if (viewInfo.type == VK_IMAGE_VIEW_TYPE_2D_ARRAY) viewInfo.type = VK_IMAGE_VIEW_TYPE_2D;
if (viewInfo.layerCount == 1) {
if (viewInfo.viewType == VK_IMAGE_VIEW_TYPE_1D_ARRAY)
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_1D;
if (viewInfo.viewType == VK_IMAGE_VIEW_TYPE_2D_ARRAY)
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
}
// Populate view info struct
m_info.pResource = pResource;
m_info.Dimension = resourceDesc.Dim;
m_info.BindFlags = resourceDesc.BindFlags;
m_info.Image.Aspects = viewInfo.aspect;
m_info.Image.MinLevel = viewInfo.minLevel;
m_info.Image.MinLayer = viewInfo.minLayer;
m_info.Image.NumLevels = viewInfo.numLevels;
m_info.Image.NumLayers = viewInfo.numLayers;
m_info.Image.Aspects = viewInfo.aspects;
m_info.Image.MinLevel = viewInfo.mipIndex;
m_info.Image.MinLayer = viewInfo.layerIndex;
m_info.Image.NumLevels = viewInfo.mipCount;
m_info.Image.NumLayers = viewInfo.layerCount;
// Create the underlying image view object
m_view = pDevice->GetDXVKDevice()->createImageView(texture->GetImage(), viewInfo);
m_view = texture->GetImage()->createView(viewInfo);
}
D3D11RenderTargetView::~D3D11RenderTargetView() {
ResourceReleasePrivate(m_resource);
m_resource = nullptr;
m_view = nullptr;
}
@ -137,12 +142,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

@ -52,13 +52,11 @@ namespace dxvk {
}
VkImageLayout GetRenderLayout() const {
return m_view->imageInfo().tiling == VK_IMAGE_TILING_OPTIMAL
? VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
: VK_IMAGE_LAYOUT_GENERAL;
return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
}
UINT GetSampleCount() const {
return UINT(m_view->imageInfo().sampleCount);
return UINT(m_view->image()->info().sampleCount);
}
D3D10RenderTargetView* GetD3D10Iface() {

View file

@ -42,123 +42,123 @@ namespace dxvk {
}
// Fill in buffer view info
DxvkBufferViewCreateInfo viewInfo;
DxvkBufferViewKey viewInfo;
viewInfo.usage = VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT;
if (bufInfo.Flags & D3D11_BUFFEREX_SRV_FLAG_RAW) {
// Raw buffer view. We'll represent this as a
// uniform texel buffer with UINT32 elements.
viewInfo.format = VK_FORMAT_R32_UINT;
viewInfo.rangeOffset = sizeof(uint32_t) * bufInfo.FirstElement;
viewInfo.rangeLength = sizeof(uint32_t) * bufInfo.NumElements;
viewInfo.offset = sizeof(uint32_t) * bufInfo.FirstElement;
viewInfo.size = sizeof(uint32_t) * bufInfo.NumElements;
} else if (pDesc->Format == DXGI_FORMAT_UNKNOWN) {
// Structured buffer view
viewInfo.format = VK_FORMAT_R32_UINT;
viewInfo.rangeOffset = buffer->Desc()->StructureByteStride * bufInfo.FirstElement;
viewInfo.rangeLength = buffer->Desc()->StructureByteStride * bufInfo.NumElements;
viewInfo.offset = buffer->Desc()->StructureByteStride * bufInfo.FirstElement;
viewInfo.size = buffer->Desc()->StructureByteStride * bufInfo.NumElements;
} else {
viewInfo.format = pDevice->LookupFormat(pDesc->Format, DXGI_VK_FORMAT_MODE_COLOR).Format;
const DxvkFormatInfo* formatInfo = lookupFormatInfo(viewInfo.format);
viewInfo.rangeOffset = formatInfo->elementSize * bufInfo.FirstElement;
viewInfo.rangeLength = formatInfo->elementSize * bufInfo.NumElements;
viewInfo.offset = formatInfo->elementSize * bufInfo.FirstElement;
viewInfo.size = formatInfo->elementSize * bufInfo.NumElements;
}
// Populate view info struct
m_info.Buffer.Offset = viewInfo.rangeOffset;
m_info.Buffer.Length = viewInfo.rangeLength;
m_info.Buffer.Offset = viewInfo.offset;
m_info.Buffer.Length = viewInfo.size;
// Create underlying buffer view object
m_bufferView = pDevice->GetDXVKDevice()->createBufferView(
buffer->GetBuffer(), viewInfo);
m_bufferView = buffer->GetBuffer()->createView(viewInfo);
} else {
auto texture = GetCommonTexture(pResource);
auto formatInfo = pDevice->LookupFormat(pDesc->Format, texture->GetFormatMode());
DxvkImageViewCreateInfo viewInfo;
viewInfo.format = formatInfo.Format;
viewInfo.aspect = formatInfo.Aspect;
viewInfo.swizzle = formatInfo.Swizzle;
viewInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
DxvkImageViewKey viewInfo;
viewInfo.format = formatInfo.Format;
viewInfo.aspects = formatInfo.Aspect;
viewInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
viewInfo.packedSwizzle = DxvkImageViewKey::packSwizzle(formatInfo.Swizzle);
// Shaders expect the stencil value in the G component
if (viewInfo.aspect == VK_IMAGE_ASPECT_STENCIL_BIT) {
viewInfo.swizzle = VkComponentMapping {
if (viewInfo.aspects == VK_IMAGE_ASPECT_STENCIL_BIT) {
viewInfo.packedSwizzle = DxvkImageViewKey::packSwizzle({
VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_R,
VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_ZERO };
VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_ZERO });
}
switch (pDesc->ViewDimension) {
case D3D11_SRV_DIMENSION_TEXTURE1D:
viewInfo.type = VK_IMAGE_VIEW_TYPE_1D;
viewInfo.minLevel = pDesc->Texture1D.MostDetailedMip;
viewInfo.numLevels = pDesc->Texture1D.MipLevels;
viewInfo.minLayer = 0;
viewInfo.numLayers = 1;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_1D;
viewInfo.mipIndex = pDesc->Texture1D.MostDetailedMip;
viewInfo.mipCount = pDesc->Texture1D.MipLevels;
viewInfo.layerIndex = 0;
viewInfo.layerCount = 1;
break;
case D3D11_SRV_DIMENSION_TEXTURE1DARRAY:
viewInfo.type = VK_IMAGE_VIEW_TYPE_1D_ARRAY;
viewInfo.minLevel = pDesc->Texture1DArray.MostDetailedMip;
viewInfo.numLevels = pDesc->Texture1DArray.MipLevels;
viewInfo.minLayer = pDesc->Texture1DArray.FirstArraySlice;
viewInfo.numLayers = pDesc->Texture1DArray.ArraySize;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_1D_ARRAY;
viewInfo.mipIndex = pDesc->Texture1DArray.MostDetailedMip;
viewInfo.mipCount = pDesc->Texture1DArray.MipLevels;
viewInfo.layerIndex = pDesc->Texture1DArray.FirstArraySlice;
viewInfo.layerCount = pDesc->Texture1DArray.ArraySize;
break;
case D3D11_SRV_DIMENSION_TEXTURE2D:
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.minLevel = pDesc->Texture2D.MostDetailedMip;
viewInfo.numLevels = pDesc->Texture2D.MipLevels;
viewInfo.minLayer = 0;
viewInfo.numLayers = 1;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.mipIndex = pDesc->Texture2D.MostDetailedMip;
viewInfo.mipCount = pDesc->Texture2D.MipLevels;
viewInfo.layerIndex = 0;
viewInfo.layerCount = 1;
break;
case D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
viewInfo.minLevel = pDesc->Texture2DArray.MostDetailedMip;
viewInfo.numLevels = pDesc->Texture2DArray.MipLevels;
viewInfo.minLayer = pDesc->Texture2DArray.FirstArraySlice;
viewInfo.numLayers = pDesc->Texture2DArray.ArraySize;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
viewInfo.mipIndex = pDesc->Texture2DArray.MostDetailedMip;
viewInfo.mipCount = pDesc->Texture2DArray.MipLevels;
viewInfo.layerIndex = pDesc->Texture2DArray.FirstArraySlice;
viewInfo.layerCount = pDesc->Texture2DArray.ArraySize;
break;
case D3D11_SRV_DIMENSION_TEXTURE2DMS:
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.minLevel = 0;
viewInfo.numLevels = 1;
viewInfo.minLayer = 0;
viewInfo.numLayers = 1;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.mipIndex = 0;
viewInfo.mipCount = 1;
viewInfo.layerIndex = 0;
viewInfo.layerCount = 1;
break;
case D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY:
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
viewInfo.minLevel = 0;
viewInfo.numLevels = 1;
viewInfo.minLayer = pDesc->Texture2DMSArray.FirstArraySlice;
viewInfo.numLayers = pDesc->Texture2DMSArray.ArraySize;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
viewInfo.mipIndex = 0;
viewInfo.mipCount = 1;
viewInfo.layerIndex = pDesc->Texture2DMSArray.FirstArraySlice;
viewInfo.layerCount = pDesc->Texture2DMSArray.ArraySize;
break;
case D3D11_SRV_DIMENSION_TEXTURE3D:
viewInfo.type = VK_IMAGE_VIEW_TYPE_3D;
viewInfo.minLevel = pDesc->Texture3D.MostDetailedMip;
viewInfo.numLevels = pDesc->Texture3D.MipLevels;
viewInfo.minLayer = 0;
viewInfo.numLayers = 1;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_3D;
viewInfo.mipIndex = pDesc->Texture3D.MostDetailedMip;
viewInfo.mipCount = pDesc->Texture3D.MipLevels;
viewInfo.layerIndex = 0;
viewInfo.layerCount = 1;
break;
case D3D11_SRV_DIMENSION_TEXTURECUBE: {
const bool cubeArraysEnabled = pDevice->GetDXVKDevice()->features().core.features.imageCubeArray;
viewInfo.type = cubeArraysEnabled ? VK_IMAGE_VIEW_TYPE_CUBE_ARRAY : VK_IMAGE_VIEW_TYPE_CUBE;
viewInfo.minLevel = pDesc->TextureCube.MostDetailedMip;
viewInfo.numLevels = pDesc->TextureCube.MipLevels;
viewInfo.minLayer = 0;
viewInfo.numLayers = 6;
viewInfo.viewType = cubeArraysEnabled ? VK_IMAGE_VIEW_TYPE_CUBE_ARRAY : VK_IMAGE_VIEW_TYPE_CUBE;
viewInfo.mipIndex = pDesc->TextureCube.MostDetailedMip;
viewInfo.mipCount = pDesc->TextureCube.MipLevels;
viewInfo.layerIndex = 0;
viewInfo.layerCount = 6;
} break;
case D3D11_SRV_DIMENSION_TEXTURECUBEARRAY:
viewInfo.type = VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
viewInfo.minLevel = pDesc->TextureCubeArray.MostDetailedMip;
viewInfo.numLevels = pDesc->TextureCubeArray.MipLevels;
viewInfo.minLayer = pDesc->TextureCubeArray.First2DArrayFace;
viewInfo.numLayers = pDesc->TextureCubeArray.NumCubes * 6;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
viewInfo.mipIndex = pDesc->TextureCubeArray.MostDetailedMip;
viewInfo.mipCount = pDesc->TextureCubeArray.MipLevels;
viewInfo.layerIndex = pDesc->TextureCubeArray.First2DArrayFace;
viewInfo.layerCount = pDesc->TextureCubeArray.NumCubes * 6;
break;
default:
@ -166,23 +166,27 @@ namespace dxvk {
}
if (texture->GetPlaneCount() > 1)
viewInfo.aspect = vk::getPlaneAspect(GetPlaneSlice(pDesc));
viewInfo.aspects = vk::getPlaneAspect(GetPlaneSlice(pDesc));
// Populate view info struct
m_info.Image.Aspects = viewInfo.aspect;
m_info.Image.MinLevel = viewInfo.minLevel;
m_info.Image.MinLayer = viewInfo.minLayer;
m_info.Image.NumLevels = viewInfo.numLevels;
m_info.Image.NumLayers = viewInfo.numLayers;
m_info.Image.Aspects = viewInfo.aspects;
m_info.Image.MinLevel = viewInfo.mipIndex;
m_info.Image.MinLayer = viewInfo.layerIndex;
m_info.Image.NumLevels = viewInfo.mipCount;
m_info.Image.NumLayers = viewInfo.layerCount;
// Create the underlying image view object
m_imageView = pDevice->GetDXVKDevice()->createImageView(texture->GetImage(), viewInfo);
m_imageView = texture->GetImage()->createView(viewInfo);
}
}
D3D11ShaderResourceView::~D3D11ShaderResourceView() {
ResourceReleasePrivate(m_resource);
m_resource = nullptr;
m_imageView = nullptr;
m_bufferView = nullptr;
}
@ -205,12 +209,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 +302,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

@ -25,86 +25,86 @@ namespace dxvk {
if (resourceDesc.Dim == D3D11_RESOURCE_DIMENSION_BUFFER) {
auto buffer = static_cast<D3D11Buffer*>(pResource);
DxvkBufferViewCreateInfo viewInfo;
DxvkBufferViewKey viewInfo;
viewInfo.usage = VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
if (pDesc->Buffer.Flags & D3D11_BUFFEREX_SRV_FLAG_RAW) {
viewInfo.format = VK_FORMAT_R32_UINT;
viewInfo.rangeOffset = sizeof(uint32_t) * pDesc->Buffer.FirstElement;
viewInfo.rangeLength = sizeof(uint32_t) * pDesc->Buffer.NumElements;
viewInfo.format = VK_FORMAT_R32_UINT;
viewInfo.offset = sizeof(uint32_t) * pDesc->Buffer.FirstElement;
viewInfo.size = sizeof(uint32_t) * pDesc->Buffer.NumElements;
} else if (pDesc->Format == DXGI_FORMAT_UNKNOWN) {
viewInfo.format = VK_FORMAT_R32_UINT;
viewInfo.rangeOffset = buffer->Desc()->StructureByteStride * pDesc->Buffer.FirstElement;
viewInfo.rangeLength = buffer->Desc()->StructureByteStride * pDesc->Buffer.NumElements;
viewInfo.format = VK_FORMAT_R32_UINT;
viewInfo.offset = buffer->Desc()->StructureByteStride * pDesc->Buffer.FirstElement;
viewInfo.size = buffer->Desc()->StructureByteStride * pDesc->Buffer.NumElements;
} else {
viewInfo.format = pDevice->LookupFormat(pDesc->Format, DXGI_VK_FORMAT_MODE_COLOR).Format;
const DxvkFormatInfo* formatInfo = lookupFormatInfo(viewInfo.format);
viewInfo.rangeOffset = formatInfo->elementSize * pDesc->Buffer.FirstElement;
viewInfo.rangeLength = formatInfo->elementSize * pDesc->Buffer.NumElements;
viewInfo.offset = formatInfo->elementSize * pDesc->Buffer.FirstElement;
viewInfo.size = formatInfo->elementSize * pDesc->Buffer.NumElements;
}
if (pDesc->Buffer.Flags & (D3D11_BUFFER_UAV_FLAG_APPEND | D3D11_BUFFER_UAV_FLAG_COUNTER))
m_counterView = CreateCounterBufferView();
// Populate view info struct
m_info.Buffer.Offset = viewInfo.rangeOffset;
m_info.Buffer.Length = viewInfo.rangeLength;
m_info.Buffer.Offset = viewInfo.offset;
m_info.Buffer.Length = viewInfo.size;
m_bufferView = pDevice->GetDXVKDevice()->createBufferView(
buffer->GetBuffer(), viewInfo);
m_bufferView = buffer->GetBuffer()->createView(viewInfo);
} else {
auto texture = GetCommonTexture(pResource);
auto formatInfo = pDevice->LookupFormat(pDesc->Format, texture->GetFormatMode());
DxvkImageViewCreateInfo viewInfo;
viewInfo.format = formatInfo.Format;
viewInfo.aspect = formatInfo.Aspect;
viewInfo.usage = VK_IMAGE_USAGE_STORAGE_BIT;
DxvkImageViewKey viewInfo;
viewInfo.format = formatInfo.Format;
viewInfo.aspects = formatInfo.Aspect;
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;
viewInfo.minLevel = pDesc->Texture1D.MipSlice;
viewInfo.numLevels = 1;
viewInfo.minLayer = 0;
viewInfo.numLayers = 1;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_1D;
viewInfo.mipIndex = pDesc->Texture1D.MipSlice;
viewInfo.mipCount = 1;
viewInfo.layerIndex = 0;
viewInfo.layerCount = 1;
break;
case D3D11_UAV_DIMENSION_TEXTURE1DARRAY:
viewInfo.type = VK_IMAGE_VIEW_TYPE_1D_ARRAY;
viewInfo.minLevel = pDesc->Texture1DArray.MipSlice;
viewInfo.numLevels = 1;
viewInfo.minLayer = pDesc->Texture1DArray.FirstArraySlice;
viewInfo.numLayers = pDesc->Texture1DArray.ArraySize;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_1D_ARRAY;
viewInfo.mipIndex = pDesc->Texture1DArray.MipSlice;
viewInfo.mipCount = 1;
viewInfo.layerIndex = pDesc->Texture1DArray.FirstArraySlice;
viewInfo.layerCount = pDesc->Texture1DArray.ArraySize;
break;
case D3D11_UAV_DIMENSION_TEXTURE2D:
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.minLevel = pDesc->Texture2D.MipSlice;
viewInfo.numLevels = 1;
viewInfo.minLayer = 0;
viewInfo.numLayers = 1;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.mipIndex = pDesc->Texture2D.MipSlice;
viewInfo.mipCount = 1;
viewInfo.layerIndex = 0;
viewInfo.layerCount = 1;
break;
case D3D11_UAV_DIMENSION_TEXTURE2DARRAY:
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
viewInfo.minLevel = pDesc->Texture2DArray.MipSlice;
viewInfo.numLevels = 1;
viewInfo.minLayer = pDesc->Texture2DArray.FirstArraySlice;
viewInfo.numLayers = pDesc->Texture2DArray.ArraySize;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
viewInfo.mipIndex = pDesc->Texture2DArray.MipSlice;
viewInfo.mipCount = 1;
viewInfo.layerIndex = pDesc->Texture2DArray.FirstArraySlice;
viewInfo.layerCount = pDesc->Texture2DArray.ArraySize;
break;
case D3D11_UAV_DIMENSION_TEXTURE3D:
// FIXME we actually have to map this to a
// 2D array view in order to support W slices
viewInfo.type = VK_IMAGE_VIEW_TYPE_3D;
viewInfo.minLevel = pDesc->Texture3D.MipSlice;
viewInfo.numLevels = 1;
viewInfo.minLayer = 0;
viewInfo.numLayers = 1;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_3D;
viewInfo.mipIndex = pDesc->Texture3D.MipSlice;
viewInfo.mipCount = 1;
viewInfo.layerIndex = 0;
viewInfo.layerCount = 1;
break;
default:
@ -112,23 +112,27 @@ namespace dxvk {
}
if (texture->GetPlaneCount() > 1)
viewInfo.aspect = vk::getPlaneAspect(GetPlaneSlice(pDesc));
viewInfo.aspects = vk::getPlaneAspect(GetPlaneSlice(pDesc));
// Populate view info struct
m_info.Image.Aspects = viewInfo.aspect;
m_info.Image.MinLevel = viewInfo.minLevel;
m_info.Image.MinLayer = viewInfo.minLayer;
m_info.Image.NumLevels = viewInfo.numLevels;
m_info.Image.NumLayers = viewInfo.numLayers;
m_info.Image.Aspects = viewInfo.aspects;
m_info.Image.MinLevel = viewInfo.mipIndex;
m_info.Image.MinLayer = viewInfo.layerIndex;
m_info.Image.NumLevels = viewInfo.mipCount;
m_info.Image.NumLayers = viewInfo.layerCount;
m_imageView = pDevice->GetDXVKDevice()->createImageView(
GetCommonTexture(pResource)->GetImage(), viewInfo);
m_imageView = GetCommonTexture(pResource)->GetImage()->createView(viewInfo);
}
}
D3D11UnorderedAccessView::~D3D11UnorderedAccessView() {
ResourceReleasePrivate(m_resource);
m_resource = nullptr;
m_bufferView = nullptr;
m_counterView = nullptr;
m_imageView = nullptr;
}
@ -147,8 +151,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;
}
@ -211,7 +218,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;
@ -443,15 +450,17 @@ namespace dxvk {
| VK_ACCESS_TRANSFER_READ_BIT
| VK_ACCESS_SHADER_WRITE_BIT
| VK_ACCESS_SHADER_READ_BIT;
info.debugName = "UAV counter";
Rc<DxvkBuffer> buffer = device->createBuffer(info, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
DxvkBufferViewCreateInfo viewInfo;
DxvkBufferViewKey viewInfo;
viewInfo.format = VK_FORMAT_UNDEFINED;
viewInfo.rangeOffset = 0;
viewInfo.rangeLength = sizeof(uint32_t);
viewInfo.offset = 0;
viewInfo.size = sizeof(uint32_t);
viewInfo.usage = VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
return device->createBufferView(buffer, viewInfo);
return buffer->createView(viewInfo);
}
}

View file

@ -43,6 +43,10 @@ namespace dxvk {
return m_info.BindFlags & Flags;
}
BOOL HasCounter() const {
return m_counterView != nullptr;
}
D3D11_RESOURCE_DIMENSION GetResourceType() const {
D3D11_RESOURCE_DIMENSION type;
m_resource->GetType(&type);

View file

@ -42,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',
@ -68,23 +69,33 @@ 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,
d3d11_dll = shared_library(dxvk_name_prefix+'d3d11', 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,
link_args : d3d11_ld_args,
link_depends : [ d3d11_link_depends ],
kwargs : dxvk_so_version,
)
d3d11_dep = declare_dependency(
link_with : [ d3d11_dll ],
include_directories : [ dxvk_include_path ],
)
if platform != 'windows'
pkg.generate(d3d11_dll,
filebase: dxvk_pkg_prefix + 'd3d11',
subdirs: 'dxvk',
)
endif

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;
}

6
src/d3d8/d3d8.def Normal file
View file

@ -0,0 +1,6 @@
LIBRARY D3D8.DLL
EXPORTS
ValidatePixelShader @ 2
ValidateVertexShader @ 3
DebugSetMute @ 4
Direct3DCreate8 @ 5

10
src/d3d8/d3d8.sym Normal file
View file

@ -0,0 +1,10 @@
{
global:
ValidatePixelShader;
ValidateVertexShader;
DebugSetMute;
Direct3DCreate8;
local:
*;
};

250
src/d3d8/d3d8_batch.h Normal file
View file

@ -0,0 +1,250 @@
#pragma once
#include "d3d8_include.h"
#include "d3d8_buffer.h"
#include "d3d8_format.h"
#include <vector>
#include <cstdint>
namespace dxvk {
inline constexpr size_t D3DPT_COUNT = size_t(D3DPT_TRIANGLEFAN) + 1;
inline constexpr D3DPRIMITIVETYPE D3DPT_INVALID = D3DPRIMITIVETYPE(0);
// Vertex buffer that can handle many tiny locks while
// still maintaing the lock ordering of direct-mapped buffers.
class D3D8BatchBuffer final : public D3D8VertexBuffer {
public:
D3D8BatchBuffer(
D3D8Device* pDevice,
D3DPOOL Pool,
DWORD Usage,
UINT Length,
DWORD FVF)
: D3D8VertexBuffer(pDevice, nullptr, Pool, Usage)
, m_data(Length)
, m_fvf(FVF) {
}
HRESULT STDMETHODCALLTYPE Lock(
UINT OffsetToLock,
UINT SizeToLock,
BYTE** ppbData,
DWORD Flags) {
*ppbData = m_data.data() + OffsetToLock;
return D3D_OK;
}
HRESULT STDMETHODCALLTYPE Unlock() {
return D3D_OK;
}
HRESULT STDMETHODCALLTYPE GetDesc(D3DVERTEXBUFFER_DESC* pDesc) {
if (unlikely(pDesc == nullptr))
return D3DERR_INVALIDCALL;
pDesc->Format = D3DFMT_VERTEXDATA;
pDesc->Type = D3DRTYPE_VERTEXBUFFER;
pDesc->Usage = m_usage;
pDesc->Pool = m_pool;
pDesc->Size = m_data.size();
pDesc->FVF = m_fvf;
return D3D_OK;
}
void STDMETHODCALLTYPE PreLoad() {
}
const void* GetPtr(UINT byteOffset = 0) const {
return m_data.data() + byteOffset;
}
UINT Size() const {
return m_data.size();
}
private:
std::vector<BYTE> m_data;
DWORD m_fvf;
};
// Main handler for batching D3D8 draw calls.
class D3D8Batcher {
struct Batch {
D3DPRIMITIVETYPE PrimitiveType = D3DPT_INVALID;
std::vector<uint16_t> Indices;
UINT Offset = 0;
UINT MinVertex = std::numeric_limits<uint32_t>::max();
UINT MaxVertex = 0;
UINT PrimitiveCount = 0;
UINT DrawCallCount = 0;
};
public:
D3D8Batcher(D3D8Device* pDevice8, Com<d3d9::IDirect3DDevice9>&& pDevice9)
: m_device8(pDevice8)
, m_device(std::move(pDevice9)) {
}
inline D3D8BatchBuffer* CreateVertexBuffer(UINT Length, DWORD Usage, DWORD FVF, D3DPOOL Pool) {
return ref(new D3D8BatchBuffer(m_device8, Pool, Usage, Length, FVF));
}
inline void StateChange() {
if (likely(m_batches.empty()))
return;
for (auto& draw : m_batches) {
if (draw.PrimitiveType == D3DPT_INVALID)
continue;
for (auto& index : draw.Indices)
index -= draw.MinVertex;
m_device->DrawIndexedPrimitiveUP(
d3d9::D3DPRIMITIVETYPE(draw.PrimitiveType),
0,
draw.MaxVertex - draw.MinVertex,
draw.PrimitiveCount,
draw.Indices.data(),
d3d9::D3DFMT_INDEX16,
m_stream->GetPtr(draw.MinVertex * m_stride),
m_stride);
m_device->SetStreamSource(0, D3D8VertexBuffer::GetD3D9Nullable(m_stream), 0, m_stride);
m_device->SetIndices(D3D8IndexBuffer::GetD3D9Nullable(m_indices));
draw.PrimitiveType = D3DPRIMITIVETYPE(0);
draw.Offset = 0;
draw.MinVertex = std::numeric_limits<uint32_t>::max();
draw.MaxVertex = 0;
draw.PrimitiveCount = 0;
draw.DrawCallCount = 0;
}
}
inline void EndFrame() {
// Nothing to be done.
}
inline HRESULT DrawPrimitive(
D3DPRIMITIVETYPE PrimitiveType,
UINT StartVertex,
UINT PrimitiveCount) {
// None of this linestrip or fan malarkey
D3DPRIMITIVETYPE batchedPrimType = PrimitiveType;
switch (PrimitiveType) {
case D3DPT_LINESTRIP: batchedPrimType = D3DPT_LINELIST; break;
case D3DPT_TRIANGLEFAN: batchedPrimType = D3DPT_TRIANGLELIST; break;
default: break;
}
Batch* batch = &m_batches[size_t(batchedPrimType)];
batch->PrimitiveType = batchedPrimType;
//UINT vertices = GetVertexCount8(PrimitiveType, PrimitiveCount);
switch (PrimitiveType) {
case D3DPT_POINTLIST:
batch->Indices.resize(batch->Offset + PrimitiveCount);
for (UINT i = 0; i < PrimitiveCount; i++)
batch->Indices[batch->Offset++] = (StartVertex + i);
break;
case D3DPT_LINELIST:
batch->Indices.resize(batch->Offset + PrimitiveCount * 2);
for (UINT i = 0; i < PrimitiveCount; i++) {
batch->Indices[batch->Offset++] = (StartVertex + i * 2 + 0);
batch->Indices[batch->Offset++] = (StartVertex + i * 2 + 1);
}
break;
case D3DPT_LINESTRIP:
batch->Indices.resize(batch->Offset + PrimitiveCount * 2);
for (UINT i = 0; i < PrimitiveCount; i++) {
batch->Indices[batch->Offset++] = (StartVertex + i + 0);
batch->Indices[batch->Offset++] = (StartVertex + i + 1);
}
break;
case D3DPT_TRIANGLELIST:
batch->Indices.resize(batch->Offset + PrimitiveCount * 3);
for (UINT i = 0; i < PrimitiveCount; i++) {
batch->Indices[batch->Offset++] = (StartVertex + i * 3 + 0);
batch->Indices[batch->Offset++] = (StartVertex + i * 3 + 1);
batch->Indices[batch->Offset++] = (StartVertex + i * 3 + 2);
}
break;
case D3DPT_TRIANGLESTRIP:
// Join with degenerate triangle
// 1 2 3, 3 4, 4 5 6
batch->Indices.resize(batch->Offset + PrimitiveCount + 2);
if (batch->Offset > 0) {
batch->Indices[batch->Offset + 1] = batch->Indices[batch->Offset-2];
batch->Indices[batch->Offset += 2] = StartVertex;
}
for (UINT i = 0; i < PrimitiveCount; i++) {
batch->Indices[batch->Offset++] = (StartVertex + i + 0);
}
break;
// 1 2 3 4 5 6 7 -> 1 2 3, 1 3 4, 1 4 5, 1 5 6, 1 6 7
case D3DPT_TRIANGLEFAN:
batch->Indices.resize(batch->Offset + PrimitiveCount * 3);
for (UINT i = 0; i < PrimitiveCount; i++) {
batch->Indices[batch->Offset++] = (StartVertex + 0);
batch->Indices[batch->Offset++] = (StartVertex + i + 1);
batch->Indices[batch->Offset++] = (StartVertex + i + 2);
}
break;
default:
return D3DERR_INVALIDCALL;
}
batch->MinVertex = std::min(batch->MinVertex, StartVertex);
if (!batch->Indices.empty())
batch->MaxVertex = std::max(batch->MaxVertex, UINT(batch->Indices.back() + 1));
batch->PrimitiveCount += PrimitiveCount;
batch->DrawCallCount++;
return D3D_OK;
}
inline void SetStream(UINT num, D3D8VertexBuffer* stream, UINT stride) {
if (unlikely(num != 0)) {
StateChange();
return;
}
if (unlikely(m_stream != stream || m_stride != stride)) {
StateChange();
m_stream = static_cast<D3D8BatchBuffer*>(stream);
m_stride = stride;
}
}
inline void SetIndices(D3D8IndexBuffer* indices, INT baseVertexIndex) {
if (m_indices != indices || m_baseVertexIndex != baseVertexIndex) {
StateChange();
m_indices = indices;
m_baseVertexIndex = baseVertexIndex;
}
}
private:
D3D8Device* m_device8;
Com<d3d9::IDirect3DDevice9> m_device;
D3D8BatchBuffer* m_stream = nullptr;
UINT m_stride = 0;
D3D8IndexBuffer* m_indices = nullptr;
INT m_baseVertexIndex = 0;
std::array<Batch, D3DPT_COUNT> m_batches;
};
}

38
src/d3d8/d3d8_buffer.cpp Normal file
View file

@ -0,0 +1,38 @@
#include "d3d8_buffer.h"
#include "d3d8_device.h"
namespace dxvk {
// D3D8VertexBuffer
D3D8VertexBuffer::D3D8VertexBuffer(
D3D8Device* pDevice,
Com<d3d9::IDirect3DVertexBuffer9>&& pBuffer,
D3DPOOL Pool,
DWORD Usage)
: D3D8VertexBufferBase(pDevice, std::move(pBuffer), Pool, Usage) {
}
D3DRESOURCETYPE STDMETHODCALLTYPE D3D8VertexBuffer::GetType() { return D3DRTYPE_VERTEXBUFFER; }
HRESULT STDMETHODCALLTYPE D3D8VertexBuffer::GetDesc(D3DVERTEXBUFFER_DESC* pDesc) {
return GetD3D9()->GetDesc(reinterpret_cast<d3d9::D3DVERTEXBUFFER_DESC*>(pDesc));
}
// D3D8IndexBuffer
D3D8IndexBuffer::D3D8IndexBuffer(
D3D8Device* pDevice,
Com<d3d9::IDirect3DIndexBuffer9>&& pBuffer,
D3DPOOL Pool,
DWORD Usage)
: D3D8IndexBufferBase(pDevice, std::move(pBuffer), Pool, Usage) {
}
D3DRESOURCETYPE STDMETHODCALLTYPE D3D8IndexBuffer::GetType() { return D3DRTYPE_INDEXBUFFER; }
HRESULT STDMETHODCALLTYPE D3D8IndexBuffer::GetDesc(D3DINDEXBUFFER_DESC* pDesc) {
return GetD3D9()->GetDesc(reinterpret_cast<d3d9::D3DINDEXBUFFER_DESC*>(pDesc));
}
}

93
src/d3d8/d3d8_buffer.h Normal file
View file

@ -0,0 +1,93 @@
#pragma once
#include "d3d8_include.h"
#include "d3d8_options.h"
#include "d3d8_resource.h"
namespace dxvk {
template <typename D3D9, typename D3D8>
class D3D8Buffer : public D3D8Resource<D3D9, D3D8> {
public:
D3D8Buffer(
D3D8Device* pDevice,
Com<D3D9>&& pBuffer,
D3DPOOL Pool,
DWORD Usage)
: D3D8Resource<D3D9, D3D8> (pDevice, Pool, std::move(pBuffer))
, m_usage (Usage) {
m_options = this->GetParent()->GetOptions();
}
HRESULT STDMETHODCALLTYPE Lock(
UINT OffsetToLock,
UINT SizeToLock,
BYTE** ppbData,
DWORD Flags) {
if (m_options->forceLegacyDiscard &&
(Flags & D3DLOCK_DISCARD) &&
!((m_usage & D3DUSAGE_DYNAMIC) &&
(m_usage & D3DUSAGE_WRITEONLY)))
Flags &= ~D3DLOCK_DISCARD;
return this->GetD3D9()->Lock(
OffsetToLock,
SizeToLock,
reinterpret_cast<void**>(ppbData),
Flags);
}
HRESULT STDMETHODCALLTYPE Unlock() {
return this->GetD3D9()->Unlock();
}
void STDMETHODCALLTYPE PreLoad() {
this->GetD3D9()->PreLoad();
}
protected:
const D3D8Options* m_options;
const DWORD m_usage;
};
using D3D8VertexBufferBase = D3D8Buffer<d3d9::IDirect3DVertexBuffer9, IDirect3DVertexBuffer8>;
class D3D8VertexBuffer : public D3D8VertexBufferBase {
public:
D3D8VertexBuffer(
D3D8Device* pDevice,
Com<d3d9::IDirect3DVertexBuffer9>&& pBuffer,
D3DPOOL Pool,
DWORD Usage);
D3DRESOURCETYPE STDMETHODCALLTYPE GetType() final;
HRESULT STDMETHODCALLTYPE GetDesc(D3DVERTEXBUFFER_DESC* pDesc);
};
using D3D8IndexBufferBase = D3D8Buffer<d3d9::IDirect3DIndexBuffer9, IDirect3DIndexBuffer8>;
class D3D8IndexBuffer final : public D3D8IndexBufferBase {
public:
D3D8IndexBuffer(
D3D8Device* pDevice,
Com<d3d9::IDirect3DIndexBuffer9>&& pBuffer,
D3DPOOL Pool,
DWORD Usage);
D3DRESOURCETYPE STDMETHODCALLTYPE GetType() final;
HRESULT STDMETHODCALLTYPE GetDesc(D3DINDEXBUFFER_DESC* pDesc) final;
};
}

8
src/d3d8/d3d8_caps.h Normal file
View file

@ -0,0 +1,8 @@
#pragma once
namespace dxvk::d8caps {
inline constexpr uint32_t MAX_TEXTURE_STAGES = 8;
inline constexpr uint32_t MAX_STREAMS = 16;
}

194
src/d3d8/d3d8_d3d9_util.h Normal file
View file

@ -0,0 +1,194 @@
#pragma once
// Utility functions for converting
// between DirectX8 and DirectX9 types.
#include "d3d8_include.h"
#include "d3d8_format.h"
#include "d3d8_options.h"
#include <utility>
namespace dxvk {
// (8<-9) D3DCAPSX: Writes to D3DCAPS8 from D3DCAPS9
inline void ConvertCaps8(const d3d9::D3DCAPS9& caps9, D3DCAPS8* pCaps8) {
// should be aligned
std::memcpy(pCaps8, &caps9, sizeof(D3DCAPS8));
// Max supported shader model is PS 1.4 and VS 1.1
pCaps8->VertexShaderVersion = D3DVS_VERSION(1, 1);
// Late fixed-function capable hardware will advertise VS 1.1
// support, but will not advertise any support for PS
if (likely(caps9.PixelShaderVersion != D3DPS_VERSION(0, 0)))
pCaps8->PixelShaderVersion = D3DPS_VERSION(1, 4);
// Remove D3D9-specific caps:
pCaps8->Caps2 &= ~D3DCAPS2_CANAUTOGENMIPMAP;
pCaps8->Caps3 &= ~D3DCAPS3_LINEAR_TO_SRGB_PRESENTATION
& ~D3DCAPS3_COPY_TO_VIDMEM
& ~D3DCAPS3_COPY_TO_SYSTEMMEM;
pCaps8->PrimitiveMiscCaps &= ~D3DPMISCCAPS_INDEPENDENTWRITEMASKS
& ~D3DPMISCCAPS_PERSTAGECONSTANT
& ~D3DPMISCCAPS_FOGANDSPECULARALPHA
& ~D3DPMISCCAPS_SEPARATEALPHABLEND
& ~D3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
& ~D3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING
& ~D3DPMISCCAPS_FOGVERTEXCLAMPED
& ~D3DPMISCCAPS_POSTBLENDSRGBCONVERT;
pCaps8->RasterCaps &= ~D3DPRASTERCAPS_SCISSORTEST
& ~D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS
& ~D3DPRASTERCAPS_DEPTHBIAS
& ~D3DPRASTERCAPS_MULTISAMPLE_TOGGLE;
pCaps8->SrcBlendCaps &= ~D3DPBLENDCAPS_BLENDFACTOR;
pCaps8->DestBlendCaps &= ~D3DPBLENDCAPS_BLENDFACTOR;
pCaps8->LineCaps &= ~D3DLINECAPS_ANTIALIAS;
pCaps8->StencilCaps &= ~D3DSTENCILCAPS_TWOSIDED;
pCaps8->VertexProcessingCaps &= ~D3DVTXPCAPS_TEXGEN_SPHEREMAP;
// Add D3D8-specific caps:
// Removed in D3D9, since it can always render windowed
pCaps8->Caps2 |= D3DCAPS2_CANRENDERWINDOWED
// A remnant from a bygone age of ddraw interop most likely
/* | D3DCAPS2_NO2DDURING3DSCENE*/;
// Used in conjunction with D3DPRASTERCAPS_PAT, but generally unadvertised
/*pCaps8->PrimitiveMiscCaps |= D3DPMISCCAPS_LINEPATTERNREP;*/
// Replaced by D3DPRASTERCAPS_DEPTHBIAS in D3D9
pCaps8->RasterCaps |= D3DPRASTERCAPS_ZBIAS
// Advertised on Nvidia cards by modern drivers, but not on AMD or Intel
/* | D3DPRASTERCAPS_ANTIALIASEDGES*/
// Advertised on Nvidia cards, but not on AMD or Intel
/* | D3DPRASTERCAPS_STRETCHBLTMULTISAMPLE*/
// TODO: Implement D3DRS_LINEPATTERN - vkCmdSetLineRasterizationModeEXT
/* | D3DPRASTERCAPS_PAT*/;
// MAG only filter caps, generally unsupported
/*pCaps8->TextureFilterCaps |= D3DPTFILTERCAPS_MAGFAFLATCUBIC*/
/* | D3DPTFILTERCAPS_MAGFGAUSSIANCUBIC;*/
/*pCaps8->CubeTextureFilterCaps = pCaps8->TextureFilterCaps;*/
/*pCaps8->VolumeTextureFilterCaps = pCaps8->TextureFilterCaps;*/
// Not advertised on any modern hardware
/*pCaps8->VertexProcessingCaps |= D3DVTXPCAPS_NO_VSDT_UBYTE4;*/
}
// (9<-8) D3DD3DPRESENT_PARAMETERS: Returns D3D9's params given an input for D3D8
inline d3d9::D3DPRESENT_PARAMETERS ConvertPresentParameters9(D3DPRESENT_PARAMETERS* pParams) {
// A 0 back buffer count needs to be corrected and made visible to the D3D8 application as well
pParams->BackBufferCount = std::max(pParams->BackBufferCount, 1u);
if (pParams->BackBufferFormat == D3DFMT_UNKNOWN)
pParams->BackBufferFormat = D3DFMT_X8R8G8B8;
d3d9::D3DPRESENT_PARAMETERS params;
params.BackBufferWidth = pParams->BackBufferWidth;
params.BackBufferHeight = pParams->BackBufferHeight;
params.BackBufferFormat = d3d9::D3DFORMAT(pParams->BackBufferFormat);
params.BackBufferCount = pParams->BackBufferCount;
params.MultiSampleType = d3d9::D3DMULTISAMPLE_TYPE(pParams->MultiSampleType);
// MultiSampleQuality is only used with D3DMULTISAMPLE_NONMASKABLE, which is not available in D3D8
params.MultiSampleQuality = 0;
// If an application passes multiple D3DPRESENT_INTERVAL flags, this will be
// validated appropriately by D3D9. Simply copy the values here.
UINT PresentationInterval = pParams->FullScreen_PresentationInterval;
if (pParams->Windowed) {
// D3D8: For windowed swap chain, the back buffer is copied to the window immediately.
PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
}
D3DSWAPEFFECT SwapEffect = pParams->SwapEffect;
if (SwapEffect == D3DSWAPEFFECT_COPY_VSYNC) {
// D3DSWAPEFFECT_COPY_VSYNC has been removed from D3D9, use D3DSWAPEFFECT_COPY
SwapEffect = D3DSWAPEFFECT_COPY;
// D3D8: In windowed mode, D3DSWAPEFFECT_COPY_VSYNC enables VSYNC.
// In fullscreen, D3DPRESENT_INTERVAL_IMMEDIATE is meaningless.
if (pParams->Windowed || PresentationInterval == D3DPRESENT_INTERVAL_IMMEDIATE) {
PresentationInterval = D3DPRESENT_INTERVAL_ONE;
}
}
params.SwapEffect = d3d9::D3DSWAPEFFECT(SwapEffect);
params.hDeviceWindow = pParams->hDeviceWindow;
params.Windowed = pParams->Windowed;
params.EnableAutoDepthStencil = pParams->EnableAutoDepthStencil;
params.AutoDepthStencilFormat = d3d9::D3DFORMAT(pParams->AutoDepthStencilFormat);
params.Flags = pParams->Flags;
// D3DPRESENT_RATE_UNLIMITED is unsupported, use D3DPRESENT_RATE_DEFAULT (or 0)
if (unlikely(pParams->FullScreen_RefreshRateInHz == D3DPRESENT_RATE_UNLIMITED)) {
params.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
} else {
params.FullScreen_RefreshRateInHz = pParams->FullScreen_RefreshRateInHz;
}
// FullScreen_PresentationInterval -> PresentationInterval
params.PresentationInterval = PresentationInterval;
return params;
}
// (8<-9) Convert D3DSURFACE_DESC
inline void ConvertSurfaceDesc8(const d3d9::D3DSURFACE_DESC* pSurf9, D3DSURFACE_DESC* pSurf8) {
pSurf8->Format = D3DFORMAT(pSurf9->Format);
pSurf8->Type = D3DRESOURCETYPE(pSurf9->Type);
pSurf8->Usage = pSurf9->Usage;
pSurf8->Pool = D3DPOOL(pSurf9->Pool);
pSurf8->Size = getSurfaceSize(pSurf8->Format, pSurf9->Width, pSurf9->Height);
pSurf8->MultiSampleType = D3DMULTISAMPLE_TYPE(pSurf9->MultiSampleType);
// DX8: No multisample quality
pSurf8->Width = pSurf9->Width;
pSurf8->Height = pSurf9->Height;
}
// (8<-9) Convert D3DVOLUME_DESC
inline void ConvertVolumeDesc8(const d3d9::D3DVOLUME_DESC* pVol9, D3DVOLUME_DESC* pVol8) {
pVol8->Format = D3DFORMAT(pVol9->Format);
pVol8->Type = D3DRESOURCETYPE(pVol9->Type);
pVol8->Usage = pVol9->Usage;
pVol8->Pool = D3DPOOL(pVol9->Pool);
pVol8->Size = getSurfaceSize(pVol8->Format, pVol9->Width, pVol9->Height) * pVol9->Depth;
pVol8->Width = pVol9->Width;
pVol8->Height = pVol9->Height;
pVol8->Depth = pVol9->Depth;
}
// If this D3DTEXTURESTAGESTATETYPE has been remapped to a d3d9::D3DSAMPLERSTATETYPE
// it will be returned, otherwise returns -1u
inline d3d9::D3DSAMPLERSTATETYPE GetSamplerStateType9(const D3DTEXTURESTAGESTATETYPE StageType) {
switch (StageType) {
// 13-21:
case D3DTSS_ADDRESSU: return d3d9::D3DSAMP_ADDRESSU;
case D3DTSS_ADDRESSV: return d3d9::D3DSAMP_ADDRESSV;
case D3DTSS_BORDERCOLOR: return d3d9::D3DSAMP_BORDERCOLOR;
case D3DTSS_MAGFILTER: return d3d9::D3DSAMP_MAGFILTER;
case D3DTSS_MINFILTER: return d3d9::D3DSAMP_MINFILTER;
case D3DTSS_MIPFILTER: return d3d9::D3DSAMP_MIPFILTER;
case D3DTSS_MIPMAPLODBIAS: return d3d9::D3DSAMP_MIPMAPLODBIAS;
case D3DTSS_MAXMIPLEVEL: return d3d9::D3DSAMP_MAXMIPLEVEL;
case D3DTSS_MAXANISOTROPY: return d3d9::D3DSAMP_MAXANISOTROPY;
// 25:
case D3DTSS_ADDRESSW: return d3d9::D3DSAMP_ADDRESSW;
default: return d3d9::D3DSAMPLERSTATETYPE(-1u);
}
}
}

2188
src/d3d8/d3d8_device.cpp Normal file

File diff suppressed because it is too large Load diff

478
src/d3d8/d3d8_device.h Normal file
View file

@ -0,0 +1,478 @@
#pragma once
#include "d3d8_include.h"
#include "d3d8_multithread.h"
#include "d3d8_texture.h"
#include "d3d8_buffer.h"
#include "d3d8_swapchain.h"
#include "d3d8_state_block.h"
#include "d3d8_d3d9_util.h"
#include "d3d8_caps.h"
#include "d3d8_batch.h"
#include "../d3d9/d3d9_bridge.h"
#include <array>
#include <vector>
#include <type_traits>
#include <unordered_map>
namespace dxvk {
class D3D8Interface;
struct D3D8VertexShaderInfo;
using D3D8DeviceBase = D3D8WrappedObject<d3d9::IDirect3DDevice9, IDirect3DDevice8>;
class D3D8Device final : public D3D8DeviceBase {
friend class D3D8StateBlock;
public:
D3D8Device(
D3D8Interface* pParent,
Com<d3d9::IDirect3DDevice9>&& pDevice,
D3DDEVTYPE DeviceType,
HWND hFocusWindow,
DWORD BehaviorFlags,
D3DPRESENT_PARAMETERS* pParams);
~D3D8Device();
HRESULT STDMETHODCALLTYPE TestCooperativeLevel();
UINT STDMETHODCALLTYPE GetAvailableTextureMem();
HRESULT STDMETHODCALLTYPE ResourceManagerDiscardBytes(DWORD bytes);
HRESULT STDMETHODCALLTYPE GetDirect3D(IDirect3D8** ppD3D8);
HRESULT STDMETHODCALLTYPE GetDeviceCaps(D3DCAPS8* pCaps);
HRESULT STDMETHODCALLTYPE GetDisplayMode(D3DDISPLAYMODE* pMode);
HRESULT STDMETHODCALLTYPE GetCreationParameters(D3DDEVICE_CREATION_PARAMETERS* pParameters);
HRESULT STDMETHODCALLTYPE SetCursorProperties(
UINT XHotSpot,
UINT YHotSpot,
IDirect3DSurface8* pCursorBitmap);
void STDMETHODCALLTYPE SetCursorPosition(UINT XScreenSpace, UINT YScreenSpace, DWORD Flags);
// Microsoft d3d8.h in the DirectX 9 SDK uses a different function signature...
void STDMETHODCALLTYPE SetCursorPosition(int X, int Y, DWORD Flags);
BOOL STDMETHODCALLTYPE ShowCursor(BOOL bShow);
HRESULT STDMETHODCALLTYPE CreateAdditionalSwapChain(
D3DPRESENT_PARAMETERS* pPresentationParameters,
IDirect3DSwapChain8** ppSwapChain);
HRESULT STDMETHODCALLTYPE Reset(D3DPRESENT_PARAMETERS* pPresentationParameters);
HRESULT STDMETHODCALLTYPE Present(
const RECT* pSourceRect,
const RECT* pDestRect,
HWND hDestWindowOverride,
const RGNDATA* pDirtyRegion);
HRESULT STDMETHODCALLTYPE GetBackBuffer(
UINT iBackBuffer,
D3DBACKBUFFER_TYPE Type,
IDirect3DSurface8** ppBackBuffer);
HRESULT STDMETHODCALLTYPE GetRasterStatus(D3DRASTER_STATUS* pRasterStatus);
void STDMETHODCALLTYPE SetGammaRamp(DWORD Flags, const D3DGAMMARAMP* pRamp);
void STDMETHODCALLTYPE GetGammaRamp(D3DGAMMARAMP* pRamp);
HRESULT STDMETHODCALLTYPE CreateTexture(
UINT Width,
UINT Height,
UINT Levels,
DWORD Usage,
D3DFORMAT Format,
D3DPOOL Pool,
IDirect3DTexture8** ppTexture);
HRESULT STDMETHODCALLTYPE CreateVolumeTexture(
UINT Width,
UINT Height,
UINT Depth,
UINT Levels,
DWORD Usage,
D3DFORMAT Format,
D3DPOOL Pool,
IDirect3DVolumeTexture8** ppVolumeTexture);
HRESULT STDMETHODCALLTYPE CreateCubeTexture(
UINT EdgeLength,
UINT Levels,
DWORD Usage,
D3DFORMAT Format,
D3DPOOL Pool,
IDirect3DCubeTexture8** ppCubeTexture);
HRESULT STDMETHODCALLTYPE CreateVertexBuffer(
UINT Length,
DWORD Usage,
DWORD FVF,
D3DPOOL Pool,
IDirect3DVertexBuffer8** ppVertexBuffer);
HRESULT STDMETHODCALLTYPE CreateIndexBuffer(
UINT Length,
DWORD Usage,
D3DFORMAT Format,
D3DPOOL Pool,
IDirect3DIndexBuffer8** ppIndexBuffer);
HRESULT STDMETHODCALLTYPE CreateRenderTarget(
UINT Width,
UINT Height,
D3DFORMAT Format,
D3DMULTISAMPLE_TYPE MultiSample,
BOOL Lockable,
IDirect3DSurface8** ppSurface);
HRESULT STDMETHODCALLTYPE CreateDepthStencilSurface(
UINT Width,
UINT Height,
D3DFORMAT Format,
D3DMULTISAMPLE_TYPE MultiSample,
IDirect3DSurface8** ppSurface);
HRESULT STDMETHODCALLTYPE CreateImageSurface(UINT Width, UINT Height, D3DFORMAT Format, IDirect3DSurface8** ppSurface);
HRESULT STDMETHODCALLTYPE CopyRects(
IDirect3DSurface8* pSourceSurface,
const RECT* pSourceRectsArray,
UINT cRects,
IDirect3DSurface8* pDestinationSurface,
const POINT* pDestPointsArray);
HRESULT STDMETHODCALLTYPE UpdateTexture(
IDirect3DBaseTexture8* pSourceTexture,
IDirect3DBaseTexture8* pDestinationTexture);
HRESULT STDMETHODCALLTYPE GetFrontBuffer(IDirect3DSurface8* pDestSurface);
HRESULT STDMETHODCALLTYPE SetRenderTarget(IDirect3DSurface8* pRenderTarget, IDirect3DSurface8* pNewZStencil);
HRESULT STDMETHODCALLTYPE GetRenderTarget(IDirect3DSurface8** ppRenderTarget);
HRESULT STDMETHODCALLTYPE GetDepthStencilSurface(IDirect3DSurface8** ppZStencilSurface);
HRESULT STDMETHODCALLTYPE BeginScene();
HRESULT STDMETHODCALLTYPE EndScene();
HRESULT STDMETHODCALLTYPE Clear(
DWORD Count,
const D3DRECT* pRects,
DWORD Flags,
D3DCOLOR Color,
float Z,
DWORD Stencil);
HRESULT STDMETHODCALLTYPE SetTransform(D3DTRANSFORMSTATETYPE State, const D3DMATRIX* pMatrix);
HRESULT STDMETHODCALLTYPE GetTransform(D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix);
HRESULT STDMETHODCALLTYPE MultiplyTransform(D3DTRANSFORMSTATETYPE TransformState, const D3DMATRIX* pMatrix);
HRESULT STDMETHODCALLTYPE SetViewport(const D3DVIEWPORT8* pViewport);
HRESULT STDMETHODCALLTYPE GetViewport(D3DVIEWPORT8* pViewport);
HRESULT STDMETHODCALLTYPE SetMaterial(const D3DMATERIAL8* pMaterial);
HRESULT STDMETHODCALLTYPE GetMaterial(D3DMATERIAL8* pMaterial);
HRESULT STDMETHODCALLTYPE SetLight(DWORD Index, const D3DLIGHT8* pLight);
HRESULT STDMETHODCALLTYPE GetLight(DWORD Index, D3DLIGHT8* pLight);
HRESULT STDMETHODCALLTYPE LightEnable(DWORD Index, BOOL Enable);
HRESULT STDMETHODCALLTYPE GetLightEnable(DWORD Index, BOOL* pEnable);
HRESULT STDMETHODCALLTYPE SetClipPlane(DWORD Index, const float* pPlane);
HRESULT STDMETHODCALLTYPE GetClipPlane(DWORD Index, float* pPlane);
HRESULT STDMETHODCALLTYPE SetRenderState(D3DRENDERSTATETYPE State, DWORD Value);
HRESULT STDMETHODCALLTYPE GetRenderState(D3DRENDERSTATETYPE State, DWORD* pValue);
HRESULT STDMETHODCALLTYPE CreateStateBlock(
D3DSTATEBLOCKTYPE Type,
DWORD* pToken);
HRESULT STDMETHODCALLTYPE CaptureStateBlock(DWORD Token);
HRESULT STDMETHODCALLTYPE ApplyStateBlock(DWORD Token);
HRESULT STDMETHODCALLTYPE DeleteStateBlock(DWORD Token);
HRESULT STDMETHODCALLTYPE BeginStateBlock();
HRESULT STDMETHODCALLTYPE EndStateBlock(DWORD* pToken);
HRESULT STDMETHODCALLTYPE SetClipStatus(const D3DCLIPSTATUS8* pClipStatus);
HRESULT STDMETHODCALLTYPE GetClipStatus(D3DCLIPSTATUS8* pClipStatus);
HRESULT STDMETHODCALLTYPE GetTexture(DWORD Stage, IDirect3DBaseTexture8** ppTexture);
HRESULT STDMETHODCALLTYPE SetTexture(DWORD Stage, IDirect3DBaseTexture8* pTexture);
HRESULT STDMETHODCALLTYPE GetTextureStageState(
DWORD Stage,
D3DTEXTURESTAGESTATETYPE Type,
DWORD* pValue);
HRESULT STDMETHODCALLTYPE SetTextureStageState(
DWORD Stage,
D3DTEXTURESTAGESTATETYPE Type,
DWORD Value);
HRESULT STDMETHODCALLTYPE ValidateDevice(DWORD* pNumPasses);
HRESULT STDMETHODCALLTYPE GetInfo(DWORD DevInfoID, void* pDevInfoStruct, DWORD DevInfoStructSize);
HRESULT STDMETHODCALLTYPE SetPaletteEntries(UINT PaletteNumber, const PALETTEENTRY* pEntries);
HRESULT STDMETHODCALLTYPE GetPaletteEntries(UINT PaletteNumber, PALETTEENTRY* pEntries);
HRESULT STDMETHODCALLTYPE SetCurrentTexturePalette(UINT PaletteNumber);
HRESULT STDMETHODCALLTYPE GetCurrentTexturePalette(UINT* PaletteNumber);
HRESULT STDMETHODCALLTYPE DrawPrimitive(
D3DPRIMITIVETYPE PrimitiveType,
UINT StartVertex,
UINT PrimitiveCount);
HRESULT STDMETHODCALLTYPE DrawIndexedPrimitive(
D3DPRIMITIVETYPE PrimitiveType,
UINT MinVertexIndex,
UINT NumVertices,
UINT StartIndex,
UINT PrimitiveCount);
HRESULT STDMETHODCALLTYPE DrawPrimitiveUP(
D3DPRIMITIVETYPE PrimitiveType,
UINT PrimitiveCount,
const void* pVertexStreamZeroData,
UINT VertexStreamZeroStride);
HRESULT STDMETHODCALLTYPE DrawIndexedPrimitiveUP(
D3DPRIMITIVETYPE PrimitiveType,
UINT MinVertexIndex,
UINT NumVertices,
UINT PrimitiveCount,
const void* pIndexData,
D3DFORMAT IndexDataFormat,
const void* pVertexStreamZeroData,
UINT VertexStreamZeroStride);
HRESULT STDMETHODCALLTYPE ProcessVertices(
UINT SrcStartIndex,
UINT DestIndex,
UINT VertexCount,
IDirect3DVertexBuffer8* pDestBuffer,
DWORD Flags);
HRESULT STDMETHODCALLTYPE CreateVertexShader(
const DWORD* pDeclaration,
const DWORD* pFunction,
DWORD* pHandle,
DWORD Usage);
HRESULT STDMETHODCALLTYPE SetVertexShader(DWORD Handle);
HRESULT STDMETHODCALLTYPE GetVertexShader(DWORD* pHandle);
HRESULT STDMETHODCALLTYPE DeleteVertexShader(DWORD Handle);
HRESULT STDMETHODCALLTYPE SetVertexShaderConstant(
DWORD StartRegister,
const void* pConstantData,
DWORD ConstantCount);
HRESULT STDMETHODCALLTYPE GetVertexShaderConstant(DWORD Register, void* pConstantData, DWORD ConstantCount);
HRESULT STDMETHODCALLTYPE GetVertexShaderDeclaration(DWORD Handle, void* pData, DWORD* pSizeOfData);
HRESULT STDMETHODCALLTYPE GetVertexShaderFunction(DWORD Handle, void* pData, DWORD* pSizeOfData);
HRESULT STDMETHODCALLTYPE SetStreamSource(
UINT StreamNumber,
IDirect3DVertexBuffer8* pStreamData,
UINT Stride);
HRESULT STDMETHODCALLTYPE GetStreamSource(
UINT StreamNumber,
IDirect3DVertexBuffer8** ppStreamData,
UINT* pStride);
HRESULT STDMETHODCALLTYPE SetIndices(IDirect3DIndexBuffer8* pIndexData, UINT BaseVertexIndex);
HRESULT STDMETHODCALLTYPE GetIndices(
IDirect3DIndexBuffer8** ppIndexData,
UINT* pBaseVertexIndex);
HRESULT STDMETHODCALLTYPE CreatePixelShader(
const DWORD* pFunction,
DWORD* pHandle);
HRESULT STDMETHODCALLTYPE SetPixelShader(DWORD Handle);
HRESULT STDMETHODCALLTYPE GetPixelShader(DWORD* pHandle);
HRESULT STDMETHODCALLTYPE DeletePixelShader(THIS_ DWORD Handle);
HRESULT STDMETHODCALLTYPE GetPixelShaderConstant(DWORD Register, void* pConstantData, DWORD ConstantCount);
HRESULT STDMETHODCALLTYPE SetPixelShaderConstant(
DWORD StartRegister,
const void* pConstantData,
DWORD ConstantCount);
HRESULT STDMETHODCALLTYPE GetPixelShaderFunction(DWORD Handle, void* pData, DWORD* pSizeOfData);
HRESULT STDMETHODCALLTYPE DrawRectPatch(
UINT Handle,
const float* pNumSegs,
const D3DRECTPATCH_INFO* pRectPatchInfo);
HRESULT STDMETHODCALLTYPE DrawTriPatch(
UINT Handle,
const float* pNumSegs,
const D3DTRIPATCH_INFO* pTriPatchInfo);
HRESULT STDMETHODCALLTYPE DeletePatch(UINT Handle);
const D3D8Options* GetOptions() const {
return &m_d3d8Options;
}
inline bool ShouldRecord() { return m_recorder != nullptr; }
inline bool ShouldBatch() { return m_batcher != nullptr; }
D3D8DeviceLock LockDevice() {
return m_multithread.AcquireLock();
}
/**
* Marks any state change in the device, so we can signal
* the batcher to emit draw calls. StateChange should be
* called immediately before changing any D3D9 state.
*/
inline void StateChange() {
if (ShouldBatch())
m_batcher->StateChange();
}
inline void ResetState() {
// Mirrors how D3D9 handles the BackBufferCount
m_presentParams.BackBufferCount = std::max(m_presentParams.BackBufferCount, 1u);
// Purge cached objects
m_textures.fill(nullptr);
m_streams.fill(D3D8VBO());
m_indices = nullptr;
m_renderTarget = nullptr;
m_depthStencil = nullptr;
m_backBuffers.clear();
m_backBuffers.resize(m_presentParams.BackBufferCount);
m_autoDepthStencil = nullptr;
m_shadowPerspectiveDivide = false;
}
inline void RecreateBackBuffersAndAutoDepthStencil() {
for (UINT i = 0; i < m_presentParams.BackBufferCount; i++) {
Com<d3d9::IDirect3DSurface9> pSurface9;
GetD3D9()->GetBackBuffer(0, i, d3d9::D3DBACKBUFFER_TYPE_MONO, &pSurface9);
m_backBuffers[i] = new D3D8Surface(this, D3DPOOL_DEFAULT, std::move(pSurface9));
}
Com<d3d9::IDirect3DSurface9> pStencil9;
// This call will fail if the D3D9 device is created without
// the EnableAutoDepthStencil presentation parameter set to TRUE.
HRESULT res = GetD3D9()->GetDepthStencilSurface(&pStencil9);
m_autoDepthStencil = FAILED(res) ? nullptr : new D3D8Surface(this, D3DPOOL_DEFAULT, std::move(pStencil9));
m_renderTarget = m_backBuffers[0];
m_depthStencil = m_autoDepthStencil;
}
friend d3d9::IDirect3DPixelShader9* getPixelShaderPtr(D3D8Device* device, DWORD Handle);
friend D3D8VertexShaderInfo* getVertexShaderInfo(D3D8Device* device, DWORD Handle);
private:
Com<IDxvkD3D8Bridge> m_bridge;
const D3D8Options& m_d3d8Options;
Com<D3D8Interface> m_parent;
D3DPRESENT_PARAMETERS m_presentParams;
// Value of D3DRS_LINEPATTERN
D3DLINEPATTERN m_linePattern = {};
// Value of D3DRS_ZVISIBLE (although the RS is not supported, its value is stored)
DWORD m_zVisible = 0;
// Value of D3DRS_PATCHSEGMENTS
float m_patchSegments = 1.0f;
// Controls fixed-function exclusive mode (no PS support)
bool m_isFixedFunctionOnly = false;
bool m_shadowPerspectiveDivide = false;
D3D8StateBlock* m_recorder = nullptr;
DWORD m_recorderToken = 0;
DWORD m_token = 0;
std::unordered_map<DWORD, D3D8StateBlock> m_stateBlocks;
D3D8Batcher* m_batcher = nullptr;
struct D3D8VBO {
Com<D3D8VertexBuffer, false> buffer = nullptr;
UINT stride = 0;
};
std::array<Com<D3D8Texture2D, false>, d8caps::MAX_TEXTURE_STAGES> m_textures;
std::array<D3D8VBO, d8caps::MAX_STREAMS> m_streams;
Com<D3D8IndexBuffer, false> m_indices;
UINT m_baseVertexIndex = 0;
std::vector<Com<D3D8Surface, false>> m_backBuffers;
Com<D3D8Surface, false> m_autoDepthStencil;
Com<D3D8Surface, false> m_renderTarget;
Com<D3D8Surface, false> m_depthStencil;
std::vector<D3D8VertexShaderInfo> m_vertexShaders;
std::vector<Com<d3d9::IDirect3DPixelShader9>> m_pixelShaders;
DWORD m_currentVertexShader = 0; // can be FVF or vs index (marked by D3DFVF_RESERVED0)
DWORD m_currentPixelShader = 0;
D3DDEVTYPE m_deviceType;
HWND m_window;
DWORD m_behaviorFlags;
D3D8Multithread m_multithread;
};
}

View file

@ -0,0 +1,83 @@
#pragma once
// Common methods for device-tied objects.
// - AddRef, Release from IUnknown
// - GetDevice from various classes including IDirect3DResource8
#include "d3d8_include.h"
#include "d3d8_wrapped_object.h"
namespace dxvk {
class D3D8Device;
template <typename D3D9, typename D3D8>
class D3D8DeviceChild : public D3D8WrappedObject<D3D9, D3D8> {
public:
D3D8DeviceChild(D3D8Device* pDevice, Com<D3D9>&& Object)
: D3D8WrappedObject<D3D9, D3D8>(std::move(Object))
, m_parent( pDevice ) { }
ULONG STDMETHODCALLTYPE AddRef() {
uint32_t refCount = this->m_refCount++;
if (unlikely(!refCount)) {
this->AddRefPrivate();
GetDevice()->AddRef();
}
return refCount + 1;
}
ULONG STDMETHODCALLTYPE Release() {
uint32_t oldRefCount, refCount;
do {
oldRefCount = this->m_refCount.load(std::memory_order_acquire);
// clamp value to 0 to prevent underruns
if (unlikely(!oldRefCount))
return 0;
refCount = oldRefCount - 1;
} while (!this->m_refCount.compare_exchange_weak(oldRefCount,
refCount,
std::memory_order_release,
std::memory_order_acquire));
if (unlikely(!refCount)) {
auto* pDevice = GetDevice();
this->ReleasePrivate();
pDevice->Release();
}
return refCount;
}
HRESULT STDMETHODCALLTYPE GetDevice(IDirect3DDevice8** ppDevice) {
InitReturnPtr(ppDevice);
if (ppDevice == nullptr)
return D3DERR_INVALIDCALL;
*ppDevice = ref(GetDevice());
return D3D_OK;
}
IDirect3DDevice8* GetDevice() {
return reinterpret_cast<IDirect3DDevice8*>(m_parent);
}
D3D8Device* GetParent() {
return m_parent;
}
protected:
D3D8Device* m_parent;
};
}

220
src/d3d8/d3d8_format.h Normal file
View file

@ -0,0 +1,220 @@
#pragma once
#include "d3d8_include.h"
namespace dxvk {
constexpr bool isDXT(D3DFORMAT fmt) {
return fmt == D3DFMT_DXT1
|| fmt == D3DFMT_DXT2
|| fmt == D3DFMT_DXT3
|| fmt == D3DFMT_DXT4
|| fmt == D3DFMT_DXT5;
}
constexpr bool isDXT(d3d9::D3DFORMAT fmt) {
return isDXT(D3DFORMAT(fmt));
}
constexpr bool isUnsupportedSurfaceFormat(D3DFORMAT fmt) {
// mirror what dxvk doesn't support in terms of d3d9 surface formats
return fmt == D3DFMT_R8G8B8
|| fmt == D3DFMT_R3G3B2
|| fmt == D3DFMT_A8R3G3B2
|| fmt == D3DFMT_A8P8
|| fmt == D3DFMT_P8;
// not included in the d3d8 spec
//|| fmt == D3DFMT_CXV8U8;
}
constexpr bool isSupportedDepthStencilFormat(D3DFORMAT fmt) {
// native d3d8 doesn't support D3DFMT_D32, D3DFMT_D15S1 or D3DFMT_D24X4S4
return fmt == D3DFMT_D16_LOCKABLE
|| fmt == D3DFMT_D16
//|| fmt == D3DFMT_D32
//|| fmt == D3DFMT_D15S1
//|| fmt == D3DFMT_D24X4S4
|| fmt == D3DFMT_D24S8
|| fmt == D3DFMT_D24X8;
}
constexpr bool isDepthStencilFormat(D3DFORMAT fmt) {
return fmt == D3DFMT_D16_LOCKABLE
|| fmt == D3DFMT_D16
|| fmt == D3DFMT_D32
|| fmt == D3DFMT_D15S1
|| fmt == D3DFMT_D24X4S4
|| fmt == D3DFMT_D24S8
|| fmt == D3DFMT_D24X8;
}
// Get bytes per pixel (or 4x4 block for DXT)
constexpr UINT getFormatStride(D3DFORMAT fmt) {
switch (fmt) {
default:
case D3DFMT_UNKNOWN:
return 0;
case D3DFMT_R3G3B2:
case D3DFMT_A8:
case D3DFMT_P8:
case D3DFMT_L8:
case D3DFMT_A4L4:
return 1;
case D3DFMT_R5G6B5:
case D3DFMT_X1R5G5B5:
case D3DFMT_A1R5G5B5:
case D3DFMT_A4R4G4B4:
case D3DFMT_A8R3G3B2:
case D3DFMT_X4R4G4B4:
case D3DFMT_A8P8:
case D3DFMT_A8L8:
case D3DFMT_V8U8:
case D3DFMT_L6V5U5:
case D3DFMT_D16_LOCKABLE:
case D3DFMT_D15S1:
case D3DFMT_D16:
case D3DFMT_UYVY:
case D3DFMT_YUY2:
return 2;
case D3DFMT_R8G8B8:
return 3;
case D3DFMT_A8R8G8B8:
case D3DFMT_X8R8G8B8:
case D3DFMT_A2B10G10R10:
//case D3DFMT_A8B8G8R8:
//case D3DFMT_X8B8G8R8:
case D3DFMT_G16R16:
case D3DFMT_X8L8V8U8:
case D3DFMT_Q8W8V8U8:
case D3DFMT_V16U16:
case D3DFMT_W11V11U10:
case D3DFMT_A2W10V10U10:
case D3DFMT_D32:
case D3DFMT_D24S8:
case D3DFMT_D24X8:
case D3DFMT_D24X4S4:
return 4;
case D3DFMT_DXT1:
return 8;
case D3DFMT_DXT2:
case D3DFMT_DXT3:
case D3DFMT_DXT4:
case D3DFMT_DXT5:
return 16;
}
}
constexpr uint32_t GetVertexCount8(D3DPRIMITIVETYPE type, UINT count) {
switch (type) {
default:
case D3DPT_TRIANGLELIST: return count * 3;
case D3DPT_POINTLIST: return count;
case D3DPT_LINELIST: return count * 2;
case D3DPT_LINESTRIP: return count + 1;
case D3DPT_TRIANGLESTRIP: return count + 2;
case D3DPT_TRIANGLEFAN: return count + 2;
}
}
// Essentially the same logic as D3D9VertexDecl::SetFVF
constexpr UINT GetFVFStride(DWORD FVF) {
uint32_t texCount = 0;
uint32_t betas = 0;
uint8_t betaIdx = 0xFF;
UINT size = 0;
switch (FVF & D3DFVF_POSITION_MASK) {
case D3DFVF_XYZ:
case D3DFVF_XYZB1:
case D3DFVF_XYZB2:
case D3DFVF_XYZB3:
case D3DFVF_XYZB4:
case D3DFVF_XYZB5:
size += sizeof(float) * 3;
if ((FVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZ)
break;
betas = (((FVF & D3DFVF_XYZB5) - D3DFVF_XYZB1) >> 1) + 1;
if (FVF & D3DFVF_LASTBETA_D3DCOLOR)
betaIdx = sizeof(D3DCOLOR);
else if (FVF & D3DFVF_LASTBETA_UBYTE4)
betaIdx = sizeof(BYTE) * 4;
else if ((FVF & D3DFVF_XYZB5) == D3DFVF_XYZB5)
betaIdx = sizeof(float);
if (betaIdx != 0xFF)
betas--;
if (betas > 0) {
if (betas <= 4)
size += sizeof(float) * betas;
}
if (betaIdx != 0xFF) {
size += betaIdx;
}
break;
case D3DFVF_XYZW:
case D3DFVF_XYZRHW:
size += sizeof(float) * 4;
break;
default:
break;
}
if (FVF & D3DFVF_NORMAL) {
size += sizeof(float) * 3;
}
if (FVF & D3DFVF_PSIZE) {
size += sizeof(float);
}
if (FVF & D3DFVF_DIFFUSE) {
size += sizeof(D3DCOLOR);
}
if (FVF & D3DFVF_SPECULAR) {
size += sizeof(D3DCOLOR);
}
texCount = (FVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
texCount = std::min(texCount, 8u);
for (uint32_t i = 0; i < texCount; i++) {
switch ((FVF >> (16 + i * 2)) & 0x3) {
case D3DFVF_TEXTUREFORMAT1:
size += sizeof(float);
break;
case D3DFVF_TEXTUREFORMAT2:
size += sizeof(float) * 2;
break;
case D3DFVF_TEXTUREFORMAT3:
size += sizeof(float) * 3;
break;
case D3DFVF_TEXTUREFORMAT4:
size += sizeof(float) * 4;
break;
default:
break;
}
}
return size;
}
constexpr UINT getSurfaceSize(D3DFORMAT Format, UINT Width, UINT Height) {
if (isDXT(Format)) {
Width = ((Width + 3) >> 2);
Height = ((Height + 3) >> 2);
}
return Width * Height * getFormatStride(Format);
}
}

206
src/d3d8/d3d8_include.h Normal file
View file

@ -0,0 +1,206 @@
#pragma once
#ifndef _MSC_VER
#ifdef _WIN32_WINNT
#undef _WIN32_WINNT
#endif
#define _WIN32_WINNT 0x0A00
#endif
#include <stdint.h>
#include <d3d8.h>
// Declare __uuidof for D3D8 interfaces
#ifdef __CRT_UUID_DECL
__CRT_UUID_DECL(IDirect3D8, 0x1DD9E8DA,0x1C77,0x4D40,0xB0,0xCF,0x98,0xFE,0xFD,0xFF,0x95,0x12);
__CRT_UUID_DECL(IDirect3DDevice8, 0x7385E5DF,0x8FE8,0x41D5,0x86,0xB6,0xD7,0xB4,0x85,0x47,0xB6,0xCF);
__CRT_UUID_DECL(IDirect3DResource8, 0x1B36BB7B,0x09B7,0x410A,0xB4,0x45,0x7D,0x14,0x30,0xD7,0xB3,0x3F);
__CRT_UUID_DECL(IDirect3DVertexBuffer8, 0x8AEEEAC7,0x05F9,0x44D4,0xB5,0x91,0x00,0x0B,0x0D,0xF1,0xCB,0x95);
__CRT_UUID_DECL(IDirect3DVolume8, 0xBD7349F5,0x14F1,0x42E4,0x9C,0x79,0x97,0x23,0x80,0xDB,0x40,0xC0);
__CRT_UUID_DECL(IDirect3DSwapChain8, 0x928C088B,0x76B9,0x4C6B,0xA5,0x36,0xA5,0x90,0x85,0x38,0x76,0xCD);
__CRT_UUID_DECL(IDirect3DSurface8, 0xB96EEBCA,0xB326,0x4EA5,0x88,0x2F,0x2F,0xF5,0xBA,0xE0,0x21,0xDD);
__CRT_UUID_DECL(IDirect3DIndexBuffer8, 0x0E689C9A,0x053D,0x44A0,0x9D,0x92,0xDB,0x0E,0x3D,0x75,0x0F,0x86);
__CRT_UUID_DECL(IDirect3DBaseTexture8, 0xB4211CFA,0x51B9,0x4A9F,0xAB,0x78,0xDB,0x99,0xB2,0xBB,0x67,0x8E);
__CRT_UUID_DECL(IDirect3DTexture8, 0xE4CDD575,0x2866,0x4F01,0xB1,0x2E,0x7E,0xEC,0xE1,0xEC,0x93,0x58);
__CRT_UUID_DECL(IDirect3DCubeTexture8, 0x3EE5B968,0x2ACA,0x4C34,0x8B,0xB5,0x7E,0x0C,0x3D,0x19,0xB7,0x50);
__CRT_UUID_DECL(IDirect3DVolumeTexture8, 0x4B8AAAFA,0x140F,0x42BA,0x91,0x31,0x59,0x7E,0xAF,0xAA,0x2E,0xAD);
#elif defined(_MSC_VER)
interface DECLSPEC_UUID("1DD9E8DA-1C77-4D40-B0CF-98FEFDFF9512") IDirect3D8;
interface DECLSPEC_UUID("7385E5DF-8FE8-41D5-86B6-D7B48547B6CF") IDirect3DDevice8;
interface DECLSPEC_UUID("1B36BB7B-09B7-410A-B445-7D1430D7B33F") IDirect3DResource8;
interface DECLSPEC_UUID("8AEEEAC7-05F9-44D4-B591-000B0DF1CB95") IDirect3DVertexBuffer8;
interface DECLSPEC_UUID("BD7349F5-14F1-42E4-9C79-972380DB40C0") IDirect3DVolume8;
interface DECLSPEC_UUID("928C088B-76B9-4C6B-A536-A590853876CD") IDirect3DSwapChain8;
interface DECLSPEC_UUID("B96EEBCA-B326-4EA5-882F-2FF5BAE021DD") IDirect3DSurface8;
interface DECLSPEC_UUID("0E689C9A-053D-44A0-9D92-DB0E3D750F86") IDirect3DIndexBuffer8;
interface DECLSPEC_UUID("B4211CFA-51B9-4A9F-AB78-DB99B2BB678E") IDirect3DBaseTexture8;
interface DECLSPEC_UUID("E4CDD575-2866-4F01-B12E-7EECE1EC9358") IDirect3DTexture8;
interface DECLSPEC_UUID("3EE5B968-2ACA-4C34-8BB5-7E0C3D19B750") IDirect3DCubeTexture8;
interface DECLSPEC_UUID("4B8AAAFA-140F-42BA-9131-597EAFAA2EAD") IDirect3DVolumeTexture8;
#endif
// Undefine D3D8 macros
#undef DIRECT3D_VERSION
#undef D3D_SDK_VERSION
#undef D3DCS_ALL // parentheses added in D3D9
#undef D3DFVF_POSITION_MASK // changed from 0x00E to 0x400E in D3D9
#undef D3DFVF_RESERVED2 // reduced from 4 to 2 in DX9
#undef D3DSP_REGNUM_MASK // changed from 0x00000FFF to 0x000007FF in D3D9
#if defined(__MINGW32__) || defined(__GNUC__)
// Avoid redundant definitions (add D3D*_DEFINED macros here)
#define D3DRECT_DEFINED
#define D3DMATRIX_DEFINED
// Temporarily override __CRT_UUID_DECL to allow usage in d3d9 namespace
#pragma push_macro("__CRT_UUID_DECL")
#ifdef __CRT_UUID_DECL
#undef __CRT_UUID_DECL
#endif
#ifdef __MINGW32__
#define __CRT_UUID_DECL(type,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \
} \
extern "C++" template<> struct __mingw_uuidof_s<d3d9::type> { static constexpr IID __uuid_inst = {l,w1,w2, {b1,b2,b3,b4,b5,b6,b7,b8}}; }; \
extern "C++" template<> constexpr const GUID &__mingw_uuidof<d3d9::type>() { return __mingw_uuidof_s<d3d9::type>::__uuid_inst; } \
extern "C++" template<> constexpr const GUID &__mingw_uuidof<d3d9::type*>() { return __mingw_uuidof_s<d3d9::type>::__uuid_inst; } \
namespace d3d9 {
#elif defined(__GNUC__)
#define __CRT_UUID_DECL(type, a, b, c, d, e, f, g, h, i, j, k) \
} \
extern "C++" { template <> constexpr GUID __uuidof_helper<d3d9::type>() { return GUID{a,b,c,{d,e,f,g,h,i,j,k}}; } } \
extern "C++" { template <> constexpr GUID __uuidof_helper<d3d9::type*>() { return __uuidof_helper<d3d9::type>(); } } \
extern "C++" { template <> constexpr GUID __uuidof_helper<const d3d9::type*>() { return __uuidof_helper<d3d9::type>(); } } \
extern "C++" { template <> constexpr GUID __uuidof_helper<d3d9::type&>() { return __uuidof_helper<d3d9::type>(); } } \
extern "C++" { template <> constexpr GUID __uuidof_helper<const d3d9::type&>() { return __uuidof_helper<d3d9::type>(); } } \
namespace d3d9 {
#endif
#endif // defined(__MINGW32__) || defined(__GNUC__)
/**
* \brief Direct3D 9
*
* All D3D9 interfaces are included within
* a namespace, so as not to collide with
* D3D8 interfaces.
*/
namespace d3d9 {
#include <d3d9.h>
}
// Indicates d3d9:: namespace is in-use.
#define DXVK_D3D9_NAMESPACE
#if defined(__MINGW32__) || defined(__GNUC__)
#pragma pop_macro("__CRT_UUID_DECL")
#endif
//for some reason we need to specify __declspec(dllexport) for MinGW
#if defined(__WINE__) || !defined(_WIN32)
#define DLLEXPORT __attribute__((visibility("default")))
#else
#define DLLEXPORT
#endif
#include "../util/com/com_guid.h"
#include "../util/com/com_object.h"
#include "../util/com/com_pointer.h"
#include "../util/log/log.h"
#include "../util/log/log_debug.h"
#include "../util/sync/sync_recursive.h"
#include "../util/util_error.h"
#include "../util/util_likely.h"
#include "../util/util_string.h"
// 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
// From d3dtypes.h
#ifndef D3DDEVINFOID_TEXTUREMANAGER
#define D3DDEVINFOID_TEXTUREMANAGER 1
#endif
#ifndef D3DDEVINFOID_D3DTEXTUREMANAGER
#define D3DDEVINFOID_D3DTEXTUREMANAGER 2
#endif
#ifndef D3DDEVINFOID_TEXTURING
#define D3DDEVINFOID_TEXTURING 3
#endif
// From d3dhal.h
#ifndef D3DDEVINFOID_VCACHE
#define D3DDEVINFOID_VCACHE 4
#endif
// MinGW headers are broken. Who'dve guessed?
#ifndef _MSC_VER
// Missing from d3d8types.h
#ifndef D3DDEVINFOID_RESOURCEMANAGER
#define D3DDEVINFOID_RESOURCEMANAGER 5
#endif
#ifndef D3DDEVINFOID_VERTEXSTATS
#define D3DDEVINFOID_VERTEXSTATS 6 // Aka D3DDEVINFOID_D3DVERTEXSTATS
#endif
#ifndef D3DPRESENT_RATE_UNLIMITED
#define D3DPRESENT_RATE_UNLIMITED 0x7FFFFFFF
#endif
#else // _MSC_VER
// These are enum typedefs in the MinGW headers, but not defined by Microsoft
#define D3DVSDT_TYPE DWORD
#define D3DVSDE_REGISTER DWORD
#endif

159
src/d3d8/d3d8_interface.cpp Normal file
View file

@ -0,0 +1,159 @@
#include "d3d8_interface.h"
#include "d3d8_device.h"
#include "d3d8_texture.h"
#include <cstring>
namespace dxvk {
D3D8Interface::D3D8Interface() {
m_d3d9 = d3d9::Direct3DCreate9(D3D_SDK_VERSION);
// Get the bridge interface to D3D9.
if (FAILED(m_d3d9->QueryInterface(__uuidof(IDxvkD3D8InterfaceBridge), (void**)&m_bridge))) {
throw DxvkError("D3D8Interface: ERROR! Failed to get D3D9 Bridge. d3d9.dll might not be DXVK!");
}
m_bridge->SetD3D8CompatibilityMode(true);
m_d3d8Options = D3D8Options(*m_bridge->GetConfig());
m_adapterCount = m_d3d9->GetAdapterCount();
m_adapterModeCounts.resize(m_adapterCount);
m_adapterModes.reserve(m_adapterCount);
for (UINT adapter = 0; adapter < m_adapterCount; adapter++) {
m_adapterModes.emplace_back();
// cache adapter modes and mode counts for each d3d9 format
for (d3d9::D3DFORMAT fmt : ADAPTER_FORMATS) {
const UINT modeCount = m_d3d9->GetAdapterModeCount(adapter, fmt);
for (UINT mode = 0; mode < modeCount; mode++) {
m_adapterModes[adapter].emplace_back();
m_d3d9->EnumAdapterModes(adapter, fmt, mode, &(m_adapterModes[adapter].back()));
// can't use modeCount as it's only for one fmt
m_adapterModeCounts[adapter]++;
}
}
}
}
HRESULT STDMETHODCALLTYPE D3D8Interface::QueryInterface(REFIID riid, void** ppvObject) {
if (ppvObject == nullptr)
return E_POINTER;
*ppvObject = nullptr;
if (riid == __uuidof(IUnknown)
|| riid == __uuidof(IDirect3D8)) {
*ppvObject = ref(this);
return S_OK;
}
Logger::warn("D3D8Interface::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
return E_NOINTERFACE;
}
HRESULT STDMETHODCALLTYPE D3D8Interface::GetAdapterIdentifier(
UINT Adapter,
DWORD Flags,
D3DADAPTER_IDENTIFIER8* pIdentifier) {
if (unlikely(pIdentifier == nullptr))
return D3DERR_INVALIDCALL;
// This flag now has the opposite effect.
// Either way, WHQLevel will be 1 with Direct3D9Ex
if (Flags & D3DENUM_NO_WHQL_LEVEL)
Flags &= ~D3DENUM_WHQL_LEVEL;
else
Flags |= D3DENUM_WHQL_LEVEL;
d3d9::D3DADAPTER_IDENTIFIER9 identifier9;
HRESULT res = m_d3d9->GetAdapterIdentifier(Adapter, Flags, &identifier9);
if (likely(SUCCEEDED(res))) {
strncpy(pIdentifier->Driver, identifier9.Driver, MAX_DEVICE_IDENTIFIER_STRING);
strncpy(pIdentifier->Description, identifier9.Description, MAX_DEVICE_IDENTIFIER_STRING);
pIdentifier->DriverVersion = identifier9.DriverVersion;
pIdentifier->VendorId = identifier9.VendorId;
pIdentifier->DeviceId = identifier9.DeviceId;
pIdentifier->SubSysId = identifier9.SubSysId;
pIdentifier->Revision = identifier9.Revision;
pIdentifier->DeviceIdentifier = identifier9.DeviceIdentifier;
pIdentifier->WHQLLevel = identifier9.WHQLLevel;
}
return res;
}
HRESULT __stdcall D3D8Interface::EnumAdapterModes(
UINT Adapter,
UINT Mode,
D3DDISPLAYMODE* pMode) {
if (Adapter >= m_adapterCount || Mode >= m_adapterModeCounts[Adapter] || pMode == nullptr) {
return D3DERR_INVALIDCALL;
}
pMode->Width = m_adapterModes[Adapter][Mode].Width;
pMode->Height = m_adapterModes[Adapter][Mode].Height;
pMode->RefreshRate = m_adapterModes[Adapter][Mode].RefreshRate;
pMode->Format = D3DFORMAT(m_adapterModes[Adapter][Mode].Format);
return D3D_OK;
}
HRESULT __stdcall D3D8Interface::CreateDevice(
UINT Adapter,
D3DDEVTYPE DeviceType,
HWND hFocusWindow,
DWORD BehaviorFlags,
D3DPRESENT_PARAMETERS* pPresentationParameters,
IDirect3DDevice8** ppReturnedDeviceInterface) {
InitReturnPtr(ppReturnedDeviceInterface);
if (unlikely(pPresentationParameters == nullptr ||
ppReturnedDeviceInterface == nullptr))
return D3DERR_INVALIDCALL;
// D3DSWAPEFFECT_COPY can not be used with more than one back buffer.
// This is also technically true for D3DSWAPEFFECT_COPY_VSYNC, however
// RC Cars depends on it not being rejected.
if (unlikely(pPresentationParameters->SwapEffect == D3DSWAPEFFECT_COPY
&& pPresentationParameters->BackBufferCount > 1))
return D3DERR_INVALIDCALL;
// In D3D8 nothing except D3DPRESENT_INTERVAL_DEFAULT can be used
// as a flag for windowed presentation.
if (unlikely(pPresentationParameters->Windowed
&& pPresentationParameters->FullScreen_PresentationInterval != D3DPRESENT_INTERVAL_DEFAULT))
return D3DERR_INVALIDCALL;
Com<d3d9::IDirect3DDevice9> pDevice9 = nullptr;
d3d9::D3DPRESENT_PARAMETERS params = ConvertPresentParameters9(pPresentationParameters);
HRESULT res = m_d3d9->CreateDevice(
Adapter,
(d3d9::D3DDEVTYPE)DeviceType,
hFocusWindow,
BehaviorFlags,
&params,
&pDevice9
);
if (likely(SUCCEEDED(res)))
*ppReturnedDeviceInterface = ref(new D3D8Device(
this, std::move(pDevice9),
DeviceType, hFocusWindow, BehaviorFlags,
pPresentationParameters
));
return res;
}
}

172
src/d3d8/d3d8_interface.h Normal file
View file

@ -0,0 +1,172 @@
#pragma once
#include "d3d8_include.h"
#include "d3d8_d3d9_util.h"
#include "d3d8_options.h"
#include "d3d8_format.h"
#include "../d3d9/d3d9_bridge.h"
namespace dxvk {
/**
* \brief D3D8 interface implementation
*
* Implements the IDirect3DDevice8 interfaces
* which provides the way to get adapters and create other objects such as \ref IDirect3DDevice8.
* similar to \ref DxgiFactory but for D3D8.
*/
class D3D8Interface final : public ComObjectClamp<IDirect3D8> {
static constexpr d3d9::D3DFORMAT ADAPTER_FORMATS[] = {
d3d9::D3DFMT_A1R5G5B5,
//d3d9::D3DFMT_A2R10G10B10, (not in D3D8)
d3d9::D3DFMT_A8R8G8B8,
d3d9::D3DFMT_R5G6B5,
d3d9::D3DFMT_X1R5G5B5,
d3d9::D3DFMT_X8R8G8B8
};
public:
D3D8Interface();
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject);
HRESULT STDMETHODCALLTYPE RegisterSoftwareDevice(void* pInitializeFunction) {
return m_d3d9->RegisterSoftwareDevice(pInitializeFunction);
}
UINT STDMETHODCALLTYPE GetAdapterCount() {
return m_d3d9->GetAdapterCount();
}
HRESULT STDMETHODCALLTYPE GetAdapterIdentifier(
UINT Adapter,
DWORD Flags,
D3DADAPTER_IDENTIFIER8* pIdentifier);
UINT STDMETHODCALLTYPE GetAdapterModeCount(UINT Adapter) {
return m_adapterModeCounts[Adapter];
}
HRESULT STDMETHODCALLTYPE EnumAdapterModes(
UINT Adapter,
UINT Mode,
D3DDISPLAYMODE* pMode);
HRESULT STDMETHODCALLTYPE GetAdapterDisplayMode(UINT Adapter, D3DDISPLAYMODE* pMode) {
return m_d3d9->GetAdapterDisplayMode(Adapter, (d3d9::D3DDISPLAYMODE*)pMode);
}
HRESULT STDMETHODCALLTYPE CheckDeviceType(
UINT Adapter,
D3DDEVTYPE DevType,
D3DFORMAT AdapterFormat,
D3DFORMAT BackBufferFormat,
BOOL bWindowed) {
// Ignore the bWindowed parameter when querying D3D9. D3D8 does
// identical validations between windowed and fullscreen modes, adhering
// to the stricter fullscreen adapter and back buffer format validations.
return m_d3d9->CheckDeviceType(
Adapter,
(d3d9::D3DDEVTYPE)DevType,
(d3d9::D3DFORMAT)AdapterFormat,
(d3d9::D3DFORMAT)BackBufferFormat,
FALSE
);
}
HRESULT STDMETHODCALLTYPE CheckDeviceFormat(
UINT Adapter,
D3DDEVTYPE DeviceType,
D3DFORMAT AdapterFormat,
DWORD Usage,
D3DRESOURCETYPE RType,
D3DFORMAT CheckFormat) {
return m_d3d9->CheckDeviceFormat(
Adapter,
(d3d9::D3DDEVTYPE)DeviceType,
(d3d9::D3DFORMAT)AdapterFormat,
Usage,
(d3d9::D3DRESOURCETYPE)RType,
(d3d9::D3DFORMAT)CheckFormat
);
}
HRESULT STDMETHODCALLTYPE CheckDeviceMultiSampleType(
UINT Adapter,
D3DDEVTYPE DeviceType,
D3DFORMAT SurfaceFormat,
BOOL Windowed,
D3DMULTISAMPLE_TYPE MultiSampleType) {
DWORD* pQualityLevels = nullptr;
return m_d3d9->CheckDeviceMultiSampleType(
Adapter,
(d3d9::D3DDEVTYPE)DeviceType,
(d3d9::D3DFORMAT)SurfaceFormat,
Windowed,
(d3d9::D3DMULTISAMPLE_TYPE)MultiSampleType,
pQualityLevels
);
}
HRESULT STDMETHODCALLTYPE CheckDepthStencilMatch(
UINT Adapter,
D3DDEVTYPE DeviceType,
D3DFORMAT AdapterFormat,
D3DFORMAT RenderTargetFormat,
D3DFORMAT DepthStencilFormat) {
if (isSupportedDepthStencilFormat(DepthStencilFormat))
return m_d3d9->CheckDepthStencilMatch(
Adapter,
(d3d9::D3DDEVTYPE)DeviceType,
(d3d9::D3DFORMAT)AdapterFormat,
(d3d9::D3DFORMAT)RenderTargetFormat,
(d3d9::D3DFORMAT)DepthStencilFormat
);
return D3DERR_NOTAVAILABLE;
}
HRESULT STDMETHODCALLTYPE GetDeviceCaps(
UINT Adapter,
D3DDEVTYPE DeviceType,
D3DCAPS8* pCaps) {
if (unlikely(pCaps == nullptr))
return D3DERR_INVALIDCALL;
d3d9::D3DCAPS9 caps9;
HRESULT res = m_d3d9->GetDeviceCaps(Adapter, (d3d9::D3DDEVTYPE)DeviceType, &caps9);
if (likely(SUCCEEDED(res)))
ConvertCaps8(caps9, pCaps);
return res;
}
HMONITOR STDMETHODCALLTYPE GetAdapterMonitor(UINT Adapter) {
return m_d3d9->GetAdapterMonitor(Adapter);
}
HRESULT STDMETHODCALLTYPE CreateDevice(
UINT Adapter,
D3DDEVTYPE DeviceType,
HWND hFocusWindow,
DWORD BehaviorFlags,
D3DPRESENT_PARAMETERS* pPresentationParameters,
IDirect3DDevice8** ppReturnedDeviceInterface);
const D3D8Options& GetOptions() { return m_d3d8Options; }
private:
UINT m_adapterCount;
std::vector<UINT> m_adapterModeCounts;
std::vector<std::vector<d3d9::D3DDISPLAYMODE>> m_adapterModes;
Com<d3d9::IDirect3D9> m_d3d9;
Com<IDxvkD3D8InterfaceBridge> m_bridge;
D3D8Options m_d3d8Options;
};
}

124
src/d3d8/d3d8_main.cpp Normal file
View file

@ -0,0 +1,124 @@
#include "d3d8_interface.h"
namespace dxvk {
Logger Logger::s_instance("d3d8.log");
HRESULT CreateD3D8(IDirect3D8** ppDirect3D8) {
if (!ppDirect3D8)
return D3DERR_INVALIDCALL;
*ppDirect3D8 = ref(new D3D8Interface());
return D3D_OK;
}
}
extern "C" {
DLLEXPORT HRESULT __stdcall ValidatePixelShader(
const DWORD* pPixelShader,
const D3DCAPS8* pCaps,
BOOL ErrorReturn,
char** pErrorString) {
HRESULT res = S_OK;
std::string errorMessage = "";
// ValidatePixelShader returns immediately in case of a NULL pPixelShader
if (unlikely(pPixelShader == nullptr)) {
dxvk::Logger::warn("D3D8: ValidatePixelShader: Null pPixelShader");
return E_FAIL;
} else {
const uint32_t majorVersion = D3DSHADER_VERSION_MAJOR(pPixelShader[0]);
const uint32_t minorVersion = D3DSHADER_VERSION_MINOR(pPixelShader[0]);
if (unlikely(majorVersion != 1 || minorVersion > 4)) {
errorMessage = dxvk::str::format("D3D8: ValidatePixelShader: Unsupported PS version ",
majorVersion, ".", minorVersion);
res = E_FAIL;
} else if (unlikely(pCaps && pPixelShader[0] > pCaps->PixelShaderVersion)) {
errorMessage = dxvk::str::format("D3D8: ValidatePixelShader: Caps: Unsupported PS version ",
majorVersion, ".", minorVersion);
res = E_FAIL;
}
}
if (unlikely(res != S_OK)) {
dxvk::Logger::warn(errorMessage);
if (!ErrorReturn)
errorMessage = "";
}
#ifdef _WIN32
if (pErrorString != nullptr) {
const size_t errorMessageSize = errorMessage.size() + 1;
// Wine tests call HeapFree() on the returned error string,
// so the expectation is for it to be allocated on the heap.
*pErrorString = (char*) HeapAlloc(GetProcessHeap(), 0, errorMessageSize);
if (*pErrorString)
memcpy(*pErrorString, errorMessage.c_str(), errorMessageSize);
}
#endif
return res;
}
DLLEXPORT HRESULT __stdcall ValidateVertexShader(
const DWORD* pVertexShader,
const DWORD* pVertexDecl,
const D3DCAPS8* pCaps,
BOOL ErrorReturn,
char** pErrorString) {
HRESULT res = S_OK;
std::string errorMessage = "";
if (unlikely(pVertexShader == nullptr)) {
errorMessage = "D3D8: ValidateVertexShader: Null pVertexShader";
res = E_FAIL;
} else {
const uint32_t majorVersion = D3DSHADER_VERSION_MAJOR(pVertexShader[0]);
const uint32_t minorVersion = D3DSHADER_VERSION_MINOR(pVertexShader[0]);
if (unlikely(majorVersion != 1 || minorVersion > 1)) {
errorMessage = dxvk::str::format("D3D8: ValidateVertexShader: Unsupported VS version ",
majorVersion, ".", minorVersion);
res = E_FAIL;
} else if (unlikely(pCaps && pVertexShader[0] > pCaps->VertexShaderVersion)) {
errorMessage = dxvk::str::format("D3D8: ValidateVertexShader: Caps: Unsupported VS version ",
majorVersion, ".", minorVersion);
res = E_FAIL;
}
}
if (unlikely(res != S_OK)) {
dxvk::Logger::warn(errorMessage);
if (!ErrorReturn)
errorMessage = "";
}
#ifdef _WIN32
if (pErrorString != nullptr) {
const size_t errorMessageSize = errorMessage.size() + 1;
// Wine tests call HeapFree() on the returned error string,
// so the expectation is for it to be allocated on the heap.
*pErrorString = (char*) HeapAlloc(GetProcessHeap(), 0, errorMessageSize);
if (*pErrorString)
memcpy(*pErrorString, errorMessage.c_str(), errorMessageSize);
}
#endif
return res;
}
DLLEXPORT void __stdcall DebugSetMute() {}
DLLEXPORT IDirect3D8* __stdcall Direct3DCreate8(UINT nSDKVersion) {
IDirect3D8* pDirect3D = nullptr;
dxvk::CreateD3D8(&pDirect3D);
return pDirect3D;
}
}

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